OLD | NEW |
| (Empty) |
1 import * as ts from 'typescript'; | |
2 import * as base from './base'; | |
3 import {Transpiler} from './main'; | |
4 import {FacadeConverter} from './facade_converter'; | |
5 | |
6 export default class ExpressionTranspiler extends base.TranspilerBase { | |
7 constructor(tr: Transpiler, private fc: FacadeConverter) { super(tr); } | |
8 | |
9 visitNode(node: ts.Node): boolean { | |
10 switch (node.kind) { | |
11 case ts.SyntaxKind.BinaryExpression: | |
12 let binExpr = <ts.BinaryExpression>node; | |
13 let operatorKind = binExpr.operatorToken.kind; | |
14 let tokenStr = ts.tokenToString(operatorKind); | |
15 switch (operatorKind) { | |
16 case ts.SyntaxKind.EqualsEqualsEqualsToken: | |
17 case ts.SyntaxKind.ExclamationEqualsEqualsToken: | |
18 if (operatorKind === ts.SyntaxKind.ExclamationEqualsEqualsToken) thi
s.emit('!'); | |
19 this.emit('identical ('); | |
20 this.visit(binExpr.left); | |
21 this.emit(','); | |
22 this.visit(binExpr.right); | |
23 this.emit(')'); | |
24 break; | |
25 case ts.SyntaxKind.CaretToken: | |
26 case ts.SyntaxKind.BarToken: | |
27 case ts.SyntaxKind.AmpersandToken: | |
28 case ts.SyntaxKind.GreaterThanGreaterThanToken: | |
29 case ts.SyntaxKind.LessThanLessThanToken: | |
30 case ts.SyntaxKind.CaretEqualsToken: | |
31 case ts.SyntaxKind.BarEqualsToken: | |
32 case ts.SyntaxKind.AmpersandEqualsToken: | |
33 case ts.SyntaxKind.GreaterThanGreaterThanEqualsToken: | |
34 case ts.SyntaxKind.LessThanLessThanEqualsToken: | |
35 // In Dart, the bitwise operators are only available on int, so the
number types ts2dart | |
36 // deals with have to be converted to int explicitly to match JS's s
emantics in Dart. | |
37 if (tokenStr[tokenStr.length - 1] === '=') { | |
38 // For assignments, strip the trailing `=` sign to emit just the o
perator itself. | |
39 this.visit(binExpr.left); | |
40 this.emit('='); | |
41 this.visitAndWrapAsInt(binExpr.left); | |
42 this.emit(tokenStr.slice(0, -1)); | |
43 } else { | |
44 // normal case (LHS [op]) | |
45 this.visitAndWrapAsInt(binExpr.left); | |
46 this.emit(tokenStr); | |
47 } | |
48 this.visitAndWrapAsInt(binExpr.right); | |
49 break; | |
50 case ts.SyntaxKind.InKeyword: | |
51 this.reportError(node, 'in operator is unsupported'); | |
52 break; | |
53 case ts.SyntaxKind.InstanceOfKeyword: | |
54 this.visit(binExpr.left); | |
55 this.emit('is'); | |
56 this.fc.visitTypeName(<ts.Identifier>binExpr.right); | |
57 break; | |
58 default: | |
59 this.visit(binExpr.left); | |
60 this.emit(tokenStr); | |
61 this.visit(binExpr.right); | |
62 break; | |
63 } | |
64 break; | |
65 case ts.SyntaxKind.PrefixUnaryExpression: | |
66 let prefixUnary = <ts.PrefixUnaryExpression>node; | |
67 let operator = ts.tokenToString(prefixUnary.operator); | |
68 this.emit(operator); | |
69 | |
70 if (prefixUnary.operator === ts.SyntaxKind.TildeToken) { | |
71 this.visitAndWrapAsInt(prefixUnary.operand); | |
72 } else { | |
73 this.visit(prefixUnary.operand); | |
74 } | |
75 break; | |
76 case ts.SyntaxKind.PostfixUnaryExpression: | |
77 let postfixUnary = <ts.PostfixUnaryExpression>node; | |
78 this.visit(postfixUnary.operand); | |
79 this.emit(ts.tokenToString(postfixUnary.operator)); | |
80 break; | |
81 case ts.SyntaxKind.ConditionalExpression: | |
82 let conditional = <ts.ConditionalExpression>node; | |
83 this.visit(conditional.condition); | |
84 this.emit('?'); | |
85 this.visit(conditional.whenTrue); | |
86 this.emit(':'); | |
87 this.visit(conditional.whenFalse); | |
88 break; | |
89 case ts.SyntaxKind.DeleteExpression: | |
90 this.reportError(node, 'delete operator is unsupported'); | |
91 break; | |
92 case ts.SyntaxKind.VoidExpression: | |
93 this.reportError(node, 'void operator is unsupported'); | |
94 break; | |
95 case ts.SyntaxKind.TypeOfExpression: | |
96 this.reportError(node, 'typeof operator is unsupported'); | |
97 break; | |
98 | |
99 case ts.SyntaxKind.ParenthesizedExpression: | |
100 let parenExpr = <ts.ParenthesizedExpression>node; | |
101 this.emit('('); | |
102 this.visit(parenExpr.expression); | |
103 this.emit(')'); | |
104 break; | |
105 | |
106 case ts.SyntaxKind.PropertyAccessExpression: | |
107 let propAccess = <ts.PropertyAccessExpression>node; | |
108 if (propAccess.name.text === 'stack' && | |
109 this.hasAncestor(propAccess, ts.SyntaxKind.CatchClause)) { | |
110 // Handle `e.stack` accesses in catch clauses by mangling to `e_stack`
. | |
111 // FIXME: Use type checker/FacadeConverter to make sure this is actual
ly Error.stack. | |
112 this.visit(propAccess.expression); | |
113 this.emitNoSpace('_stack'); | |
114 } else { | |
115 if (this.fc.handlePropertyAccess(propAccess)) break; | |
116 this.visit(propAccess.expression); | |
117 this.emit('.'); | |
118 this.visit(propAccess.name); | |
119 } | |
120 break; | |
121 case ts.SyntaxKind.ElementAccessExpression: | |
122 let elemAccess = <ts.ElementAccessExpression>node; | |
123 this.visit(elemAccess.expression); | |
124 this.emit('['); | |
125 this.visit(elemAccess.argumentExpression); | |
126 this.emit(']'); | |
127 break; | |
128 | |
129 default: | |
130 return false; | |
131 } | |
132 return true; | |
133 } | |
134 | |
135 visitAndWrapAsInt(n: ts.Expression) { | |
136 let lhsIsHexLit = n.kind === ts.SyntaxKind.NumericLiteral; | |
137 if (lhsIsHexLit) { | |
138 this.visit(n); | |
139 return; | |
140 } | |
141 this.emit('('); | |
142 this.visit(n); | |
143 this.emit('as int)'); | |
144 } | |
145 } | |
OLD | NEW |