repackaging: all the file moves
This commit is contained in:
426
modules/@angular/compiler/src/output/abstract_emitter.ts
Normal file
426
modules/@angular/compiler/src/output/abstract_emitter.ts
Normal file
@ -0,0 +1,426 @@
|
||||
import {
|
||||
isPresent,
|
||||
isBlank,
|
||||
isString,
|
||||
evalExpression,
|
||||
RegExpWrapper,
|
||||
StringWrapper
|
||||
} from 'angular2/src/facade/lang';
|
||||
import {ListWrapper} from 'angular2/src/facade/collection';
|
||||
import {BaseException, unimplemented} from 'angular2/src/facade/exceptions';
|
||||
import * as o from './output_ast';
|
||||
|
||||
var _SINGLE_QUOTE_ESCAPE_STRING_RE = /'|\\|\n|\r|\$/g;
|
||||
export var CATCH_ERROR_VAR = o.variable('error');
|
||||
export var CATCH_STACK_VAR = o.variable('stack');
|
||||
|
||||
export abstract class OutputEmitter {
|
||||
abstract emitStatements(moduleUrl: string, stmts: o.Statement[], exportedVars: string[]): string;
|
||||
}
|
||||
|
||||
class _EmittedLine {
|
||||
parts: string[] = [];
|
||||
constructor(public indent: number) {}
|
||||
}
|
||||
|
||||
export class EmitterVisitorContext {
|
||||
static createRoot(exportedVars: string[]): EmitterVisitorContext {
|
||||
return new EmitterVisitorContext(exportedVars, 0);
|
||||
}
|
||||
|
||||
private _lines: _EmittedLine[];
|
||||
private _classes: o.ClassStmt[] = [];
|
||||
|
||||
constructor(private _exportedVars: string[], private _indent: number) {
|
||||
this._lines = [new _EmittedLine(_indent)];
|
||||
}
|
||||
|
||||
private get _currentLine(): _EmittedLine { return this._lines[this._lines.length - 1]; }
|
||||
|
||||
isExportedVar(varName: string): boolean { return this._exportedVars.indexOf(varName) !== -1; }
|
||||
|
||||
println(lastPart: string = ''): void { this.print(lastPart, true); }
|
||||
|
||||
lineIsEmpty(): boolean { return this._currentLine.parts.length === 0; }
|
||||
|
||||
print(part: string, newLine: boolean = false) {
|
||||
if (part.length > 0) {
|
||||
this._currentLine.parts.push(part);
|
||||
}
|
||||
if (newLine) {
|
||||
this._lines.push(new _EmittedLine(this._indent));
|
||||
}
|
||||
}
|
||||
|
||||
removeEmptyLastLine() {
|
||||
if (this.lineIsEmpty()) {
|
||||
this._lines.pop();
|
||||
}
|
||||
}
|
||||
|
||||
incIndent() {
|
||||
this._indent++;
|
||||
this._currentLine.indent = this._indent;
|
||||
}
|
||||
|
||||
decIndent() {
|
||||
this._indent--;
|
||||
this._currentLine.indent = this._indent;
|
||||
}
|
||||
|
||||
pushClass(clazz: o.ClassStmt) { this._classes.push(clazz); }
|
||||
|
||||
popClass(): o.ClassStmt { return this._classes.pop(); }
|
||||
|
||||
get currentClass(): o.ClassStmt {
|
||||
return this._classes.length > 0 ? this._classes[this._classes.length - 1] : null;
|
||||
}
|
||||
|
||||
toSource(): any {
|
||||
var lines = this._lines;
|
||||
if (lines[lines.length - 1].parts.length === 0) {
|
||||
lines = lines.slice(0, lines.length - 1);
|
||||
}
|
||||
return lines.map((line) => {
|
||||
if (line.parts.length > 0) {
|
||||
return _createIndent(line.indent) + line.parts.join('');
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
})
|
||||
.join('\n');
|
||||
}
|
||||
}
|
||||
|
||||
export abstract class AbstractEmitterVisitor implements o.StatementVisitor, o.ExpressionVisitor {
|
||||
constructor(private _escapeDollarInStrings: boolean) {}
|
||||
|
||||
visitExpressionStmt(stmt: o.ExpressionStatement, ctx: EmitterVisitorContext): any {
|
||||
stmt.expr.visitExpression(this, ctx);
|
||||
ctx.println(';');
|
||||
return null;
|
||||
}
|
||||
|
||||
visitReturnStmt(stmt: o.ReturnStatement, ctx: EmitterVisitorContext): any {
|
||||
ctx.print(`return `);
|
||||
stmt.value.visitExpression(this, ctx);
|
||||
ctx.println(';');
|
||||
return null;
|
||||
}
|
||||
|
||||
abstract visitCastExpr(ast: o.CastExpr, context: any): any;
|
||||
|
||||
abstract visitDeclareClassStmt(stmt: o.ClassStmt, ctx: EmitterVisitorContext): any;
|
||||
|
||||
visitIfStmt(stmt: o.IfStmt, ctx: EmitterVisitorContext): any {
|
||||
ctx.print(`if (`);
|
||||
stmt.condition.visitExpression(this, ctx);
|
||||
ctx.print(`) {`);
|
||||
var hasElseCase = isPresent(stmt.falseCase) && stmt.falseCase.length > 0;
|
||||
if (stmt.trueCase.length <= 1 && !hasElseCase) {
|
||||
ctx.print(` `);
|
||||
this.visitAllStatements(stmt.trueCase, ctx);
|
||||
ctx.removeEmptyLastLine();
|
||||
ctx.print(` `);
|
||||
} else {
|
||||
ctx.println();
|
||||
ctx.incIndent();
|
||||
this.visitAllStatements(stmt.trueCase, ctx);
|
||||
ctx.decIndent();
|
||||
if (hasElseCase) {
|
||||
ctx.println(`} else {`);
|
||||
ctx.incIndent();
|
||||
this.visitAllStatements(stmt.falseCase, ctx);
|
||||
ctx.decIndent();
|
||||
}
|
||||
}
|
||||
ctx.println(`}`);
|
||||
return null;
|
||||
}
|
||||
|
||||
abstract visitTryCatchStmt(stmt: o.TryCatchStmt, ctx: EmitterVisitorContext): any;
|
||||
|
||||
visitThrowStmt(stmt: o.ThrowStmt, ctx: EmitterVisitorContext): any {
|
||||
ctx.print(`throw `);
|
||||
stmt.error.visitExpression(this, ctx);
|
||||
ctx.println(`;`);
|
||||
return null;
|
||||
}
|
||||
visitCommentStmt(stmt: o.CommentStmt, ctx: EmitterVisitorContext): any {
|
||||
var lines = stmt.comment.split('\n');
|
||||
lines.forEach((line) => { ctx.println(`// ${line}`); });
|
||||
return null;
|
||||
}
|
||||
abstract visitDeclareVarStmt(stmt: o.DeclareVarStmt, ctx: EmitterVisitorContext): any;
|
||||
visitWriteVarExpr(expr: o.WriteVarExpr, ctx: EmitterVisitorContext): any {
|
||||
var lineWasEmpty = ctx.lineIsEmpty();
|
||||
if (!lineWasEmpty) {
|
||||
ctx.print('(');
|
||||
}
|
||||
ctx.print(`${expr.name} = `);
|
||||
expr.value.visitExpression(this, ctx);
|
||||
if (!lineWasEmpty) {
|
||||
ctx.print(')');
|
||||
}
|
||||
return null;
|
||||
}
|
||||
visitWriteKeyExpr(expr: o.WriteKeyExpr, ctx: EmitterVisitorContext): any {
|
||||
var lineWasEmpty = ctx.lineIsEmpty();
|
||||
if (!lineWasEmpty) {
|
||||
ctx.print('(');
|
||||
}
|
||||
expr.receiver.visitExpression(this, ctx);
|
||||
ctx.print(`[`);
|
||||
expr.index.visitExpression(this, ctx);
|
||||
ctx.print(`] = `);
|
||||
expr.value.visitExpression(this, ctx);
|
||||
if (!lineWasEmpty) {
|
||||
ctx.print(')');
|
||||
}
|
||||
return null;
|
||||
}
|
||||
visitWritePropExpr(expr: o.WritePropExpr, ctx: EmitterVisitorContext): any {
|
||||
var lineWasEmpty = ctx.lineIsEmpty();
|
||||
if (!lineWasEmpty) {
|
||||
ctx.print('(');
|
||||
}
|
||||
expr.receiver.visitExpression(this, ctx);
|
||||
ctx.print(`.${expr.name} = `);
|
||||
expr.value.visitExpression(this, ctx);
|
||||
if (!lineWasEmpty) {
|
||||
ctx.print(')');
|
||||
}
|
||||
return null;
|
||||
}
|
||||
visitInvokeMethodExpr(expr: o.InvokeMethodExpr, ctx: EmitterVisitorContext): any {
|
||||
expr.receiver.visitExpression(this, ctx);
|
||||
var name = expr.name;
|
||||
if (isPresent(expr.builtin)) {
|
||||
name = this.getBuiltinMethodName(expr.builtin);
|
||||
if (isBlank(name)) {
|
||||
// some builtins just mean to skip the call.
|
||||
// e.g. `bind` in Dart.
|
||||
return null;
|
||||
}
|
||||
}
|
||||
ctx.print(`.${name}(`);
|
||||
this.visitAllExpressions(expr.args, ctx, `,`);
|
||||
ctx.print(`)`);
|
||||
return null;
|
||||
}
|
||||
|
||||
abstract getBuiltinMethodName(method: o.BuiltinMethod): string;
|
||||
|
||||
visitInvokeFunctionExpr(expr: o.InvokeFunctionExpr, ctx: EmitterVisitorContext): any {
|
||||
expr.fn.visitExpression(this, ctx);
|
||||
ctx.print(`(`);
|
||||
this.visitAllExpressions(expr.args, ctx, ',');
|
||||
ctx.print(`)`);
|
||||
return null;
|
||||
}
|
||||
visitReadVarExpr(ast: o.ReadVarExpr, ctx: EmitterVisitorContext): any {
|
||||
var varName = ast.name;
|
||||
if (isPresent(ast.builtin)) {
|
||||
switch (ast.builtin) {
|
||||
case o.BuiltinVar.Super:
|
||||
varName = 'super';
|
||||
break;
|
||||
case o.BuiltinVar.This:
|
||||
varName = 'this';
|
||||
break;
|
||||
case o.BuiltinVar.CatchError:
|
||||
varName = CATCH_ERROR_VAR.name;
|
||||
break;
|
||||
case o.BuiltinVar.CatchStack:
|
||||
varName = CATCH_STACK_VAR.name;
|
||||
break;
|
||||
default:
|
||||
throw new BaseException(`Unknown builtin variable ${ast.builtin}`);
|
||||
}
|
||||
}
|
||||
ctx.print(varName);
|
||||
return null;
|
||||
}
|
||||
visitInstantiateExpr(ast: o.InstantiateExpr, ctx: EmitterVisitorContext): any {
|
||||
ctx.print(`new `);
|
||||
ast.classExpr.visitExpression(this, ctx);
|
||||
ctx.print(`(`);
|
||||
this.visitAllExpressions(ast.args, ctx, ',');
|
||||
ctx.print(`)`);
|
||||
return null;
|
||||
}
|
||||
visitLiteralExpr(ast: o.LiteralExpr, ctx: EmitterVisitorContext): any {
|
||||
var value = ast.value;
|
||||
if (isString(value)) {
|
||||
ctx.print(escapeSingleQuoteString(value, this._escapeDollarInStrings));
|
||||
} else if (isBlank(value)) {
|
||||
ctx.print('null');
|
||||
} else {
|
||||
ctx.print(`${value}`);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
abstract visitExternalExpr(ast: o.ExternalExpr, ctx: EmitterVisitorContext): any;
|
||||
|
||||
visitConditionalExpr(ast: o.ConditionalExpr, ctx: EmitterVisitorContext): any {
|
||||
ctx.print(`(`);
|
||||
ast.condition.visitExpression(this, ctx);
|
||||
ctx.print('? ');
|
||||
ast.trueCase.visitExpression(this, ctx);
|
||||
ctx.print(': ');
|
||||
ast.falseCase.visitExpression(this, ctx);
|
||||
ctx.print(`)`);
|
||||
return null;
|
||||
}
|
||||
visitNotExpr(ast: o.NotExpr, ctx: EmitterVisitorContext): any {
|
||||
ctx.print('!');
|
||||
ast.condition.visitExpression(this, ctx);
|
||||
return null;
|
||||
}
|
||||
abstract visitFunctionExpr(ast: o.FunctionExpr, ctx: EmitterVisitorContext): any;
|
||||
abstract visitDeclareFunctionStmt(stmt: o.DeclareFunctionStmt, context: any): any;
|
||||
|
||||
visitBinaryOperatorExpr(ast: o.BinaryOperatorExpr, ctx: EmitterVisitorContext): any {
|
||||
var opStr;
|
||||
switch (ast.operator) {
|
||||
case o.BinaryOperator.Equals:
|
||||
opStr = '==';
|
||||
break;
|
||||
case o.BinaryOperator.Identical:
|
||||
opStr = '===';
|
||||
break;
|
||||
case o.BinaryOperator.NotEquals:
|
||||
opStr = '!=';
|
||||
break;
|
||||
case o.BinaryOperator.NotIdentical:
|
||||
opStr = '!==';
|
||||
break;
|
||||
case o.BinaryOperator.And:
|
||||
opStr = '&&';
|
||||
break;
|
||||
case o.BinaryOperator.Or:
|
||||
opStr = '||';
|
||||
break;
|
||||
case o.BinaryOperator.Plus:
|
||||
opStr = '+';
|
||||
break;
|
||||
case o.BinaryOperator.Minus:
|
||||
opStr = '-';
|
||||
break;
|
||||
case o.BinaryOperator.Divide:
|
||||
opStr = '/';
|
||||
break;
|
||||
case o.BinaryOperator.Multiply:
|
||||
opStr = '*';
|
||||
break;
|
||||
case o.BinaryOperator.Modulo:
|
||||
opStr = '%';
|
||||
break;
|
||||
case o.BinaryOperator.Lower:
|
||||
opStr = '<';
|
||||
break;
|
||||
case o.BinaryOperator.LowerEquals:
|
||||
opStr = '<=';
|
||||
break;
|
||||
case o.BinaryOperator.Bigger:
|
||||
opStr = '>';
|
||||
break;
|
||||
case o.BinaryOperator.BiggerEquals:
|
||||
opStr = '>=';
|
||||
break;
|
||||
default:
|
||||
throw new BaseException(`Unknown operator ${ast.operator}`);
|
||||
}
|
||||
ctx.print(`(`);
|
||||
ast.lhs.visitExpression(this, ctx);
|
||||
ctx.print(` ${opStr} `);
|
||||
ast.rhs.visitExpression(this, ctx);
|
||||
ctx.print(`)`);
|
||||
return null;
|
||||
}
|
||||
|
||||
visitReadPropExpr(ast: o.ReadPropExpr, ctx: EmitterVisitorContext): any {
|
||||
ast.receiver.visitExpression(this, ctx);
|
||||
ctx.print(`.`);
|
||||
ctx.print(ast.name);
|
||||
return null;
|
||||
}
|
||||
visitReadKeyExpr(ast: o.ReadKeyExpr, ctx: EmitterVisitorContext): any {
|
||||
ast.receiver.visitExpression(this, ctx);
|
||||
ctx.print(`[`);
|
||||
ast.index.visitExpression(this, ctx);
|
||||
ctx.print(`]`);
|
||||
return null;
|
||||
}
|
||||
visitLiteralArrayExpr(ast: o.LiteralArrayExpr, ctx: EmitterVisitorContext): any {
|
||||
var useNewLine = ast.entries.length > 1;
|
||||
ctx.print(`[`, useNewLine);
|
||||
ctx.incIndent();
|
||||
this.visitAllExpressions(ast.entries, ctx, ',', useNewLine);
|
||||
ctx.decIndent();
|
||||
ctx.print(`]`, useNewLine);
|
||||
return null;
|
||||
}
|
||||
visitLiteralMapExpr(ast: o.LiteralMapExpr, ctx: EmitterVisitorContext): any {
|
||||
var useNewLine = ast.entries.length > 1;
|
||||
ctx.print(`{`, useNewLine);
|
||||
ctx.incIndent();
|
||||
this.visitAllObjects((entry) => {
|
||||
ctx.print(`${escapeSingleQuoteString(entry[0], this._escapeDollarInStrings)}: `);
|
||||
entry[1].visitExpression(this, ctx);
|
||||
}, ast.entries, ctx, ',', useNewLine);
|
||||
ctx.decIndent();
|
||||
ctx.print(`}`, useNewLine);
|
||||
return null;
|
||||
}
|
||||
|
||||
visitAllExpressions(expressions: o.Expression[], ctx: EmitterVisitorContext, separator: string,
|
||||
newLine: boolean = false): void {
|
||||
this.visitAllObjects((expr) => expr.visitExpression(this, ctx), expressions, ctx, separator,
|
||||
newLine);
|
||||
}
|
||||
|
||||
visitAllObjects(handler: Function, expressions: any, ctx: EmitterVisitorContext,
|
||||
separator: string, newLine: boolean = false): void {
|
||||
for (var i = 0; i < expressions.length; i++) {
|
||||
if (i > 0) {
|
||||
ctx.print(separator, newLine);
|
||||
}
|
||||
handler(expressions[i]);
|
||||
}
|
||||
if (newLine) {
|
||||
ctx.println();
|
||||
}
|
||||
}
|
||||
|
||||
visitAllStatements(statements: o.Statement[], ctx: EmitterVisitorContext): void {
|
||||
statements.forEach((stmt) => { return stmt.visitStatement(this, ctx); });
|
||||
}
|
||||
}
|
||||
|
||||
export function escapeSingleQuoteString(input: string, escapeDollar: boolean): any {
|
||||
if (isBlank(input)) {
|
||||
return null;
|
||||
}
|
||||
var body = StringWrapper.replaceAllMapped(input, _SINGLE_QUOTE_ESCAPE_STRING_RE, (match) => {
|
||||
if (match[0] == '$') {
|
||||
return escapeDollar ? '\\$' : '$';
|
||||
} else if (match[0] == '\n') {
|
||||
return '\\n';
|
||||
} else if (match[0] == '\r') {
|
||||
return '\\r';
|
||||
} else {
|
||||
return `\\${match[0]}`;
|
||||
}
|
||||
});
|
||||
return `'${body}'`;
|
||||
}
|
||||
|
||||
function _createIndent(count: number): string {
|
||||
var res = '';
|
||||
for (var i = 0; i < count; i++) {
|
||||
res += ' ';
|
||||
}
|
||||
return res;
|
||||
}
|
164
modules/@angular/compiler/src/output/abstract_js_emitter.ts
Normal file
164
modules/@angular/compiler/src/output/abstract_js_emitter.ts
Normal file
@ -0,0 +1,164 @@
|
||||
import {isPresent} from 'angular2/src/facade/lang';
|
||||
import {BaseException} from 'angular2/src/facade/exceptions';
|
||||
import * as o from './output_ast';
|
||||
import {
|
||||
EmitterVisitorContext,
|
||||
AbstractEmitterVisitor,
|
||||
CATCH_ERROR_VAR,
|
||||
CATCH_STACK_VAR
|
||||
} from './abstract_emitter';
|
||||
|
||||
export abstract class AbstractJsEmitterVisitor extends AbstractEmitterVisitor {
|
||||
constructor() { super(false); }
|
||||
visitDeclareClassStmt(stmt: o.ClassStmt, ctx: EmitterVisitorContext): any {
|
||||
ctx.pushClass(stmt);
|
||||
this._visitClassConstructor(stmt, ctx);
|
||||
|
||||
if (isPresent(stmt.parent)) {
|
||||
ctx.print(`${stmt.name}.prototype = Object.create(`);
|
||||
stmt.parent.visitExpression(this, ctx);
|
||||
ctx.println(`.prototype);`);
|
||||
}
|
||||
stmt.getters.forEach((getter) => this._visitClassGetter(stmt, getter, ctx));
|
||||
stmt.methods.forEach((method) => this._visitClassMethod(stmt, method, ctx));
|
||||
ctx.popClass();
|
||||
return null;
|
||||
}
|
||||
|
||||
private _visitClassConstructor(stmt: o.ClassStmt, ctx: EmitterVisitorContext) {
|
||||
ctx.print(`function ${stmt.name}(`);
|
||||
if (isPresent(stmt.constructorMethod)) {
|
||||
this._visitParams(stmt.constructorMethod.params, ctx);
|
||||
}
|
||||
ctx.println(`) {`);
|
||||
ctx.incIndent();
|
||||
if (isPresent(stmt.constructorMethod)) {
|
||||
if (stmt.constructorMethod.body.length > 0) {
|
||||
ctx.println(`var self = this;`);
|
||||
this.visitAllStatements(stmt.constructorMethod.body, ctx);
|
||||
}
|
||||
}
|
||||
ctx.decIndent();
|
||||
ctx.println(`}`);
|
||||
}
|
||||
|
||||
private _visitClassGetter(stmt: o.ClassStmt, getter: o.ClassGetter, ctx: EmitterVisitorContext) {
|
||||
ctx.println(
|
||||
`Object.defineProperty(${stmt.name}.prototype, '${getter.name}', { get: function() {`);
|
||||
ctx.incIndent();
|
||||
if (getter.body.length > 0) {
|
||||
ctx.println(`var self = this;`);
|
||||
this.visitAllStatements(getter.body, ctx);
|
||||
}
|
||||
ctx.decIndent();
|
||||
ctx.println(`}});`);
|
||||
}
|
||||
|
||||
private _visitClassMethod(stmt: o.ClassStmt, method: o.ClassMethod, ctx: EmitterVisitorContext) {
|
||||
ctx.print(`${stmt.name}.prototype.${method.name} = function(`);
|
||||
this._visitParams(method.params, ctx);
|
||||
ctx.println(`) {`);
|
||||
ctx.incIndent();
|
||||
if (method.body.length > 0) {
|
||||
ctx.println(`var self = this;`);
|
||||
this.visitAllStatements(method.body, ctx);
|
||||
}
|
||||
ctx.decIndent();
|
||||
ctx.println(`};`);
|
||||
}
|
||||
|
||||
visitReadVarExpr(ast: o.ReadVarExpr, ctx: EmitterVisitorContext): string {
|
||||
if (ast.builtin === o.BuiltinVar.This) {
|
||||
ctx.print('self');
|
||||
} else if (ast.builtin === o.BuiltinVar.Super) {
|
||||
throw new BaseException(
|
||||
`'super' needs to be handled at a parent ast node, not at the variable level!`);
|
||||
} else {
|
||||
super.visitReadVarExpr(ast, ctx);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
visitDeclareVarStmt(stmt: o.DeclareVarStmt, ctx: EmitterVisitorContext): any {
|
||||
ctx.print(`var ${stmt.name} = `);
|
||||
stmt.value.visitExpression(this, ctx);
|
||||
ctx.println(`;`);
|
||||
return null;
|
||||
}
|
||||
visitCastExpr(ast: o.CastExpr, ctx: EmitterVisitorContext): any {
|
||||
ast.value.visitExpression(this, ctx);
|
||||
return null;
|
||||
}
|
||||
visitInvokeFunctionExpr(expr: o.InvokeFunctionExpr, ctx: EmitterVisitorContext): string {
|
||||
var fnExpr = expr.fn;
|
||||
if (fnExpr instanceof o.ReadVarExpr && fnExpr.builtin === o.BuiltinVar.Super) {
|
||||
ctx.currentClass.parent.visitExpression(this, ctx);
|
||||
ctx.print(`.call(this`);
|
||||
if (expr.args.length > 0) {
|
||||
ctx.print(`, `);
|
||||
this.visitAllExpressions(expr.args, ctx, ',');
|
||||
}
|
||||
ctx.print(`)`);
|
||||
} else {
|
||||
super.visitInvokeFunctionExpr(expr, ctx);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
visitFunctionExpr(ast: o.FunctionExpr, ctx: EmitterVisitorContext): any {
|
||||
ctx.print(`function(`);
|
||||
this._visitParams(ast.params, ctx);
|
||||
ctx.println(`) {`);
|
||||
ctx.incIndent();
|
||||
this.visitAllStatements(ast.statements, ctx);
|
||||
ctx.decIndent();
|
||||
ctx.print(`}`);
|
||||
return null;
|
||||
}
|
||||
visitDeclareFunctionStmt(stmt: o.DeclareFunctionStmt, ctx: EmitterVisitorContext): any {
|
||||
ctx.print(`function ${stmt.name}(`);
|
||||
this._visitParams(stmt.params, ctx);
|
||||
ctx.println(`) {`);
|
||||
ctx.incIndent();
|
||||
this.visitAllStatements(stmt.statements, ctx);
|
||||
ctx.decIndent();
|
||||
ctx.println(`}`);
|
||||
return null;
|
||||
}
|
||||
visitTryCatchStmt(stmt: o.TryCatchStmt, ctx: EmitterVisitorContext): any {
|
||||
ctx.println(`try {`);
|
||||
ctx.incIndent();
|
||||
this.visitAllStatements(stmt.bodyStmts, ctx);
|
||||
ctx.decIndent();
|
||||
ctx.println(`} catch (${CATCH_ERROR_VAR.name}) {`);
|
||||
ctx.incIndent();
|
||||
var catchStmts = [
|
||||
<o.Statement>CATCH_STACK_VAR.set(CATCH_ERROR_VAR.prop('stack'))
|
||||
.toDeclStmt(null, [o.StmtModifier.Final])
|
||||
].concat(stmt.catchStmts);
|
||||
this.visitAllStatements(catchStmts, ctx);
|
||||
ctx.decIndent();
|
||||
ctx.println(`}`);
|
||||
return null;
|
||||
}
|
||||
|
||||
private _visitParams(params: o.FnParam[], ctx: EmitterVisitorContext): void {
|
||||
this.visitAllObjects((param) => ctx.print(param.name), params, ctx, ',');
|
||||
}
|
||||
|
||||
getBuiltinMethodName(method: o.BuiltinMethod): string {
|
||||
var name;
|
||||
switch (method) {
|
||||
case o.BuiltinMethod.ConcatArray:
|
||||
name = 'concat';
|
||||
break;
|
||||
case o.BuiltinMethod.SubscribeObservable:
|
||||
name = 'subscribe';
|
||||
break;
|
||||
case o.BuiltinMethod.bind:
|
||||
name = 'bind';
|
||||
break;
|
||||
default:
|
||||
throw new BaseException(`Unknown builtin method: ${method}`);
|
||||
}
|
||||
return name;
|
||||
}
|
||||
}
|
384
modules/@angular/compiler/src/output/dart_emitter.ts
Normal file
384
modules/@angular/compiler/src/output/dart_emitter.ts
Normal file
@ -0,0 +1,384 @@
|
||||
import {
|
||||
StringWrapper,
|
||||
RegExpWrapper,
|
||||
isPresent,
|
||||
isBlank,
|
||||
Math,
|
||||
isString,
|
||||
isArray
|
||||
} from 'angular2/src/facade/lang';
|
||||
import {ListWrapper} from 'angular2/src/facade/collection';
|
||||
import {BaseException} from 'angular2/src/facade/exceptions';
|
||||
import {CompileIdentifierMetadata} from '../compile_metadata';
|
||||
import * as o from './output_ast';
|
||||
import {
|
||||
OutputEmitter,
|
||||
EmitterVisitorContext,
|
||||
AbstractEmitterVisitor,
|
||||
CATCH_ERROR_VAR,
|
||||
CATCH_STACK_VAR,
|
||||
escapeSingleQuoteString
|
||||
} from './abstract_emitter';
|
||||
import {getImportModulePath, ImportEnv} from './path_util';
|
||||
|
||||
var _debugModuleUrl = 'asset://debug/lib';
|
||||
|
||||
export function debugOutputAstAsDart(ast: o.Statement | o.Expression | o.Type | any[]): string {
|
||||
var converter = new _DartEmitterVisitor(_debugModuleUrl);
|
||||
var ctx = EmitterVisitorContext.createRoot([]);
|
||||
var asts: any[];
|
||||
if (isArray(ast)) {
|
||||
asts = <any[]>ast;
|
||||
} else {
|
||||
asts = [ast];
|
||||
}
|
||||
asts.forEach((ast) => {
|
||||
if (ast instanceof o.Statement) {
|
||||
ast.visitStatement(converter, ctx);
|
||||
} else if (ast instanceof o.Expression) {
|
||||
ast.visitExpression(converter, ctx);
|
||||
} else if (ast instanceof o.Type) {
|
||||
ast.visitType(converter, ctx);
|
||||
} else {
|
||||
throw new BaseException(`Don't know how to print debug info for ${ast}`);
|
||||
}
|
||||
});
|
||||
return ctx.toSource();
|
||||
}
|
||||
|
||||
export class DartEmitter implements OutputEmitter {
|
||||
constructor() {}
|
||||
emitStatements(moduleUrl: string, stmts: o.Statement[], exportedVars: string[]): string {
|
||||
var srcParts = [];
|
||||
// Note: We are not creating a library here as Dart does not need it.
|
||||
// Dart analzyer might complain about it though.
|
||||
|
||||
var converter = new _DartEmitterVisitor(moduleUrl);
|
||||
var ctx = EmitterVisitorContext.createRoot(exportedVars);
|
||||
converter.visitAllStatements(stmts, ctx);
|
||||
|
||||
converter.importsWithPrefixes.forEach((prefix, importedModuleUrl) => {
|
||||
srcParts.push(
|
||||
`import '${getImportModulePath(moduleUrl, importedModuleUrl, ImportEnv.Dart)}' as ${prefix};`);
|
||||
});
|
||||
srcParts.push(ctx.toSource());
|
||||
return srcParts.join('\n');
|
||||
}
|
||||
}
|
||||
|
||||
class _DartEmitterVisitor extends AbstractEmitterVisitor implements o.TypeVisitor {
|
||||
importsWithPrefixes = new Map<string, string>();
|
||||
|
||||
constructor(private _moduleUrl: string) { super(true); }
|
||||
|
||||
visitExternalExpr(ast: o.ExternalExpr, ctx: EmitterVisitorContext): any {
|
||||
this._visitIdentifier(ast.value, ast.typeParams, ctx);
|
||||
return null;
|
||||
}
|
||||
visitDeclareVarStmt(stmt: o.DeclareVarStmt, ctx: EmitterVisitorContext): any {
|
||||
if (stmt.hasModifier(o.StmtModifier.Final)) {
|
||||
if (isConstType(stmt.type)) {
|
||||
ctx.print(`const `);
|
||||
} else {
|
||||
ctx.print(`final `);
|
||||
}
|
||||
} else if (isBlank(stmt.type)) {
|
||||
ctx.print(`var `);
|
||||
}
|
||||
if (isPresent(stmt.type)) {
|
||||
stmt.type.visitType(this, ctx);
|
||||
ctx.print(` `);
|
||||
}
|
||||
ctx.print(`${stmt.name} = `);
|
||||
stmt.value.visitExpression(this, ctx);
|
||||
ctx.println(`;`);
|
||||
return null;
|
||||
}
|
||||
visitCastExpr(ast: o.CastExpr, ctx: EmitterVisitorContext): any {
|
||||
ctx.print(`(`);
|
||||
ast.value.visitExpression(this, ctx);
|
||||
ctx.print(` as `);
|
||||
ast.type.visitType(this, ctx);
|
||||
ctx.print(`)`);
|
||||
return null;
|
||||
}
|
||||
visitDeclareClassStmt(stmt: o.ClassStmt, ctx: EmitterVisitorContext): any {
|
||||
ctx.pushClass(stmt);
|
||||
ctx.print(`class ${stmt.name}`);
|
||||
if (isPresent(stmt.parent)) {
|
||||
ctx.print(` extends `);
|
||||
stmt.parent.visitExpression(this, ctx);
|
||||
}
|
||||
ctx.println(` {`);
|
||||
ctx.incIndent();
|
||||
stmt.fields.forEach((field) => this._visitClassField(field, ctx));
|
||||
if (isPresent(stmt.constructorMethod)) {
|
||||
this._visitClassConstructor(stmt, ctx);
|
||||
}
|
||||
stmt.getters.forEach((getter) => this._visitClassGetter(getter, ctx));
|
||||
stmt.methods.forEach((method) => this._visitClassMethod(method, ctx));
|
||||
ctx.decIndent();
|
||||
ctx.println(`}`);
|
||||
ctx.popClass();
|
||||
return null;
|
||||
}
|
||||
private _visitClassField(field: o.ClassField, ctx: EmitterVisitorContext) {
|
||||
if (field.hasModifier(o.StmtModifier.Final)) {
|
||||
ctx.print(`final `);
|
||||
} else if (isBlank(field.type)) {
|
||||
ctx.print(`var `);
|
||||
}
|
||||
if (isPresent(field.type)) {
|
||||
field.type.visitType(this, ctx);
|
||||
ctx.print(` `);
|
||||
}
|
||||
ctx.println(`${field.name};`);
|
||||
}
|
||||
private _visitClassGetter(getter: o.ClassGetter, ctx: EmitterVisitorContext) {
|
||||
if (isPresent(getter.type)) {
|
||||
getter.type.visitType(this, ctx);
|
||||
ctx.print(` `);
|
||||
}
|
||||
ctx.println(`get ${getter.name} {`);
|
||||
ctx.incIndent();
|
||||
this.visitAllStatements(getter.body, ctx);
|
||||
ctx.decIndent();
|
||||
ctx.println(`}`);
|
||||
}
|
||||
private _visitClassConstructor(stmt: o.ClassStmt, ctx: EmitterVisitorContext) {
|
||||
ctx.print(`${stmt.name}(`);
|
||||
this._visitParams(stmt.constructorMethod.params, ctx);
|
||||
ctx.print(`)`);
|
||||
|
||||
var ctorStmts = stmt.constructorMethod.body;
|
||||
var superCtorExpr = ctorStmts.length > 0 ? getSuperConstructorCallExpr(ctorStmts[0]) : null;
|
||||
if (isPresent(superCtorExpr)) {
|
||||
ctx.print(`: `);
|
||||
superCtorExpr.visitExpression(this, ctx);
|
||||
ctorStmts = ctorStmts.slice(1);
|
||||
}
|
||||
ctx.println(` {`);
|
||||
ctx.incIndent();
|
||||
this.visitAllStatements(ctorStmts, ctx);
|
||||
ctx.decIndent();
|
||||
ctx.println(`}`);
|
||||
}
|
||||
private _visitClassMethod(method: o.ClassMethod, ctx: EmitterVisitorContext) {
|
||||
if (isPresent(method.type)) {
|
||||
method.type.visitType(this, ctx);
|
||||
} else {
|
||||
ctx.print(`void`);
|
||||
}
|
||||
ctx.print(` ${method.name}(`);
|
||||
this._visitParams(method.params, ctx);
|
||||
ctx.println(`) {`);
|
||||
ctx.incIndent();
|
||||
this.visitAllStatements(method.body, ctx);
|
||||
ctx.decIndent();
|
||||
ctx.println(`}`);
|
||||
}
|
||||
|
||||
visitFunctionExpr(ast: o.FunctionExpr, ctx: EmitterVisitorContext): any {
|
||||
ctx.print(`(`);
|
||||
this._visitParams(ast.params, ctx);
|
||||
ctx.println(`) {`);
|
||||
ctx.incIndent();
|
||||
this.visitAllStatements(ast.statements, ctx);
|
||||
ctx.decIndent();
|
||||
ctx.print(`}`);
|
||||
return null;
|
||||
}
|
||||
visitDeclareFunctionStmt(stmt: o.DeclareFunctionStmt, ctx: EmitterVisitorContext): any {
|
||||
if (isPresent(stmt.type)) {
|
||||
stmt.type.visitType(this, ctx);
|
||||
} else {
|
||||
ctx.print(`void`);
|
||||
}
|
||||
ctx.print(` ${stmt.name}(`);
|
||||
this._visitParams(stmt.params, ctx);
|
||||
ctx.println(`) {`);
|
||||
ctx.incIndent();
|
||||
this.visitAllStatements(stmt.statements, ctx);
|
||||
ctx.decIndent();
|
||||
ctx.println(`}`);
|
||||
return null;
|
||||
}
|
||||
|
||||
getBuiltinMethodName(method: o.BuiltinMethod): string {
|
||||
var name;
|
||||
switch (method) {
|
||||
case o.BuiltinMethod.ConcatArray:
|
||||
name = '.addAll';
|
||||
break;
|
||||
case o.BuiltinMethod.SubscribeObservable:
|
||||
name = 'listen';
|
||||
break;
|
||||
case o.BuiltinMethod.bind:
|
||||
name = null;
|
||||
break;
|
||||
default:
|
||||
throw new BaseException(`Unknown builtin method: ${method}`);
|
||||
}
|
||||
return name;
|
||||
}
|
||||
visitTryCatchStmt(stmt: o.TryCatchStmt, ctx: EmitterVisitorContext): any {
|
||||
ctx.println(`try {`);
|
||||
ctx.incIndent();
|
||||
this.visitAllStatements(stmt.bodyStmts, ctx);
|
||||
ctx.decIndent();
|
||||
ctx.println(`} catch (${CATCH_ERROR_VAR.name}, ${CATCH_STACK_VAR.name}) {`);
|
||||
ctx.incIndent();
|
||||
this.visitAllStatements(stmt.catchStmts, ctx);
|
||||
ctx.decIndent();
|
||||
ctx.println(`}`);
|
||||
return null;
|
||||
}
|
||||
visitBinaryOperatorExpr(ast: o.BinaryOperatorExpr, ctx: EmitterVisitorContext): any {
|
||||
switch (ast.operator) {
|
||||
case o.BinaryOperator.Identical:
|
||||
ctx.print(`identical(`);
|
||||
ast.lhs.visitExpression(this, ctx);
|
||||
ctx.print(`, `);
|
||||
ast.rhs.visitExpression(this, ctx);
|
||||
ctx.print(`)`);
|
||||
break;
|
||||
case o.BinaryOperator.NotIdentical:
|
||||
ctx.print(`!identical(`);
|
||||
ast.lhs.visitExpression(this, ctx);
|
||||
ctx.print(`, `);
|
||||
ast.rhs.visitExpression(this, ctx);
|
||||
ctx.print(`)`);
|
||||
break;
|
||||
default:
|
||||
super.visitBinaryOperatorExpr(ast, ctx);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
visitLiteralArrayExpr(ast: o.LiteralArrayExpr, ctx: EmitterVisitorContext): any {
|
||||
if (isConstType(ast.type)) {
|
||||
ctx.print(`const `);
|
||||
}
|
||||
return super.visitLiteralArrayExpr(ast, ctx);
|
||||
}
|
||||
visitLiteralMapExpr(ast: o.LiteralMapExpr, ctx: EmitterVisitorContext): any {
|
||||
if (isConstType(ast.type)) {
|
||||
ctx.print(`const `);
|
||||
}
|
||||
if (isPresent(ast.valueType)) {
|
||||
ctx.print(`<String, `);
|
||||
ast.valueType.visitType(this, ctx);
|
||||
ctx.print(`>`);
|
||||
}
|
||||
return super.visitLiteralMapExpr(ast, ctx);
|
||||
}
|
||||
visitInstantiateExpr(ast: o.InstantiateExpr, ctx: EmitterVisitorContext): any {
|
||||
ctx.print(isConstType(ast.type) ? `const` : `new`);
|
||||
ctx.print(' ');
|
||||
ast.classExpr.visitExpression(this, ctx);
|
||||
ctx.print(`(`);
|
||||
this.visitAllExpressions(ast.args, ctx, `,`);
|
||||
ctx.print(`)`);
|
||||
return null;
|
||||
}
|
||||
visitBuiltintType(type: o.BuiltinType, ctx: EmitterVisitorContext): any {
|
||||
var typeStr;
|
||||
switch (type.name) {
|
||||
case o.BuiltinTypeName.Bool:
|
||||
typeStr = 'bool';
|
||||
break;
|
||||
case o.BuiltinTypeName.Dynamic:
|
||||
typeStr = 'dynamic';
|
||||
break;
|
||||
case o.BuiltinTypeName.Function:
|
||||
typeStr = 'Function';
|
||||
break;
|
||||
case o.BuiltinTypeName.Number:
|
||||
typeStr = 'num';
|
||||
break;
|
||||
case o.BuiltinTypeName.Int:
|
||||
typeStr = 'int';
|
||||
break;
|
||||
case o.BuiltinTypeName.String:
|
||||
typeStr = 'String';
|
||||
break;
|
||||
default:
|
||||
throw new BaseException(`Unsupported builtin type ${type.name}`);
|
||||
}
|
||||
ctx.print(typeStr);
|
||||
return null;
|
||||
}
|
||||
visitExternalType(ast: o.ExternalType, ctx: EmitterVisitorContext): any {
|
||||
this._visitIdentifier(ast.value, ast.typeParams, ctx);
|
||||
return null;
|
||||
}
|
||||
visitArrayType(type: o.ArrayType, ctx: EmitterVisitorContext): any {
|
||||
ctx.print(`List<`);
|
||||
if (isPresent(type.of)) {
|
||||
type.of.visitType(this, ctx);
|
||||
} else {
|
||||
ctx.print(`dynamic`);
|
||||
}
|
||||
ctx.print(`>`);
|
||||
return null;
|
||||
}
|
||||
visitMapType(type: o.MapType, ctx: EmitterVisitorContext): any {
|
||||
ctx.print(`Map<String, `);
|
||||
if (isPresent(type.valueType)) {
|
||||
type.valueType.visitType(this, ctx);
|
||||
} else {
|
||||
ctx.print(`dynamic`);
|
||||
}
|
||||
ctx.print(`>`);
|
||||
return null;
|
||||
}
|
||||
|
||||
private _visitParams(params: o.FnParam[], ctx: EmitterVisitorContext): void {
|
||||
this.visitAllObjects((param) => {
|
||||
if (isPresent(param.type)) {
|
||||
param.type.visitType(this, ctx);
|
||||
ctx.print(' ');
|
||||
}
|
||||
ctx.print(param.name);
|
||||
}, params, ctx, ',');
|
||||
}
|
||||
|
||||
private _visitIdentifier(value: CompileIdentifierMetadata, typeParams: o.Type[],
|
||||
ctx: EmitterVisitorContext): void {
|
||||
if (isBlank(value.name)) {
|
||||
throw new BaseException(`Internal error: unknown identifier ${value}`);
|
||||
}
|
||||
if (isPresent(value.moduleUrl) && value.moduleUrl != this._moduleUrl) {
|
||||
var prefix = this.importsWithPrefixes.get(value.moduleUrl);
|
||||
if (isBlank(prefix)) {
|
||||
prefix = `import${this.importsWithPrefixes.size}`;
|
||||
this.importsWithPrefixes.set(value.moduleUrl, prefix);
|
||||
}
|
||||
ctx.print(`${prefix}.`);
|
||||
}
|
||||
ctx.print(value.name);
|
||||
if (isPresent(typeParams) && typeParams.length > 0) {
|
||||
ctx.print(`<`);
|
||||
this.visitAllObjects((type) => type.visitType(this, ctx), typeParams, ctx, ',');
|
||||
ctx.print(`>`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getSuperConstructorCallExpr(stmt: o.Statement): o.Expression {
|
||||
if (stmt instanceof o.ExpressionStatement) {
|
||||
var expr = stmt.expr;
|
||||
if (expr instanceof o.InvokeFunctionExpr) {
|
||||
var fn = expr.fn;
|
||||
if (fn instanceof o.ReadVarExpr) {
|
||||
if (fn.builtin === o.BuiltinVar.Super) {
|
||||
return expr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function isConstType(type: o.Type): boolean {
|
||||
return isPresent(type) && type.hasModifier(o.TypeModifier.Const);
|
||||
}
|
68
modules/@angular/compiler/src/output/interpretive_view.ts
Normal file
68
modules/@angular/compiler/src/output/interpretive_view.ts
Normal file
@ -0,0 +1,68 @@
|
||||
import {isPresent} from 'angular2/src/facade/lang';
|
||||
import {AppView, DebugAppView} from 'angular2/src/core/linker/view';
|
||||
import {AppElement} from 'angular2/src/core/linker/element';
|
||||
import {BaseException} from 'angular2/src/facade/exceptions';
|
||||
import {InstanceFactory, DynamicInstance} from './output_interpreter';
|
||||
|
||||
export class InterpretiveAppViewInstanceFactory implements InstanceFactory {
|
||||
createInstance(superClass: any, clazz: any, args: any[], props: Map<string, any>,
|
||||
getters: Map<string, Function>, methods: Map<string, Function>): any {
|
||||
if (superClass === AppView) {
|
||||
// We are always using DebugAppView as parent.
|
||||
// However, in prod mode we generate a constructor call that does
|
||||
// not have the argument for the debugNodeInfos.
|
||||
args = args.concat([null]);
|
||||
return new _InterpretiveAppView(args, props, getters, methods);
|
||||
} else if (superClass === DebugAppView) {
|
||||
return new _InterpretiveAppView(args, props, getters, methods);
|
||||
}
|
||||
throw new BaseException(`Can't instantiate class ${superClass} in interpretative mode`);
|
||||
}
|
||||
}
|
||||
|
||||
class _InterpretiveAppView extends DebugAppView<any> implements DynamicInstance {
|
||||
constructor(args: any[], public props: Map<string, any>, public getters: Map<string, Function>,
|
||||
public methods: Map<string, Function>) {
|
||||
super(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);
|
||||
}
|
||||
createInternal(rootSelector: string | any): AppElement {
|
||||
var m = this.methods.get('createInternal');
|
||||
if (isPresent(m)) {
|
||||
return m(rootSelector);
|
||||
} else {
|
||||
return super.createInternal(rootSelector);
|
||||
}
|
||||
}
|
||||
injectorGetInternal(token: any, nodeIndex: number, notFoundResult: any): any {
|
||||
var m = this.methods.get('injectorGetInternal');
|
||||
if (isPresent(m)) {
|
||||
return m(token, nodeIndex, notFoundResult);
|
||||
} else {
|
||||
return super.injectorGet(token, nodeIndex, notFoundResult);
|
||||
}
|
||||
}
|
||||
destroyInternal(): void {
|
||||
var m = this.methods.get('destroyInternal');
|
||||
if (isPresent(m)) {
|
||||
return m();
|
||||
} else {
|
||||
return super.destroyInternal();
|
||||
}
|
||||
}
|
||||
dirtyParentQueriesInternal(): void {
|
||||
var m = this.methods.get('dirtyParentQueriesInternal');
|
||||
if (isPresent(m)) {
|
||||
return m();
|
||||
} else {
|
||||
return super.dirtyParentQueriesInternal();
|
||||
}
|
||||
}
|
||||
detectChangesInternal(throwOnChange: boolean): void {
|
||||
var m = this.methods.get('detectChangesInternal');
|
||||
if (isPresent(m)) {
|
||||
return m(throwOnChange);
|
||||
} else {
|
||||
return super.detectChangesInternal(throwOnChange);
|
||||
}
|
||||
}
|
||||
}
|
77
modules/@angular/compiler/src/output/js_emitter.ts
Normal file
77
modules/@angular/compiler/src/output/js_emitter.ts
Normal file
@ -0,0 +1,77 @@
|
||||
import * as o from './output_ast';
|
||||
import {
|
||||
isPresent,
|
||||
isBlank,
|
||||
isString,
|
||||
evalExpression,
|
||||
RegExpWrapper,
|
||||
StringWrapper
|
||||
} from 'angular2/src/facade/lang';
|
||||
import {BaseException} from 'angular2/src/facade/exceptions';
|
||||
import {OutputEmitter, EmitterVisitorContext} from './abstract_emitter';
|
||||
import {AbstractJsEmitterVisitor} from './abstract_js_emitter';
|
||||
import {getImportModulePath, ImportEnv} from './path_util';
|
||||
|
||||
export class JavaScriptEmitter implements OutputEmitter {
|
||||
constructor() {}
|
||||
emitStatements(moduleUrl: string, stmts: o.Statement[], exportedVars: string[]): string {
|
||||
var converter = new JsEmitterVisitor(moduleUrl);
|
||||
var ctx = EmitterVisitorContext.createRoot(exportedVars);
|
||||
converter.visitAllStatements(stmts, ctx);
|
||||
var srcParts = [];
|
||||
converter.importsWithPrefixes.forEach((prefix, importedModuleUrl) => {
|
||||
// Note: can't write the real word for import as it screws up system.js auto detection...
|
||||
srcParts.push(`var ${prefix} = req` +
|
||||
`uire('${getImportModulePath(moduleUrl, importedModuleUrl, ImportEnv.JS)}');`);
|
||||
});
|
||||
srcParts.push(ctx.toSource());
|
||||
return srcParts.join('\n');
|
||||
}
|
||||
}
|
||||
|
||||
class JsEmitterVisitor extends AbstractJsEmitterVisitor {
|
||||
importsWithPrefixes = new Map<string, string>();
|
||||
|
||||
constructor(private _moduleUrl: string) { super(); }
|
||||
|
||||
visitExternalExpr(ast: o.ExternalExpr, ctx: EmitterVisitorContext): any {
|
||||
if (isBlank(ast.value.name)) {
|
||||
throw new BaseException(`Internal error: unknown identifier ${ast.value}`);
|
||||
}
|
||||
if (isPresent(ast.value.moduleUrl) && ast.value.moduleUrl != this._moduleUrl) {
|
||||
var prefix = this.importsWithPrefixes.get(ast.value.moduleUrl);
|
||||
if (isBlank(prefix)) {
|
||||
prefix = `import${this.importsWithPrefixes.size}`;
|
||||
this.importsWithPrefixes.set(ast.value.moduleUrl, prefix);
|
||||
}
|
||||
ctx.print(`${prefix}.`);
|
||||
}
|
||||
ctx.print(ast.value.name);
|
||||
return null;
|
||||
}
|
||||
visitDeclareVarStmt(stmt: o.DeclareVarStmt, ctx: EmitterVisitorContext): any {
|
||||
super.visitDeclareVarStmt(stmt, ctx);
|
||||
if (ctx.isExportedVar(stmt.name)) {
|
||||
ctx.println(exportVar(stmt.name));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
visitDeclareFunctionStmt(stmt: o.DeclareFunctionStmt, ctx: EmitterVisitorContext): any {
|
||||
super.visitDeclareFunctionStmt(stmt, ctx);
|
||||
if (ctx.isExportedVar(stmt.name)) {
|
||||
ctx.println(exportVar(stmt.name));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
visitDeclareClassStmt(stmt: o.ClassStmt, ctx: EmitterVisitorContext): any {
|
||||
super.visitDeclareClassStmt(stmt, ctx);
|
||||
if (ctx.isExportedVar(stmt.name)) {
|
||||
ctx.println(exportVar(stmt.name));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function exportVar(varName: string): string {
|
||||
return `Object.defineProperty(exports, '${varName}', { get: function() { return ${varName}; }});`;
|
||||
}
|
870
modules/@angular/compiler/src/output/output_ast.ts
Normal file
870
modules/@angular/compiler/src/output/output_ast.ts
Normal file
@ -0,0 +1,870 @@
|
||||
import {isString, isPresent, isBlank} from 'angular2/src/facade/lang';
|
||||
import {CompileIdentifierMetadata} from '../compile_metadata';
|
||||
|
||||
//// Types
|
||||
export enum TypeModifier {
|
||||
Const
|
||||
}
|
||||
|
||||
export abstract class Type {
|
||||
constructor(public modifiers: TypeModifier[] = null) {
|
||||
if (isBlank(modifiers)) {
|
||||
this.modifiers = [];
|
||||
}
|
||||
}
|
||||
abstract visitType(visitor: TypeVisitor, context: any): any;
|
||||
|
||||
hasModifier(modifier: TypeModifier): boolean { return this.modifiers.indexOf(modifier) !== -1; }
|
||||
}
|
||||
|
||||
export enum BuiltinTypeName {
|
||||
Dynamic,
|
||||
Bool,
|
||||
String,
|
||||
Int,
|
||||
Number,
|
||||
Function
|
||||
}
|
||||
|
||||
export class BuiltinType extends Type {
|
||||
constructor(public name: BuiltinTypeName, modifiers: TypeModifier[] = null) { super(modifiers); }
|
||||
visitType(visitor: TypeVisitor, context: any): any {
|
||||
return visitor.visitBuiltintType(this, context);
|
||||
}
|
||||
}
|
||||
|
||||
export class ExternalType extends Type {
|
||||
constructor(public value: CompileIdentifierMetadata, public typeParams: Type[] = null,
|
||||
modifiers: TypeModifier[] = null) {
|
||||
super(modifiers);
|
||||
}
|
||||
visitType(visitor: TypeVisitor, context: any): any {
|
||||
return visitor.visitExternalType(this, context);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export class ArrayType extends Type {
|
||||
constructor(public of: Type, modifiers: TypeModifier[] = null) { super(modifiers); }
|
||||
visitType(visitor: TypeVisitor, context: any): any {
|
||||
return visitor.visitArrayType(this, context);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export class MapType extends Type {
|
||||
constructor(public valueType: Type, modifiers: TypeModifier[] = null) { super(modifiers); }
|
||||
visitType(visitor: TypeVisitor, context: any): any { return visitor.visitMapType(this, context); }
|
||||
}
|
||||
|
||||
export var DYNAMIC_TYPE = new BuiltinType(BuiltinTypeName.Dynamic);
|
||||
export var BOOL_TYPE = new BuiltinType(BuiltinTypeName.Bool);
|
||||
export var INT_TYPE = new BuiltinType(BuiltinTypeName.Int);
|
||||
export var NUMBER_TYPE = new BuiltinType(BuiltinTypeName.Number);
|
||||
export var STRING_TYPE = new BuiltinType(BuiltinTypeName.String);
|
||||
export var FUNCTION_TYPE = new BuiltinType(BuiltinTypeName.Function);
|
||||
|
||||
|
||||
export interface TypeVisitor {
|
||||
visitBuiltintType(type: BuiltinType, context: any): any;
|
||||
visitExternalType(type: ExternalType, context: any): any;
|
||||
visitArrayType(type: ArrayType, context: any): any;
|
||||
visitMapType(type: MapType, context: any): any;
|
||||
}
|
||||
|
||||
///// Expressions
|
||||
|
||||
export enum BinaryOperator {
|
||||
Equals,
|
||||
NotEquals,
|
||||
Identical,
|
||||
NotIdentical,
|
||||
Minus,
|
||||
Plus,
|
||||
Divide,
|
||||
Multiply,
|
||||
Modulo,
|
||||
And,
|
||||
Or,
|
||||
Lower,
|
||||
LowerEquals,
|
||||
Bigger,
|
||||
BiggerEquals
|
||||
}
|
||||
|
||||
|
||||
export abstract class Expression {
|
||||
constructor(public type: Type) {}
|
||||
|
||||
abstract visitExpression(visitor: ExpressionVisitor, context: any): any;
|
||||
|
||||
prop(name: string): ReadPropExpr { return new ReadPropExpr(this, name); }
|
||||
|
||||
key(index: Expression, type: Type = null): ReadKeyExpr {
|
||||
return new ReadKeyExpr(this, index, type);
|
||||
}
|
||||
|
||||
callMethod(name: string | BuiltinMethod, params: Expression[]): InvokeMethodExpr {
|
||||
return new InvokeMethodExpr(this, name, params);
|
||||
}
|
||||
|
||||
callFn(params: Expression[]): InvokeFunctionExpr { return new InvokeFunctionExpr(this, params); }
|
||||
|
||||
instantiate(params: Expression[], type: Type = null): InstantiateExpr {
|
||||
return new InstantiateExpr(this, params, type);
|
||||
}
|
||||
|
||||
conditional(trueCase: Expression, falseCase: Expression = null): ConditionalExpr {
|
||||
return new ConditionalExpr(this, trueCase, falseCase);
|
||||
}
|
||||
|
||||
equals(rhs: Expression): BinaryOperatorExpr {
|
||||
return new BinaryOperatorExpr(BinaryOperator.Equals, this, rhs);
|
||||
}
|
||||
notEquals(rhs: Expression): BinaryOperatorExpr {
|
||||
return new BinaryOperatorExpr(BinaryOperator.NotEquals, this, rhs);
|
||||
}
|
||||
identical(rhs: Expression): BinaryOperatorExpr {
|
||||
return new BinaryOperatorExpr(BinaryOperator.Identical, this, rhs);
|
||||
}
|
||||
notIdentical(rhs: Expression): BinaryOperatorExpr {
|
||||
return new BinaryOperatorExpr(BinaryOperator.NotIdentical, this, rhs);
|
||||
}
|
||||
minus(rhs: Expression): BinaryOperatorExpr {
|
||||
return new BinaryOperatorExpr(BinaryOperator.Minus, this, rhs);
|
||||
}
|
||||
plus(rhs: Expression): BinaryOperatorExpr {
|
||||
return new BinaryOperatorExpr(BinaryOperator.Plus, this, rhs);
|
||||
}
|
||||
divide(rhs: Expression): BinaryOperatorExpr {
|
||||
return new BinaryOperatorExpr(BinaryOperator.Divide, this, rhs);
|
||||
}
|
||||
multiply(rhs: Expression): BinaryOperatorExpr {
|
||||
return new BinaryOperatorExpr(BinaryOperator.Multiply, this, rhs);
|
||||
}
|
||||
modulo(rhs: Expression): BinaryOperatorExpr {
|
||||
return new BinaryOperatorExpr(BinaryOperator.Modulo, this, rhs);
|
||||
}
|
||||
and(rhs: Expression): BinaryOperatorExpr {
|
||||
return new BinaryOperatorExpr(BinaryOperator.And, this, rhs);
|
||||
}
|
||||
or(rhs: Expression): BinaryOperatorExpr {
|
||||
return new BinaryOperatorExpr(BinaryOperator.Or, this, rhs);
|
||||
}
|
||||
lower(rhs: Expression): BinaryOperatorExpr {
|
||||
return new BinaryOperatorExpr(BinaryOperator.Lower, this, rhs);
|
||||
}
|
||||
lowerEquals(rhs: Expression): BinaryOperatorExpr {
|
||||
return new BinaryOperatorExpr(BinaryOperator.LowerEquals, this, rhs);
|
||||
}
|
||||
bigger(rhs: Expression): BinaryOperatorExpr {
|
||||
return new BinaryOperatorExpr(BinaryOperator.Bigger, this, rhs);
|
||||
}
|
||||
biggerEquals(rhs: Expression): BinaryOperatorExpr {
|
||||
return new BinaryOperatorExpr(BinaryOperator.BiggerEquals, this, rhs);
|
||||
}
|
||||
isBlank(): Expression {
|
||||
// Note: We use equals by purpose here to compare to null and undefined in JS.
|
||||
return this.equals(NULL_EXPR);
|
||||
}
|
||||
cast(type: Type): Expression { return new CastExpr(this, type); }
|
||||
toStmt(): Statement { return new ExpressionStatement(this); }
|
||||
}
|
||||
|
||||
export enum BuiltinVar {
|
||||
This,
|
||||
Super,
|
||||
CatchError,
|
||||
CatchStack
|
||||
}
|
||||
|
||||
export class ReadVarExpr extends Expression {
|
||||
public name;
|
||||
public builtin: BuiltinVar;
|
||||
|
||||
constructor(name: string | BuiltinVar, type: Type = null) {
|
||||
super(type);
|
||||
if (isString(name)) {
|
||||
this.name = <string>name;
|
||||
this.builtin = null;
|
||||
} else {
|
||||
this.name = null;
|
||||
this.builtin = <BuiltinVar>name;
|
||||
}
|
||||
}
|
||||
visitExpression(visitor: ExpressionVisitor, context: any): any {
|
||||
return visitor.visitReadVarExpr(this, context);
|
||||
}
|
||||
|
||||
set(value: Expression): WriteVarExpr { return new WriteVarExpr(this.name, value); }
|
||||
}
|
||||
|
||||
|
||||
export class WriteVarExpr extends Expression {
|
||||
public value: Expression;
|
||||
constructor(public name: string, value: Expression, type: Type = null) {
|
||||
super(isPresent(type) ? type : value.type);
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
visitExpression(visitor: ExpressionVisitor, context: any): any {
|
||||
return visitor.visitWriteVarExpr(this, context);
|
||||
}
|
||||
|
||||
toDeclStmt(type: Type = null, modifiers: StmtModifier[] = null): DeclareVarStmt {
|
||||
return new DeclareVarStmt(this.name, this.value, type, modifiers);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export class WriteKeyExpr extends Expression {
|
||||
public value: Expression;
|
||||
constructor(public receiver: Expression, public index: Expression, value: Expression,
|
||||
type: Type = null) {
|
||||
super(isPresent(type) ? type : value.type);
|
||||
this.value = value;
|
||||
}
|
||||
visitExpression(visitor: ExpressionVisitor, context: any): any {
|
||||
return visitor.visitWriteKeyExpr(this, context);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export class WritePropExpr extends Expression {
|
||||
public value: Expression;
|
||||
constructor(public receiver: Expression, public name: string, value: Expression,
|
||||
type: Type = null) {
|
||||
super(isPresent(type) ? type : value.type);
|
||||
this.value = value;
|
||||
}
|
||||
visitExpression(visitor: ExpressionVisitor, context: any): any {
|
||||
return visitor.visitWritePropExpr(this, context);
|
||||
}
|
||||
}
|
||||
|
||||
export enum BuiltinMethod {
|
||||
ConcatArray,
|
||||
SubscribeObservable,
|
||||
bind
|
||||
}
|
||||
|
||||
export class InvokeMethodExpr extends Expression {
|
||||
public name: string;
|
||||
public builtin: BuiltinMethod;
|
||||
constructor(public receiver: Expression, method: string | BuiltinMethod,
|
||||
public args: Expression[], type: Type = null) {
|
||||
super(type);
|
||||
if (isString(method)) {
|
||||
this.name = <string>method;
|
||||
this.builtin = null;
|
||||
} else {
|
||||
this.name = null;
|
||||
this.builtin = <BuiltinMethod>method;
|
||||
}
|
||||
}
|
||||
visitExpression(visitor: ExpressionVisitor, context: any): any {
|
||||
return visitor.visitInvokeMethodExpr(this, context);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export class InvokeFunctionExpr extends Expression {
|
||||
constructor(public fn: Expression, public args: Expression[], type: Type = null) { super(type); }
|
||||
visitExpression(visitor: ExpressionVisitor, context: any): any {
|
||||
return visitor.visitInvokeFunctionExpr(this, context);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export class InstantiateExpr extends Expression {
|
||||
constructor(public classExpr: Expression, public args: Expression[], type?: Type) { super(type); }
|
||||
visitExpression(visitor: ExpressionVisitor, context: any): any {
|
||||
return visitor.visitInstantiateExpr(this, context);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export class LiteralExpr extends Expression {
|
||||
constructor(public value: any, type: Type = null) { super(type); }
|
||||
visitExpression(visitor: ExpressionVisitor, context: any): any {
|
||||
return visitor.visitLiteralExpr(this, context);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export class ExternalExpr extends Expression {
|
||||
constructor(public value: CompileIdentifierMetadata, type: Type = null,
|
||||
public typeParams: Type[] = null) {
|
||||
super(type);
|
||||
}
|
||||
visitExpression(visitor: ExpressionVisitor, context: any): any {
|
||||
return visitor.visitExternalExpr(this, context);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export class ConditionalExpr extends Expression {
|
||||
public trueCase: Expression;
|
||||
constructor(public condition: Expression, trueCase: Expression,
|
||||
public falseCase: Expression = null, type: Type = null) {
|
||||
super(isPresent(type) ? type : trueCase.type);
|
||||
this.trueCase = trueCase;
|
||||
}
|
||||
visitExpression(visitor: ExpressionVisitor, context: any): any {
|
||||
return visitor.visitConditionalExpr(this, context);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export class NotExpr extends Expression {
|
||||
constructor(public condition: Expression) { super(BOOL_TYPE); }
|
||||
visitExpression(visitor: ExpressionVisitor, context: any): any {
|
||||
return visitor.visitNotExpr(this, context);
|
||||
}
|
||||
}
|
||||
|
||||
export class CastExpr extends Expression {
|
||||
constructor(public value: Expression, type: Type) { super(type); }
|
||||
visitExpression(visitor: ExpressionVisitor, context: any): any {
|
||||
return visitor.visitCastExpr(this, context);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export class FnParam {
|
||||
constructor(public name: string, public type: Type = null) {}
|
||||
}
|
||||
|
||||
|
||||
export class FunctionExpr extends Expression {
|
||||
constructor(public params: FnParam[], public statements: Statement[], type: Type = null) {
|
||||
super(type);
|
||||
}
|
||||
visitExpression(visitor: ExpressionVisitor, context: any): any {
|
||||
return visitor.visitFunctionExpr(this, context);
|
||||
}
|
||||
|
||||
toDeclStmt(name: string, modifiers: StmtModifier[] = null): DeclareFunctionStmt {
|
||||
return new DeclareFunctionStmt(name, this.params, this.statements, this.type, modifiers);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export class BinaryOperatorExpr extends Expression {
|
||||
public lhs: Expression;
|
||||
constructor(public operator: BinaryOperator, lhs: Expression, public rhs: Expression,
|
||||
type: Type = null) {
|
||||
super(isPresent(type) ? type : lhs.type);
|
||||
this.lhs = lhs;
|
||||
}
|
||||
visitExpression(visitor: ExpressionVisitor, context: any): any {
|
||||
return visitor.visitBinaryOperatorExpr(this, context);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export class ReadPropExpr extends Expression {
|
||||
constructor(public receiver: Expression, public name: string, type: Type = null) { super(type); }
|
||||
visitExpression(visitor: ExpressionVisitor, context: any): any {
|
||||
return visitor.visitReadPropExpr(this, context);
|
||||
}
|
||||
set(value: Expression): WritePropExpr {
|
||||
return new WritePropExpr(this.receiver, this.name, value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export class ReadKeyExpr extends Expression {
|
||||
constructor(public receiver: Expression, public index: Expression, type: Type = null) {
|
||||
super(type);
|
||||
}
|
||||
visitExpression(visitor: ExpressionVisitor, context: any): any {
|
||||
return visitor.visitReadKeyExpr(this, context);
|
||||
}
|
||||
set(value: Expression): WriteKeyExpr {
|
||||
return new WriteKeyExpr(this.receiver, this.index, value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export class LiteralArrayExpr extends Expression {
|
||||
public entries: Expression[];
|
||||
constructor(entries: Expression[], type: Type = null) {
|
||||
super(type);
|
||||
this.entries = entries;
|
||||
}
|
||||
visitExpression(visitor: ExpressionVisitor, context: any): any {
|
||||
return visitor.visitLiteralArrayExpr(this, context);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export class LiteralMapExpr extends Expression {
|
||||
public valueType: Type = null;
|
||||
;
|
||||
constructor(public entries: Array<Array<string | Expression>>, type: MapType = null) {
|
||||
super(type);
|
||||
if (isPresent(type)) {
|
||||
this.valueType = type.valueType;
|
||||
}
|
||||
}
|
||||
visitExpression(visitor: ExpressionVisitor, context: any): any {
|
||||
return visitor.visitLiteralMapExpr(this, context);
|
||||
}
|
||||
}
|
||||
|
||||
export interface ExpressionVisitor {
|
||||
visitReadVarExpr(ast: ReadVarExpr, context: any): any;
|
||||
visitWriteVarExpr(expr: WriteVarExpr, context: any): any;
|
||||
visitWriteKeyExpr(expr: WriteKeyExpr, context: any): any;
|
||||
visitWritePropExpr(expr: WritePropExpr, context: any): any;
|
||||
visitInvokeMethodExpr(ast: InvokeMethodExpr, context: any): any;
|
||||
visitInvokeFunctionExpr(ast: InvokeFunctionExpr, context: any): any;
|
||||
visitInstantiateExpr(ast: InstantiateExpr, context: any): any;
|
||||
visitLiteralExpr(ast: LiteralExpr, context: any): any;
|
||||
visitExternalExpr(ast: ExternalExpr, context: any): any;
|
||||
visitConditionalExpr(ast: ConditionalExpr, context: any): any;
|
||||
visitNotExpr(ast: NotExpr, context: any): any;
|
||||
visitCastExpr(ast: CastExpr, context: any): any;
|
||||
visitFunctionExpr(ast: FunctionExpr, context: any): any;
|
||||
visitBinaryOperatorExpr(ast: BinaryOperatorExpr, context: any): any;
|
||||
visitReadPropExpr(ast: ReadPropExpr, context: any): any;
|
||||
visitReadKeyExpr(ast: ReadKeyExpr, context: any): any;
|
||||
visitLiteralArrayExpr(ast: LiteralArrayExpr, context: any): any;
|
||||
visitLiteralMapExpr(ast: LiteralMapExpr, context: any): any;
|
||||
}
|
||||
|
||||
export var THIS_EXPR = new ReadVarExpr(BuiltinVar.This);
|
||||
export var SUPER_EXPR = new ReadVarExpr(BuiltinVar.Super);
|
||||
export var CATCH_ERROR_VAR = new ReadVarExpr(BuiltinVar.CatchError);
|
||||
export var CATCH_STACK_VAR = new ReadVarExpr(BuiltinVar.CatchStack);
|
||||
export var NULL_EXPR = new LiteralExpr(null, null);
|
||||
|
||||
//// Statements
|
||||
export enum StmtModifier {
|
||||
Final,
|
||||
Private
|
||||
}
|
||||
|
||||
export abstract class Statement {
|
||||
constructor(public modifiers: StmtModifier[] = null) {
|
||||
if (isBlank(modifiers)) {
|
||||
this.modifiers = [];
|
||||
}
|
||||
}
|
||||
|
||||
abstract visitStatement(visitor: StatementVisitor, context: any): any;
|
||||
|
||||
hasModifier(modifier: StmtModifier): boolean { return this.modifiers.indexOf(modifier) !== -1; }
|
||||
}
|
||||
|
||||
|
||||
export class DeclareVarStmt extends Statement {
|
||||
public type: Type;
|
||||
constructor(public name: string, public value: Expression, type: Type = null,
|
||||
modifiers: StmtModifier[] = null) {
|
||||
super(modifiers);
|
||||
this.type = isPresent(type) ? type : value.type;
|
||||
}
|
||||
|
||||
visitStatement(visitor: StatementVisitor, context: any): any {
|
||||
return visitor.visitDeclareVarStmt(this, context);
|
||||
}
|
||||
}
|
||||
|
||||
export class DeclareFunctionStmt extends Statement {
|
||||
constructor(public name: string, public params: FnParam[], public statements: Statement[],
|
||||
public type: Type = null, modifiers: StmtModifier[] = null) {
|
||||
super(modifiers);
|
||||
}
|
||||
|
||||
visitStatement(visitor: StatementVisitor, context: any): any {
|
||||
return visitor.visitDeclareFunctionStmt(this, context);
|
||||
}
|
||||
}
|
||||
|
||||
export class ExpressionStatement extends Statement {
|
||||
constructor(public expr: Expression) { super(); }
|
||||
|
||||
visitStatement(visitor: StatementVisitor, context: any): any {
|
||||
return visitor.visitExpressionStmt(this, context);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export class ReturnStatement extends Statement {
|
||||
constructor(public value: Expression) { super(); }
|
||||
visitStatement(visitor: StatementVisitor, context: any): any {
|
||||
return visitor.visitReturnStmt(this, context);
|
||||
}
|
||||
}
|
||||
|
||||
export class AbstractClassPart {
|
||||
constructor(public type: Type = null, public modifiers: StmtModifier[]) {
|
||||
if (isBlank(modifiers)) {
|
||||
this.modifiers = [];
|
||||
}
|
||||
}
|
||||
hasModifier(modifier: StmtModifier): boolean { return this.modifiers.indexOf(modifier) !== -1; }
|
||||
}
|
||||
|
||||
export class ClassField extends AbstractClassPart {
|
||||
constructor(public name: string, type: Type = null, modifiers: StmtModifier[] = null) {
|
||||
super(type, modifiers);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export class ClassMethod extends AbstractClassPart {
|
||||
constructor(public name: string, public params: FnParam[], public body: Statement[],
|
||||
type: Type = null, modifiers: StmtModifier[] = null) {
|
||||
super(type, modifiers);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export class ClassGetter extends AbstractClassPart {
|
||||
constructor(public name: string, public body: Statement[], type: Type = null,
|
||||
modifiers: StmtModifier[] = null) {
|
||||
super(type, modifiers);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export class ClassStmt extends Statement {
|
||||
constructor(public name: string, public parent: Expression, public fields: ClassField[],
|
||||
public getters: ClassGetter[], public constructorMethod: ClassMethod,
|
||||
public methods: ClassMethod[], modifiers: StmtModifier[] = null) {
|
||||
super(modifiers);
|
||||
}
|
||||
visitStatement(visitor: StatementVisitor, context: any): any {
|
||||
return visitor.visitDeclareClassStmt(this, context);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export class IfStmt extends Statement {
|
||||
constructor(public condition: Expression, public trueCase: Statement[],
|
||||
public falseCase: Statement[] = /*@ts2dart_const*/[]) {
|
||||
super();
|
||||
}
|
||||
visitStatement(visitor: StatementVisitor, context: any): any {
|
||||
return visitor.visitIfStmt(this, context);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export class CommentStmt extends Statement {
|
||||
constructor(public comment: string) { super(); }
|
||||
visitStatement(visitor: StatementVisitor, context: any): any {
|
||||
return visitor.visitCommentStmt(this, context);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export class TryCatchStmt extends Statement {
|
||||
constructor(public bodyStmts: Statement[], public catchStmts: Statement[]) { super(); }
|
||||
visitStatement(visitor: StatementVisitor, context: any): any {
|
||||
return visitor.visitTryCatchStmt(this, context);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export class ThrowStmt extends Statement {
|
||||
constructor(public error: Expression) { super(); }
|
||||
visitStatement(visitor: StatementVisitor, context: any): any {
|
||||
return visitor.visitThrowStmt(this, context);
|
||||
}
|
||||
}
|
||||
|
||||
export interface StatementVisitor {
|
||||
visitDeclareVarStmt(stmt: DeclareVarStmt, context: any): any;
|
||||
visitDeclareFunctionStmt(stmt: DeclareFunctionStmt, context: any): any;
|
||||
visitExpressionStmt(stmt: ExpressionStatement, context: any): any;
|
||||
visitReturnStmt(stmt: ReturnStatement, context: any): any;
|
||||
visitDeclareClassStmt(stmt: ClassStmt, context: any): any;
|
||||
visitIfStmt(stmt: IfStmt, context: any): any;
|
||||
visitTryCatchStmt(stmt: TryCatchStmt, context: any): any;
|
||||
visitThrowStmt(stmt: ThrowStmt, context: any): any;
|
||||
visitCommentStmt(stmt: CommentStmt, context: any): any;
|
||||
}
|
||||
|
||||
export class ExpressionTransformer implements StatementVisitor, ExpressionVisitor {
|
||||
visitReadVarExpr(ast: ReadVarExpr, context: any): any { return ast; }
|
||||
visitWriteVarExpr(expr: WriteVarExpr, context: any): any {
|
||||
return new WriteVarExpr(expr.name, expr.value.visitExpression(this, context));
|
||||
}
|
||||
visitWriteKeyExpr(expr: WriteKeyExpr, context: any): any {
|
||||
return new WriteKeyExpr(expr.receiver.visitExpression(this, context),
|
||||
expr.index.visitExpression(this, context),
|
||||
expr.value.visitExpression(this, context));
|
||||
}
|
||||
visitWritePropExpr(expr: WritePropExpr, context: any): any {
|
||||
return new WritePropExpr(expr.receiver.visitExpression(this, context), expr.name,
|
||||
expr.value.visitExpression(this, context));
|
||||
}
|
||||
visitInvokeMethodExpr(ast: InvokeMethodExpr, context: any): any {
|
||||
var method = isPresent(ast.builtin) ? ast.builtin : ast.name;
|
||||
return new InvokeMethodExpr(ast.receiver.visitExpression(this, context), method,
|
||||
this.visitAllExpressions(ast.args, context), ast.type);
|
||||
}
|
||||
visitInvokeFunctionExpr(ast: InvokeFunctionExpr, context: any): any {
|
||||
return new InvokeFunctionExpr(ast.fn.visitExpression(this, context),
|
||||
this.visitAllExpressions(ast.args, context), ast.type);
|
||||
}
|
||||
visitInstantiateExpr(ast: InstantiateExpr, context: any): any {
|
||||
return new InstantiateExpr(ast.classExpr.visitExpression(this, context),
|
||||
this.visitAllExpressions(ast.args, context), ast.type);
|
||||
}
|
||||
visitLiteralExpr(ast: LiteralExpr, context: any): any { return ast; }
|
||||
visitExternalExpr(ast: ExternalExpr, context: any): any { return ast; }
|
||||
visitConditionalExpr(ast: ConditionalExpr, context: any): any {
|
||||
return new ConditionalExpr(ast.condition.visitExpression(this, context),
|
||||
ast.trueCase.visitExpression(this, context),
|
||||
ast.falseCase.visitExpression(this, context));
|
||||
}
|
||||
visitNotExpr(ast: NotExpr, context: any): any {
|
||||
return new NotExpr(ast.condition.visitExpression(this, context));
|
||||
}
|
||||
visitCastExpr(ast: CastExpr, context: any): any {
|
||||
return new CastExpr(ast.value.visitExpression(this, context), context);
|
||||
}
|
||||
visitFunctionExpr(ast: FunctionExpr, context: any): any {
|
||||
// Don't descend into nested functions
|
||||
return ast;
|
||||
}
|
||||
visitBinaryOperatorExpr(ast: BinaryOperatorExpr, context: any): any {
|
||||
return new BinaryOperatorExpr(ast.operator, ast.lhs.visitExpression(this, context),
|
||||
ast.rhs.visitExpression(this, context), ast.type);
|
||||
}
|
||||
visitReadPropExpr(ast: ReadPropExpr, context: any): any {
|
||||
return new ReadPropExpr(ast.receiver.visitExpression(this, context), ast.name, ast.type);
|
||||
}
|
||||
visitReadKeyExpr(ast: ReadKeyExpr, context: any): any {
|
||||
return new ReadKeyExpr(ast.receiver.visitExpression(this, context),
|
||||
ast.index.visitExpression(this, context), ast.type);
|
||||
}
|
||||
visitLiteralArrayExpr(ast: LiteralArrayExpr, context: any): any {
|
||||
return new LiteralArrayExpr(this.visitAllExpressions(ast.entries, context));
|
||||
}
|
||||
visitLiteralMapExpr(ast: LiteralMapExpr, context: any): any {
|
||||
return new LiteralMapExpr(ast.entries.map(
|
||||
(entry) => [entry[0], (<Expression>entry[1]).visitExpression(this, context)]));
|
||||
}
|
||||
visitAllExpressions(exprs: Expression[], context: any): Expression[] {
|
||||
return exprs.map(expr => expr.visitExpression(this, context));
|
||||
}
|
||||
|
||||
visitDeclareVarStmt(stmt: DeclareVarStmt, context: any): any {
|
||||
return new DeclareVarStmt(stmt.name, stmt.value.visitExpression(this, context), stmt.type,
|
||||
stmt.modifiers);
|
||||
}
|
||||
visitDeclareFunctionStmt(stmt: DeclareFunctionStmt, context: any): any {
|
||||
// Don't descend into nested functions
|
||||
return stmt;
|
||||
}
|
||||
visitExpressionStmt(stmt: ExpressionStatement, context: any): any {
|
||||
return new ExpressionStatement(stmt.expr.visitExpression(this, context));
|
||||
}
|
||||
visitReturnStmt(stmt: ReturnStatement, context: any): any {
|
||||
return new ReturnStatement(stmt.value.visitExpression(this, context));
|
||||
}
|
||||
visitDeclareClassStmt(stmt: ClassStmt, context: any): any {
|
||||
// Don't descend into nested functions
|
||||
return stmt;
|
||||
}
|
||||
visitIfStmt(stmt: IfStmt, context: any): any {
|
||||
return new IfStmt(stmt.condition.visitExpression(this, context),
|
||||
this.visitAllStatements(stmt.trueCase, context),
|
||||
this.visitAllStatements(stmt.falseCase, context));
|
||||
}
|
||||
visitTryCatchStmt(stmt: TryCatchStmt, context: any): any {
|
||||
return new TryCatchStmt(this.visitAllStatements(stmt.bodyStmts, context),
|
||||
this.visitAllStatements(stmt.catchStmts, context));
|
||||
}
|
||||
visitThrowStmt(stmt: ThrowStmt, context: any): any {
|
||||
return new ThrowStmt(stmt.error.visitExpression(this, context));
|
||||
}
|
||||
visitCommentStmt(stmt: CommentStmt, context: any): any { return stmt; }
|
||||
visitAllStatements(stmts: Statement[], context: any): Statement[] {
|
||||
return stmts.map(stmt => stmt.visitStatement(this, context));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export class RecursiveExpressionVisitor implements StatementVisitor, ExpressionVisitor {
|
||||
visitReadVarExpr(ast: ReadVarExpr, context: any): any { return ast; }
|
||||
visitWriteVarExpr(expr: WriteVarExpr, context: any): any {
|
||||
expr.value.visitExpression(this, context);
|
||||
return expr;
|
||||
}
|
||||
visitWriteKeyExpr(expr: WriteKeyExpr, context: any): any {
|
||||
expr.receiver.visitExpression(this, context);
|
||||
expr.index.visitExpression(this, context);
|
||||
expr.value.visitExpression(this, context);
|
||||
return expr;
|
||||
}
|
||||
visitWritePropExpr(expr: WritePropExpr, context: any): any {
|
||||
expr.receiver.visitExpression(this, context);
|
||||
expr.value.visitExpression(this, context);
|
||||
return expr;
|
||||
}
|
||||
visitInvokeMethodExpr(ast: InvokeMethodExpr, context: any): any {
|
||||
ast.receiver.visitExpression(this, context);
|
||||
this.visitAllExpressions(ast.args, context);
|
||||
return ast;
|
||||
}
|
||||
visitInvokeFunctionExpr(ast: InvokeFunctionExpr, context: any): any {
|
||||
ast.fn.visitExpression(this, context);
|
||||
this.visitAllExpressions(ast.args, context);
|
||||
return ast;
|
||||
}
|
||||
visitInstantiateExpr(ast: InstantiateExpr, context: any): any {
|
||||
ast.classExpr.visitExpression(this, context);
|
||||
this.visitAllExpressions(ast.args, context);
|
||||
return ast;
|
||||
}
|
||||
visitLiteralExpr(ast: LiteralExpr, context: any): any { return ast; }
|
||||
visitExternalExpr(ast: ExternalExpr, context: any): any { return ast; }
|
||||
visitConditionalExpr(ast: ConditionalExpr, context: any): any {
|
||||
ast.condition.visitExpression(this, context);
|
||||
ast.trueCase.visitExpression(this, context);
|
||||
ast.falseCase.visitExpression(this, context);
|
||||
return ast;
|
||||
}
|
||||
visitNotExpr(ast: NotExpr, context: any): any {
|
||||
ast.condition.visitExpression(this, context);
|
||||
return ast;
|
||||
}
|
||||
visitCastExpr(ast: CastExpr, context: any): any {
|
||||
ast.value.visitExpression(this, context);
|
||||
return ast;
|
||||
}
|
||||
visitFunctionExpr(ast: FunctionExpr, context: any): any { return ast; }
|
||||
visitBinaryOperatorExpr(ast: BinaryOperatorExpr, context: any): any {
|
||||
ast.lhs.visitExpression(this, context);
|
||||
ast.rhs.visitExpression(this, context);
|
||||
return ast;
|
||||
}
|
||||
visitReadPropExpr(ast: ReadPropExpr, context: any): any {
|
||||
ast.receiver.visitExpression(this, context);
|
||||
return ast;
|
||||
}
|
||||
visitReadKeyExpr(ast: ReadKeyExpr, context: any): any {
|
||||
ast.receiver.visitExpression(this, context);
|
||||
ast.index.visitExpression(this, context);
|
||||
return ast;
|
||||
}
|
||||
visitLiteralArrayExpr(ast: LiteralArrayExpr, context: any): any {
|
||||
this.visitAllExpressions(ast.entries, context);
|
||||
return ast;
|
||||
}
|
||||
visitLiteralMapExpr(ast: LiteralMapExpr, context: any): any {
|
||||
ast.entries.forEach((entry) => (<Expression>entry[1]).visitExpression(this, context));
|
||||
return ast;
|
||||
}
|
||||
visitAllExpressions(exprs: Expression[], context: any): void {
|
||||
exprs.forEach(expr => expr.visitExpression(this, context));
|
||||
}
|
||||
|
||||
visitDeclareVarStmt(stmt: DeclareVarStmt, context: any): any {
|
||||
stmt.value.visitExpression(this, context);
|
||||
return stmt;
|
||||
}
|
||||
visitDeclareFunctionStmt(stmt: DeclareFunctionStmt, context: any): any {
|
||||
// Don't descend into nested functions
|
||||
return stmt;
|
||||
}
|
||||
visitExpressionStmt(stmt: ExpressionStatement, context: any): any {
|
||||
stmt.expr.visitExpression(this, context);
|
||||
return stmt;
|
||||
}
|
||||
visitReturnStmt(stmt: ReturnStatement, context: any): any {
|
||||
stmt.value.visitExpression(this, context);
|
||||
return stmt;
|
||||
}
|
||||
visitDeclareClassStmt(stmt: ClassStmt, context: any): any {
|
||||
// Don't descend into nested functions
|
||||
return stmt;
|
||||
}
|
||||
visitIfStmt(stmt: IfStmt, context: any): any {
|
||||
stmt.condition.visitExpression(this, context);
|
||||
this.visitAllStatements(stmt.trueCase, context);
|
||||
this.visitAllStatements(stmt.falseCase, context);
|
||||
return stmt;
|
||||
}
|
||||
visitTryCatchStmt(stmt: TryCatchStmt, context: any): any {
|
||||
this.visitAllStatements(stmt.bodyStmts, context);
|
||||
this.visitAllStatements(stmt.catchStmts, context);
|
||||
return stmt;
|
||||
}
|
||||
visitThrowStmt(stmt: ThrowStmt, context: any): any {
|
||||
stmt.error.visitExpression(this, context);
|
||||
return stmt;
|
||||
}
|
||||
visitCommentStmt(stmt: CommentStmt, context: any): any { return stmt; }
|
||||
visitAllStatements(stmts: Statement[], context: any): void {
|
||||
stmts.forEach(stmt => stmt.visitStatement(this, context));
|
||||
}
|
||||
}
|
||||
|
||||
export function replaceVarInExpression(varName: string, newValue: Expression,
|
||||
expression: Expression): Expression {
|
||||
var transformer = new _ReplaceVariableTransformer(varName, newValue);
|
||||
return expression.visitExpression(transformer, null);
|
||||
}
|
||||
|
||||
class _ReplaceVariableTransformer extends ExpressionTransformer {
|
||||
constructor(private _varName: string, private _newValue: Expression) { super(); }
|
||||
visitReadVarExpr(ast: ReadVarExpr, context: any): any {
|
||||
return ast.name == this._varName ? this._newValue : ast;
|
||||
}
|
||||
}
|
||||
|
||||
export function findReadVarNames(stmts: Statement[]): Set<string> {
|
||||
var finder = new _VariableFinder();
|
||||
finder.visitAllStatements(stmts, null);
|
||||
return finder.varNames;
|
||||
}
|
||||
|
||||
class _VariableFinder extends RecursiveExpressionVisitor {
|
||||
varNames = new Set<string>();
|
||||
visitReadVarExpr(ast: ReadVarExpr, context: any): any {
|
||||
this.varNames.add(ast.name);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export function variable(name: string, type: Type = null): ReadVarExpr {
|
||||
return new ReadVarExpr(name, type);
|
||||
}
|
||||
|
||||
export function importExpr(id: CompileIdentifierMetadata, typeParams: Type[] = null): ExternalExpr {
|
||||
return new ExternalExpr(id, null, typeParams);
|
||||
}
|
||||
|
||||
export function importType(id: CompileIdentifierMetadata, typeParams: Type[] = null,
|
||||
typeModifiers: TypeModifier[] = null): ExternalType {
|
||||
return isPresent(id) ? new ExternalType(id, typeParams, typeModifiers) : null;
|
||||
}
|
||||
|
||||
export function literal(value: any, type: Type = null): LiteralExpr {
|
||||
return new LiteralExpr(value, type);
|
||||
}
|
||||
|
||||
export function literalArr(values: Expression[], type: Type = null): LiteralArrayExpr {
|
||||
return new LiteralArrayExpr(values, type);
|
||||
}
|
||||
|
||||
export function literalMap(values: Array<Array<string | Expression>>,
|
||||
type: MapType = null): LiteralMapExpr {
|
||||
return new LiteralMapExpr(values, type);
|
||||
}
|
||||
|
||||
export function not(expr: Expression): NotExpr {
|
||||
return new NotExpr(expr);
|
||||
}
|
||||
|
||||
export function fn(params: FnParam[], body: Statement[], type: Type = null): FunctionExpr {
|
||||
return new FunctionExpr(params, body, type);
|
||||
}
|
422
modules/@angular/compiler/src/output/output_interpreter.ts
Normal file
422
modules/@angular/compiler/src/output/output_interpreter.ts
Normal file
@ -0,0 +1,422 @@
|
||||
import {
|
||||
isPresent,
|
||||
isBlank,
|
||||
isString,
|
||||
evalExpression,
|
||||
IS_DART,
|
||||
FunctionWrapper
|
||||
} from 'angular2/src/facade/lang';
|
||||
import {ObservableWrapper} from 'angular2/src/facade/async';
|
||||
import * as o from './output_ast';
|
||||
import {reflector} from 'angular2/src/core/reflection/reflection';
|
||||
import {BaseException, unimplemented} from 'angular2/src/facade/exceptions';
|
||||
import {MapWrapper, ListWrapper} from 'angular2/src/facade/collection';
|
||||
import {debugOutputAstAsDart} from './dart_emitter';
|
||||
import {debugOutputAstAsTypeScript} from './ts_emitter';
|
||||
|
||||
export function interpretStatements(statements: o.Statement[], resultVar: string,
|
||||
instanceFactory: InstanceFactory): any {
|
||||
var stmtsWithReturn = statements.concat([new o.ReturnStatement(o.variable(resultVar))]);
|
||||
var ctx = new _ExecutionContext(null, null, null, null, new Map<string, any>(),
|
||||
new Map<string, any>(), new Map<string, Function>(),
|
||||
new Map<string, Function>(), instanceFactory);
|
||||
var visitor = new StatementInterpreter();
|
||||
var result = visitor.visitAllStatements(stmtsWithReturn, ctx);
|
||||
return isPresent(result) ? result.value : null;
|
||||
}
|
||||
|
||||
export interface InstanceFactory {
|
||||
createInstance(superClass: any, clazz: any, constructorArgs: any[], props: Map<string, any>,
|
||||
getters: Map<string, Function>, methods: Map<string, Function>): DynamicInstance;
|
||||
}
|
||||
|
||||
export abstract class DynamicInstance {
|
||||
get props(): Map<string, any> { return unimplemented(); }
|
||||
get getters(): Map<string, Function> { return unimplemented(); }
|
||||
get methods(): Map<string, any> { return unimplemented(); }
|
||||
get clazz(): any { return unimplemented(); }
|
||||
}
|
||||
|
||||
function isDynamicInstance(instance: any): any {
|
||||
if (IS_DART) {
|
||||
return instance instanceof DynamicInstance;
|
||||
} else {
|
||||
return isPresent(instance) && isPresent(instance.props) && isPresent(instance.getters) &&
|
||||
isPresent(instance.methods);
|
||||
}
|
||||
}
|
||||
|
||||
function _executeFunctionStatements(varNames: string[], varValues: any[], statements: o.Statement[],
|
||||
ctx: _ExecutionContext, visitor: StatementInterpreter): any {
|
||||
var childCtx = ctx.createChildWihtLocalVars();
|
||||
for (var i = 0; i < varNames.length; i++) {
|
||||
childCtx.vars.set(varNames[i], varValues[i]);
|
||||
}
|
||||
var result = visitor.visitAllStatements(statements, childCtx);
|
||||
return isPresent(result) ? result.value : null;
|
||||
}
|
||||
|
||||
class _ExecutionContext {
|
||||
constructor(public parent: _ExecutionContext, public superClass: any, public superInstance: any,
|
||||
public className: string, public vars: Map<string, any>,
|
||||
public props: Map<string, any>, public getters: Map<string, Function>,
|
||||
public methods: Map<string, Function>, public instanceFactory: InstanceFactory) {}
|
||||
|
||||
createChildWihtLocalVars(): _ExecutionContext {
|
||||
return new _ExecutionContext(this, this.superClass, this.superInstance, this.className,
|
||||
new Map<string, any>(), this.props, this.getters, this.methods,
|
||||
this.instanceFactory);
|
||||
}
|
||||
}
|
||||
|
||||
class ReturnValue {
|
||||
constructor(public value: any) {}
|
||||
}
|
||||
|
||||
class _DynamicClass {
|
||||
constructor(private _classStmt: o.ClassStmt, private _ctx: _ExecutionContext,
|
||||
private _visitor: StatementInterpreter) {}
|
||||
|
||||
instantiate(args: any[]): DynamicInstance {
|
||||
var props = new Map<string, any>();
|
||||
var getters = new Map<string, Function>();
|
||||
var methods = new Map<string, Function>();
|
||||
var superClass = this._classStmt.parent.visitExpression(this._visitor, this._ctx);
|
||||
var instanceCtx =
|
||||
new _ExecutionContext(this._ctx, superClass, null, this._classStmt.name, this._ctx.vars,
|
||||
props, getters, methods, this._ctx.instanceFactory);
|
||||
|
||||
this._classStmt.fields.forEach((field: o.ClassField) => { props.set(field.name, null); });
|
||||
this._classStmt.getters.forEach((getter: o.ClassGetter) => {
|
||||
getters.set(getter.name, () => _executeFunctionStatements([], [], getter.body, instanceCtx,
|
||||
this._visitor));
|
||||
});
|
||||
this._classStmt.methods.forEach((method: o.ClassMethod) => {
|
||||
var paramNames = method.params.map(param => param.name);
|
||||
methods.set(method.name, _declareFn(paramNames, method.body, instanceCtx, this._visitor));
|
||||
});
|
||||
|
||||
var ctorParamNames = this._classStmt.constructorMethod.params.map(param => param.name);
|
||||
_executeFunctionStatements(ctorParamNames, args, this._classStmt.constructorMethod.body,
|
||||
instanceCtx, this._visitor);
|
||||
return instanceCtx.superInstance;
|
||||
}
|
||||
|
||||
debugAst(): string { return this._visitor.debugAst(this._classStmt); }
|
||||
}
|
||||
|
||||
class StatementInterpreter implements o.StatementVisitor, o.ExpressionVisitor {
|
||||
debugAst(ast: o.Expression | o.Statement | o.Type): string {
|
||||
return IS_DART ? debugOutputAstAsDart(ast) : debugOutputAstAsTypeScript(ast);
|
||||
}
|
||||
|
||||
visitDeclareVarStmt(stmt: o.DeclareVarStmt, ctx: _ExecutionContext): any {
|
||||
ctx.vars.set(stmt.name, stmt.value.visitExpression(this, ctx));
|
||||
return null;
|
||||
}
|
||||
visitWriteVarExpr(expr: o.WriteVarExpr, ctx: _ExecutionContext): any {
|
||||
var value = expr.value.visitExpression(this, ctx);
|
||||
var currCtx = ctx;
|
||||
while (currCtx != null) {
|
||||
if (currCtx.vars.has(expr.name)) {
|
||||
currCtx.vars.set(expr.name, value);
|
||||
return value;
|
||||
}
|
||||
currCtx = currCtx.parent;
|
||||
}
|
||||
throw new BaseException(`Not declared variable ${expr.name}`);
|
||||
}
|
||||
visitReadVarExpr(ast: o.ReadVarExpr, ctx: _ExecutionContext): any {
|
||||
var varName = ast.name;
|
||||
if (isPresent(ast.builtin)) {
|
||||
switch (ast.builtin) {
|
||||
case o.BuiltinVar.Super:
|
||||
case o.BuiltinVar.This:
|
||||
return ctx.superInstance;
|
||||
case o.BuiltinVar.CatchError:
|
||||
varName = CATCH_ERROR_VAR;
|
||||
break;
|
||||
case o.BuiltinVar.CatchStack:
|
||||
varName = CATCH_STACK_VAR;
|
||||
break;
|
||||
default:
|
||||
throw new BaseException(`Unknown builtin variable ${ast.builtin}`);
|
||||
}
|
||||
}
|
||||
var currCtx = ctx;
|
||||
while (currCtx != null) {
|
||||
if (currCtx.vars.has(varName)) {
|
||||
return currCtx.vars.get(varName);
|
||||
}
|
||||
currCtx = currCtx.parent;
|
||||
}
|
||||
throw new BaseException(`Not declared variable ${varName}`);
|
||||
}
|
||||
visitWriteKeyExpr(expr: o.WriteKeyExpr, ctx: _ExecutionContext): any {
|
||||
var receiver = expr.receiver.visitExpression(this, ctx);
|
||||
var index = expr.index.visitExpression(this, ctx);
|
||||
var value = expr.value.visitExpression(this, ctx);
|
||||
receiver[index] = value;
|
||||
return value;
|
||||
}
|
||||
visitWritePropExpr(expr: o.WritePropExpr, ctx: _ExecutionContext): any {
|
||||
var receiver = expr.receiver.visitExpression(this, ctx);
|
||||
var value = expr.value.visitExpression(this, ctx);
|
||||
if (isDynamicInstance(receiver)) {
|
||||
var di = <DynamicInstance>receiver;
|
||||
if (di.props.has(expr.name)) {
|
||||
di.props.set(expr.name, value);
|
||||
} else {
|
||||
reflector.setter(expr.name)(receiver, value);
|
||||
}
|
||||
} else {
|
||||
reflector.setter(expr.name)(receiver, value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
visitInvokeMethodExpr(expr: o.InvokeMethodExpr, ctx: _ExecutionContext): any {
|
||||
var receiver = expr.receiver.visitExpression(this, ctx);
|
||||
var args = this.visitAllExpressions(expr.args, ctx);
|
||||
var result;
|
||||
if (isPresent(expr.builtin)) {
|
||||
switch (expr.builtin) {
|
||||
case o.BuiltinMethod.ConcatArray:
|
||||
result = ListWrapper.concat(receiver, args[0]);
|
||||
break;
|
||||
case o.BuiltinMethod.SubscribeObservable:
|
||||
result = ObservableWrapper.subscribe(receiver, args[0]);
|
||||
break;
|
||||
case o.BuiltinMethod.bind:
|
||||
if (IS_DART) {
|
||||
result = receiver;
|
||||
} else {
|
||||
result = receiver.bind(args[0]);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new BaseException(`Unknown builtin method ${expr.builtin}`);
|
||||
}
|
||||
} else if (isDynamicInstance(receiver)) {
|
||||
var di = <DynamicInstance>receiver;
|
||||
if (di.methods.has(expr.name)) {
|
||||
result = FunctionWrapper.apply(di.methods.get(expr.name), args);
|
||||
} else {
|
||||
result = reflector.method(expr.name)(receiver, args);
|
||||
}
|
||||
} else {
|
||||
result = reflector.method(expr.name)(receiver, args);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
visitInvokeFunctionExpr(stmt: o.InvokeFunctionExpr, ctx: _ExecutionContext): any {
|
||||
var args = this.visitAllExpressions(stmt.args, ctx);
|
||||
var fnExpr = stmt.fn;
|
||||
if (fnExpr instanceof o.ReadVarExpr && fnExpr.builtin === o.BuiltinVar.Super) {
|
||||
ctx.superInstance = ctx.instanceFactory.createInstance(ctx.superClass, ctx.className, args,
|
||||
ctx.props, ctx.getters, ctx.methods);
|
||||
ctx.parent.superInstance = ctx.superInstance;
|
||||
return null;
|
||||
} else {
|
||||
var fn = stmt.fn.visitExpression(this, ctx);
|
||||
return FunctionWrapper.apply(fn, args);
|
||||
}
|
||||
}
|
||||
visitReturnStmt(stmt: o.ReturnStatement, ctx: _ExecutionContext): any {
|
||||
return new ReturnValue(stmt.value.visitExpression(this, ctx));
|
||||
}
|
||||
visitDeclareClassStmt(stmt: o.ClassStmt, ctx: _ExecutionContext): any {
|
||||
var clazz = new _DynamicClass(stmt, ctx, this);
|
||||
ctx.vars.set(stmt.name, clazz);
|
||||
return null;
|
||||
}
|
||||
visitExpressionStmt(stmt: o.ExpressionStatement, ctx: _ExecutionContext): any {
|
||||
return stmt.expr.visitExpression(this, ctx);
|
||||
}
|
||||
visitIfStmt(stmt: o.IfStmt, ctx: _ExecutionContext): any {
|
||||
var condition = stmt.condition.visitExpression(this, ctx);
|
||||
if (condition) {
|
||||
return this.visitAllStatements(stmt.trueCase, ctx);
|
||||
} else if (isPresent(stmt.falseCase)) {
|
||||
return this.visitAllStatements(stmt.falseCase, ctx);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
visitTryCatchStmt(stmt: o.TryCatchStmt, ctx: _ExecutionContext): any {
|
||||
try {
|
||||
return this.visitAllStatements(stmt.bodyStmts, ctx);
|
||||
} catch (e) {
|
||||
var childCtx = ctx.createChildWihtLocalVars();
|
||||
childCtx.vars.set(CATCH_ERROR_VAR, e);
|
||||
childCtx.vars.set(CATCH_STACK_VAR, e.stack);
|
||||
return this.visitAllStatements(stmt.catchStmts, childCtx);
|
||||
}
|
||||
}
|
||||
visitThrowStmt(stmt: o.ThrowStmt, ctx: _ExecutionContext): any {
|
||||
throw stmt.error.visitExpression(this, ctx);
|
||||
}
|
||||
visitCommentStmt(stmt: o.CommentStmt, context?: any): any { return null; }
|
||||
visitInstantiateExpr(ast: o.InstantiateExpr, ctx: _ExecutionContext): any {
|
||||
var args = this.visitAllExpressions(ast.args, ctx);
|
||||
var clazz = ast.classExpr.visitExpression(this, ctx);
|
||||
if (clazz instanceof _DynamicClass) {
|
||||
return clazz.instantiate(args);
|
||||
} else {
|
||||
return FunctionWrapper.apply(reflector.factory(clazz), args);
|
||||
}
|
||||
}
|
||||
visitLiteralExpr(ast: o.LiteralExpr, ctx: _ExecutionContext): any { return ast.value; }
|
||||
visitExternalExpr(ast: o.ExternalExpr, ctx: _ExecutionContext): any { return ast.value.runtime; }
|
||||
visitConditionalExpr(ast: o.ConditionalExpr, ctx: _ExecutionContext): any {
|
||||
if (ast.condition.visitExpression(this, ctx)) {
|
||||
return ast.trueCase.visitExpression(this, ctx);
|
||||
} else if (isPresent(ast.falseCase)) {
|
||||
return ast.falseCase.visitExpression(this, ctx);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
visitNotExpr(ast: o.NotExpr, ctx: _ExecutionContext): any {
|
||||
return !ast.condition.visitExpression(this, ctx);
|
||||
}
|
||||
visitCastExpr(ast: o.CastExpr, ctx: _ExecutionContext): any {
|
||||
return ast.value.visitExpression(this, ctx);
|
||||
}
|
||||
visitFunctionExpr(ast: o.FunctionExpr, ctx: _ExecutionContext): any {
|
||||
var paramNames = ast.params.map((param) => param.name);
|
||||
return _declareFn(paramNames, ast.statements, ctx, this);
|
||||
}
|
||||
visitDeclareFunctionStmt(stmt: o.DeclareFunctionStmt, ctx: _ExecutionContext): any {
|
||||
var paramNames = stmt.params.map((param) => param.name);
|
||||
ctx.vars.set(stmt.name, _declareFn(paramNames, stmt.statements, ctx, this));
|
||||
return null;
|
||||
}
|
||||
visitBinaryOperatorExpr(ast: o.BinaryOperatorExpr, ctx: _ExecutionContext): any {
|
||||
var lhs = () => ast.lhs.visitExpression(this, ctx);
|
||||
var rhs = () => ast.rhs.visitExpression(this, ctx);
|
||||
|
||||
switch (ast.operator) {
|
||||
case o.BinaryOperator.Equals:
|
||||
return lhs() == rhs();
|
||||
case o.BinaryOperator.Identical:
|
||||
return lhs() === rhs();
|
||||
case o.BinaryOperator.NotEquals:
|
||||
return lhs() != rhs();
|
||||
case o.BinaryOperator.NotIdentical:
|
||||
return lhs() !== rhs();
|
||||
case o.BinaryOperator.And:
|
||||
return lhs() && rhs();
|
||||
case o.BinaryOperator.Or:
|
||||
return lhs() || rhs();
|
||||
case o.BinaryOperator.Plus:
|
||||
return lhs() + rhs();
|
||||
case o.BinaryOperator.Minus:
|
||||
return lhs() - rhs();
|
||||
case o.BinaryOperator.Divide:
|
||||
return lhs() / rhs();
|
||||
case o.BinaryOperator.Multiply:
|
||||
return lhs() * rhs();
|
||||
case o.BinaryOperator.Modulo:
|
||||
return lhs() % rhs();
|
||||
case o.BinaryOperator.Lower:
|
||||
return lhs() < rhs();
|
||||
case o.BinaryOperator.LowerEquals:
|
||||
return lhs() <= rhs();
|
||||
case o.BinaryOperator.Bigger:
|
||||
return lhs() > rhs();
|
||||
case o.BinaryOperator.BiggerEquals:
|
||||
return lhs() >= rhs();
|
||||
default:
|
||||
throw new BaseException(`Unknown operator ${ast.operator}`);
|
||||
}
|
||||
}
|
||||
visitReadPropExpr(ast: o.ReadPropExpr, ctx: _ExecutionContext): any {
|
||||
var result;
|
||||
var receiver = ast.receiver.visitExpression(this, ctx);
|
||||
if (isDynamicInstance(receiver)) {
|
||||
var di = <DynamicInstance>receiver;
|
||||
if (di.props.has(ast.name)) {
|
||||
result = di.props.get(ast.name);
|
||||
} else if (di.getters.has(ast.name)) {
|
||||
result = di.getters.get(ast.name)();
|
||||
} else if (di.methods.has(ast.name)) {
|
||||
result = di.methods.get(ast.name);
|
||||
} else {
|
||||
result = reflector.getter(ast.name)(receiver);
|
||||
}
|
||||
} else {
|
||||
result = reflector.getter(ast.name)(receiver);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
visitReadKeyExpr(ast: o.ReadKeyExpr, ctx: _ExecutionContext): any {
|
||||
var receiver = ast.receiver.visitExpression(this, ctx);
|
||||
var prop = ast.index.visitExpression(this, ctx);
|
||||
return receiver[prop];
|
||||
}
|
||||
visitLiteralArrayExpr(ast: o.LiteralArrayExpr, ctx: _ExecutionContext): any {
|
||||
return this.visitAllExpressions(ast.entries, ctx);
|
||||
}
|
||||
visitLiteralMapExpr(ast: o.LiteralMapExpr, ctx: _ExecutionContext): any {
|
||||
var result = {};
|
||||
ast.entries.forEach((entry) => result[<string>entry[0]] =
|
||||
(<o.Expression>entry[1]).visitExpression(this, ctx));
|
||||
return result;
|
||||
}
|
||||
|
||||
visitAllExpressions(expressions: o.Expression[], ctx: _ExecutionContext): any {
|
||||
return expressions.map((expr) => expr.visitExpression(this, ctx));
|
||||
}
|
||||
|
||||
visitAllStatements(statements: o.Statement[], ctx: _ExecutionContext): ReturnValue {
|
||||
for (var i = 0; i < statements.length; i++) {
|
||||
var stmt = statements[i];
|
||||
var val = stmt.visitStatement(this, ctx);
|
||||
if (val instanceof ReturnValue) {
|
||||
return val;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function _declareFn(varNames: string[], statements: o.Statement[], ctx: _ExecutionContext,
|
||||
visitor: StatementInterpreter): Function {
|
||||
switch (varNames.length) {
|
||||
case 0:
|
||||
return () => _executeFunctionStatements(varNames, [], statements, ctx, visitor);
|
||||
case 1:
|
||||
return (d0) => _executeFunctionStatements(varNames, [d0], statements, ctx, visitor);
|
||||
case 2:
|
||||
return (d0, d1) => _executeFunctionStatements(varNames, [d0, d1], statements, ctx, visitor);
|
||||
case 3:
|
||||
return (d0, d1, d2) =>
|
||||
_executeFunctionStatements(varNames, [d0, d1, d2], statements, ctx, visitor);
|
||||
case 4:
|
||||
return (d0, d1, d2, d3) =>
|
||||
_executeFunctionStatements(varNames, [d0, d1, d2, d3], statements, ctx, visitor);
|
||||
case 5:
|
||||
return (d0, d1, d2, d3, d4) => _executeFunctionStatements(varNames, [d0, d1, d2, d3, d4],
|
||||
statements, ctx, visitor);
|
||||
case 6:
|
||||
return (d0, d1, d2, d3, d4, d5) => _executeFunctionStatements(
|
||||
varNames, [d0, d1, d2, d3, d4, d5], statements, ctx, visitor);
|
||||
case 7:
|
||||
return (d0, d1, d2, d3, d4, d5, d6) => _executeFunctionStatements(
|
||||
varNames, [d0, d1, d2, d3, d4, d5, d6], statements, ctx, visitor);
|
||||
case 8:
|
||||
return (d0, d1, d2, d3, d4, d5, d6, d7) => _executeFunctionStatements(
|
||||
varNames, [d0, d1, d2, d3, d4, d5, d6, d7], statements, ctx, visitor);
|
||||
case 9:
|
||||
return (d0, d1, d2, d3, d4, d5, d6, d7, d8) => _executeFunctionStatements(
|
||||
varNames, [d0, d1, d2, d3, d4, d5, d6, d7, d8], statements, ctx, visitor);
|
||||
case 10:
|
||||
return (d0, d1, d2, d3, d4, d5, d6, d7, d8, d9) => _executeFunctionStatements(
|
||||
varNames, [d0, d1, d2, d3, d4, d5, d6, d7, d8, d9], statements, ctx, visitor);
|
||||
default:
|
||||
throw new BaseException(
|
||||
'Declaring functions with more than 10 arguments is not supported right now');
|
||||
}
|
||||
}
|
||||
|
||||
var CATCH_ERROR_VAR = 'error';
|
||||
var CATCH_STACK_VAR = 'stack';
|
46
modules/@angular/compiler/src/output/output_jit.ts
Normal file
46
modules/@angular/compiler/src/output/output_jit.ts
Normal file
@ -0,0 +1,46 @@
|
||||
import {
|
||||
isPresent,
|
||||
isBlank,
|
||||
isString,
|
||||
evalExpression,
|
||||
RegExpWrapper,
|
||||
StringWrapper
|
||||
} from 'angular2/src/facade/lang';
|
||||
import * as o from './output_ast';
|
||||
import {EmitterVisitorContext} from './abstract_emitter';
|
||||
import {AbstractJsEmitterVisitor} from './abstract_js_emitter';
|
||||
import {sanitizeIdentifier} from '../util';
|
||||
|
||||
export function jitStatements(sourceUrl: string, statements: o.Statement[],
|
||||
resultVar: string): any {
|
||||
var converter = new JitEmitterVisitor();
|
||||
var ctx = EmitterVisitorContext.createRoot([resultVar]);
|
||||
converter.visitAllStatements(statements, ctx);
|
||||
return evalExpression(sourceUrl, resultVar, ctx.toSource(), converter.getArgs());
|
||||
}
|
||||
|
||||
class JitEmitterVisitor extends AbstractJsEmitterVisitor {
|
||||
private _evalArgNames: string[] = [];
|
||||
private _evalArgValues: any[] = [];
|
||||
|
||||
getArgs(): {[key: string]: any} {
|
||||
var result = {};
|
||||
for (var i = 0; i < this._evalArgNames.length; i++) {
|
||||
result[this._evalArgNames[i]] = this._evalArgValues[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
visitExternalExpr(ast: o.ExternalExpr, ctx: EmitterVisitorContext): any {
|
||||
var value = ast.value.runtime;
|
||||
var id = this._evalArgValues.indexOf(value);
|
||||
if (id === -1) {
|
||||
id = this._evalArgValues.length;
|
||||
this._evalArgValues.push(value);
|
||||
var name = isPresent(ast.value.name) ? sanitizeIdentifier(ast.value.name) : 'val';
|
||||
this._evalArgNames.push(sanitizeIdentifier(`jit_${name}${id}`));
|
||||
}
|
||||
ctx.print(this._evalArgNames[id]);
|
||||
return null;
|
||||
}
|
||||
}
|
80
modules/@angular/compiler/src/output/path_util.ts
Normal file
80
modules/@angular/compiler/src/output/path_util.ts
Normal file
@ -0,0 +1,80 @@
|
||||
import {BaseException} from 'angular2/src/facade/exceptions';
|
||||
import {isPresent, isBlank, RegExpWrapper, Math} from 'angular2/src/facade/lang';
|
||||
|
||||
// asset:<package-name>/<realm>/<path-to-module>
|
||||
var _ASSET_URL_RE = /asset:([^\/]+)\/([^\/]+)\/(.+)/g;
|
||||
|
||||
var _PATH_SEP = '/';
|
||||
var _PATH_SEP_RE = /\//g;
|
||||
|
||||
export enum ImportEnv {
|
||||
Dart,
|
||||
JS
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the module path to use for an import.
|
||||
*/
|
||||
export function getImportModulePath(moduleUrlStr: string, importedUrlStr: string,
|
||||
importEnv: ImportEnv): string {
|
||||
var absolutePathPrefix: string = importEnv === ImportEnv.Dart ? `package:` : '';
|
||||
var moduleUrl = _AssetUrl.parse(moduleUrlStr, false);
|
||||
var importedUrl = _AssetUrl.parse(importedUrlStr, true);
|
||||
if (isBlank(importedUrl)) {
|
||||
return importedUrlStr;
|
||||
}
|
||||
|
||||
// Try to create a relative path first
|
||||
if (moduleUrl.firstLevelDir == importedUrl.firstLevelDir &&
|
||||
moduleUrl.packageName == importedUrl.packageName) {
|
||||
return getRelativePath(moduleUrl.modulePath, importedUrl.modulePath, importEnv);
|
||||
} else if (importedUrl.firstLevelDir == 'lib') {
|
||||
return `${absolutePathPrefix}${importedUrl.packageName}/${importedUrl.modulePath}`;
|
||||
}
|
||||
throw new BaseException(`Can't import url ${importedUrlStr} from ${moduleUrlStr}`);
|
||||
}
|
||||
|
||||
class _AssetUrl {
|
||||
static parse(url: string, allowNonMatching: boolean): _AssetUrl {
|
||||
var match = RegExpWrapper.firstMatch(_ASSET_URL_RE, url);
|
||||
if (isPresent(match)) {
|
||||
return new _AssetUrl(match[1], match[2], match[3]);
|
||||
}
|
||||
if (allowNonMatching) {
|
||||
return null;
|
||||
}
|
||||
throw new BaseException(`Url ${url} is not a valid asset: url`);
|
||||
}
|
||||
|
||||
constructor(public packageName: string, public firstLevelDir: string, public modulePath: string) {
|
||||
}
|
||||
}
|
||||
|
||||
export function getRelativePath(modulePath: string, importedPath: string,
|
||||
importEnv: ImportEnv): string {
|
||||
var moduleParts = modulePath.split(_PATH_SEP_RE);
|
||||
var importedParts = importedPath.split(_PATH_SEP_RE);
|
||||
var longestPrefix = getLongestPathSegmentPrefix(moduleParts, importedParts);
|
||||
|
||||
var resultParts = [];
|
||||
var goParentCount = moduleParts.length - 1 - longestPrefix;
|
||||
for (var i = 0; i < goParentCount; i++) {
|
||||
resultParts.push('..');
|
||||
}
|
||||
if (goParentCount <= 0 && importEnv === ImportEnv.JS) {
|
||||
resultParts.push('.');
|
||||
}
|
||||
for (var i = longestPrefix; i < importedParts.length; i++) {
|
||||
resultParts.push(importedParts[i]);
|
||||
}
|
||||
return resultParts.join(_PATH_SEP);
|
||||
}
|
||||
|
||||
export function getLongestPathSegmentPrefix(arr1: string[], arr2: string[]): number {
|
||||
var prefixSize = 0;
|
||||
var minLen = Math.min(arr1.length, arr2.length);
|
||||
while (prefixSize < minLen && arr1[prefixSize] == arr2[prefixSize]) {
|
||||
prefixSize++;
|
||||
}
|
||||
return prefixSize;
|
||||
}
|
332
modules/@angular/compiler/src/output/ts_emitter.ts
Normal file
332
modules/@angular/compiler/src/output/ts_emitter.ts
Normal file
@ -0,0 +1,332 @@
|
||||
import * as o from './output_ast';
|
||||
import {
|
||||
isPresent,
|
||||
isBlank,
|
||||
isString,
|
||||
evalExpression,
|
||||
RegExpWrapper,
|
||||
StringWrapper,
|
||||
isArray
|
||||
} from 'angular2/src/facade/lang';
|
||||
import {CompileIdentifierMetadata} from '../compile_metadata';
|
||||
import {BaseException} from 'angular2/src/facade/exceptions';
|
||||
import {
|
||||
OutputEmitter,
|
||||
EmitterVisitorContext,
|
||||
AbstractEmitterVisitor,
|
||||
CATCH_ERROR_VAR,
|
||||
CATCH_STACK_VAR
|
||||
} from './abstract_emitter';
|
||||
import {getImportModulePath, ImportEnv} from './path_util';
|
||||
|
||||
var _debugModuleUrl = 'asset://debug/lib';
|
||||
|
||||
export function debugOutputAstAsTypeScript(ast: o.Statement | o.Expression | o.Type |
|
||||
any[]): string {
|
||||
var converter = new _TsEmitterVisitor(_debugModuleUrl);
|
||||
var ctx = EmitterVisitorContext.createRoot([]);
|
||||
var asts: any[];
|
||||
if (isArray(ast)) {
|
||||
asts = <any[]>ast;
|
||||
} else {
|
||||
asts = [ast];
|
||||
}
|
||||
asts.forEach((ast) => {
|
||||
if (ast instanceof o.Statement) {
|
||||
ast.visitStatement(converter, ctx);
|
||||
} else if (ast instanceof o.Expression) {
|
||||
ast.visitExpression(converter, ctx);
|
||||
} else if (ast instanceof o.Type) {
|
||||
ast.visitType(converter, ctx);
|
||||
} else {
|
||||
throw new BaseException(`Don't know how to print debug info for ${ast}`);
|
||||
}
|
||||
});
|
||||
return ctx.toSource();
|
||||
}
|
||||
|
||||
export class TypeScriptEmitter implements OutputEmitter {
|
||||
constructor() {}
|
||||
emitStatements(moduleUrl: string, stmts: o.Statement[], exportedVars: string[]): string {
|
||||
var converter = new _TsEmitterVisitor(moduleUrl);
|
||||
var ctx = EmitterVisitorContext.createRoot(exportedVars);
|
||||
converter.visitAllStatements(stmts, ctx);
|
||||
var srcParts = [];
|
||||
converter.importsWithPrefixes.forEach((prefix, importedModuleUrl) => {
|
||||
// Note: can't write the real word for import as it screws up system.js auto detection...
|
||||
srcParts.push(
|
||||
`imp` +
|
||||
`ort * as ${prefix} from '${getImportModulePath(moduleUrl, importedModuleUrl, ImportEnv.JS)}';`);
|
||||
});
|
||||
srcParts.push(ctx.toSource());
|
||||
return srcParts.join('\n');
|
||||
}
|
||||
}
|
||||
|
||||
class _TsEmitterVisitor extends AbstractEmitterVisitor implements o.TypeVisitor {
|
||||
constructor(private _moduleUrl: string) { super(false); }
|
||||
|
||||
importsWithPrefixes = new Map<string, string>();
|
||||
|
||||
visitExternalExpr(ast: o.ExternalExpr, ctx: EmitterVisitorContext): any {
|
||||
this._visitIdentifier(ast.value, ast.typeParams, ctx);
|
||||
return null;
|
||||
}
|
||||
visitDeclareVarStmt(stmt: o.DeclareVarStmt, ctx: EmitterVisitorContext): any {
|
||||
if (ctx.isExportedVar(stmt.name)) {
|
||||
ctx.print(`export `);
|
||||
}
|
||||
if (stmt.hasModifier(o.StmtModifier.Final)) {
|
||||
ctx.print(`const`);
|
||||
} else {
|
||||
ctx.print(`var`);
|
||||
}
|
||||
ctx.print(` ${stmt.name}`);
|
||||
if (isPresent(stmt.type)) {
|
||||
ctx.print(`:`);
|
||||
stmt.type.visitType(this, ctx);
|
||||
}
|
||||
ctx.print(` = `);
|
||||
stmt.value.visitExpression(this, ctx);
|
||||
ctx.println(`;`);
|
||||
return null;
|
||||
}
|
||||
visitCastExpr(ast: o.CastExpr, ctx: EmitterVisitorContext): any {
|
||||
ctx.print(`(<`);
|
||||
ast.type.visitType(this, ctx);
|
||||
ctx.print(`>`);
|
||||
ast.value.visitExpression(this, ctx);
|
||||
ctx.print(`)`);
|
||||
return null;
|
||||
}
|
||||
visitDeclareClassStmt(stmt: o.ClassStmt, ctx: EmitterVisitorContext): any {
|
||||
ctx.pushClass(stmt);
|
||||
if (ctx.isExportedVar(stmt.name)) {
|
||||
ctx.print(`export `);
|
||||
}
|
||||
ctx.print(`class ${stmt.name}`);
|
||||
if (isPresent(stmt.parent)) {
|
||||
ctx.print(` extends `);
|
||||
stmt.parent.visitExpression(this, ctx);
|
||||
}
|
||||
ctx.println(` {`);
|
||||
ctx.incIndent();
|
||||
stmt.fields.forEach((field) => this._visitClassField(field, ctx));
|
||||
if (isPresent(stmt.constructorMethod)) {
|
||||
this._visitClassConstructor(stmt, ctx);
|
||||
}
|
||||
stmt.getters.forEach((getter) => this._visitClassGetter(getter, ctx));
|
||||
stmt.methods.forEach((method) => this._visitClassMethod(method, ctx));
|
||||
ctx.decIndent();
|
||||
ctx.println(`}`);
|
||||
ctx.popClass();
|
||||
return null;
|
||||
}
|
||||
private _visitClassField(field: o.ClassField, ctx: EmitterVisitorContext) {
|
||||
if (field.hasModifier(o.StmtModifier.Private)) {
|
||||
ctx.print(`private `);
|
||||
}
|
||||
ctx.print(field.name);
|
||||
if (isPresent(field.type)) {
|
||||
ctx.print(`:`);
|
||||
field.type.visitType(this, ctx);
|
||||
} else {
|
||||
ctx.print(`: any`);
|
||||
}
|
||||
ctx.println(`;`);
|
||||
}
|
||||
private _visitClassGetter(getter: o.ClassGetter, ctx: EmitterVisitorContext) {
|
||||
if (getter.hasModifier(o.StmtModifier.Private)) {
|
||||
ctx.print(`private `);
|
||||
}
|
||||
ctx.print(`get ${getter.name}()`);
|
||||
if (isPresent(getter.type)) {
|
||||
ctx.print(`:`);
|
||||
getter.type.visitType(this, ctx);
|
||||
}
|
||||
ctx.println(` {`);
|
||||
ctx.incIndent();
|
||||
this.visitAllStatements(getter.body, ctx);
|
||||
ctx.decIndent();
|
||||
ctx.println(`}`);
|
||||
}
|
||||
private _visitClassConstructor(stmt: o.ClassStmt, ctx: EmitterVisitorContext) {
|
||||
ctx.print(`constructor(`);
|
||||
this._visitParams(stmt.constructorMethod.params, ctx);
|
||||
ctx.println(`) {`);
|
||||
ctx.incIndent();
|
||||
this.visitAllStatements(stmt.constructorMethod.body, ctx);
|
||||
ctx.decIndent();
|
||||
ctx.println(`}`);
|
||||
}
|
||||
private _visitClassMethod(method: o.ClassMethod, ctx: EmitterVisitorContext) {
|
||||
if (method.hasModifier(o.StmtModifier.Private)) {
|
||||
ctx.print(`private `);
|
||||
}
|
||||
ctx.print(`${method.name}(`);
|
||||
this._visitParams(method.params, ctx);
|
||||
ctx.print(`):`);
|
||||
if (isPresent(method.type)) {
|
||||
method.type.visitType(this, ctx);
|
||||
} else {
|
||||
ctx.print(`void`);
|
||||
}
|
||||
ctx.println(` {`);
|
||||
ctx.incIndent();
|
||||
this.visitAllStatements(method.body, ctx);
|
||||
ctx.decIndent();
|
||||
ctx.println(`}`);
|
||||
}
|
||||
visitFunctionExpr(ast: o.FunctionExpr, ctx: EmitterVisitorContext): any {
|
||||
ctx.print(`(`);
|
||||
this._visitParams(ast.params, ctx);
|
||||
ctx.print(`):`);
|
||||
if (isPresent(ast.type)) {
|
||||
ast.type.visitType(this, ctx);
|
||||
} else {
|
||||
ctx.print(`void`);
|
||||
}
|
||||
ctx.println(` => {`);
|
||||
ctx.incIndent();
|
||||
this.visitAllStatements(ast.statements, ctx);
|
||||
ctx.decIndent();
|
||||
ctx.print(`}`);
|
||||
return null;
|
||||
}
|
||||
visitDeclareFunctionStmt(stmt: o.DeclareFunctionStmt, ctx: EmitterVisitorContext): any {
|
||||
if (ctx.isExportedVar(stmt.name)) {
|
||||
ctx.print(`export `);
|
||||
}
|
||||
ctx.print(`function ${stmt.name}(`);
|
||||
this._visitParams(stmt.params, ctx);
|
||||
ctx.print(`):`);
|
||||
if (isPresent(stmt.type)) {
|
||||
stmt.type.visitType(this, ctx);
|
||||
} else {
|
||||
ctx.print(`void`);
|
||||
}
|
||||
ctx.println(` {`);
|
||||
ctx.incIndent();
|
||||
this.visitAllStatements(stmt.statements, ctx);
|
||||
ctx.decIndent();
|
||||
ctx.println(`}`);
|
||||
return null;
|
||||
}
|
||||
visitTryCatchStmt(stmt: o.TryCatchStmt, ctx: EmitterVisitorContext): any {
|
||||
ctx.println(`try {`);
|
||||
ctx.incIndent();
|
||||
this.visitAllStatements(stmt.bodyStmts, ctx);
|
||||
ctx.decIndent();
|
||||
ctx.println(`} catch (${CATCH_ERROR_VAR.name}) {`);
|
||||
ctx.incIndent();
|
||||
var catchStmts = [
|
||||
<o.Statement>CATCH_STACK_VAR.set(CATCH_ERROR_VAR.prop('stack'))
|
||||
.toDeclStmt(null, [o.StmtModifier.Final])
|
||||
].concat(stmt.catchStmts);
|
||||
this.visitAllStatements(catchStmts, ctx);
|
||||
ctx.decIndent();
|
||||
ctx.println(`}`);
|
||||
return null;
|
||||
}
|
||||
|
||||
visitBuiltintType(type: o.BuiltinType, ctx: EmitterVisitorContext): any {
|
||||
var typeStr;
|
||||
switch (type.name) {
|
||||
case o.BuiltinTypeName.Bool:
|
||||
typeStr = 'boolean';
|
||||
break;
|
||||
case o.BuiltinTypeName.Dynamic:
|
||||
typeStr = 'any';
|
||||
break;
|
||||
case o.BuiltinTypeName.Function:
|
||||
typeStr = 'Function';
|
||||
break;
|
||||
case o.BuiltinTypeName.Number:
|
||||
typeStr = 'number';
|
||||
break;
|
||||
case o.BuiltinTypeName.Int:
|
||||
typeStr = 'number';
|
||||
break;
|
||||
case o.BuiltinTypeName.String:
|
||||
typeStr = 'string';
|
||||
break;
|
||||
default:
|
||||
throw new BaseException(`Unsupported builtin type ${type.name}`);
|
||||
}
|
||||
ctx.print(typeStr);
|
||||
return null;
|
||||
}
|
||||
visitExternalType(ast: o.ExternalType, ctx: EmitterVisitorContext): any {
|
||||
this._visitIdentifier(ast.value, ast.typeParams, ctx);
|
||||
return null;
|
||||
}
|
||||
visitArrayType(type: o.ArrayType, ctx: EmitterVisitorContext): any {
|
||||
if (isPresent(type.of)) {
|
||||
type.of.visitType(this, ctx);
|
||||
} else {
|
||||
ctx.print(`any`);
|
||||
}
|
||||
ctx.print(`[]`);
|
||||
return null;
|
||||
}
|
||||
visitMapType(type: o.MapType, ctx: EmitterVisitorContext): any {
|
||||
ctx.print(`{[key: string]:`);
|
||||
if (isPresent(type.valueType)) {
|
||||
type.valueType.visitType(this, ctx);
|
||||
} else {
|
||||
ctx.print(`any`);
|
||||
}
|
||||
ctx.print(`}`);
|
||||
return null;
|
||||
}
|
||||
|
||||
getBuiltinMethodName(method: o.BuiltinMethod): string {
|
||||
var name;
|
||||
switch (method) {
|
||||
case o.BuiltinMethod.ConcatArray:
|
||||
name = 'concat';
|
||||
break;
|
||||
case o.BuiltinMethod.SubscribeObservable:
|
||||
name = 'subscribe';
|
||||
break;
|
||||
case o.BuiltinMethod.bind:
|
||||
name = 'bind';
|
||||
break;
|
||||
default:
|
||||
throw new BaseException(`Unknown builtin method: ${method}`);
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
private _visitParams(params: o.FnParam[], ctx: EmitterVisitorContext): void {
|
||||
this.visitAllObjects((param) => {
|
||||
ctx.print(param.name);
|
||||
if (isPresent(param.type)) {
|
||||
ctx.print(`:`);
|
||||
param.type.visitType(this, ctx);
|
||||
}
|
||||
}, params, ctx, ',');
|
||||
}
|
||||
|
||||
private _visitIdentifier(value: CompileIdentifierMetadata, typeParams: o.Type[],
|
||||
ctx: EmitterVisitorContext): void {
|
||||
if (isBlank(value.name)) {
|
||||
throw new BaseException(`Internal error: unknown identifier ${value}`);
|
||||
}
|
||||
if (isPresent(value.moduleUrl) && value.moduleUrl != this._moduleUrl) {
|
||||
var prefix = this.importsWithPrefixes.get(value.moduleUrl);
|
||||
if (isBlank(prefix)) {
|
||||
prefix = `import${this.importsWithPrefixes.size}`;
|
||||
this.importsWithPrefixes.set(value.moduleUrl, prefix);
|
||||
}
|
||||
ctx.print(`${prefix}.`);
|
||||
}
|
||||
ctx.print(value.name);
|
||||
if (isPresent(typeParams) && typeParams.length > 0) {
|
||||
ctx.print(`<`);
|
||||
this.visitAllObjects((type) => type.visitType(this, ctx), typeParams, ctx, ',');
|
||||
ctx.print(`>`);
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user