Skip to content

Commit

Permalink
v0.7.7
Browse files Browse the repository at this point in the history
  • Loading branch information
ethanblake4 committed Feb 28, 2024
1 parent 96ecba4 commit a73de23
Show file tree
Hide file tree
Showing 18 changed files with 187 additions and 61 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
## 0.7.7
- Support for redirecting constructors
- Fixed issue where tree-shaking would not always detect uses of symbols made
visible by an export
- Fixed dart:io File constructor
- Better detection of main.dart files
- Fixed empty function bodies causing scope leakage
- Support for `Map.remove()`

## 0.7.6
- Support for 'break' inside loops
- Support for constructor block bodies
Expand Down
11 changes: 6 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -634,8 +634,8 @@ may vary when bridging.
| ------- | ------------- | ----- |
| Imports || [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/lib_composition_test.dart#L14), [[2]](https://github.com/ethanblake4/dart_eval/blob/master/test/lib_composition_test.dart#L144), [[3]](https://github.com/ethanblake4/dart_eval/blob/master/test/lib_composition_test.dart#L176) |
| Exports || [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/lib_composition_test.dart#L45), [[2]](https://github.com/ethanblake4/dart_eval/blob/master/test/lib_composition_test.dart#L200) |
| `part` / `part of` || [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/statement_test.dart#L76) |
| `show` and `hide` || [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/statement_test.dart#L14) |
| `part` / `part of` || [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/lib_composition_test.dart#L76) |
| `show` and `hide` || [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/lib_composition_test.dart#L14) |
| Conditional imports || N/A |
| Deferred imports || N/A |
| Functions || [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/function_test.dart#L36) |
Expand All @@ -647,7 +647,7 @@ may vary when bridging.
| For loops || [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/loop_test.dart#L13), [[2]](https://github.com/ethanblake4/dart_eval/blob/master/test/loop_test.dart#L28) |
| While loops || [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/loop_test.dart#L69) |
| Do-while loops || [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/loop_test.dart#L86) |
| For-each loops || [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/statement_test.dart#L52) |
| For-each loops || [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/loop_test.dart#L54), [[2]](https://github.com/ethanblake4/dart_eval/blob/master/test/loop_test.dart#L71) |
| Async for-each || N/A |
| Switch statements || N/A |
| Labels, `break` & `continue` | Partial | [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/loop_test.dart#L126), [[2]](https://github.com/ethanblake4/dart_eval/blob/master/test/loop_test.dart#L146) |
Expand All @@ -656,7 +656,7 @@ may vary when bridging.
| Try-catch-finally || [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/exception_test.dart#L132), [[2]](https://github.com/ethanblake4/dart_eval/blob/master/test/exception_test.dart#147), [[3]](https://github.com/ethanblake4/dart_eval/blob/master/test/exception_test.dart#187), [[4]](https://github.com/ethanblake4/dart_eval/blob/master/test/exception_test.dart#209), [[5]](https://github.com/ethanblake4/dart_eval/blob/master/test/exception_test.dart#231) |
| Lists || [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/collection_test.dart) |
| Iterable || [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/collection_test.dart#L14), [[2]](https://github.com/ethanblake4/dart_eval/blob/master/test/collection_test.dart#L29) |
| Maps | Partial | [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/convert_test.dart#L60) |
| Maps | Partial | [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/convert_test.dart#L60), [[2]](https://github.com/ethanblake4/dart_eval/blob/master/test/collection_test.dart#L145), [[3]](https://github.com/ethanblake4/dart_eval/blob/master/test/collection_test.dart#L160), [[4]](https://github.com/ethanblake4/dart_eval/blob/master/test/collection_test.dart#L175) |
| Sets || N/A |
| Collection `for` || [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/collection_test.dart#L14), [[2]](https://github.com/ethanblake4/dart_eval/blob/master/test/collection_test.dart#L76) |
| Collection `if` || [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/collection_test.dart#L14), [[2]](https://github.com/ethanblake4/dart_eval/blob/master/test/collection_test.dart#L52) |
Expand All @@ -665,9 +665,10 @@ may vary when bridging.
| Class static methods || [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/class_test.dart#L147), [[2]](https://github.com/ethanblake4/dart_eval/blob/master/test/class_test.dart#L167) |
| Getters and setters || [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/class_test.dart#L253) |
| Factory constructors || [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/class_test.dart#L375) |
| Redirecting constructors || [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/class_test.dart#L474) |
| `new` keyword || [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/class_test.dart#L195) |
| Class inheritance || [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/functional1_test.dart) |
| Abstract and `implements` | Partial | |
| Abstract and `implements` | Partial | [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/packages/hlc_test.dart#L8) |
| `this` keyword || [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/class_test.dart#L89), [[2]](https://github.com/ethanblake4/dart_eval/blob/master/test/class_test.dart#L116) |
| `super` keyword || [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/class_test.dart#L319) |
| Super constructor params || [[1]](https://github.com/ethanblake4/dart_eval/blob/master/test/class_test.dart#L277) |
Expand Down
32 changes: 17 additions & 15 deletions lib/src/eval/compiler/compiler.dart
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ class Compiler implements BridgeDeclarationRegistry, EvalPluginRegistry {
/// full URIs (e.g. `package:foo/main.dart`) or just filenames (e.g.
/// `main.dart`). Adding a file to this list prevents it from being dead-code
/// eliminated.
final entrypoints = ['main.dart'];
final entrypoints = ['/main.dart'];

// Add a plugin, which will only be run once.
@override
Expand Down Expand Up @@ -913,7 +913,7 @@ Map<Library, Map<String, DeclarationOrPrefix>> _resolveImportsAndExports(
final crawler = CachedFastCrawler(exportGraph.edges);

final result = <Library, Map<String, DeclarationOrPrefix>>{};
final usedDeclarationsForLibrary = <Library, Set<String>>{};
final usedDeclarationsForLibrary = <int, Set<String>>{};

final worklist = <Library>[];
final importMap = <Library, List<_Import>>{};
Expand Down Expand Up @@ -1015,8 +1015,8 @@ Map<Library, Map<String, DeclarationOrPrefix>> _resolveImportsAndExports(
}
}
if (isEntrypoint && ids!.contains(declaration.first)) {
usedDeclarationsForLibrary[lib] ??= {'main'};
usedDeclarationsForLibrary[lib]!.add(declaration.first);
usedDeclarationsForLibrary[libId] ??= {'main'};
usedDeclarationsForLibrary[libId]!.add(declaration.first);
if (!worklist.contains(lib)) {
worklist.add(lib);
}
Expand Down Expand Up @@ -1047,8 +1047,8 @@ Map<Library, Map<String, DeclarationOrPrefix>> _resolveImportsAndExports(
/// Run tree-shaking
while (worklist.isNotEmpty) {
final library = worklist.removeLast();
Map<Library, Set<String>> applyUsedDeclarations = {};
for (final dec in usedDeclarationsForLibrary[library]!) {
Map<int, Set<String>> applyUsedDeclarations = {};
for (final dec in (usedDeclarationsForLibrary[libraryIds[library]] ?? {})) {
final ids = usedIdentifiers[library]?[dec];
if (ids == null) continue;
final importsWithImplicitSelf = [
Expand All @@ -1062,22 +1062,24 @@ Map<Library, Map<String, DeclarationOrPrefix>> _resolveImportsAndExports(
}
processedImports.add(iid);
final lib = uriMap[import.uri]!;
final decs = importedDeclarationsMap[library]?[lib];
final decs = result[library]?.entries.toList();
if (decs == null) continue;
for (final declaration in decs) {
if (ids.contains(declaration.first)) {
applyUsedDeclarations[lib] ??= {'main'};
applyUsedDeclarations[lib]!.add(declaration.first);
if (ids.contains(declaration.key)) {
final applyLib =
declaration.value.declaration?.sourceLib ?? libraryIds[lib]!;
applyUsedDeclarations[applyLib] ??= {'main'};
applyUsedDeclarations[applyLib]!.add(declaration.key);
if (!worklist.contains(lib)) {
worklist.add(lib);
}
}
}
}
}
for (final lib in applyUsedDeclarations.keys) {
usedDeclarationsForLibrary[lib] ??= {};
usedDeclarationsForLibrary[lib]!.addAll(applyUsedDeclarations[lib]!);
for (final libId in applyUsedDeclarations.keys) {
usedDeclarationsForLibrary[libId] ??= {};
usedDeclarationsForLibrary[libId]!.addAll(applyUsedDeclarations[libId]!);
}
}

Expand All @@ -1088,8 +1090,8 @@ Map<Library, Map<String, DeclarationOrPrefix>> _resolveImportsAndExports(
l.declarations = l.declarations
.where((declaration) =>
declaration.isBridge ||
DeclarationOrBridge.nameOf(declaration).any(
(name) => {...?usedDeclarationsForLibrary[l]}.contains(name)))
DeclarationOrBridge.nameOf(declaration).any((name) =>
{...?usedDeclarationsForLibrary[libraryIds[l]]}.contains(name)))
.toList();
}

Expand Down
2 changes: 0 additions & 2 deletions lib/src/eval/compiler/context.dart
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,6 @@ class CompilerContext with ScopeContext {
List<ContextSaveState> typeUninferenceSaveStates = [];
List<CompilerLabel> labels = [];
Map<CompilerLabel, Set<int>> labelReferences = {};
List<bool> inTypeInferenceContext = [];
final List<Variable> caughtExceptions = [];
PrescanContext? preScan;
int nearestAsyncFrame = -1;
Expand Down Expand Up @@ -307,7 +306,6 @@ class CompilerContext with ScopeContext {

void enterTypeInferenceContext() {
typeInferenceSaveStates.add(saveState());
inTypeInferenceContext.add(true);
}

void inferTypes() {
Expand Down
39 changes: 39 additions & 0 deletions lib/src/eval/compiler/declaration/constructor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ import 'package:dart_eval/src/eval/compiler/builtins.dart';
import 'package:dart_eval/src/eval/compiler/context.dart';
import 'package:dart_eval/src/eval/compiler/errors.dart';
import 'package:dart_eval/src/eval/compiler/expression/expression.dart';
import 'package:dart_eval/src/eval/compiler/expression/method_invocation.dart';
import 'package:dart_eval/src/eval/compiler/helpers/argument_list.dart';
import 'package:dart_eval/src/eval/compiler/helpers/fpl.dart';
import 'package:dart_eval/src/eval/compiler/helpers/return.dart';
import 'package:dart_eval/src/eval/compiler/offset_tracker.dart';
import 'package:dart_eval/src/eval/compiler/reference.dart';
import 'package:dart_eval/src/eval/compiler/scope.dart';
import 'package:dart_eval/src/eval/compiler/source.dart';
Expand Down Expand Up @@ -39,10 +41,18 @@ void compileConstructorDeclaration(
ctx.scopeFrameOffset = d.parameters.parameters.length + (isEnum ? 2 : 0);

SuperConstructorInvocation? $superInitializer;
RedirectingConstructorInvocation? $redirectingInitializer;
final otherInitializers = <ConstructorInitializer>[];
for (final initializer in d.initializers) {
if (initializer is SuperConstructorInvocation) {
$superInitializer = initializer;
} else if (initializer is RedirectingConstructorInvocation) {
if (d.initializers.length > 1) {
throw CompileError(
'Redirecting constructor invocation must be the only initializer',
d);
}
$redirectingInitializer = initializer;
} else if ($superInitializer != null) {
throw CompileError(
'Super constructor invocation must be last in the initializer list',
Expand Down Expand Up @@ -70,6 +80,11 @@ void compileConstructorDeclaration(
final p = param.parameter;
final V = param.V;
Variable vrep;
if ($redirectingInitializer != null && !(p is SimpleFormalParameter)) {
throw CompileError(
'Redirecting constructor invocation cannot have super or this parameters',
d);
}
if (p is FieldFormalParameter) {
TypeRef? _type;
if (p.type != null) {
Expand Down Expand Up @@ -112,6 +127,7 @@ void compileConstructorDeclaration(

final clsType = TypeRef.lookupDeclaration(ctx, ctx.library, parent);

// Handle factory constructor
if (d.factoryKeyword != null) {
final b = d.body;

Expand Down Expand Up @@ -144,6 +160,29 @@ void compileConstructorDeclaration(
return;
}

// Handle redirecting constructor
if ($redirectingInitializer != null) {
final name = $redirectingInitializer.constructorName?.name ?? '';
final _dec = resolveStaticMethod(ctx, clsType, name);
final dec = _dec.declaration!;
final fpl = (dec as ConstructorDeclaration).parameters.parameters;

compileArgumentList(
ctx, $redirectingInitializer.argumentList, clsType.file, fpl, dec,
source: $redirectingInitializer.argumentList);

final offset =
DeferredOrOffset.lookupStatic(ctx, clsType.file, clsType.name, name);
final loc = ctx.pushOp(Call.make(offset.offset ?? -1), Call.length);
if (offset.offset == null) {
ctx.offsetTracker.setOffset(loc, offset);
}
ctx.pushOp(PushReturnValue.make(), PushReturnValue.LEN);
final V = Variable.alloc(ctx, clsType);
doReturn(ctx, AlwaysReturnType(clsType, false), V);
return;
}

final $extends = parent is EnumDeclaration
? null
: (parent as ClassDeclaration).extendsClause;
Expand Down
2 changes: 1 addition & 1 deletion lib/src/eval/compiler/declaration/function.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import 'package:dart_eval/src/eval/compiler/variable.dart';
import 'package:dart_eval/src/eval/runtime/runtime.dart';

void compileFunctionDeclaration(FunctionDeclaration d, CompilerContext ctx) {
ctx.runPrescan(d);
//ctx.runPrescan(d);
final pos = beginMethod(ctx, d, d.offset, '${d.name.lexeme}()');
ctx.topLevelDeclarationPositions[ctx.library]![d.name.lexeme] = pos;

Expand Down
3 changes: 2 additions & 1 deletion lib/src/eval/compiler/declaration/method.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import 'package:dart_eval/src/eval/runtime/runtime.dart';

int compileMethodDeclaration(MethodDeclaration d, CompilerContext ctx,
NamedCompilationUnitMember parent) {
ctx.runPrescan(d);
///ctx.runPrescan(d);
final b = d.body;
final parentName = parent.name.lexeme;
final methodName = d.name.lexeme;
Expand Down Expand Up @@ -70,6 +70,7 @@ int compileMethodDeclaration(MethodDeclaration d, CompilerContext ctx,
isAsync: b.isAsynchronous);
ctx.endAllocScope();
} else if (b is EmptyFunctionBody) {
ctx.endAllocScope();
return -1;
} else {
throw CompileError('Unknown function body type ${b.runtimeType}');
Expand Down
2 changes: 1 addition & 1 deletion lib/src/eval/compiler/expression/conditional.dart
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ Variable compileConditionalExpression(
types.add(v.type);
vRef.setValue(ctx, v);
return StatementInfo(-1);
}, resolveStateToThen: true);
}, resolveStateToThen: true, source: e);

final val = vRef.getValue(ctx).updated(ctx);
return val.copyWith(
Expand Down
2 changes: 1 addition & 1 deletion lib/src/eval/compiler/expression/identifier.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import 'package:dart_eval/src/eval/compiler/variable.dart';
import '../util.dart';

Variable compileIdentifier(Identifier id, CompilerContext ctx) {
return compileIdentifierAsReference(id, ctx).getValue(ctx);
return compileIdentifierAsReference(id, ctx).getValue(ctx, id);
}

Reference compileIdentifierAsReference(Identifier id, CompilerContext ctx) {
Expand Down
2 changes: 1 addition & 1 deletion lib/src/eval/compiler/expression/property_access.dart
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ Variable compilePropertyAccess(PropertyAccess pa, CompilerContext ctx,
ctx.pushOp(CopyValue.make(out.scopeFrameOffset, V.scopeFrameOffset),
CopyValue.LEN);
return StatementInfo(-1);
});
}, source: pa);
return out;
}

Expand Down
9 changes: 8 additions & 1 deletion lib/src/eval/compiler/macros/branch.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import 'package:analyzer/dart/ast/ast.dart';
import 'package:dart_eval/dart_eval_bridge.dart';
import 'package:dart_eval/src/eval/compiler/context.dart';
import 'package:dart_eval/src/eval/compiler/errors.dart';
import 'package:dart_eval/src/eval/compiler/macros/macro.dart';
import 'package:dart_eval/src/eval/compiler/model/label.dart';
import 'package:dart_eval/src/eval/compiler/statement/statement.dart';
Expand All @@ -10,10 +13,14 @@ StatementInfo macroBranch(
{required MacroVariableClosure condition,
required MacroStatementClosure thenBranch,
MacroStatementClosure? elseBranch,
bool resolveStateToThen = false}) {
bool resolveStateToThen = false,
AstNode? source}) {
ctx.beginAllocScope();
ctx.enterTypeInferenceContext();
final conditionResult = condition(ctx).unboxIfNeeded(ctx);
if (!conditionResult.type.isAssignableTo(ctx, CoreTypes.bool.ref(ctx))) {
throw CompileError("Conditions must have a static type of 'bool'", source);
}

final rewriteCond = JumpIfFalse.make(conditionResult.scopeFrameOffset, -1);
final rewritePos = ctx.pushOp(rewriteCond, JumpIfFalse.LEN);
Expand Down
17 changes: 9 additions & 8 deletions lib/src/eval/compiler/reference.dart
Original file line number Diff line number Diff line change
Expand Up @@ -105,13 +105,14 @@ class IdentifierReference implements Reference {
'Cannot assign value of type ${value.type} to field "$name" of type $type',
source);
}
final _value =
type.boxed ? value.boxIfNeeded(ctx) : value.unboxIfNeeded(ctx);
final _value = type.boxed
? value.boxIfNeeded(ctx, source)
: value.unboxIfNeeded(ctx);
ctx.pushOp(
SetGlobal.make(gIndex, _value.scopeFrameOffset), SetGlobal.LEN);
return _value;
}
object = object!.boxIfNeeded(ctx);
object = object!.boxIfNeeded(ctx, source);
final fieldType = TypeRef.lookupFieldType(ctx, object!.type, name,
forSet: true, source: source) ??
CoreTypes.dynamic.ref(ctx);
Expand All @@ -120,7 +121,7 @@ class IdentifierReference implements Reference {
'Cannot assign value of type ${value.type} to field "$name" of type $fieldType',
source);
}
final _v = value.boxIfNeeded(ctx);
final _v = value.boxIfNeeded(ctx, source);
final op = SetObjectProperty.make(
object!.scopeFrameOffset, name, _v.scopeFrameOffset);
ctx.pushOp(op, SetObjectProperty.len(op));
Expand Down Expand Up @@ -160,7 +161,7 @@ class IdentifierReference implements Reference {
}
final $this = ctx.lookupLocal('#this')!;
final op = SetObjectProperty.make($this.scopeFrameOffset, name,
value.boxIfNeeded(ctx).scopeFrameOffset);
value.boxIfNeeded(ctx, source).scopeFrameOffset);
ctx.pushOp(op, SetObjectProperty.len(op));
return value;
}
Expand Down Expand Up @@ -240,7 +241,7 @@ class IdentifierReference implements Reference {
ctx.pushOp(PushReturnValue.make(), PushReturnValue.LEN);
return Variable.alloc(ctx, type);
}
object = object!.boxIfNeeded(ctx);
object = object!.boxIfNeeded(ctx, source);
return object!.getProperty(ctx, name);
}

Expand Down Expand Up @@ -500,7 +501,7 @@ class IndexedReference implements Reference {
final map = _variable.unboxIfNeeded(ctx);
_index = (_variable.type.specifiedTypeArgs.isEmpty ||
_variable.type.specifiedTypeArgs[0].boxed)
? _index.boxIfNeeded(ctx)
? _index.boxIfNeeded(ctx, source)
: _index.unboxIfNeeded(ctx);
ctx.pushOp(IndexMap.make(map.scopeFrameOffset, _index.scopeFrameOffset),
IndexMap.LEN);
Expand Down Expand Up @@ -533,7 +534,7 @@ class IndexedReference implements Reference {
final elementType = list.type.specifiedTypeArgs[0];
var _value = value;
if (elementType.boxed) {
_value = _value.boxIfNeeded(ctx);
_value = _value.boxIfNeeded(ctx, source);
} else {
_value = _value.unboxIfNeeded(ctx);
}
Expand Down
1 change: 1 addition & 0 deletions lib/src/eval/compiler/statement/if.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,6 @@ StatementInfo compileIfStatement(
? null
: (_ctx, expectedReturnType) =>
compileStatement(elseStatement, expectedReturnType, _ctx),
source: s,
);
}
Loading

0 comments on commit a73de23

Please sign in to comment.