From a7de106cdf35264fc4b41080c9750a139fe20726 Mon Sep 17 00:00:00 2001 From: Ben Vercammen Date: Sat, 6 Jan 2024 08:33:03 +0100 Subject: [PATCH 1/3] Book bridge example (not working) --- example/bridge_example.dart | 91 +++++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 example/bridge_example.dart diff --git a/example/bridge_example.dart b/example/bridge_example.dart new file mode 100644 index 00000000..82435387 --- /dev/null +++ b/example/bridge_example.dart @@ -0,0 +1,91 @@ +import 'package:dart_eval/dart_eval.dart'; +import 'package:dart_eval/dart_eval_bridge.dart'; +import 'package:dart_eval/dart_eval_extensions.dart'; +import 'package:dart_eval/stdlib/core.dart'; + +/// An example class we want to bridge +class Book { + Book(this.pages); + final List pages; + + String getPage(int index) => pages[index]; +} + +/// This is our bridge class +class $Book$bridge extends Book with $Bridge { + static final $type = BridgeTypeSpec('package:hello/book.dart', 'Book').ref; + + /// Create a class declaration for the dart_eval compiler + static final $declaration = BridgeClassDef(BridgeClassType($type), + constructors: { + // Define the default constructor with an empty string + '': BridgeFunctionDef(returns: $type.annotate, params: [ + // 'pages'.param(CoreTypes.string.ref.annotate) + 'pages'.param(CoreTypes.list.ref.annotate) + ]).asConstructor + }, + methods: { + 'getPage': BridgeFunctionDef( + returns: CoreTypes.string.ref.annotate, + params: ['index'.param(CoreTypes.int.ref.annotate)], + ).asMethod, + }, bridge: true); + + /// Recreate the original constructor + $Book$bridge(super.pages); + + static $Value? $new( + Runtime runtime, $Value? target, List<$Value?> args) { + return $Book$bridge(args[0]!.$value); + } + + @override + $Value? $bridgeGet(String identifier) { + if (identifier == 'getPage') { + return $Function((_, target, args) { + return $String(getPage(args[0]!.$value)); + }); + } + throw UnimplementedError('Unknown property $identifier'); + } + + @override + $Value? $bridgeSet(String identifier, $Value value) => + throw UnimplementedError('Unknown property $identifier'); + + /// Override the original class' properties and methods + @override + String getPage(int index) => $_invoke('getPage', [$int(index)]); + + @override + List get pages => $_get('pages'); +} + +void main() { + final compiler = Compiler(); + compiler.defineBridgeClass($Book$bridge.$declaration); + + final program = compiler.compile({'hello' : { + 'main.dart': ''' + import 'book.dart'; + class MyBook extends Book { + MyBook(List pages) : super(pages); + String getPage(int index) => 'Hello world!'; + } + + Book main() { + final book = MyBook(['Hello world!', 'Hello again!']); + return book; + } + ''' + }}); + + final runtime = Runtime.ofProgram(program); + runtime.registerBridgeFunc( + 'package:hello/book.dart', 'Book.', $Book$bridge.$new, isBridge: true); + + // Now we can use the new book class outside dart_eval! + final book = runtime.executeLib('package:hello/main.dart', 'main') + as Book; + print(book.getPage(1)); // -> 'Hello world!' +} \ No newline at end of file From a2c7b25a1d2800fcac5f1ad131abbc13f705c3e6 Mon Sep 17 00:00:00 2001 From: Ben Vercammen Date: Sat, 13 Jan 2024 10:38:47 +0100 Subject: [PATCH 2/3] Book bridge example (fixed) --- example/bridge_example.dart | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/example/bridge_example.dart b/example/bridge_example.dart index 82435387..fa5df7f3 100644 --- a/example/bridge_example.dart +++ b/example/bridge_example.dart @@ -6,6 +6,7 @@ import 'package:dart_eval/stdlib/core.dart'; /// An example class we want to bridge class Book { Book(this.pages); + final List pages; String getPage(int index) => pages[index]; @@ -19,24 +20,23 @@ class $Book$bridge extends Book with $Bridge { static final $declaration = BridgeClassDef(BridgeClassType($type), constructors: { // Define the default constructor with an empty string - '': BridgeFunctionDef(returns: $type.annotate, params: [ - // 'pages'.param(CoreTypes.string.ref.annotate) - 'pages'.param(CoreTypes.list.ref.annotate) - ]).asConstructor + '': BridgeFunctionDef( + returns: $type.annotate, + params: ['pages'.param(CoreTypes.list.ref.annotate)]).asConstructor }, methods: { 'getPage': BridgeFunctionDef( returns: CoreTypes.string.ref.annotate, params: ['index'.param(CoreTypes.int.ref.annotate)], ).asMethod, - }, bridge: true); + }, + bridge: true); /// Recreate the original constructor $Book$bridge(super.pages); - static $Value? $new( - Runtime runtime, $Value? target, List<$Value?> args) { - return $Book$bridge(args[0]!.$value); + static $Value? $new(Runtime runtime, $Value? target, List<$Value?> args) { + return $Book$bridge((args[0]!.$reified as List).cast()); } @override @@ -65,8 +65,9 @@ void main() { final compiler = Compiler(); compiler.defineBridgeClass($Book$bridge.$declaration); - final program = compiler.compile({'hello' : { - 'main.dart': ''' + final program = compiler.compile({ + 'hello': { + 'main.dart': ''' import 'book.dart'; class MyBook extends Book { MyBook(List pages) : super(pages); @@ -78,14 +79,15 @@ void main() { return book; } ''' - }}); + } + }); final runtime = Runtime.ofProgram(program); runtime.registerBridgeFunc( - 'package:hello/book.dart', 'Book.', $Book$bridge.$new, isBridge: true); + 'package:hello/book.dart', 'Book.', $Book$bridge.$new, + isBridge: true); // Now we can use the new book class outside dart_eval! - final book = runtime.executeLib('package:hello/main.dart', 'main') - as Book; + final book = runtime.executeLib('package:hello/main.dart', 'main') as Book; print(book.getPage(1)); // -> 'Hello world!' -} \ No newline at end of file +} From a39b68610325e36ee69be8adb5db4eac0a56d191 Mon Sep 17 00:00:00 2001 From: Ben Vercammen Date: Sun, 14 Jan 2024 10:31:15 +0100 Subject: [PATCH 3/3] Book bridge example (new question) --- example/bridge_example.dart | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/example/bridge_example.dart b/example/bridge_example.dart index fa5df7f3..7fec269c 100644 --- a/example/bridge_example.dart +++ b/example/bridge_example.dart @@ -24,6 +24,7 @@ class $Book$bridge extends Book with $Bridge { returns: $type.annotate, params: ['pages'.param(CoreTypes.list.ref.annotate)]).asConstructor }, + fields: {'pages': BridgeFieldDef(CoreTypes.list.ref.annotate)}, methods: { 'getPage': BridgeFunctionDef( returns: CoreTypes.string.ref.annotate, @@ -53,12 +54,25 @@ class $Book$bridge extends Book with $Bridge { $Value? $bridgeSet(String identifier, $Value value) => throw UnimplementedError('Unknown property $identifier'); + @override + $Value? $getProperty(Runtime runtime, String identifier) { + switch (identifier) { + case 'pages': + // TODO: Now we just pass along the bridged/parent class' property, so values don't change... + return $List<$String>(identifier, + $List<$String>.wrap(pages.map((e) => $String(e)).toList())); + default: + return super.$getProperty(runtime, identifier); + } + } + /// Override the original class' properties and methods @override String getPage(int index) => $_invoke('getPage', [$int(index)]); - @override - List get pages => $_get('pages'); + // @override + // List get pages => $_get('pages'); + } void main() { @@ -75,7 +89,9 @@ void main() { } Book main() { - final book = MyBook(['Hello world!', 'Hello again!']); + final book = MyBook(['Hi world!', 'Hello again!']); + book.pages.add('Next Chapter'); + book.pages.add('Final Chapter'); return book; } ''' @@ -90,4 +106,8 @@ void main() { // Now we can use the new book class outside dart_eval! final book = runtime.executeLib('package:hello/main.dart', 'main') as Book; print(book.getPage(1)); // -> 'Hello world!' + print(book is Book); + print(book is $Book$bridge); + // TODO: I'd expect the "Next Chapter" and "Final Chapter" here as well... + print(book.pages); }