Skip to content

Commit a6eb0ff

Browse files
committed
prep 0.8.1
1 parent c719b27 commit a6eb0ff

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+1223
-447
lines changed

CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,14 @@
1+
## 0.8.1
2+
- Added support for configurable parser error handling
3+
- Fix accessing enum index values from an imported enum (thanks @jacksonrl)
4+
- Improve error handling when using `await` on a bridged future
5+
(thanks @MohamedAl-Kainai)
6+
- Support for enums in the binding generator
7+
- Fix serializing generic function types in BridgeTypeRef
8+
- Fix binding generator outputting incorrect import paths in eval_plugin.dart
9+
- Document how to create JSON bindings
10+
- Support for double.nan, double.infinity, and double.negativeInfinity
11+
112
## 0.8.0
213
- (Breaking) Type parameters provided to BridgeTypeRef are now
314
`BridgeTypeAnnotation` objects instead of `BridgeTypeRef` objects to allow

README.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ can be used outside it by creating an interface and [bridge class](#bridge-inter
2020
dart_eval's compiler is powered under the hood by the Dart
2121
[analyzer](https://pub.dev/packages/analyzer), so it achieves 100% correct and
2222
up-to-date parsing. While compilation and execution aren't quite there yet, dart_eval
23-
has over 250 tests that are run in CI to ensure correctness.
23+
has over 300 tests that are run in CI to ensure correctness.
2424

2525
Currently dart_eval implements a majority of the Dart spec, but there
2626
are still missing features like generators and extension methods.
@@ -340,7 +340,7 @@ final program = compiler.compile({'my_package': {
340340
final runtime = Runtime.ofProgram(program);
341341
runtime.addPlugin(MyAppPlugin()); // MyAppPlugin is the generated plugin
342342
343-
final book = runtime.executeLib('package:my_package/main.dart', 'main') as Book;
343+
final book = runtime.executeLib('package:my_package/main.dart', 'main').$value as Book;
344344
print(book.getPage(0)); // prints 'Page 1'
345345
```
346346

@@ -396,6 +396,10 @@ The binding generator also supports binding classes that rely on an
396396
existing plugin by using JSON binding files. To add these, create a folder in your project
397397
root called `.dart_eval`, add a `bindings` subfolder, and place JSON binding files there.
398398

399+
Currently, the binding generator does not support directly creating JSON bindings, but
400+
they can be created by first generating Dart bindings and then making a script to convert them
401+
to JSON with a `BridgeSerializer`.
402+
399403
For some specialized use cases, bindings may need to be manually adjusted or written from scratch.
400404
For information about this, refer to the
401405
[wrapper interop wiki page](https://github.com/ethanblake4/dart_eval/wiki/Wrappers) and

example/dart_eval_example.dart

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import 'package:dart_eval/stdlib/core.dart';
55

66
// ** Sample class definitions ** //
77
// Typically you would mark these with @Bind() to generate bindings,
8-
// but that annotation is part of the eval_annotation package so we
8+
// but that annotation is part of the eval_annotation package so we
99
// don't have access to it here.
1010

1111
// @Bind()
@@ -73,7 +73,7 @@ void main(List<String> args) {
7373
// Create a runtime from the compiled program, and add our plugin.
7474
final runtime = Runtime.ofProgram(program);
7575
runtime.addPlugin(ExamplePlugin());
76-
76+
7777
// Call the function and cast the result to the desired type
7878
final timeTracker = runtime.executeLib(
7979
'package:example/main.dart',
@@ -282,4 +282,4 @@ class ExamplePlugin implements EvalPlugin {
282282
$WorldTimeTracker$bridge.$new,
283283
isBridge: true);
284284
}
285-
}
285+
}

lib/dart_eval.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ export 'src/eval/runtime/runtime.dart' show Runtime;
66
export 'src/eval/compiler/compiler.dart';
77
export 'src/eval/compiler/program.dart';
88
export 'src/eval/runtime/override.dart' hide runtimeOverride;
9+
export 'src/eval/compiler/model/diagnostic_mode.dart';

lib/src/eval/bindgen/bindgen.dart

Lines changed: 71 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import 'package:dart_eval/src/eval/bindgen/bridge.dart';
99
import 'package:dart_eval/src/eval/bindgen/bridge_declaration.dart';
1010
import 'package:dart_eval/src/eval/bindgen/configure.dart';
1111
import 'package:dart_eval/src/eval/bindgen/context.dart';
12+
import 'package:dart_eval/src/eval/bindgen/enum.dart';
1213
import 'package:dart_eval/src/eval/bindgen/methods.dart';
1314
import 'package:dart_eval/src/eval/bindgen/properties.dart';
1415
import 'package:dart_eval/src/eval/bindgen/statics.dart';
@@ -27,6 +28,7 @@ class Bindgen implements BridgeDeclarationRegistry {
2728
final _bridgeDeclarations = <String, List<BridgeDeclaration>>{};
2829
final _exportedLibMappings = <String, String>{};
2930
final List<({String file, String uri, String name})> registerClasses = [];
31+
final List<({String file, String uri, String name})> registerEnums = [];
3032

3133
AnalysisContextCollection? _contextCollection;
3234

@@ -151,13 +153,15 @@ class Bindgen implements BridgeDeclarationRegistry {
151153
}
152154
}
153155

154-
final units =
155-
analysisResult.unit.declarations.whereType<ClassDeclaration>();
156+
final units = analysisResult.unit.declarations;
156157

157158
final resolved = units
158159
.where((declaration) => declaration.declaredFragment != null)
159-
.map((declaration) =>
160-
_$instance(ctx, declaration.declaredFragment!.element))
160+
.map((declaration) => declaration is ClassDeclaration
161+
? _$instance(ctx, declaration.declaredFragment!.element)
162+
: (declaration is EnumDeclaration
163+
? _$enum(ctx, declaration.declaredFragment!.element)
164+
: null))
161165
.toList()
162166
.nonNulls;
163167

@@ -177,29 +181,38 @@ class Bindgen implements BridgeDeclarationRegistry {
177181
return null;
178182
}
179183

180-
String? _$instance(BindgenContext ctx, ClassElement2 element) {
184+
({bool process, bool isBridge}) _shouldProcess(
185+
BindgenContext ctx, TypeDefiningElement2 element) {
181186
final metadata = element.metadata2;
182187
final bindAnno = metadata.annotations
183188
.firstWhereOrNull((element) => element.element2?.displayName == 'Bind');
184189
final bindAnnoValue = bindAnno?.computeConstantValue();
185-
if (!ctx.all) {
186-
if (bindAnnoValue == null) {
187-
return null;
188-
}
189-
final implicitSupers =
190-
bindAnnoValue.getField('implicitSupers')?.toBoolValue() ?? false;
191-
ctx.implicitSupers = implicitSupers;
192-
final override = bindAnnoValue.getField('overrideLibrary');
193-
if (override != null && !override.isNull) {
194-
final overrideUri = override.toStringValue();
195-
if (overrideUri != null) {
196-
ctx.libOverrides[element.name3!] = overrideUri;
197-
}
190+
191+
if (bindAnnoValue == null && !ctx.all) {
192+
return (process: false, isBridge: false);
193+
}
194+
final implicitSupers =
195+
bindAnnoValue?.getField('implicitSupers')?.toBoolValue() ?? false;
196+
ctx.implicitSupers = implicitSupers;
197+
final override = bindAnnoValue?.getField('overrideLibrary');
198+
if (override != null && !override.isNull) {
199+
final overrideUri = override.toStringValue();
200+
if (overrideUri != null) {
201+
ctx.libOverrides[element.name3!] = overrideUri;
198202
}
199203
}
200204

201205
final isBridge = bindAnnoValue?.getField('bridge')?.toBoolValue() ?? false;
202206

207+
return (process: ctx.all || bindAnnoValue != null, isBridge: isBridge);
208+
}
209+
210+
String? _$instance(BindgenContext ctx, ClassElement2 element) {
211+
final (:process, :isBridge) = _shouldProcess(ctx, element);
212+
if (!process) {
213+
return null;
214+
}
215+
203216
if (element.isSealed) {
204217
throw CompileError(
205218
'Cannot bind sealed class ${element.name3} as a bridge type. '
@@ -261,10 +274,46 @@ ${$setProperty(ctx, element)}
261274
''';
262275
}
263276

264-
String $superclassWrapper(BindgenContext ctx, ClassElement2 element) {
277+
String? _$enum(BindgenContext ctx, EnumElement2 element) {
278+
final (:process, :isBridge) = _shouldProcess(ctx, element);
279+
if (!process) {
280+
return null;
281+
}
282+
283+
registerEnums.add((
284+
file: ctx.filename,
285+
uri: ctx.libOverrides[element.name3!] ?? ctx.uri,
286+
name: '${element.name3!}${isBridge ? '\$bridge' : ''}',
287+
));
288+
289+
return '''
290+
/// dart_eval enum wrapper binding for [${element.name3}]
291+
class \$${element.name3} implements \$Instance {
292+
/// Configure this enum for use in a [Runtime]
293+
${bindConfigureEnumForRuntime(ctx, element)}
294+
/// Compile-time type specification of [\$${element.name3}]
295+
${bindTypeSpec(ctx, element)}
296+
/// Compile-time type declaration of [\$${element.name3}]
297+
${bindBridgeType(ctx, element)}
298+
/// Compile-time class declaration of [\$${element.name3}]
299+
${bindBridgeDeclaration(ctx, element)}
300+
${$enumValues(ctx, element)}
301+
${$staticMethods(ctx, element)}
302+
${$staticGetters(ctx, element)}
303+
${$staticSetters(ctx, element)}
304+
${$wrap(ctx, element)}
305+
${$getRuntimeType(element)}
306+
${$getProperty(ctx, element)}
307+
${$methods(ctx, element)}
308+
${$setProperty(ctx, element)}
309+
}
310+
''';
311+
}
312+
313+
String $superclassWrapper(BindgenContext ctx, InterfaceElement2 element) {
265314
final supertype = element.supertype;
266315
final objectWrapper = '\$Object(\$value)';
267-
if (supertype == null || ctx.implicitSupers) {
316+
if (supertype == null || ctx.implicitSupers || element is EnumElement2) {
268317
ctx.imports.add('package:dart_eval/stdlib/core.dart');
269318
return objectWrapper;
270319
}
@@ -279,14 +328,14 @@ ${$setProperty(ctx, element)}
279328
return narrowWrapper;
280329
}
281330

282-
String $getRuntimeType(ClassElement2 element) {
331+
String $getRuntimeType(InterfaceElement2 element) {
283332
return '''
284333
@override
285334
int \$getRuntimeType(Runtime runtime) => runtime.lookupType(\$spec);
286335
''';
287336
}
288337

289-
String $wrap(BindgenContext ctx, ClassElement2 element) {
338+
String $wrap(BindgenContext ctx, InterfaceElement2 element) {
290339
return '''
291340
final \$Instance _superclass;
292341

lib/src/eval/bindgen/bridge.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,8 @@ String parameterHeader(List<FormalParameterElement> params,
108108
paramBuffer.write('${param.type.getDisplayString()} ');
109109
}
110110
}
111-
paramBuffer.write(param.name3 ?? 'arg$i');
111+
paramBuffer.write(
112+
param.name3 == null || param.name3!.isEmpty ? 'arg$i' : param.name3);
112113
if (i < params.length - 1) {
113114
paramBuffer.write(', ');
114115
}

lib/src/eval/bindgen/bridge_declaration.dart

Lines changed: 35 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import 'package:dart_eval/src/eval/bindgen/context.dart';
33
import 'package:dart_eval/src/eval/bindgen/parameters.dart';
44
import 'package:dart_eval/src/eval/bindgen/type.dart';
55

6-
String bindTypeSpec(BindgenContext ctx, ClassElement2 element) {
6+
String bindTypeSpec(BindgenContext ctx, InterfaceElement2 element) {
77
final uri = ctx.libOverrides[element.name3] ?? ctx.uri;
88
return '''
99
static const \$spec = BridgeTypeSpec(
@@ -13,21 +13,21 @@ String bindTypeSpec(BindgenContext ctx, ClassElement2 element) {
1313
''';
1414
}
1515

16-
String bindBridgeType(BindgenContext ctx, ClassElement2 element) {
16+
String bindBridgeType(BindgenContext ctx, InterfaceElement2 element) {
1717
return '''
1818
static const \$type = BridgeTypeRef(\$spec);
1919
''';
2020
}
2121

22-
String? bindBridgeDeclaration(BindgenContext ctx, ClassElement2 element,
22+
String? bindBridgeDeclaration(BindgenContext ctx, InterfaceElement2 element,
2323
{bool isBridge = false}) {
24-
if (element.constructors2.isEmpty) {
24+
if (element is ClassElement2 && element.constructors2.isEmpty) {
2525
return null;
2626
}
2727

2828
var genericsStr = '';
2929
final typeParams = element.typeParameters2;
30-
if (typeParams.isNotEmpty) {
30+
if (typeParams.isNotEmpty && element is ClassElement2) {
3131
genericsStr = '''\ngenerics: {
3232
${typeParams.map((e) {
3333
final boundStr = e.bound != null && !ctx.implicitSupers
@@ -39,31 +39,41 @@ String? bindBridgeDeclaration(BindgenContext ctx, ClassElement2 element,
3939
}
4040

4141
var extendsStr = '';
42-
if (element.supertype != null &&
42+
if (element is ClassElement2 &&
43+
element.supertype != null &&
4344
!element.supertype!.isDartCoreObject &&
4445
!ctx.implicitSupers) {
4546
extendsStr =
4647
'\n\$extends: ${bridgeTypeRefFromType(ctx, element.supertype!)},';
4748
}
4849

4950
var implementsStr = '';
50-
if (element.interfaces.isNotEmpty) {
51+
if (element is ClassElement2 && element.interfaces.isNotEmpty) {
5152
implementsStr =
5253
'\n\$implements: [${element.interfaces.map((e) => bridgeTypeRefFromType(ctx, e)).join(', ')}],';
5354
}
5455

56+
var enumValuesStr = '';
57+
if (element is EnumElement2) {
58+
enumValuesStr = '''
59+
values: [${element.constants2.map((e) => "'${e.name3}'").join(', ')}],
60+
''';
61+
}
62+
5563
return '''
56-
static const \$declaration = BridgeClassDef(
57-
BridgeClassType(
64+
static const \$declaration = ${element is ClassElement2 ? 'BridgeClassDef(BridgeClassType(' : 'BridgeEnumDef('}
5865
\$type,
59-
isAbstract: ${element.isAbstract},
66+
${element is ClassElement2 && element.isAbstract ? 'isAbstract: true,' : ''}
67+
$enumValuesStr
6068
$genericsStr
6169
$extendsStr
6270
$implementsStr
63-
),
71+
${element is ClassElement2 ? '),' : ''}
72+
${element is ClassElement2 ? '''
6473
constructors: {
6574
${constructors(ctx, element)}
6675
},
76+
''' : ''}
6777
methods: {
6878
${methods(ctx, element)}
6979
},
@@ -76,19 +86,21 @@ ${setters(ctx, element)}
7686
fields: {
7787
${fields(ctx, element)}
7888
},
89+
${element is ClassElement2 ? '''
7990
wrap: ${!isBridge},
8091
bridge: $isBridge,
92+
''' : ''}
8193
);
8294
''';
8395
}
8496

85-
String constructors(BindgenContext ctx, ClassElement2 element) {
97+
String constructors(BindgenContext ctx, InterfaceElement2 element) {
8698
return element.constructors2
8799
.map((e) => bridgeConstructorDef(ctx, constructor: e))
88100
.join('\n');
89101
}
90102

91-
String methods(BindgenContext ctx, ClassElement2 element) {
103+
String methods(BindgenContext ctx, InterfaceElement2 element) {
92104
final methods = {
93105
if (ctx.implicitSupers)
94106
for (var s in element.allSupertypes)
@@ -103,7 +115,7 @@ String methods(BindgenContext ctx, ClassElement2 element) {
103115
.join('\n');
104116
}
105117

106-
String getters(BindgenContext ctx, ClassElement2 element) {
118+
String getters(BindgenContext ctx, InterfaceElement2 element) {
107119
final getters = {
108120
if (ctx.implicitSupers)
109121
for (var s in element.allSupertypes)
@@ -114,12 +126,16 @@ String getters(BindgenContext ctx, ClassElement2 element) {
114126

115127
return getters.values
116128
.where((m) => !(const ['hashCode', 'runtimeType'].contains(m.name3)))
117-
.where((element) => !element.isSynthetic)
129+
.where((element) =>
130+
!element.isSynthetic ||
131+
(element is EnumElement2 &&
132+
element.nonSynthetic2 is FieldElement2 &&
133+
!(element.nonSynthetic2 as FieldElement2).isEnumConstant))
118134
.map((e) => bridgeGetterDef(ctx, getter: e))
119135
.join('\n');
120136
}
121137

122-
String setters(BindgenContext ctx, ClassElement2 element) {
138+
String setters(BindgenContext ctx, InterfaceElement2 element) {
123139
final setters = {
124140
if (ctx.implicitSupers)
125141
for (var s in element.allSupertypes)
@@ -134,7 +150,7 @@ String setters(BindgenContext ctx, ClassElement2 element) {
134150
.join('\n');
135151
}
136152

137-
String fields(BindgenContext ctx, ClassElement2 element) {
153+
String fields(BindgenContext ctx, InterfaceElement2 element) {
138154
final allFields = {
139155
if (ctx.implicitSupers)
140156
for (var s in element.allSupertypes)
@@ -145,7 +161,8 @@ String fields(BindgenContext ctx, ClassElement2 element) {
145161
for (final f in element.fields2) f.name3: f
146162
};
147163

148-
final fields = allFields.values.where((element) => !element.isSynthetic);
164+
final fields = allFields.values
165+
.where((element) => !element.isSynthetic && !element.isEnumConstant);
149166

150167
return fields
151168
.map(

0 commit comments

Comments
 (0)