OLD | NEW |
| (Empty) |
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | |
2 // for details. All rights reserved. Use of this source code is governed by a | |
3 // BSD-style license that can be found in the LICENSE file. | |
4 | |
5 | |
6 #import('file_system.dart'); | |
7 #import('lang.dart'); | |
8 | |
9 interface JsEvaluator { | |
10 var eval(String source); | |
11 } | |
12 | |
13 class Evaluator { | |
14 JsEvaluator _jsEvaluator; | |
15 static String _prelude; | |
16 Library _lib; | |
17 | |
18 static void initWorld(String homedir, List<String> args, FileSystem files) { | |
19 parseOptions(homedir, args, files); | |
20 options.forceDynamic = true; | |
21 options.compileAll = true; | |
22 | |
23 initializeWorld(files); | |
24 world.process(); | |
25 world.resolveAll(); | |
26 | |
27 world.gen = new WorldGenerator(null, new CodeWriter()); | |
28 world.gen.markLibrariesUsed([world.coreimpl, world.corelib]); | |
29 | |
30 world.gen.writeTypes(world.coreimpl); | |
31 world.gen.writeTypes(world.corelib); | |
32 world.gen.writeGlobals(); | |
33 _prelude = world.gen.writer.text; | |
34 | |
35 // Set these here so that we can compile the corelib without its errors | |
36 // killing us | |
37 options.throwOnErrors = true; | |
38 options.throwOnFatal = true; | |
39 } | |
40 | |
41 _removeMember(String name) { | |
42 _lib.topType._resolvedMembers.remove(name); | |
43 _lib.topType.members.remove(name); | |
44 // Don't rely on the existing member's jsname, because the existing member | |
45 // may be null but the jsname may still be defined. This can happen if | |
46 // multiple Evaluators are instantiated against the same world. | |
47 var jsname = '${_lib.jsname}_$name'; | |
48 world._topNames.remove(name); | |
49 world._topNames.remove(jsname); | |
50 } | |
51 | |
52 Evaluator(JsEvaluator this._jsEvaluator) { | |
53 if (_prelude == null) { | |
54 throw new UnsupportedOperationException( | |
55 "Must call Evaluator.initWorld before creating a Evaluator."); | |
56 } | |
57 this._jsEvaluator.eval(_prelude); | |
58 _lib = new Library(new SourceFile("_ifrog_", "")); | |
59 _lib.imports.add(new LibraryImport(world.corelib)); | |
60 _lib.resolve(); | |
61 } | |
62 | |
63 void _ensureVariableDefined(Identifier name, | |
64 [List<Token> modifiers = const [], TypeReference type = null]) { | |
65 var member = _lib.topType.getMember(name.name); | |
66 if (member is FieldMember || member is PropertyMember) return; | |
67 _removeMember(name.name); | |
68 _lib.topType.addField( | |
69 new VariableDefinition(modifiers, type, [name], [null], name.span)); | |
70 _lib.topType.getMember(name.name).resolve(); | |
71 } | |
72 | |
73 var eval(String dart) { | |
74 var source = new SourceFile("_ifrog_", dart); | |
75 world.gen.writer = new CodeWriter(); | |
76 | |
77 var code; | |
78 var parsed = new Parser(source, throwOnIncomplete: true, | |
79 optionalSemicolons: true).evalUnit(); | |
80 var method = new MethodMember("_ifrog_dummy", _lib.topType, null); | |
81 var methGen = new MethodGenerator(method, null); | |
82 | |
83 if (parsed is ExpressionStatement) { | |
84 var body = parsed.body; | |
85 // Auto-declare variables that haven't been declared yet, so users can | |
86 // write "a = 1" rather than "var a = 1" | |
87 if (body is BinaryExpression && body.op.kind == TokenKind.ASSIGN && | |
88 body.x is VarExpression) { | |
89 _ensureVariableDefined(body.x.dynamic.name); | |
90 } | |
91 code = body.visit(methGen).code; | |
92 | |
93 } else if (parsed is VariableDefinition) { | |
94 var assignments = <Statement>[]; | |
95 zip(parsed.names, parsed.values, (name, value) { | |
96 _ensureVariableDefined(name, parsed.modifiers, parsed.type); | |
97 var expr = new BinaryExpression( | |
98 new Token.fake(TokenKind.ASSIGN, parsed.span), | |
99 new VarExpression(name, name.span), value, parsed.span); | |
100 new ExpressionStatement(expr, parsed.span).visit(methGen); | |
101 }); | |
102 code = methGen.writer.text; | |
103 | |
104 } else if (parsed is FunctionDefinition) { | |
105 var methodName = parsed.name.name; | |
106 _removeMember(methodName); | |
107 _lib.topType.addMethod(methodName, parsed); | |
108 MethodMember definedMethod = _lib.topType.getMember(methodName); | |
109 definedMethod.resolve(); | |
110 var definedMethGen = new MethodGenerator(definedMethod, null); | |
111 definedMethGen.run(); | |
112 definedMethGen.writeDefinition(world.gen.writer, null); | |
113 code = world.gen.writer.text; | |
114 } else if (parsed is TypeDefinition) { | |
115 _removeMember(parsed.name.name); | |
116 parsed.visit(new _LibraryVisitor(_lib)); | |
117 var type = _lib.findTypeByName(parsed.name.name); | |
118 type.resolve(); | |
119 world.gen.markTypeUsed(type); | |
120 world.gen.writeType(type); | |
121 code = '${world.gen.writer.text}; undefined'; | |
122 } else { | |
123 parsed.visit(methGen); | |
124 code = methGen.writer.text; | |
125 } | |
126 | |
127 world.gen.writer = new CodeWriter(); | |
128 world.gen.writeAllDynamicStubs([world.coreimpl, world.corelib, _lib]); | |
129 | |
130 return this._jsEvaluator.eval('${world.gen.writer.text}; $code'); | |
131 } | |
132 } | |
OLD | NEW |