|
|
|
@ -15,7 +15,7 @@ import {List, Map, ListWrapper, MapWrapper} from 'facade/collection';
|
|
|
|
|
import {AST, AccessMember, ImplicitReceiver, AstVisitor, LiteralPrimitive,
|
|
|
|
|
Binary, Formatter, MethodCall, FunctionCall, PrefixNot, Conditional,
|
|
|
|
|
LiteralArray, LiteralMap, KeyedAccess, Chain, Assignment} from './parser/ast';
|
|
|
|
|
|
|
|
|
|
import {ContextWithVariableBindings} from './parser/context_with_variable_bindings';
|
|
|
|
|
|
|
|
|
|
export class ProtoRecordRange {
|
|
|
|
|
headRecord:ProtoRecord;
|
|
|
|
@ -304,11 +304,36 @@ export class RecordRange {
|
|
|
|
|
for (var record:Record = this.headRecord;
|
|
|
|
|
record != null;
|
|
|
|
|
record = record.next) {
|
|
|
|
|
|
|
|
|
|
if (record.isImplicitReceiver) {
|
|
|
|
|
record.updateContext(context);
|
|
|
|
|
this._setContextForRecord(context, record);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_setContextForRecord(context, record:Record) {
|
|
|
|
|
var proto = record.protoRecord;
|
|
|
|
|
|
|
|
|
|
while (context instanceof ContextWithVariableBindings) {
|
|
|
|
|
if (context.hasBinding(proto.name)) {
|
|
|
|
|
this._setVarBindingGetter(context, record, proto);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
context = context.parent;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this._setRegularGetter(context, record, proto);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_setVarBindingGetter(context, record:Record, proto:ProtoRecord) {
|
|
|
|
|
record.funcOrValue = _mapGetter(proto.name);
|
|
|
|
|
record.updateContext(context.varBindings);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_setRegularGetter(context, record:Record, proto:ProtoRecord) {
|
|
|
|
|
record.funcOrValue = proto.funcOrValue;
|
|
|
|
|
record.updateContext(context);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function _link(a:Record, b:Record) {
|
|
|
|
@ -353,25 +378,25 @@ class ProtoRecordCreator {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
visitLiteralPrimitive(ast:LiteralPrimitive, dest) {
|
|
|
|
|
this.add(this.construct(RECORD_TYPE_CONST, ast.value, 0, dest));
|
|
|
|
|
this.add(this.construct(RECORD_TYPE_CONST, ast.value, 0, null, dest));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
visitBinary(ast:Binary, dest) {
|
|
|
|
|
var record = this.construct(RECORD_TYPE_INVOKE_PURE_FUNCTION,
|
|
|
|
|
_operationToFunction(ast.operation), 2, dest);
|
|
|
|
|
_operationToFunction(ast.operation), 2, null, dest);
|
|
|
|
|
ast.left.visit(this, new Destination(record, 0));
|
|
|
|
|
ast.right.visit(this, new Destination(record, 1));
|
|
|
|
|
this.add(record);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
visitPrefixNot(ast:PrefixNot, dest) {
|
|
|
|
|
var record = this.construct(RECORD_TYPE_INVOKE_PURE_FUNCTION, _operation_negate, 1, dest);
|
|
|
|
|
var record = this.construct(RECORD_TYPE_INVOKE_PURE_FUNCTION, _operation_negate, 1, null, dest);
|
|
|
|
|
ast.expression.visit(this, new Destination(record, 0));
|
|
|
|
|
this.add(record);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
visitAccessMember(ast:AccessMember, dest) {
|
|
|
|
|
var record = this.construct(RECORD_TYPE_PROPERTY, ast.getter, 0, dest);
|
|
|
|
|
var record = this.construct(RECORD_TYPE_PROPERTY, ast.getter, 0, ast.name, dest);
|
|
|
|
|
if (ast.receiver instanceof ImplicitReceiver) {
|
|
|
|
|
record.setIsImplicitReceiver();
|
|
|
|
|
} else {
|
|
|
|
@ -381,7 +406,7 @@ class ProtoRecordCreator {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
visitFormatter(ast:Formatter, dest) {
|
|
|
|
|
var record = this.construct(RECORD_TYPE_INVOKE_FORMATTER, ast.name, ast.allArgs.length, dest);
|
|
|
|
|
var record = this.construct(RECORD_TYPE_INVOKE_FORMATTER, ast.name, ast.allArgs.length, null, dest);
|
|
|
|
|
for (var i = 0; i < ast.allArgs.length; ++i) {
|
|
|
|
|
ast.allArgs[i].visit(this, new Destination(record, i));
|
|
|
|
|
}
|
|
|
|
@ -389,7 +414,7 @@ class ProtoRecordCreator {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
visitMethodCall(ast:MethodCall, dest) {
|
|
|
|
|
var record = this.construct(RECORD_TYPE_INVOKE_METHOD, ast.fn, ast.args.length, dest);
|
|
|
|
|
var record = this.construct(RECORD_TYPE_INVOKE_METHOD, ast.fn, ast.args.length, null, dest);
|
|
|
|
|
for (var i = 0; i < ast.args.length; ++i) {
|
|
|
|
|
ast.args[i].visit(this, new Destination(record, i));
|
|
|
|
|
}
|
|
|
|
@ -402,7 +427,7 @@ class ProtoRecordCreator {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
visitFunctionCall(ast:FunctionCall, dest) {
|
|
|
|
|
var record = this.construct(RECORD_TYPE_INVOKE_CLOSURE, null, ast.args.length, dest);
|
|
|
|
|
var record = this.construct(RECORD_TYPE_INVOKE_CLOSURE, null, ast.args.length, null, dest);
|
|
|
|
|
ast.target.visit(this, new Destination(record, null));
|
|
|
|
|
for (var i = 0; i < ast.args.length; ++i) {
|
|
|
|
|
ast.args[i].visit(this, new Destination(record, i));
|
|
|
|
@ -411,7 +436,7 @@ class ProtoRecordCreator {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
visitConditional(ast:Conditional, dest) {
|
|
|
|
|
var record = this.construct(RECORD_TYPE_INVOKE_PURE_FUNCTION, _cond, 3, dest);
|
|
|
|
|
var record = this.construct(RECORD_TYPE_INVOKE_PURE_FUNCTION, _cond, 3, null, dest);
|
|
|
|
|
ast.condition.visit(this, new Destination(record, 0));
|
|
|
|
|
ast.trueExp.visit(this, new Destination(record, 1));
|
|
|
|
|
ast.falseExp.visit(this, new Destination(record, 2));
|
|
|
|
@ -422,7 +447,7 @@ class ProtoRecordCreator {
|
|
|
|
|
|
|
|
|
|
visitLiteralArray(ast:LiteralArray, dest) {
|
|
|
|
|
var length = ast.expressions.length;
|
|
|
|
|
var record = this.construct(RECORD_TYPE_INVOKE_PURE_FUNCTION, _arrayFn(length), length, dest);
|
|
|
|
|
var record = this.construct(RECORD_TYPE_INVOKE_PURE_FUNCTION, _arrayFn(length), length, null, dest);
|
|
|
|
|
for (var i = 0; i < length; ++i) {
|
|
|
|
|
ast.expressions[i].visit(this, new Destination(record, i));
|
|
|
|
|
}
|
|
|
|
@ -431,7 +456,7 @@ class ProtoRecordCreator {
|
|
|
|
|
|
|
|
|
|
visitLiteralMap(ast:LiteralMap, dest) {
|
|
|
|
|
var length = ast.values.length;
|
|
|
|
|
var record = this.construct(RECORD_TYPE_INVOKE_PURE_FUNCTION, _mapFn(ast.keys, length), length, dest);
|
|
|
|
|
var record = this.construct(RECORD_TYPE_INVOKE_PURE_FUNCTION, _mapFn(ast.keys, length), length, null, dest);
|
|
|
|
|
for (var i = 0; i < length; ++i) {
|
|
|
|
|
ast.values[i].visit(this, new Destination(record, i));
|
|
|
|
|
}
|
|
|
|
@ -448,8 +473,8 @@ class ProtoRecordCreator {
|
|
|
|
|
ast.visit(this, memento);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
construct(recordType, funcOrValue, arity, dest) {
|
|
|
|
|
return new ProtoRecord(this.protoRecordRange, recordType, funcOrValue, arity, dest);
|
|
|
|
|
construct(recordType, funcOrValue, arity, name, dest) {
|
|
|
|
|
return new ProtoRecord(this.protoRecordRange, recordType, funcOrValue, arity, name, dest);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
add(protoRecord:ProtoRecord) {
|
|
|
|
@ -540,3 +565,10 @@ function _mapFn(keys:List, length:int) {
|
|
|
|
|
default: throw new BaseException(`Does not support literal maps with more than 9 elements`);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//TODO: cache the getters
|
|
|
|
|
function _mapGetter(key) {
|
|
|
|
|
return function(map) {
|
|
|
|
|
return MapWrapper.get(map, key);
|
|
|
|
|
}
|
|
|
|
|
}
|