Skip to content

Commit a9f2121

Browse files
committed
Basic math interpretation & tests
1 parent 96cdc8b commit a9f2121

File tree

4 files changed

+116
-31
lines changed

4 files changed

+116
-31
lines changed

interpreter.py

Lines changed: 42 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,93 +1,104 @@
1-
# from antlr4 import ParserRuleContext
21
from generated.MyParser import MyParser
32
from generated.MyParserVisitor import MyParserVisitor
3+
from utils.values import Int, Float, String
44

55

66
class Interpreter(MyParserVisitor):
77
def visitProgram(self, ctx: MyParser.ProgramContext):
8-
print("Program")
9-
return self.visitChildren(ctx)
8+
return self.visitChildren(ctx) # todo
109

1110
def visitScopeStatement(self, ctx: MyParser.ScopeStatementContext):
12-
return self.visitChildren(ctx)
11+
return self.visitChildren(ctx) # todo
1312

1413
def visitSimpleStatement(self, ctx: MyParser.SimpleStatementContext):
15-
return self.visitChildren(ctx)
14+
return self.visitChildren(ctx) # todo
1615

1716
def visitIfThenElse(self, ctx: MyParser.IfThenElseContext):
18-
return self.visitChildren(ctx)
17+
return self.visitChildren(ctx) # todo
1918

2019
def visitIf(self, ctx: MyParser.IfContext):
21-
return self.visitChildren(ctx)
20+
return self.visitChildren(ctx) # todo
2221

2322
def visitThen(self, ctx: MyParser.ThenContext):
24-
return self.visitChildren(ctx)
23+
return self.visitChildren(ctx) # todo
2524

2625
def visitElse(self, ctx: MyParser.ElseContext):
27-
return self.visitChildren(ctx)
26+
return self.visitChildren(ctx) # todo
2827

2928
def visitForLoop(self, ctx: MyParser.ForLoopContext):
30-
return self.visitChildren(ctx)
29+
return self.visitChildren(ctx) # todo
3130

3231
def visitRange(self, ctx: MyParser.RangeContext):
33-
return self.visitChildren(ctx)
32+
return self.visitChildren(ctx) # todo
3433

3534
def visitWhileLoop(self, ctx: MyParser.WhileLoopContext):
36-
return self.visitChildren(ctx)
35+
return self.visitChildren(ctx) # todo
3736

3837
def visitComparison(self, ctx: MyParser.ComparisonContext):
39-
return self.visitChildren(ctx)
38+
return self.visitChildren(ctx) # todo
4039

4140
def visitSimpleAssignment(self, ctx: MyParser.SimpleAssignmentContext):
42-
return self.visitChildren(ctx)
41+
return self.visitChildren(ctx) # todo
4342

4443
def visitCompoundAssignment(self, ctx: MyParser.CompoundAssignmentContext):
45-
return self.visitChildren(ctx)
44+
return self.visitChildren(ctx) # todo
4645

4746
def visitPrint(self, ctx: MyParser.PrintContext):
48-
return self.visitChildren(ctx)
47+
for i in range(1, len(ctx.children) - 1, 2):
48+
print(self.visit(ctx.children[i]).value)
4949

5050
def visitReturn(self, ctx: MyParser.ReturnContext):
51-
return self.visitChildren(ctx)
51+
return self.visitChildren(ctx) # todo
5252

5353
def visitBinaryExpression(self, ctx: MyParser.BinaryExpressionContext):
54-
return self.visitChildren(ctx)
54+
a = self.visit(ctx.getChild(0))
55+
b = self.visit(ctx.getChild(2))
56+
match ctx.op.type:
57+
case MyParser.PLUS:
58+
return a + b
59+
case MyParser.MINUS:
60+
return a - b
61+
case MyParser.MULTIPLY:
62+
return a * b
63+
case MyParser.DIVIDE:
64+
return a / b
65+
# todo: MAT_* operations
5566

5667
def visitParenthesesExpression(self, ctx: MyParser.ParenthesesExpressionContext):
57-
return self.visitChildren(ctx)
68+
return self.visit(ctx.getChild(1))
5869

5970
def visitTransposeExpression(self, ctx: MyParser.TransposeExpressionContext):
60-
return self.visitChildren(ctx)
71+
return self.visitChildren(ctx) # todo
6172

6273
def visitMinusExpression(self, ctx: MyParser.MinusExpressionContext):
63-
return self.visitChildren(ctx)
74+
return self.visitChildren(ctx) # todo
6475

