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

Side by Side Diff: lib/compiler/implementation/js_backend/constant_emitter.dart

Issue 10915083: Change assert implementation to not depend on a top-level function called 'assert'. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Address review comments. Created 8 years, 3 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2012, 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 class ConstantEmitter implements ConstantVisitor {
6 final Compiler compiler;
7 final Namer namer;
8
9 CodeBuffer buffer;
10 bool shouldEmitCanonicalVersion;
11
12 ConstantEmitter(this.compiler, this.namer);
13
14 /**
15 * Unless the constant can be emitted multiple times (as for numbers and
16 * strings) use the canonical name.
17 */
18 void emitCanonicalVersionOfConstant(Constant constant, CodeBuffer newBuffer) {
19 shouldEmitCanonicalVersion = true;
20 buffer = newBuffer;
21 _visit(constant);
22 }
23
24 /**
25 * Emit the JavaScript code of the constant. If the constant must be
26 * canonicalized this method emits the initialization value.
27 */
28 void emitJavaScriptCodeForConstant(Constant constant, CodeBuffer newBuffer) {
29 shouldEmitCanonicalVersion = false;
30 buffer = newBuffer;
31 _visit(constant);
32 }
33
34 _visit(Constant constant) {
35 constant.accept(this);
36 }
37
38 void visitSentinel(SentinelConstant constant) {
39 if (shouldEmitCanonicalVersion) {
40 buffer.add(namer.CURRENT_ISOLATE);
41 } else {
42 compiler.internalError(
43 "The parameter sentinel constant does not need specific JS code");
44 }
45 }
46
47 void visitFunction(FunctionConstant constant) {
48 if (shouldEmitCanonicalVersion) {
49 buffer.add(namer.isolatePropertiesAccess(constant.element));
50 } else {
51 compiler.internalError(
52 "The function constant does not need specific JS code");
53 }
54 }
55
56 void visitNull(NullConstant constant) {
57 buffer.add("null");
58 }
59
60 void visitInt(IntConstant constant) {
61 buffer.add(constant.value.toString());
62 }
63
64 void visitDouble(DoubleConstant constant) {
65 double value = constant.value;
66 if (value.isNaN()) {
67 buffer.add("(0/0)");
68 } else if (value == double.INFINITY) {
69 buffer.add("(1/0)");
70 } else if (value == -double.INFINITY) {
71 buffer.add("(-1/0)");
72 } else {
73 buffer.add("$value");
74 }
75 }
76
77 void visitTrue(TrueConstant constant) {
78 buffer.add("true");
79 }
80
81 void visitFalse(FalseConstant constant) {
82 buffer.add("false");
83 }
84
85 /**
86 * Write the contents of the quoted string to a [CodeBuffer] in
87 * a form that is valid as JavaScript string literal content.
88 * The string is assumed quoted by single quote characters.
89 */
90 void writeEscapedString(DartString string,
91 CodeBuffer buffer,
92 Node diagnosticNode) {
93 Iterator<int> iterator = string.iterator();
94 while (iterator.hasNext()) {
95 int code = iterator.next();
96 if (code === $SQ) {
97 buffer.add(@"\'");
98 } else if (code === $LF) {
99 buffer.add(@'\n');
100 } else if (code === $CR) {
101 buffer.add(@'\r');
102 } else if (code === $LS) {
103 // This Unicode line terminator and $PS are invalid in JS string
104 // literals.
105 buffer.add(@'\u2028');
106 } else if (code === $PS) {
107 buffer.add(@'\u2029');
108 } else if (code === $BACKSLASH) {
109 buffer.add(@'\\');
110 } else {
111 if (code > 0xffff) {
112 compiler.reportError(
113 diagnosticNode,
114 'Unhandled non-BMP character: U+${code.toRadixString(16)}');
115 }
116 // TODO(lrn): Consider whether all codes above 0x7f really need to
117 // be escaped. We build a Dart string here, so it should be a literal
118 // stage that converts it to, e.g., UTF-8 for a JS interpreter.
119 if (code < 0x20) {
120 buffer.add(@'\x');
121 if (code < 0x10) buffer.add('0');
122 buffer.add(code.toRadixString(16));
123 } else if (code >= 0x80) {
124 if (code < 0x100) {
125 buffer.add(@'\x');
126 } else {
127 buffer.add(@'\u');
128 if (code < 0x1000) {
129 buffer.add('0');
130 }
131 }
132 buffer.add(code.toRadixString(16));
133 } else {
134 buffer.addCharCode(code);
135 }
136 }
137 }
138 }
139
140 void visitString(StringConstant constant) {
141 buffer.add("'");
142 writeEscapedString(constant.value, buffer, constant.node);
143 buffer.add("'");
144 }
145
146 void emitCanonicalVersion(Constant constant) {
147 String name = namer.constantName(constant);
148 buffer.add(namer.isolatePropertiesAccessForConstant(name));
149 }
150
151 void visitList(ListConstant constant) {
152 if (shouldEmitCanonicalVersion) {
153 emitCanonicalVersion(constant);
154 } else {
155 shouldEmitCanonicalVersion = true;
156 buffer.add("${namer.ISOLATE}.makeConstantList");
157 buffer.add("([");
158 for (int i = 0; i < constant.entries.length; i++) {
159 if (i != 0) buffer.add(", ");
160 _visit(constant.entries[i]);
161 }
162 buffer.add("])");
163 }
164 }
165
166 String getJsConstructor(ClassElement element) {
167 return namer.isolatePropertiesAccess(element);
168 }
169
170 void visitMap(MapConstant constant) {
171 if (shouldEmitCanonicalVersion) {
172 emitCanonicalVersion(constant);
173 } else {
174 void writeJsMap() {
175 buffer.add("{");
176 int valueIndex = 0;
177 for (int i = 0; i < constant.keys.entries.length; i++) {
178 StringConstant key = constant.keys.entries[i];
179 if (key.value == MapConstant.PROTO_PROPERTY) continue;
180
181 if (valueIndex != 0) buffer.add(", ");
182
183 // Keys in literal maps must be emitted in place.
184 emitJavaScriptCodeForConstant(key, buffer);
185
186 buffer.add(": ");
187 emitCanonicalVersionOfConstant(constant.values[valueIndex++], buffer);
188 }
189 buffer.add("}");
190 if (valueIndex != constant.values.length) {
191 compiler.internalError("Bad value count.");
192 }
193 }
194
195 void badFieldCountError() {
196 compiler.internalError(
197 "Compiler and ConstantMap disagree on number of fields.");
198 }
199
200 shouldEmitCanonicalVersion = true;
201
202 ClassElement classElement = constant.type.element;
203 buffer.add("new ");
204 buffer.add(getJsConstructor(classElement));
205 buffer.add("(");
206 // The arguments of the JavaScript constructor for any given Dart class
207 // are in the same order as the members of the class element.
208 int emittedArgumentCount = 0;
209 classElement.forEachInstanceField(
210 includeBackendMembers: true,
211 includeSuperMembers: true,
212 f: (ClassElement enclosing, Element field) {
213 if (emittedArgumentCount != 0) buffer.add(", ");
214 if (field.name == MapConstant.LENGTH_NAME) {
215 buffer.add(constant.keys.entries.length);
216 } else if (field.name == MapConstant.JS_OBJECT_NAME) {
217 writeJsMap();
218 } else if (field.name == MapConstant.KEYS_NAME) {
219 emitCanonicalVersionOfConstant(constant.keys, buffer);
220 } else if (field.name == MapConstant.PROTO_VALUE) {
221 assert(constant.protoValue !== null);
222 emitCanonicalVersionOfConstant(constant.protoValue, buffer);
223 } else {
224 badFieldCountError();
225 }
226 emittedArgumentCount++;
227 });
228 if ((constant.protoValue === null && emittedArgumentCount != 3) ||
229 (constant.protoValue !== null && emittedArgumentCount != 4)) {
230 badFieldCountError();
231 }
232 buffer.add(")");
233 }
234 }
235
236 void visitConstructed(ConstructedConstant constant) {
237 if (shouldEmitCanonicalVersion) {
238 emitCanonicalVersion(constant);
239 } else {
240 shouldEmitCanonicalVersion = true;
241
242 buffer.add("new ");
243 buffer.add(getJsConstructor(constant.type.element));
244 buffer.add("(");
245 for (int i = 0; i < constant.fields.length; i++) {
246 if (i != 0) buffer.add(", ");
247 _visit(constant.fields[i]);
248 }
249 buffer.add(")");
250 }
251 }
252 }
OLDNEW
« no previous file with comments | « lib/compiler/implementation/elements/elements.dart ('k') | lib/compiler/implementation/js_backend/emitter.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698