feat(Reflection): extract reflection capabilities into a separate module
This commit is contained in:
@ -1,6 +1,5 @@
|
||||
import {FIELD, autoConvertAdd, isBlank, isPresent, FunctionWrapper, BaseException} from "facade/lang";
|
||||
import {List, Map, ListWrapper, MapWrapper} from "facade/collection";
|
||||
import {ClosureMap} from "./closure_map";
|
||||
|
||||
export class AST {
|
||||
eval(context) {
|
||||
@ -316,11 +315,9 @@ export class MethodCall extends AST {
|
||||
|
||||
export class FunctionCall extends AST {
|
||||
target:AST;
|
||||
closureMap:ClosureMap;
|
||||
args:List;
|
||||
constructor(target:AST, closureMap:ClosureMap, args:List) {
|
||||
constructor(target:AST, args:List) {
|
||||
this.target = target;
|
||||
this.closureMap = closureMap;
|
||||
this.args = args;
|
||||
}
|
||||
|
||||
|
@ -1,22 +0,0 @@
|
||||
library change_detection.parser.closure_map;
|
||||
|
||||
import 'dart:mirrors';
|
||||
|
||||
typedef SetterFn(Object obj, value);
|
||||
|
||||
class ClosureMap {
|
||||
Function getter(String name) {
|
||||
var symbol = new Symbol(name);
|
||||
return (receiver) => reflect(receiver).getField(symbol).reflectee;
|
||||
}
|
||||
|
||||
Function setter(String name) {
|
||||
var symbol = new Symbol(name);
|
||||
return (receiver, value) => reflect(receiver).setField(symbol, value).reflectee;
|
||||
}
|
||||
|
||||
Function fn(String name) {
|
||||
var symbol = new Symbol(name);
|
||||
return (receiver, posArgs) => reflect(receiver).invoke(symbol, posArgs).reflectee;
|
||||
}
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
export var SetterFn = Function;
|
||||
|
||||
export class ClosureMap {
|
||||
getter(name:string) {
|
||||
return new Function('o', 'return o.' + name + ';');
|
||||
}
|
||||
|
||||
setter(name:string) {
|
||||
return new Function('o', 'v', 'return o.' + name + ' = v;');
|
||||
}
|
||||
|
||||
fn(name:string) {
|
||||
var method = `o.${name}`;
|
||||
return new Function('o', 'args',
|
||||
`if (!${method}) throw new Error('"${name}" is undefined');` +
|
||||
`return ${method}.apply(o, args);`);
|
||||
}
|
||||
}
|
@ -1,8 +1,8 @@
|
||||
import {FIELD, int, isBlank, BaseException, StringWrapper} from 'facade/lang';
|
||||
import {FIELD, int, isBlank, isPresent, BaseException, StringWrapper} from 'facade/lang';
|
||||
import {ListWrapper, List} from 'facade/collection';
|
||||
import {Lexer, EOF, Token, $PERIOD, $COLON, $SEMICOLON, $LBRACKET, $RBRACKET,
|
||||
$COMMA, $LBRACE, $RBRACE, $LPAREN, $RPAREN} from './lexer';
|
||||
import {ClosureMap} from './closure_map';
|
||||
import {reflector, Reflector} from 'reflection/reflection';
|
||||
import {
|
||||
AST,
|
||||
ImplicitReceiver,
|
||||
@ -29,41 +29,41 @@ var _implicitReceiver = new ImplicitReceiver();
|
||||
|
||||
export class Parser {
|
||||
_lexer:Lexer;
|
||||
_closureMap:ClosureMap;
|
||||
constructor(lexer:Lexer, closureMap:ClosureMap){
|
||||
_reflector:Reflector;
|
||||
constructor(lexer:Lexer, providedReflector:Reflector = null){
|
||||
this._lexer = lexer;
|
||||
this._closureMap = closureMap;
|
||||
this._reflector = isPresent(providedReflector) ? providedReflector : reflector;
|
||||
}
|
||||
|
||||
parseAction(input:string):ASTWithSource {
|
||||
var tokens = this._lexer.tokenize(input);
|
||||
var ast = new _ParseAST(input, tokens, this._closureMap, true).parseChain();
|
||||
var ast = new _ParseAST(input, tokens, this._reflector, true).parseChain();
|
||||
return new ASTWithSource(ast, input);
|
||||
}
|
||||
|
||||
parseBinding(input:string):ASTWithSource {
|
||||
var tokens = this._lexer.tokenize(input);
|
||||
var ast = new _ParseAST(input, tokens, this._closureMap, false).parseChain();
|
||||
var ast = new _ParseAST(input, tokens, this._reflector, false).parseChain();
|
||||
return new ASTWithSource(ast, input);
|
||||
}
|
||||
|
||||
parseTemplateBindings(input:string):List<TemplateBinding> {
|
||||
var tokens = this._lexer.tokenize(input);
|
||||
return new _ParseAST(input, tokens, this._closureMap, false).parseTemplateBindings();
|
||||
return new _ParseAST(input, tokens, this._reflector, false).parseTemplateBindings();
|
||||
}
|
||||
}
|
||||
|
||||
class _ParseAST {
|
||||
input:string;
|
||||
tokens:List<Token>;
|
||||
closureMap:ClosureMap;
|
||||
reflector:Reflector;
|
||||
parseAction:boolean;
|
||||
index:int;
|
||||
constructor(input:string, tokens:List, closureMap:ClosureMap, parseAction:boolean) {
|
||||
constructor(input:string, tokens:List, reflector:Reflector, parseAction:boolean) {
|
||||
this.input = input;
|
||||
this.tokens = tokens;
|
||||
this.index = 0;
|
||||
this.closureMap = closureMap;
|
||||
this.reflector = reflector;
|
||||
this.parseAction = parseAction;
|
||||
}
|
||||
|
||||
@ -311,7 +311,7 @@ class _ParseAST {
|
||||
} else if (this.optionalCharacter($LPAREN)) {
|
||||
var args = this.parseCallArguments();
|
||||
this.expectCharacter($RPAREN);
|
||||
result = new FunctionCall(result, this.closureMap, args);
|
||||
result = new FunctionCall(result, args);
|
||||
|
||||
} else {
|
||||
return result;
|
||||
@ -398,12 +398,12 @@ class _ParseAST {
|
||||
if (this.optionalCharacter($LPAREN)) {
|
||||
var args = this.parseCallArguments();
|
||||
this.expectCharacter($RPAREN);
|
||||
var fn = this.closureMap.fn(id);
|
||||
var fn = this.reflector.method(id);
|
||||
return new MethodCall(receiver, fn, args);
|
||||
|
||||
} else {
|
||||
var getter = this.closureMap.getter(id);
|
||||
var setter = this.closureMap.setter(id);
|
||||
var getter = this.reflector.getter(id);
|
||||
var setter = this.reflector.setter(id);
|
||||
return new AccessMember(receiver, id, getter, setter);
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
import {ProtoRecordRange, RecordRange} from './record_range';
|
||||
import {FIELD, isPresent, isBlank, int, StringWrapper, FunctionWrapper, BaseException} from 'facade/lang';
|
||||
import {List, Map, ListWrapper, MapWrapper} from 'facade/collection';
|
||||
import {ClosureMap} from 'change_detection/parser/closure_map';
|
||||
|
||||
var _fresh = new Object();
|
||||
|
||||
|
@ -4,7 +4,6 @@ import {isPresent} from 'facade/lang';
|
||||
import {List, ListWrapper, MapWrapper} from 'facade/collection';
|
||||
import {Parser} from 'change_detection/parser/parser';
|
||||
import {Lexer} from 'change_detection/parser/lexer';
|
||||
import {ClosureMap} from 'change_detection/parser/closure_map';
|
||||
|
||||
import {
|
||||
ChangeDetector,
|
||||
@ -18,7 +17,7 @@ import {Record} from 'change_detection/record';
|
||||
|
||||
export function main() {
|
||||
function ast(exp:string) {
|
||||
var parser = new Parser(new Lexer(), new ClosureMap());
|
||||
var parser = new Parser(new Lexer());
|
||||
return parser.parseBinding(exp).ast;
|
||||
}
|
||||
|
||||
|
@ -1,10 +1,10 @@
|
||||
import {ddescribe, describe, it, xit, iit, expect, beforeEach} from 'test_lib/test_lib';
|
||||
import {BaseException, isBlank, isPresent} from 'facade/lang';
|
||||
import {reflector} from 'reflection/reflection';
|
||||
import {MapWrapper, ListWrapper} from 'facade/collection';
|
||||
import {Parser} from 'change_detection/parser/parser';
|
||||
import {Lexer} from 'change_detection/parser/lexer';
|
||||
import {Formatter, LiteralPrimitive} from 'change_detection/parser/ast';
|
||||
import {ClosureMap} from 'change_detection/parser/closure_map';
|
||||
|
||||
class TestData {
|
||||
a;
|
||||
@ -31,7 +31,7 @@ export function main() {
|
||||
}
|
||||
|
||||
function createParser() {
|
||||
return new Parser(new Lexer(), new ClosureMap());
|
||||
return new Parser(new Lexer(), reflector);
|
||||
}
|
||||
|
||||
function parseAction(text) {
|
||||
|
@ -4,7 +4,6 @@ import {List, ListWrapper, MapWrapper} from 'facade/collection';
|
||||
import {isPresent} from 'facade/lang';
|
||||
import {Parser} from 'change_detection/parser/parser';
|
||||
import {Lexer} from 'change_detection/parser/lexer';
|
||||
import {ClosureMap} from 'change_detection/parser/closure_map';
|
||||
|
||||
import {
|
||||
ChangeDetector,
|
||||
|
Reference in New Issue
Block a user