6576
def visitSingleExpression(self, ctx: MyParser.SingleExpressionContext):
66-
return self.visitChildren(ctx)
77+
return self.visit(ctx.getChild(0))
6778

6879
def visitSpecialMatrixFunction(self, ctx: MyParser.SpecialMatrixFunctionContext):
69-
return self.visitChildren(ctx)
80+
return self.visitChildren(ctx) # todo
7081

7182
def visitBreak(self, ctx: MyParser.BreakContext):
72-
return self.visitChildren(ctx)
83+
return self.visitChildren(ctx) # todo
7384

7485
def visitContinue(self, ctx: MyParser.ContinueContext):
75-
return self.visitChildren(ctx)
86+
return self.visitChildren(ctx) # todo
7687

7788
def visitVector(self, ctx: MyParser.VectorContext):
78-
return self.visitChildren(ctx)
89+
return self.visitChildren(ctx) # todo
7990

8091
def visitElementReference(self, ctx: MyParser.ElementReferenceContext):
81-
return self.visitChildren(ctx)
92+
return self.visitChildren(ctx) # todo
8293

8394
def visitId(self, ctx: MyParser.IdContext):
84-
return self.visitChildren(ctx)
95+
return self.visitChildren(ctx) # todo
8596

8697
def visitInt(self, ctx: MyParser.IntContext):
87-
return self.visitChildren(ctx)
98+
return Int(ctx.getText())
8899

89100
def visitFloat(self, ctx: MyParser.FloatContext):
90-
return self.visitChildren(ctx)
101+
return Float(ctx.getText())
91102

92103
def visitString(self, ctx: MyParser.StringContext):
93-
return self.visitChildren(ctx)
104+
return String(ctx.getText())

test_main.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,3 +63,15 @@ def test_sem_errors(name: str, line_numbers: list[int], additional: str):
6363
assert result.stdout.lower().count("line") == len(line_numbers)
6464
if additional:
6565
assert result.stdout.lower().count(additional) == len(line_numbers)
66+
67+
68+
@pytest.mark.parametrize(
69+
"name,output",
70+
[
71+
("simple_math", [23, 35, 1, 1.0, 1]),
72+
]
73+
)
74+
def test_interpreter(name: str, output: str):
75+
result = runner.invoke(app, ["run", f"tests/interpreter/{name}.txt"])
76+
assert result.exit_code == 0
77+
assert result.stdout.strip() == "\n".join(map(str, output))

tests/interpreter/simple_math.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
print 3 + 4 * 5, (3 + 4) * 5;
2+
print 2 / 2, 1.0 * 1.0, 2 - 1;

utils/values.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
class Value:
2+
def __init__(self, value):
3+
self.value = value
4+
5+
6+
class Int(Value):
7+
def __init__(self, value):
8+
super().__init__(int(value))
9+
10+
def __add__(self, other):
11+
if isinstance(other, Int):
12+
return Int(self.value + other.value)
13+
raise TypeError()
14+
15+
def __sub__(self, other):
16+
if isinstance(other, Int):
17+
return Int(self.value - other.value)
18+
raise TypeError()
19+
20+
def __mul__(self, other):
21+
if isinstance(other, Int):
22+
return Int(self.value * other.value)
23+
raise TypeError()
24+
25+
def __truediv__(self, other):
26+
if isinstance(other, Int):
27+
if self.value % other.value == 0:
28+
return Int(self.value // other.value)
29+
return Float(self.value / other.value)
30+
raise TypeError()
31+
32+
33+
class Float(Value):
34+
def __init__(self, value):
35+
super().__init__(float(value))
36+
37+
def __add__(self, other):
38+
if isinstance(other, Float):
39+
return Float(self.value + other.value)
40+
raise TypeError()
41+
42+
def __sub__(self, other):
43+
if isinstance(other, Float):
44+
return Float(self.value - other.value)
45+
raise TypeError()
46+
47+
def __mul__(self, other):
48+
if isinstance(other, Float):
49+
return Float(self.value * other.value)
50+
raise TypeError()
51+
52+
def __truediv__(self, other):
53+
if isinstance(other, Float):
54+
return Float(self.value / other.value)
55+
raise TypeError()
56+
57+
58+
class String(Value):
59+
def __init__(self, value):
60+
super().__init__(value)

0 commit comments

Comments
 (0)