From f50661aac44f59e7be2cb0abf9148c7a09e7f32c Mon Sep 17 00:00:00 2001 From: Vijay Menon Date: Tue, 14 Jul 2015 17:48:38 -0700 Subject: [PATCH] Add support for Enums Fixes #248 R=jmesserly@google.com Review URL: https://codereview.chromium.org/1224083017. --- .../lib/src/codegen/js_codegen.dart | 53 ++++++++++++++++++- .../test/codegen/expect/fieldtest.js | 19 +++++++ pkg/dev_compiler/test/codegen/fieldtest.dart | 4 ++ 3 files changed, 74 insertions(+), 2 deletions(-) diff --git a/pkg/dev_compiler/lib/src/codegen/js_codegen.dart b/pkg/dev_compiler/lib/src/codegen/js_codegen.dart index 1eab31a1d0a5..3dfbe257d4fe 100644 --- a/pkg/dev_compiler/lib/src/codegen/js_codegen.dart +++ b/pkg/dev_compiler/lib/src/codegen/js_codegen.dart @@ -420,8 +420,57 @@ class JSCodegenVisitor extends GeneralizingAstVisitor { } @override - JS.Statement visitEnumDeclaration(EnumDeclaration node) => - _unimplementedCall("Unimplemented enum: $node").toStatement(); + JS.Statement visitEnumDeclaration(EnumDeclaration node) { + var element = node.element; + var type = element.type; + var name = js.string(type.name); + var id = new JS.Identifier(type.name); + + // Generate a class per section 13 of the spec. + // TODO(vsm): Generate any accompanying metadata + + // Create constructor and initialize index + var constructor = + new JS.Method(name, js.call('function(index) { this.index = index; }')); + var fields = new List.from( + element.fields.where((f) => f.type == type)); + + // Create toString() method + var properties = new List(); + for (var i = 0; i < fields.length; ++i) { + properties.add(new JS.Property( + js.number(i), js.string('${type.name}.${fields[i].name}'))); + } + var nameMap = new JS.ObjectInitializer(properties, multiline: true); + var toStringF = new JS.Method(js.string('toString'), + js.call('function () { return #[this.index]; }', nameMap)); + + // Create enum class + var classExpr = new JS.ClassExpression( + id, _classHeritage(element), [constructor, toStringF]); + var result = [js.statement('#', classExpr)]; + + // Create static fields for each enum value + for (var i = 0; i < fields.length; ++i) { + result.add(js.statement('#.# = dart.const(new #(#));', [ + id, + fields[i].name, + id, + js.number(i) + ])); + } + + // Create static values list + var values = new JS.ArrayInitializer( + fields.map((f) => js.call('#.#', [id, f.name])).toList()); + result.add(js.statement('#.values = dart.const(dart.list(#, #));', [ + id, + values, + _emitTypeName(type) + ])); + + return _statement(result); + } /// Given a class element and body, complete the class declaration. /// This handles generic type parameters, laziness (in library-cycle cases), diff --git a/pkg/dev_compiler/test/codegen/expect/fieldtest.js b/pkg/dev_compiler/test/codegen/expect/fieldtest.js index b69e90dba298..f69baba971e9 100644 --- a/pkg/dev_compiler/test/codegen/expect/fieldtest.js +++ b/pkg/dev_compiler/test/codegen/expect/fieldtest.js @@ -92,12 +92,31 @@ dart_library.library('fieldtest', null, /* Imports */[ StaticFieldOrder2.c = dart.notNull(StaticFieldOrder2.d) + 2; StaticFieldOrder2.b = dart.notNull(StaticFieldOrder2.c) + 3; StaticFieldOrder2.a = dart.notNull(StaticFieldOrder2.b) + 1; + class MyEnum extends core.Object { + MyEnum(index) { + this.index = index; + } + toString() { + return { + 0: "MyEnum.Val1", + 1: "MyEnum.Val2", + 2: "MyEnum.Val3", + 3: "MyEnum.Val4" + }[this.index]; + } + }; + MyEnum.Val1 = dart.const(new MyEnum(0)); + MyEnum.Val2 = dart.const(new MyEnum(1)); + MyEnum.Val3 = dart.const(new MyEnum(2)); + MyEnum.Val4 = dart.const(new MyEnum(3)); + MyEnum.values = dart.const(dart.list([MyEnum.Val1, MyEnum.Val2, MyEnum.Val3, MyEnum.Val4], MyEnum)); function main() { let a = new A(); foo(a); bar(a); core.print(baz(a)); core.print(new (Generic$(core.String))().foo(' world')); + core.print(MyEnum.values); } dart.fn(main, dart.void, []); // Exports: diff --git a/pkg/dev_compiler/test/codegen/fieldtest.dart b/pkg/dev_compiler/test/codegen/fieldtest.dart index a6b140e72df5..b3a596ee61f4 100644 --- a/pkg/dev_compiler/test/codegen/fieldtest.dart +++ b/pkg/dev_compiler/test/codegen/fieldtest.dart @@ -64,6 +64,8 @@ class StaticFieldOrder2 { static const d = 4; } +enum MyEnum { Val1, Val2, Val3, Val4 } + void main() { var a = new A(); foo(a); @@ -71,4 +73,6 @@ void main() { print(baz(a)); print(new Generic().foo(' world')); + + print(MyEnum.values); }