Chromium Code Reviews| 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 1414 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1425 world.warning('not allowed in static method', node.span); | 1425 world.warning('not allowed in static method', node.span); |
| 1426 } | 1426 } |
| 1427 } | 1427 } |
| 1428 | 1428 |
| 1429 _makeSuperValue(Node node) { | 1429 _makeSuperValue(Node node) { |
| 1430 var parentType = method.declaringType.parent; | 1430 var parentType = method.declaringType.parent; |
| 1431 _checkNonStatic(node); | 1431 _checkNonStatic(node); |
| 1432 if (parentType == null) { | 1432 if (parentType == null) { |
| 1433 world.error('no super class', node.span); | 1433 world.error('no super class', node.span); |
| 1434 } | 1434 } |
| 1435 return new Value(parentType, 'this', true); | 1435 return new Value(parentType, 'this', |
| 1436 /*isSuper:*/true, /*needsTemp:*/false); | |
| 1436 } | 1437 } |
| 1437 | 1438 |
| 1438 _getOutermostMethod() { | 1439 _getOutermostMethod() { |
| 1439 var result = this; | 1440 var result = this; |
| 1440 while (result.enclosingMethod != null) { | 1441 while (result.enclosingMethod != null) { |
| 1441 result = result.enclosingMethod; | 1442 result = result.enclosingMethod; |
| 1442 } | 1443 } |
| 1443 return result; | 1444 return result; |
| 1444 } | 1445 } |
| 1445 | 1446 |
| 1446 /** | 1447 /** |
| 1447 * Creates a reference to the enclosing type ('this') that can be used within | 1448 * Creates a reference to the enclosing type ('this') that can be used within |
| 1448 * closures. | 1449 * closures. |
| 1449 */ | 1450 */ |
| 1450 _makeThisValue(Node node) { | 1451 _makeThisValue(Node node) { |
| 1451 if (enclosingMethod != null) { | 1452 if (enclosingMethod != null) { |
| 1452 var outermostMethod = _getOutermostMethod(); | 1453 var outermostMethod = _getOutermostMethod(); |
| 1453 outermostMethod._checkNonStatic(node); | 1454 outermostMethod._checkNonStatic(node); |
| 1454 outermostMethod.needsThis = true; | 1455 outermostMethod.needsThis = true; |
| 1455 return new Value(outermostMethod.method.declaringType, '\$this'); | 1456 return new Value(outermostMethod.method.declaringType, '\$this', |
| 1457 /*isSuper:*/false, /*needsTemp:*/false); | |
| 1456 } else { | 1458 } else { |
| 1457 _checkNonStatic(node); | 1459 _checkNonStatic(node); |
| 1458 return new Value(method.declaringType, 'this'); | 1460 return new Value(method.declaringType, 'this', |
| 1461 /*isSuper:*/false, /*needsTemp:*/false); | |
| 1459 } | 1462 } |
| 1460 } | 1463 } |
| 1461 | 1464 |
| 1462 // ******************* Expressions ******************* | 1465 // ******************* Expressions ******************* |
| 1463 visitLambdaExpression(LambdaExpression node) { | 1466 visitLambdaExpression(LambdaExpression node) { |
| 1464 var name = ''; | 1467 var name = ''; |
| 1465 if (node.func.name != null) { | 1468 if (node.func.name != null) { |
| 1466 name = world.toJsIdentifier(node.func.name.name); | 1469 name = world.toJsIdentifier(node.func.name.name); |
| 1467 } | 1470 } |
| 1468 | 1471 |
| (...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1657 Value captureOriginal(Value right)) { | 1660 Value captureOriginal(Value right)) { |
| 1658 var target = visitValue(xn.target); | 1661 var target = visitValue(xn.target); |
| 1659 var index = visitValue(xn.index); | 1662 var index = visitValue(xn.index); |
| 1660 var y = visitValue(yn); | 1663 var y = visitValue(yn); |
| 1661 | 1664 |
| 1662 var tmptarget = target; | 1665 var tmptarget = target; |
| 1663 var tmpindex = index; | 1666 var tmpindex = index; |
| 1664 if (kind != 0) { | 1667 if (kind != 0) { |
| 1665 tmptarget = getTemp(target); | 1668 tmptarget = getTemp(target); |
| 1666 tmpindex = getTemp(index); | 1669 tmpindex = getTemp(index); |
| 1670 index = assignTemp(tmpindex, index); | |
|
Jennifer Messerly
2011/11/07 21:29:53
for consistency, I'd remove this line, and change
| |
| 1667 var right = tmptarget.invoke(this, '\$index', | 1671 var right = tmptarget.invoke(this, '\$index', |
| 1668 position, new Arguments(null, [assignTemp(tmpindex, index)])); | 1672 position, new Arguments(null, [tmpindex])); |
| 1669 right = captureOriginal(right); | 1673 right = captureOriginal(right); |
| 1670 y = right.invoke(this, TokenKind.binaryMethodName(kind), | 1674 y = right.invoke(this, TokenKind.binaryMethodName(kind), |
| 1671 position, new Arguments(null, [y])); | 1675 position, new Arguments(null, [y])); |
| 1672 } | 1676 } |
| 1673 var ret = assignTemp(tmptarget, target).invoke(this, '\$setindex', | 1677 var ret = assignTemp(tmptarget, target).invoke(this, '\$setindex', |
| 1674 position, new Arguments(null, [index, y])); | 1678 position, new Arguments(null, [index, y])); |
| 1675 if (tmptarget != target) freeTemp(tmptarget); | 1679 if (tmptarget != target) freeTemp(tmptarget); |
| 1676 if (tmpindex != index) freeTemp(tmpindex); | 1680 if (tmpindex != index) freeTemp(tmpindex); |
| 1677 return ret; | 1681 return ret; |
| 1678 } | 1682 } |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1710 // --x becomes x -= 1 | 1714 // --x becomes x -= 1 |
| 1711 // TODO(jimhug): Confirm that --x becomes x -= 1 as it is in VM. | 1715 // TODO(jimhug): Confirm that --x becomes x -= 1 as it is in VM. |
| 1712 var kind = (TokenKind.INCR == node.op.kind ? | 1716 var kind = (TokenKind.INCR == node.op.kind ? |
| 1713 TokenKind.ADD : TokenKind.SUB); | 1717 TokenKind.ADD : TokenKind.SUB); |
| 1714 var operand = new LiteralExpression(1, | 1718 var operand = new LiteralExpression(1, |
| 1715 new TypeReference(node.span, world.numType), '1', node.span); | 1719 new TypeReference(node.span, world.numType), '1', node.span); |
| 1716 | 1720 |
| 1717 return _visitAssign(kind, node.self, operand, node, null); | 1721 return _visitAssign(kind, node.self, operand, node, null); |
| 1718 } | 1722 } |
| 1719 case TokenKind.NOT: | 1723 case TokenKind.NOT: |
| 1720 // TODO(jimhug): turn into method invoke? | 1724 // TODO(jimhug): Issue #359 seeks to clarify this behavior. |
| 1721 if (value.type.isBool && value.isConst) { | 1725 if (value.type.isBool && value.isConst) { |
| 1722 var newVal = !value.actualValue; | 1726 var newVal = !value.actualValue; |
| 1723 return new EvaluatedValue(value.type, newVal, '${newVal}', node.span); | 1727 return new EvaluatedValue(value.type, newVal, '${newVal}', node.span); |
| 1724 } else { | 1728 } else { |
| 1725 return new Value(world.boolType, '!${value.code}'); | 1729 var newVal = value.convertToNonNullBool(this, node); |
|
Jennifer Messerly
2011/11/07 21:29:53
Ah. I was wondering why we had the extra non-null
| |
| 1730 return new Value(world.boolType, '!${newVal.code}'); | |
| 1726 } | 1731 } |
| 1727 | 1732 |
| 1728 case TokenKind.ADD: // this should be a noop? | 1733 case TokenKind.ADD: |
| 1734 // TODO(jimhug): Issue #359 seeks to clarify this behavior. | |
| 1735 return value.convertTo(this, world.numType, node); | |
| 1736 | |
| 1729 case TokenKind.SUB: | 1737 case TokenKind.SUB: |
| 1730 case TokenKind.BIT_NOT: | 1738 case TokenKind.BIT_NOT: |
| 1731 // TODO(jimhug): turn into method invokes more thoroughly | 1739 if (node.op.kind == TokenKind.BIT_NOT) { |
|
Jennifer Messerly
2011/11/07 21:29:53
this is so much nicer.
| |
| 1732 if (value.type.isNum) { | 1740 return value.invoke(this, '\$bit_not', node, Arguments.EMPTY); |
| 1733 if (value.isConst) { | 1741 } else if (node.op.kind == TokenKind.SUB) { |
| 1734 if (node.op.kind == TokenKind.ADD) { | 1742 return value.invoke(this, '\$negate', node, Arguments.EMPTY); |
| 1735 return value; | |
| 1736 } else if (node.op.kind == TokenKind.SUB) { | |
| 1737 var newVal = -value.actualValue; | |
| 1738 return new EvaluatedValue( | |
| 1739 value.type, newVal, '$newVal', node.span); | |
| 1740 } else { | |
| 1741 var newVal = (~value.actualValue.toInt()).toDouble(); | |
| 1742 return new EvaluatedValue( | |
| 1743 value.type, newVal, '$newVal', node.span); | |
| 1744 } | |
| 1745 } | |
| 1746 return new Value(value.type, '${node.op}${value.code}'); | |
| 1747 } else { | 1743 } else { |
| 1748 String name; | 1744 world.internalError('unimplemented: unary ${node.op}', |
| 1749 if (node.op.kind == TokenKind.BIT_NOT) name = '\$bit_not'; | 1745 node.span); |
| 1750 else if (node.op.kind == TokenKind.SUB) name = '\$negate'; | |
| 1751 else world.internalError( | |
| 1752 'unimplemented: unary ${node.op} on var', node.span); | |
| 1753 return new Value(world.varType, '$name(${value.code})'); | |
| 1754 } | 1746 } |
| 1755 default: | 1747 default: |
| 1756 world.internalError('unimplemented: ${node.op}', node.span); | 1748 world.internalError('unimplemented: ${node.op}', node.span); |
| 1757 } | 1749 } |
| 1758 } | 1750 } |
| 1759 | 1751 |
| 1760 visitPostfixExpression(PostfixExpression node, [bool isVoid = false]) { | 1752 visitPostfixExpression(PostfixExpression node, [bool isVoid = false]) { |
| 1761 var value = visitValue(node.body); | 1753 var value = visitValue(node.body); |
| 1762 if (value.type.isNum) { | 1754 if (value.type.isNum) { |
| 1763 return new Value(value.type, '${value.code}${node.op}'); | 1755 return new Value(value.type, '${value.code}${node.op}'); |
| (...skipping 406 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2170 result.add(new Value(world.varType, '\$$i', false, /*needsTemp:*/false)); | 2162 result.add(new Value(world.varType, '\$$i', false, /*needsTemp:*/false)); |
| 2171 } | 2163 } |
| 2172 for (int i = bareCount; i < length; i++) { | 2164 for (int i = bareCount; i < length; i++) { |
| 2173 var name = getName(i); | 2165 var name = getName(i); |
| 2174 if (name == null) name = '\$$i'; | 2166 if (name == null) name = '\$$i'; |
| 2175 result.add(new Value(world.varType, name, false, /*needsTemp:*/false)); | 2167 result.add(new Value(world.varType, name, false, /*needsTemp:*/false)); |
| 2176 } | 2168 } |
| 2177 return new Arguments(nodes, result); | 2169 return new Arguments(nodes, result); |
| 2178 } | 2170 } |
| 2179 } | 2171 } |
| OLD | NEW |