Skip to content

Commit 1f85922

Browse files
Add files via upload
0 parents  commit 1f85922

File tree

9 files changed

+1063
-0
lines changed

9 files changed

+1063
-0
lines changed

debug_test.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# debug_test.py
2+
from mas_lexer import lexer
3+
from mas_parser import parser
4+
from mas_interpreter import MASInterpreter
5+
6+
code = "print('hi')\n" # ← note \n
7+
8+
print("Tokens:")
9+
lexer.input(code)
10+
for tok in lexer:
11+
print(tok)
12+
13+
print("\nParsing...")
14+
ast = parser.parse(code, lexer=lexer)
15+
print("AST:", "Success" if ast else "Failed")
16+
17+
if ast:
18+
print("✅ Parsed successfully!")
19+
print("\n🚀 Interpreting...\n")
20+
interp = MASInterpreter()
21+
interp.visit(ast)
22+
print("\n✨ Done!")
23+
else:
24+
print("❌ Parse failed")

mas_ast.py

Lines changed: 254 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,254 @@
1+
# mas_ast.py
2+
3+
class ASTNode:
4+
pass
5+
6+
class Program(ASTNode):
7+
def __init__(self, statements):
8+
self.statements = statements # list of stmts
9+
10+
class Assign(ASTNode):
11+
def __init__(self, name, value):
12+
self.name = name # str
13+
self.value = value # expr
14+
15+
class BinOp(ASTNode):
16+
def __init__(self, left, op, right):
17+
self.left = left
18+
self.op = op # str: '+', '==', etc.
19+
self.right = right
20+
21+
class UnaryOp(ASTNode):
22+
def __init__(self, op, operand):
23+
self.op = op # e.g., '-'
24+
self.operand = operand
25+
26+
class Number(ASTNode):
27+
def __init__(self, value):
28+
self.value = value # int or float
29+
30+
class String(ASTNode):
31+
def __init__(self, value):
32+
self.value = value # str
33+
34+
class Boolean(ASTNode):
35+
def __init__(self, value):
36+
self.value = value # True/False
37+
38+
class Null(ASTNode):
39+
pass
40+
41+
class Var(ASTNode):
42+
def __init__(self, name):
43+
self.name = name
44+
45+
class List(ASTNode):
46+
def __init__(self, elements):
47+
self.elements = elements
48+
49+
class Dict(ASTNode):
50+
def __init__(self, pairs): # list of (key_expr, value_expr)
51+
self.pairs = pairs
52+
53+
class Call(ASTNode):
54+
def __init__(self, func, args):
55+
self.func = func # Var or expr
56+
self.args = args # list of expr
57+
58+
# Control flow
59+
class If(ASTNode):
60+
def __init__(self, condition, body, elifs, else_body):
61+
self.condition = condition # expr
62+
self.body = body # list of stmt
63+
self.elifs = elifs # list of (cond, body)
64+
self.else_body = else_body # list of stmt or None
65+
66+
class Loop(ASTNode): # while
67+
def __init__(self, condition, body):
68+
self.condition = condition
69+
self.body = body
70+
71+
class Each(ASTNode): # for-in
72+
def __init__(self, target, iterable, body):
73+
self.target = target # Var (e.g., 'x')
74+
self.iterable = iterable # expr (e.g., [1,2,3])
75+
self.body = body
76+
77+
class FuncDef(ASTNode):
78+
def __init__(self, name, params, body):
79+
self.name = name
80+
self.params = params # list of str
81+
self.body = body # list of stmt
82+
83+
class Return(ASTNode): # 'give'
84+
def __init__(self, value):
85+
self.value = value # expr or None
86+
87+
class Break(ASTNode): # 'stop'
88+
pass
89+
90+
class Continue(ASTNode): # 'next'
91+
pass
92+
93+
class ExprStmt(ASTNode): # standalone expression (e.g., function call)
94+
def __init__(self, expr):
95+
self.expr = expr
96+
97+
# mas_ast.py (append at the bottom)
98+
99+
def dump_ast(node, indent=0):
100+
"""Recursively print the AST in a readable format."""
101+
prefix = " " * indent
102+
if isinstance(node, Program):
103+
print(f"{prefix}Program")
104+
for stmt in node.statements:
105+
dump_ast(stmt, indent + 1)
106+
elif isinstance(node, Assign):
107+
print(f"{prefix}Assign: {node.name}")
108+
dump_ast(node.value, indent + 1)
109+
elif isinstance(node, Var):
110+
print(f"{prefix}Var: {node.name}")
111+
elif isinstance(node, Number):
112+
print(f"{prefix}Number: {node.value}")
113+
elif isinstance(node, String):
114+
print(f"{prefix}String: \"{node.value}\"")
115+
elif isinstance(node, Boolean):
116+
print(f"{prefix}Boolean: {node.value}")
117+
elif isinstance(node, Null):
118+
print(f"{prefix}Null")
119+
elif isinstance(node, BinOp):
120+
print(f"{prefix}BinOp: {node.op}")
121+
dump_ast(node.left, indent + 1)
122+
dump_ast(node.right, indent + 1)
123+
elif isinstance(node, UnaryOp):
124+
print(f"{prefix}UnaryOp: {node.op}")
125+
dump_ast(node.operand, indent + 1)
126+
elif isinstance(node, List):
127+
print(f"{prefix}List")
128+
for elem in node.elements:
129+
dump_ast(elem, indent + 1)
130+
elif isinstance(node, Dict):
131+
print(f"{prefix}Dict")
132+
for key, val in node.pairs:
133+
print(f"{' ' * (indent + 1)}Key:")
134+
dump_ast(key, indent + 2)
135+
print(f"{' ' * (indent + 1)}Value:")
136+
dump_ast(val, indent + 2)
137+
elif isinstance(node, Call):
138+
print(f"{prefix}Call: {node.func.name if isinstance(node.func, Var) else '...'}")
139+
for arg in node.args:
140+
dump_ast(arg, indent + 1)
141+
elif isinstance(node, Loop):
142+
print(f"{prefix}Loop")
143+
print(f"{' ' * (indent + 1)}Condition:")
144+
dump_ast(node.condition, indent + 2)
145+
print(f"{' ' * (indent + 1)}Body:")
146+
for stmt in node.body:
147+
dump_ast(stmt, indent + 2)
148+
elif isinstance(node, Each):
149+
print(f"{prefix}Each")
150+
print(f"{' ' * (indent + 1)}Target:")
151+
dump_ast(node.target, indent + 2)
152+
print(f"{' ' * (indent + 1)}Iterable:")
153+
dump_ast(node.iterable, indent + 2)
154+
print(f"{' ' * (indent + 1)}Body:")
155+
for stmt in node.body:
156+
dump_ast(stmt, indent + 2)
157+
elif isinstance(node, If):
158+
print(f"{prefix}If")
159+
print(f"{' ' * (indent + 1)}Condition:")
160+
dump_ast(node.condition, indent + 2)
161+
print(f"{' ' * (indent + 1)}Body:")
162+
for stmt in node.body:
163+
dump_ast(stmt, indent + 2)
164+
for cond, body in node.elifs:
165+
print(f"{' ' * (indent + 1)}Elif:")
166+
dump_ast(cond, indent + 2)
167+
for stmt in body:
168+
dump_ast(stmt, indent + 2)
169+
if node.else_body:
170+
print(f"{' ' * (indent + 1)}Else:")
171+
for stmt in node.else_body:
172+
dump_ast(stmt, indent + 2)
173+
elif isinstance(node, FuncDef):
174+
print(f"{prefix}FuncDef: {node.name}({', '.join(node.params)})")
175+
for stmt in node.body:
176+
dump_ast(stmt, indent + 1)
177+
elif isinstance(node, Return):
178+
print(f"{prefix}Return")
179+
dump_ast(node.value, indent + 1)
180+
elif isinstance(node, Break):
181+
print(f"{prefix}Break")
182+
elif isinstance(node, Continue):
183+
print(f"{prefix}Continue")
184+
elif isinstance(node, ExprStmt):
185+
print(f"{prefix}ExprStmt")
186+
dump_ast(node.expr, indent + 1)
187+
else:
188+
print(f"{prefix}Unknown node: {type(node)}")
189+
190+
# mas_ast.py — Add at the bottom
191+
192+
class MASObject:
193+
"""Base class for all MAS runtime objects (for future GC)."""
194+
def __init__(self):
195+
self.refcount = 1
196+
197+
def incref(self):
198+
self.refcount += 1
199+
200+
def decref(self):
201+
self.refcount -= 1
202+
if self.refcount == 0:
203+
self._free()
204+
205+
def _free(self):
206+
pass # Override in subclasses
207+
208+
class MASNumber(MASObject):
209+
def __init__(self, value):
210+
super().__init__()
211+
self.value = value
212+
def __repr__(self): return str(self.value)
213+
214+
class MASString(MASObject):
215+
def __init__(self, value):
216+
super().__init__()
217+
self.value = value
218+
def __repr__(self): return f'"{self.value}"'
219+
220+
class MASBoolean(MASObject):
221+
def __init__(self, value):
222+
super().__init__()
223+
self.value = value
224+
def __repr__(self): return 'true' if self.value else 'false'
225+
226+
class MASNull(MASObject):
227+
def __repr__(self): return 'null'
228+
229+
class MASList(MASObject):
230+
def __init__(self, items):
231+
super().__init__()
232+
self.items = items # list of MASObject
233+
for item in self.items:
234+
item.incref()
235+
def __repr__(self): return '[' + ', '.join(repr(x) for x in self.items) + ']'
236+
def _free(self):
237+
for item in self.items:
238+
item.decref()
239+
240+
class MASDict(MASObject):
241+
def __init__(self, pairs):
242+
super().__init__()
243+
# pairs: list of (key: MASObject, value: MASObject)
244+
self.pairs = pairs
245+
for k, v in self.pairs:
246+
k.incref()
247+
v.incref()
248+
def __repr__(self):
249+
items = [f"{k}: {v}" for k, v in self.pairs]
250+
return '{' + ', '.join(items) + '}'
251+
def _free(self):
252+
for k, v in self.pairs:
253+
k.decref()
254+
v.decref()

0 commit comments

Comments
 (0)