samlang 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
samlang/__init__.py ADDED
@@ -0,0 +1,6 @@
1
+ """
2
+ SamLang - A modern, high-performance programming language.
3
+ Created by Samrane Ahmed.
4
+ """
5
+
6
+ __version__ = "0.1.0"
samlang/__main__.py ADDED
@@ -0,0 +1,8 @@
1
+ """
2
+ Module entry point for `python -m samlang`.
3
+ Author: Samrane Ahmed
4
+ """
5
+ from samlang.cli import main
6
+
7
+ if __name__ == "__main__":
8
+ main()
samlang/ast_nodes.py ADDED
@@ -0,0 +1,641 @@
1
+ """
2
+ Abstract Syntax Tree (AST) Nodes for SamLang.
3
+ Author: Samrane Ahmed
4
+ """
5
+
6
+ from typing import List, Optional, Tuple
7
+ from samlang.tokens import Token, Position
8
+
9
+
10
+ class ASTNode:
11
+ """Base class for all Abstract Syntax Tree nodes in SamLang."""
12
+ def __init__(self, pos_start: Optional[Position] = None, pos_end: Optional[Position] = None):
13
+ self.pos_start: Optional[Position] = pos_start
14
+ self.pos_end: Optional[Position] = pos_end
15
+
16
+ def __repr__(self) -> str:
17
+ return f"{self.__class__.__name__}()"
18
+
19
+
20
+ class NumberNode(ASTNode):
21
+ """Represents numeric literals (integers and floats)."""
22
+ def __init__(self, tok: Token):
23
+ super().__init__(tok.pos_start, tok.pos_end)
24
+ self.tok: Token = tok
25
+ self.value: float = tok.value
26
+
27
+ def __repr__(self) -> str:
28
+ return f"NumberNode({self.value})"
29
+
30
+
31
+ class StringNode(ASTNode):
32
+ """Represents string literals."""
33
+ def __init__(self, tok: Token):
34
+ super().__init__(tok.pos_start, tok.pos_end)
35
+ self.tok: Token = tok
36
+ self.value: str = tok.value
37
+
38
+ def __repr__(self) -> str:
39
+ return f"StringNode({repr(self.value)})"
40
+
41
+
42
+ class VarAccessNode(ASTNode):
43
+ """Represents reading a variable value."""
44
+ def __init__(self, var_name_tok: Token):
45
+ super().__init__(var_name_tok.pos_start, var_name_tok.pos_end)
46
+ self.var_name_tok: Token = var_name_tok
47
+ self.var_name: str = var_name_tok.value
48
+
49
+ def __repr__(self) -> str:
50
+ return f"VarAccessNode({self.var_name})"
51
+
52
+
53
+ class VarAssignNode(ASTNode):
54
+ """Represents assigning a value to a variable (let x = expr or x = expr)."""
55
+ def __init__(self, var_name_tok: Token, value_node: ASTNode):
56
+ super().__init__(var_name_tok.pos_start, value_node.pos_end)
57
+ self.var_name_tok: Token = var_name_tok
58
+ self.var_name: str = var_name_tok.value
59
+ self.value_node: ASTNode = value_node
60
+
61
+ def __repr__(self) -> str:
62
+ return f"VarAssignNode({self.var_name} = {self.value_node})"
63
+
64
+
65
+ class BinOpNode(ASTNode):
66
+ """Represents binary operations (e.g. left + right, left * right)."""
67
+ def __init__(self, left_node: ASTNode, op_tok: Token, right_node: ASTNode):
68
+ super().__init__(left_node.pos_start, right_node.pos_end)
69
+ self.left_node: ASTNode = left_node
70
+ self.op_tok: Token = op_tok
71
+ self.right_node: ASTNode = right_node
72
+
73
+ def __repr__(self) -> str:
74
+ return f"BinOpNode({self.left_node} {self.op_tok.type} {self.right_node})"
75
+
76
+
77
+ class UnaryOpNode(ASTNode):
78
+ """Represents unary operations (e.g. -x, +x)."""
79
+ def __init__(self, op_tok: Token, node: ASTNode):
80
+ super().__init__(op_tok.pos_start, node.pos_end)
81
+ self.op_tok: Token = op_tok
82
+ self.node: ASTNode = node
83
+
84
+ def __repr__(self) -> str:
85
+ return f"UnaryOpNode({self.op_tok.type} {self.node})"
86
+
87
+
88
+ class PrintNode(ASTNode):
89
+ """Represents the built-in print, println, and echo statements."""
90
+ def __init__(self, expr_nodes: List[ASTNode], newline: bool = True, pos_start: Optional[Position] = None, pos_end: Optional[Position] = None):
91
+ super().__init__(pos_start, pos_end)
92
+ self.expr_nodes: List[ASTNode] = expr_nodes
93
+ self.newline: bool = newline
94
+
95
+ def __repr__(self) -> str:
96
+ return f"PrintNode({self.expr_nodes}, newline={self.newline})"
97
+
98
+
99
+ class BooleanNode(ASTNode):
100
+ """Represents boolean literals (true and false)."""
101
+ def __init__(self, tok: Token):
102
+ super().__init__(tok.pos_start, tok.pos_end)
103
+ self.tok: Token = tok
104
+ self.value: bool = bool(tok.value)
105
+
106
+ def __repr__(self) -> str:
107
+ return f"BooleanNode({self.value})"
108
+
109
+
110
+ class NullNode(ASTNode):
111
+ """Represents the null / nil literal."""
112
+ def __init__(self, tok: Token):
113
+ super().__init__(tok.pos_start, tok.pos_end)
114
+ self.tok: Token = tok
115
+ self.value = None
116
+
117
+ def __repr__(self) -> str:
118
+ return "NullNode()"
119
+
120
+
121
+ class BlockNode(ASTNode):
122
+ """Represents a scoped block of statements { ... }."""
123
+ def __init__(self, statements: List[ASTNode], pos_start: Optional[Position] = None, pos_end: Optional[Position] = None):
124
+ super().__init__(pos_start, pos_end)
125
+ self.statements: List[ASTNode] = statements
126
+
127
+ def __repr__(self) -> str:
128
+ return f"BlockNode({len(self.statements)} stmts)"
129
+
130
+
131
+ class FuncDefNode(ASTNode):
132
+ """Represents a function definition: func name(arg1, arg2) { body }."""
133
+ def __init__(self, func_name_tok: Token, arg_name_toks: List[Token], body_node: ASTNode):
134
+ super().__init__(func_name_tok.pos_start, body_node.pos_end)
135
+ self.func_name_tok: Token = func_name_tok
136
+ self.func_name: str = func_name_tok.value
137
+ self.arg_name_toks: List[Token] = arg_name_toks
138
+ self.arg_names: List[str] = [tok.value for tok in arg_name_toks]
139
+ self.body_node: ASTNode = body_node
140
+
141
+ def __repr__(self) -> str:
142
+ return f"FuncDefNode({self.func_name}({', '.join(self.arg_names)}))"
143
+
144
+
145
+ class FuncCallNode(ASTNode):
146
+ """Represents a function call: func_name(expr1, expr2)."""
147
+ def __init__(self, call_node: ASTNode, arg_nodes: List[ASTNode], pos_end: Optional[Position] = None):
148
+ super().__init__(call_node.pos_start, pos_end or call_node.pos_end)
149
+ self.call_node: ASTNode = call_node
150
+ self.arg_nodes: List[ASTNode] = arg_nodes
151
+
152
+ def __repr__(self) -> str:
153
+ return f"FuncCallNode({self.call_node}({len(self.arg_nodes)} args))"
154
+
155
+
156
+ class ReturnNode(ASTNode):
157
+ """Represents a return statement: return expr;."""
158
+ def __init__(self, value_node: Optional[ASTNode], pos_start: Position, pos_end: Optional[Position] = None):
159
+ super().__init__(pos_start, pos_end or (value_node.pos_end if value_node else pos_start))
160
+ self.value_node: Optional[ASTNode] = value_node
161
+
162
+ def __repr__(self) -> str:
163
+ return f"ReturnNode({self.value_node})"
164
+
165
+
166
+ class IfNode(ASTNode):
167
+ """Represents conditional branching: if cond { } elif cond { } else { }."""
168
+ def __init__(self, cases: List[Tuple[ASTNode, ASTNode]], else_case: Optional[ASTNode] = None, pos_start: Optional[Position] = None, pos_end: Optional[Position] = None):
169
+ super().__init__(pos_start, pos_end)
170
+ self.cases: List[Tuple[ASTNode, ASTNode]] = cases
171
+ self.else_case: Optional[ASTNode] = else_case
172
+
173
+ def __repr__(self) -> str:
174
+ return f"IfNode({len(self.cases)} cases, has_else={self.else_case is not None})"
175
+
176
+
177
+ class WhileNode(ASTNode):
178
+ """Represents while loops: while cond { body }."""
179
+ def __init__(self, condition_node: ASTNode, body_node: ASTNode, pos_start: Optional[Position] = None, pos_end: Optional[Position] = None):
180
+ super().__init__(pos_start, pos_end or body_node.pos_end)
181
+ self.condition_node: ASTNode = condition_node
182
+ self.body_node: ASTNode = body_node
183
+
184
+ def __repr__(self) -> str:
185
+ return f"WhileNode({self.condition_node})"
186
+
187
+
188
+ class ForNode(ASTNode):
189
+ """Represents a C-style for loop: for (init; cond; step) { body }."""
190
+ def __init__(self, init_node: Optional[ASTNode], cond_node: Optional[ASTNode], step_node: Optional[ASTNode], body_node: ASTNode, pos_start: Optional[Position] = None, pos_end: Optional[Position] = None):
191
+ super().__init__(pos_start, pos_end or body_node.pos_end)
192
+ self.init_node: Optional[ASTNode] = init_node
193
+ self.cond_node: Optional[ASTNode] = cond_node
194
+ self.step_node: Optional[ASTNode] = step_node
195
+ self.body_node: ASTNode = body_node
196
+
197
+ def __repr__(self) -> str:
198
+ return f"ForNode({self.init_node}; {self.cond_node}; {self.step_node})"
199
+
200
+
201
+ class ForRangeNode(ASTNode):
202
+ """Represents a range-based for loop: for var in range(...) { body }."""
203
+ def __init__(self, var_name_tok: Token, start_node: ASTNode, stop_node: ASTNode, step_node: ASTNode, body_node: ASTNode, pos_start: Optional[Position] = None, pos_end: Optional[Position] = None):
204
+ super().__init__(pos_start, pos_end or body_node.pos_end)
205
+ self.var_name_tok: Token = var_name_tok
206
+ self.var_name: str = var_name_tok.value
207
+ self.start_node: ASTNode = start_node
208
+ self.stop_node: ASTNode = stop_node
209
+ self.step_node: ASTNode = step_node
210
+ self.body_node: ASTNode = body_node
211
+
212
+ def __repr__(self) -> str:
213
+ return f"ForRangeNode({self.var_name} in range({self.start_node}, {self.stop_node}, {self.step_node}))"
214
+
215
+
216
+ class DoWhileNode(ASTNode):
217
+ """Represents a do-while loop: do { body } while (cond);."""
218
+ def __init__(self, body_node: ASTNode, condition_node: ASTNode, pos_start: Optional[Position] = None, pos_end: Optional[Position] = None):
219
+ super().__init__(pos_start, pos_end or condition_node.pos_end)
220
+ self.body_node: ASTNode = body_node
221
+ self.condition_node: ASTNode = condition_node
222
+
223
+ def __repr__(self) -> str:
224
+ return f"DoWhileNode(while {self.condition_node})"
225
+
226
+
227
+ class ConstAssignNode(ASTNode):
228
+ """Represents constant definition: const NAME = expr;."""
229
+ def __init__(self, var_name_tok: Token, value_node: ASTNode):
230
+ super().__init__(var_name_tok.pos_start, value_node.pos_end)
231
+ self.var_name_tok: Token = var_name_tok
232
+ self.var_name: str = var_name_tok.value
233
+ self.value_node: ASTNode = value_node
234
+
235
+ def __repr__(self) -> str:
236
+ return f"ConstAssignNode(const {self.var_name} = {self.value_node})"
237
+
238
+
239
+ class IncDecNode(ASTNode):
240
+ """Represents increment or decrement: x++, x--, ++x, --x."""
241
+ def __init__(self, var_name_tok: Token, op_tok: Token, is_prefix: bool = False):
242
+ pos_start = op_tok.pos_start if is_prefix else var_name_tok.pos_start
243
+ pos_end = var_name_tok.pos_end if is_prefix else op_tok.pos_end
244
+ super().__init__(pos_start, pos_end)
245
+ self.var_name_tok: Token = var_name_tok
246
+ self.var_name: str = var_name_tok.value
247
+ self.op_tok: Token = op_tok
248
+ self.is_prefix: bool = is_prefix
249
+
250
+ def __repr__(self) -> str:
251
+ prefix = "prefix" if self.is_prefix else "postfix"
252
+ return f"IncDecNode({prefix} {self.var_name}{self.op_tok.type})"
253
+
254
+
255
+ class CompoundAssignNode(ASTNode):
256
+ """Represents compound assignment: x += 5, x -= 2, x *= 3, etc."""
257
+ def __init__(self, var_name_tok: Token, op_tok: Token, value_node: ASTNode):
258
+ super().__init__(var_name_tok.pos_start, value_node.pos_end)
259
+ self.var_name_tok: Token = var_name_tok
260
+ self.var_name: str = var_name_tok.value
261
+ self.op_tok: Token = op_tok
262
+ self.value_node: ASTNode = value_node
263
+
264
+ def __repr__(self) -> str:
265
+ return f"CompoundAssignNode({self.var_name} {self.op_tok.type} {self.value_node})"
266
+
267
+
268
+ class RepeatNode(ASTNode):
269
+ """Represents a repeat loop: repeat count { body }."""
270
+ def __init__(self, count_node: ASTNode, body_node: ASTNode, pos_start: Optional[Position] = None, pos_end: Optional[Position] = None):
271
+ super().__init__(pos_start, pos_end or body_node.pos_end)
272
+ self.count_node: ASTNode = count_node
273
+ self.body_node: ASTNode = body_node
274
+
275
+ def __repr__(self) -> str:
276
+ return f"RepeatNode({self.count_node})"
277
+
278
+
279
+ class ListNode(ASTNode):
280
+ """Represents a list literal: [elem1, elem2, ...]."""
281
+ def __init__(self, element_nodes: List[ASTNode], pos_start: Optional[Position] = None, pos_end: Optional[Position] = None):
282
+ super().__init__(pos_start, pos_end)
283
+ self.element_nodes: List[ASTNode] = element_nodes
284
+
285
+ def __repr__(self) -> str:
286
+ return f"ListNode({self.element_nodes})"
287
+
288
+
289
+ class IndexAccessNode(ASTNode):
290
+ """Represents indexing into a collection: target[index]."""
291
+ def __init__(self, target_node: ASTNode, index_node: ASTNode, pos_start: Optional[Position] = None, pos_end: Optional[Position] = None):
292
+ super().__init__(pos_start or target_node.pos_start, pos_end or index_node.pos_end)
293
+ self.target_node: ASTNode = target_node
294
+ self.index_node: ASTNode = index_node
295
+
296
+ def __repr__(self) -> str:
297
+ return f"IndexAccessNode({self.target_node}[{self.index_node}])"
298
+
299
+
300
+ class IndexAssignNode(ASTNode):
301
+ """Represents assigning to an index: target[index] = val or target[index] += val."""
302
+ def __init__(self, target_node: ASTNode, index_node: ASTNode, op_tok: Token, value_node: ASTNode, pos_start: Optional[Position] = None, pos_end: Optional[Position] = None):
303
+ super().__init__(pos_start or target_node.pos_start, pos_end or value_node.pos_end)
304
+ self.target_node: ASTNode = target_node
305
+ self.index_node: ASTNode = index_node
306
+ self.op_tok: Token = op_tok
307
+ self.value_node: ASTNode = value_node
308
+
309
+ def __repr__(self) -> str:
310
+ return f"IndexAssignNode({self.target_node}[{self.index_node}] {self.op_tok.type} {self.value_node})"
311
+
312
+
313
+ class ForInNode(ASTNode):
314
+ """Represents for-in collection loop: for item in list { } or for i, item in list { }."""
315
+ def __init__(self, item_var_tok: Token, index_var_tok: Optional[Token], iterable_node: ASTNode, body_node: ASTNode, pos_start: Optional[Position] = None, pos_end: Optional[Position] = None):
316
+ super().__init__(pos_start, pos_end or body_node.pos_end)
317
+ self.item_var_tok: Token = item_var_tok
318
+ self.item_var: str = item_var_tok.value
319
+ self.index_var_tok: Optional[Token] = index_var_tok
320
+ self.index_var: Optional[str] = index_var_tok.value if index_var_tok else None
321
+ self.iterable_node: ASTNode = iterable_node
322
+ self.body_node: ASTNode = body_node
323
+
324
+ def __repr__(self) -> str:
325
+ idx_str = f"{self.index_var}, " if self.index_var else ""
326
+ return f"ForInNode({idx_str}{self.item_var} in {self.iterable_node})"
327
+
328
+
329
+ class TernaryNode(ASTNode):
330
+ """Represents ternary conditional operator: cond ? true_expr : false_expr."""
331
+ def __init__(self, condition_node: ASTNode, true_node: ASTNode, false_node: ASTNode, pos_start: Optional[Position] = None, pos_end: Optional[Position] = None):
332
+ super().__init__(pos_start or condition_node.pos_start, pos_end or false_node.pos_end)
333
+ self.condition_node: ASTNode = condition_node
334
+ self.true_node: ASTNode = true_node
335
+ self.false_node: ASTNode = false_node
336
+
337
+ def __repr__(self) -> str:
338
+ return f"TernaryNode({self.condition_node} ? {self.true_node} : {self.false_node})"
339
+
340
+
341
+ class DictNode(ASTNode):
342
+ """Represents a dictionary / hashmap literal: { key: value, ... }."""
343
+ def __init__(self, key_value_pairs: List[Tuple[ASTNode, ASTNode]], pos_start: Optional[Position] = None, pos_end: Optional[Position] = None):
344
+ super().__init__(pos_start, pos_end)
345
+ self.key_value_pairs: List[Tuple[ASTNode, ASTNode]] = key_value_pairs
346
+
347
+ def __repr__(self) -> str:
348
+ return f"DictNode({len(self.key_value_pairs)} pairs)"
349
+
350
+
351
+ class StatementsNode(ASTNode):
352
+ """Represents a list of sequential statements in a script."""
353
+ def __init__(self, statements: List[ASTNode], pos_start: Optional[Position] = None, pos_end: Optional[Position] = None):
354
+ super().__init__(pos_start, pos_end)
355
+ self.statements: List[ASTNode] = statements
356
+
357
+ def __repr__(self) -> str:
358
+ return f"StatementsNode({len(self.statements)} stmts)"
359
+
360
+
361
+ class ImportNode(ASTNode):
362
+ """
363
+ Represents an import statement:
364
+ - import "path/file.sl" [as alias]
365
+ - import module_name [as alias]
366
+ - import { item1, item2 as alias2 } from "path/file.sl"
367
+ - import item1, item2 from "path/file.sl"
368
+ - import * from "path/file.sl"
369
+ - from "path/file.sl" import item1, item2
370
+ - from "path/file.sl" import *
371
+ """
372
+ def __init__(
373
+ self,
374
+ module_path: str,
375
+ alias: Optional[str] = None,
376
+ items: Optional[List[Tuple[str, Optional[str]]]] = None,
377
+ is_wildcard: bool = False,
378
+ pos_start: Optional[Position] = None,
379
+ pos_end: Optional[Position] = None
380
+ ):
381
+ super().__init__(pos_start, pos_end)
382
+ self.module_path: str = module_path
383
+ self.alias: Optional[str] = alias
384
+ self.items: Optional[List[Tuple[str, Optional[str]]]] = items
385
+ self.is_wildcard: bool = is_wildcard
386
+
387
+ def __repr__(self) -> str:
388
+ if self.is_wildcard:
389
+ return f"ImportNode(* from {self.module_path})"
390
+ if self.items:
391
+ items_str = ", ".join(f"{orig} as {al}" if al else orig for orig, al in self.items)
392
+ return f"ImportNode({{{items_str}}} from {self.module_path})"
393
+ if self.alias:
394
+ return f"ImportNode({self.module_path} as {self.alias})"
395
+ return f"ImportNode({self.module_path})"
396
+
397
+
398
+ class ExportNode(ASTNode):
399
+ """Represents an export statement: export func foo() ... or export const X = 1;"""
400
+ def __init__(self, statement_node: ASTNode, pos_start: Optional[Position] = None, pos_end: Optional[Position] = None):
401
+ super().__init__(pos_start or statement_node.pos_start, pos_end or statement_node.pos_end)
402
+ self.statement_node: ASTNode = statement_node
403
+
404
+ def __repr__(self) -> str:
405
+ return f"ExportNode({self.statement_node})"
406
+
407
+
408
+ class BreakNode(ASTNode):
409
+ """Represents a break statement inside loops."""
410
+ def __init__(self, pos_start: Optional[Position] = None, pos_end: Optional[Position] = None):
411
+ super().__init__(pos_start, pos_end)
412
+
413
+ def __repr__(self) -> str:
414
+ return "BreakNode()"
415
+
416
+
417
+ class ContinueNode(ASTNode):
418
+ """Represents a continue statement inside loops."""
419
+ def __init__(self, pos_start: Optional[Position] = None, pos_end: Optional[Position] = None):
420
+ super().__init__(pos_start, pos_end)
421
+
422
+ def __repr__(self) -> str:
423
+ return "ContinueNode()"
424
+
425
+
426
+ class TryCatchNode(ASTNode):
427
+ """Represents try-catch error handling: try { ... } catch (err) { ... } [finally { ... }]"""
428
+ def __init__(
429
+ self,
430
+ try_body: ASTNode,
431
+ catch_var_tok: Optional[Token],
432
+ catch_body: ASTNode,
433
+ finally_body: Optional[ASTNode] = None,
434
+ pos_start: Optional[Position] = None,
435
+ pos_end: Optional[Position] = None
436
+ ):
437
+ super().__init__(pos_start, pos_end)
438
+ self.try_body: ASTNode = try_body
439
+ self.catch_var: Optional[str] = catch_var_tok.value if catch_var_tok else None
440
+ self.catch_body: ASTNode = catch_body
441
+ self.finally_body: Optional[ASTNode] = finally_body
442
+
443
+ def __repr__(self) -> str:
444
+ var_str = f"({self.catch_var})" if self.catch_var else ""
445
+ return f"TryCatchNode(try {self.try_body} catch{var_str} {self.catch_body})"
446
+
447
+
448
+ class LambdaNode(ASTNode):
449
+ """Represents an anonymous / arrow function: (x, y) => expr or (x) => { ... }."""
450
+ def __init__(self, arg_names: List[str], body_node: ASTNode, pos_start: Optional[Position] = None, pos_end: Optional[Position] = None):
451
+ super().__init__(pos_start, pos_end)
452
+ self.arg_names: List[str] = arg_names
453
+ self.body_node: ASTNode = body_node
454
+
455
+ def __repr__(self) -> str:
456
+ return f"LambdaNode(({', '.join(self.arg_names)}) => {self.body_node})"
457
+
458
+
459
+ class PropertyDefNode(ASTNode):
460
+ """Represents a property: let Name { get; set; } [= default]."""
461
+ def __init__(
462
+ self,
463
+ name_tok: Token,
464
+ has_get: bool = True,
465
+ has_set: bool = True,
466
+ default_node: Optional[ASTNode] = None,
467
+ pos_start: Optional[Position] = None,
468
+ pos_end: Optional[Position] = None
469
+ ):
470
+ super().__init__(pos_start or name_tok.pos_start, pos_end or (default_node.pos_end if default_node else name_tok.pos_end))
471
+ self.name_tok: Token = name_tok
472
+ self.name: str = name_tok.value
473
+ self.has_get: bool = has_get
474
+ self.has_set: bool = has_set
475
+ self.default_node: Optional[ASTNode] = default_node
476
+
477
+ def __repr__(self) -> str:
478
+ gs = f"{{ {'get; ' if self.has_get else ''}{'set; ' if self.has_set else ''}}}"
479
+ return f"PropertyDefNode({self.name} {gs})"
480
+
481
+
482
+ class MethodDefNode(ASTNode):
483
+ """Represents a class method or constructor with virtual/override/static modifiers."""
484
+ def __init__(
485
+ self,
486
+ name_tok: Token,
487
+ arg_name_toks: List[Token],
488
+ body_node: ASTNode,
489
+ is_virtual: bool = False,
490
+ is_override: bool = False,
491
+ is_static: bool = False,
492
+ pos_start: Optional[Position] = None,
493
+ pos_end: Optional[Position] = None
494
+ ):
495
+ super().__init__(pos_start or name_tok.pos_start, pos_end or body_node.pos_end)
496
+ self.name_tok: Token = name_tok
497
+ self.name: str = name_tok.value
498
+ self.arg_name_toks: List[Token] = arg_name_toks
499
+ self.body_node: ASTNode = body_node
500
+ self.is_virtual: bool = is_virtual
501
+ self.is_override: bool = is_override
502
+ self.is_static: bool = is_static
503
+
504
+ def __repr__(self) -> str:
505
+ mods = []
506
+ if self.is_virtual: mods.append("virtuel")
507
+ if self.is_override: mods.append("override")
508
+ if self.is_static: mods.append("static")
509
+ mod_str = (" " + " ".join(mods)) if mods else ""
510
+ return f"MethodDefNode(func{mod_str} {self.name}(...))"
511
+
512
+
513
+ class ClassDefNode(ASTNode):
514
+ """Represents a class definition: class Name [: Parent] { ... }."""
515
+ def __init__(
516
+ self,
517
+ name_tok: Token,
518
+ parent_tok: Optional[Token],
519
+ properties: List[PropertyDefNode],
520
+ methods: List[MethodDefNode],
521
+ constructor: Optional[MethodDefNode] = None,
522
+ pos_start: Optional[Position] = None,
523
+ pos_end: Optional[Position] = None
524
+ ):
525
+ super().__init__(pos_start or name_tok.pos_start, pos_end or name_tok.pos_end)
526
+ self.name_tok: Token = name_tok
527
+ self.name: str = name_tok.value
528
+ self.parent_tok: Optional[Token] = parent_tok
529
+ self.parent_name: Optional[str] = parent_tok.value if parent_tok else None
530
+ self.properties: List[PropertyDefNode] = properties
531
+ self.methods: List[MethodDefNode] = methods
532
+ self.constructor: Optional[MethodDefNode] = constructor
533
+
534
+ def __repr__(self) -> str:
535
+ parent_str = f" : {self.parent_name}" if self.parent_name else ""
536
+ return f"ClassDefNode({self.name}{parent_str})"
537
+
538
+
539
+ class NewNode(ASTNode):
540
+ """Represents object instantiation: new ClassName(args)."""
541
+ def __init__(
542
+ self,
543
+ class_node: ASTNode,
544
+ arg_nodes: List[ASTNode],
545
+ pos_start: Optional[Position] = None,
546
+ pos_end: Optional[Position] = None
547
+ ):
548
+ super().__init__(pos_start or class_node.pos_start, pos_end or class_node.pos_end)
549
+ self.class_node: ASTNode = class_node
550
+ self.arg_nodes: List[ASTNode] = arg_nodes
551
+
552
+ def __repr__(self) -> str:
553
+ return f"NewNode(new {self.class_node}({len(self.arg_nodes)} args))"
554
+
555
+
556
+ class BaseCallNode(ASTNode):
557
+ """Represents calling parent constructor: base(args)."""
558
+ def __init__(
559
+ self,
560
+ arg_nodes: List[ASTNode],
561
+ pos_start: Optional[Position] = None,
562
+ pos_end: Optional[Position] = None
563
+ ):
564
+ super().__init__(pos_start, pos_end)
565
+ self.arg_nodes: List[ASTNode] = arg_nodes
566
+
567
+ def __repr__(self) -> str:
568
+ return f"BaseCallNode(base({len(self.arg_nodes)} args))"
569
+
570
+
571
+ class BaseAccessNode(ASTNode):
572
+ """Represents accessing parent member: base.member."""
573
+ def __init__(
574
+ self,
575
+ member_tok: Token,
576
+ pos_start: Optional[Position] = None,
577
+ pos_end: Optional[Position] = None
578
+ ):
579
+ super().__init__(pos_start, pos_end or member_tok.pos_end)
580
+ self.member_tok: Token = member_tok
581
+ self.member_name: str = member_tok.value
582
+
583
+ def __repr__(self) -> str:
584
+ return f"BaseAccessNode(base.{self.member_name})"
585
+
586
+
587
+ class ThisNode(ASTNode):
588
+ """Represents 'this' or 'self' reference to current instance."""
589
+ def __init__(self, tok: Token):
590
+ super().__init__(tok.pos_start, tok.pos_end)
591
+ self.tok: Token = tok
592
+ self.name: str = tok.value
593
+
594
+ def __repr__(self) -> str:
595
+ return f"ThisNode({self.name})"
596
+
597
+
598
+ class TypedVarAssignNode(ASTNode):
599
+ """Represents explicit typed variable declaration: Person s = new Student()."""
600
+ def __init__(
601
+ self,
602
+ type_tok: Token,
603
+ var_name_tok: Token,
604
+ value_node: ASTNode,
605
+ pos_start: Optional[Position] = None,
606
+ pos_end: Optional[Position] = None
607
+ ):
608
+ super().__init__(pos_start or type_tok.pos_start, pos_end or value_node.pos_end)
609
+ self.type_tok: Token = type_tok
610
+ self.type_name: str = type_tok.value
611
+ self.var_name_tok: Token = var_name_tok
612
+ self.var_name: str = var_name_tok.value
613
+ self.value_node: ASTNode = value_node
614
+
615
+ def __repr__(self) -> str:
616
+ return f"TypedVarAssignNode({self.type_name} {self.var_name} = {self.value_node})"
617
+
618
+
619
+ class MemberAssignNode(ASTNode):
620
+ """Represents assignment to an object property: obj.prop = value."""
621
+ def __init__(
622
+ self,
623
+ target_node: ASTNode,
624
+ member_tok: Token,
625
+ value_node: ASTNode,
626
+ pos_start: Optional[Position] = None,
627
+ pos_end: Optional[Position] = None
628
+ ):
629
+ super().__init__(pos_start or target_node.pos_start, pos_end or value_node.pos_end)
630
+ self.target_node: ASTNode = target_node
631
+ self.member_tok: Token = member_tok
632
+ self.member_name: str = member_tok.value
633
+ self.value_node: ASTNode = value_node
634
+
635
+ def __repr__(self) -> str:
636
+ return f"MemberAssignNode({self.target_node}.{self.member_name} = {self.value_node})"
637
+
638
+
639
+
640
+
641
+