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