-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathInterpreter.cs
More file actions
91 lines (81 loc) · 3.28 KB
/
Copy pathInterpreter.cs
File metadata and controls
91 lines (81 loc) · 3.28 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
using System;
using System.Collections.Generic;
using System.Numerics;
namespace JCore
{
public class Interpreter
{
private readonly Dictionary<string, string> variables = new();
private readonly HashSet<string> constants = new();
public void Run(List<Node> nodes)
{
foreach (var node in nodes)
{
switch (node)
{
case SayNode say:
var result = Evaluate(say.Expression);
Console.WriteLine(result);
break;
case LetNode let:
if (constants.Contains(let.Name))
{
Console.WriteLine($"❌ Cannot overwrite constant '{let.Name}' with let.");
}
else
{
var value = Evaluate(let.Value);
variables[let.Name] = value.ToString();
}
break;
case ConstNode constant:
if (constants.Contains(constant.Name))
{
Console.WriteLine($"❌ Constant '{constant.Name}' already defined.");
}
else
{
var value = Evaluate(constant.Value);
variables[constant.Name] = value.ToString();
constants.Add(constant.Name);
}
break;
case UnknownNode unknown:
Console.WriteLine($"❌ Unknown command: {unknown.Command}");
break;
default:
Console.WriteLine("⚠️ Unhandled node type.");
break;
}
}
}
private object Evaluate(Node node)
{
return node switch
{
NumberNode n => n.Value,
StringNode s => s.Value,
VariableNode v => variables.TryGetValue(v.Name, out var val)
? val
: throw new Exception($"❌ Undefined variable '{v.Name}'"),
BinaryOpNode b => EvaluateOp(Evaluate(b.Left), b.Operator, Evaluate(b.Right)),
_ => throw new Exception("❌ Invalid expression")
};
}
private BigInteger EvaluateOp(object left, string op, object right)
{
if (!BigInteger.TryParse(left.ToString(), out var l))
throw new Exception($"❌ Cannot perform math on '{left}'");
if (!BigInteger.TryParse(right.ToString(), out var r))
throw new Exception($"❌ Cannot perform math on '{right}'");
return op switch
{
"PLUS" => l + r,
"MINUS" => l - r,
"STAR" => l * r,
"SLASH" => r != 0 ? l / r : throw new Exception("❌ Division by zero"),
_ => throw new Exception($"❌ Unknown operator '{op}'")
};
}
}
}