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 1160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1171 visitTypedValue(Expression node, Type expectedType) { | 1171 visitTypedValue(Expression node, Type expectedType) { |
| 1172 return visitValue(node).convertTo(this, expectedType, node); | 1172 return visitValue(node).convertTo(this, expectedType, node); |
| 1173 } | 1173 } |
| 1174 | 1174 |
| 1175 visitVoid(Expression node) { | 1175 visitVoid(Expression node) { |
| 1176 // TODO(jmesserly): should we generalize this? | 1176 // TODO(jmesserly): should we generalize this? |
| 1177 if (node is PostfixExpression) { | 1177 if (node is PostfixExpression) { |
| 1178 var value = visitPostfixExpression(node, /*isVoid:*/true); | 1178 var value = visitPostfixExpression(node, /*isVoid:*/true); |
| 1179 value.checkFirstClass(node.span); | 1179 value.checkFirstClass(node.span); |
| 1180 return value; | 1180 return value; |
| 1181 } else if (node is BinaryExpression) { | |
| 1182 var value = visitBinaryExpression(node, /*isVoid:*/true); | |
|
Jennifer Messerly
2011/12/06 01:06:39
you could actually pass "isVoid:true" now :)
| |
| 1183 value.checkFirstClass(node.span); | |
| 1184 return value; | |
| 1181 } | 1185 } |
| 1182 // TODO(jimhug): Some level of warnings for non-void things here? | 1186 // TODO(jimhug): Some level of warnings for non-void things here? |
| 1183 return visitValue(node); | 1187 return visitValue(node); |
| 1184 } | 1188 } |
| 1185 | 1189 |
| 1186 // ******************* Statements ******************* | 1190 // ******************* Statements ******************* |
| 1187 | 1191 |
| 1188 bool visitDietStatement(DietStatement node) { | 1192 bool visitDietStatement(DietStatement node) { |
| 1189 var parser = new Parser(node.span.file, startOffset: node.span.start); | 1193 var parser = new Parser(node.span.file, startOffset: node.span.start); |
| 1190 visitStatementsInBlock(parser.block()); | 1194 visitStatementsInBlock(parser.block()); |
| (...skipping 551 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1742 | 1746 |
| 1743 return target.invoke(this, name, position, _makeArgs(node.arguments)); | 1747 return target.invoke(this, name, position, _makeArgs(node.arguments)); |
| 1744 } | 1748 } |
| 1745 | 1749 |
| 1746 visitIndexExpression(IndexExpression node) { | 1750 visitIndexExpression(IndexExpression node) { |
| 1747 var target = visitValue(node.target); | 1751 var target = visitValue(node.target); |
| 1748 var index = visitValue(node.index); | 1752 var index = visitValue(node.index); |
| 1749 return target.invoke(this, ':index', node, new Arguments(null, [index])); | 1753 return target.invoke(this, ':index', node, new Arguments(null, [index])); |
| 1750 } | 1754 } |
| 1751 | 1755 |
| 1752 visitBinaryExpression(BinaryExpression node) { | 1756 visitBinaryExpression(BinaryExpression node, [bool isVoid = false]) { |
| 1753 final kind = node.op.kind; | 1757 final kind = node.op.kind; |
| 1754 // TODO(jimhug): Ensure these have same semantics as JS! | 1758 // TODO(jimhug): Ensure these have same semantics as JS! |
| 1755 if (kind == TokenKind.AND || kind == TokenKind.OR) { | 1759 if (kind == TokenKind.AND || kind == TokenKind.OR) { |
| 1756 var x = visitTypedValue(node.x, world.nonNullBool); | 1760 var x = visitTypedValue(node.x, world.nonNullBool); |
| 1757 var y = visitTypedValue(node.y, world.nonNullBool); | 1761 var y = visitTypedValue(node.y, world.nonNullBool); |
| 1758 final code = '${x.code} ${node.op} ${y.code}'; | 1762 final code = '${x.code} ${node.op} ${y.code}'; |
| 1759 if (x.isConst && y.isConst) { | 1763 if (x.isConst && y.isConst) { |
| 1760 var value = (kind == TokenKind.AND) | 1764 var value = (kind == TokenKind.AND) |
| 1761 ? x.actualValue && y.actualValue : x.actualValue || y.actualValue; | 1765 ? x.actualValue && y.actualValue : x.actualValue || y.actualValue; |
| 1762 return new EvaluatedValue(world.nonNullBool, value, '$value', | 1766 return new EvaluatedValue(world.nonNullBool, value, '$value', |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1809 var name = TokenKind.binaryMethodName(node.op.kind); | 1813 var name = TokenKind.binaryMethodName(node.op.kind); |
| 1810 if (node.op.kind == TokenKind.NE) { | 1814 if (node.op.kind == TokenKind.NE) { |
| 1811 name = ':ne'; | 1815 name = ':ne'; |
| 1812 } | 1816 } |
| 1813 if (name == null) { | 1817 if (name == null) { |
| 1814 world.internalError('unimplemented binary op ${node.op}', node.span); | 1818 world.internalError('unimplemented binary op ${node.op}', node.span); |
| 1815 return; | 1819 return; |
| 1816 } | 1820 } |
| 1817 return x.invoke(this, name, node, new Arguments(null, [y])); | 1821 return x.invoke(this, name, node, new Arguments(null, [y])); |
| 1818 } else { | 1822 } else { |
| 1819 return _visitAssign(assignKind, node.x, node.y, node, null); | 1823 return _visitAssign(assignKind, node.x, node.y, node, null, isVoid); |
| 1820 } | 1824 } |
| 1821 } | 1825 } |
| 1822 | 1826 |
| 1823 /** | 1827 /** |
| 1824 * Visits an assignment expression. | 1828 * Visits an assignment expression. |
| 1825 * Note: captureOriginal can optionally capture the original value of the | 1829 * Note: captureOriginal can optionally capture the original value of the |
| 1826 * left side. This is used by postfix expressions to ensure they return the | 1830 * left side. This is used by postfix expressions to ensure they return the |
| 1827 * original value, before it has been modified. | 1831 * original value, before it has been modified. |
| 1828 */ | 1832 */ |
| 1829 _visitAssign(int kind, Expression xn, Expression yn, Node position, | 1833 _visitAssign(int kind, Expression xn, Expression yn, Node position, |
| 1830 Value captureOriginal(Value right)) { | 1834 Value captureOriginal(Value right), [bool isVoid = false]) { |
| 1831 | 1835 |
| 1832 if (captureOriginal == null) { | 1836 if (captureOriginal == null) { |
| 1833 captureOriginal = (x) => x; | 1837 captureOriginal = (x) => x; |
| 1834 } | 1838 } |
| 1835 | 1839 |
| 1836 // TODO(jimhug): The usual battle with making assign impl not look ugly. | 1840 // TODO(jimhug): The usual battle with making assign impl not look ugly. |
| 1837 if (xn is VarExpression) { | 1841 if (xn is VarExpression) { |
| 1838 return _visitVarAssign(kind, xn, yn, position, captureOriginal); | 1842 return _visitVarAssign(kind, xn, yn, position, captureOriginal); |
| 1839 } else if (xn is IndexExpression) { | 1843 } else if (xn is IndexExpression) { |
| 1840 return _visitIndexAssign(kind, xn, yn, position, captureOriginal); | 1844 return _visitIndexAssign(kind, xn, yn, position, captureOriginal, isVoid); |
| 1841 } else if (xn is DotExpression) { | 1845 } else if (xn is DotExpression) { |
| 1842 return _visitDotAssign(kind, xn, yn, position, captureOriginal); | 1846 return _visitDotAssign(kind, xn, yn, position, captureOriginal); |
| 1843 } else { | 1847 } else { |
| 1844 world.error('illegal lhs', xn.span); | 1848 world.error('illegal lhs', xn.span); |
| 1845 } | 1849 } |
| 1846 } | 1850 } |
| 1847 | 1851 |
| 1848 // TODO(jmesserly): it'd be nice if we didn't have to deal directly with | 1852 // TODO(jmesserly): it'd be nice if we didn't have to deal directly with |
| 1849 // MemberSets here and in visitVarExpression. | 1853 // MemberSets here and in visitVarExpression. |
| 1850 _visitVarAssign(int kind, VarExpression xn, Expression yn, Node position, | 1854 _visitVarAssign(int kind, VarExpression xn, Expression yn, Node position, |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1921 } else { | 1925 } else { |
| 1922 var right = x; | 1926 var right = x; |
| 1923 right = captureOriginal(right); | 1927 right = captureOriginal(right); |
| 1924 y = right.invoke(this, TokenKind.binaryMethodName(kind), | 1928 y = right.invoke(this, TokenKind.binaryMethodName(kind), |
| 1925 position, new Arguments(null, [y])); | 1929 position, new Arguments(null, [y])); |
| 1926 return new Value(y.type, '${x.code} = ${y.code}', position.span); | 1930 return new Value(y.type, '${x.code} = ${y.code}', position.span); |
| 1927 } | 1931 } |
| 1928 } | 1932 } |
| 1929 | 1933 |
| 1930 _visitIndexAssign(int kind, IndexExpression xn, Expression yn, Node position, | 1934 _visitIndexAssign(int kind, IndexExpression xn, Expression yn, Node position, |
| 1931 Value captureOriginal(Value right)) { | 1935 Value captureOriginal(Value right), [bool isVoid = false]) { |
| 1932 var target = visitValue(xn.target); | 1936 var target = visitValue(xn.target); |
| 1933 var index = visitValue(xn.index); | 1937 var index = visitValue(xn.index); |
| 1934 var y = visitValue(yn); | 1938 var y = visitValue(yn); |
| 1935 | 1939 |
| 1936 var tmptarget = target; | 1940 var tmptarget = target; |
| 1937 var tmpindex = index; | 1941 var tmpindex = index; |
| 1938 if (kind != 0) { | 1942 if (kind != 0) { |
| 1939 tmptarget = getTemp(target); | 1943 tmptarget = getTemp(target); |
| 1940 tmpindex = getTemp(index); | 1944 tmpindex = getTemp(index); |
| 1941 index = assignTemp(tmpindex, index); | 1945 index = assignTemp(tmpindex, index); |
| 1942 var right = tmptarget.invoke(this, ':index', | 1946 var right = tmptarget.invoke(this, ':index', |
| 1943 position, new Arguments(null, [tmpindex])); | 1947 position, new Arguments(null, [tmpindex])); |
| 1944 right = captureOriginal(right); | 1948 right = captureOriginal(right); |
| 1945 y = right.invoke(this, TokenKind.binaryMethodName(kind), | 1949 y = right.invoke(this, TokenKind.binaryMethodName(kind), |
| 1946 position, new Arguments(null, [y])); | 1950 position, new Arguments(null, [y])); |
| 1947 } | 1951 } |
| 1952 | |
| 1953 var tmpy = null; | |
| 1954 // If the assignment is an expression statement (x[i] = y;) it is translated | |
| 1955 // as (x.$setindex(i, y)), otherwise as (x.$setindex(i, t = y), t). | |
| 1956 if (!isVoid) { | |
| 1957 tmpy = getTemp(y); | |
| 1958 y = assignTemp(tmpy, y); | |
| 1959 } | |
| 1948 var ret = assignTemp(tmptarget, target).invoke(this, ':setindex', | 1960 var ret = assignTemp(tmptarget, target).invoke(this, ':setindex', |
| 1949 position, new Arguments(null, [index, y])); | 1961 position, new Arguments(null, [index, y])); |
| 1962 if (tmpy != null) { | |
| 1963 ret = new Value(ret.type, '(${ret.code}, ${tmpy.code})', ret.span); | |
| 1964 if (tmpy != y) freeTemp(tmpy); | |
| 1965 } | |
| 1950 if (tmptarget != target) freeTemp(tmptarget); | 1966 if (tmptarget != target) freeTemp(tmptarget); |
| 1951 if (tmpindex != index) freeTemp(tmpindex); | 1967 if (tmpindex != index) freeTemp(tmpindex); |
| 1952 return ret; | 1968 return ret; |
| 1953 } | 1969 } |
| 1954 | 1970 |
| 1955 _visitDotAssign(int kind, DotExpression xn, Expression yn, Node position, | 1971 _visitDotAssign(int kind, DotExpression xn, Expression yn, Node position, |
| 1956 Value captureOriginal(Value right)) { | 1972 Value captureOriginal(Value right)) { |
| 1957 | 1973 |
| 1958 // This is not visitValue because types are assignable through . | 1974 // This is not visitValue because types are assignable through . |
| 1959 var target = xn.self.visit(this); | 1975 var target = xn.self.visit(this); |
| (...skipping 489 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2449 result.add(new Value(world.varType, '\$$i', null, /*needsTemp:*/false)); | 2465 result.add(new Value(world.varType, '\$$i', null, /*needsTemp:*/false)); |
| 2450 } | 2466 } |
| 2451 for (int i = bareCount; i < length; i++) { | 2467 for (int i = bareCount; i < length; i++) { |
| 2452 var name = getName(i); | 2468 var name = getName(i); |
| 2453 if (name == null) name = '\$$i'; | 2469 if (name == null) name = '\$$i'; |
| 2454 result.add(new Value(world.varType, name, null, /*needsTemp:*/false)); | 2470 result.add(new Value(world.varType, name, null, /*needsTemp:*/false)); |
| 2455 } | 2471 } |
| 2456 return new Arguments(nodes, result); | 2472 return new Arguments(nodes, result); |
| 2457 } | 2473 } |
| 2458 } | 2474 } |
| OLD | NEW |