mirror of
https://github.com/aNNiMON/HotaruFX.git
synced 2024-09-19 14:14:21 +03:00
Add evaluation of assignment, value and variable expressions
This commit is contained in:
parent
037b7aa67e
commit
69cbd5a04f
@ -0,0 +1,14 @@
|
|||||||
|
package com.annimon.hotarufx.exceptions;
|
||||||
|
|
||||||
|
import com.annimon.hotarufx.lexer.SourcePosition;
|
||||||
|
|
||||||
|
public class HotaruRuntimeException extends RuntimeException {
|
||||||
|
|
||||||
|
public HotaruRuntimeException(String s) {
|
||||||
|
super(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
public HotaruRuntimeException(String string, SourcePosition start, SourcePosition end) {
|
||||||
|
super(string + " at " + start + " .. " + end);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
package com.annimon.hotarufx.exceptions;
|
||||||
|
|
||||||
|
import com.annimon.hotarufx.lexer.SourcePosition;
|
||||||
|
|
||||||
|
public class VariableNotFoundException extends HotaruRuntimeException {
|
||||||
|
|
||||||
|
public VariableNotFoundException(String variable, SourcePosition start, SourcePosition end) {
|
||||||
|
super("Variable " + variable + " does not exists", start, end);
|
||||||
|
}
|
||||||
|
}
|
@ -1,9 +1,11 @@
|
|||||||
package com.annimon.hotarufx.parser.visitors;
|
package com.annimon.hotarufx.parser.visitors;
|
||||||
|
|
||||||
|
import com.annimon.hotarufx.exceptions.VariableNotFoundException;
|
||||||
import com.annimon.hotarufx.lib.Context;
|
import com.annimon.hotarufx.lib.Context;
|
||||||
import com.annimon.hotarufx.lib.NumberValue;
|
import com.annimon.hotarufx.lib.NumberValue;
|
||||||
import com.annimon.hotarufx.lib.Value;
|
import com.annimon.hotarufx.lib.Value;
|
||||||
import com.annimon.hotarufx.parser.ast.*;
|
import com.annimon.hotarufx.parser.ast.*;
|
||||||
|
import lombok.val;
|
||||||
|
|
||||||
public class InterpreterVisitor implements ResultVisitor<Value, Context> {
|
public class InterpreterVisitor implements ResultVisitor<Value, Context> {
|
||||||
|
|
||||||
@ -14,12 +16,17 @@ public class InterpreterVisitor implements ResultVisitor<Value, Context> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Value visit(AssignNode node, Context context) {
|
public Value visit(AssignNode node, Context context) {
|
||||||
return NumberValue.ZERO;
|
val value = node.value.accept(this, context);
|
||||||
|
return node.target.set(this, value, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Value visit(BlockNode node, Context context) {
|
public Value visit(BlockNode node, Context context) {
|
||||||
return NumberValue.ZERO;
|
Value last = NumberValue.ZERO;
|
||||||
|
for (Node statement : node.statements) {
|
||||||
|
last = statement.accept(this, context);
|
||||||
|
}
|
||||||
|
return last;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -39,11 +46,35 @@ public class InterpreterVisitor implements ResultVisitor<Value, Context> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Value visit(ValueNode node, Context context) {
|
public Value visit(ValueNode node, Context context) {
|
||||||
return NumberValue.ZERO;
|
return node.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Value visit(VariableNode node, Context context) {
|
public Value visit(VariableNode node, Context context) {
|
||||||
return NumberValue.ZERO;
|
return node.get(this, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Value get(AccessNode node, Context context) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Value set(AccessNode node, Value value, Context context) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Value get(VariableNode node, Context context) {
|
||||||
|
val result = context.variables().get(node.name);
|
||||||
|
if (result == null)
|
||||||
|
throw new VariableNotFoundException(node.name, node.start(), node.end());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Value set(VariableNode node, Value value, Context context) {
|
||||||
|
context.variables().put(node.name, value);
|
||||||
|
return value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,46 @@
|
|||||||
|
package com.annimon.hotarufx.parser.visitors;
|
||||||
|
|
||||||
|
import com.annimon.hotarufx.exceptions.VariableNotFoundException;
|
||||||
|
import com.annimon.hotarufx.lexer.HotaruLexer;
|
||||||
|
import com.annimon.hotarufx.lib.Context;
|
||||||
|
import com.annimon.hotarufx.lib.NumberValue;
|
||||||
|
import com.annimon.hotarufx.lib.Value;
|
||||||
|
import com.annimon.hotarufx.parser.HotaruParser;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
import static org.hamcrest.Matchers.allOf;
|
||||||
|
import static org.hamcrest.Matchers.hasEntry;
|
||||||
|
import static org.hamcrest.Matchers.is;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
|
|
||||||
|
class InterpreterVisitorTest {
|
||||||
|
|
||||||
|
static Value eval(String input) {
|
||||||
|
return eval(input, new Context());
|
||||||
|
}
|
||||||
|
|
||||||
|
static Value eval(String input, Context context) {
|
||||||
|
return HotaruParser.parse(HotaruLexer.tokenize(input))
|
||||||
|
.accept(new InterpreterVisitor(), context);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testAssignVariables() {
|
||||||
|
Context context = new Context();
|
||||||
|
|
||||||
|
String input = "A = 1\nB = 2\nC = B";
|
||||||
|
Value result = eval(input, context);
|
||||||
|
|
||||||
|
assertThat(result.toString(), is("2"));
|
||||||
|
assertThat(context.variables(), allOf(
|
||||||
|
hasEntry("A", NumberValue.of(1)),
|
||||||
|
hasEntry("B", NumberValue.of(2)),
|
||||||
|
hasEntry("C", NumberValue.of(2))
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testRuntimeErrors() {
|
||||||
|
assertThrows(VariableNotFoundException.class, () -> eval("A = B"));
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user