From 965ebf16cbf8e7ac572c7feb4fc7e8bb6aa08d4e Mon Sep 17 00:00:00 2001 From: Ethan Date: Mon, 8 Jan 2024 14:02:45 -0700 Subject: [PATCH] Better error message for invoking nonexistent bridged default constructor --- example/bridge_example.dart | 92 ------------------- .../expression/method_invocation.dart | 8 +- 2 files changed, 7 insertions(+), 93 deletions(-) delete mode 100644 example/bridge_example.dart diff --git a/example/bridge_example.dart b/example/bridge_example.dart deleted file mode 100644 index f7a52d8..0000000 --- a/example/bridge_example.dart +++ /dev/null @@ -1,92 +0,0 @@ -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]!.$reified as List).cast()); - } - - @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!' -} diff --git a/lib/src/eval/compiler/expression/method_invocation.dart b/lib/src/eval/compiler/expression/method_invocation.dart index 353b53a..8f6358d 100644 --- a/lib/src/eval/compiler/expression/method_invocation.dart +++ b/lib/src/eval/compiler/expression/method_invocation.dart @@ -117,8 +117,14 @@ Variable compileMethodInvocation(CompilerContext ctx, MethodInvocation e, if (_dec.isBridge) { final bridge = _dec.bridge; + + /// If we're invoking a class identifier directly (like ClassName()), call + /// its default constructor final fnDescriptor = bridge is BridgeClassDef - ? bridge.constructors['']!.functionDescriptor + ? (bridge.constructors['']?.functionDescriptor ?? + (throw CompileError( + 'Class "${e.methodName.name}" does not have a default constructor', + e))) : (bridge as BridgeFunctionDeclaration).function; final argsPair = compileArgumentListWithBridge(