OLD | NEW |
1 import 'package:angular/core/parser/parser.dart'; | 1 import 'package:angular/core/parser/parser.dart'; |
2 import 'package:angular/utils.dart' show isReservedWord; | 2 import 'package:angular/utils.dart' show isReservedWord; |
3 import 'dart:math'; | |
4 | 3 |
5 class DartGetterSetterGen extends ParserBackend { | 4 class DartGetterSetterGen extends ParserBackend { |
6 final Set<String> properties = new Set<String>(); | 5 final properties = new Set<String>(); |
7 final Map<String, Set<int>> calls = new Map<String, Set<int>>(); | 6 final calls = new Set<String>(); |
| 7 final symbols = new Set<String>(); |
8 | 8 |
9 bool isAssignable(expression) => true; | 9 bool isAssignable(expression) => true; |
10 | 10 |
11 registerAccess(String name) { | 11 registerAccess(String name) { |
12 if (isReservedWord(name)) return; | 12 if (isReservedWord(name)) return; |
13 properties.add(name); | 13 properties.add(name); |
14 } | 14 } |
15 | 15 |
16 registerCall(String name, List arguments) { | 16 registerCall(String name, CallArguments arguments) { |
17 if (isReservedWord(name)) return; | 17 if (isReservedWord(name)) return; |
18 Set<int> arities = calls.putIfAbsent(name, () => new Set<int>()); | 18 calls.add(name); |
19 arities.add(arguments.length); | 19 symbols.addAll(arguments.named.keys); |
20 } | 20 } |
21 | 21 |
22 newAccessScope(String name) | 22 newAccessScope(String name) => registerAccess(name); |
23 => registerAccess(name); | 23 newAccessMember(var object, String name) => registerAccess(name); |
24 newAccessMember(var object, String name) | 24 newCallScope(String name, CallArguments arguments) => |
25 => registerAccess(name); | 25 registerCall(name, arguments); |
26 newCallScope(String name, List arguments) | 26 newCallMember(var object, String name, CallArguments arguments) => |
27 => registerCall(name, arguments); | 27 registerCall(name, arguments); |
28 newCallMember(var object, String name, List arguments) | |
29 => registerCall(name, arguments); | |
30 } | 28 } |
31 | 29 |
32 class ParserGetterSetter { | 30 class ParserGetterSetter { |
33 final Parser parser; | 31 final Parser parser; |
34 final ParserBackend backend; | 32 final ParserBackend backend; |
35 ParserGetterSetter(this.parser, this.backend); | 33 ParserGetterSetter(this.parser, this.backend); |
36 | 34 |
37 generateParser(List<String> exprs) { | 35 generateParser(List<String> exprs, StringSink sink) { |
38 exprs.forEach((expr) { | 36 exprs.forEach((expr) { |
39 try { | 37 try { |
40 parser(expr); | 38 parser(expr); |
41 } catch (e) { | 39 } catch (e) { |
42 // Ignore exceptions. | 40 // Ignore exceptions. |
43 } | 41 } |
44 }); | 42 }); |
45 | 43 |
46 DartGetterSetterGen backend = this.backend; | 44 DartGetterSetterGen backend = this.backend; |
47 print(generateClosureMap(backend.properties, backend.calls)); | 45 sink.write(generateClosureMap(backend.properties, backend.calls, |
| 46 backend.symbols)); |
48 } | 47 } |
49 | 48 |
50 generateClosureMap(Set<String> properties, Map<String, Set<int>> calls) { | 49 generateClosureMap(Set<String> properties, |
| 50 Set<String> calls, |
| 51 Set<String> symbols) { |
| 52 var getters = new Set.from(properties)..addAll(calls); |
51 return ''' | 53 return ''' |
52 class StaticClosureMap extends ClosureMap { | 54 StaticClosureMap closureMap = new StaticClosureMap( |
53 Map<String, Getter> _getters = ${generateGetterMap(properties)}; | 55 ${generateGetterMap(getters)}, |
54 Map<String, Setter> _setters = ${generateSetterMap(properties)}; | 56 ${generateSetterMap(properties)}, |
55 List<Map<String, Function>> _functions = ${generateFunctionMap(calls)}; | 57 ${generateSymbolMap(symbols)}); |
56 | |
57 Getter lookupGetter(String name) | |
58 => _getters[name]; | |
59 Setter lookupSetter(String name) | |
60 => _setters[name]; | |
61 lookupFunction(String name, int arity) | |
62 => (arity < _functions.length) ? _functions[arity][name] : null; | |
63 } | |
64 '''; | 58 '''; |
65 } | 59 } |
66 | 60 |
67 generateGetterMap(Iterable<String> keys) { | 61 generateGetterMap(Iterable<String> keys) { |
68 var lines = keys.map((key) => 'r"${key}": (o) => o.$key'); | 62 var lines = keys.map((key) => ' r"${key}": (o) => o.$key'); |
69 return '{\n ${lines.join(",\n ")}\n }'; | 63 return '{\n${lines.join(",\n")}\n }'; |
70 } | 64 } |
71 | 65 |
72 generateSetterMap(Iterable<String> keys) { | 66 generateSetterMap(Iterable<String> keys) { |
73 var lines = keys.map((key) => 'r"${key}": (o, v) => o.$key = v'); | 67 var lines = keys.map((key) => ' r"${key}": (o,v) => o.$key = v'); |
74 return '{\n ${lines.join(",\n ")}\n }'; | 68 return '{\n${lines.join(",\n")}\n }'; |
75 } | 69 } |
76 | 70 |
77 generateFunctionMap(Map<String, Set<int>> calls) { | 71 generateSymbolMap(Set<String> symbols) { |
78 Map<int, Set<String>> arities = {}; | 72 var lines = symbols.map((key) => ' r"${key}": #$key'); |
79 calls.forEach((name, callArities) { | 73 return '{\n${lines.join(",\n")}\n }'; |
80 callArities.forEach((arity){ | |
81 arities.putIfAbsent(arity, () => new Set<String>()).add(name); | |
82 }); | |
83 }); | |
84 | |
85 var maxArity = arities.keys.reduce((x, y) => max(x, y)); | |
86 | |
87 var maps = new Iterable.generate(maxArity, (arity) { | |
88 var names = arities[arity]; | |
89 if (names == null) { | |
90 return '{\n }'; | |
91 } else { | |
92 var args = new List.generate(arity, (e) => "a$e").join(','); | |
93 var p = args.isEmpty ? '' : ', $args'; | |
94 var lines = names.map((name) => 'r"$name": (o$p) => o.$name($args)'); | |
95 return '{\n ${lines.join(",\n ")}\n }'; | |
96 } | |
97 }); | |
98 | |
99 return '[${maps.join(",")}]'; | |
100 } | 74 } |
101 } | 75 } |
OLD | NEW |