author | attila |
Wed, 05 Jun 2013 10:44:32 +0200 | |
changeset 17981 | 9b8e085aa1fe |
parent 17973 | d220c8157f25 |
child 18335 | 1b5fdae617cf |
permissions | -rw-r--r-- |
16147 | 1 |
/* |
16151 | 2 |
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. |
16147 | 3 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 |
* |
|
5 |
* This code is free software; you can redistribute it and/or modify it |
|
6 |
* under the terms of the GNU General Public License version 2 only, as |
|
7 |
* published by the Free Software Foundation. Oracle designates this |
|
8 |
* particular file as subject to the "Classpath" exception as provided |
|
9 |
* by Oracle in the LICENSE file that accompanied this code. |
|
10 |
* |
|
11 |
* This code is distributed in the hope that it will be useful, but WITHOUT |
|
12 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
13 |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
14 |
* version 2 for more details (a copy is included in the LICENSE file that |
|
15 |
* accompanied this code). |
|
16 |
* |
|
17 |
* You should have received a copy of the GNU General Public License version |
|
18 |
* 2 along with this work; if not, write to the Free Software Foundation, |
|
19 |
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
20 |
* |
|
21 |
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
|
22 |
* or visit www.oracle.com if you need additional information or have any |
|
23 |
* questions. |
|
24 |
*/ |
|
25 |
||
26 |
package jdk.nashorn.internal.parser; |
|
27 |
||
28 |
import static jdk.nashorn.internal.codegen.CompilerConstants.ARGUMENTS; |
|
29 |
import static jdk.nashorn.internal.codegen.CompilerConstants.EVAL; |
|
30 |
import static jdk.nashorn.internal.codegen.CompilerConstants.FUNCTION_PREFIX; |
|
31 |
import static jdk.nashorn.internal.codegen.CompilerConstants.RUN_SCRIPT; |
|
32 |
import static jdk.nashorn.internal.parser.TokenType.ASSIGN; |
|
33 |
import static jdk.nashorn.internal.parser.TokenType.CASE; |
|
34 |
import static jdk.nashorn.internal.parser.TokenType.CATCH; |
|
35 |
import static jdk.nashorn.internal.parser.TokenType.COLON; |
|
36 |
import static jdk.nashorn.internal.parser.TokenType.COMMARIGHT; |
|
37 |
import static jdk.nashorn.internal.parser.TokenType.DECPOSTFIX; |
|
38 |
import static jdk.nashorn.internal.parser.TokenType.DECPREFIX; |
|
39 |
import static jdk.nashorn.internal.parser.TokenType.ELSE; |
|
40 |
import static jdk.nashorn.internal.parser.TokenType.EOF; |
|
41 |
import static jdk.nashorn.internal.parser.TokenType.EOL; |
|
42 |
import static jdk.nashorn.internal.parser.TokenType.FINALLY; |
|
43 |
import static jdk.nashorn.internal.parser.TokenType.FUNCTION; |
|
44 |
import static jdk.nashorn.internal.parser.TokenType.IDENT; |
|
45 |
import static jdk.nashorn.internal.parser.TokenType.IF; |
|
46 |
import static jdk.nashorn.internal.parser.TokenType.INCPOSTFIX; |
|
47 |
import static jdk.nashorn.internal.parser.TokenType.LBRACE; |
|
48 |
import static jdk.nashorn.internal.parser.TokenType.LPAREN; |
|
49 |
import static jdk.nashorn.internal.parser.TokenType.RBRACE; |
|
50 |
import static jdk.nashorn.internal.parser.TokenType.RBRACKET; |
|
51 |
import static jdk.nashorn.internal.parser.TokenType.RPAREN; |
|
52 |
import static jdk.nashorn.internal.parser.TokenType.SEMICOLON; |
|
53 |
import static jdk.nashorn.internal.parser.TokenType.TERNARY; |
|
54 |
import static jdk.nashorn.internal.parser.TokenType.WHILE; |
|
55 |
||
56 |
import java.util.ArrayList; |
|
57 |
import java.util.HashSet; |
|
16530
201d682e75f4
8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents:
16525
diff
changeset
|
58 |
import java.util.Iterator; |
17233 | 59 |
import java.util.LinkedHashMap; |
16147 | 60 |
import java.util.List; |
61 |
import java.util.Map; |
|
16233
95d3e01c04c3
8008199: Lazy compilation and trampoline implementation
lagergren
parents:
16211
diff
changeset
|
62 |
import jdk.nashorn.internal.codegen.CompilerConstants; |
95d3e01c04c3
8008199: Lazy compilation and trampoline implementation
lagergren
parents:
16211
diff
changeset
|
63 |
import jdk.nashorn.internal.codegen.Namespace; |
16147 | 64 |
import jdk.nashorn.internal.ir.AccessNode; |
17524
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
65 |
import jdk.nashorn.internal.ir.BaseNode; |
16147 | 66 |
import jdk.nashorn.internal.ir.BinaryNode; |
67 |
import jdk.nashorn.internal.ir.Block; |
|
17233 | 68 |
import jdk.nashorn.internal.ir.BlockLexicalContext; |
16147 | 69 |
import jdk.nashorn.internal.ir.BreakNode; |
70 |
import jdk.nashorn.internal.ir.BreakableNode; |
|
71 |
import jdk.nashorn.internal.ir.CallNode; |
|
72 |
import jdk.nashorn.internal.ir.CaseNode; |
|
73 |
import jdk.nashorn.internal.ir.CatchNode; |
|
74 |
import jdk.nashorn.internal.ir.ContinueNode; |
|
75 |
import jdk.nashorn.internal.ir.EmptyNode; |
|
76 |
import jdk.nashorn.internal.ir.ExecuteNode; |
|
77 |
import jdk.nashorn.internal.ir.ForNode; |
|
78 |
import jdk.nashorn.internal.ir.FunctionNode; |
|
16530
201d682e75f4
8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents:
16525
diff
changeset
|
79 |
import jdk.nashorn.internal.ir.FunctionNode.CompilationState; |
16147 | 80 |
import jdk.nashorn.internal.ir.IdentNode; |
81 |
import jdk.nashorn.internal.ir.IfNode; |
|
82 |
import jdk.nashorn.internal.ir.IndexNode; |
|
83 |
import jdk.nashorn.internal.ir.LabelNode; |
|
16530
201d682e75f4
8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents:
16525
diff
changeset
|
84 |
import jdk.nashorn.internal.ir.LexicalContext; |
16147 | 85 |
import jdk.nashorn.internal.ir.LiteralNode; |
17233 | 86 |
import jdk.nashorn.internal.ir.LoopNode; |
16147 | 87 |
import jdk.nashorn.internal.ir.Node; |
88 |
import jdk.nashorn.internal.ir.ObjectNode; |
|
89 |
import jdk.nashorn.internal.ir.PropertyKey; |
|
90 |
import jdk.nashorn.internal.ir.PropertyNode; |
|
91 |
import jdk.nashorn.internal.ir.ReturnNode; |
|
92 |
import jdk.nashorn.internal.ir.RuntimeNode; |
|
17524
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
93 |
import jdk.nashorn.internal.ir.Statement; |
16147 | 94 |
import jdk.nashorn.internal.ir.SwitchNode; |
95 |
import jdk.nashorn.internal.ir.TernaryNode; |
|
96 |
import jdk.nashorn.internal.ir.ThrowNode; |
|
97 |
import jdk.nashorn.internal.ir.TryNode; |
|
98 |
import jdk.nashorn.internal.ir.UnaryNode; |
|
99 |
import jdk.nashorn.internal.ir.VarNode; |
|
100 |
import jdk.nashorn.internal.ir.WhileNode; |
|
101 |
import jdk.nashorn.internal.ir.WithNode; |
|
16252
3bfe9b68a0fa
8008648: Lazy JIT scope and callee semantics bugfixes. Broke out wallclock timer.
lagergren
parents:
16245
diff
changeset
|
102 |
import jdk.nashorn.internal.runtime.DebugLogger; |
16233
95d3e01c04c3
8008199: Lazy compilation and trampoline implementation
lagergren
parents:
16211
diff
changeset
|
103 |
import jdk.nashorn.internal.runtime.ErrorManager; |
16147 | 104 |
import jdk.nashorn.internal.runtime.JSErrorType; |
105 |
import jdk.nashorn.internal.runtime.ParserException; |
|
16262
75513555e603
8008731: Separate configuration environment (options, error/output writer etc.) from Context
sundar
parents:
16252
diff
changeset
|
106 |
import jdk.nashorn.internal.runtime.ScriptEnvironment; |
16245
6a1c6c8bc113
8008371: Fix Dynalink compiler warnings and whitespace
attila
parents:
16239
diff
changeset
|
107 |
import jdk.nashorn.internal.runtime.ScriptingFunctions; |
16233
95d3e01c04c3
8008199: Lazy compilation and trampoline implementation
lagergren
parents:
16211
diff
changeset
|
108 |
import jdk.nashorn.internal.runtime.Source; |
16252
3bfe9b68a0fa
8008648: Lazy JIT scope and callee semantics bugfixes. Broke out wallclock timer.
lagergren
parents:
16245
diff
changeset
|
109 |
import jdk.nashorn.internal.runtime.Timing; |
16147 | 110 |
|
111 |
/** |
|
112 |
* Builds the IR. |
|
113 |
*/ |
|
114 |
public class Parser extends AbstractParser { |
|
16262
75513555e603
8008731: Separate configuration environment (options, error/output writer etc.) from Context
sundar
parents:
16252
diff
changeset
|
115 |
/** Current script environment. */ |
75513555e603
8008731: Separate configuration environment (options, error/output writer etc.) from Context
sundar
parents:
16252
diff
changeset
|
116 |
private final ScriptEnvironment env; |
16147 | 117 |
|
16211 | 118 |
/** Is scripting mode. */ |
119 |
private final boolean scripting; |
|
120 |
||
17524
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
121 |
private List<Statement> functionDeclarations; |
16147 | 122 |
|
17233 | 123 |
private final BlockLexicalContext lc = new BlockLexicalContext(); |
124 |
||
16233
95d3e01c04c3
8008199: Lazy compilation and trampoline implementation
lagergren
parents:
16211
diff
changeset
|
125 |
/** Namespace for function names where not explicitly given */ |
95d3e01c04c3
8008199: Lazy compilation and trampoline implementation
lagergren
parents:
16211
diff
changeset
|
126 |
private final Namespace namespace; |
95d3e01c04c3
8008199: Lazy compilation and trampoline implementation
lagergren
parents:
16211
diff
changeset
|
127 |
|
16525
1409942e618e
8009982: Lazy execution bugfix. Added lazy sunspider unit test. Added mandreel to compile-octane test. Fixed warnings
lagergren
parents:
16523
diff
changeset
|
128 |
private static final DebugLogger LOG = new DebugLogger("parser"); |
16252
3bfe9b68a0fa
8008648: Lazy JIT scope and callee semantics bugfixes. Broke out wallclock timer.
lagergren
parents:
16245
diff
changeset
|
129 |
|
16147 | 130 |
/** |
16233
95d3e01c04c3
8008199: Lazy compilation and trampoline implementation
lagergren
parents:
16211
diff
changeset
|
131 |
* Constructor |
95d3e01c04c3
8008199: Lazy compilation and trampoline implementation
lagergren
parents:
16211
diff
changeset
|
132 |
* |
16262
75513555e603
8008731: Separate configuration environment (options, error/output writer etc.) from Context
sundar
parents:
16252
diff
changeset
|
133 |
* @param env script environment |
16233
95d3e01c04c3
8008199: Lazy compilation and trampoline implementation
lagergren
parents:
16211
diff
changeset
|
134 |
* @param source source to parse |
95d3e01c04c3
8008199: Lazy compilation and trampoline implementation
lagergren
parents:
16211
diff
changeset
|
135 |
* @param errors error manager |
16147 | 136 |
*/ |
16262
75513555e603
8008731: Separate configuration environment (options, error/output writer etc.) from Context
sundar
parents:
16252
diff
changeset
|
137 |
public Parser(final ScriptEnvironment env, final Source source, final ErrorManager errors) { |
75513555e603
8008731: Separate configuration environment (options, error/output writer etc.) from Context
sundar
parents:
16252
diff
changeset
|
138 |
this(env, source, errors, env._strict); |
16147 | 139 |
} |
140 |
||
141 |
/** |
|
142 |
* Construct a parser. |
|
16233
95d3e01c04c3
8008199: Lazy compilation and trampoline implementation
lagergren
parents:
16211
diff
changeset
|
143 |
* |
16262
75513555e603
8008731: Separate configuration environment (options, error/output writer etc.) from Context
sundar
parents:
16252
diff
changeset
|
144 |
* @param env script environment |
16233
95d3e01c04c3
8008199: Lazy compilation and trampoline implementation
lagergren
parents:
16211
diff
changeset
|
145 |
* @param source source to parse |
95d3e01c04c3
8008199: Lazy compilation and trampoline implementation
lagergren
parents:
16211
diff
changeset
|
146 |
* @param errors error manager |
95d3e01c04c3
8008199: Lazy compilation and trampoline implementation
lagergren
parents:
16211
diff
changeset
|
147 |
* @param strict parser created with strict mode enabled. |
16147 | 148 |
*/ |
16262
75513555e603
8008731: Separate configuration environment (options, error/output writer etc.) from Context
sundar
parents:
16252
diff
changeset
|
149 |
public Parser(final ScriptEnvironment env, final Source source, final ErrorManager errors, final boolean strict) { |
16233
95d3e01c04c3
8008199: Lazy compilation and trampoline implementation
lagergren
parents:
16211
diff
changeset
|
150 |
super(source, errors, strict); |
17233 | 151 |
this.env = env; |
16262
75513555e603
8008731: Separate configuration environment (options, error/output writer etc.) from Context
sundar
parents:
16252
diff
changeset
|
152 |
this.namespace = new Namespace(env.getNamespace()); |
75513555e603
8008731: Separate configuration environment (options, error/output writer etc.) from Context
sundar
parents:
16252
diff
changeset
|
153 |
this.scripting = env._scripting; |
16147 | 154 |
} |
155 |
||
156 |
/** |
|
16233
95d3e01c04c3
8008199: Lazy compilation and trampoline implementation
lagergren
parents:
16211
diff
changeset
|
157 |
* Execute parse and return the resulting function node. |
95d3e01c04c3
8008199: Lazy compilation and trampoline implementation
lagergren
parents:
16211
diff
changeset
|
158 |
* Errors will be thrown and the error manager will contain information |
95d3e01c04c3
8008199: Lazy compilation and trampoline implementation
lagergren
parents:
16211
diff
changeset
|
159 |
* if parsing should fail |
95d3e01c04c3
8008199: Lazy compilation and trampoline implementation
lagergren
parents:
16211
diff
changeset
|
160 |
* |
95d3e01c04c3
8008199: Lazy compilation and trampoline implementation
lagergren
parents:
16211
diff
changeset
|
161 |
* This is the default parse call, which will name the function node |
95d3e01c04c3
8008199: Lazy compilation and trampoline implementation
lagergren
parents:
16211
diff
changeset
|
162 |
* "runScript" {@link CompilerConstants#RUN_SCRIPT} |
95d3e01c04c3
8008199: Lazy compilation and trampoline implementation
lagergren
parents:
16211
diff
changeset
|
163 |
* |
95d3e01c04c3
8008199: Lazy compilation and trampoline implementation
lagergren
parents:
16211
diff
changeset
|
164 |
* @return function node resulting from successful parse |
95d3e01c04c3
8008199: Lazy compilation and trampoline implementation
lagergren
parents:
16211
diff
changeset
|
165 |
*/ |
95d3e01c04c3
8008199: Lazy compilation and trampoline implementation
lagergren
parents:
16211
diff
changeset
|
166 |
public FunctionNode parse() { |
17233 | 167 |
return parse(RUN_SCRIPT.symbolName()); |
16233
95d3e01c04c3
8008199: Lazy compilation and trampoline implementation
lagergren
parents:
16211
diff
changeset
|
168 |
} |
95d3e01c04c3
8008199: Lazy compilation and trampoline implementation
lagergren
parents:
16211
diff
changeset
|
169 |
|
95d3e01c04c3
8008199: Lazy compilation and trampoline implementation
lagergren
parents:
16211
diff
changeset
|
170 |
/** |
95d3e01c04c3
8008199: Lazy compilation and trampoline implementation
lagergren
parents:
16211
diff
changeset
|
171 |
* Execute parse and return the resulting function node. |
95d3e01c04c3
8008199: Lazy compilation and trampoline implementation
lagergren
parents:
16211
diff
changeset
|
172 |
* Errors will be thrown and the error manager will contain information |
95d3e01c04c3
8008199: Lazy compilation and trampoline implementation
lagergren
parents:
16211
diff
changeset
|
173 |
* if parsing should fail |
95d3e01c04c3
8008199: Lazy compilation and trampoline implementation
lagergren
parents:
16211
diff
changeset
|
174 |
* |
95d3e01c04c3
8008199: Lazy compilation and trampoline implementation
lagergren
parents:
16211
diff
changeset
|
175 |
* @param scriptName name for the script, given to the parsed FunctionNode |
95d3e01c04c3
8008199: Lazy compilation and trampoline implementation
lagergren
parents:
16211
diff
changeset
|
176 |
* |
95d3e01c04c3
8008199: Lazy compilation and trampoline implementation
lagergren
parents:
16211
diff
changeset
|
177 |
* @return function node resulting from successful parse |
16147 | 178 |
*/ |
179 |
public FunctionNode parse(final String scriptName) { |
|
16252
3bfe9b68a0fa
8008648: Lazy JIT scope and callee semantics bugfixes. Broke out wallclock timer.
lagergren
parents:
16245
diff
changeset
|
180 |
final long t0 = Timing.isEnabled() ? System.currentTimeMillis() : 0L; |
17233 | 181 |
LOG.info(this, " begin for '", scriptName, "'"); |
16252
3bfe9b68a0fa
8008648: Lazy JIT scope and callee semantics bugfixes. Broke out wallclock timer.
lagergren
parents:
16245
diff
changeset
|
182 |
|
16147 | 183 |
try { |
184 |
stream = new TokenStream(); |
|
16262
75513555e603
8008731: Separate configuration environment (options, error/output writer etc.) from Context
sundar
parents:
16252
diff
changeset
|
185 |
lexer = new Lexer(source, stream, scripting && !env._no_syntax_extensions); |
16147 | 186 |
|
187 |
// Set up first token (skips opening EOL.) |
|
188 |
k = -1; |
|
189 |
next(); |
|
190 |
||
191 |
// Begin parse. |
|
192 |
return program(scriptName); |
|
193 |
} catch (final Exception e) { |
|
17973
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
194 |
handleParseException(e); |
16147 | 195 |
|
196 |
return null; |
|
17973
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
197 |
} finally { |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
198 |
final String end = this + " end '" + scriptName + "'"; |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
199 |
if (Timing.isEnabled()) { |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
200 |
Timing.accumulateTime(toString(), System.currentTimeMillis() - t0); |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
201 |
LOG.info(end, "' in ", (System.currentTimeMillis() - t0), " ms"); |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
202 |
} else { |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
203 |
LOG.info(end); |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
204 |
} |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
205 |
} |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
206 |
} |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
207 |
|
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
208 |
/** |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
209 |
* Parse and return the list of function parameter list. A comma |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
210 |
* separated list of function parameter identifiers is expected to be parsed. |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
211 |
* Errors will be thrown and the error manager will contain information |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
212 |
* if parsing should fail. This method is used to check if parameter Strings |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
213 |
* passed to "Function" constructor is a valid or not. |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
214 |
* |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
215 |
* @return the list of IdentNodes representing the formal parameter list |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
216 |
*/ |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
217 |
public List<IdentNode> parseFormalParameterList() { |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
218 |
try { |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
219 |
stream = new TokenStream(); |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
220 |
lexer = new Lexer(source, stream, scripting && !env._no_syntax_extensions); |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
221 |
|
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
222 |
// Set up first token (skips opening EOL.) |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
223 |
k = -1; |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
224 |
next(); |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
225 |
|
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
226 |
return formalParameterList(TokenType.EOF); |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
227 |
} catch (final Exception e) { |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
228 |
handleParseException(e); |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
229 |
return null; |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
230 |
} |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
231 |
} |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
232 |
|
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
233 |
/** |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
234 |
* Execute parse and return the resulting function node. |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
235 |
* Errors will be thrown and the error manager will contain information |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
236 |
* if parsing should fail. This method is used to check if code String |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
237 |
* passed to "Function" constructor is a valid function body or not. |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
238 |
* |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
239 |
* @return function node resulting from successful parse |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
240 |
*/ |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
241 |
public FunctionNode parseFunctionBody() { |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
242 |
try { |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
243 |
stream = new TokenStream(); |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
244 |
lexer = new Lexer(source, stream, scripting && !env._no_syntax_extensions); |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
245 |
|
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
246 |
// Set up first token (skips opening EOL.) |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
247 |
k = -1; |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
248 |
next(); |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
249 |
|
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
250 |
// Make a fake token for the function. |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
251 |
final long functionToken = Token.toDesc(FUNCTION, 0, source.getLength()); |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
252 |
// Set up the function to append elements. |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
253 |
|
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
254 |
FunctionNode function = newFunctionNode( |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
255 |
functionToken, |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
256 |
new IdentNode(functionToken, Token.descPosition(functionToken), RUN_SCRIPT.symbolName()), |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
257 |
new ArrayList<IdentNode>(), |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
258 |
FunctionNode.Kind.NORMAL); |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
259 |
|
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
260 |
functionDeclarations = new ArrayList<>(); |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
261 |
sourceElements(); |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
262 |
addFunctionDeclarations(function); |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
263 |
functionDeclarations = null; |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
264 |
|
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
265 |
expect(EOF); |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
266 |
|
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
267 |
function.setFinish(source.getLength() - 1); |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
268 |
|
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
269 |
function = restoreFunctionNode(function, token); //commit code |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
270 |
function = function.setBody(lc, function.getBody().setNeedsScope(lc)); |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
271 |
return function; |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
272 |
} catch (final Exception e) { |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
273 |
handleParseException(e); |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
274 |
return null; |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
275 |
} |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
276 |
} |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
277 |
|
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
278 |
private void handleParseException(final Exception e) { |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
279 |
// Extract message from exception. The message will be in error |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
280 |
// message format. |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
281 |
String message = e.getMessage(); |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
282 |
|
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
283 |
// If empty message. |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
284 |
if (message == null) { |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
285 |
message = e.toString(); |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
286 |
} |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
287 |
|
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
288 |
// Issue message. |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
289 |
if (e instanceof ParserException) { |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
290 |
errors.error((ParserException)e); |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
291 |
} else { |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
292 |
errors.error(message); |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
293 |
} |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
294 |
|
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
295 |
if (env._dump_on_error) { |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
296 |
e.printStackTrace(env.getErr()); |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
297 |
} |
16147 | 298 |
} |
299 |
||
300 |
/** |
|
301 |
* Skip to a good parsing recovery point. |
|
302 |
*/ |
|
303 |
private void recover(final Exception e) { |
|
304 |
if (e != null) { |
|
305 |
// Extract message from exception. The message will be in error |
|
306 |
// message format. |
|
307 |
String message = e.getMessage(); |
|
308 |
||
309 |
// If empty message. |
|
310 |
if (message == null) { |
|
311 |
message = e.toString(); |
|
312 |
} |
|
313 |
||
314 |
// Issue message. |
|
315 |
if (e instanceof ParserException) { |
|
316 |
errors.error((ParserException)e); |
|
317 |
} else { |
|
318 |
errors.error(message); |
|
319 |
} |
|
320 |
||
16262
75513555e603
8008731: Separate configuration environment (options, error/output writer etc.) from Context
sundar
parents:
16252
diff
changeset
|
321 |
if (env._dump_on_error) { |
75513555e603
8008731: Separate configuration environment (options, error/output writer etc.) from Context
sundar
parents:
16252
diff
changeset
|
322 |
e.printStackTrace(env.getErr()); |
16147 | 323 |
} |
324 |
} |
|
325 |
||
326 |
// Skip to a recovery point. |
|
327 |
loop: |
|
328 |
while (true) { |
|
329 |
switch (type) { |
|
330 |
case EOF: |
|
331 |
// Can not go any further. |
|
332 |
break loop; |
|
333 |
case EOL: |
|
334 |
case SEMICOLON: |
|
335 |
case RBRACE: |
|
336 |
// Good recovery points. |
|
337 |
next(); |
|
338 |
break loop; |
|
339 |
default: |
|
340 |
// So we can recover after EOL. |
|
341 |
nextOrEOL(); |
|
342 |
break; |
|
343 |
} |
|
344 |
} |
|
345 |
} |
|
346 |
||
347 |
/** |
|
348 |
* Set up a new block. |
|
349 |
* |
|
350 |
* @return New block. |
|
351 |
*/ |
|
352 |
private Block newBlock() { |
|
17524
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
353 |
return lc.push(new Block(line, token, Token.descPosition(token))); |
16147 | 354 |
} |
355 |
||
356 |
/** |
|
357 |
* Set up a new function block. |
|
358 |
* |
|
359 |
* @param ident Name of function. |
|
360 |
* @return New block. |
|
361 |
*/ |
|
17233 | 362 |
private FunctionNode newFunctionNode(final long startToken, final IdentNode ident, final List<IdentNode> parameters, final FunctionNode.Kind kind) { |
16147 | 363 |
// Build function name. |
364 |
final StringBuilder sb = new StringBuilder(); |
|
365 |
||
17233 | 366 |
final FunctionNode parentFunction = lc.getCurrentFunction(); |
367 |
if (parentFunction != null && !parentFunction.isProgram()) { |
|
16530
201d682e75f4
8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents:
16525
diff
changeset
|
368 |
sb.append(parentFunction.getName()).append('$'); |
16147 | 369 |
} |
370 |
||
17233 | 371 |
sb.append(ident != null ? ident.getName() : FUNCTION_PREFIX.symbolName()); |
16233
95d3e01c04c3
8008199: Lazy compilation and trampoline implementation
lagergren
parents:
16211
diff
changeset
|
372 |
final String name = namespace.uniqueName(sb.toString()); |
17233 | 373 |
assert parentFunction != null || name.equals(RUN_SCRIPT.symbolName()) : "name = " + name;// must not rename runScript(). |
374 |
||
375 |
int flags = 0; |
|
376 |
if (parentFunction == null) { |
|
377 |
flags |= FunctionNode.IS_PROGRAM; |
|
378 |
} |
|
379 |
if (isStrictMode) { |
|
380 |
flags |= FunctionNode.IS_STRICT; |
|
381 |
} |
|
17518
2225a4f929c0
8013477: Node.setSymbol needs to be copy on write - enable IR snapshots for recompilation based on callsite type specialization. [not enabled by default, hidden by a flag for now]
lagergren
parents:
17257
diff
changeset
|
382 |
if (env._specialize_calls != null) { |
2225a4f929c0
8013477: Node.setSymbol needs to be copy on write - enable IR snapshots for recompilation based on callsite type specialization. [not enabled by default, hidden by a flag for now]
lagergren
parents:
17257
diff
changeset
|
383 |
if (env._specialize_calls.contains(name)) { |
2225a4f929c0
8013477: Node.setSymbol needs to be copy on write - enable IR snapshots for recompilation based on callsite type specialization. [not enabled by default, hidden by a flag for now]
lagergren
parents:
17257
diff
changeset
|
384 |
flags |= FunctionNode.CAN_SPECIALIZE; |
2225a4f929c0
8013477: Node.setSymbol needs to be copy on write - enable IR snapshots for recompilation based on callsite type specialization. [not enabled by default, hidden by a flag for now]
lagergren
parents:
17257
diff
changeset
|
385 |
} |
2225a4f929c0
8013477: Node.setSymbol needs to be copy on write - enable IR snapshots for recompilation based on callsite type specialization. [not enabled by default, hidden by a flag for now]
lagergren
parents:
17257
diff
changeset
|
386 |
} |
16147 | 387 |
|
388 |
// Start new block. |
|
17233 | 389 |
FunctionNode functionNode = |
390 |
new FunctionNode( |
|
391 |
source, |
|
17524
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
392 |
line, //TODO? |
17233 | 393 |
token, |
394 |
Token.descPosition(token), |
|
395 |
startToken, |
|
396 |
namespace, |
|
397 |
ident, |
|
398 |
name, |
|
399 |
parameters, |
|
400 |
kind, |
|
401 |
flags); |
|
402 |
||
403 |
lc.push(functionNode); |
|
404 |
// Create new block, and just put it on the context stack, restoreFunctionNode() will associate it with the |
|
405 |
// FunctionNode. |
|
406 |
newBlock(); |
|
17518
2225a4f929c0
8013477: Node.setSymbol needs to be copy on write - enable IR snapshots for recompilation based on callsite type specialization. [not enabled by default, hidden by a flag for now]
lagergren
parents:
17257
diff
changeset
|
407 |
|
17233 | 408 |
return functionNode; |
16147 | 409 |
} |
410 |
||
411 |
/** |
|
412 |
* Restore the current block. |
|
413 |
*/ |
|
17233 | 414 |
private Block restoreBlock(final Block block) { |
17518
2225a4f929c0
8013477: Node.setSymbol needs to be copy on write - enable IR snapshots for recompilation based on callsite type specialization. [not enabled by default, hidden by a flag for now]
lagergren
parents:
17257
diff
changeset
|
415 |
return lc.pop(block); |
17233 | 416 |
} |
417 |
||
17518
2225a4f929c0
8013477: Node.setSymbol needs to be copy on write - enable IR snapshots for recompilation based on callsite type specialization. [not enabled by default, hidden by a flag for now]
lagergren
parents:
17257
diff
changeset
|
418 |
|
17233 | 419 |
private FunctionNode restoreFunctionNode(final FunctionNode functionNode, final long lastToken) { |
420 |
final Block newBody = restoreBlock(lc.getFunctionBody(functionNode)); |
|
421 |
||
17518
2225a4f929c0
8013477: Node.setSymbol needs to be copy on write - enable IR snapshots for recompilation based on callsite type specialization. [not enabled by default, hidden by a flag for now]
lagergren
parents:
17257
diff
changeset
|
422 |
return lc.pop(functionNode). |
2225a4f929c0
8013477: Node.setSymbol needs to be copy on write - enable IR snapshots for recompilation based on callsite type specialization. [not enabled by default, hidden by a flag for now]
lagergren
parents:
17257
diff
changeset
|
423 |
setBody(lc, newBody). |
2225a4f929c0
8013477: Node.setSymbol needs to be copy on write - enable IR snapshots for recompilation based on callsite type specialization. [not enabled by default, hidden by a flag for now]
lagergren
parents:
17257
diff
changeset
|
424 |
setLastToken(lc, lastToken). |
2225a4f929c0
8013477: Node.setSymbol needs to be copy on write - enable IR snapshots for recompilation based on callsite type specialization. [not enabled by default, hidden by a flag for now]
lagergren
parents:
17257
diff
changeset
|
425 |
setState(lc, errors.hasErrors() ? CompilationState.PARSE_ERROR : CompilationState.PARSED). |
2225a4f929c0
8013477: Node.setSymbol needs to be copy on write - enable IR snapshots for recompilation based on callsite type specialization. [not enabled by default, hidden by a flag for now]
lagergren
parents:
17257
diff
changeset
|
426 |
snapshot(lc); |
2225a4f929c0
8013477: Node.setSymbol needs to be copy on write - enable IR snapshots for recompilation based on callsite type specialization. [not enabled by default, hidden by a flag for now]
lagergren
parents:
17257
diff
changeset
|
427 |
} |
16147 | 428 |
|
429 |
/** |
|
430 |
* Get the statements in a block. |
|
431 |
* @return Block statements. |
|
432 |
*/ |
|
433 |
private Block getBlock(final boolean needsBraces) { |
|
434 |
// Set up new block. Captures LBRACE. |
|
17233 | 435 |
Block newBlock = newBlock(); |
16147 | 436 |
try { |
16530
201d682e75f4
8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents:
16525
diff
changeset
|
437 |
// Block opening brace. |
201d682e75f4
8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents:
16525
diff
changeset
|
438 |
if (needsBraces) { |
201d682e75f4
8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents:
16525
diff
changeset
|
439 |
expect(LBRACE); |
201d682e75f4
8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents:
16525
diff
changeset
|
440 |
} |
17233 | 441 |
// Accumulate block statements. |
442 |
statementList(); |
|
443 |
||
16147 | 444 |
} finally { |
17233 | 445 |
newBlock = restoreBlock(newBlock); |
16147 | 446 |
} |
447 |
||
16523
af8b30edebce
8009718: Lazy execution architecture continued - ScriptFunctionData is either final or recompilable. Moved ScriptFunctionData creation logic away from runtime to compile time. Prepared for method generation/specialization. Got rid of ScriptFunctionImplTrampoline whose semantics could be done as part of the relinking anyway. Merge with the lookup package change.
lagergren
parents:
16262
diff
changeset
|
448 |
final int possibleEnd = Token.descPosition(token) + Token.descLength(token); |
16147 | 449 |
|
450 |
// Block closing brace. |
|
451 |
if (needsBraces) { |
|
452 |
expect(RBRACE); |
|
453 |
} |
|
454 |
||
455 |
newBlock.setFinish(possibleEnd); |
|
456 |
||
457 |
return newBlock; |
|
458 |
} |
|
459 |
||
460 |
/** |
|
461 |
* Get all the statements generated by a single statement. |
|
462 |
* @return Statements. |
|
463 |
*/ |
|
464 |
private Block getStatement() { |
|
465 |
if (type == LBRACE) { |
|
466 |
return getBlock(true); |
|
467 |
} |
|
468 |
// Set up new block. Captures first token. |
|
17233 | 469 |
Block newBlock = newBlock(); |
16147 | 470 |
try { |
471 |
statement(); |
|
472 |
} finally { |
|
17233 | 473 |
newBlock = restoreBlock(newBlock); |
16147 | 474 |
} |
475 |
return newBlock; |
|
476 |
} |
|
477 |
||
478 |
/** |
|
479 |
* Detect calls to special functions. |
|
480 |
* @param ident Called function. |
|
481 |
*/ |
|
482 |
private void detectSpecialFunction(final IdentNode ident) { |
|
483 |
final String name = ident.getName(); |
|
484 |
||
17233 | 485 |
if (EVAL.symbolName().equals(name)) { |
17255 | 486 |
markEval(lc); |
16147 | 487 |
} |
488 |
} |
|
489 |
||
490 |
/** |
|
491 |
* Detect use of special properties. |
|
492 |
* @param ident Referenced property. |
|
493 |
*/ |
|
494 |
private void detectSpecialProperty(final IdentNode ident) { |
|
495 |
final String name = ident.getName(); |
|
496 |
||
17233 | 497 |
if (ARGUMENTS.symbolName().equals(name)) { |
498 |
lc.setFlag(lc.getCurrentFunction(), FunctionNode.USES_ARGUMENTS); |
|
16147 | 499 |
} |
500 |
} |
|
501 |
||
502 |
/** |
|
503 |
* Tells whether a IdentNode can be used as L-value of an assignment |
|
504 |
* |
|
505 |
* @param ident IdentNode to be checked |
|
506 |
* @return whether the ident can be used as L-value |
|
507 |
*/ |
|
508 |
private static boolean checkIdentLValue(final IdentNode ident) { |
|
509 |
return Token.descType(ident.getToken()).getKind() != TokenKind.KEYWORD; |
|
510 |
} |
|
511 |
||
512 |
/** |
|
513 |
* Verify an assignment expression. |
|
514 |
* @param op Operation token. |
|
515 |
* @param lhs Left hand side expression. |
|
516 |
* @param rhs Right hand side expression. |
|
517 |
* @return Verified expression. |
|
518 |
*/ |
|
519 |
private Node verifyAssignment(final long op, final Node lhs, final Node rhs) { |
|
520 |
final TokenType opType = Token.descType(op); |
|
521 |
||
522 |
switch (opType) { |
|
523 |
case ASSIGN: |
|
524 |
case ASSIGN_ADD: |
|
525 |
case ASSIGN_BIT_AND: |
|
526 |
case ASSIGN_BIT_OR: |
|
527 |
case ASSIGN_BIT_XOR: |
|
528 |
case ASSIGN_DIV: |
|
529 |
case ASSIGN_MOD: |
|
530 |
case ASSIGN_MUL: |
|
531 |
case ASSIGN_SAR: |
|
532 |
case ASSIGN_SHL: |
|
533 |
case ASSIGN_SHR: |
|
534 |
case ASSIGN_SUB: |
|
535 |
if (!(lhs instanceof AccessNode || |
|
536 |
lhs instanceof IndexNode || |
|
537 |
lhs instanceof IdentNode)) { |
|
16262
75513555e603
8008731: Separate configuration environment (options, error/output writer etc.) from Context
sundar
parents:
16252
diff
changeset
|
538 |
if (env._early_lvalue_error) { |
17233 | 539 |
throw error(JSErrorType.REFERENCE_ERROR, AbstractParser.message("invalid.lvalue"), lhs.getToken()); |
16147 | 540 |
} |
541 |
return referenceError(lhs, rhs); |
|
542 |
} |
|
543 |
||
544 |
if (lhs instanceof IdentNode) { |
|
16523
af8b30edebce
8009718: Lazy execution architecture continued - ScriptFunctionData is either final or recompilable. Moved ScriptFunctionData creation logic away from runtime to compile time. Prepared for method generation/specialization. Got rid of ScriptFunctionImplTrampoline whose semantics could be done as part of the relinking anyway. Merge with the lookup package change.
lagergren
parents:
16262
diff
changeset
|
545 |
if (!checkIdentLValue((IdentNode)lhs)) { |
16147 | 546 |
return referenceError(lhs, rhs); |
547 |
} |
|
548 |
verifyStrictIdent((IdentNode)lhs, "assignment"); |
|
549 |
} |
|
550 |
break; |
|
551 |
||
552 |
default: |
|
553 |
break; |
|
554 |
} |
|
555 |
||
556 |
// Build up node. |
|
17523
cb4a7c901e0d
8013913: Removed Source field from all nodes except FunctionNode in order to save footprint
lagergren
parents:
17518
diff
changeset
|
557 |
return new BinaryNode(op, lhs, rhs); |
16147 | 558 |
} |
559 |
||
560 |
/** |
|
561 |
* Reduce increment/decrement to simpler operations. |
|
562 |
* @param firstToken First token. |
|
563 |
* @param tokenType Operation token (INCPREFIX/DEC.) |
|
564 |
* @param expression Left hand side expression. |
|
565 |
* @param isPostfix Prefix or postfix. |
|
566 |
* @return Reduced expression. |
|
567 |
*/ |
|
17523
cb4a7c901e0d
8013913: Removed Source field from all nodes except FunctionNode in order to save footprint
lagergren
parents:
17518
diff
changeset
|
568 |
private static Node incDecExpression(final long firstToken, final TokenType tokenType, final Node expression, final boolean isPostfix) { |
16147 | 569 |
if (isPostfix) { |
17523
cb4a7c901e0d
8013913: Removed Source field from all nodes except FunctionNode in order to save footprint
lagergren
parents:
17518
diff
changeset
|
570 |
return new UnaryNode(Token.recast(firstToken, tokenType == DECPREFIX ? DECPOSTFIX : INCPOSTFIX), expression.getStart(), Token.descPosition(firstToken) + Token.descLength(firstToken), expression); |
16147 | 571 |
} |
572 |
||
17523
cb4a7c901e0d
8013913: Removed Source field from all nodes except FunctionNode in order to save footprint
lagergren
parents:
17518
diff
changeset
|
573 |
return new UnaryNode(firstToken, expression); |
16147 | 574 |
} |
575 |
||
576 |
/** |
|
577 |
* ----------------------------------------------------------------------- |
|
578 |
* |
|
579 |
* Grammar based on |
|
580 |
* |
|
581 |
* ECMAScript Language Specification |
|
582 |
* ECMA-262 5th Edition / December 2009 |
|
583 |
* |
|
584 |
* ----------------------------------------------------------------------- |
|
585 |
*/ |
|
586 |
||
587 |
/** |
|
588 |
* Program : |
|
589 |
* SourceElements? |
|
590 |
* |
|
591 |
* See 14 |
|
592 |
* |
|
593 |
* Parse the top level script. |
|
594 |
*/ |
|
595 |
private FunctionNode program(final String scriptName) { |
|
596 |
// Make a fake token for the script. |
|
597 |
final long functionToken = Token.toDesc(FUNCTION, 0, source.getLength()); |
|
598 |
// Set up the script to append elements. |
|
16523
af8b30edebce
8009718: Lazy execution architecture continued - ScriptFunctionData is either final or recompilable. Moved ScriptFunctionData creation logic away from runtime to compile time. Prepared for method generation/specialization. Got rid of ScriptFunctionImplTrampoline whose semantics could be done as part of the relinking anyway. Merge with the lookup package change.
lagergren
parents:
16262
diff
changeset
|
599 |
|
17233 | 600 |
FunctionNode script = newFunctionNode( |
601 |
functionToken, |
|
17523
cb4a7c901e0d
8013913: Removed Source field from all nodes except FunctionNode in order to save footprint
lagergren
parents:
17518
diff
changeset
|
602 |
new IdentNode(functionToken, Token.descPosition(functionToken), scriptName), |
17233 | 603 |
new ArrayList<IdentNode>(), |
604 |
FunctionNode.Kind.SCRIPT); |
|
605 |
||
16530
201d682e75f4
8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents:
16525
diff
changeset
|
606 |
functionDeclarations = new ArrayList<>(); |
16147 | 607 |
sourceElements(); |
17233 | 608 |
addFunctionDeclarations(script); |
16530
201d682e75f4
8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents:
16525
diff
changeset
|
609 |
functionDeclarations = null; |
17233 | 610 |
|
16147 | 611 |
expect(EOF); |
17233 | 612 |
|
16147 | 613 |
script.setFinish(source.getLength() - 1); |
614 |
||
17233 | 615 |
script = restoreFunctionNode(script, token); //commit code |
616 |
script = script.setBody(lc, script.getBody().setNeedsScope(lc)); |
|
17518
2225a4f929c0
8013477: Node.setSymbol needs to be copy on write - enable IR snapshots for recompilation based on callsite type specialization. [not enabled by default, hidden by a flag for now]
lagergren
parents:
17257
diff
changeset
|
617 |
|
16147 | 618 |
return script; |
619 |
} |
|
620 |
||
621 |
/** |
|
622 |
* Directive value or null if statement is not a directive. |
|
623 |
* |
|
624 |
* @param stmt Statement to be checked |
|
625 |
* @return Directive value if the given statement is a directive |
|
626 |
*/ |
|
627 |
private String getDirective(final Node stmt) { |
|
628 |
if (stmt instanceof ExecuteNode) { |
|
629 |
final Node expr = ((ExecuteNode)stmt).getExpression(); |
|
630 |
if (expr instanceof LiteralNode) { |
|
631 |
final LiteralNode<?> lit = (LiteralNode<?>)expr; |
|
632 |
final long litToken = lit.getToken(); |
|
633 |
final TokenType tt = Token.descType(litToken); |
|
634 |
// A directive is either a string or an escape string |
|
635 |
if (tt == TokenType.STRING || tt == TokenType.ESCSTRING) { |
|
636 |
// Make sure that we don't unescape anything. Return as seen in source! |
|
637 |
return source.getString(lit.getStart(), Token.descLength(litToken)); |
|
638 |
} |
|
639 |
} |
|
640 |
} |
|
641 |
||
642 |
return null; |
|
643 |
} |
|
644 |
||
645 |
/** |
|
646 |
* SourceElements : |
|
647 |
* SourceElement |
|
648 |
* SourceElements SourceElement |
|
649 |
* |
|
650 |
* See 14 |
|
651 |
* |
|
652 |
* Parse the elements of the script or function. |
|
653 |
*/ |
|
654 |
private void sourceElements() { |
|
655 |
List<Node> directiveStmts = null; |
|
656 |
boolean checkDirective = true; |
|
657 |
final boolean oldStrictMode = isStrictMode; |
|
658 |
||
659 |
try { |
|
660 |
// If is a script, then process until the end of the script. |
|
661 |
while (type != EOF) { |
|
662 |
// Break if the end of a code block. |
|
663 |
if (type == RBRACE) { |
|
664 |
break; |
|
665 |
} |
|
666 |
||
667 |
try { |
|
668 |
// Get the next element. |
|
669 |
statement(true); |
|
670 |
||
671 |
// check for directive prologues |
|
672 |
if (checkDirective) { |
|
673 |
// skip any debug statement like line number to get actual first line |
|
17233 | 674 |
final Node lastStatement = lc.getLastStatement(); |
16147 | 675 |
|
676 |
// get directive prologue, if any |
|
677 |
final String directive = getDirective(lastStatement); |
|
678 |
||
679 |
// If we have seen first non-directive statement, |
|
680 |
// no more directive statements!! |
|
681 |
checkDirective = directive != null; |
|
682 |
||
683 |
if (checkDirective) { |
|
684 |
if (!oldStrictMode) { |
|
685 |
if (directiveStmts == null) { |
|
686 |
directiveStmts = new ArrayList<>(); |
|
687 |
} |
|
688 |
directiveStmts.add(lastStatement); |
|
689 |
} |
|
690 |
||
691 |
// handle use strict directive |
|
692 |
if ("use strict".equals(directive)) { |
|
693 |
isStrictMode = true; |
|
17233 | 694 |
final FunctionNode function = lc.getCurrentFunction(); |
695 |
lc.setFlag(lc.getCurrentFunction(), FunctionNode.IS_STRICT); |
|
16147 | 696 |
|
697 |
// We don't need to check these, if lexical environment is already strict |
|
698 |
if (!oldStrictMode && directiveStmts != null) { |
|
699 |
// check that directives preceding this one do not violate strictness |
|
700 |
for (final Node statement : directiveStmts) { |
|
701 |
// the get value will force unescape of preceeding |
|
702 |
// escaped string directives |
|
703 |
getValue(statement.getToken()); |
|
704 |
} |
|
705 |
||
706 |
// verify that function name as well as parameter names |
|
16201
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16196
diff
changeset
|
707 |
// satisfy strict mode restrictions. |
16147 | 708 |
verifyStrictIdent(function.getIdent(), "function name"); |
709 |
for (final IdentNode param : function.getParameters()) { |
|
710 |
verifyStrictIdent(param, "function parameter"); |
|
711 |
} |
|
712 |
} |
|
713 |
} |
|
714 |
} |
|
715 |
} |
|
716 |
} catch (final Exception e) { |
|
17233 | 717 |
//recover parsing |
16147 | 718 |
recover(e); |
719 |
} |
|
720 |
||
721 |
// No backtracking from here on. |
|
722 |
stream.commit(k); |
|
723 |
} |
|
724 |
} finally { |
|
725 |
isStrictMode = oldStrictMode; |
|
726 |
} |
|
727 |
} |
|
728 |
||
729 |
/** |
|
730 |
* Statement : |
|
731 |
* Block |
|
732 |
* VariableStatement |
|
733 |
* EmptyStatement |
|
734 |
* ExpressionStatement |
|
735 |
* IfStatement |
|
736 |
* IterationStatement |
|
737 |
* ContinueStatement |
|
738 |
* BreakStatement |
|
739 |
* ReturnStatement |
|
740 |
* WithStatement |
|
741 |
* LabelledStatement |
|
742 |
* SwitchStatement |
|
743 |
* ThrowStatement |
|
744 |
* TryStatement |
|
745 |
* DebuggerStatement |
|
746 |
* |
|
747 |
* see 12 |
|
748 |
* |
|
749 |
* Parse any of the basic statement types. |
|
750 |
*/ |
|
751 |
private void statement() { |
|
752 |
statement(false); |
|
753 |
} |
|
754 |
||
755 |
/** |
|
756 |
* @param topLevel does this statement occur at the "top level" of a script or a function? |
|
757 |
*/ |
|
758 |
private void statement(final boolean topLevel) { |
|
759 |
if (type == FUNCTION) { |
|
760 |
// As per spec (ECMA section 12), function declarations as arbitrary statement |
|
761 |
// is not "portable". Implementation can issue a warning or disallow the same. |
|
16530
201d682e75f4
8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents:
16525
diff
changeset
|
762 |
functionExpression(true, topLevel); |
16147 | 763 |
return; |
764 |
} |
|
765 |
||
766 |
switch (type) { |
|
767 |
case LBRACE: |
|
768 |
block(); |
|
769 |
break; |
|
770 |
case RBRACE: |
|
771 |
break; |
|
772 |
case VAR: |
|
773 |
variableStatement(true); |
|
774 |
break; |
|
775 |
case SEMICOLON: |
|
776 |
emptyStatement(); |
|
777 |
break; |
|
778 |
case IF: |
|
779 |
ifStatement(); |
|
780 |
break; |
|
781 |
case FOR: |
|
782 |
forStatement(); |
|
783 |
break; |
|
784 |
case WHILE: |
|
785 |
whileStatement(); |
|
786 |
break; |
|
787 |
case DO: |
|
788 |
doStatement(); |
|
789 |
break; |
|
790 |
case CONTINUE: |
|
791 |
continueStatement(); |
|
792 |
break; |
|
793 |
case BREAK: |
|
794 |
breakStatement(); |
|
795 |
break; |
|
796 |
case RETURN: |
|
797 |
returnStatement(); |
|
798 |
break; |
|
799 |
case YIELD: |
|
800 |
yieldStatement(); |
|
801 |
break; |
|
802 |
case WITH: |
|
803 |
withStatement(); |
|
804 |
break; |
|
805 |
case SWITCH: |
|
806 |
switchStatement(); |
|
807 |
break; |
|
808 |
case THROW: |
|
809 |
throwStatement(); |
|
810 |
break; |
|
811 |
case TRY: |
|
812 |
tryStatement(); |
|
813 |
break; |
|
814 |
case DEBUGGER: |
|
815 |
debuggerStatement(); |
|
816 |
break; |
|
817 |
case RPAREN: |
|
818 |
case RBRACKET: |
|
819 |
case EOF: |
|
820 |
expect(SEMICOLON); |
|
821 |
break; |
|
822 |
default: |
|
823 |
if (type == IDENT || isNonStrictModeIdent()) { |
|
824 |
if (T(k + 1) == COLON) { |
|
825 |
labelStatement(); |
|
826 |
return; |
|
827 |
} |
|
828 |
} |
|
829 |
||
830 |
expressionStatement(); |
|
831 |
break; |
|
832 |
} |
|
833 |
} |
|
834 |
||
835 |
/** |
|
836 |
* block : |
|
837 |
* { StatementList? } |
|
838 |
* |
|
839 |
* see 12.1 |
|
840 |
* |
|
841 |
* Parse a statement block. |
|
842 |
*/ |
|
843 |
private void block() { |
|
844 |
final Block newBlock = getBlock(true); |
|
845 |
// Force block execution. |
|
17524
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
846 |
appendStatement(new ExecuteNode(newBlock.getLineNumber(), newBlock.getToken(), finish, newBlock)); |
16147 | 847 |
} |
848 |
||
849 |
/** |
|
850 |
* StatementList : |
|
851 |
* Statement |
|
852 |
* StatementList Statement |
|
853 |
* |
|
854 |
* See 12.1 |
|
855 |
* |
|
856 |
* Parse a list of statements. |
|
857 |
*/ |
|
858 |
private void statementList() { |
|
859 |
// Accumulate statements until end of list. */ |
|
860 |
loop: |
|
861 |
while (type != EOF) { |
|
862 |
switch (type) { |
|
863 |
case EOF: |
|
864 |
case CASE: |
|
865 |
case DEFAULT: |
|
866 |
case RBRACE: |
|
867 |
break loop; |
|
868 |
default: |
|
869 |
break; |
|
870 |
} |
|
871 |
||
872 |
// Get next statement. |
|
873 |
statement(); |
|
874 |
} |
|
875 |
} |
|
876 |
||
877 |
/** |
|
878 |
* Make sure that in strict mode, the identifier name used is allowed. |
|
879 |
* |
|
880 |
* @param ident Identifier that is verified |
|
881 |
* @param contextString String used in error message to give context to the user |
|
882 |
*/ |
|
883 |
private void verifyStrictIdent(final IdentNode ident, final String contextString) { |
|
884 |
if (isStrictMode) { |
|
885 |
switch (ident.getName()) { |
|
886 |
case "eval": |
|
887 |
case "arguments": |
|
17233 | 888 |
throw error(AbstractParser.message("strict.name", ident.getName(), contextString), ident.getToken()); |
16147 | 889 |
default: |
890 |
break; |
|
891 |
} |
|
892 |
} |
|
893 |
} |
|
894 |
||
895 |
/** |
|
896 |
* VariableStatement : |
|
897 |
* var VariableDeclarationList ; |
|
898 |
* |
|
899 |
* VariableDeclarationList : |
|
900 |
* VariableDeclaration |
|
901 |
* VariableDeclarationList , VariableDeclaration |
|
902 |
* |
|
903 |
* VariableDeclaration : |
|
904 |
* Identifier Initializer? |
|
905 |
* |
|
906 |
* Initializer : |
|
907 |
* = AssignmentExpression |
|
908 |
* |
|
909 |
* See 12.2 |
|
910 |
* |
|
911 |
* Parse a VAR statement. |
|
912 |
* @param isStatement True if a statement (not used in a FOR.) |
|
913 |
*/ |
|
914 |
private List<VarNode> variableStatement(final boolean isStatement) { |
|
915 |
// VAR tested in caller. |
|
916 |
next(); |
|
917 |
||
918 |
final List<VarNode> vars = new ArrayList<>(); |
|
919 |
||
920 |
while (true) { |
|
921 |
// Get starting token. |
|
17524
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
922 |
final int varLine = line; |
16147 | 923 |
final long varToken = token; |
924 |
// Get name of var. |
|
925 |
final IdentNode name = getIdent(); |
|
926 |
verifyStrictIdent(name, "variable name"); |
|
927 |
||
928 |
// Assume no init. |
|
929 |
Node init = null; |
|
930 |
||
931 |
// Look for initializer assignment. |
|
932 |
if (type == ASSIGN) { |
|
933 |
next(); |
|
934 |
||
935 |
// Get initializer expression. Suppress IN if not statement. |
|
936 |
init = assignmentExpression(!isStatement); |
|
937 |
} |
|
938 |
||
939 |
// Allocate var node. |
|
17524
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
940 |
final VarNode var = new VarNode(varLine, varToken, finish, name, init); |
16147 | 941 |
vars.add(var); |
17233 | 942 |
appendStatement(var); |
16147 | 943 |
|
944 |
if (type != COMMARIGHT) { |
|
945 |
break; |
|
946 |
} |
|
947 |
next(); |
|
948 |
} |
|
949 |
||
950 |
// If is a statement then handle end of line. |
|
951 |
if (isStatement) { |
|
16153 | 952 |
boolean semicolon = type == SEMICOLON; |
16147 | 953 |
endOfLine(); |
16153 | 954 |
if (semicolon) { |
17233 | 955 |
lc.getCurrentBlock().setFinish(finish); |
16153 | 956 |
} |
16147 | 957 |
} |
958 |
||
959 |
return vars; |
|
960 |
} |
|
961 |
||
962 |
/** |
|
963 |
* EmptyStatement : |
|
964 |
* ; |
|
965 |
* |
|
966 |
* See 12.3 |
|
967 |
* |
|
968 |
* Parse an empty statement. |
|
969 |
*/ |
|
970 |
private void emptyStatement() { |
|
16262
75513555e603
8008731: Separate configuration environment (options, error/output writer etc.) from Context
sundar
parents:
16252
diff
changeset
|
971 |
if (env._empty_statements) { |
17524
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
972 |
appendStatement(new EmptyNode(line, token, Token.descPosition(token) + Token.descLength(token))); |
16147 | 973 |
} |
974 |
||
975 |
// SEMICOLON checked in caller. |
|
976 |
next(); |
|
977 |
} |
|
978 |
||
979 |
/** |
|
980 |
* ExpressionStatement : |
|
981 |
* Expression ; // [lookahead ~( or function )] |
|
982 |
* |
|
983 |
* See 12.4 |
|
984 |
* |
|
985 |
* Parse an expression used in a statement block. |
|
986 |
*/ |
|
987 |
private void expressionStatement() { |
|
988 |
// Lookahead checked in caller. |
|
17524
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
989 |
final int expressionLine = line; |
16147 | 990 |
final long expressionToken = token; |
991 |
||
992 |
// Get expression and add as statement. |
|
993 |
final Node expression = expression(); |
|
994 |
||
995 |
ExecuteNode executeNode = null; |
|
996 |
if (expression != null) { |
|
17524
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
997 |
executeNode = new ExecuteNode(expressionLine, expressionToken, finish, expression); |
17233 | 998 |
appendStatement(executeNode); |
16147 | 999 |
} else { |
1000 |
expect(null); |
|
1001 |
} |
|
1002 |
||
1003 |
endOfLine(); |
|
1004 |
||
1005 |
if (executeNode != null) { |
|
1006 |
executeNode.setFinish(finish); |
|
17233 | 1007 |
lc.getCurrentBlock().setFinish(finish); |
16147 | 1008 |
} |
1009 |
} |
|
1010 |
||
1011 |
/** |
|
1012 |
* IfStatement : |
|
1013 |
* if ( Expression ) Statement else Statement |
|
1014 |
* if ( Expression ) Statement |
|
1015 |
* |
|
1016 |
* See 12.5 |
|
1017 |
* |
|
1018 |
* Parse an IF statement. |
|
1019 |
*/ |
|
1020 |
private void ifStatement() { |
|
1021 |
// Capture IF token. |
|
17524
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
1022 |
final int ifLine = line; |
16147 | 1023 |
final long ifToken = token; |
1024 |
// IF tested in caller. |
|
1025 |
next(); |
|
1026 |
||
1027 |
expect(LPAREN); |
|
1028 |
final Node test = expression(); |
|
1029 |
expect(RPAREN); |
|
1030 |
final Block pass = getStatement(); |
|
1031 |
||
1032 |
Block fail = null; |
|
1033 |
if (type == ELSE) { |
|
1034 |
next(); |
|
1035 |
fail = getStatement(); |
|
1036 |
} |
|
1037 |
||
17524
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
1038 |
appendStatement(new IfNode(ifLine, ifToken, fail != null ? fail.getFinish() : pass.getFinish(), test, pass, fail)); |
16147 | 1039 |
} |
1040 |
||
1041 |
/** |
|
1042 |
* ... IterationStatement: |
|
1043 |
* ... |
|
1044 |
* for ( Expression[NoIn]?; Expression? ; Expression? ) Statement |
|
1045 |
* for ( var VariableDeclarationList[NoIn]; Expression? ; Expression? ) Statement |
|
1046 |
* for ( LeftHandSideExpression in Expression ) Statement |
|
1047 |
* for ( var VariableDeclaration[NoIn] in Expression ) Statement |
|
1048 |
* |
|
1049 |
* See 12.6 |
|
1050 |
* |
|
1051 |
* Parse a FOR statement. |
|
1052 |
*/ |
|
1053 |
private void forStatement() { |
|
1054 |
// Create FOR node, capturing FOR token. |
|
17524
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
1055 |
ForNode forNode = new ForNode(line, token, Token.descPosition(token), null, null, null, null, ForNode.IS_FOR); |
16147 | 1056 |
|
1057 |
// Set up new block for scope of vars. Captures first token. |
|
17233 | 1058 |
Block outer = newBlock(); |
1059 |
lc.push(forNode); |
|
16147 | 1060 |
|
1061 |
try { |
|
1062 |
// FOR tested in caller. |
|
1063 |
next(); |
|
1064 |
||
1065 |
// Nashorn extension: for each expression. |
|
1066 |
// iterate property values rather than property names. |
|
16262
75513555e603
8008731: Separate configuration environment (options, error/output writer etc.) from Context
sundar
parents:
16252
diff
changeset
|
1067 |
if (!env._no_syntax_extensions && type == IDENT && "each".equals(getValue())) { |
17233 | 1068 |
forNode = forNode.setIsForEach(lc); |
16147 | 1069 |
next(); |
1070 |
} |
|
1071 |
||
1072 |
expect(LPAREN); |
|
1073 |
||
17233 | 1074 |
List<VarNode> vars = null; |
1075 |
||
1076 |
switch (type) { |
|
1077 |
case VAR: |
|
1078 |
// Var statements captured in for outer block. |
|
1079 |
vars = variableStatement(false); |
|
1080 |
break; |
|
1081 |
case SEMICOLON: |
|
1082 |
break; |
|
1083 |
default: |
|
1084 |
final Node expression = expression(unaryExpression(), COMMARIGHT.getPrecedence(), true); |
|
1085 |
forNode = forNode.setInit(lc, expression); |
|
1086 |
break; |
|
1087 |
} |
|
1088 |
||
1089 |
switch (type) { |
|
1090 |
case SEMICOLON: |
|
1091 |
// for (init; test; modify) |
|
1092 |
expect(SEMICOLON); |
|
1093 |
if (type != SEMICOLON) { |
|
1094 |
forNode = forNode.setTest(lc, expression()); |
|
1095 |
} |
|
1096 |
expect(SEMICOLON); |
|
1097 |
if (type != RPAREN) { |
|
1098 |
forNode = forNode.setModify(lc, expression()); |
|
1099 |
} |
|
1100 |
break; |
|
1101 |
||
1102 |
case IN: |
|
1103 |
forNode = forNode.setIsForIn(lc); |
|
1104 |
if (vars != null) { |
|
1105 |
// for (var i in obj) |
|
1106 |
if (vars.size() == 1) { |
|
1107 |
forNode = forNode.setInit(lc, new IdentNode(vars.get(0).getName())); |
|
1108 |
} else { |
|
1109 |
// for (var i, j in obj) is invalid |
|
1110 |
throw error(AbstractParser.message("many.vars.in.for.in.loop"), vars.get(1).getToken()); |
|
1111 |
} |
|
1112 |
||
1113 |
} else { |
|
1114 |
// for (expr in obj) |
|
1115 |
final Node init = forNode.getInit(); |
|
1116 |
assert init != null : "for..in init expression can not be null here"; |
|
1117 |
||
1118 |
// check if initial expression is a valid L-value |
|
1119 |
if (!(init instanceof AccessNode || |
|
1120 |
init instanceof IndexNode || |
|
1121 |
init instanceof IdentNode)) { |
|
1122 |
throw error(AbstractParser.message("not.lvalue.for.in.loop"), init.getToken()); |
|
1123 |
} |
|
1124 |
||
1125 |
if (init instanceof IdentNode) { |
|
1126 |
if (!checkIdentLValue((IdentNode)init)) { |
|
1127 |
throw error(AbstractParser.message("not.lvalue.for.in.loop"), init.getToken()); |
|
1128 |
} |
|
1129 |
verifyStrictIdent((IdentNode)init, "for-in iterator"); |
|
1130 |
} |
|
1131 |
} |
|
1132 |
||
1133 |
next(); |
|
1134 |
||
1135 |
// Get the collection expression. |
|
1136 |
forNode = forNode.setModify(lc, expression()); |
|
1137 |
break; |
|
1138 |
||
1139 |
default: |
|
1140 |
expect(SEMICOLON); |
|
1141 |
break; |
|
1142 |
} |
|
16147 | 1143 |
|
1144 |
expect(RPAREN); |
|
1145 |
||
1146 |
// Set the for body. |
|
1147 |
final Block body = getStatement(); |
|
17233 | 1148 |
forNode = forNode.setBody(lc, body); |
16147 | 1149 |
forNode.setFinish(body.getFinish()); |
1150 |
outer.setFinish(body.getFinish()); |
|
1151 |
||
17233 | 1152 |
appendStatement(forNode); |
16147 | 1153 |
} finally { |
17233 | 1154 |
lc.pop(forNode); |
1155 |
outer = restoreBlock(outer); |
|
16147 | 1156 |
} |
1157 |
||
17524
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
1158 |
appendStatement(new ExecuteNode(outer.getLineNumber(), outer.getToken(), outer.getFinish(), outer)); |
16147 | 1159 |
} |
1160 |
||
1161 |
/** |
|
1162 |
* ... IterationStatement : |
|
1163 |
* ... |
|
1164 |
* Expression[NoIn]?; Expression? ; Expression? |
|
1165 |
* var VariableDeclarationList[NoIn]; Expression? ; Expression? |
|
1166 |
* LeftHandSideExpression in Expression |
|
1167 |
* var VariableDeclaration[NoIn] in Expression |
|
1168 |
* |
|
1169 |
* See 12.6 |
|
1170 |
* |
|
1171 |
* Parse the control section of a FOR statement. Also used for |
|
1172 |
* comprehensions. |
|
1173 |
* @param forNode Owning FOR. |
|
1174 |
*/ |
|
17233 | 1175 |
|
16147 | 1176 |
|
1177 |
/** |
|
1178 |
* ...IterationStatement : |
|
1179 |
* ... |
|
1180 |
* while ( Expression ) Statement |
|
1181 |
* ... |
|
1182 |
* |
|
1183 |
* See 12.6 |
|
1184 |
* |
|
1185 |
* Parse while statement. |
|
1186 |
*/ |
|
1187 |
private void whileStatement() { |
|
1188 |
// Capture WHILE token. |
|
17524
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
1189 |
final int whileLine = line; |
16147 | 1190 |
final long whileToken = token; |
1191 |
// WHILE tested in caller. |
|
1192 |
next(); |
|
1193 |
||
1194 |
// Construct WHILE node. |
|
17524
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
1195 |
WhileNode whileNode = new WhileNode(whileLine, whileToken, Token.descPosition(whileToken), false); |
17233 | 1196 |
lc.push(whileNode); |
16147 | 1197 |
|
1198 |
try { |
|
1199 |
expect(LPAREN); |
|
17233 | 1200 |
whileNode = whileNode.setTest(lc, expression()); |
16147 | 1201 |
expect(RPAREN); |
17233 | 1202 |
whileNode = whileNode.setBody(lc, getStatement()); |
1203 |
appendStatement(whileNode); |
|
16147 | 1204 |
} finally { |
17233 | 1205 |
lc.pop(whileNode); |
16147 | 1206 |
} |
1207 |
} |
|
1208 |
||
1209 |
/** |
|
1210 |
* ...IterationStatement : |
|
1211 |
* ... |
|
1212 |
* do Statement while( Expression ) ; |
|
1213 |
* ... |
|
1214 |
* |
|
1215 |
* See 12.6 |
|
1216 |
* |
|
1217 |
* Parse DO WHILE statement. |
|
1218 |
*/ |
|
1219 |
private void doStatement() { |
|
1220 |
// Capture DO token. |
|
17524
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
1221 |
final int doLine = line; |
16147 | 1222 |
final long doToken = token; |
1223 |
// DO tested in the caller. |
|
1224 |
next(); |
|
1225 |
||
17524
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
1226 |
WhileNode doWhileNode = new WhileNode(doLine, doToken, Token.descPosition(doToken), true); |
17233 | 1227 |
lc.push(doWhileNode); |
16147 | 1228 |
|
1229 |
try { |
|
1230 |
// Get DO body. |
|
17233 | 1231 |
doWhileNode = doWhileNode.setBody(lc, getStatement()); |
16147 | 1232 |
|
1233 |
expect(WHILE); |
|
1234 |
expect(LPAREN); |
|
17233 | 1235 |
doWhileNode = doWhileNode.setTest(lc, expression()); |
16147 | 1236 |
expect(RPAREN); |
1237 |
||
1238 |
if (type == SEMICOLON) { |
|
1239 |
endOfLine(); |
|
1240 |
} |
|
1241 |
doWhileNode.setFinish(finish); |
|
17233 | 1242 |
appendStatement(doWhileNode); |
16147 | 1243 |
} finally { |
17233 | 1244 |
lc.pop(doWhileNode); |
16147 | 1245 |
} |
1246 |
} |
|
1247 |
||
1248 |
/** |
|
1249 |
* ContinueStatement : |
|
1250 |
* continue Identifier? ; // [no LineTerminator here] |
|
1251 |
* |
|
1252 |
* See 12.7 |
|
1253 |
* |
|
1254 |
* Parse CONTINUE statement. |
|
1255 |
*/ |
|
1256 |
private void continueStatement() { |
|
1257 |
// Capture CONTINUE token. |
|
17524
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
1258 |
final int continueLine = line; |
16147 | 1259 |
final long continueToken = token; |
1260 |
// CONTINUE tested in caller. |
|
1261 |
nextOrEOL(); |
|
1262 |
||
1263 |
LabelNode labelNode = null; |
|
1264 |
||
1265 |
// SEMICOLON or label. |
|
1266 |
switch (type) { |
|
1267 |
case RBRACE: |
|
1268 |
case SEMICOLON: |
|
1269 |
case EOL: |
|
1270 |
break; |
|
1271 |
||
1272 |
default: |
|
1273 |
final IdentNode ident = getIdent(); |
|
17233 | 1274 |
labelNode = lc.findLabel(ident.getName()); |
16147 | 1275 |
|
1276 |
if (labelNode == null) { |
|
17233 | 1277 |
throw error(AbstractParser.message("undefined.label", ident.getName()), ident.getToken()); |
16147 | 1278 |
} |
1279 |
||
1280 |
break; |
|
1281 |
} |
|
1282 |
||
17233 | 1283 |
final IdentNode label = labelNode == null ? null : labelNode.getLabel(); |
1284 |
final LoopNode targetNode = lc.getContinueTo(label); |
|
16147 | 1285 |
|
1286 |
if (targetNode == null) { |
|
17233 | 1287 |
throw error(AbstractParser.message("illegal.continue.stmt"), continueToken); |
16147 | 1288 |
} |
1289 |
||
1290 |
endOfLine(); |
|
1291 |
||
1292 |
// Construct and add CONTINUE node. |
|
17524
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
1293 |
appendStatement(new ContinueNode(continueLine, continueToken, finish, label == null ? null : new IdentNode(label))); |
16147 | 1294 |
} |
1295 |
||
1296 |
/** |
|
1297 |
* BreakStatement : |
|
1298 |
* break Identifier? ; // [no LineTerminator here] |
|
1299 |
* |
|
1300 |
* See 12.8 |
|
1301 |
* |
|
1302 |
*/ |
|
1303 |
private void breakStatement() { |
|
1304 |
// Capture BREAK token. |
|
17524
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
1305 |
final int breakLine = line; |
16147 | 1306 |
final long breakToken = token; |
1307 |
// BREAK tested in caller. |
|
1308 |
nextOrEOL(); |
|
1309 |
||
1310 |
LabelNode labelNode = null; |
|
1311 |
||
1312 |
// SEMICOLON or label. |
|
1313 |
switch (type) { |
|
1314 |
case RBRACE: |
|
1315 |
case SEMICOLON: |
|
1316 |
case EOL: |
|
1317 |
break; |
|
1318 |
||
1319 |
default: |
|
1320 |
final IdentNode ident = getIdent(); |
|
17233 | 1321 |
labelNode = lc.findLabel(ident.getName()); |
16147 | 1322 |
|
1323 |
if (labelNode == null) { |
|
17233 | 1324 |
throw error(AbstractParser.message("undefined.label", ident.getName()), ident.getToken()); |
16147 | 1325 |
} |
1326 |
||
1327 |
break; |
|
1328 |
} |
|
1329 |
||
17233 | 1330 |
//either an explicit label - then get its node or just a "break" - get first breakable |
1331 |
//targetNode is what we are breaking out from. |
|
1332 |
final IdentNode label = labelNode == null ? null : labelNode.getLabel(); |
|
1333 |
final BreakableNode targetNode = lc.getBreakable(label); |
|
16147 | 1334 |
if (targetNode == null) { |
17233 | 1335 |
throw error(AbstractParser.message("illegal.break.stmt"), breakToken); |
16147 | 1336 |
} |
1337 |
||
1338 |
endOfLine(); |
|
1339 |
||
1340 |
// Construct and add BREAK node. |
|
17524
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
1341 |
appendStatement(new BreakNode(breakLine, breakToken, finish, label == null ? null : new IdentNode(label))); |
16147 | 1342 |
} |
1343 |
||
1344 |
/** |
|
1345 |
* ReturnStatement : |
|
1346 |
* return Expression? ; // [no LineTerminator here] |
|
1347 |
* |
|
1348 |
* See 12.9 |
|
1349 |
* |
|
1350 |
* Parse RETURN statement. |
|
1351 |
*/ |
|
1352 |
private void returnStatement() { |
|
1353 |
// check for return outside function |
|
17233 | 1354 |
if (lc.getCurrentFunction().getKind() == FunctionNode.Kind.SCRIPT) { |
1355 |
throw error(AbstractParser.message("invalid.return")); |
|
16147 | 1356 |
} |
1357 |
||
1358 |
// Capture RETURN token. |
|
17524
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
1359 |
final int returnLine = line; |
16147 | 1360 |
final long returnToken = token; |
1361 |
// RETURN tested in caller. |
|
1362 |
nextOrEOL(); |
|
1363 |
||
1364 |
Node expression = null; |
|
1365 |
||
1366 |
// SEMICOLON or expression. |
|
1367 |
switch (type) { |
|
1368 |
case RBRACE: |
|
1369 |
case SEMICOLON: |
|
1370 |
case EOL: |
|
1371 |
break; |
|
1372 |
||
1373 |
default: |
|
1374 |
expression = expression(); |
|
1375 |
break; |
|
1376 |
} |
|
1377 |
||
1378 |
endOfLine(); |
|
1379 |
||
1380 |
// Construct and add RETURN node. |
|
17524
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
1381 |
appendStatement(new ReturnNode(returnLine, returnToken, finish, expression)); |
16147 | 1382 |
} |
1383 |
||
1384 |
/** |
|
1385 |
* YieldStatement : |
|
1386 |
* yield Expression? ; // [no LineTerminator here] |
|
1387 |
* |
|
1388 |
* JavaScript 1.8 |
|
1389 |
* |
|
1390 |
* Parse YIELD statement. |
|
1391 |
*/ |
|
1392 |
private void yieldStatement() { |
|
1393 |
// Capture YIELD token. |
|
17524
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
1394 |
final int yieldLine = line; |
16147 | 1395 |
final long yieldToken = token; |
1396 |
// YIELD tested in caller. |
|
1397 |
nextOrEOL(); |
|
1398 |
||
1399 |
Node expression = null; |
|
1400 |
||
1401 |
// SEMICOLON or expression. |
|
1402 |
switch (type) { |
|
1403 |
case RBRACE: |
|
1404 |
case SEMICOLON: |
|
1405 |
case EOL: |
|
1406 |
break; |
|
1407 |
||
1408 |
default: |
|
1409 |
expression = expression(); |
|
1410 |
break; |
|
1411 |
} |
|
1412 |
||
1413 |
endOfLine(); |
|
1414 |
||
1415 |
// Construct and add YIELD node. |
|
17524
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
1416 |
appendStatement(new ReturnNode(yieldLine, yieldToken, finish, expression)); |
16147 | 1417 |
} |
1418 |
||
1419 |
/** |
|
1420 |
* WithStatement : |
|
1421 |
* with ( Expression ) Statement |
|
1422 |
* |
|
1423 |
* See 12.10 |
|
1424 |
* |
|
1425 |
* Parse WITH statement. |
|
1426 |
*/ |
|
1427 |
private void withStatement() { |
|
1428 |
// Capture WITH token. |
|
17524
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
1429 |
final int withLine = line; |
16147 | 1430 |
final long withToken = token; |
1431 |
// WITH tested in caller. |
|
1432 |
next(); |
|
1433 |
||
1434 |
// ECMA 12.10.1 strict mode restrictions |
|
1435 |
if (isStrictMode) { |
|
17233 | 1436 |
throw error(AbstractParser.message("strict.no.with"), withToken); |
16147 | 1437 |
} |
1438 |
||
1439 |
// Get WITH expression. |
|
17524
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
1440 |
WithNode withNode = new WithNode(withLine, withToken, finish); |
16147 | 1441 |
|
1442 |
try { |
|
17233 | 1443 |
lc.push(withNode); |
16147 | 1444 |
expect(LPAREN); |
17233 | 1445 |
withNode = withNode.setExpression(lc, expression()); |
16147 | 1446 |
expect(RPAREN); |
17233 | 1447 |
withNode = withNode.setBody(lc, getStatement()); |
16147 | 1448 |
} finally { |
17233 | 1449 |
lc.pop(withNode); |
16147 | 1450 |
} |
1451 |
||
17233 | 1452 |
appendStatement(withNode); |
16147 | 1453 |
} |
1454 |
||
1455 |
/** |
|
1456 |
* SwitchStatement : |
|
1457 |
* switch ( Expression ) CaseBlock |
|
1458 |
* |
|
1459 |
* CaseBlock : |
|
1460 |
* { CaseClauses? } |
|
1461 |
* { CaseClauses? DefaultClause CaseClauses } |
|
1462 |
* |
|
1463 |
* CaseClauses : |
|
1464 |
* CaseClause |
|
1465 |
* CaseClauses CaseClause |
|
1466 |
* |
|
1467 |
* CaseClause : |
|
1468 |
* case Expression : StatementList? |
|
1469 |
* |
|
1470 |
* DefaultClause : |
|
1471 |
* default : StatementList? |
|
1472 |
* |
|
1473 |
* See 12.11 |
|
1474 |
* |
|
1475 |
* Parse SWITCH statement. |
|
1476 |
*/ |
|
1477 |
private void switchStatement() { |
|
17524
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
1478 |
final int switchLine = line; |
16147 | 1479 |
final long switchToken = token; |
1480 |
// SWITCH tested in caller. |
|
1481 |
next(); |
|
1482 |
||
1483 |
// Create and add switch statement. |
|
17524
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
1484 |
SwitchNode switchNode = new SwitchNode(switchLine, switchToken, Token.descPosition(switchToken), null, new ArrayList<CaseNode>(), null); |
17233 | 1485 |
lc.push(switchNode); |
16147 | 1486 |
|
1487 |
try { |
|
1488 |
expect(LPAREN); |
|
17233 | 1489 |
switchNode = switchNode.setExpression(lc, expression()); |
16147 | 1490 |
expect(RPAREN); |
1491 |
||
1492 |
expect(LBRACE); |
|
1493 |
||
1494 |
// Prepare to accumulate cases. |
|
1495 |
final List<CaseNode> cases = new ArrayList<>(); |
|
1496 |
CaseNode defaultCase = null; |
|
1497 |
||
1498 |
while (type != RBRACE) { |
|
1499 |
// Prepare for next case. |
|
1500 |
Node caseExpression = null; |
|
1501 |
final long caseToken = token; |
|
1502 |
||
1503 |
switch (type) { |
|
1504 |
case CASE: |
|
1505 |
next(); |
|
1506 |
caseExpression = expression(); |
|
1507 |
break; |
|
1508 |
||
1509 |
case DEFAULT: |
|
1510 |
if (defaultCase != null) { |
|
17233 | 1511 |
throw error(AbstractParser.message("duplicate.default.in.switch")); |
16147 | 1512 |
} |
1513 |
next(); |
|
1514 |
break; |
|
1515 |
||
1516 |
default: |
|
1517 |
// Force an error. |
|
1518 |
expect(CASE); |
|
1519 |
break; |
|
1520 |
} |
|
1521 |
||
1522 |
expect(COLON); |
|
1523 |
||
1524 |
// Get CASE body. |
|
1525 |
final Block statements = getBlock(false); |
|
17523
cb4a7c901e0d
8013913: Removed Source field from all nodes except FunctionNode in order to save footprint
lagergren
parents:
17518
diff
changeset
|
1526 |
final CaseNode caseNode = new CaseNode(caseToken, finish, caseExpression, statements); |
16153 | 1527 |
statements.setFinish(finish); |
16147 | 1528 |
|
1529 |
if (caseExpression == null) { |
|
1530 |
defaultCase = caseNode; |
|
1531 |
} |
|
1532 |
||
1533 |
cases.add(caseNode); |
|
1534 |
} |
|
1535 |
||
17233 | 1536 |
switchNode = switchNode.setCases(lc, cases, defaultCase); |
16147 | 1537 |
next(); |
1538 |
switchNode.setFinish(finish); |
|
1539 |
||
17233 | 1540 |
appendStatement(switchNode); |
16147 | 1541 |
} finally { |
17233 | 1542 |
lc.pop(switchNode); |
16147 | 1543 |
} |
1544 |
} |
|
1545 |
||
1546 |
/** |
|
1547 |
* LabelledStatement : |
|
1548 |
* Identifier : Statement |
|
1549 |
* |
|
1550 |
* See 12.12 |
|
1551 |
* |
|
1552 |
* Parse label statement. |
|
1553 |
*/ |
|
1554 |
private void labelStatement() { |
|
1555 |
// Capture label token. |
|
1556 |
final long labelToken = token; |
|
1557 |
// Get label ident. |
|
1558 |
final IdentNode ident = getIdent(); |
|
1559 |
||
1560 |
expect(COLON); |
|
1561 |
||
17233 | 1562 |
if (lc.findLabel(ident.getName()) != null) { |
1563 |
throw error(AbstractParser.message("duplicate.label", ident.getName()), labelToken); |
|
16147 | 1564 |
} |
1565 |
||
17524
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
1566 |
LabelNode labelNode = new LabelNode(line, labelToken, finish, ident, null); |
16147 | 1567 |
try { |
17233 | 1568 |
lc.push(labelNode); |
1569 |
labelNode = labelNode.setBody(lc, getStatement()); |
|
16147 | 1570 |
labelNode.setFinish(finish); |
17233 | 1571 |
appendStatement(labelNode); |
16147 | 1572 |
} finally { |
17233 | 1573 |
assert lc.peek() instanceof LabelNode; |
1574 |
lc.pop(labelNode); |
|
16147 | 1575 |
} |
1576 |
} |
|
1577 |
||
1578 |
/** |
|
1579 |
* ThrowStatement : |
|
1580 |
* throw Expression ; // [no LineTerminator here] |
|
1581 |
* |
|
1582 |
* See 12.13 |
|
1583 |
* |
|
1584 |
* Parse throw statement. |
|
1585 |
*/ |
|
1586 |
private void throwStatement() { |
|
1587 |
// Capture THROW token. |
|
17524
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
1588 |
final int throwLine = line; |
16147 | 1589 |
final long throwToken = token; |
1590 |
// THROW tested in caller. |
|
1591 |
nextOrEOL(); |
|
1592 |
||
1593 |
Node expression = null; |
|
1594 |
||
1595 |
// SEMICOLON or expression. |
|
1596 |
switch (type) { |
|
1597 |
case RBRACE: |
|
1598 |
case SEMICOLON: |
|
1599 |
case EOL: |
|
1600 |
break; |
|
1601 |
||
1602 |
default: |
|
1603 |
expression = expression(); |
|
1604 |
break; |
|
1605 |
} |
|
1606 |
||
1607 |
if (expression == null) { |
|
17233 | 1608 |
throw error(AbstractParser.message("expected.operand", type.getNameOrType())); |
16147 | 1609 |
} |
1610 |
||
1611 |
endOfLine(); |
|
1612 |
||
17745
86e5a15b3b20
8014426: Original exception no longer thrown away when a finally rethrows
lagergren
parents:
17524
diff
changeset
|
1613 |
appendStatement(new ThrowNode(throwLine, throwToken, finish, expression, 0)); |
16147 | 1614 |
} |
1615 |
||
1616 |
/** |
|
1617 |
* TryStatement : |
|
1618 |
* try Block Catch |
|
1619 |
* try Block Finally |
|
1620 |
* try Block Catch Finally |
|
1621 |
* |
|
1622 |
* Catch : |
|
1623 |
* catch( Identifier if Expression ) Block |
|
1624 |
* catch( Identifier ) Block |
|
1625 |
* |
|
1626 |
* Finally : |
|
1627 |
* finally Block |
|
1628 |
* |
|
1629 |
* See 12.14 |
|
1630 |
* |
|
1631 |
* Parse TRY statement. |
|
1632 |
*/ |
|
1633 |
private void tryStatement() { |
|
1634 |
// Capture TRY token. |
|
17524
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
1635 |
final int tryLine = line; |
16147 | 1636 |
final long tryToken = token; |
1637 |
// TRY tested in caller. |
|
1638 |
next(); |
|
1639 |
||
16239
fbae49f786c6
8008215: break in catch clause causes java.lang.VerifyError: Inconsistent stackmap
hannesw
parents:
16237
diff
changeset
|
1640 |
// Container block needed to act as target for labeled break statements |
17233 | 1641 |
Block outer = newBlock(); |
16239
fbae49f786c6
8008215: break in catch clause causes java.lang.VerifyError: Inconsistent stackmap
hannesw
parents:
16237
diff
changeset
|
1642 |
|
16147 | 1643 |
// Create try. |
1644 |
||
1645 |
try { |
|
17233 | 1646 |
final Block tryBody = getBlock(true); |
16147 | 1647 |
final List<Block> catchBlocks = new ArrayList<>(); |
1648 |
||
1649 |
while (type == CATCH) { |
|
17524
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
1650 |
final int catchLine = line; |
16147 | 1651 |
final long catchToken = token; |
1652 |
next(); |
|
1653 |
expect(LPAREN); |
|
1654 |
final IdentNode exception = getIdent(); |
|
1655 |
||
1656 |
// ECMA 12.4.1 strict mode restrictions |
|
1657 |
verifyStrictIdent(exception, "catch argument"); |
|
1658 |
||
1659 |
// Check for conditional catch. |
|
1660 |
Node ifExpression = null; |
|
1661 |
if (type == IF) { |
|
1662 |
next(); |
|
1663 |
// Get the exception condition. |
|
1664 |
ifExpression = expression(); |
|
1665 |
} |
|
1666 |
||
1667 |
expect(RPAREN); |
|
1668 |
||
17233 | 1669 |
Block catchBlock = newBlock(); |
16147 | 1670 |
try { |
1671 |
// Get CATCH body. |
|
1672 |
final Block catchBody = getBlock(true); |
|
17745
86e5a15b3b20
8014426: Original exception no longer thrown away when a finally rethrows
lagergren
parents:
17524
diff
changeset
|
1673 |
final CatchNode catchNode = new CatchNode(catchLine, catchToken, finish, exception, ifExpression, catchBody, 0); |
17233 | 1674 |
appendStatement(catchNode); |
1675 |
} finally { |
|
1676 |
catchBlock = restoreBlock(catchBlock); |
|
16147 | 1677 |
catchBlocks.add(catchBlock); |
1678 |
} |
|
1679 |
||
1680 |
// If unconditional catch then should to be the end. |
|
1681 |
if (ifExpression == null) { |
|
1682 |
break; |
|
1683 |
} |
|
1684 |
} |
|
1685 |
||
1686 |
// Prepare to capture finally statement. |
|
1687 |
Block finallyStatements = null; |
|
1688 |
||
1689 |
if (type == FINALLY) { |
|
1690 |
next(); |
|
1691 |
finallyStatements = getBlock(true); |
|
1692 |
} |
|
1693 |
||
1694 |
// Need at least one catch or a finally. |
|
1695 |
if (catchBlocks.isEmpty() && finallyStatements == null) { |
|
17233 | 1696 |
throw error(AbstractParser.message("missing.catch.or.finally"), tryToken); |
16147 | 1697 |
} |
1698 |
||
17524
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
1699 |
final TryNode tryNode = new TryNode(tryLine, tryToken, Token.descPosition(tryToken), tryBody, catchBlocks, finallyStatements); |
17233 | 1700 |
// Add try. |
1701 |
assert lc.peek() == outer; |
|
1702 |
appendStatement(tryNode); |
|
1703 |
||
16147 | 1704 |
tryNode.setFinish(finish); |
16239
fbae49f786c6
8008215: break in catch clause causes java.lang.VerifyError: Inconsistent stackmap
hannesw
parents:
16237
diff
changeset
|
1705 |
outer.setFinish(finish); |
16147 | 1706 |
|
1707 |
} finally { |
|
17233 | 1708 |
outer = restoreBlock(outer); |
16147 | 1709 |
} |
16239
fbae49f786c6
8008215: break in catch clause causes java.lang.VerifyError: Inconsistent stackmap
hannesw
parents:
16237
diff
changeset
|
1710 |
|
17524
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
1711 |
appendStatement(new ExecuteNode(outer.getLineNumber(), outer.getToken(), outer.getFinish(), outer)); |
16147 | 1712 |
} |
1713 |
||
1714 |
/** |
|
1715 |
* DebuggerStatement : |
|
1716 |
* debugger ; |
|
1717 |
* |
|
1718 |
* See 12.15 |
|
1719 |
* |
|
1720 |
* Parse debugger statement. |
|
1721 |
*/ |
|
1722 |
private void debuggerStatement() { |
|
1723 |
// Capture DEBUGGER token. |
|
17524
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
1724 |
final int debuggerLine = line; |
16147 | 1725 |
final long debuggerToken = token; |
1726 |
// DEBUGGER tested in caller. |
|
1727 |
next(); |
|
1728 |
endOfLine(); |
|
17524
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
1729 |
appendStatement(new ExecuteNode(debuggerLine, debuggerToken, finish, new RuntimeNode(debuggerToken, finish, RuntimeNode.Request.DEBUGGER, new ArrayList<Node>()))); |
16147 | 1730 |
} |
1731 |
||
1732 |
/** |
|
1733 |
* PrimaryExpression : |
|
1734 |
* this |
|
1735 |
* Identifier |
|
1736 |
* Literal |
|
1737 |
* ArrayLiteral |
|
1738 |
* ObjectLiteral |
|
1739 |
* ( Expression ) |
|
1740 |
* |
|
1741 |
* See 11.1 |
|
1742 |
* |
|
1743 |
* Parse primary expression. |
|
1744 |
* @return Expression node. |
|
1745 |
*/ |
|
1746 |
@SuppressWarnings("fallthrough") |
|
1747 |
private Node primaryExpression() { |
|
1748 |
// Capture first token. |
|
17524
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
1749 |
final int primaryLine = line; |
16147 | 1750 |
final long primaryToken = token; |
1751 |
||
1752 |
switch (type) { |
|
1753 |
case THIS: |
|
1754 |
final String name = type.getName(); |
|
1755 |
next(); |
|
17523
cb4a7c901e0d
8013913: Removed Source field from all nodes except FunctionNode in order to save footprint
lagergren
parents:
17518
diff
changeset
|
1756 |
return new IdentNode(primaryToken, finish, name); |
16147 | 1757 |
case IDENT: |
1758 |
final IdentNode ident = getIdent(); |
|
1759 |
if (ident == null) { |
|
1760 |
break; |
|
1761 |
} |
|
1762 |
detectSpecialProperty(ident); |
|
1763 |
return ident; |
|
1764 |
case OCTAL: |
|
1765 |
if (isStrictMode) { |
|
17233 | 1766 |
throw error(AbstractParser.message("strict.no.octal"), token); |
16147 | 1767 |
} |
1768 |
case STRING: |
|
1769 |
case ESCSTRING: |
|
1770 |
case DECIMAL: |
|
1771 |
case HEXADECIMAL: |
|
1772 |
case FLOATING: |
|
1773 |
case REGEX: |
|
1774 |
case XML: |
|
1775 |
return getLiteral(); |
|
16211 | 1776 |
case EXECSTRING: |
17524
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
1777 |
return execString(primaryLine, primaryToken); |
16147 | 1778 |
case FALSE: |
1779 |
next(); |
|
17523
cb4a7c901e0d
8013913: Removed Source field from all nodes except FunctionNode in order to save footprint
lagergren
parents:
17518
diff
changeset
|
1780 |
return LiteralNode.newInstance(primaryToken, finish, false); |
16147 | 1781 |
case TRUE: |
1782 |
next(); |
|
17523
cb4a7c901e0d
8013913: Removed Source field from all nodes except FunctionNode in order to save footprint
lagergren
parents:
17518
diff
changeset
|
1783 |
return LiteralNode.newInstance(primaryToken, finish, true); |
16147 | 1784 |
case NULL: |
1785 |
next(); |
|
17523
cb4a7c901e0d
8013913: Removed Source field from all nodes except FunctionNode in order to save footprint
lagergren
parents:
17518
diff
changeset
|
1786 |
return LiteralNode.newInstance(primaryToken, finish); |
16147 | 1787 |
case LBRACKET: |
1788 |
return arrayLiteral(); |
|
1789 |
case LBRACE: |
|
1790 |
return objectLiteral(); |
|
1791 |
case LPAREN: |
|
1792 |
next(); |
|
1793 |
||
1794 |
final Node expression = expression(); |
|
1795 |
||
1796 |
expect(RPAREN); |
|
1797 |
||
1798 |
return expression; |
|
1799 |
||
1800 |
default: |
|
1801 |
// In this context some operator tokens mark the start of a literal. |
|
1802 |
if (lexer.scanLiteral(primaryToken, type)) { |
|
1803 |
next(); |
|
1804 |
return getLiteral(); |
|
1805 |
} |
|
1806 |
if (isNonStrictModeIdent()) { |
|
1807 |
return getIdent(); |
|
1808 |
} |
|
1809 |
break; |
|
1810 |
} |
|
1811 |
||
1812 |
return null; |
|
1813 |
} |
|
1814 |
||
16211 | 1815 |
/** |
1816 |
* Convert execString to a call to $EXEC. |
|
1817 |
* |
|
1818 |
* @param primaryToken Original string token. |
|
1819 |
* @return callNode to $EXEC. |
|
1820 |
*/ |
|
17524
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
1821 |
Node execString(final int primaryLine, final long primaryToken) { |
16211 | 1822 |
// Synthesize an ident to call $EXEC. |
17523
cb4a7c901e0d
8013913: Removed Source field from all nodes except FunctionNode in order to save footprint
lagergren
parents:
17518
diff
changeset
|
1823 |
final IdentNode execIdent = new IdentNode(primaryToken, finish, ScriptingFunctions.EXEC_NAME); |
16211 | 1824 |
// Skip over EXECSTRING. |
1825 |
next(); |
|
1826 |
// Set up argument list for call. |
|
1827 |
final List<Node> arguments = new ArrayList<>(); |
|
1828 |
// Skip beginning of edit string expression. |
|
1829 |
expect(LBRACE); |
|
1830 |
// Add the following expression to arguments. |
|
1831 |
arguments.add(expression()); |
|
1832 |
// Skip ending of edit string expression. |
|
1833 |
expect(RBRACE); |
|
1834 |
||
17524
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
1835 |
return new CallNode(primaryLine, primaryToken, finish, execIdent, arguments); |
16211 | 1836 |
} |
16147 | 1837 |
|
1838 |
/** |
|
1839 |
* ArrayLiteral : |
|
1840 |
* [ Elision? ] |
|
1841 |
* [ ElementList ] |
|
1842 |
* [ ElementList , Elision? ] |
|
1843 |
* [ expression for (LeftHandExpression in expression) ( (if ( Expression ) )? ] |
|
1844 |
* |
|
1845 |
* ElementList : Elision? AssignmentExpression |
|
1846 |
* ElementList , Elision? AssignmentExpression |
|
1847 |
* |
|
1848 |
* Elision : |
|
1849 |
* , |
|
1850 |
* Elision , |
|
1851 |
* |
|
1852 |
* See 12.1.4 |
|
1853 |
* JavaScript 1.8 |
|
1854 |
* |
|
1855 |
* Parse array literal. |
|
1856 |
* @return Expression node. |
|
1857 |
*/ |
|
1858 |
private Node arrayLiteral() { |
|
1859 |
// Capture LBRACKET token. |
|
1860 |
final long arrayToken = token; |
|
1861 |
// LBRACKET tested in caller. |
|
1862 |
next(); |
|
1863 |
||
1864 |
// Prepare to accummulating elements. |
|
1865 |
final List<Node> elements = new ArrayList<>(); |
|
1866 |
// Track elisions. |
|
1867 |
boolean elision = true; |
|
1868 |
loop: |
|
1869 |
while (true) { |
|
1870 |
switch (type) { |
|
1871 |
case RBRACKET: |
|
1872 |
next(); |
|
1873 |
||
1874 |
break loop; |
|
1875 |
||
1876 |
case COMMARIGHT: |
|
1877 |
next(); |
|
1878 |
||
1879 |
// If no prior expression |
|
1880 |
if (elision) { |
|
1881 |
elements.add(null); |
|
1882 |
} |
|
1883 |
||
1884 |
elision = true; |
|
1885 |
||
1886 |
break; |
|
1887 |
||
1888 |
default: |
|
16523
af8b30edebce
8009718: Lazy execution architecture continued - ScriptFunctionData is either final or recompilable. Moved ScriptFunctionData creation logic away from runtime to compile time. Prepared for method generation/specialization. Got rid of ScriptFunctionImplTrampoline whose semantics could be done as part of the relinking anyway. Merge with the lookup package change.
lagergren
parents:
16262
diff
changeset
|
1889 |
if (!elision) { |
17233 | 1890 |
throw error(AbstractParser.message("expected.comma", type.getNameOrType())); |
16147 | 1891 |
} |
1892 |
// Add expression element. |
|
1893 |
final Node expression = assignmentExpression(false); |
|
1894 |
||
1895 |
if (expression != null) { |
|
1896 |
elements.add(expression); |
|
1897 |
} else { |
|
1898 |
expect(RBRACKET); |
|
1899 |
} |
|
1900 |
||
1901 |
elision = false; |
|
1902 |
break; |
|
1903 |
} |
|
1904 |
} |
|
1905 |
||
17523
cb4a7c901e0d
8013913: Removed Source field from all nodes except FunctionNode in order to save footprint
lagergren
parents:
17518
diff
changeset
|
1906 |
return LiteralNode.newInstance(arrayToken, finish, elements); |
16147 | 1907 |
} |
1908 |
||
1909 |
/** |
|
1910 |
* ObjectLiteral : |
|
1911 |
* { } |
|
1912 |
* { PropertyNameAndValueList } { PropertyNameAndValueList , } |
|
1913 |
* |
|
1914 |
* PropertyNameAndValueList : |
|
1915 |
* PropertyAssignment |
|
1916 |
* PropertyNameAndValueList , PropertyAssignment |
|
1917 |
* |
|
1918 |
* See 11.1.5 |
|
1919 |
* |
|
1920 |
* Parse an object literal. |
|
1921 |
* @return Expression node. |
|
1922 |
*/ |
|
1923 |
private Node objectLiteral() { |
|
1924 |
// Capture LBRACE token. |
|
1925 |
final long objectToken = token; |
|
1926 |
// LBRACE tested in caller. |
|
1927 |
next(); |
|
1928 |
||
1929 |
// Object context. |
|
1930 |
// Prepare to accumulate elements. |
|
17233 | 1931 |
// final List<Node> elements = new ArrayList<>(); |
1932 |
final Map<String, PropertyNode> map = new LinkedHashMap<>(); |
|
16147 | 1933 |
|
16523
af8b30edebce
8009718: Lazy execution architecture continued - ScriptFunctionData is either final or recompilable. Moved ScriptFunctionData creation logic away from runtime to compile time. Prepared for method generation/specialization. Got rid of ScriptFunctionImplTrampoline whose semantics could be done as part of the relinking anyway. Merge with the lookup package change.
lagergren
parents:
16262
diff
changeset
|
1934 |
// Create a block for the object literal. |
16147 | 1935 |
boolean commaSeen = true; |
1936 |
loop: |
|
1937 |
while (true) { |
|
1938 |
switch (type) { |
|
1939 |
case RBRACE: |
|
1940 |
next(); |
|
1941 |
break loop; |
|
1942 |
||
1943 |
case COMMARIGHT: |
|
1944 |
next(); |
|
1945 |
commaSeen = true; |
|
1946 |
break; |
|
1947 |
||
1948 |
default: |
|
16523
af8b30edebce
8009718: Lazy execution architecture continued - ScriptFunctionData is either final or recompilable. Moved ScriptFunctionData creation logic away from runtime to compile time. Prepared for method generation/specialization. Got rid of ScriptFunctionImplTrampoline whose semantics could be done as part of the relinking anyway. Merge with the lookup package change.
lagergren
parents:
16262
diff
changeset
|
1949 |
if (!commaSeen) { |
17233 | 1950 |
throw error(AbstractParser.message("expected.comma", type.getNameOrType())); |
1951 |
} |
|
1952 |
||
1953 |
commaSeen = false; |
|
1954 |
// Get and add the next property. |
|
1955 |
final PropertyNode property = propertyAssignment(); |
|
1956 |
final String key = property.getKeyName(); |
|
1957 |
final PropertyNode existingProperty = map.get(key); |
|
1958 |
||
1959 |
if (existingProperty == null) { |
|
1960 |
map.put(key, property); |
|
1961 |
// elements.add(property); |
|
1962 |
break; |
|
1963 |
} |
|
1964 |
||
16523
af8b30edebce
8009718: Lazy execution architecture continued - ScriptFunctionData is either final or recompilable. Moved ScriptFunctionData creation logic away from runtime to compile time. Prepared for method generation/specialization. Got rid of ScriptFunctionImplTrampoline whose semantics could be done as part of the relinking anyway. Merge with the lookup package change.
lagergren
parents:
16262
diff
changeset
|
1965 |
// ECMA section 11.1.5 Object Initialiser |
af8b30edebce
8009718: Lazy execution architecture continued - ScriptFunctionData is either final or recompilable. Moved ScriptFunctionData creation logic away from runtime to compile time. Prepared for method generation/specialization. Got rid of ScriptFunctionImplTrampoline whose semantics could be done as part of the relinking anyway. Merge with the lookup package change.
lagergren
parents:
16262
diff
changeset
|
1966 |
// point # 4 on property assignment production |
17233 | 1967 |
final Node value = property.getValue(); |
1968 |
final FunctionNode getter = property.getGetter(); |
|
1969 |
final FunctionNode setter = property.getSetter(); |
|
1970 |
||
1971 |
final Node prevValue = existingProperty.getValue(); |
|
1972 |
final FunctionNode prevGetter = existingProperty.getGetter(); |
|
1973 |
final FunctionNode prevSetter = existingProperty.getSetter(); |
|
16523
af8b30edebce
8009718: Lazy execution architecture continued - ScriptFunctionData is either final or recompilable. Moved ScriptFunctionData creation logic away from runtime to compile time. Prepared for method generation/specialization. Got rid of ScriptFunctionImplTrampoline whose semantics could be done as part of the relinking anyway. Merge with the lookup package change.
lagergren
parents:
16262
diff
changeset
|
1974 |
|
af8b30edebce
8009718: Lazy execution architecture continued - ScriptFunctionData is either final or recompilable. Moved ScriptFunctionData creation logic away from runtime to compile time. Prepared for method generation/specialization. Got rid of ScriptFunctionImplTrampoline whose semantics could be done as part of the relinking anyway. Merge with the lookup package change.
lagergren
parents:
16262
diff
changeset
|
1975 |
boolean redefinitionOk = true; |
af8b30edebce
8009718: Lazy execution architecture continued - ScriptFunctionData is either final or recompilable. Moved ScriptFunctionData creation logic away from runtime to compile time. Prepared for method generation/specialization. Got rid of ScriptFunctionImplTrampoline whose semantics could be done as part of the relinking anyway. Merge with the lookup package change.
lagergren
parents:
16262
diff
changeset
|
1976 |
// ECMA 11.1.5 strict mode restrictions |
af8b30edebce
8009718: Lazy execution architecture continued - ScriptFunctionData is either final or recompilable. Moved ScriptFunctionData creation logic away from runtime to compile time. Prepared for method generation/specialization. Got rid of ScriptFunctionImplTrampoline whose semantics could be done as part of the relinking anyway. Merge with the lookup package change.
lagergren
parents:
16262
diff
changeset
|
1977 |
if (isStrictMode) { |
af8b30edebce
8009718: Lazy execution architecture continued - ScriptFunctionData is either final or recompilable. Moved ScriptFunctionData creation logic away from runtime to compile time. Prepared for method generation/specialization. Got rid of ScriptFunctionImplTrampoline whose semantics could be done as part of the relinking anyway. Merge with the lookup package change.
lagergren
parents:
16262
diff
changeset
|
1978 |
if (value != null && prevValue != null) { |
16147 | 1979 |
redefinitionOk = false; |
1980 |
} |
|
16523
af8b30edebce
8009718: Lazy execution architecture continued - ScriptFunctionData is either final or recompilable. Moved ScriptFunctionData creation logic away from runtime to compile time. Prepared for method generation/specialization. Got rid of ScriptFunctionImplTrampoline whose semantics could be done as part of the relinking anyway. Merge with the lookup package change.
lagergren
parents:
16262
diff
changeset
|
1981 |
} |
af8b30edebce
8009718: Lazy execution architecture continued - ScriptFunctionData is either final or recompilable. Moved ScriptFunctionData creation logic away from runtime to compile time. Prepared for method generation/specialization. Got rid of ScriptFunctionImplTrampoline whose semantics could be done as part of the relinking anyway. Merge with the lookup package change.
lagergren
parents:
16262
diff
changeset
|
1982 |
|
af8b30edebce
8009718: Lazy execution architecture continued - ScriptFunctionData is either final or recompilable. Moved ScriptFunctionData creation logic away from runtime to compile time. Prepared for method generation/specialization. Got rid of ScriptFunctionImplTrampoline whose semantics could be done as part of the relinking anyway. Merge with the lookup package change.
lagergren
parents:
16262
diff
changeset
|
1983 |
final boolean isPrevAccessor = prevGetter != null || prevSetter != null; |
17233 | 1984 |
final boolean isAccessor = getter != null || setter != null; |
16523
af8b30edebce
8009718: Lazy execution architecture continued - ScriptFunctionData is either final or recompilable. Moved ScriptFunctionData creation logic away from runtime to compile time. Prepared for method generation/specialization. Got rid of ScriptFunctionImplTrampoline whose semantics could be done as part of the relinking anyway. Merge with the lookup package change.
lagergren
parents:
16262
diff
changeset
|
1985 |
|
af8b30edebce
8009718: Lazy execution architecture continued - ScriptFunctionData is either final or recompilable. Moved ScriptFunctionData creation logic away from runtime to compile time. Prepared for method generation/specialization. Got rid of ScriptFunctionImplTrampoline whose semantics could be done as part of the relinking anyway. Merge with the lookup package change.
lagergren
parents:
16262
diff
changeset
|
1986 |
// data property redefined as accessor property |
af8b30edebce
8009718: Lazy execution architecture continued - ScriptFunctionData is either final or recompilable. Moved ScriptFunctionData creation logic away from runtime to compile time. Prepared for method generation/specialization. Got rid of ScriptFunctionImplTrampoline whose semantics could be done as part of the relinking anyway. Merge with the lookup package change.
lagergren
parents:
16262
diff
changeset
|
1987 |
if (prevValue != null && isAccessor) { |
af8b30edebce
8009718: Lazy execution architecture continued - ScriptFunctionData is either final or recompilable. Moved ScriptFunctionData creation logic away from runtime to compile time. Prepared for method generation/specialization. Got rid of ScriptFunctionImplTrampoline whose semantics could be done as part of the relinking anyway. Merge with the lookup package change.
lagergren
parents:
16262
diff
changeset
|
1988 |
redefinitionOk = false; |
af8b30edebce
8009718: Lazy execution architecture continued - ScriptFunctionData is either final or recompilable. Moved ScriptFunctionData creation logic away from runtime to compile time. Prepared for method generation/specialization. Got rid of ScriptFunctionImplTrampoline whose semantics could be done as part of the relinking anyway. Merge with the lookup package change.
lagergren
parents:
16262
diff
changeset
|
1989 |
} |
af8b30edebce
8009718: Lazy execution architecture continued - ScriptFunctionData is either final or recompilable. Moved ScriptFunctionData creation logic away from runtime to compile time. Prepared for method generation/specialization. Got rid of ScriptFunctionImplTrampoline whose semantics could be done as part of the relinking anyway. Merge with the lookup package change.
lagergren
parents:
16262
diff
changeset
|
1990 |
|
af8b30edebce
8009718: Lazy execution architecture continued - ScriptFunctionData is either final or recompilable. Moved ScriptFunctionData creation logic away from runtime to compile time. Prepared for method generation/specialization. Got rid of ScriptFunctionImplTrampoline whose semantics could be done as part of the relinking anyway. Merge with the lookup package change.
lagergren
parents:
16262
diff
changeset
|
1991 |
// accessor property redefined as data |
af8b30edebce
8009718: Lazy execution architecture continued - ScriptFunctionData is either final or recompilable. Moved ScriptFunctionData creation logic away from runtime to compile time. Prepared for method generation/specialization. Got rid of ScriptFunctionImplTrampoline whose semantics could be done as part of the relinking anyway. Merge with the lookup package change.
lagergren
parents:
16262
diff
changeset
|
1992 |
if (isPrevAccessor && value != null) { |
af8b30edebce
8009718: Lazy execution architecture continued - ScriptFunctionData is either final or recompilable. Moved ScriptFunctionData creation logic away from runtime to compile time. Prepared for method generation/specialization. Got rid of ScriptFunctionImplTrampoline whose semantics could be done as part of the relinking anyway. Merge with the lookup package change.
lagergren
parents:
16262
diff
changeset
|
1993 |
redefinitionOk = false; |
af8b30edebce
8009718: Lazy execution architecture continued - ScriptFunctionData is either final or recompilable. Moved ScriptFunctionData creation logic away from runtime to compile time. Prepared for method generation/specialization. Got rid of ScriptFunctionImplTrampoline whose semantics could be done as part of the relinking anyway. Merge with the lookup package change.
lagergren
parents:
16262
diff
changeset
|
1994 |
} |
af8b30edebce
8009718: Lazy execution architecture continued - ScriptFunctionData is either final or recompilable. Moved ScriptFunctionData creation logic away from runtime to compile time. Prepared for method generation/specialization. Got rid of ScriptFunctionImplTrampoline whose semantics could be done as part of the relinking anyway. Merge with the lookup package change.
lagergren
parents:
16262
diff
changeset
|
1995 |
|
af8b30edebce
8009718: Lazy execution architecture continued - ScriptFunctionData is either final or recompilable. Moved ScriptFunctionData creation logic away from runtime to compile time. Prepared for method generation/specialization. Got rid of ScriptFunctionImplTrampoline whose semantics could be done as part of the relinking anyway. Merge with the lookup package change.
lagergren
parents:
16262
diff
changeset
|
1996 |
if (isAccessor && isPrevAccessor) { |
af8b30edebce
8009718: Lazy execution architecture continued - ScriptFunctionData is either final or recompilable. Moved ScriptFunctionData creation logic away from runtime to compile time. Prepared for method generation/specialization. Got rid of ScriptFunctionImplTrampoline whose semantics could be done as part of the relinking anyway. Merge with the lookup package change.
lagergren
parents:
16262
diff
changeset
|
1997 |
if (getter != null && prevGetter != null || |
af8b30edebce
8009718: Lazy execution architecture continued - ScriptFunctionData is either final or recompilable. Moved ScriptFunctionData creation logic away from runtime to compile time. Prepared for method generation/specialization. Got rid of ScriptFunctionImplTrampoline whose semantics could be done as part of the relinking anyway. Merge with the lookup package change.
lagergren
parents:
16262
diff
changeset
|
1998 |
setter != null && prevSetter != null) { |
af8b30edebce
8009718: Lazy execution architecture continued - ScriptFunctionData is either final or recompilable. Moved ScriptFunctionData creation logic away from runtime to compile time. Prepared for method generation/specialization. Got rid of ScriptFunctionImplTrampoline whose semantics could be done as part of the relinking anyway. Merge with the lookup package change.
lagergren
parents:
16262
diff
changeset
|
1999 |
redefinitionOk = false; |
16147 | 2000 |
} |
16523
af8b30edebce
8009718: Lazy execution architecture continued - ScriptFunctionData is either final or recompilable. Moved ScriptFunctionData creation logic away from runtime to compile time. Prepared for method generation/specialization. Got rid of ScriptFunctionImplTrampoline whose semantics could be done as part of the relinking anyway. Merge with the lookup package change.
lagergren
parents:
16262
diff
changeset
|
2001 |
} |
af8b30edebce
8009718: Lazy execution architecture continued - ScriptFunctionData is either final or recompilable. Moved ScriptFunctionData creation logic away from runtime to compile time. Prepared for method generation/specialization. Got rid of ScriptFunctionImplTrampoline whose semantics could be done as part of the relinking anyway. Merge with the lookup package change.
lagergren
parents:
16262
diff
changeset
|
2002 |
|
af8b30edebce
8009718: Lazy execution architecture continued - ScriptFunctionData is either final or recompilable. Moved ScriptFunctionData creation logic away from runtime to compile time. Prepared for method generation/specialization. Got rid of ScriptFunctionImplTrampoline whose semantics could be done as part of the relinking anyway. Merge with the lookup package change.
lagergren
parents:
16262
diff
changeset
|
2003 |
if (!redefinitionOk) { |
17233 | 2004 |
throw error(AbstractParser.message("property.redefinition", key.toString()), property.getToken()); |
16523
af8b30edebce
8009718: Lazy execution architecture continued - ScriptFunctionData is either final or recompilable. Moved ScriptFunctionData creation logic away from runtime to compile time. Prepared for method generation/specialization. Got rid of ScriptFunctionImplTrampoline whose semantics could be done as part of the relinking anyway. Merge with the lookup package change.
lagergren
parents:
16262
diff
changeset
|
2005 |
} |
af8b30edebce
8009718: Lazy execution architecture continued - ScriptFunctionData is either final or recompilable. Moved ScriptFunctionData creation logic away from runtime to compile time. Prepared for method generation/specialization. Got rid of ScriptFunctionImplTrampoline whose semantics could be done as part of the relinking anyway. Merge with the lookup package change.
lagergren
parents:
16262
diff
changeset
|
2006 |
|
17233 | 2007 |
PropertyNode newProperty = existingProperty; |
16523
af8b30edebce
8009718: Lazy execution architecture continued - ScriptFunctionData is either final or recompilable. Moved ScriptFunctionData creation logic away from runtime to compile time. Prepared for method generation/specialization. Got rid of ScriptFunctionImplTrampoline whose semantics could be done as part of the relinking anyway. Merge with the lookup package change.
lagergren
parents:
16262
diff
changeset
|
2008 |
if (value != null) { |
17233 | 2009 |
if (prevValue == null) { |
2010 |
map.put(key, newProperty = newProperty.setValue(value)); |
|
16523
af8b30edebce
8009718: Lazy execution architecture continued - ScriptFunctionData is either final or recompilable. Moved ScriptFunctionData creation logic away from runtime to compile time. Prepared for method generation/specialization. Got rid of ScriptFunctionImplTrampoline whose semantics could be done as part of the relinking anyway. Merge with the lookup package change.
lagergren
parents:
16262
diff
changeset
|
2011 |
} else { |
17233 | 2012 |
final long propertyToken = Token.recast(newProperty.getToken(), COMMARIGHT); |
17523
cb4a7c901e0d
8013913: Removed Source field from all nodes except FunctionNode in order to save footprint
lagergren
parents:
17518
diff
changeset
|
2013 |
map.put(key, newProperty = newProperty.setValue(new BinaryNode(propertyToken, prevValue, value))); |
16147 | 2014 |
} |
2015 |
||
17233 | 2016 |
map.put(key, newProperty = newProperty.setGetter(null).setSetter(null)); |
16147 | 2017 |
} |
2018 |
||
16523
af8b30edebce
8009718: Lazy execution architecture continued - ScriptFunctionData is either final or recompilable. Moved ScriptFunctionData creation logic away from runtime to compile time. Prepared for method generation/specialization. Got rid of ScriptFunctionImplTrampoline whose semantics could be done as part of the relinking anyway. Merge with the lookup package change.
lagergren
parents:
16262
diff
changeset
|
2019 |
if (getter != null) { |
17233 | 2020 |
map.put(key, newProperty = newProperty.setGetter(getter)); |
16523
af8b30edebce
8009718: Lazy execution architecture continued - ScriptFunctionData is either final or recompilable. Moved ScriptFunctionData creation logic away from runtime to compile time. Prepared for method generation/specialization. Got rid of ScriptFunctionImplTrampoline whose semantics could be done as part of the relinking anyway. Merge with the lookup package change.
lagergren
parents:
16262
diff
changeset
|
2021 |
} |
af8b30edebce
8009718: Lazy execution architecture continued - ScriptFunctionData is either final or recompilable. Moved ScriptFunctionData creation logic away from runtime to compile time. Prepared for method generation/specialization. Got rid of ScriptFunctionImplTrampoline whose semantics could be done as part of the relinking anyway. Merge with the lookup package change.
lagergren
parents:
16262
diff
changeset
|
2022 |
|
af8b30edebce
8009718: Lazy execution architecture continued - ScriptFunctionData is either final or recompilable. Moved ScriptFunctionData creation logic away from runtime to compile time. Prepared for method generation/specialization. Got rid of ScriptFunctionImplTrampoline whose semantics could be done as part of the relinking anyway. Merge with the lookup package change.
lagergren
parents:
16262
diff
changeset
|
2023 |
if (setter != null) { |
17233 | 2024 |
map.put(key, newProperty = newProperty.setSetter(setter)); |
16523
af8b30edebce
8009718: Lazy execution architecture continued - ScriptFunctionData is either final or recompilable. Moved ScriptFunctionData creation logic away from runtime to compile time. Prepared for method generation/specialization. Got rid of ScriptFunctionImplTrampoline whose semantics could be done as part of the relinking anyway. Merge with the lookup package change.
lagergren
parents:
16262
diff
changeset
|
2025 |
} |
17233 | 2026 |
break; |
16147 | 2027 |
} |
2028 |
} |
|
2029 |
||
17981
9b8e085aa1fe
8015955: ObjectNode.elements should be stronger typed
attila
parents:
17973
diff
changeset
|
2030 |
return new ObjectNode(objectToken, finish, new ArrayList<>(map.values())); |
16147 | 2031 |
} |
2032 |
||
2033 |
/** |
|
2034 |
* PropertyName : |
|
2035 |
* IdentifierName |
|
2036 |
* StringLiteral |
|
2037 |
* NumericLiteral |
|
2038 |
* |
|
2039 |
* See 11.1.5 |
|
2040 |
* |
|
2041 |
* @return PropertyName node |
|
2042 |
*/ |
|
2043 |
@SuppressWarnings("fallthrough") |
|
2044 |
private PropertyKey propertyName() { |
|
2045 |
switch (type) { |
|
2046 |
case IDENT: |
|
2047 |
return getIdent(); |
|
2048 |
case OCTAL: |
|
2049 |
if (isStrictMode) { |
|
17233 | 2050 |
throw error(AbstractParser.message("strict.no.octal"), token); |
16147 | 2051 |
} |
2052 |
case STRING: |
|
2053 |
case ESCSTRING: |
|
2054 |
case DECIMAL: |
|
2055 |
case HEXADECIMAL: |
|
2056 |
case FLOATING: |
|
2057 |
return getLiteral(); |
|
2058 |
default: |
|
2059 |
return getIdentifierName(); |
|
2060 |
} |
|
2061 |
} |
|
2062 |
||
2063 |
/** |
|
2064 |
* PropertyAssignment : |
|
2065 |
* PropertyName : AssignmentExpression |
|
2066 |
* get PropertyName ( ) { FunctionBody } |
|
2067 |
* set PropertyName ( PropertySetParameterList ) { FunctionBody } |
|
2068 |
* |
|
2069 |
* PropertySetParameterList : |
|
2070 |
* Identifier |
|
2071 |
* |
|
2072 |
* PropertyName : |
|
2073 |
* IdentifierName |
|
2074 |
* StringLiteral |
|
2075 |
* NumericLiteral |
|
2076 |
* |
|
2077 |
* See 11.1.5 |
|
2078 |
* |
|
2079 |
* Parse an object literal property. |
|
2080 |
* @return Property or reference node. |
|
2081 |
*/ |
|
2082 |
private PropertyNode propertyAssignment() { |
|
2083 |
// Capture firstToken. |
|
2084 |
final long propertyToken = token; |
|
2085 |
||
2086 |
FunctionNode functionNode; |
|
2087 |
PropertyKey propertyName; |
|
2088 |
||
2089 |
if (type == IDENT) { |
|
2090 |
// Get IDENT. |
|
2091 |
final String ident = (String)expectValue(IDENT); |
|
2092 |
||
2093 |
if (type != COLON) { |
|
2094 |
final long getSetToken = token; |
|
2095 |
||
2096 |
switch (ident) { |
|
2097 |
case "get": |
|
2098 |
final PropertyKey getIdent = propertyName(); |
|
2099 |
final String getterName = getIdent.getPropertyName(); |
|
17523
cb4a7c901e0d
8013913: Removed Source field from all nodes except FunctionNode in order to save footprint
lagergren
parents:
17518
diff
changeset
|
2100 |
final IdentNode getNameNode = new IdentNode(((Node)getIdent).getToken(), finish, "get " + getterName); |
16147 | 2101 |
expect(LPAREN); |
2102 |
expect(RPAREN); |
|
17233 | 2103 |
functionNode = functionBody(getSetToken, getNameNode, new ArrayList<IdentNode>(), FunctionNode.Kind.GETTER); |
17523
cb4a7c901e0d
8013913: Removed Source field from all nodes except FunctionNode in order to save footprint
lagergren
parents:
17518
diff
changeset
|
2104 |
return new PropertyNode(propertyToken, finish, getIdent, null, functionNode, null); |
16147 | 2105 |
|
2106 |
case "set": |
|
2107 |
final PropertyKey setIdent = propertyName(); |
|
2108 |
final String setterName = setIdent.getPropertyName(); |
|
17523
cb4a7c901e0d
8013913: Removed Source field from all nodes except FunctionNode in order to save footprint
lagergren
parents:
17518
diff
changeset
|
2109 |
final IdentNode setNameNode = new IdentNode(((Node)setIdent).getToken(), finish, "set " + setterName); |
16147 | 2110 |
expect(LPAREN); |
2111 |
final IdentNode argIdent = getIdent(); |
|
2112 |
verifyStrictIdent(argIdent, "setter argument"); |
|
2113 |
expect(RPAREN); |
|
17233 | 2114 |
List<IdentNode> parameters = new ArrayList<>(); |
16147 | 2115 |
parameters.add(argIdent); |
2116 |
functionNode = functionBody(getSetToken, setNameNode, parameters, FunctionNode.Kind.SETTER); |
|
17523
cb4a7c901e0d
8013913: Removed Source field from all nodes except FunctionNode in order to save footprint
lagergren
parents:
17518
diff
changeset
|
2117 |
return new PropertyNode(propertyToken, finish, setIdent, null, null, functionNode); |
16147 | 2118 |
|
2119 |
default: |
|
2120 |
break; |
|
2121 |
} |
|
2122 |
} |
|
2123 |
||
17523
cb4a7c901e0d
8013913: Removed Source field from all nodes except FunctionNode in order to save footprint
lagergren
parents:
17518
diff
changeset
|
2124 |
propertyName = new IdentNode(propertyToken, finish, ident); |
16147 | 2125 |
} else { |
2126 |
propertyName = propertyName(); |
|
2127 |
} |
|
2128 |
||
2129 |
expect(COLON); |
|
2130 |
||
17523
cb4a7c901e0d
8013913: Removed Source field from all nodes except FunctionNode in order to save footprint
lagergren
parents:
17518
diff
changeset
|
2131 |
return new PropertyNode(propertyToken, finish, propertyName, assignmentExpression(false), null, null); |
17233 | 2132 |
} |
2133 |
||
16147 | 2134 |
/** |
2135 |
* LeftHandSideExpression : |
|
2136 |
* NewExpression |
|
2137 |
* CallExpression |
|
2138 |
* |
|
2139 |
* CallExpression : |
|
2140 |
* MemberExpression Arguments |
|
2141 |
* CallExpression Arguments |
|
2142 |
* CallExpression [ Expression ] |
|
2143 |
* CallExpression . IdentifierName |
|
2144 |
* |
|
2145 |
* See 11.2 |
|
2146 |
* |
|
2147 |
* Parse left hand side expression. |
|
2148 |
* @return Expression node. |
|
2149 |
*/ |
|
2150 |
private Node leftHandSideExpression() { |
|
17524
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
2151 |
int callLine = line; |
16147 | 2152 |
long callToken = token; |
2153 |
||
2154 |
Node lhs = memberExpression(); |
|
2155 |
||
2156 |
if (type == LPAREN) { |
|
2157 |
final List<Node> arguments = argumentList(); |
|
2158 |
||
2159 |
// Catch special functions. |
|
2160 |
if (lhs instanceof IdentNode) { |
|
2161 |
detectSpecialFunction((IdentNode)lhs); |
|
2162 |
} |
|
2163 |
||
17524
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
2164 |
lhs = new CallNode(callLine, callToken, finish, lhs, arguments); |
16147 | 2165 |
} |
2166 |
||
2167 |
loop: |
|
2168 |
while (true) { |
|
2169 |
// Capture token. |
|
17524
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
2170 |
callLine = line; |
16147 | 2171 |
callToken = token; |
2172 |
||
2173 |
switch (type) { |
|
2174 |
case LPAREN: |
|
2175 |
// Get NEW or FUNCTION arguments. |
|
2176 |
final List<Node> arguments = argumentList(); |
|
2177 |
||
2178 |
// Create call node. |
|
17524
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
2179 |
lhs = new CallNode(callLine, callToken, finish, lhs, arguments); |
16147 | 2180 |
|
2181 |
break; |
|
2182 |
||
2183 |
case LBRACKET: |
|
2184 |
next(); |
|
2185 |
||
2186 |
// Get array index. |
|
2187 |
final Node rhs = expression(); |
|
2188 |
||
2189 |
expect(RBRACKET); |
|
2190 |
||
2191 |
// Create indexing node. |
|
17523
cb4a7c901e0d
8013913: Removed Source field from all nodes except FunctionNode in order to save footprint
lagergren
parents:
17518
diff
changeset
|
2192 |
lhs = new IndexNode(callToken, finish, lhs, rhs); |
16147 | 2193 |
|
2194 |
break; |
|
2195 |
||
2196 |
case PERIOD: |
|
2197 |
next(); |
|
2198 |
||
2199 |
final IdentNode property = getIdentifierName(); |
|
2200 |
||
2201 |
// Create property access node. |
|
17523
cb4a7c901e0d
8013913: Removed Source field from all nodes except FunctionNode in order to save footprint
lagergren
parents:
17518
diff
changeset
|
2202 |
lhs = new AccessNode(callToken, finish, lhs, property); |
16147 | 2203 |
|
2204 |
break; |
|
2205 |
||
2206 |
default: |
|
2207 |
break loop; |
|
2208 |
} |
|
2209 |
} |
|
2210 |
||
2211 |
return lhs; |
|
2212 |
} |
|
2213 |
||
2214 |
/** |
|
2215 |
* NewExpression : |
|
2216 |
* MemberExpression |
|
2217 |
* new NewExpression |
|
2218 |
* |
|
2219 |
* See 11.2 |
|
2220 |
* |
|
2221 |
* Parse new expression. |
|
2222 |
* @return Expression node. |
|
2223 |
*/ |
|
2224 |
private Node newExpression() { |
|
2225 |
final long newToken = token; |
|
2226 |
// NEW is tested in caller. |
|
2227 |
next(); |
|
2228 |
||
2229 |
// Get function base. |
|
17524
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
2230 |
final int callLine = line; |
16147 | 2231 |
final Node constructor = memberExpression(); |
2232 |
if (constructor == null) { |
|
2233 |
return null; |
|
2234 |
} |
|
2235 |
// Get arguments. |
|
2236 |
List<Node> arguments; |
|
2237 |
||
2238 |
// Allow for missing arguments. |
|
2239 |
if (type == LPAREN) { |
|
2240 |
arguments = argumentList(); |
|
2241 |
} else { |
|
2242 |
arguments = new ArrayList<>(); |
|
2243 |
} |
|
2244 |
||
16196
58f6f046bb5e
8006983: Introduce a command line option to switch off syntactic extensions of nashorn
sundar
parents:
16191
diff
changeset
|
2245 |
// Nashorn extension: This is to support the following interface implementation |
58f6f046bb5e
8006983: Introduce a command line option to switch off syntactic extensions of nashorn
sundar
parents:
16191
diff
changeset
|
2246 |
// syntax: |
16147 | 2247 |
// |
2248 |
// var r = new java.lang.Runnable() { |
|
2249 |
// run: function() { println("run"); } |
|
2250 |
// }; |
|
2251 |
// |
|
2252 |
// The object literal following the "new Constructor()" expresssion |
|
2253 |
// is passed as an additional (last) argument to the constructor. |
|
2254 |
||
16262
75513555e603
8008731: Separate configuration environment (options, error/output writer etc.) from Context
sundar
parents:
16252
diff
changeset
|
2255 |
if (!env._no_syntax_extensions && type == LBRACE) { |
16147 | 2256 |
arguments.add(objectLiteral()); |
2257 |
} |
|
2258 |
||
17524
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
2259 |
final CallNode callNode = new CallNode(callLine, constructor.getToken(), finish, constructor, arguments); |
17523
cb4a7c901e0d
8013913: Removed Source field from all nodes except FunctionNode in order to save footprint
lagergren
parents:
17518
diff
changeset
|
2260 |
|
cb4a7c901e0d
8013913: Removed Source field from all nodes except FunctionNode in order to save footprint
lagergren
parents:
17518
diff
changeset
|
2261 |
return new UnaryNode(newToken, callNode); |
16147 | 2262 |
} |
2263 |
||
2264 |
/** |
|
2265 |
* MemberExpression : |
|
2266 |
* PrimaryExpression |
|
2267 |
* FunctionExpression |
|
2268 |
* MemberExpression [ Expression ] |
|
2269 |
* MemberExpression . IdentifierName |
|
2270 |
* new MemberExpression Arguments |
|
2271 |
* |
|
2272 |
* See 11.2 |
|
2273 |
* |
|
2274 |
* Parse member expression. |
|
2275 |
* @return Expression node. |
|
2276 |
*/ |
|
2277 |
private Node memberExpression() { |
|
2278 |
// Prepare to build operation. |
|
2279 |
Node lhs; |
|
2280 |
||
2281 |
switch (type) { |
|
2282 |
case NEW: |
|
2283 |
// Get new exppression. |
|
2284 |
lhs = newExpression(); |
|
2285 |
break; |
|
2286 |
||
2287 |
case FUNCTION: |
|
2288 |
// Get function expression. |
|
16530
201d682e75f4
8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents:
16525
diff
changeset
|
2289 |
lhs = functionExpression(false, false); |
16147 | 2290 |
break; |
2291 |
||
2292 |
default: |
|
2293 |
// Get primary expression. |
|
2294 |
lhs = primaryExpression(); |
|
2295 |
break; |
|
2296 |
} |
|
2297 |
||
2298 |
loop: |
|
2299 |
while (true) { |
|
2300 |
// Capture token. |
|
2301 |
final long callToken = token; |
|
2302 |
||
2303 |
switch (type) { |
|
2304 |
case LBRACKET: |
|
2305 |
next(); |
|
2306 |
||
2307 |
// Get array index. |
|
2308 |
final Node index = expression(); |
|
2309 |
||
2310 |
expect(RBRACKET); |
|
2311 |
||
2312 |
// Create indexing node. |
|
17523
cb4a7c901e0d
8013913: Removed Source field from all nodes except FunctionNode in order to save footprint
lagergren
parents:
17518
diff
changeset
|
2313 |
lhs = new IndexNode(callToken, finish, lhs, index); |
16147 | 2314 |
|
2315 |
break; |
|
2316 |
||
2317 |
case PERIOD: |
|
2318 |
if (lhs == null) { |
|
17233 | 2319 |
throw error(AbstractParser.message("expected.operand", type.getNameOrType())); |
16147 | 2320 |
} |
2321 |
||
2322 |
next(); |
|
2323 |
||
2324 |
final IdentNode property = getIdentifierName(); |
|
2325 |
||
2326 |
// Create property access node. |
|
17523
cb4a7c901e0d
8013913: Removed Source field from all nodes except FunctionNode in order to save footprint
lagergren
parents:
17518
diff
changeset
|
2327 |
lhs = new AccessNode(callToken, finish, lhs, property); |
16147 | 2328 |
|
2329 |
break; |
|
2330 |
||
2331 |
default: |
|
2332 |
break loop; |
|
2333 |
} |
|
2334 |
} |
|
2335 |
||
2336 |
return lhs; |
|
2337 |
} |
|
2338 |
||
2339 |
/** |
|
2340 |
* Arguments : |
|
2341 |
* ( ) |
|
2342 |
* ( ArgumentList ) |
|
2343 |
* |
|
2344 |
* ArgumentList : |
|
2345 |
* AssignmentExpression |
|
2346 |
* ArgumentList , AssignmentExpression |
|
2347 |
* |
|
2348 |
* See 11.2 |
|
2349 |
* |
|
2350 |
* Parse function call arguments. |
|
2351 |
* @return Argument list. |
|
2352 |
*/ |
|
2353 |
private List<Node> argumentList() { |
|
2354 |
// Prepare to accumulate list of arguments. |
|
2355 |
final List<Node> nodeList = new ArrayList<>(); |
|
2356 |
// LPAREN tested in caller. |
|
2357 |
next(); |
|
2358 |
||
2359 |
// Track commas. |
|
2360 |
boolean first = true; |
|
2361 |
||
2362 |
while (type != RPAREN) { |
|
2363 |
// Comma prior to every argument except the first. |
|
2364 |
if (!first) { |
|
2365 |
expect(COMMARIGHT); |
|
2366 |
} else { |
|
2367 |
first = false; |
|
2368 |
} |
|
2369 |
||
2370 |
// Get argument expression. |
|
2371 |
nodeList.add(assignmentExpression(false)); |
|
2372 |
} |
|
2373 |
||
2374 |
expect(RPAREN); |
|
2375 |
||
2376 |
return nodeList; |
|
2377 |
} |
|
2378 |
||
2379 |
/** |
|
2380 |
* FunctionDeclaration : |
|
2381 |
* function Identifier ( FormalParameterList? ) { FunctionBody } |
|
2382 |
* |
|
2383 |
* FunctionExpression : |
|
2384 |
* function Identifier? ( FormalParameterList? ) { FunctionBody } |
|
2385 |
* |
|
2386 |
* See 13 |
|
2387 |
* |
|
2388 |
* Parse function declaration. |
|
2389 |
* @param isStatement True if for is a statement. |
|
2390 |
* |
|
2391 |
* @return Expression node. |
|
2392 |
*/ |
|
16530
201d682e75f4
8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents:
16525
diff
changeset
|
2393 |
private Node functionExpression(final boolean isStatement, final boolean topLevel) { |
16147 | 2394 |
final long functionToken = token; |
17524
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
2395 |
final int functionLine = line; |
16147 | 2396 |
// FUNCTION is tested in caller. |
2397 |
next(); |
|
2398 |
||
2399 |
IdentNode name = null; |
|
2400 |
||
2401 |
if (type == IDENT || isNonStrictModeIdent()) { |
|
2402 |
name = getIdent(); |
|
2403 |
verifyStrictIdent(name, "function name"); |
|
16196
58f6f046bb5e
8006983: Introduce a command line option to switch off syntactic extensions of nashorn
sundar
parents:
16191
diff
changeset
|
2404 |
} else if (isStatement) { |
58f6f046bb5e
8006983: Introduce a command line option to switch off syntactic extensions of nashorn
sundar
parents:
16191
diff
changeset
|
2405 |
// Nashorn extension: anonymous function statements |
16262
75513555e603
8008731: Separate configuration environment (options, error/output writer etc.) from Context
sundar
parents:
16252
diff
changeset
|
2406 |
if (env._no_syntax_extensions || !env._anon_functions) { |
16196
58f6f046bb5e
8006983: Introduce a command line option to switch off syntactic extensions of nashorn
sundar
parents:
16191
diff
changeset
|
2407 |
expect(IDENT); |
58f6f046bb5e
8006983: Introduce a command line option to switch off syntactic extensions of nashorn
sundar
parents:
16191
diff
changeset
|
2408 |
} |
16147 | 2409 |
} |
2410 |
||
2411 |
// name is null, generate anonymous name |
|
2412 |
boolean isAnonymous = false; |
|
2413 |
if (name == null) { |
|
2414 |
final String tmpName = "_L" + source.getLine(Token.descPosition(token)); |
|
17523
cb4a7c901e0d
8013913: Removed Source field from all nodes except FunctionNode in order to save footprint
lagergren
parents:
17518
diff
changeset
|
2415 |
name = new IdentNode(functionToken, Token.descPosition(functionToken), tmpName); |
16147 | 2416 |
isAnonymous = true; |
2417 |
} |
|
2418 |
||
2419 |
expect(LPAREN); |
|
2420 |
final List<IdentNode> parameters = formalParameterList(); |
|
2421 |
expect(RPAREN); |
|
2422 |
||
17233 | 2423 |
FunctionNode functionNode = functionBody(functionToken, name, parameters, FunctionNode.Kind.NORMAL); |
16147 | 2424 |
|
16530
201d682e75f4
8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents:
16525
diff
changeset
|
2425 |
if (isStatement) { |
17233 | 2426 |
if (topLevel) { |
2427 |
functionNode = functionNode.setFlag(lc, FunctionNode.IS_DECLARED); |
|
17257
a2232050cd8f
8008814: Configurable ignore/warning/error behavior for function declaration as statement
attila
parents:
17255
diff
changeset
|
2428 |
} else if (isStrictMode) { |
a2232050cd8f
8008814: Configurable ignore/warning/error behavior for function declaration as statement
attila
parents:
17255
diff
changeset
|
2429 |
throw error(JSErrorType.SYNTAX_ERROR, AbstractParser.message("strict.no.func.decl.here"), functionToken); |
a2232050cd8f
8008814: Configurable ignore/warning/error behavior for function declaration as statement
attila
parents:
17255
diff
changeset
|
2430 |
} else if (env._function_statement == ScriptEnvironment.FunctionStatementBehavior.ERROR) { |
a2232050cd8f
8008814: Configurable ignore/warning/error behavior for function declaration as statement
attila
parents:
17255
diff
changeset
|
2431 |
throw error(JSErrorType.SYNTAX_ERROR, AbstractParser.message("no.func.decl.here"), functionToken); |
a2232050cd8f
8008814: Configurable ignore/warning/error behavior for function declaration as statement
attila
parents:
17255
diff
changeset
|
2432 |
} else if (env._function_statement == ScriptEnvironment.FunctionStatementBehavior.WARNING) { |
a2232050cd8f
8008814: Configurable ignore/warning/error behavior for function declaration as statement
attila
parents:
17255
diff
changeset
|
2433 |
warning(JSErrorType.SYNTAX_ERROR, AbstractParser.message("no.func.decl.here.warn"), functionToken); |
16530
201d682e75f4
8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents:
16525
diff
changeset
|
2434 |
} |
17233 | 2435 |
if (ARGUMENTS.symbolName().equals(name.getName())) { |
17249
a2014831ae7a
8013325: function named 'arguments' should set DEFINES_ARGUMENTS flag in its parent, not itself
attila
parents:
17233
diff
changeset
|
2436 |
lc.setFlag(lc.getCurrentFunction(), FunctionNode.DEFINES_ARGUMENTS); |
16206
83069fa0935b
8006529: Methods always get callee - it should be conditional
attila
parents:
16201
diff
changeset
|
2437 |
} |
16147 | 2438 |
} |
2439 |
||
2440 |
if (isAnonymous) { |
|
17233 | 2441 |
functionNode = functionNode.setFlag(lc, FunctionNode.IS_ANONYMOUS); |
16147 | 2442 |
} |
2443 |
||
2444 |
final int arity = parameters.size(); |
|
2445 |
||
17233 | 2446 |
final boolean strict = functionNode.isStrict(); |
16147 | 2447 |
if (arity > 1) { |
2448 |
final HashSet<String> parametersSet = new HashSet<>(arity); |
|
2449 |
||
2450 |
for (int i = arity - 1; i >= 0; i--) { |
|
2451 |
final IdentNode parameter = parameters.get(i); |
|
2452 |
String parameterName = parameter.getName(); |
|
2453 |
||
17233 | 2454 |
if (ARGUMENTS.symbolName().equals(parameterName)) { |
2455 |
functionNode = functionNode.setFlag(lc, FunctionNode.DEFINES_ARGUMENTS); |
|
16147 | 2456 |
} |
2457 |
||
2458 |
if (parametersSet.contains(parameterName)) { |
|
2459 |
// redefinition of parameter name |
|
2460 |
if (strict) { |
|
17233 | 2461 |
throw error(AbstractParser.message("strict.param.redefinition", parameterName), parameter.getToken()); |
16147 | 2462 |
} |
17233 | 2463 |
// rename in non-strict mode |
2464 |
parameterName = functionNode.uniqueName(parameterName); |
|
2465 |
final long parameterToken = parameter.getToken(); |
|
17523
cb4a7c901e0d
8013913: Removed Source field from all nodes except FunctionNode in order to save footprint
lagergren
parents:
17518
diff
changeset
|
2466 |
parameters.set(i, new IdentNode(parameterToken, Token.descPosition(parameterToken), functionNode.uniqueName(parameterName))); |
16147 | 2467 |
} |
2468 |
||
2469 |
parametersSet.add(parameterName); |
|
2470 |
} |
|
2471 |
} else if (arity == 1) { |
|
17233 | 2472 |
if (ARGUMENTS.symbolName().equals(parameters.get(0).getName())) { |
2473 |
functionNode = functionNode.setFlag(lc, FunctionNode.DEFINES_ARGUMENTS); |
|
16147 | 2474 |
} |
2475 |
} |
|
2476 |
||
2477 |
if (isStatement) { |
|
17524
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
2478 |
final VarNode varNode = new VarNode(functionLine, functionToken, finish, name, functionNode, VarNode.IS_STATEMENT); |
17233 | 2479 |
if (topLevel) { |
16530
201d682e75f4
8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents:
16525
diff
changeset
|
2480 |
functionDeclarations.add(varNode); |
16191
7dd981da8e11
8006755: Functions inside with statements dont get correct scope
sundar
parents:
16187
diff
changeset
|
2481 |
} else { |
17233 | 2482 |
appendStatement(varNode); |
16191
7dd981da8e11
8006755: Functions inside with statements dont get correct scope
sundar
parents:
16187
diff
changeset
|
2483 |
} |
16147 | 2484 |
} |
2485 |
||
16530
201d682e75f4
8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents:
16525
diff
changeset
|
2486 |
return functionNode; |
16147 | 2487 |
} |
2488 |
||
2489 |
/** |
|
2490 |
* FormalParameterList : |
|
2491 |
* Identifier |
|
2492 |
* FormalParameterList , Identifier |
|
2493 |
* |
|
2494 |
* See 13 |
|
2495 |
* |
|
2496 |
* Parse function parameter list. |
|
2497 |
* @return List of parameter nodes. |
|
2498 |
*/ |
|
2499 |
private List<IdentNode> formalParameterList() { |
|
17973
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
2500 |
return formalParameterList(RPAREN); |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
2501 |
} |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
2502 |
|
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
2503 |
/** |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
2504 |
* Same as the other method of the same name - except that the end |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
2505 |
* token type expected is passed as argument to this method. |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
2506 |
* |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
2507 |
* FormalParameterList : |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
2508 |
* Identifier |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
2509 |
* FormalParameterList , Identifier |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
2510 |
* |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
2511 |
* See 13 |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
2512 |
* |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
2513 |
* Parse function parameter list. |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
2514 |
* @return List of parameter nodes. |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
2515 |
*/ |
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
2516 |
private List<IdentNode> formalParameterList(final TokenType endType) { |
16147 | 2517 |
// Prepare to gather parameters. |
2518 |
final List<IdentNode> parameters = new ArrayList<>(); |
|
2519 |
// Track commas. |
|
2520 |
boolean first = true; |
|
2521 |
||
17973
d220c8157f25
8015345: Function("}),print('test'),({") should throw SyntaxError
sundar
parents:
17745
diff
changeset
|
2522 |
while (type != endType) { |
16147 | 2523 |
// Comma prior to every argument except the first. |
2524 |
if (!first) { |
|
2525 |
expect(COMMARIGHT); |
|
2526 |
} else { |
|
2527 |
first = false; |
|
2528 |
} |
|
2529 |
||
2530 |
// Get and add parameter. |
|
2531 |
final IdentNode ident = getIdent(); |
|
2532 |
||
2533 |
// ECMA 13.1 strict mode restrictions |
|
2534 |
verifyStrictIdent(ident, "function parameter"); |
|
2535 |
||
2536 |
parameters.add(ident); |
|
2537 |
} |
|
2538 |
||
2539 |
return parameters; |
|
2540 |
} |
|
2541 |
||
2542 |
/** |
|
2543 |
* FunctionBody : |
|
2544 |
* SourceElements? |
|
2545 |
* |
|
2546 |
* See 13 |
|
2547 |
* |
|
2548 |
* Parse function body. |
|
2549 |
* @return function node (body.) |
|
2550 |
*/ |
|
2551 |
private FunctionNode functionBody(final long firstToken, final IdentNode ident, final List<IdentNode> parameters, final FunctionNode.Kind kind) { |
|
2552 |
FunctionNode functionNode = null; |
|
17233 | 2553 |
long lastToken = 0L; |
16147 | 2554 |
|
2555 |
try { |
|
2556 |
// Create a new function block. |
|
17233 | 2557 |
functionNode = newFunctionNode(firstToken, ident, parameters, kind); |
16147 | 2558 |
|
2559 |
// Nashorn extension: expression closures |
|
16262
75513555e603
8008731: Separate configuration environment (options, error/output writer etc.) from Context
sundar
parents:
16252
diff
changeset
|
2560 |
if (!env._no_syntax_extensions && type != LBRACE) { |
16147 | 2561 |
/* |
2562 |
* Example: |
|
2563 |
* |
|
2564 |
* function square(x) x * x; |
|
2565 |
* print(square(3)); |
|
2566 |
*/ |
|
2567 |
||
2568 |
// just expression as function body |
|
2569 |
final Node expr = expression(); |
|
17233 | 2570 |
assert lc.getCurrentBlock() == lc.getFunctionBody(functionNode); |
16201
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16196
diff
changeset
|
2571 |
// create a return statement - this creates code in itself and does not need to be |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16196
diff
changeset
|
2572 |
// wrapped into an ExecuteNode |
17524
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
2573 |
final ReturnNode returnNode = new ReturnNode(functionNode.getLineNumber(), expr.getToken(), finish, expr); |
17233 | 2574 |
appendStatement(returnNode); |
2575 |
lastToken = token; |
|
16147 | 2576 |
functionNode.setFinish(Token.descPosition(token) + Token.descLength(token)); |
2577 |
||
2578 |
} else { |
|
2579 |
expect(LBRACE); |
|
2580 |
||
2581 |
// Gather the function elements. |
|
17524
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
2582 |
final List<Statement> prevFunctionDecls = functionDeclarations; |
16530
201d682e75f4
8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents:
16525
diff
changeset
|
2583 |
functionDeclarations = new ArrayList<>(); |
201d682e75f4
8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents:
16525
diff
changeset
|
2584 |
try { |
201d682e75f4
8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents:
16525
diff
changeset
|
2585 |
sourceElements(); |
17233 | 2586 |
addFunctionDeclarations(functionNode); |
16530
201d682e75f4
8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents:
16525
diff
changeset
|
2587 |
} finally { |
201d682e75f4
8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents:
16525
diff
changeset
|
2588 |
functionDeclarations = prevFunctionDecls; |
201d682e75f4
8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents:
16525
diff
changeset
|
2589 |
} |
16147 | 2590 |
|
17233 | 2591 |
lastToken = token; |
16147 | 2592 |
expect(RBRACE); |
2593 |
functionNode.setFinish(finish); |
|
2594 |
||
2595 |
} |
|
2596 |
} finally { |
|
17233 | 2597 |
functionNode = restoreFunctionNode(functionNode, lastToken); |
16147 | 2598 |
} |
2599 |
return functionNode; |
|
2600 |
} |
|
2601 |
||
17233 | 2602 |
private void addFunctionDeclarations(final FunctionNode functionNode) { |
2603 |
assert lc.peek() == lc.getFunctionBody(functionNode); |
|
2604 |
VarNode lastDecl = null; |
|
2605 |
for (int i = functionDeclarations.size() - 1; i >= 0; i--) { |
|
17524
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
2606 |
Statement decl = functionDeclarations.get(i); |
17233 | 2607 |
if (lastDecl == null && decl instanceof VarNode) { |
2608 |
decl = lastDecl = ((VarNode)decl).setFlag(VarNode.IS_LAST_FUNCTION_DECLARATION); |
|
2609 |
lc.setFlag(functionNode, FunctionNode.HAS_FUNCTION_DECLARATIONS); |
|
2610 |
} |
|
2611 |
prependStatement(decl); |
|
2612 |
} |
|
2613 |
} |
|
2614 |
||
17523
cb4a7c901e0d
8013913: Removed Source field from all nodes except FunctionNode in order to save footprint
lagergren
parents:
17518
diff
changeset
|
2615 |
private static RuntimeNode referenceError(final Node lhs, final Node rhs) { |
16147 | 2616 |
final ArrayList<Node> args = new ArrayList<>(); |
2617 |
args.add(lhs); |
|
2618 |
if (rhs == null) { |
|
17523
cb4a7c901e0d
8013913: Removed Source field from all nodes except FunctionNode in order to save footprint
lagergren
parents:
17518
diff
changeset
|
2619 |
args.add(LiteralNode.newInstance(lhs.getToken(), lhs.getFinish())); |
16147 | 2620 |
} else { |
2621 |
args.add(rhs); |
|
2622 |
} |
|
17523
cb4a7c901e0d
8013913: Removed Source field from all nodes except FunctionNode in order to save footprint
lagergren
parents:
17518
diff
changeset
|
2623 |
args.add(LiteralNode.newInstance(lhs.getToken(), lhs.getFinish(), lhs.toString())); |
cb4a7c901e0d
8013913: Removed Source field from all nodes except FunctionNode in order to save footprint
lagergren
parents:
17518
diff
changeset
|
2624 |
return new RuntimeNode(lhs.getToken(), lhs.getFinish(), RuntimeNode.Request.REFERENCE_ERROR, args); |
16147 | 2625 |
} |
2626 |
||
2627 |
/* |
|
2628 |
* parse LHS [a, b, ..., c]. |
|
2629 |
* |
|
2630 |
* JavaScript 1.8. |
|
2631 |
*/ |
|
2632 |
//private Node destructureExpression() { |
|
2633 |
// return null; |
|
2634 |
//} |
|
2635 |
||
2636 |
/** |
|
2637 |
* PostfixExpression : |
|
2638 |
* LeftHandSideExpression |
|
2639 |
* LeftHandSideExpression ++ // [no LineTerminator here] |
|
2640 |
* LeftHandSideExpression -- // [no LineTerminator here] |
|
2641 |
* |
|
2642 |
* See 11.3 |
|
2643 |
* |
|
2644 |
* UnaryExpression : |
|
2645 |
* PostfixExpression |
|
2646 |
* delete UnaryExpression |
|
2647 |
* Node UnaryExpression |
|
2648 |
* typeof UnaryExpression |
|
2649 |
* ++ UnaryExpression |
|
2650 |
* -- UnaryExpression |
|
2651 |
* + UnaryExpression |
|
2652 |
* - UnaryExpression |
|
2653 |
* ~ UnaryExpression |
|
2654 |
* ! UnaryExpression |
|
2655 |
* |
|
2656 |
* See 11.4 |
|
2657 |
* |
|
2658 |
* Parse unary expression. |
|
2659 |
* @return Expression node. |
|
2660 |
*/ |
|
2661 |
private Node unaryExpression() { |
|
17524
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
2662 |
final int unaryLine = line; |
16147 | 2663 |
final long unaryToken = token; |
2664 |
||
2665 |
switch (type) { |
|
17524
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
2666 |
case DELETE: { |
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
2667 |
next(); |
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
2668 |
final Node expr = unaryExpression(); |
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
2669 |
if (expr instanceof BaseNode || expr instanceof IdentNode) { |
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
2670 |
return new UnaryNode(unaryToken, expr); |
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
2671 |
} |
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
2672 |
appendStatement(new ExecuteNode(unaryLine, unaryToken, finish, expr)); |
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
2673 |
return LiteralNode.newInstance(unaryToken, finish, true); |
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
2674 |
} |
16147 | 2675 |
case VOID: |
2676 |
case TYPEOF: |
|
2677 |
case ADD: |
|
2678 |
case SUB: |
|
2679 |
case BIT_NOT: |
|
2680 |
case NOT: |
|
2681 |
next(); |
|
2682 |
final Node expr = unaryExpression(); |
|
17523
cb4a7c901e0d
8013913: Removed Source field from all nodes except FunctionNode in order to save footprint
lagergren
parents:
17518
diff
changeset
|
2683 |
return new UnaryNode(unaryToken, expr); |
16147 | 2684 |
|
2685 |
case INCPREFIX: |
|
2686 |
case DECPREFIX: |
|
2687 |
final TokenType opType = type; |
|
2688 |
next(); |
|
2689 |
||
2690 |
final Node lhs = leftHandSideExpression(); |
|
2691 |
// ++, -- without operand.. |
|
2692 |
if (lhs == null) { |
|
2693 |
// error would have been issued when looking for 'lhs' |
|
2694 |
return null; |
|
2695 |
} |
|
2696 |
if (!(lhs instanceof AccessNode || |
|
2697 |
lhs instanceof IndexNode || |
|
2698 |
lhs instanceof IdentNode)) { |
|
2699 |
return referenceError(lhs, null); |
|
2700 |
} |
|
2701 |
||
2702 |
if (lhs instanceof IdentNode) { |
|
16523
af8b30edebce
8009718: Lazy execution architecture continued - ScriptFunctionData is either final or recompilable. Moved ScriptFunctionData creation logic away from runtime to compile time. Prepared for method generation/specialization. Got rid of ScriptFunctionImplTrampoline whose semantics could be done as part of the relinking anyway. Merge with the lookup package change.
lagergren
parents:
16262
diff
changeset
|
2703 |
if (!checkIdentLValue((IdentNode)lhs)) { |
16147 | 2704 |
return referenceError(lhs, null); |
2705 |
} |
|
2706 |
verifyStrictIdent((IdentNode)lhs, "operand for " + opType.getName() + " operator"); |
|
2707 |
} |
|
2708 |
||
2709 |
return incDecExpression(unaryToken, opType, lhs, false); |
|
2710 |
||
2711 |
default: |
|
2712 |
break; |
|
2713 |
} |
|
2714 |
||
2715 |
Node expression = leftHandSideExpression(); |
|
2716 |
||
2717 |
if (last != EOL) { |
|
2718 |
switch (type) { |
|
2719 |
case INCPREFIX: |
|
2720 |
case DECPREFIX: |
|
2721 |
final TokenType opType = type; |
|
2722 |
final Node lhs = expression; |
|
2723 |
if (!(lhs instanceof AccessNode || |
|
2724 |
lhs instanceof IndexNode || |
|
2725 |
lhs instanceof IdentNode)) { |
|
2726 |
next(); |
|
2727 |
return referenceError(lhs, null); |
|
2728 |
} |
|
2729 |
if (lhs instanceof IdentNode) { |
|
16523
af8b30edebce
8009718: Lazy execution architecture continued - ScriptFunctionData is either final or recompilable. Moved ScriptFunctionData creation logic away from runtime to compile time. Prepared for method generation/specialization. Got rid of ScriptFunctionImplTrampoline whose semantics could be done as part of the relinking anyway. Merge with the lookup package change.
lagergren
parents:
16262
diff
changeset
|
2730 |
if (!checkIdentLValue((IdentNode)lhs)) { |
16147 | 2731 |
next(); |
2732 |
return referenceError(lhs, null); |
|
2733 |
} |
|
2734 |
verifyStrictIdent((IdentNode)lhs, "operand for " + opType.getName() + " operator"); |
|
2735 |
} |
|
2736 |
expression = incDecExpression(token, type, expression, true); |
|
2737 |
next(); |
|
2738 |
break; |
|
2739 |
default: |
|
2740 |
break; |
|
2741 |
} |
|
2742 |
} |
|
2743 |
||
2744 |
if (expression == null) { |
|
17233 | 2745 |
throw error(AbstractParser.message("expected.operand", type.getNameOrType())); |
16147 | 2746 |
} |
2747 |
||
2748 |
return expression; |
|
2749 |
} |
|
2750 |
||
2751 |
/** |
|
2752 |
* MultiplicativeExpression : |
|
2753 |
* UnaryExpression |
|
2754 |
* MultiplicativeExpression * UnaryExpression |
|
2755 |
* MultiplicativeExpression / UnaryExpression |
|
2756 |
* MultiplicativeExpression % UnaryExpression |
|
2757 |
* |
|
2758 |
* See 11.5 |
|
2759 |
* |
|
2760 |
* AdditiveExpression : |
|
2761 |
* MultiplicativeExpression |
|
2762 |
* AdditiveExpression + MultiplicativeExpression |
|
2763 |
* AdditiveExpression - MultiplicativeExpression |
|
2764 |
* |
|
2765 |
* See 11.6 |
|
2766 |
* |
|
2767 |
* ShiftExpression : |
|
2768 |
* AdditiveExpression |
|
2769 |
* ShiftExpression << AdditiveExpression |
|
2770 |
* ShiftExpression >> AdditiveExpression |
|
2771 |
* ShiftExpression >>> AdditiveExpression |
|
2772 |
* |
|
2773 |
* See 11.7 |
|
2774 |
* |
|
2775 |
* RelationalExpression : |
|
2776 |
* ShiftExpression |
|
2777 |
* RelationalExpression < ShiftExpression |
|
2778 |
* RelationalExpression > ShiftExpression |
|
2779 |
* RelationalExpression <= ShiftExpression |
|
2780 |
* RelationalExpression >= ShiftExpression |
|
2781 |
* RelationalExpression instanceof ShiftExpression |
|
2782 |
* RelationalExpression in ShiftExpression // if !noIf |
|
2783 |
* |
|
2784 |
* See 11.8 |
|
2785 |
* |
|
2786 |
* RelationalExpression |
|
2787 |
* EqualityExpression == RelationalExpression |
|
2788 |
* EqualityExpression != RelationalExpression |
|
2789 |
* EqualityExpression === RelationalExpression |
|
2790 |
* EqualityExpression !== RelationalExpression |
|
2791 |
* |
|
2792 |
* See 11.9 |
|
2793 |
* |
|
2794 |
* BitwiseANDExpression : |
|
2795 |
* EqualityExpression |
|
2796 |
* BitwiseANDExpression & EqualityExpression |
|
2797 |
* |
|
2798 |
* BitwiseXORExpression : |
|
2799 |
* BitwiseANDExpression |
|
2800 |
* BitwiseXORExpression ^ BitwiseANDExpression |
|
2801 |
* |
|
2802 |
* BitwiseORExpression : |
|
2803 |
* BitwiseXORExpression |
|
2804 |
* BitwiseORExpression | BitwiseXORExpression |
|
2805 |
* |
|
2806 |
* See 11.10 |
|
2807 |
* |
|
2808 |
* LogicalANDExpression : |
|
2809 |
* BitwiseORExpression |
|
2810 |
* LogicalANDExpression && BitwiseORExpression |
|
2811 |
* |
|
2812 |
* LogicalORExpression : |
|
2813 |
* LogicalANDExpression |
|
2814 |
* LogicalORExpression || LogicalANDExpression |
|
2815 |
* |
|
2816 |
* See 11.11 |
|
2817 |
* |
|
2818 |
* ConditionalExpression : |
|
2819 |
* LogicalORExpression |
|
2820 |
* LogicalORExpression ? AssignmentExpression : AssignmentExpression |
|
2821 |
* |
|
2822 |
* See 11.12 |
|
2823 |
* |
|
2824 |
* AssignmentExpression : |
|
2825 |
* ConditionalExpression |
|
2826 |
* LeftHandSideExpression AssignmentOperator AssignmentExpression |
|
2827 |
* |
|
2828 |
* AssignmentOperator : |
|
2829 |
* = *= /= %= += -= <<= >>= >>>= &= ^= |= |
|
2830 |
* |
|
2831 |
* See 11.13 |
|
2832 |
* |
|
2833 |
* Expression : |
|
2834 |
* AssignmentExpression |
|
2835 |
* Expression , AssignmentExpression |
|
2836 |
* |
|
2837 |
* See 11.14 |
|
2838 |
* |
|
2839 |
* Parse expression. |
|
2840 |
* @return Expression node. |
|
2841 |
*/ |
|
2842 |
private Node expression() { |
|
2843 |
// TODO - Destructuring array. |
|
2844 |
// Include commas in expression parsing. |
|
2845 |
return expression(unaryExpression(), COMMARIGHT.getPrecedence(), false); |
|
2846 |
} |
|
17233 | 2847 |
|
16147 | 2848 |
private Node expression(final Node exprLhs, final int minPrecedence, final boolean noIn) { |
2849 |
// Get the precedence of the next operator. |
|
2850 |
int precedence = type.getPrecedence(); |
|
2851 |
Node lhs = exprLhs; |
|
2852 |
||
2853 |
// While greater precedence. |
|
2854 |
while (type.isOperator(noIn) && precedence >= minPrecedence) { |
|
2855 |
// Capture the operator token. |
|
2856 |
final long op = token; |
|
2857 |
||
2858 |
if (type == TERNARY) { |
|
2859 |
// Skip operator. |
|
2860 |
next(); |
|
2861 |
||
2862 |
// Pass expression. Middle expression of a conditional expression can be a "in" |
|
2863 |
// expression - even in the contexts where "in" is not permitted. |
|
2864 |
final Node rhs = expression(unaryExpression(), ASSIGN.getPrecedence(), false); |
|
2865 |
||
2866 |
expect(COLON); |
|
2867 |
||
2868 |
// Fail expression. |
|
2869 |
final Node third = expression(unaryExpression(), ASSIGN.getPrecedence(), noIn); |
|
2870 |
||
2871 |
// Build up node. |
|
17523
cb4a7c901e0d
8013913: Removed Source field from all nodes except FunctionNode in order to save footprint
lagergren
parents:
17518
diff
changeset
|
2872 |
lhs = new TernaryNode(op, lhs, rhs, third); |
16147 | 2873 |
} else { |
2874 |
// Skip operator. |
|
2875 |
next(); |
|
2876 |
||
2877 |
// Get the next primary expression. |
|
2878 |
Node rhs = unaryExpression(); |
|
2879 |
||
2880 |
// Get precedence of next operator. |
|
2881 |
int nextPrecedence = type.getPrecedence(); |
|
2882 |
||
2883 |
// Subtask greater precedence. |
|
2884 |
while (type.isOperator(noIn) && |
|
2885 |
(nextPrecedence > precedence || |
|
2886 |
nextPrecedence == precedence && !type.isLeftAssociative())) { |
|
2887 |
rhs = expression(rhs, nextPrecedence, noIn); |
|
2888 |
nextPrecedence = type.getPrecedence(); |
|
2889 |
} |
|
2890 |
||
2891 |
lhs = verifyAssignment(op, lhs, rhs); |
|
2892 |
} |
|
2893 |
||
2894 |
precedence = type.getPrecedence(); |
|
2895 |
} |
|
2896 |
||
2897 |
return lhs; |
|
2898 |
} |
|
2899 |
||
2900 |
private Node assignmentExpression(final boolean noIn) { |
|
2901 |
// TODO - Handle decompose. |
|
2902 |
// Exclude commas in expression parsing. |
|
2903 |
return expression(unaryExpression(), ASSIGN.getPrecedence(), noIn); |
|
2904 |
} |
|
2905 |
||
2906 |
/** |
|
2907 |
* Parse an end of line. |
|
2908 |
*/ |
|
2909 |
private void endOfLine() { |
|
2910 |
switch (type) { |
|
2911 |
case SEMICOLON: |
|
2912 |
case EOL: |
|
2913 |
next(); |
|
2914 |
break; |
|
2915 |
case RPAREN: |
|
2916 |
case RBRACKET: |
|
2917 |
case RBRACE: |
|
2918 |
case EOF: |
|
2919 |
break; |
|
2920 |
default: |
|
2921 |
if (last != EOL) { |
|
2922 |
expect(SEMICOLON); |
|
2923 |
} |
|
2924 |
break; |
|
2925 |
} |
|
2926 |
} |
|
2927 |
||
16252
3bfe9b68a0fa
8008648: Lazy JIT scope and callee semantics bugfixes. Broke out wallclock timer.
lagergren
parents:
16245
diff
changeset
|
2928 |
@Override |
3bfe9b68a0fa
8008648: Lazy JIT scope and callee semantics bugfixes. Broke out wallclock timer.
lagergren
parents:
16245
diff
changeset
|
2929 |
public String toString() { |
3bfe9b68a0fa
8008648: Lazy JIT scope and callee semantics bugfixes. Broke out wallclock timer.
lagergren
parents:
16245
diff
changeset
|
2930 |
return "[JavaScript Parsing]"; |
3bfe9b68a0fa
8008648: Lazy JIT scope and callee semantics bugfixes. Broke out wallclock timer.
lagergren
parents:
16245
diff
changeset
|
2931 |
} |
16530
201d682e75f4
8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents:
16525
diff
changeset
|
2932 |
|
17255 | 2933 |
private static void markEval(final LexicalContext lc) { |
17233 | 2934 |
final Iterator<FunctionNode> iter = lc.getFunctions(); |
2935 |
boolean flaggedCurrentFn = false; |
|
2936 |
while (iter.hasNext()) { |
|
2937 |
final FunctionNode fn = iter.next(); |
|
2938 |
if (!flaggedCurrentFn) { |
|
17255 | 2939 |
lc.setFlag(fn, FunctionNode.HAS_EVAL); |
17233 | 2940 |
flaggedCurrentFn = true; |
2941 |
} else { |
|
17255 | 2942 |
lc.setFlag(fn, FunctionNode.HAS_NESTED_EVAL); |
17233 | 2943 |
} |
2944 |
lc.setFlag(lc.getFunctionBody(fn), Block.NEEDS_SCOPE); |
|
2945 |
} |
|
16530
201d682e75f4
8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents:
16525
diff
changeset
|
2946 |
} |
201d682e75f4
8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents:
16525
diff
changeset
|
2947 |
|
17524
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
2948 |
private void prependStatement(final Statement statement) { |
17233 | 2949 |
lc.prependStatement(statement); |
2950 |
} |
|
2951 |
||
17524
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
2952 |
private void appendStatement(final Statement statement) { |
17233 | 2953 |
lc.appendStatement(statement); |
16530
201d682e75f4
8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents:
16525
diff
changeset
|
2954 |
} |
16147 | 2955 |
} |