Skip to content

Commit

Permalink
Merge pull request #118 from wrbl606/add_++_--_prefix_support
Browse files Browse the repository at this point in the history
Add `++i` and `--i` support
  • Loading branch information
ethanblake4 authored Oct 19, 2023
2 parents 1169c6b + 22386d8 commit 3558bac
Show file tree
Hide file tree
Showing 4 changed files with 207 additions and 21 deletions.
22 changes: 12 additions & 10 deletions lib/src/eval/compiler/expression/postfix.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,24 @@ import 'package:dart_eval/src/eval/runtime/runtime.dart';

Variable compilePostfixExpression(PostfixExpression e, CompilerContext ctx) {
final V = compileExpressionAsReference(e.operand, ctx);
var L = V.getValue(ctx);
final L = V.getValue(ctx);
var out = L;

if (L.name != null) {
out = Variable.alloc(ctx, L.type);
ctx.pushOp(PushNull.make(), PushNull.LEN);
ctx.pushOp(CopyValue.make(out.scopeFrameOffset, L.scopeFrameOffset),
CopyValue.LEN);
}
out = Variable.alloc(ctx, L.type);
ctx.pushOp(PushNull.make(), PushNull.LEN);
ctx.pushOp(
CopyValue.make(out.scopeFrameOffset, L.scopeFrameOffset), CopyValue.LEN);

final opMap = {TokenType.PLUS_PLUS: '+', TokenType.MINUS_MINUS: '-'};
const opMap = {TokenType.PLUS_PLUS: '+', TokenType.MINUS_MINUS: '-'};

V.setValue(
ctx,
L.invoke(
ctx,
L.invoke(ctx, opMap[e.operator.type]!,
[BuiltinValue(intval: 1).push(ctx)]).result);
opMap[e.operator.type]!,
[BuiltinValue(intval: 1).push(ctx)],
).result,
);

return out;
}
64 changes: 53 additions & 11 deletions lib/src/eval/compiler/expression/prefix.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,33 @@ import 'package:analyzer/dart/ast/token.dart';
import 'package:dart_eval/dart_eval_bridge.dart';
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/reference.dart';
import 'package:dart_eval/src/eval/compiler/type.dart';
import 'package:dart_eval/src/eval/compiler/variable.dart';
import 'package:dart_eval/src/eval/runtime/runtime.dart';

import '../errors.dart';
import 'expression.dart';

const _opMap = {
TokenType.MINUS: '-',
TokenType.BANG: '!',
TokenType.PLUS_PLUS: '+',
TokenType.MINUS_MINUS: '-',
};

