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

Side by Side Diff: frog/gen.dart

Issue 8538019: incremental progress on Value (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: rebased Created 9 years, 1 month 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 472 matching lines...) Expand 10 before | Expand all | Expand 10 after
483 // (This lookup might report errors, which is a bit strange. 483 // (This lookup might report errors, which is a bit strange.
484 // But probably harmless since we have to pay for the lookup anyway.) 484 // But probably harmless since we have to pay for the lookup anyway.)
485 final type = enclosingMethod.method.declaringType; 485 final type = enclosingMethod.method.declaringType;
486 if (type.library.lookup(name, null) != null) return true; 486 if (type.library.lookup(name, null) != null) return true;
487 487
488 // Nobody else needs this name. It's safe to reuse. 488 // Nobody else needs this name. It's safe to reuse.
489 return false; 489 return false;
490 } 490 }
491 491
492 492
493 Value create(String name, Type type, Node location, 493 Value create(String name, Type type, SourceSpan span,
494 [bool isParameter = false]) { 494 [bool isParameter = false]) {
495 495
496 var jsName = world.toJsIdentifier(name); 496 var jsName = world.toJsIdentifier(name);
497 if (_vars.containsKey(name)) { 497 if (_vars.containsKey(name)) {
498 if (location != null) { 498 world.error('duplicate name "$name"', span);
499 world.error('duplicate name "$name"', location.span);
500 } else {
501 world.internalError('conflict with temporary name "$name"');
502 }
503 } 499 }
504 500
505 // Make sure variables don't shadow any names we might need to access. 501 // Make sure variables don't shadow any names we might need to access.
506 if (!isParameter) { 502 if (!isParameter) {
507 int index = 0; 503 int index = 0;
508 while (_isDefinedInParent(jsName)) { 504 while (_isDefinedInParent(jsName)) {
509 jsName = '$name${index++}'; 505 jsName = '$name${index++}';
510 } 506 }
511 } 507 }
512 508
513 var ret = new Value(type, jsName, location != null ? location.span : null, 509 var ret = new Value(type, jsName, span, false);
514 false, false);
515 _vars[name] = ret; 510 _vars[name] = ret;
516 return ret; 511 return ret;
517 } 512 }
518 513
519 Value declareParameter(Parameter p) { 514 Value declareParameter(Parameter p) {
520 return create(p.name, p.type, p.definition, isParameter:true); 515 return create(p.name, p.type, p.definition.span, isParameter:true);
521 } 516 }
522 517
523 /** Declares a variable in the current scope for this identifier. */ 518 /** Declares a variable in the current scope for this identifier. */
524 Value declare(DeclaredIdentifier id) { 519 Value declare(DeclaredIdentifier id) {
525 var type = enclosingMethod.method.resolveType(id.type, false); 520 var type = enclosingMethod.method.resolveType(id.type, false);
526 return create(id.name.name, type, id); 521 return create(id.name.name, type, id.span);
527 } 522 }
528 523
529 /** 524 /**
530 * Finds the first lexically enclosing catch block, if any, and returns its 525 * Finds the first lexically enclosing catch block, if any, and returns its
531 * exception variable. 526 * exception variable.
532 */ 527 */
533 Value getRethrow() { 528 Value getRethrow() {
534 var scope = this; 529 var scope = this;
535 while (scope.rethrow == null && scope.parent != null) { 530 while (scope.rethrow == null && scope.parent != null) {
536 scope = scope.parent; 531 scope = scope.parent;
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
570 if (enclosingMethod != null) { 565 if (enclosingMethod != null) {
571 _scope = new BlockScope(this, enclosingMethod._scope); 566 _scope = new BlockScope(this, enclosingMethod._scope);
572 captures = new Set(); 567 captures = new Set();
573 } else { 568 } else {
574 _scope = new BlockScope(this, null); 569 _scope = new BlockScope(this, null);
575 } 570 }
576 // For named lambdas, add the name to this scope so we can call it 571 // For named lambdas, add the name to this scope so we can call it
577 // recursively. 572 // recursively.
578 if (enclosingMethod != null && method.name != '') { 573 if (enclosingMethod != null && method.name != '') {
579 MethodMember m = method; // lambdas must be MethodMembers 574 MethodMember m = method; // lambdas must be MethodMembers
580 _scope.create(m.name, m.functionType, m.definition); 575 _scope.create(m.name, m.functionType, m.definition.span);
581 } 576 }
582 _usedTemps = new Set(); 577 _usedTemps = new Set();
583 _freeTemps = []; 578 _freeTemps = [];
584 } 579 }
585 580
586 Library get library() => method.library; 581 Library get library() => method.library;
587 582
588 // TODO(jimhug): Where does this really belong? 583 // TODO(jimhug): Where does this really belong?
589 MemberSet findMembers(String name) { 584 MemberSet findMembers(String name) {
590 return library._findMembers(name); 585 return library._findMembers(name);
591 } 586 }
592 587
593 bool get isClosure() => (enclosingMethod != null); 588 bool get isClosure() => (enclosingMethod != null);
594 589
595 bool get isStatic() => method.isStatic; 590 bool get isStatic() => method.isStatic;
596 591
597 Value getTemp(Value value) { 592 Value getTemp(Value value) {
598 return value.needsTemp ? forceTemp(value) : value; 593 return value.needsTemp ? forceTemp(value) : value;
599 } 594 }
600 595
601 Value forceTemp(Value value) { 596 Value forceTemp(Value value) {
602 String name; 597 String name;
603 if (_freeTemps.length > 0) { 598 if (_freeTemps.length > 0) {
604 name = _freeTemps.removeLast(); 599 name = _freeTemps.removeLast();
605 } else { 600 } else {
606 name = '\$' + _usedTemps.length; 601 name = '\$' + _usedTemps.length;
607 } 602 }
608 _usedTemps.add(name); 603 _usedTemps.add(name);
609 return new Value(value.type, name, value.span, 604 return new Value(value.type, name, value.span, /*needsTemp:*/false);
610 /*isSuper:*/false, /*needsTemp:*/false);
611 } 605 }
612 606
613 Value assignTemp(Value tmp, Value v) { 607 Value assignTemp(Value tmp, Value v) {
614 if (tmp == v) { 608 if (tmp == v) {
615 return v; 609 return v;
616 } else { 610 } else {
617 // TODO(jmesserly): we should mark this returned value with the temp 611 // TODO(jmesserly): we should mark this returned value with the temp
618 // somehow, so getTemp will reuse it instead of allocating a new one. 612 // somehow, so getTemp will reuse it instead of allocating a new one.
619 return new Value(v.type, '(${tmp.code} = ${v.code})', v.span); 613 return new Value(v.type, '(${tmp.code} = ${v.code})', v.span);
620 } 614 }
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after
803 var field = method.declaringType.getMember(p.name); 797 var field = method.declaringType.getMember(p.name);
804 if (field == null) { 798 if (field == null) {
805 world.error('bad this parameter - no matching field', 799 world.error('bad this parameter - no matching field',
806 p.definition.span); 800 p.definition.span);
807 } 801 }
808 if (!field.isField) { 802 if (!field.isField) {
809 world.error('"this.${p.name}" does not refer to a field', 803 world.error('"this.${p.name}" does not refer to a field',
810 p.definition.span); 804 p.definition.span);
811 } 805 }
812 var paramValue = new Value(field.returnType, p.name, 806 var paramValue = new Value(field.returnType, p.name,
813 p.definition.span, false, false); 807 p.definition.span, false);
814 _paramCode.add(paramValue.code); 808 _paramCode.add(paramValue.code);
815 809
816 initializers.add('this.${field.jsname} = ${paramValue.code};'); 810 initializers.add('this.${field.jsname} = ${paramValue.code};');
817 initializedFields.add(p.name); 811 initializedFields.add(p.name);
818 } else { 812 } else {
819 var paramValue = _scope.declareParameter(p); 813 var paramValue = _scope.declareParameter(p);
820 _paramCode.add(paramValue.code); 814 _paramCode.add(paramValue.code);
821 } 815 }
822 } 816 }
823 817
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after
1065 var value = visitValue(node.values[i]); 1059 var value = visitValue(node.values[i]);
1066 if (isFinal) { 1060 if (isFinal) {
1067 if (value == null) { 1061 if (value == null) {
1068 world.error('no value specified for final variable', node.span); 1062 world.error('no value specified for final variable', node.span);
1069 } else { 1063 } else {
1070 // TODO(jimhug): Mark inferred types as special for correct errors. 1064 // TODO(jimhug): Mark inferred types as special for correct errors.
1071 if (thisType.isVar) thisType = value.type; 1065 if (thisType.isVar) thisType = value.type;
1072 } 1066 }
1073 } 1067 }
1074 1068
1075 var val = _scope.create(name, thisType, node.names[i]); 1069 var val = _scope.create(name, thisType, node.names[i].span);
1076 1070
1077 if (value == null) { 1071 if (value == null) {
1078 writer.write('${val.code}'); 1072 writer.write('${val.code}');
1079 } else { 1073 } else {
1080 value = value.convertTo(this, type, node.values[i]); 1074 value = value.convertTo(this, type, node.values[i]);
1081 writer.write('${val.code} = ${value.code}'); 1075 writer.write('${val.code} = ${value.code}');
1082 } 1076 }
1083 } 1077 }
1084 writer.writeln(';'); 1078 writer.writeln(';');
1085 return false; 1079 return false;
1086 1080
1087 } 1081 }
1088 1082
1089 bool visitFunctionDefinition(FunctionDefinition node) { 1083 bool visitFunctionDefinition(FunctionDefinition node) {
1090 var name = world.toJsIdentifier(node.name.name); 1084 var name = world.toJsIdentifier(node.name.name);
1091 1085
1092 var meth = _makeLambdaMethod(name, node); 1086 var meth = _makeLambdaMethod(name, node);
1093 1087
1094 // TODO(jimhug): Pass js name into writeDefinition? 1088 // TODO(jimhug): Pass js name into writeDefinition?
1095 var funcValue = _scope.create(name, meth.functionType, method.definition); 1089 var funcValue =
1090 _scope.create(name, meth.functionType, method.definition.span);
1096 meth.generator.writeDefinition(writer, null); 1091 meth.generator.writeDefinition(writer, null);
1097 return false; 1092 return false;
1098 } 1093 }
1099 1094
1100 /** 1095 /**
1101 * Returns true indicating that normal control-flow is interrupted by 1096 * Returns true indicating that normal control-flow is interrupted by
1102 * this statement. (This could be a return, break, throw, or continue.) 1097 * this statement. (This could be a return, break, throw, or continue.)
1103 */ 1098 */
1104 bool visitReturnStatement(ReturnStatement node) { 1099 bool visitReturnStatement(ReturnStatement node) {
1105 if (node.value == null) { 1100 if (node.value == null) {
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
1234 return false; 1229 return false;
1235 } 1230 }
1236 1231
1237 bool visitForInStatement(ForInStatement node) { 1232 bool visitForInStatement(ForInStatement node) {
1238 // TODO(jimhug): visitValue and other cleanups here. 1233 // TODO(jimhug): visitValue and other cleanups here.
1239 var itemType = method.resolveType(node.item.type, false); 1234 var itemType = method.resolveType(node.item.type, false);
1240 var itemName = node.item.name.name; 1235 var itemName = node.item.name.name;
1241 var list = node.list.visit(this); 1236 var list = node.list.visit(this);
1242 _pushBlock(/*reentrant:*/true); 1237 _pushBlock(/*reentrant:*/true);
1243 // TODO(jimhug): Check that itemType matches list members... 1238 // TODO(jimhug): Check that itemType matches list members...
1244 var item = _scope.create(itemName, itemType, node.item.name); 1239 var item = _scope.create(itemName, itemType, node.item.name.span);
1245 Value listVar = list; 1240 Value listVar = list;
1246 if (list.needsTemp) { 1241 if (list.needsTemp) {
1247 listVar = _scope.create('\$list', list.type, null); 1242 listVar = _scope.create('\$list', list.type, null);
1248 writer.writeln('var ${listVar.code} = ${list.code};'); 1243 writer.writeln('var ${listVar.code} = ${list.code};');
1249 } 1244 }
1250 1245
1251 // Special path for list for readability and perf optimization. 1246 // Special path for list for readability and perf optimization.
1252 if (list.type.isList) { 1247 if (list.type.isList) {
1253 var tmpi = _scope.create('\$i', world.numType, null); 1248 var tmpi = _scope.create('\$i', world.numType, null);
1254 writer.enterBlock('for (var ${tmpi.code} = 0;' + 1249 writer.enterBlock('for (var ${tmpi.code} = 0;' +
1255 '${tmpi.code} < ${listVar.code}.length; ${tmpi.code}++) {'); 1250 '${tmpi.code} < ${listVar.code}.length; ${tmpi.code}++) {');
1256 var value = listVar.invoke(this, '\$index', node.list, 1251 var value = listVar.invoke(this, '\$index', node.list,
1257 new Arguments(null, [tmpi])); 1252 new Arguments(null, [tmpi]));
1258 writer.writeln('var ${item.code} = ${value.code};'); 1253 writer.writeln('var ${item.code} = ${value.code};');
1259 } else { 1254 } else {
1260 _pushBlock(); 1255 _pushBlock();
1261 // Needed to tell the runtime that we're doing this behind its back. 1256 var iterator = list.invoke(this, 'iterator', node.list, Arguments.EMPTY);
1262 var c = world.coreimpl.types['ListIterator'].getConstructor('');
1263 c.invoke(this, node, null,
1264 new Arguments(null, [new Value(null, 'l', node.list.span)]));
1265
1266 var iterator = list.invoke(this, 'iterator', node.list,
1267 Arguments.EMPTY);
1268 var tmpi = _scope.create('\$i', iterator.type, null); 1257 var tmpi = _scope.create('\$i', iterator.type, null);
1269 1258
1270 var hasNext = tmpi.invoke(this, 'hasNext', node.list, Arguments.EMPTY); 1259 var hasNext = tmpi.invoke(this, 'hasNext', node.list, Arguments.EMPTY);
1271 var next = tmpi.invoke(this, 'next', node.list, Arguments.EMPTY); 1260 var next = tmpi.invoke(this, 'next', node.list, Arguments.EMPTY);
1272 1261
1273 writer.enterBlock( 1262 writer.enterBlock(
1274 'for (var ${tmpi.code} = ${iterator.code}; ${hasNext.code}; ) {'); 1263 'for (var ${tmpi.code} = ${iterator.code}; ${hasNext.code}; ) {');
1275 writer.writeln('var ${item.code} = ${next.code};'); 1264 writer.writeln('var ${item.code} = ${next.code};');
1276 } 1265 }
1277 1266
1278 visitStatementsInBlock(node.body); 1267 visitStatementsInBlock(node.body);
1279 writer.exitBlock('}'); 1268 writer.exitBlock('}');
1280 _popBlock(); 1269 _popBlock();
1281 return false; 1270 return false;
1282 } 1271 }
1283 1272
1284 void _genToDartException(String ex, Node node) { 1273 void _genToDartException(String ex, Node node) {
1285 var types = const [ 1274 var types = const [
1286 'NullPointerException', 'ObjectNotClosureException', 1275 'NullPointerException', 'ObjectNotClosureException',
1287 'NoSuchMethodException', 'StackOverflowException']; 1276 'NoSuchMethodException', 'StackOverflowException'];
1288 var target = new Value(null, 'this', node.span); 1277 // TODO(jimhug): This is an egregious hack to get some toStrings called.
Jennifer Messerly 2011/11/12 00:39:58 Yeah, we probably just want to invoke all toString
1278 var target = new Value(world.varType, 'this', node.span);
1289 for (var name in types) { 1279 for (var name in types) {
1290 world.corelib.types[name].markUsed(); 1280 world.corelib.types[name].markUsed();
1291 world.corelib.types[name].members['toString'].invoke( 1281 world.corelib.types[name].members['toString'].invoke(
1292 this, node, target, Arguments.EMPTY); 1282 this, node, target, Arguments.EMPTY);
1293 } 1283 }
1294 writer.writeln('$ex = \$toDartException($ex);'); 1284 writer.writeln('$ex = \$toDartException($ex);');
1295 world.gen.corejs.useToDartException = true; 1285 world.gen.corejs.useToDartException = true;
1296 } 1286 }
1297 1287
1298 bool visitTryStatement(TryStatement node) { 1288 bool visitTryStatement(TryStatement node) {
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after
1496 world.warning('not allowed in static method', node.span); 1486 world.warning('not allowed in static method', node.span);
1497 } 1487 }
1498 } 1488 }
1499 1489
1500 _makeSuperValue(Node node) { 1490 _makeSuperValue(Node node) {
1501 var parentType = method.declaringType.parent; 1491 var parentType = method.declaringType.parent;
1502 _checkNonStatic(node); 1492 _checkNonStatic(node);
1503 if (parentType == null) { 1493 if (parentType == null) {
1504 world.error('no super class', node.span); 1494 world.error('no super class', node.span);
1505 } 1495 }
1506 return new Value(parentType, 'this', node.span, 1496 // TODO(jimhug): Replace with SuperValue.
Jennifer Messerly 2011/11/12 00:39:58 +1
1507 /*isSuper:*/true, /*needsTemp:*/false); 1497 var ret = new Value(parentType, 'this', node.span, false);
1498 ret.isSuper = true;
1499 return ret;
1508 } 1500 }
1509 1501
1510 _getOutermostMethod() { 1502 _getOutermostMethod() {
1511 var result = this; 1503 var result = this;
1512 while (result.enclosingMethod != null) { 1504 while (result.enclosingMethod != null) {
1513 result = result.enclosingMethod; 1505 result = result.enclosingMethod;
1514 } 1506 }
1515 return result; 1507 return result;
1516 } 1508 }
1517 1509
(...skipping 11 matching lines...) Expand all
1529 /** 1521 /**
1530 * Creates a reference to the enclosing type ('this') that can be used within 1522 * Creates a reference to the enclosing type ('this') that can be used within
1531 * closures. 1523 * closures.
1532 */ 1524 */
1533 Value _makeThisValue(Node node) { 1525 Value _makeThisValue(Node node) {
1534 if (enclosingMethod != null) { 1526 if (enclosingMethod != null) {
1535 var outermostMethod = _getOutermostMethod(); 1527 var outermostMethod = _getOutermostMethod();
1536 outermostMethod._checkNonStatic(node); 1528 outermostMethod._checkNonStatic(node);
1537 outermostMethod.needsThis = true; 1529 outermostMethod.needsThis = true;
1538 return new Value(outermostMethod.method.declaringType, '\$this', 1530 return new Value(outermostMethod.method.declaringType, '\$this',
1539 node != null ? node.span : null, /*isSuper:*/false, /*needsTemp:*/false) ; 1531 node != null ? node.span : null, /*needsTemp:*/false);
1540 } else { 1532 } else {
1541 _checkNonStatic(node); 1533 _checkNonStatic(node);
1542 return new Value(method.declaringType, 'this', node != null ? node.span : null, 1534 return new Value(method.declaringType, 'this', node != null ? node.span : null,
1543 /*isSuper:*/false, /*needsTemp:*/false); 1535 /*needsTemp:*/false);
1544 } 1536 }
1545 } 1537 }
1546 1538
1547 // ******************* Expressions ******************* 1539 // ******************* Expressions *******************
1548 visitLambdaExpression(LambdaExpression node) { 1540 visitLambdaExpression(LambdaExpression node) {
1549 var name = ''; 1541 var name = '';
1550 if (node.func.name != null) { 1542 if (node.func.name != null) {
1551 name = world.toJsIdentifier(node.func.name.name); 1543 name = world.toJsIdentifier(node.func.name.name);
1552 } 1544 }
1553 1545
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
1597 // TODO(jimhug): Ensure these have same semantics as JS! 1589 // TODO(jimhug): Ensure these have same semantics as JS!
1598 if (kind == TokenKind.AND || kind == TokenKind.OR) { 1590 if (kind == TokenKind.AND || kind == TokenKind.OR) {
1599 var x = visitValue(node.x); 1591 var x = visitValue(node.x);
1600 var y = visitValue(node.y); 1592 var y = visitValue(node.y);
1601 final code = '${x.code} ${node.op} ${y.code}'; 1593 final code = '${x.code} ${node.op} ${y.code}';
1602 if (x.isConst && y.isConst) { 1594 if (x.isConst && y.isConst) {
1603 var value = (kind == TokenKind.AND) 1595 var value = (kind == TokenKind.AND)
1604 ? x.actualValue && y.actualValue : x.actualValue || y.actualValue; 1596 ? x.actualValue && y.actualValue : x.actualValue || y.actualValue;
1605 return new EvaluatedValue(x.type, value, '$value', node.span); 1597 return new EvaluatedValue(x.type, value, '$value', node.span);
1606 } 1598 }
1607 return new Value(null, code, node.span); 1599 var ret = new Value(Type.union(x.type, y.type), code, node.span);
1600 return ret.convertToNonNullBool(this, node);
1608 } else if (kind == TokenKind.EQ_STRICT || kind == TokenKind.NE_STRICT) { 1601 } else if (kind == TokenKind.EQ_STRICT || kind == TokenKind.NE_STRICT) {
1609 var x = visitValue(node.x); 1602 var x = visitValue(node.x);
1610 var y = visitValue(node.y); 1603 var y = visitValue(node.y);
1611 if (x.isConst && y.isConst) { 1604 if (x.isConst && y.isConst) {
1612 var value = kind == TokenKind.EQ_STRICT 1605 var value = kind == TokenKind.EQ_STRICT
1613 // Note: it is ok to use == and not === here since all of these 1606 // Note: it is ok to use == and not === here since all of these
1614 // constant comparisons are applied to doubles, bool, or strings. 1607 // constant comparisons are applied to doubles, bool, or strings.
1615 // We need it for the compile-time evaluator because 1608 // We need it for the compile-time evaluator because
1616 // (9).toDouble() === 9.0 is false in dartvm. 1609 // (9).toDouble() === 9.0 is false in dartvm.
1617 ? x.actualValue == y.actualValue : x.actualValue != y.actualValue; 1610 ? x.actualValue == y.actualValue : x.actualValue != y.actualValue;
1618 return new EvaluatedValue(world.boolType, value, "$value", node.span); 1611 return new EvaluatedValue(world.boolType, value, "$value", node.span);
1619 } 1612 }
1620 if (x.code == 'null' || y.code == 'null') { 1613 if (x.code == 'null' || y.code == 'null') {
1621 // Switching to == ensures that null and undefined are interchangable. 1614 // Switching to == ensures that null and undefined are interchangable.
1622 final op = node.op.toString().substring(0,2); 1615 final op = node.op.toString().substring(0,2);
1623 return new Value(null, '${x.code} $op ${y.code}', node.span); 1616 return new Value(world.boolType, '${x.code} $op ${y.code}', node.span);
Jennifer Messerly 2011/11/12 00:39:58 it's funny, I caught this one too. But it's now it
1624 } else { 1617 } else {
1625 // TODO(jimhug): Resolve issue with undefined and null here. 1618 // TODO(jimhug): Resolve issue with undefined and null here.
1626 return new Value(null, '${x.code} ${node.op} ${y.code}', node.span); 1619 return new Value(world.boolType, '${x.code} ${node.op} ${y.code}',
1620 node.span);
1627 } 1621 }
1628 } 1622 }
1629 1623
1630 final assignKind = TokenKind.kindFromAssign(node.op.kind); 1624 final assignKind = TokenKind.kindFromAssign(node.op.kind);
1631 if (assignKind == -1) { 1625 if (assignKind == -1) {
1632 final x = visitValue(node.x); 1626 final x = visitValue(node.x);
1633 final y = visitValue(node.y); 1627 final y = visitValue(node.y);
1634 var name = TokenKind.binaryMethodName(node.op.kind); 1628 var name = TokenKind.binaryMethodName(node.op.kind);
1635 if (node.op.kind == TokenKind.NE) { 1629 if (node.op.kind == TokenKind.NE) {
1636 name = '\$ne'; 1630 name = '\$ne';
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
1682 1676
1683 if (x == null) { 1677 if (x == null) {
1684 // Look for a setter in the class 1678 // Look for a setter in the class
1685 var members = method.declaringType.resolveMember(name); 1679 var members = method.declaringType.resolveMember(name);
1686 if (members != null) { 1680 if (members != null) {
1687 x = _makeThisOrType(position.span); 1681 x = _makeThisOrType(position.span);
1688 if (kind == 0) { 1682 if (kind == 0) {
1689 return x.set_(this, name, position, y); 1683 return x.set_(this, name, position, y);
1690 } else if (!members.treatAsField || members.containsMethods) { 1684 } else if (!members.treatAsField || members.containsMethods) {
1691 var right = x.get_(this, name, position); 1685 var right = x.get_(this, name, position);
1692 //var right = members._get(this, position, x);
1693 right = captureOriginal(right); 1686 right = captureOriginal(right);
1694 y = right.invoke(this, TokenKind.binaryMethodName(kind), 1687 y = right.invoke(this, TokenKind.binaryMethodName(kind),
1695 position, new Arguments(null, [y])); 1688 position, new Arguments(null, [y]));
1696 return x.set_(this, name, position, y); 1689 return x.set_(this, name, position, y);
1697 } else { 1690 } else {
1698 x = x.get_(this, name, position); 1691 x = x.get_(this, name, position);
1699 } 1692 }
1700 } else { 1693 } else {
1701 // Look for a top-level setter 1694 // Look for a top-level setter
1702 final member = library.lookup(name, xn.name.span); 1695 final member = library.lookup(name, xn.name.span);
(...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after
2045 final name = node.name.name; 2038 final name = node.name.name;
2046 2039
2047 // First check in block scopes. 2040 // First check in block scopes.
2048 var ret = _scope.lookup(name); 2041 var ret = _scope.lookup(name);
2049 if (ret != null) return ret; 2042 if (ret != null) return ret;
2050 2043
2051 return _makeThisOrType(node.span).get_(this, name, node); 2044 return _makeThisOrType(node.span).get_(this, name, node);
2052 } 2045 }
2053 2046
2054 _makeMissingValue(String name) { 2047 _makeMissingValue(String name) {
2055 // TODO(jimhug): Probably goes away to be fully replaced by doesNotUnder 2048 // TODO(jimhug): Probably goes away to be fully replaced by noSuchMethod
2056 return new Value(null, '$name()/*NotFound*/', null); 2049 return new Value(world.varType, '$name()/*NotFound*/', null);
2057 } 2050 }
2058 2051
2059 _makeThisOrType(SourceSpan span) { 2052 _makeThisOrType(SourceSpan span) {
2060 return new BareValue(this, _getOutermostMethod(), span); 2053 return new BareValue(this, _getOutermostMethod(), span);
2061 } 2054 }
2062 2055
2063 visitThisExpression(ThisExpression node) { 2056 visitThisExpression(ThisExpression node) {
2064 return _makeThisValue(node); 2057 return _makeThisValue(node);
2065 } 2058 }
2066 2059
2067 visitSuperExpression(SuperExpression node) { 2060 visitSuperExpression(SuperExpression node) {
2068 return _makeSuperValue(node); 2061 return _makeSuperValue(node);
2069 } 2062 }
2070 2063
2071 visitNullExpression(NullExpression node) { 2064 visitNullExpression(NullExpression node) {
2072 return new EvaluatedValue(null, null, 'null', null); 2065 // TODO(jimhug): should be passing node.span
2066 // TODO(jimhug): Can we do better than var for the type?
2067 return new EvaluatedValue(world.varType, null, 'null', null);
2073 } 2068 }
2074 2069
2075 visitLiteralExpression(LiteralExpression node) { 2070 visitLiteralExpression(LiteralExpression node) {
2076 // All Literal types are filled in at parse time, so no need to resolve. 2071 // All Literal types are filled in at parse time, so no need to resolve.
2077 var type = node.type.type; 2072 var type = node.type.type;
2078 assert(type != null); 2073 assert(type != null);
2079 2074
2080 if (node.value is List) { 2075 if (node.value is List) {
2081 var items = []; 2076 var items = [];
2082 for (var item in node.value) { 2077 for (var item in node.value) {
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
2132 List<Value> values; 2127 List<Value> values;
2133 List<ArgumentNode> nodes; 2128 List<ArgumentNode> nodes;
2134 int _bareCount; 2129 int _bareCount;
2135 2130
2136 Arguments(this.nodes, this.values); 2131 Arguments(this.nodes, this.values);
2137 2132
2138 /** Constructs a bare list of arguments. */ 2133 /** Constructs a bare list of arguments. */
2139 factory Arguments.bare(int arity) { 2134 factory Arguments.bare(int arity) {
2140 var values = []; 2135 var values = [];
2141 for (int i = 0; i < arity; i++) { 2136 for (int i = 0; i < arity; i++) {
2142 // TODO(jimhug): Need source locations. 2137 // TODO(jimhug): Need a firm rule about null SourceSpans are allowed.
2143 values.add(new Value(world.varType, '\$$i', null, false, /*needsTemp:*/fal se)); 2138 values.add(new Value(world.varType, '\$$i', null, /*needsTemp:*/false));
2144 } 2139 }
2145 return new Arguments(null, values); 2140 return new Arguments(null, values);
2146 } 2141 }
2147 2142
2148 int get nameCount() => length - bareCount; 2143 int get nameCount() => length - bareCount;
2149 bool get hasNames() => bareCount < length; 2144 bool get hasNames() => bareCount < length;
2150 2145
2151 int get length() => values.length; 2146 int get length() => values.length;
2152 2147
2153 String getName(int i) => nodes[i].label.name; 2148 String getName(int i) => nodes[i].label.name;
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
2221 for (int i = bareCount; i < length; i++) { 2216 for (int i = bareCount; i < length; i++) {
2222 names.add(getName(i)); 2217 names.add(getName(i));
2223 } 2218 }
2224 return names; 2219 return names;
2225 } 2220 }
2226 2221
2227 /** Gets the argument names used in a call stub; uses $0 $1 for bare args. */ 2222 /** Gets the argument names used in a call stub; uses $0 $1 for bare args. */
2228 Arguments toCallStubArgs() { 2223 Arguments toCallStubArgs() {
2229 var result = []; 2224 var result = [];
2230 for (int i = 0; i < bareCount; i++) { 2225 for (int i = 0; i < bareCount; i++) {
2231 // TODO(jimhug): Need source locations. 2226 result.add(new Value(world.varType, '\$$i', null, /*needsTemp:*/false));
2232 result.add(new Value(world.varType, '\$$i', null, false, /*needsTemp:*/fal se));
2233 } 2227 }
2234 for (int i = bareCount; i < length; i++) { 2228 for (int i = bareCount; i < length; i++) {
2235 var name = getName(i); 2229 var name = getName(i);
2236 if (name == null) name = '\$$i'; 2230 if (name == null) name = '\$$i';
2237 // TODO(jimhug): Need source locations. 2231 result.add(new Value(world.varType, name, null, /*needsTemp:*/false));
2238 result.add(new Value(world.varType, name, null, false, /*needsTemp:*/false ));
2239 } 2232 }
2240 return new Arguments(nodes, result); 2233 return new Arguments(nodes, result);
2241 } 2234 }
2242 } 2235 }
OLDNEW
« no previous file with comments | « frog/frogsh ('k') | frog/lib/corelib_impl.dart » ('j') | tests/co19/co19-frog.status » ('J')

Powered by Google App Engine
This is Rietveld 408576698