| OLD | NEW |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 /** | 5 /** |
| 6 * Top level generator object for writing code and keeping track of | 6 * Top level generator object for writing code and keeping track of |
| 7 * dependencies. | 7 * dependencies. |
| 8 * | 8 * |
| 9 * Should have two compilation models, but only one implemented so far. | 9 * Should have two compilation models, but only one implemented so far. |
| 10 * | 10 * |
| (...skipping 28 matching lines...) Expand all Loading... |
| 39 var metaGen = new MethodGenerator(main, null); | 39 var metaGen = new MethodGenerator(main, null); |
| 40 var mainTarget = new Value.type(main.declaringType, main.span); | 40 var mainTarget = new Value.type(main.declaringType, main.span); |
| 41 var mainCall = main.invoke(metaGen, null, mainTarget, Arguments.EMPTY); | 41 var mainCall = main.invoke(metaGen, null, mainTarget, Arguments.EMPTY); |
| 42 main.declaringType.markUsed(); | 42 main.declaringType.markUsed(); |
| 43 | 43 |
| 44 if (options.compileAll) { | 44 if (options.compileAll) { |
| 45 markLibrariesUsed( | 45 markLibrariesUsed( |
| 46 [world.coreimpl, world.corelib, main.declaringType.library]); | 46 [world.coreimpl, world.corelib, main.declaringType.library]); |
| 47 } | 47 } |
| 48 | 48 |
| 49 // These are essentially always used through literals - just include them |
| 50 world.numImplType.markUsed(); |
| 51 world.stringImplType.markUsed(); |
| 52 |
| 49 // Only include isolate-specific code if isolates are used. | 53 // Only include isolate-specific code if isolates are used. |
| 50 if (world.corelib.types['Isolate'].isUsed | 54 if (world.corelib.types['Isolate'].isUsed |
| 51 || world.coreimpl.types['ReceivePortImpl'].isUsed) { | 55 || world.coreimpl.types['ReceivePortImpl'].isUsed) { |
| 52 | 56 |
| 53 // Generate callbacks from JS to isolate code if needed | 57 // Generate callbacks from JS to isolate code if needed |
| 54 if (corejs.useWrap0 || corejs.useWrap1) { | 58 if (corejs.useWrap0 || corejs.useWrap1) { |
| 55 genMethod(world.coreimpl.types['IsolateContext'].getMember('eval')); | 59 genMethod(world.coreimpl.types['IsolateContext'].getMember('eval')); |
| 56 genMethod(world.coreimpl.types['EventLoop'].getMember('run')); | 60 genMethod(world.coreimpl.types['EventLoop'].getMember('run')); |
| 57 } | 61 } |
| 58 | 62 |
| (...skipping 987 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1046 _provideOptionalParamInfo(CodeWriter defWriter) { | 1050 _provideOptionalParamInfo(CodeWriter defWriter) { |
| 1047 if (method is MethodMember) { | 1051 if (method is MethodMember) { |
| 1048 MethodMember meth = method; | 1052 MethodMember meth = method; |
| 1049 if (meth._provideOptionalParamInfo) { | 1053 if (meth._provideOptionalParamInfo) { |
| 1050 var optNames = []; | 1054 var optNames = []; |
| 1051 var optValues = []; | 1055 var optValues = []; |
| 1052 meth.genParameterValues(); | 1056 meth.genParameterValues(); |
| 1053 for (var param in meth.parameters) { | 1057 for (var param in meth.parameters) { |
| 1054 if (param.isOptional) { | 1058 if (param.isOptional) { |
| 1055 optNames.add(param.name); | 1059 optNames.add(param.name); |
| 1060 // TODO(jimhug): Remove this last usage of escapeString. |
| 1056 optValues.add(_escapeString(param.value.code)); | 1061 optValues.add(_escapeString(param.value.code)); |
| 1057 } | 1062 } |
| 1058 } | 1063 } |
| 1059 if (optNames.length > 0) { | 1064 if (optNames.length > 0) { |
| 1060 // TODO(jmesserly): the logic for how to refer to | 1065 // TODO(jmesserly): the logic for how to refer to |
| 1061 // static/instance/top-level members is duplicated all over the place. | 1066 // static/instance/top-level members is duplicated all over the place. |
| 1062 // Badly needs cleanup. | 1067 // Badly needs cleanup. |
| 1063 var start = ''; | 1068 var start = ''; |
| 1064 if (meth.isStatic) { | 1069 if (meth.isStatic) { |
| 1065 if (!meth.declaringType.isTop) { | 1070 if (!meth.declaringType.isTop) { |
| (...skipping 426 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1492 var span = node.test.span; | 1497 var span = node.test.span; |
| 1493 | 1498 |
| 1494 // TODO(jmesserly): do we need to include path/line/column here? | 1499 // TODO(jmesserly): do we need to include path/line/column here? |
| 1495 // It should be captured in the stack trace. | 1500 // It should be captured in the stack trace. |
| 1496 var line = span.file.getLine(span.start) + 1; | 1501 var line = span.file.getLine(span.start) + 1; |
| 1497 var column = span.file.getColumn(line - 1, span.start) + 1; | 1502 var column = span.file.getColumn(line - 1, span.start) + 1; |
| 1498 | 1503 |
| 1499 // TODO(jimhug): Simplify code for creating const values. | 1504 // TODO(jimhug): Simplify code for creating const values. |
| 1500 var args = [ | 1505 var args = [ |
| 1501 test, | 1506 test, |
| 1502 new EvaluatedValue(world.stringType, | 1507 Value.fromString(span.text, node.span), |
| 1503 _escapeString(span.text), '"${_escapeString(span.text)}"', null), | 1508 Value.fromString(span.file.filename, node.span), |
| 1504 new EvaluatedValue(world.stringType, | 1509 Value.fromInt(line, node.span), |
| 1505 _escapeString(span.file.filename), | 1510 Value.fromInt(column, node.span) |
| 1506 '"${_escapeString(span.file.filename)}"', null), | |
| 1507 new EvaluatedValue(world.intType, line, line.toString(), null), | |
| 1508 new EvaluatedValue(world.intType, column, column.toString(), null) | |
| 1509 ]; | 1511 ]; |
| 1510 | 1512 |
| 1511 var tp = world.corelib.topType; | 1513 var tp = world.corelib.topType; |
| 1512 Member f = tp.getMember('_assert'); | 1514 Member f = tp.getMember('_assert'); |
| 1513 var value = f.invoke(this, node, new Value.type(tp, null), | 1515 var value = f.invoke(this, node, new Value.type(tp, null), |
| 1514 new Arguments(null, args)); | 1516 new Arguments(null, args)); |
| 1515 writer.writeln('${value.code};'); | 1517 writer.writeln('${value.code};'); |
| 1516 } | 1518 } |
| 1517 return false; | 1519 return false; |
| 1518 } | 1520 } |
| (...skipping 407 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1926 meth.generator.writeDefinition(w, node); | 1928 meth.generator.writeDefinition(w, node); |
| 1927 return new Value(meth.functionType, w.text, node.span); | 1929 return new Value(meth.functionType, w.text, node.span); |
| 1928 } | 1930 } |
| 1929 | 1931 |
| 1930 visitCallExpression(CallExpression node) { | 1932 visitCallExpression(CallExpression node) { |
| 1931 var target; | 1933 var target; |
| 1932 var position = node.target; | 1934 var position = node.target; |
| 1933 var name = ':call'; | 1935 var name = ':call'; |
| 1934 if (node.target is DotExpression) { | 1936 if (node.target is DotExpression) { |
| 1935 DotExpression dot = node.target; | 1937 DotExpression dot = node.target; |
| 1938 // ???? |
| 1936 if (dot.self is LiteralExpression) { | 1939 if (dot.self is LiteralExpression) { |
| 1937 target = (new ParenExpression(dot.self, dot.self.span)).visit(this); | 1940 target = (new ParenExpression(dot.self, dot.self.span)).visit(this); |
| 1938 } else { | 1941 } else { |
| 1939 target = dot.self.visit(this); | 1942 target = dot.self.visit(this); |
| 1940 } | 1943 } |
| 1941 name = dot.name.name; | 1944 name = dot.name.name; |
| 1942 position = dot.name; | 1945 position = dot.name; |
| 1943 } else if (node.target is VarExpression) { | 1946 } else if (node.target is VarExpression) { |
| 1944 VarExpression varExpr = node.target; | 1947 VarExpression varExpr = node.target; |
| 1945 name = varExpr.name.name; | 1948 name = varExpr.name.name; |
| (...skipping 26 matching lines...) Expand all Loading... |
| 1972 visitBinaryExpression(BinaryExpression node, [bool isVoid = false]) { | 1975 visitBinaryExpression(BinaryExpression node, [bool isVoid = false]) { |
| 1973 final kind = node.op.kind; | 1976 final kind = node.op.kind; |
| 1974 // TODO(jimhug): Ensure these have same semantics as JS! | 1977 // TODO(jimhug): Ensure these have same semantics as JS! |
| 1975 if (kind == TokenKind.AND || kind == TokenKind.OR) { | 1978 if (kind == TokenKind.AND || kind == TokenKind.OR) { |
| 1976 var x = visitTypedValue(node.x, world.nonNullBool); | 1979 var x = visitTypedValue(node.x, world.nonNullBool); |
| 1977 var y = visitTypedValue(node.y, world.nonNullBool); | 1980 var y = visitTypedValue(node.y, world.nonNullBool); |
| 1978 final code = '${x.code} ${node.op} ${y.code}'; | 1981 final code = '${x.code} ${node.op} ${y.code}'; |
| 1979 if (x.isConst && y.isConst) { | 1982 if (x.isConst && y.isConst) { |
| 1980 var value = (kind == TokenKind.AND) | 1983 var value = (kind == TokenKind.AND) |
| 1981 ? x.actualValue && y.actualValue : x.actualValue || y.actualValue; | 1984 ? x.actualValue && y.actualValue : x.actualValue || y.actualValue; |
| 1982 return new EvaluatedValue(world.nonNullBool, value, '$value', | 1985 return Value.fromBool(value, node.span); |
| 1983 node.span); | |
| 1984 } | 1986 } |
| 1985 return new Value(world.nonNullBool, code, node.span); | 1987 return new Value(world.nonNullBool, code, node.span); |
| 1986 } else if (kind == TokenKind.EQ_STRICT || kind == TokenKind.NE_STRICT) { | 1988 } else if (kind == TokenKind.EQ_STRICT || kind == TokenKind.NE_STRICT) { |
| 1987 var x = visitValue(node.x); | 1989 var x = visitValue(node.x); |
| 1988 var y = visitValue(node.y); | 1990 var y = visitValue(node.y); |
| 1989 if (x.isConst && y.isConst) { | 1991 if (x.isConst && y.isConst) { |
| 1990 var xVal = x.actualValue; | 1992 var xVal = x.actualValue; |
| 1991 var yVal = y.actualValue; | 1993 var yVal = y.actualValue; |
| 1992 | 1994 |
| 1993 // cannonicalize strings if they are using different quote chars: | |
| 1994 if (x.type.isString && y.type.isString | |
| 1995 && xVal[0] != yVal[0]) { | |
| 1996 if (xVal[0] == '"') { | |
| 1997 xVal = xVal.substring(1, xVal.length - 1); | |
| 1998 yVal = toDoubleQuote(yVal.substring(1, yVal.length - 1)); | |
| 1999 } else { | |
| 2000 xVal = toDoubleQuote(xVal.substring(1, xVal.length - 1)); | |
| 2001 yVal = yVal.substring(1, yVal.length - 1); | |
| 2002 } | |
| 2003 } | |
| 2004 | |
| 2005 // Note: it is ok to use == and not === here since all of these | 1995 // Note: it is ok to use == and not === here since all of these |
| 2006 // constant comparisons are applied to doubles, bool, or strings. | 1996 // constant comparisons are applied to doubles, bool, or strings. |
| 2007 // We need it for the compile-time evaluator because | 1997 // We need it for the compile-time evaluator because |
| 2008 // (9).toDouble() === 9.0 is false in dartvm. | 1998 // (9).toDouble() === 9.0 is false in dartvm. |
| 2009 var value = kind == TokenKind.EQ_STRICT ? xVal == yVal : xVal != yVal; | 1999 var value = kind == TokenKind.EQ_STRICT ? xVal == yVal : xVal != yVal; |
| 2010 return new EvaluatedValue(world.nonNullBool, value, "$value", | 2000 return Value.fromBool(value, node.span); |
| 2011 node.span); | |
| 2012 } | 2001 } |
| 2013 if (x.code == 'null' || y.code == 'null') { | 2002 if (x.code == 'null' || y.code == 'null') { |
| 2014 // Switching to == ensures that null and undefined are interchangable. | 2003 // Switching to == ensures that null and undefined are interchangable. |
| 2015 final op = node.op.toString().substring(0,2); | 2004 final op = node.op.toString().substring(0,2); |
| 2016 return new Value(world.nonNullBool, '${x.code} $op ${y.code}', | 2005 return new Value(world.nonNullBool, '${x.code} $op ${y.code}', |
| 2017 node.span); | 2006 node.span); |
| 2018 } else { | 2007 } else { |
| 2019 // TODO(jimhug): Resolve issue with undefined and null here. | 2008 // TODO(jimhug): Resolve issue with undefined and null here. |
| 2020 return new Value(world.nonNullBool, '${x.code} ${node.op} ${y.code}', | 2009 return new Value(world.nonNullBool, '${x.code} ${node.op} ${y.code}', |
| 2021 node.span); | 2010 node.span); |
| (...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2214 case TokenKind.INCR: | 2203 case TokenKind.INCR: |
| 2215 case TokenKind.DECR: | 2204 case TokenKind.DECR: |
| 2216 if (value.type.isNum) { | 2205 if (value.type.isNum) { |
| 2217 return new Value(value.type, '${node.op}${value.code}', node.span); | 2206 return new Value(value.type, '${node.op}${value.code}', node.span); |
| 2218 } else { | 2207 } else { |
| 2219 // ++x becomes x += 1 | 2208 // ++x becomes x += 1 |
| 2220 // --x becomes x -= 1 | 2209 // --x becomes x -= 1 |
| 2221 // TODO(jimhug): Confirm that --x becomes x -= 1 as it is in VM. | 2210 // TODO(jimhug): Confirm that --x becomes x -= 1 as it is in VM. |
| 2222 var kind = (TokenKind.INCR == node.op.kind ? | 2211 var kind = (TokenKind.INCR == node.op.kind ? |
| 2223 TokenKind.ADD : TokenKind.SUB); | 2212 TokenKind.ADD : TokenKind.SUB); |
| 2224 var operand = new LiteralExpression(1, | 2213 // TODO(jimhug): Shouldn't need a full-expression here. |
| 2225 new TypeReference(node.span, world.numType), '1', node.span); | 2214 var operand = new LiteralExpression(Value.fromInt(1, node.span), |
| 2215 node.span); |
| 2226 | 2216 |
| 2227 var assignValue = _visitAssign(kind, node.self, operand, node, null); | 2217 var assignValue = _visitAssign(kind, node.self, operand, node, null); |
| 2228 return new Value(assignValue.type, '(${assignValue.code})', | 2218 return new Value(assignValue.type, '(${assignValue.code})', |
| 2229 node.span); | 2219 node.span); |
| 2230 } | 2220 } |
| 2231 case TokenKind.NOT: | 2221 case TokenKind.NOT: |
| 2232 // TODO(jimhug): Issue #359 seeks to clarify this behavior. | 2222 // TODO(jimhug): Issue #359 seeks to clarify this behavior. |
| 2233 if (value.type.isBool && value.isConst) { | 2223 if (value.type.isBool && value.isConst) { |
| 2234 var newVal = !value.actualValue; | 2224 var newVal = !value.actualValue; |
| 2235 return new EvaluatedValue(value.type, newVal, '${newVal}', node.span); | 2225 return new EvaluatedValue(value.type, newVal, '${newVal}', node.span); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2270 visitPostfixExpression(PostfixExpression node, [bool isVoid = false]) { | 2260 visitPostfixExpression(PostfixExpression node, [bool isVoid = false]) { |
| 2271 var value = visitValue(node.body); | 2261 var value = visitValue(node.body); |
| 2272 if (value.type.isNum && !value.isFinal) { | 2262 if (value.type.isNum && !value.isFinal) { |
| 2273 return new Value(value.type, '${value.code}${node.op}', node.span); | 2263 return new Value(value.type, '${value.code}${node.op}', node.span); |
| 2274 } | 2264 } |
| 2275 | 2265 |
| 2276 // x++ is equivalent to (t = x, x = t + 1, t), where we capture all temps | 2266 // x++ is equivalent to (t = x, x = t + 1, t), where we capture all temps |
| 2277 // needed to evaluate x so we're not evaluating multiple times. Likewise, | 2267 // needed to evaluate x so we're not evaluating multiple times. Likewise, |
| 2278 // x-- is equivalent to (t = x, x = t - 1, t). | 2268 // x-- is equivalent to (t = x, x = t - 1, t). |
| 2279 var kind = (TokenKind.INCR == node.op.kind) ? TokenKind.ADD : TokenKind.SUB; | 2269 var kind = (TokenKind.INCR == node.op.kind) ? TokenKind.ADD : TokenKind.SUB; |
| 2280 var operand = new LiteralExpression(1, | 2270 // TODO(jimhug): Shouldn't need a full-expression here. |
| 2281 new TypeReference(node.span, world.numType), '1', node.span); | 2271 var operand = new LiteralExpression(Value.fromInt(1, node.span), |
| 2272 node.span); |
| 2282 | 2273 |
| 2283 // Use _visitAssign to do most of the work, but save the right side in a | 2274 // Use _visitAssign to do most of the work, but save the right side in a |
| 2284 // temporary variable if needed. | 2275 // temporary variable if needed. |
| 2285 // TODO(jmesserly): I don't like passing function args like this, but the | 2276 // TODO(jmesserly): I don't like passing function args like this, but the |
| 2286 // alternative is duplicating most of the _visitAssign logic. Needs cleanup. | 2277 // alternative is duplicating most of the _visitAssign logic. Needs cleanup. |
| 2287 var tmpleft = null, left = null; | 2278 var tmpleft = null, left = null; |
| 2288 var ret = _visitAssign(kind, node.body, operand, node, (l) { | 2279 var ret = _visitAssign(kind, node.body, operand, node, (l) { |
| 2289 if (isVoid) { | 2280 if (isVoid) { |
| 2290 // No need for a temp if we're throwing away the result. | 2281 // No need for a temp if we're throwing away the result. |
| 2291 return l; | 2282 return l; |
| (...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2523 } | 2514 } |
| 2524 | 2515 |
| 2525 visitThisExpression(ThisExpression node) { | 2516 visitThisExpression(ThisExpression node) { |
| 2526 return _makeThisValue(node); | 2517 return _makeThisValue(node); |
| 2527 } | 2518 } |
| 2528 | 2519 |
| 2529 visitSuperExpression(SuperExpression node) { | 2520 visitSuperExpression(SuperExpression node) { |
| 2530 return _makeSuperValue(node); | 2521 return _makeSuperValue(node); |
| 2531 } | 2522 } |
| 2532 | 2523 |
| 2533 visitNullExpression(NullExpression node) { | 2524 visitLiteralExpression(LiteralExpression node) { |
| 2534 // TODO(jimhug): should be passing node.span | 2525 return node.value; |
| 2535 // TODO(jimhug): Can we do better than var for the type? | |
| 2536 return new EvaluatedValue(world.varType, null, 'null', null); | |
| 2537 } | 2526 } |
| 2538 | 2527 |
| 2539 _isUnaryIncrement(Expression item) { | 2528 _isUnaryIncrement(Expression item) { |
| 2540 if (item is UnaryExpression) { | 2529 if (item is UnaryExpression) { |
| 2541 UnaryExpression u = item; | 2530 UnaryExpression u = item; |
| 2542 return u.op.kind == TokenKind.INCR || u.op.kind == TokenKind.DECR; | 2531 return u.op.kind == TokenKind.INCR || u.op.kind == TokenKind.DECR; |
| 2543 } else { | 2532 } else { |
| 2544 return false; | 2533 return false; |
| 2545 } | 2534 } |
| 2546 } | 2535 } |
| 2547 | 2536 |
| 2548 visitLiteralExpression(LiteralExpression node) { | 2537 visitStringInterpExpression(StringInterpExpression node) { |
| 2549 // All Literal types are filled in at parse time, so no need to resolve. | 2538 var items = []; |
| 2550 var type = node.type.type; | 2539 for (var item in node.pieces) { |
| 2551 assert(type != null); | 2540 var val = visitValue(item); |
| 2552 | 2541 val.invoke(this, 'toString', item, Arguments.EMPTY); |
| 2553 if (node.value is List) { | 2542 // TODO(jimhug): Ensure this solves all precedence problems. |
| 2554 var items = []; | 2543 // TODO(jmesserly): We could be smarter about prefix/postfix, but we'd |
| 2555 for (var item in node.value) { | 2544 // need to know if it will compile to a ++ or to some sort of += form. |
| 2556 var val = visitValue(item); | 2545 var code = val.code; |
| 2557 val.invoke(this, 'toString', item, Arguments.EMPTY); | 2546 if (_expressionNeedsParens(item)) { |
| 2558 | 2547 code = '(${code})'; |
| 2559 // TODO(jimhug): Ensure this solves all precedence problems. | |
| 2560 // TODO(jmesserly): We could be smarter about prefix/postfix, but we'd | |
| 2561 // need to know if it will compile to a ++ or to some sort of += form. | |
| 2562 var code = val.code; | |
| 2563 if (_expressionNeedsParens(item)) { | |
| 2564 code = '(${code})'; | |
| 2565 } | |
| 2566 // No need to concat empty strings except the first. | |
| 2567 if (items.length == 0 || (code != "''" && code != '""')) { | |
| 2568 items.add(code); | |
| 2569 } | |
| 2570 } | 2548 } |
| 2571 return new Value(type, '(${Strings.join(items, " + ")})', node.span); | 2549 // No need to concat empty strings except the first. |
| 2572 } | 2550 if (items.length == 0 || (code != "''" && code != '""')) { |
| 2573 | 2551 items.add(code); |
| 2574 if (node.value is num) { | |
| 2575 world.numImplType.markUsed(); | |
| 2576 } | |
| 2577 | |
| 2578 var text = node.text; | |
| 2579 // TODO(jimhug): Confirm that only strings need possible translation | |
| 2580 if (type.isString) { | |
| 2581 world.stringImplType.markUsed(); | |
| 2582 | |
| 2583 if (text.startsWith('@')) { | |
| 2584 text = _escapeString(parseStringLiteral(text)); | |
| 2585 text = '"$text"'; | |
| 2586 } else if (isMultilineString(text)) { | |
| 2587 // convert multi-line strings into single-line | |
| 2588 text = parseStringLiteral(text); | |
| 2589 // TODO(jimhug): What about \r? | |
| 2590 text = text.replaceAll('\n', '\\n'); | |
| 2591 text = toDoubleQuote(text); | |
| 2592 text = '"$text"'; | |
| 2593 } | |
| 2594 if (text !== node.text) { | |
| 2595 node.value = text; | |
| 2596 node.text = text; | |
| 2597 } | 2552 } |
| 2598 } | 2553 } |
| 2599 | 2554 return new Value(world.stringType, '(${Strings.join(items, " + ")})', |
| 2600 // TODO(jimhug): Should pass node.span - but that breaks something... | 2555 node.span); |
| 2601 return new EvaluatedValue(type, node.value, node.text, null); | |
| 2602 } | 2556 } |
| 2603 } | 2557 } |
| 2604 | 2558 |
| 2605 | 2559 |
| 2606 // TODO(jmesserly): move this into its own file? | 2560 // TODO(jmesserly): move this into its own file? |
| 2607 class Arguments { | 2561 class Arguments { |
| 2608 static Arguments _empty; | 2562 static Arguments _empty; |
| 2609 static Arguments get EMPTY() { | 2563 static Arguments get EMPTY() { |
| 2610 if (_empty == null) { | 2564 if (_empty == null) { |
| 2611 _empty = new Arguments(null, []); | 2565 _empty = new Arguments(null, []); |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2715 result.add(new Value(world.varType, '\$$i', null, /*needsTemp:*/false)); | 2669 result.add(new Value(world.varType, '\$$i', null, /*needsTemp:*/false)); |
| 2716 } | 2670 } |
| 2717 for (int i = bareCount; i < length; i++) { | 2671 for (int i = bareCount; i < length; i++) { |
| 2718 var name = getName(i); | 2672 var name = getName(i); |
| 2719 if (name == null) name = '\$$i'; | 2673 if (name == null) name = '\$$i'; |
| 2720 result.add(new Value(world.varType, name, null, /*needsTemp:*/false)); | 2674 result.add(new Value(world.varType, name, null, /*needsTemp:*/false)); |
| 2721 } | 2675 } |
| 2722 return new Arguments(nodes, result); | 2676 return new Arguments(nodes, result); |
| 2723 } | 2677 } |
| 2724 } | 2678 } |
| OLD | NEW |