-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathastnode.py
More file actions
128 lines (96 loc) · 3.15 KB
/
astnode.py
File metadata and controls
128 lines (96 loc) · 3.15 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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
from dataclasses import dataclass, field
from typing import Union, Tuple, Any
from llvmlite import ir
from instruction import Instruction
from type import Type
class BaseAst:
# text_indices: [int, int]
def __init__(self):
raise RuntimeError("Cannot instantiate BaseAst")
@dataclass()
class ProgN(BaseAst):
programs: list[BaseAst]
@dataclass(init=False)
class VariableDef(BaseAst):
name: str
type: Type
def __init__(self, name: str, type: Type):
self.name = name
self.type = type
@dataclass
class VariableLoad(BaseAst):
variable: VariableDef
@dataclass
class UnresolvedVariableLoad(BaseAst):
variable: str
@dataclass()
class ConstantLoad(BaseAst):
type: Type
constant: Any
@dataclass(slots=True)
class UntypedFnDef(BaseAst):
name: str
params: list[VariableDef]
body: list[BaseAst]
@dataclass
class TypedFnDef(BaseAst):
name: str
params: list[VariableDef]
body: BaseAst
return_type: Type
@dataclass(slots=True)
class FunctionApplication(BaseAst):
fn: TypedFnDef
params: list[BaseAst]
@dataclass(slots=True)
class UnresolvedFnApp(BaseAst):
fn: str
params: list[BaseAst]
@dataclass
class AstNode:
instr: Instruction
operands: list[Union['AstNode', int, str]] = field(default_factory=list)
bound_variables: dict = field(default_factory=dict)
text_indices: Tuple[int, int] = field(default=(0, 0))
def set(self, node: 'AstNode'):
self.instr = node.instr
self.operands = node.operands
self.bound_variables = node.bound_variables
self.text_indices = node.text_indices
def set_bound_vars(self, new_var: str, value: ir.Value):
self.bound_variables[new_var] = value
for k in self.operands:
match k:
case AstNode():
k.set_bound_vars(new_var, value)
def get_bound_vars(self, name: str) -> ir.Value:
try:
return self.bound_variables[name]
except KeyError:
raise KeyError(f"{name} doesn't exist in the variable namespace")
def __repr__(self):
return self.curry_type_repr(0)
def repr_operands(self, depth: int) -> str:
tail = ""
for o in self.operands:
match o:
case AstNode() as o:
tail += f"{' ' * depth}{o.curry_type_repr(depth + 1)}\n"
case _ as o:
tail += f"{' ' * depth}{o}"
return tail
def curry_type_repr(self, depth: int) -> str:
match self.instr:
case Instruction.NumberConstant:
return f"{' ' * depth}C-{self.operands[0]}"
case Instruction.String1:
return f"{' ' * depth}String({self.operands[0]})"
case Instruction.Unknown:
match self.operands:
case [x] if not isinstance(x, AstNode):
return f"{self.repr_operands(depth)}"
case _:
return f"{' ' * depth}UK-(\n{self.repr_operands(depth + 1)}"
case _:
head = f"{self.instr}"
return f"{head}\n{self.repr_operands(depth + 1)}"