| 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 |