📄 node.java
字号:
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Rhino code, released * May 6, 1999. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1997-1999 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Norris Boyd * Roshan James * Roger Lawrence * Mike McCabe * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */package org.mozilla.javascript;import java.util.Map;import java.util.LinkedHashMap;import java.util.Iterator;import java.util.Collections;/** * This class implements the root of the intermediate representation. * * @author Norris Boyd * @author Mike McCabe */public class Node{ public static final int FUNCTION_PROP = 1, LOCAL_PROP = 2, LOCAL_BLOCK_PROP = 3, REGEXP_PROP = 4, CASEARRAY_PROP = 5, /* the following properties are defined and manipulated by the optimizer - TARGETBLOCK_PROP - the block referenced by a branch node VARIABLE_PROP - the variable referenced by a BIND or NAME node ISNUMBER_PROP - this node generates code on Number children and delivers a Number result (as opposed to Objects) DIRECTCALL_PROP - this call node should emit code to test the function object against the known class and call diret if it matches. */ TARGETBLOCK_PROP = 6, VARIABLE_PROP = 7, ISNUMBER_PROP = 8, DIRECTCALL_PROP = 9, SPECIALCALL_PROP = 10, SKIP_INDEXES_PROP = 11, // array of skipped indexes of array literal OBJECT_IDS_PROP = 12, // array of properties for object literal INCRDECR_PROP = 13, // pre or post type of increment/decerement CATCH_SCOPE_PROP = 14, // index of catch scope block in catch LABEL_ID_PROP = 15, // label id: code generation uses it MEMBER_TYPE_PROP = 16, // type of element access operation NAME_PROP = 17, // property name CONTROL_BLOCK_PROP = 18, // flags a control block that can drop off PARENTHESIZED_PROP = 19, // expression is parenthesized GENERATOR_END_PROP = 20, DESTRUCTURING_ARRAY_LENGTH = 21, DESTRUCTURING_NAMES= 22, LAST_PROP = 22; // values of ISNUMBER_PROP to specify // which of the children are Number types public static final int BOTH = 0, LEFT = 1, RIGHT = 2; public static final int // values for SPECIALCALL_PROP NON_SPECIALCALL = 0, SPECIALCALL_EVAL = 1, SPECIALCALL_WITH = 2; public static final int // flags for INCRDECR_PROP DECR_FLAG = 0x1, POST_FLAG = 0x2; public static final int // flags for MEMBER_TYPE_PROP PROPERTY_FLAG = 0x1, // property access: element is valid name ATTRIBUTE_FLAG = 0x2, // x.@y or x..@y DESCENDANTS_FLAG = 0x4; // x..y or x..@i private static class NumberNode extends Node { NumberNode(double number) { super(Token.NUMBER); this.number = number; } double number; } private static class StringNode extends Node { StringNode(int type, String str) { super(type); this.str = str; } String str; Node.Scope scope; } public static class Jump extends Node { public Jump(int type) { super(type); } Jump(int type, int lineno) { super(type, lineno); } Jump(int type, Node child) { super(type, child); } Jump(int type, Node child, int lineno) { super(type, child, lineno); } public final Jump getJumpStatement() { if (!(type == Token.BREAK || type == Token.CONTINUE)) Kit.codeBug(); return jumpNode; } public final void setJumpStatement(Jump jumpStatement) { if (!(type == Token.BREAK || type == Token.CONTINUE)) Kit.codeBug(); if (jumpStatement == null) Kit.codeBug(); if (this.jumpNode != null) Kit.codeBug(); //only once this.jumpNode = jumpStatement; } public final Node getDefault() { if (!(type == Token.SWITCH)) Kit.codeBug(); return target2; } public final void setDefault(Node defaultTarget) { if (!(type == Token.SWITCH)) Kit.codeBug(); if (defaultTarget.type != Token.TARGET) Kit.codeBug(); if (target2 != null) Kit.codeBug(); //only once target2 = defaultTarget; } public final Node getFinally() { if (!(type == Token.TRY)) Kit.codeBug(); return target2; } public final void setFinally(Node finallyTarget) { if (!(type == Token.TRY)) Kit.codeBug(); if (finallyTarget.type != Token.TARGET) Kit.codeBug(); if (target2 != null) Kit.codeBug(); //only once target2 = finallyTarget; } public final Jump getLoop() { if (!(type == Token.LABEL)) Kit.codeBug(); return jumpNode; } public final void setLoop(Jump loop) { if (!(type == Token.LABEL)) Kit.codeBug(); if (loop == null) Kit.codeBug(); if (jumpNode != null) Kit.codeBug(); //only once jumpNode = loop; } public final Node getContinue() { if (type != Token.LOOP) Kit.codeBug(); return target2; } public final void setContinue(Node continueTarget) { if (type != Token.LOOP) Kit.codeBug(); if (continueTarget.type != Token.TARGET) Kit.codeBug(); if (target2 != null) Kit.codeBug(); //only once target2 = continueTarget; } public Node target; private Node target2; private Jump jumpNode; } static class Symbol { Symbol(int declType, String name) { this.declType = declType; this.name = name; this.index = -1; } /** * One of Token.FUNCTION, Token.LP (for parameters), Token.VAR, * Token.LET, or Token.CONST */ int declType; int index; String name; Node.Scope containingTable; } static class Scope extends Jump { public Scope(int nodeType) { super(nodeType); } public Scope(int nodeType, int lineno) { super(nodeType, lineno); } public Scope(int nodeType, Node n, int lineno) { super(nodeType, n, lineno); } /* * Creates a new scope node, moving symbol table information * from "scope" to the new node, and making "scope" a nested * scope contained by the new node. * Useful for injecting a new scope in a scope chain. */ public static Scope splitScope(Scope scope) { Scope result = new Scope(scope.getType()); result.symbolTable = scope.symbolTable; scope.symbolTable = null; result.parent = scope.parent; scope.parent = result; result.top = scope.top; return result; } public static void joinScopes(Scope source, Scope dest) { source.ensureSymbolTable(); dest.ensureSymbolTable(); if (!Collections.disjoint(source.symbolTable.keySet(), dest.symbolTable.keySet())) { throw Kit.codeBug(); } dest.symbolTable.putAll(source.symbolTable); } public void setParent(Scope parent) { this.parent = parent; this.top = parent == null ? (ScriptOrFnNode)this : parent.top; } public Scope getParentScope() { return parent; } public Scope getDefiningScope(String name) { for (Scope sn=this; sn != null; sn = sn.parent) { if (sn.symbolTable == null) continue; if (sn.symbolTable.containsKey(name)) return sn; } return null; } public Symbol getSymbol(String name) { return symbolTable == null ? null : symbolTable.get(name); } public void putSymbol(String name, Symbol symbol) { ensureSymbolTable(); symbolTable.put(name, symbol); symbol.containingTable = this; top.addSymbol(symbol); } public Map<String,Symbol> getSymbolTable() { return symbolTable; } private void ensureSymbolTable() { if (symbolTable == null) { symbolTable = new LinkedHashMap<String,Symbol>(5); } } // Use LinkedHashMap so that the iteration order is the insertion order protected LinkedHashMap<String,Symbol> symbolTable; private Scope parent; private ScriptOrFnNode top; } private static class PropListItem { PropListItem next; int type; int intValue; Object objectValue; } public Node(int nodeType) { type = nodeType; } public Node(int nodeType, Node child) { type = nodeType; first = last = child; child.next = null; } public Node(int nodeType, Node left, Node right) { type = nodeType; first = left; last = right; left.next = right; right.next = null; } public Node(int nodeType, Node left, Node mid, Node right) { type = nodeType; first = left; last = right; left.next = mid; mid.next = right; right.next = null; } public Node(int nodeType, int line) { type = nodeType; lineno = line; } public Node(int nodeType, Node child, int line) { this(nodeType, child); lineno = line; } public Node(int nodeType, Node left, Node right, int line) { this(nodeType, left, right); lineno = line; } public Node(int nodeType, Node left, Node mid, Node right, int line) { this(nodeType, left, mid, right); lineno = line; } public static Node newNumber(double number) { return new NumberNode(number); } public static Node newString(String str) { return new StringNode(Token.STRING, str); } public static Node newString(int type, String str) { return new StringNode(type, str); } public int getType() { return type; } public void setType(int type) { this.type = type; } public boolean hasChildren() { return first != null; } public Node getFirstChild() { return first; } public Node getLastChild() { return last; } public Node getNext() { return next; } public Node getChildBefore(Node child) { if (child == first) return null; Node n = first; while (n.next != child) { n = n.next; if (n == null) throw new RuntimeException("node is not a child"); } return n; } public Node getLastSibling() { Node n = this; while (n.next != null) { n = n.next; } return n; } public void addChildToFront(Node child) { child.next = first; first = child; if (last == null) { last = child; } } public void addChildToBack(Node child) { child.next = null; if (last == null) { first = last = child; return; } last.next = child; last = child; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -