Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(24)

Side by Side Diff: frog/gen.dart

Issue 9121025: cleanup to Value - fix for StringEscapesTest (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « frog/await/transformation.dart ('k') | frog/lib/corelib.dart » ('j') | frog/member.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698