Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(228)

Unified Diff: third_party/pkg/angular/lib/tools/parser_generator/dart_code_gen.dart

Issue 148453003: Updating Angular version (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/pkg/angular/lib/tools/parser_generator/dart_code_gen.dart
diff --git a/third_party/pkg/angular/lib/tools/parser_generator/dart_code_gen.dart b/third_party/pkg/angular/lib/tools/parser_generator/dart_code_gen.dart
index 381234447a311d6f22e0076586c99b0b6fa0305b..8856a003aa94678f08889f7b656822df609e6e01 100644
--- a/third_party/pkg/angular/lib/tools/parser_generator/dart_code_gen.dart
+++ b/third_party/pkg/angular/lib/tools/parser_generator/dart_code_gen.dart
@@ -1,308 +1,305 @@
library dart_code_gen;
import 'package:angular/tools/reserved_dart_keywords.dart';
-import 'package:angular/core/parser/parser_library.dart'; // For ParserBackend.
-import 'source.dart';
+import 'package:angular/core/parser/syntax.dart';
+
+escape(String s) => s.replaceAllMapped(new RegExp(r'(\"|\$|\n)'), (m) {
+ var char = m[1];
+ if (char == '\n') char = 'n';
+ return "\\$char";
+});
+
+class DartCodeGen {
+ final HelperMap getters = new HelperMap('_',
+ getterTemplate, getterTemplateForReserved);
+ final HelperMap holders = new HelperMap('_ensure\$',
+ holderTemplate, holderTemplateForReserved);
+ final HelperMap setters = new HelperMap('_set\$',
+ setterTemplate, setterTemplateForReserved);
+
+ String generate(Expression expression, bool assign) {
+ var v = new DartCodeGenVisitor(getters, holders, setters);
+ return assign ? v.assign(expression)('value') : v.evaluate(expression);
+ }
+}
+class DartCodeGenVisitor extends Visitor {
+ static const int STATE_EVAL = 0;
+ static const int STATE_EVAL_HOLDER = 1;
+ static const int STATE_ASSIGN = 2;
+ int state = STATE_EVAL;
-Code VALUE_CODE = new Code("value");
+ final HelperMap getters;
+ final HelperMap holders;
+ final HelperMap setters;
-typedef CodeAssign(Code c);
+ DartCodeGenVisitor(this.getters, this.holders, this.setters);
-class Code implements ParserAST, Expression {
- String id;
- String _exp;
- String simpleGetter;
- CodeAssign _assign;
+ bool get isEvaluating => state == STATE_EVAL;
+ bool get isEvaluatingHolder => state == STATE_EVAL_HOLDER;
+ bool get isAssigning => state == STATE_ASSIGN;
- Code(this._exp, [this._assign, this.simpleGetter]) {
- id = _exp == null ? simpleGetter : _exp;
- if (id == null) {
- throw 'id is null';
- }
- }
+ String lookupGetter(String key) => getters.lookup(key);
+ String lookupHolder(String key) => holders.lookup(key);
+ String lookupSetter(String key) => setters.lookup(key);
- String get exp {
- if (_exp == null) {
- throw "Can not be used in an expression: $id";
+ String lookupAccessor(String key) {
+ switch (state) {
+ case STATE_EVAL: return lookupGetter(key);
+ case STATE_EVAL_HOLDER: return lookupHolder(key);
+ case STATE_ASSIGN: return lookupSetter(key);
}
- return _exp;
}
- get assignable => _assign != null;
-
- // methods from Expression
- Expression fieldHolder;
- String fieldName;
- bool get isFieldAccess => null;
- void set exp(String s) => throw new UnimplementedError();
- ParsedGetter get eval => throw new UnimplementedError();
- ParsedSetter get assign => throw new UnimplementedError();
- List get parts => throw new UnimplementedError();
- set parts(List p) => throw new UnimplementedError();
- bind(context, localsWrapper) => throw new UnimplementedError();
-
- Source toSource(SourceBuilder _) {
- return _('new Expression', _.parens(
- _('(scope)', _.body(
- 'return $exp;'
- )),
- assignable ? _('(scope, value)', _.body(
- 'return ${_assign(VALUE_CODE).exp};'
- )) : 'null'
- ));
+ String toBool(String value)
+ => 'toBool($value)';
+ String safeCallFunction(String function, String name, String arguments)
+ => 'ensureFunction($function, "$name")($arguments)';
+
+ String evaluate(Expression expression, {bool convertToBool: false}) {
+ int old = state;
+ try {
+ state = STATE_EVAL;
+ String result = visit(expression);
+ if (convertToBool) result = toBool(result);
+ return result;
+ } finally {
+ state = old;
+ }
}
-}
-class ThrowCode extends Code {
- ThrowCode(code): super('throw $code');
- Source toSource(SourceBuilder _) {
- return _('new Expression', _.parens(
- _('(scope)', _.body()..source.addAll(exp.split('\n'))),
- assignable ? _('(scope, value)', _.body()) : 'null'
- ));
+ String evaluateHolder(Expression expression) {
+ int old = state;
+ try {
+ state = STATE_EVAL_HOLDER;
+ return visit(expression);
+ } finally {
+ state = old;
+ }
}
-}
-class MultipleStatementCode extends Code {
- MultipleStatementCode(code): super(code);
-
- Source toSource(SourceBuilder _) {
- return _('new Expression', _.parens(
- _('(scope)', _.body()..source.addAll(exp.split('\n'))),
- assignable ? _('(scope, value)', _.body()) : 'null'
- ));
+ Function assign(Expression target) {
+ int old = state;
+ try {
+ state = STATE_ASSIGN;
+ return visit(target);
+ } finally {
+ state = old;
+ }
}
-}
-
-escape(String s) => s.replaceAll('\'', '\\\'').replaceAll(r'$', r'\$');
-
-class GetterSetterGenerator {
- static RegExp LAST_PATH_PART = new RegExp(r'(.*)\.(.*)');
- static RegExp NON_WORDS = new RegExp(r'\W');
-
-
- String functions = "// GETTER AND SETTER FUNCTIONS\n\n";
- var _keyToGetterFnName = {};
- var _keyToSetterFnName = {};
- var nextUid = 0;
-
- _flatten(key) => key.replaceAll(NON_WORDS, '_');
- fieldGetter(String field, String obj) {
- var eKey = escape(field);
-
- var returnValue = isReserved(field) ? "undefined_ /* $field is reserved */" : "$obj.$field";
-
- return """
- if ($obj is Map) {
- if ($obj.containsKey('$eKey')) {
- val = $obj['$eKey'];
- } else {
- val = undefined_;
+ visitChain(Chain chain) {
+ StringBuffer buffer = new StringBuffer();
+ buffer.writeln("var result, last;");
+ for (int i = 0; i < chain.expressions.length; i++) {
+ String expression = evaluate(chain.expressions[i]);
+ buffer.writeln('last = $expression;');
+ buffer.writeln('if (last != null) result = last;');
}
- } else {
- val = $returnValue;
+ buffer.write('return result;');
+ return "$buffer";
}
-""";
+ visitFilter(Filter filter) {
+ List expressions = [ filter.expression ]..addAll(filter.arguments);
+ String arguments = expressions.map((e) => evaluate(e)).join(', ');
+ String name = escape(filter.name);
+ return 'filters("$name")($arguments)';
}
- fieldSetter(String field, String obj) {
- var eKey = escape(field);
-
- var maybeField = isReserved(field) ? "/* $field is reserved */" : """
- $obj.$field = value;
- return value;
- """;
+ visitAssign(Assign expression) {
+ String value = evaluate(expression.value);
+ return assign(expression.target)(value);
+ }
- return """
- if ($obj is Map) {
- $obj['$eKey'] = value;
- return value;
+ visitConditional(Conditional conditional) {
+ String condition = evaluate(conditional.condition, convertToBool: true);
+ String yes = evaluate(conditional.yes);
+ String no = evaluate(conditional.no);
+ return "$condition ? $yes : $no";
}
- $maybeField
-}
-""";
+ visitAccessScope(AccessScope access) {
+ String accessor = lookupAccessor(access.name);
+ return isAssigning
+ ? (value) => '$accessor(scope, $value)'
+ : '$accessor(scope)';
}
- call(String key) {
- if (_keyToGetterFnName.containsKey(key)) {
- return _keyToGetterFnName[key];
- }
+ visitAccessMember(AccessMember access) {
+ String object = !isEvaluating
+ ? evaluateHolder(access.object)
+ : evaluate(access.object);
+ String accessor = lookupAccessor(access.name);
+ return isAssigning
+ ? (value) => '$accessor($object, $value)'
+ : '$accessor($object)';
+ }
- var fnName = "_${_flatten(key)}";
-
- var keys = key.split('.');
- var lines = [
- "$fnName(s) { // for $key"];
- _(line) => lines.add(' $line');
- for(var i = 0; i < keys.length; i++) {
- var k = keys[i];
- var sk = isReserved(k) ? "null" : "s.$k";
- if (i == 0) {
- _('if (s != null ) s = s is Map ? s["${escape(k)}"] : $sk;');
- } else {
- _('if (s != null ) s = s is Map ? s["${escape(k)}"] : $sk;');
- }
- }
- _('return s;');
- lines.add('}\n\n');
+ visitAccessKeyed(AccessKeyed access) {
+ String object = evaluate(access.object);
+ String key = evaluate(access.key);
+ return (isAssigning)
+ ? (value) => 'setKeyed($object, $key, $value)'
+ : 'getKeyed($object, $key)';
+ }
- functions += lines.join('\n');
+ visitCallScope(CallScope call) {
+ String arguments = call.arguments.map((e) => evaluate(e)).join(', ');
+ String getter = lookupGetter(call.name);
+ return safeCallFunction('$getter(scope)', call.name, arguments);
+ }
- _keyToGetterFnName[key] = fnName;
- return fnName;
+ visitCallFunction(CallFunction call) {
+ String function = evaluate(call.function);
+ String arguments = call.arguments.map((e) => evaluate(e)).join(', ');
+ return safeCallFunction(function, "${call.function}", arguments);
}
- setter(String key) {
- if (_keyToSetterFnName.containsKey(key)) {
- return _keyToSetterFnName[key];
- }
+ visitCallMember(CallMember call) {
+ String object = evaluate(call.object);
+ String arguments = call.arguments.map((e) => evaluate(e)).join(', ');
+ String getter = lookupGetter(call.name);
+ return safeCallFunction('$getter($object)', call.name, arguments);
+ }
- var fnName = "_set_${_flatten(key)}";
-
- var lines = [
- "$fnName(s, v) { // for $key"];
- _(line) => lines.add(' $line');
- var keys = key.split('.');
- _(keys.length == 1 ? 'var n = s;' : 'var n;');
- var k = keys[0];
- var sk = isReserved(k) ? "null" : "s.$k";
- var nk = isReserved(k) ? "null" : "n.$k";
- if (keys.length > 1) {
- // locals
- _('n = s is Map ? s["${escape(k)}"] : $sk;');
- _('if (n == null) n = s is Map ? (s["${escape(k)}"] = {}) : ($sk = {});');
- }
- for(var i = 1; i < keys.length - 1; i++) {
- k = keys[i];
- sk = isReserved(k) ? "null" : "s.$k";
- nk = isReserved(k) ? "null" : "n.$k";
- // middle
- _('s = n; n = n is Map ? n["${escape(k)}"] : $nk;');
- _('if (n == null) n = s is Map ? (s["${escape(k)}"] = {}) : (${isReserved(k) ? "null" : "$sk = {}"});');
+ visitBinary(Binary binary) {
+ String operation = binary.operation;
+ bool logical = (operation == '||') || (operation == '&&');
+ String left = evaluate(binary.left, convertToBool: logical);
+ String right = evaluate(binary.right, convertToBool: logical);
+ if (operation == '+') {
+ return 'autoConvertAdd($left, $right)';
+ } else {
+ return '($left $operation $right)';
}
- k = keys[keys.length - 1];
- sk = isReserved(k) ? "null" : "s.$k";
- nk = isReserved(k) ? "null" : "n.$k";
- _('if (n is Map) n["${escape(k)}"] = v; else ${isReserved(k) ? "null" : "$nk = v"};');
- // finish
- _('return v;');
- lines.add('}\n\n');
-
- functions += lines.join('\n');
-
- _keyToSetterFnName[key] = fnName;
- return fnName;
}
-}
-
-
-class DartCodeGen implements ParserBackend {
- static Code ZERO = new Code("0");
-
- GetterSetterGenerator _getterGen;
-
- DartCodeGen(this._getterGen);
- setter(String path) => throw new UnimplementedError();
- getter(String path) => throw new UnimplementedError();
-
- // Returns the Dart code for a particular operator.
- _op(fn) => fn == "undefined" ? "null" : fn;
+ visitPrefix(Prefix prefix) {
+ String operation = prefix.operation;
+ bool logical = (operation == '!');
+ String expression = evaluate(prefix.expression, convertToBool: logical);
+ return '$operation$expression';
+ }
- Code ternaryFn(Code cond, Code trueBranch, Code falseBranch) =>
- new Code("toBool(${cond.exp}) ? ${trueBranch.exp} : ${falseBranch.exp}");
+ visitLiteral(Literal literal) {
+ return '$literal';
+ }
- Code binaryFn(Code left, String fn, Code right) {
- if (fn == '+') {
- return new Code("autoConvertAdd(${left.exp}, ${right.exp})");
- }
- var leftExp = left.exp;
- var rightExp = right.exp;
- if (fn == '&&' || fn == '||') {
- leftExp = "toBool($leftExp)";
- rightExp = "toBool($rightExp)";
- }
- return new Code("(${leftExp} ${_op(fn)} ${rightExp})");
+ visitLiteralString(LiteralString literal) {
+ return 'r$literal';
}
- Code unaryFn(String fn, Code right) {
- var rightExp = right.exp;
- if (fn == '!') {
- rightExp = "toBool($rightExp)";
+ visitLiteralArray(LiteralArray literal) {
+ if (literal.elements.isEmpty) return '[]';
+ StringBuffer buffer = new StringBuffer();
+ for (int i = 0; i < literal.elements.length; i++) {
+ if (i != 0) buffer.write(', ');
+ buffer.write(evaluate(literal.elements[i]));
}
- return new Code("${_op(fn)}${rightExp}");
+ return "[ $buffer ]";
}
- Code assignment(Code left, Code right, evalError) =>
- left._assign(right);
-
- Code multipleStatements(List<Code >statements) {
- var code = "var ret, last;\n";
- code += statements.map((Code s) =>
- "last = ${s.exp};\nif (last != null) { ret = last; }\n").join('\n');
- code += "return ret;\n";
- return new MultipleStatementCode(code);
+ visitLiteralObject(LiteralObject literal) {
+ if (literal.keys.isEmpty) return '{}';
+ StringBuffer buffer = new StringBuffer();
+ List<String> keys = literal.keys;
+ for (int i = 0; i < keys.length; i++) {
+ if (i != 0) buffer.write(', ');
+ buffer.write("'${keys[i]}': ");
+ buffer.write(evaluate(literal.values[i]));
+ }
+ return "{ $buffer }";
}
+}
- Code functionCall(Code fn, fnName, List<Code> argsFn, evalError) =>
- new Code("safeFunctionCall(${fn.exp}, \'${escape(fnName)}\', evalError)(${argsFn.map((a) => a.exp).join(', ')})");
+class HelperMap {
+ final Map<String, String> helpers = new Map<String, String>();
+ final Map<String, String> names = new Map<String, String>();
- Code arrayDeclaration(List<Code> elementFns) =>
- new Code("[${elementFns.map((Code e) => e.exp).join(', ')}]");
+ final String prefix;
+ final Function template;
+ final Function templateForReserved;
- Code objectIndex(Code obj, Code indexFn, evalError) {
- var assign = (Code right) =>
- new Code("objectIndexSetField(${obj.exp}, ${indexFn.exp}, ${right.exp}, evalError)");
+ HelperMap(this.prefix, this.template, this.templateForReserved);
- return new Code("objectIndexGetField(${obj.exp}, ${indexFn.exp}, evalError)", assign);
+ String lookup(String key) {
+ String name = _computeName(key);
+ if (helpers.containsKey(key)) return name;
+ helpers[key] = isReserved(key)
+ ? templateForReserved(name, key)
+ : template(name, key);
+ return name;
}
- Code fieldAccess(Code object, String field) {
- var getterFnName = _getterGen(field);
- var assign = (Code right) {
- var setterFnName = _getterGen.setter(field);
- return new Code("$setterFnName(${object.exp}, ${right.exp})");
- };
- return new Code("$getterFnName/*field:$field*/(${object.exp})", assign);
+ String _computeName(String key) {
+ String result = names[key];
+ if (result != null) return result;
+ return names[key] = "$prefix$key";
}
+}
- Code object(List keyValues) =>
- new Code(
- "{${keyValues.map((k) => "${_value(k["key"])}: ${k["value"].exp}").join(', ')}}");
- profiled(value, perf, text) => value; // no profiling for now
- Code fromOperator(String op) => new Code(_op(op));
+// ------------------------------------------------------------------
+// Templates for generated getters.
+// ------------------------------------------------------------------
+String getterTemplate(String name, String key) => """
+$name(o) {
+ if (o == null) return null;
+ return (o is Map) ? o["${escape(key)}"] : o.$key;
+}
+""";
- Code getterSetter(String key) {
- var getterFnName = _getterGen(key);
+String getterTemplateForReserved(String name, String key) => """
+$name(o) {
+ if (o == null) return null;
+ return (o is Map) ? o["${escape(key)}"] : null;
+}
+""";
- var assign = (Code right) {
- var setterFnName = _getterGen.setter(key);
- return new Code("${setterFnName}(scope, ${right.exp})", null, setterFnName);
- };
- return new Code("$getterFnName(scope)", assign, getterFnName);
+// ------------------------------------------------------------------
+// Templates for generated holders (getters for assignment).
+// ------------------------------------------------------------------
+String holderTemplate(String name, String key) => """
+$name(o) {
+ if (o == null) return null;
+ if (o is Map) {
+ var key = "${escape(key)}";
+ var result = o[key];
+ return (result == null) ? result = o[key] = {} : result;
+ } else {
+ var result = o.$key;
+ return (result == null) ? result = o.$key = {} : result;
}
+}
+""";
- String _value(v) =>
- v is String ? "r\'${escape(v)}\'" : "$v";
+String holderTemplateForReserved(String name, String key) => """
+$name(o) {
+ if (o == null) return null;
+ if (o is !Map) return {};
+ var key = "${escape(key)}";
+ var result = o[key];
+ return (result == null) ? result = o[key] = {} : result;
+}
+""";
- Code value(v) => new Code(_value(v));
- Code zero() => ZERO;
+// ------------------------------------------------------------------
+// Templates for generated setters.
+// ------------------------------------------------------------------
+String setterTemplate(String name, String key) => """
+$name(o, v) {
+ if (o is Map) o["${escape(key)}"] = v; else o.$key = v;
+ return v;
+}
+""";
- Code filter(String filterName,
- Code leftHandSide,
- List<Code> parameters,
- Function evalError) {
- return new Code(
- 'filters(\'${filterName}\')(${
- ([leftHandSide]..addAll(parameters))
- .map((Code p) => p.exp).join(', ')})');
- }
+String setterTemplateForReserved(String name, String key) => """
+$name(o, v) {
+ if (o is Map) o["${escape(key)}"] = v;
+ return v;
}
+""";
« no previous file with comments | « third_party/pkg/angular/lib/tools/io_impl.dart ('k') | third_party/pkg/angular/lib/tools/parser_generator/generator.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698