OLD | NEW |
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
4 library kernel.ast_to_binary; | 4 library kernel.ast_to_binary; |
5 | 5 |
6 import '../ast.dart'; | 6 import '../ast.dart'; |
7 import '../import_table.dart'; | 7 import '../import_table.dart'; |
8 import 'tag.dart'; | 8 import 'tag.dart'; |
9 import 'dart:convert'; | 9 import 'dart:convert'; |
10 import 'dart:typed_data'; | 10 import 'dart:typed_data'; |
11 import 'dart:collection'; | 11 import 'dart:collection'; |
12 | 12 |
13 /// Writes to a binary file. | 13 /// Writes to a binary file. |
14 /// | 14 /// |
15 /// A [BinaryPrinter] can be used to write one file and must then be | 15 /// A [BinaryPrinter] can be used to write one file and must then be |
16 /// discarded. | 16 /// discarded. |
17 class BinaryPrinter extends Visitor { | 17 class BinaryPrinter extends Visitor { |
18 ImportTable _importTable; | 18 ImportTable _importTable; |
19 | 19 |
20 // TODO: We can do the indexing on-the-fly, but for now just keep it simple. | |
21 VariableIndexer _variableIndexer; | 20 VariableIndexer _variableIndexer; |
22 LabelIndexer _labelIndexer; | 21 LabelIndexer _labelIndexer; |
23 SwitchCaseIndexer _switchCaseIndexer; | 22 SwitchCaseIndexer _switchCaseIndexer; |
24 final TypeParameterIndexer _typeParameterIndexer = new TypeParameterIndexer(); | 23 final TypeParameterIndexer _typeParameterIndexer = new TypeParameterIndexer(); |
25 final GlobalIndexer _globalIndexer; | 24 final GlobalIndexer _globalIndexer; |
26 final StringIndexer _stringIndexer = new StringIndexer(); | 25 final StringIndexer _stringIndexer = new StringIndexer(); |
27 final StringIndexer _sourceUriIndexer = new StringIndexer(); | 26 final StringIndexer _sourceUriIndexer = new StringIndexer(); |
28 | 27 |
29 final BufferedSink _sink; | 28 final BufferedSink _sink; |
30 | 29 |
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
267 writeStringReference('${node.importUri}'); | 266 writeStringReference('${node.importUri}'); |
268 // TODO(jensj): We save (almost) the same URI twice. | 267 // TODO(jensj): We save (almost) the same URI twice. |
269 writeUriReference(node.fileUri ?? ''); | 268 writeUriReference(node.fileUri ?? ''); |
270 writeNodeList(node.classes); | 269 writeNodeList(node.classes); |
271 writeNodeList(node.fields); | 270 writeNodeList(node.fields); |
272 writeNodeList(node.procedures); | 271 writeNodeList(node.procedures); |
273 } | 272 } |
274 | 273 |
275 void writeAnnotation(Expression annotation) { | 274 void writeAnnotation(Expression annotation) { |
276 _variableIndexer ??= new VariableIndexer(); | 275 _variableIndexer ??= new VariableIndexer(); |
277 _variableIndexer.build(annotation); | |
278 writeNode(annotation); | 276 writeNode(annotation); |
279 } | 277 } |
280 | 278 |
281 void writeAnnotationList(List<Expression> annotations) { | 279 void writeAnnotationList(List<Expression> annotations) { |
282 writeList(annotations, writeAnnotation); | 280 writeList(annotations, writeAnnotation); |
283 } | 281 } |
284 | 282 |
285 visitClass(Class node) { | 283 visitClass(Class node) { |
286 int flags = node.isAbstract ? 1 : 0; | 284 int flags = node.isAbstract ? 1 : 0; |
287 if (node.level == ClassLevel.Type) { | 285 if (node.level == ClassLevel.Type) { |
288 flags |= 0x2; | 286 flags |= 0x2; |
289 } | 287 } |
290 if (node.isMixinApplication) { | 288 if (node.isMixinApplication) { |
291 writeByte(Tag.MixinClass); | 289 writeByte(Tag.MixinClass); |
292 writeByte(flags); | 290 writeByte(flags); |
293 writeStringReference(node.name ?? ''); | 291 writeStringReference(node.name ?? ''); |
294 writeUriReference(node.fileUri ?? ''); | 292 writeUriReference(node.fileUri ?? ''); |
295 writeAnnotationList(node.annotations); | 293 writeAnnotationList(node.annotations); |
296 _typeParameterIndexer.push(node.typeParameters); | 294 _typeParameterIndexer.enter(node.typeParameters); |
297 writeNodeList(node.typeParameters); | 295 writeNodeList(node.typeParameters); |
298 writeNode(node.supertype); | 296 writeNode(node.supertype); |
299 writeNode(node.mixedInType); | 297 writeNode(node.mixedInType); |
300 writeNodeList(node.implementedTypes); | 298 writeNodeList(node.implementedTypes); |
301 writeNodeList(node.constructors); | 299 writeNodeList(node.constructors); |
302 _typeParameterIndexer.pop(node.typeParameters); | 300 _typeParameterIndexer.exit(node.typeParameters); |
303 } else { | 301 } else { |
304 writeByte(Tag.NormalClass); | 302 writeByte(Tag.NormalClass); |
305 writeByte(flags); | 303 writeByte(flags); |
306 writeStringReference(node.name ?? ''); | 304 writeStringReference(node.name ?? ''); |
307 writeUriReference(node.fileUri ?? ''); | 305 writeUriReference(node.fileUri ?? ''); |
308 writeAnnotationList(node.annotations); | 306 writeAnnotationList(node.annotations); |
309 _typeParameterIndexer.push(node.typeParameters); | 307 _typeParameterIndexer.enter(node.typeParameters); |
310 writeNodeList(node.typeParameters); | 308 writeNodeList(node.typeParameters); |
311 writeOptionalNode(node.supertype); | 309 writeOptionalNode(node.supertype); |
312 writeNodeList(node.implementedTypes); | 310 writeNodeList(node.implementedTypes); |
313 writeNodeList(node.fields); | 311 writeNodeList(node.fields); |
314 writeNodeList(node.constructors); | 312 writeNodeList(node.constructors); |
315 writeNodeList(node.procedures); | 313 writeNodeList(node.procedures); |
316 _typeParameterIndexer.pop(node.typeParameters); | 314 _typeParameterIndexer.exit(node.typeParameters); |
317 } | 315 } |
318 } | 316 } |
319 | 317 |
320 static final Name _emptyName = new Name(''); | 318 static final Name _emptyName = new Name(''); |
321 | 319 |
322 visitConstructor(Constructor node) { | 320 visitConstructor(Constructor node) { |
323 _variableIndexer = new VariableIndexer()..build(node); | 321 _variableIndexer = new VariableIndexer(); |
324 writeByte(Tag.Constructor); | 322 writeByte(Tag.Constructor); |
325 writeByte(node.flags); | 323 writeByte(node.flags); |
326 writeName(node.name ?? _emptyName); | 324 writeName(node.name ?? _emptyName); |
327 writeAnnotationList(node.annotations); | 325 writeAnnotationList(node.annotations); |
328 assert(node.function.typeParameters.isEmpty); | 326 assert(node.function.typeParameters.isEmpty); |
329 writeNode(node.function); | 327 writeNode(node.function); |
| 328 // Parameters are in scope in the initializers. |
| 329 _variableIndexer.restoreScope(node.function.positionalParameters.length + |
| 330 node.function.namedParameters.length); |
330 writeNodeList(node.initializers); | 331 writeNodeList(node.initializers); |
| 332 _variableIndexer = null; |
331 } | 333 } |
332 | 334 |
333 visitProcedure(Procedure node) { | 335 visitProcedure(Procedure node) { |
334 _variableIndexer = new VariableIndexer()..build(node); | 336 _variableIndexer = new VariableIndexer(); |
335 writeByte(Tag.Procedure); | 337 writeByte(Tag.Procedure); |
336 writeByte(node.kind.index); | 338 writeByte(node.kind.index); |
337 writeByte(node.flags); | 339 writeByte(node.flags); |
338 writeName(node.name ?? ''); | 340 writeName(node.name ?? ''); |
339 writeUriReference(node.fileUri ?? ''); | 341 writeUriReference(node.fileUri ?? ''); |
340 writeAnnotationList(node.annotations); | 342 writeAnnotationList(node.annotations); |
341 writeOptionalNode(node.function); | 343 writeOptionalNode(node.function); |
| 344 _variableIndexer = null; |
342 } | 345 } |
343 | 346 |
344 visitField(Field node) { | 347 visitField(Field node) { |
345 _variableIndexer = new VariableIndexer()..build(node); | 348 _variableIndexer = new VariableIndexer(); |
346 writeByte(Tag.Field); | 349 writeByte(Tag.Field); |
347 writeOffset(node); | 350 writeOffset(node); |
348 writeByte(node.flags); | 351 writeByte(node.flags); |
349 writeName(node.name ?? ''); | 352 writeName(node.name ?? ''); |
350 writeUriReference(node.fileUri ?? ''); | 353 writeUriReference(node.fileUri ?? ''); |
351 writeAnnotationList(node.annotations); | 354 writeAnnotationList(node.annotations); |
352 writeNode(node.type); | 355 writeNode(node.type); |
353 writeOptionalInferredValue(node.inferredValue); | 356 writeOptionalInferredValue(node.inferredValue); |
354 writeOptionalNode(node.initializer); | 357 writeOptionalNode(node.initializer); |
| 358 _variableIndexer = null; |
355 } | 359 } |
356 | 360 |
357 visitInvalidInitializer(InvalidInitializer node) { | 361 visitInvalidInitializer(InvalidInitializer node) { |
358 writeByte(Tag.InvalidInitializer); | 362 writeByte(Tag.InvalidInitializer); |
359 } | 363 } |
360 | 364 |
361 visitFieldInitializer(FieldInitializer node) { | 365 visitFieldInitializer(FieldInitializer node) { |
362 writeByte(Tag.FieldInitializer); | 366 writeByte(Tag.FieldInitializer); |
363 writeMemberReference(node.field); | 367 writeMemberReference(node.field); |
364 writeNode(node.value); | 368 writeNode(node.value); |
(...skipping 11 matching lines...) Expand all Loading... |
376 writeNode(node.arguments); | 380 writeNode(node.arguments); |
377 } | 381 } |
378 | 382 |
379 visitLocalInitializer(LocalInitializer node) { | 383 visitLocalInitializer(LocalInitializer node) { |
380 writeByte(Tag.LocalInitializer); | 384 writeByte(Tag.LocalInitializer); |
381 writeVariableDeclaration(node.variable); | 385 writeVariableDeclaration(node.variable); |
382 } | 386 } |
383 | 387 |
384 visitFunctionNode(FunctionNode node) { | 388 visitFunctionNode(FunctionNode node) { |
385 assert(_variableIndexer != null); | 389 assert(_variableIndexer != null); |
| 390 _variableIndexer.pushScope(); |
386 var oldLabels = _labelIndexer; | 391 var oldLabels = _labelIndexer; |
387 _labelIndexer = new LabelIndexer()..build(node); | 392 _labelIndexer = new LabelIndexer(); |
388 var oldCases = _switchCaseIndexer; | 393 var oldCases = _switchCaseIndexer; |
389 _switchCaseIndexer = new SwitchCaseIndexer()..build(node); | 394 _switchCaseIndexer = new SwitchCaseIndexer(); |
390 // Note: FunctionNode has no tag. | 395 // Note: FunctionNode has no tag. |
391 _typeParameterIndexer.push(node.typeParameters); | 396 _typeParameterIndexer.enter(node.typeParameters); |
392 writeByte(node.asyncMarker.index); | 397 writeByte(node.asyncMarker.index); |
393 writeNodeList(node.typeParameters); | 398 writeNodeList(node.typeParameters); |
394 writeUInt30(node.requiredParameterCount); | 399 writeUInt30(node.requiredParameterCount); |
395 writeVariableDeclarationList(node.positionalParameters); | 400 writeVariableDeclarationList(node.positionalParameters); |
396 writeVariableDeclarationList(node.namedParameters); | 401 writeVariableDeclarationList(node.namedParameters); |
397 writeNode(node.returnType); | 402 writeNode(node.returnType); |
398 writeOptionalInferredValue(node.inferredReturnValue); | 403 writeOptionalInferredValue(node.inferredReturnValue); |
399 writeOptionalNode(node.body); | 404 writeOptionalNode(node.body); |
400 _labelIndexer = oldLabels; | 405 _labelIndexer = oldLabels; |
401 _switchCaseIndexer = oldCases; | 406 _switchCaseIndexer = oldCases; |
402 _typeParameterIndexer.pop(node.typeParameters); | 407 _typeParameterIndexer.exit(node.typeParameters); |
| 408 _variableIndexer.popScope(); |
403 } | 409 } |
404 | 410 |
405 visitInvalidExpression(InvalidExpression node) { | 411 visitInvalidExpression(InvalidExpression node) { |
406 writeByte(Tag.InvalidExpression); | 412 writeByte(Tag.InvalidExpression); |
407 } | 413 } |
408 | 414 |
409 visitVariableGet(VariableGet node) { | 415 visitVariableGet(VariableGet node) { |
410 assert(_variableIndexer != null); | 416 assert(_variableIndexer != null); |
411 int index = _variableIndexer[node.variable]; | 417 int index = _variableIndexer[node.variable]; |
412 assert(index != null); | 418 assert(index != null); |
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
676 | 682 |
677 visitFunctionExpression(FunctionExpression node) { | 683 visitFunctionExpression(FunctionExpression node) { |
678 writeByte(Tag.FunctionExpression); | 684 writeByte(Tag.FunctionExpression); |
679 writeNode(node.function); | 685 writeNode(node.function); |
680 } | 686 } |
681 | 687 |
682 visitLet(Let node) { | 688 visitLet(Let node) { |
683 writeByte(Tag.Let); | 689 writeByte(Tag.Let); |
684 writeVariableDeclaration(node.variable); | 690 writeVariableDeclaration(node.variable); |
685 writeNode(node.body); | 691 writeNode(node.body); |
| 692 --_variableIndexer.stackHeight; |
686 } | 693 } |
687 | 694 |
688 writeStatementOrEmpty(Statement node) { | 695 writeStatementOrEmpty(Statement node) { |
689 if (node == null) { | 696 if (node == null) { |
690 writeByte(Tag.EmptyStatement); | 697 writeByte(Tag.EmptyStatement); |
691 } else { | 698 } else { |
692 writeNode(node); | 699 writeNode(node); |
693 } | 700 } |
694 } | 701 } |
695 | 702 |
696 visitInvalidStatement(InvalidStatement node) { | 703 visitInvalidStatement(InvalidStatement node) { |
697 writeByte(Tag.InvalidStatement); | 704 writeByte(Tag.InvalidStatement); |
698 } | 705 } |
699 | 706 |
700 visitExpressionStatement(ExpressionStatement node) { | 707 visitExpressionStatement(ExpressionStatement node) { |
701 writeByte(Tag.ExpressionStatement); | 708 writeByte(Tag.ExpressionStatement); |
702 writeNode(node.expression); | 709 writeNode(node.expression); |
703 } | 710 } |
704 | 711 |
705 visitBlock(Block node) { | 712 visitBlock(Block node) { |
| 713 _variableIndexer.pushScope(); |
706 writeByte(Tag.Block); | 714 writeByte(Tag.Block); |
707 writeNodeList(node.statements); | 715 writeNodeList(node.statements); |
| 716 _variableIndexer.popScope(); |
708 } | 717 } |
709 | 718 |
710 visitEmptyStatement(EmptyStatement node) { | 719 visitEmptyStatement(EmptyStatement node) { |
711 writeByte(Tag.EmptyStatement); | 720 writeByte(Tag.EmptyStatement); |
712 } | 721 } |
713 | 722 |
714 visitAssertStatement(AssertStatement node) { | 723 visitAssertStatement(AssertStatement node) { |
715 writeByte(Tag.AssertStatement); | 724 writeByte(Tag.AssertStatement); |
716 writeNode(node.condition); | 725 writeNode(node.condition); |
717 writeOptionalNode(node.message); | 726 writeOptionalNode(node.message); |
718 } | 727 } |
719 | 728 |
720 visitLabeledStatement(LabeledStatement node) { | 729 visitLabeledStatement(LabeledStatement node) { |
| 730 _labelIndexer.enter(node); |
721 writeByte(Tag.LabeledStatement); | 731 writeByte(Tag.LabeledStatement); |
722 writeNode(node.body); | 732 writeNode(node.body); |
| 733 _labelIndexer.exit(); |
723 } | 734 } |
724 | 735 |
725 visitBreakStatement(BreakStatement node) { | 736 visitBreakStatement(BreakStatement node) { |
726 writeByte(Tag.BreakStatement); | 737 writeByte(Tag.BreakStatement); |
727 writeUInt30(_labelIndexer[node.target]); | 738 writeUInt30(_labelIndexer[node.target]); |
728 } | 739 } |
729 | 740 |
730 visitWhileStatement(WhileStatement node) { | 741 visitWhileStatement(WhileStatement node) { |
731 writeByte(Tag.WhileStatement); | 742 writeByte(Tag.WhileStatement); |
732 writeNode(node.condition); | 743 writeNode(node.condition); |
733 writeNode(node.body); | 744 writeNode(node.body); |
734 } | 745 } |
735 | 746 |
736 visitDoStatement(DoStatement node) { | 747 visitDoStatement(DoStatement node) { |
737 writeByte(Tag.DoStatement); | 748 writeByte(Tag.DoStatement); |
738 writeNode(node.body); | 749 writeNode(node.body); |
739 writeNode(node.condition); | 750 writeNode(node.condition); |
740 } | 751 } |
741 | 752 |
742 visitForStatement(ForStatement node) { | 753 visitForStatement(ForStatement node) { |
| 754 _variableIndexer.pushScope(); |
743 writeByte(Tag.ForStatement); | 755 writeByte(Tag.ForStatement); |
744 writeVariableDeclarationList(node.variables); | 756 writeVariableDeclarationList(node.variables); |
745 writeOptionalNode(node.condition); | 757 writeOptionalNode(node.condition); |
746 writeNodeList(node.updates); | 758 writeNodeList(node.updates); |
747 writeNode(node.body); | 759 writeNode(node.body); |
| 760 _variableIndexer.popScope(); |
748 } | 761 } |
749 | 762 |
750 visitForInStatement(ForInStatement node) { | 763 visitForInStatement(ForInStatement node) { |
| 764 _variableIndexer.pushScope(); |
751 writeByte(node.isAsync ? Tag.AsyncForInStatement : Tag.ForInStatement); | 765 writeByte(node.isAsync ? Tag.AsyncForInStatement : Tag.ForInStatement); |
752 writeVariableDeclaration(node.variable); | 766 writeVariableDeclaration(node.variable); |
753 writeNode(node.iterable); | 767 writeNode(node.iterable); |
754 writeNode(node.body); | 768 writeNode(node.body); |
| 769 _variableIndexer.popScope(); |
755 } | 770 } |
756 | 771 |
757 visitSwitchStatement(SwitchStatement node) { | 772 visitSwitchStatement(SwitchStatement node) { |
| 773 _switchCaseIndexer.enter(node); |
758 writeByte(Tag.SwitchStatement); | 774 writeByte(Tag.SwitchStatement); |
759 writeNode(node.expression); | 775 writeNode(node.expression); |
760 writeNodeList(node.cases); | 776 writeNodeList(node.cases); |
| 777 _switchCaseIndexer.exit(node); |
761 } | 778 } |
762 | 779 |
763 visitSwitchCase(SwitchCase node) { | 780 visitSwitchCase(SwitchCase node) { |
764 // Note: there is no tag on SwitchCase. | 781 // Note: there is no tag on SwitchCase. |
765 writeNodeList(node.expressions); | 782 writeNodeList(node.expressions); |
766 writeByte(node.isDefault ? 1 : 0); | 783 writeByte(node.isDefault ? 1 : 0); |
767 writeNode(node.body); | 784 writeNode(node.body); |
768 } | 785 } |
769 | 786 |
770 visitContinueSwitchStatement(ContinueSwitchStatement node) { | 787 visitContinueSwitchStatement(ContinueSwitchStatement node) { |
(...skipping 14 matching lines...) Expand all Loading... |
785 } | 802 } |
786 | 803 |
787 visitTryCatch(TryCatch node) { | 804 visitTryCatch(TryCatch node) { |
788 writeByte(Tag.TryCatch); | 805 writeByte(Tag.TryCatch); |
789 writeNode(node.body); | 806 writeNode(node.body); |
790 writeNodeList(node.catches); | 807 writeNodeList(node.catches); |
791 } | 808 } |
792 | 809 |
793 visitCatch(Catch node) { | 810 visitCatch(Catch node) { |
794 // Note: there is no tag on Catch. | 811 // Note: there is no tag on Catch. |
| 812 _variableIndexer.pushScope(); |
795 writeNode(node.guard); | 813 writeNode(node.guard); |
796 writeOptionalVariableDeclaration(node.exception); | 814 writeOptionalVariableDeclaration(node.exception); |
797 writeOptionalVariableDeclaration(node.stackTrace); | 815 writeOptionalVariableDeclaration(node.stackTrace); |
798 writeNode(node.body); | 816 writeNode(node.body); |
| 817 _variableIndexer.popScope(); |
799 } | 818 } |
800 | 819 |
801 visitTryFinally(TryFinally node) { | 820 visitTryFinally(TryFinally node) { |
802 writeByte(Tag.TryFinally); | 821 writeByte(Tag.TryFinally); |
803 writeNode(node.body); | 822 writeNode(node.body); |
804 writeNode(node.finalizer); | 823 writeNode(node.finalizer); |
805 } | 824 } |
806 | 825 |
807 visitYieldStatement(YieldStatement node) { | 826 visitYieldStatement(YieldStatement node) { |
808 writeByte(Tag.YieldStatement); | 827 writeByte(Tag.YieldStatement); |
809 writeByte(node.flags); | 828 writeByte(node.flags); |
810 writeNode(node.expression); | 829 writeNode(node.expression); |
811 } | 830 } |
812 | 831 |
813 visitVariableDeclaration(VariableDeclaration node) { | 832 visitVariableDeclaration(VariableDeclaration node) { |
814 writeByte(Tag.VariableDeclaration); | 833 writeByte(Tag.VariableDeclaration); |
815 writeVariableDeclaration(node); | 834 writeVariableDeclaration(node); |
816 } | 835 } |
817 | 836 |
818 void writeVariableDeclaration(VariableDeclaration node) { | 837 void writeVariableDeclaration(VariableDeclaration node) { |
819 writeByte(node.flags); | 838 writeByte(node.flags); |
820 writeStringReference(node.name ?? ''); | 839 writeStringReference(node.name ?? ''); |
821 writeNode(node.type); | 840 writeNode(node.type); |
822 writeOptionalInferredValue(node.inferredValue); | 841 writeOptionalInferredValue(node.inferredValue); |
823 writeOptionalNode(node.initializer); | 842 writeOptionalNode(node.initializer); |
| 843 // Declare the variable after its initializer. It is not in scope in its |
| 844 // own initializer. |
| 845 _variableIndexer.declare(node); |
824 } | 846 } |
825 | 847 |
826 void writeVariableDeclarationList(List<VariableDeclaration> nodes) { | 848 void writeVariableDeclarationList(List<VariableDeclaration> nodes) { |
827 writeList(nodes, writeVariableDeclaration); | 849 writeList(nodes, writeVariableDeclaration); |
828 } | 850 } |
829 | 851 |
830 void writeOptionalVariableDeclaration(VariableDeclaration node) { | 852 void writeOptionalVariableDeclaration(VariableDeclaration node) { |
831 if (node == null) { | 853 if (node == null) { |
832 writeByte(Tag.Nothing); | 854 writeByte(Tag.Nothing); |
833 } else { | 855 } else { |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
882 | 904 |
883 visitFunctionType(FunctionType node) { | 905 visitFunctionType(FunctionType node) { |
884 if (node.requiredParameterCount == node.positionalParameters.length && | 906 if (node.requiredParameterCount == node.positionalParameters.length && |
885 node.typeParameters.isEmpty && | 907 node.typeParameters.isEmpty && |
886 node.namedParameters.isEmpty) { | 908 node.namedParameters.isEmpty) { |
887 writeByte(Tag.SimpleFunctionType); | 909 writeByte(Tag.SimpleFunctionType); |
888 writeNodeList(node.positionalParameters); | 910 writeNodeList(node.positionalParameters); |
889 writeNode(node.returnType); | 911 writeNode(node.returnType); |
890 } else { | 912 } else { |
891 writeByte(Tag.FunctionType); | 913 writeByte(Tag.FunctionType); |
892 _typeParameterIndexer.push(node.typeParameters); | 914 _typeParameterIndexer.enter(node.typeParameters); |
893 writeNodeList(node.typeParameters); | 915 writeNodeList(node.typeParameters); |
894 writeUInt30(node.requiredParameterCount); | 916 writeUInt30(node.requiredParameterCount); |
895 writeNodeList(node.positionalParameters); | 917 writeNodeList(node.positionalParameters); |
896 writeList(node.namedParameters.keys.toList(), (String name) { | 918 writeList(node.namedParameters.keys.toList(), (String name) { |
897 writeStringReference(name); | 919 writeStringReference(name); |
898 writeNode(node.namedParameters[name]); | 920 writeNode(node.namedParameters[name]); |
899 }); | 921 }); |
900 writeNode(node.returnType); | 922 writeNode(node.returnType); |
901 _typeParameterIndexer.pop(node.typeParameters); | 923 _typeParameterIndexer.exit(node.typeParameters); |
902 } | 924 } |
903 } | 925 } |
904 | 926 |
905 visitTypeParameterType(TypeParameterType node) { | 927 visitTypeParameterType(TypeParameterType node) { |
906 writeByte(Tag.TypeParameterType); | 928 writeByte(Tag.TypeParameterType); |
907 writeUInt30(_typeParameterIndexer[node.parameter]); | 929 writeUInt30(_typeParameterIndexer[node.parameter]); |
908 } | 930 } |
909 | 931 |
910 visitTypeParameter(TypeParameter node) { | 932 visitTypeParameter(TypeParameter node) { |
911 writeStringReference(node.name ?? ''); | 933 writeStringReference(node.name ?? ''); |
912 writeNode(node.bound); | 934 writeNode(node.bound); |
913 } | 935 } |
914 | 936 |
915 defaultNode(Node node) { | 937 defaultNode(Node node) { |
916 throw 'Unsupported node: $node'; | 938 throw 'Unsupported node: $node'; |
917 } | 939 } |
918 } | 940 } |
919 | 941 |
920 class VariableIndexer extends RecursiveVisitor { | 942 class VariableIndexer { |
921 final Map<VariableDeclaration, int> index = <VariableDeclaration, int>{}; | 943 final Map<VariableDeclaration, int> index = <VariableDeclaration, int>{}; |
| 944 final List<int> scopes = <int>[]; |
922 int stackHeight = 0; | 945 int stackHeight = 0; |
923 | 946 |
924 void build(TreeNode node) => node.accept(this); | 947 void declare(VariableDeclaration node) { |
925 | 948 index[node] = stackHeight++; |
926 visitConstructor(Constructor node) { | |
927 node.function.accept(this); | |
928 // Keep parameters in scope when traversing initializers. | |
929 stackHeight = node.function.positionalParameters.length + | |
930 node.function.namedParameters.length; | |
931 for (var init in node.initializers) { | |
932 init.accept(this); | |
933 } | |
934 stackHeight = 0; | |
935 } | 949 } |
936 | 950 |
937 visitFunctionNode(FunctionNode node) { | 951 void pushScope() { |
938 int frame = stackHeight; | 952 scopes.add(stackHeight); |
939 node.visitChildren(this); | |
940 stackHeight = frame; | |
941 } | 953 } |
942 | 954 |
943 visitBlock(Block node) { | 955 void popScope() { |
944 int frame = stackHeight; | 956 stackHeight = scopes.removeLast(); |
945 node.visitChildren(this); | |
946 stackHeight = frame; | |
947 } | 957 } |
948 | 958 |
949 visitLet(Let node) { | 959 void restoreScope(int numberOfVariables) { |
950 int frame = stackHeight; | 960 stackHeight += numberOfVariables; |
951 node.visitChildren(this); | |
952 stackHeight = frame; | |
953 } | 961 } |
954 | 962 |
955 visitForInStatement(ForInStatement node) { | 963 int operator [](VariableDeclaration node) { |
956 int frame = stackHeight; | 964 return index[node]; |
957 node.visitChildren(this); | |
958 stackHeight = frame; | |
959 } | 965 } |
960 | |
961 visitForStatement(ForStatement node) { | |
962 int frame = stackHeight; | |
963 node.visitChildren(this); | |
964 stackHeight = frame; | |
965 } | |
966 | |
967 visitCatch(Catch node) { | |
968 int frame = stackHeight; | |
969 node.visitChildren(this); | |
970 stackHeight = frame; | |
971 } | |
972 | |
973 visitVariableDeclaration(VariableDeclaration node) { | |
974 node.visitChildren(this); | |
975 assert(!index.containsKey(node)); | |
976 index[node] = stackHeight; | |
977 ++stackHeight; | |
978 } | |
979 | |
980 int operator [](VariableDeclaration node) => index[node]; | |
981 } | 966 } |
982 | 967 |
983 class LabelIndexer extends RecursiveVisitor { | 968 class LabelIndexer { |
984 final Map<LabeledStatement, int> index = <LabeledStatement, int>{}; | 969 final Map<LabeledStatement, int> index = <LabeledStatement, int>{}; |
985 int stackHeight = 0; | 970 int stackHeight = 0; |
986 | 971 |
987 void build(FunctionNode node) => node.visitChildren(this); | 972 void enter(LabeledStatement node) { |
988 | 973 index[node] = stackHeight++; |
989 visitFunctionNode(FunctionNode node) { | |
990 // Inhibit traversal into nested functions. | |
991 // The client must create a separate label indexer for the | |
992 // nested function. | |
993 } | 974 } |
994 | 975 |
995 visitLabeledStatement(LabeledStatement node) { | 976 void exit() { |
996 index[node] = stackHeight; | |
997 ++stackHeight; | |
998 node.visitChildren(this); | |
999 --stackHeight; | 977 --stackHeight; |
1000 } | 978 } |
1001 | 979 |
1002 int operator [](LabeledStatement node) => index[node]; | 980 int operator [](LabeledStatement node) => index[node]; |
1003 } | 981 } |
1004 | 982 |
1005 class SwitchCaseIndexer extends RecursiveVisitor { | 983 class SwitchCaseIndexer { |
1006 final Map<SwitchCase, int> index = <SwitchCase, int>{}; | 984 final Map<SwitchCase, int> index = <SwitchCase, int>{}; |
1007 int stackHeight = 0; | 985 int stackHeight = 0; |
1008 | 986 |
1009 void build(FunctionNode node) => node.visitChildren(this); | 987 void enter(SwitchStatement node) { |
1010 | 988 for (var caseNode in node.cases) { |
1011 visitFunctionNode(FunctionNode node) { | 989 index[caseNode] = stackHeight++; |
1012 // Inhibit traversal into nested functions. | 990 } |
1013 // The client must create a separate case indexer for the | |
1014 // nested function. | |
1015 } | 991 } |
1016 | 992 |
1017 visitSwitchStatement(SwitchStatement node) { | 993 void exit(SwitchStatement node) { |
1018 int oldHeight = stackHeight; | 994 stackHeight -= node.cases.length; |
1019 for (var caseNode in node.cases) { | |
1020 index[caseNode] = stackHeight; | |
1021 ++stackHeight; | |
1022 } | |
1023 node.visitChildren(this); | |
1024 stackHeight = oldHeight; | |
1025 } | 995 } |
1026 | 996 |
1027 int operator [](SwitchCase node) => index[node]; | 997 int operator [](SwitchCase node) => index[node]; |
1028 } | 998 } |
1029 | 999 |
1030 /// The type parameter indexer works differently from the other indexers because | |
1031 /// type parameters can be bound inside DartTypes, which can be shared by the | |
1032 /// in-memory representation (but not the binary form) and the index depends on | |
1033 /// the use site. | |
1034 class TypeParameterIndexer { | 1000 class TypeParameterIndexer { |
1035 final Map<TypeParameter, int> index = <TypeParameter, int>{}; | 1001 final Map<TypeParameter, int> index = <TypeParameter, int>{}; |
1036 int stackHeight = 0; | 1002 int stackHeight = 0; |
1037 | 1003 |
1038 void push(List<TypeParameter> typeParameters) { | 1004 void enter(List<TypeParameter> typeParameters) { |
1039 for (var parameter in typeParameters) { | 1005 for (var parameter in typeParameters) { |
1040 index[parameter] = stackHeight; | 1006 index[parameter] = stackHeight; |
1041 ++stackHeight; | 1007 ++stackHeight; |
1042 } | 1008 } |
1043 } | 1009 } |
1044 | 1010 |
1045 void pop(List<TypeParameter> typeParameters) { | 1011 void exit(List<TypeParameter> typeParameters) { |
1046 stackHeight -= typeParameters.length; | 1012 stackHeight -= typeParameters.length; |
1047 } | 1013 } |
1048 | 1014 |
1049 int operator [](TypeParameter parameter) => index[parameter]; | 1015 int operator [](TypeParameter parameter) => index[parameter]; |
1050 } | 1016 } |
1051 | 1017 |
1052 class StringTableEntry implements Comparable<StringTableEntry> { | 1018 class StringTableEntry implements Comparable<StringTableEntry> { |
1053 final String value; | 1019 final String value; |
1054 int frequency = 0; | 1020 int frequency = 0; |
1055 | 1021 |
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1249 void flush() { | 1215 void flush() { |
1250 _sink.add(_buffer.sublist(0, length)); | 1216 _sink.add(_buffer.sublist(0, length)); |
1251 _buffer = new Uint8List(SIZE); | 1217 _buffer = new Uint8List(SIZE); |
1252 length = 0; | 1218 length = 0; |
1253 } | 1219 } |
1254 | 1220 |
1255 void flushAndDestroy() { | 1221 void flushAndDestroy() { |
1256 _sink.add(_buffer.sublist(0, length)); | 1222 _sink.add(_buffer.sublist(0, length)); |
1257 } | 1223 } |
1258 } | 1224 } |
OLD | NEW |