/// Compile a [PrefixExpression] to EVC bytecode
Variable compilePrefixExpression(CompilerContext ctx, PrefixExpression e) {
var V = compileExpression(e.operand, ctx);
final method = _opMap[e.operator.type] ??
(throw CompileError('Unknown unary operator ${e.operator.type}'));

final opMap = {
TokenType.MINUS: '-',
TokenType.BANG: '!',
};
if ([TokenType.PLUS_PLUS, TokenType.MINUS_MINUS].contains(e.operator.type)) {
final V = compileExpressionAsReference(e.operand, ctx);
final L = V.getValue(ctx);
return _handleDoubleOperands(e, ctx, V, L);
}

var method = opMap[e.operator.type] ??
(throw CompileError('Unknown unary operator ${e.operator.type}'));
final V = compileExpression(e.operand, ctx);

if (method == '-' &&
V.type != CoreTypes.int.ref(ctx) &&
Expand All @@ -34,8 +44,40 @@ Variable compilePrefixExpression(CompilerContext ctx, PrefixExpression e) {
if (method == "!") {
return V.invoke(ctx, method, []).result;
}
final zero = V.type == CoreTypes.int.ref(ctx)
? BuiltinValue(intval: 0)
: BuiltinValue(doubleval: 0.0);
return zero.push(ctx).invoke(ctx, method, [V]).result;

return _zeroForType(V.type, ctx).push(ctx).invoke(ctx, method, [V]).result;
}

BuiltinValue _zeroForType(TypeRef type, CompilerContext ctx) =>
type == CoreTypes.int.ref(ctx)
? BuiltinValue(intval: 0)
: BuiltinValue(doubleval: 0.0);

BuiltinValue _oneForType(TypeRef type, CompilerContext ctx) =>
type == CoreTypes.int.ref(ctx)
? BuiltinValue(intval: 1)
: BuiltinValue(doubleval: 1.0);

Variable _handleDoubleOperands(
PrefixExpression e,
CompilerContext ctx,
Reference V,
Variable L,
) {
var l = L;

l = Variable.alloc(ctx, L.type);
ctx.pushOp(PushNull.make(), PushNull.LEN);
ctx.pushOp(
CopyValue.make(l.scopeFrameOffset, L.scopeFrameOffset),
CopyValue.LEN,
);

final result = l.invoke(
ctx,
_opMap[e.operator.type]!,
[_oneForType(l.type, ctx).push(ctx)],
).result;

return V.setValue(ctx, result);
}
71 changes: 71 additions & 0 deletions test/postfix_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import 'package:dart_eval/dart_eval.dart';
import 'package:test/expect.dart';
import 'package:test/scaffolding.dart';

void main() {
group('Postfix', () {
late Compiler compiler;

setUp(() {
compiler = Compiler();
});

test('i++', () {
final runtime = compiler.compileWriteAndLoad({
'eval_test': {
'main.dart': '''
void main() {
double d = 0.0;
double di = d++;
print(di);
print(d);
int i = 0;
int ii = i++;
print(ii);
print(i);
List<int> list = [0];
print(list[0]++);
print(list[0]);
}
'''
}
});

expect(
() {
runtime.executeLib('package:eval_test/main.dart', 'main');
},
prints('0.0\n1.0\n0\n1\n0\n1\n'),
);
});

test('i--', () {
final runtime = compiler.compileWriteAndLoad({
'eval_test': {
'main.dart': '''
void main() {
double d = 1.0;
double di = d--;
print(di);
print(d);
int i = 1;
int ii = i--;
print(ii);
print(i);
List<int> list = [1];
print(list[0]--);
print(list[0]);
}
'''
}
});

expect(
() {
runtime.executeLib('package:eval_test/main.dart', 'main');
},
prints('1.0\n0.0\n1\n0\n1\n0\n'),
);
});
});
}
71 changes: 71 additions & 0 deletions test/prefix_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import 'package:dart_eval/dart_eval.dart';
import 'package:test/expect.dart';
import 'package:test/scaffolding.dart';

void main() {
group('Prefix', () {
late Compiler compiler;

setUp(() {
compiler = Compiler();
});

test('++i', () {
final runtime = compiler.compileWriteAndLoad({
'eval_test': {
'main.dart': '''
void main() {
double d = 0.0;
double di = ++d;
print(di);
print(d);
int i = 0;
int ii = ++i;
print(ii);
print(i);
List<int> list = [0];
print(++list[0]);
print(list[0]);
}
'''
}
});

expect(
() {
runtime.executeLib('package:eval_test/main.dart', 'main');
},
prints('1.0\n1.0\n1\n1\n1\n1\n'),
);
});

test('--i', () {
final runtime = compiler.compileWriteAndLoad({
'eval_test': {
'main.dart': '''
void main() {
double d = 1.0;
double di = --d;
print(di);
print(d);
int i = 1;
int ii = --i;
print(ii);
print(i);
List<int> list = [1];
print(--list[0]);
print(list[0]);
}
'''
}
});

expect(
() {
runtime.executeLib('package:eval_test/main.dart', 'main');
},
prints('0.0\n0.0\n0\n0\n0\n0\n'),
);
});
});
}

0 comments on commit 3558bac

Please sign in to comment.