shell-lite 0.5.3.1__py3-none-any.whl → 0.5.3.2__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.
- shell_lite/interpreter.py +1 -1
- shell_lite/main.py +7 -1
- {shell_lite-0.5.3.1.dist-info → shell_lite-0.5.3.2.dist-info}/METADATA +1 -1
- {shell_lite-0.5.3.1.dist-info → shell_lite-0.5.3.2.dist-info}/RECORD +8 -11
- shell_lite/llvm_backend/__init__.py +0 -0
- shell_lite/llvm_backend/builder.py +0 -39
- shell_lite/llvm_backend/codegen.py +0 -311
- {shell_lite-0.5.3.1.dist-info → shell_lite-0.5.3.2.dist-info}/LICENSE +0 -0
- {shell_lite-0.5.3.1.dist-info → shell_lite-0.5.3.2.dist-info}/WHEEL +0 -0
- {shell_lite-0.5.3.1.dist-info → shell_lite-0.5.3.2.dist-info}/entry_points.txt +0 -0
- {shell_lite-0.5.3.1.dist-info → shell_lite-0.5.3.2.dist-info}/top_level.txt +0 -0
shell_lite/interpreter.py
CHANGED
|
@@ -1504,7 +1504,7 @@ class Interpreter:
|
|
|
1504
1504
|
self.wfile.write(str(e).encode())
|
|
1505
1505
|
except: pass
|
|
1506
1506
|
server = ReusableHTTPServer(('0.0.0.0', port_val), ShellLiteHandler)
|
|
1507
|
-
print(f"\n ShellLite Server v0.5.3.
|
|
1507
|
+
print(f"\n ShellLite Server v0.5.3.2 is running!")
|
|
1508
1508
|
print(f" \u001b[1;36m➜\u001b[0m Local: \u001b[1;4;36mhttp://localhost:{port_val}/\u001b[0m\n")
|
|
1509
1509
|
try: server.serve_forever()
|
|
1510
1510
|
except KeyboardInterrupt:
|
shell_lite/main.py
CHANGED
|
@@ -150,7 +150,7 @@ def install_globally():
|
|
|
150
150
|
return
|
|
151
151
|
ps_cmd = f'$oldPath = [Environment]::GetEnvironmentVariable("Path", "User"); if ($oldPath -notlike "*ShellLite*") {{ [Environment]::SetEnvironmentVariable("Path", "$oldPath;{install_dir}", "User") }}'
|
|
152
152
|
subprocess.run(["powershell", "-Command", ps_cmd], capture_output=True)
|
|
153
|
-
print(f"\n[SUCCESS] ShellLite (v0.5.3) is installed!")
|
|
153
|
+
print(f"\n[SUCCESS] ShellLite (v0.5.3.2) is installed!")
|
|
154
154
|
print(f"Location: {install_dir}")
|
|
155
155
|
print("\nIMPORTANT STEP REQUIRED:")
|
|
156
156
|
print("1. Close ALL open terminal windows (CMD, PowerShell, VS Code).")
|
|
@@ -443,6 +443,12 @@ def main():
|
|
|
443
443
|
print("Usage: shl llvm <filename>")
|
|
444
444
|
elif cmd == "help" or cmd == "--help" or cmd == "-h":
|
|
445
445
|
show_help()
|
|
446
|
+
elif cmd == "--version" or cmd == "-v":
|
|
447
|
+
try:
|
|
448
|
+
from importlib.metadata import version
|
|
449
|
+
print(f"ShellLite v{version('shell-lite')}")
|
|
450
|
+
except Exception:
|
|
451
|
+
print("ShellLite v0.5.3.1")
|
|
446
452
|
elif cmd == "get":
|
|
447
453
|
if len(sys.argv) > 2:
|
|
448
454
|
package_name = sys.argv[2]
|
|
@@ -2,19 +2,16 @@ shell_lite/__init__.py,sha256=frcCV1k9oG9oKj3dpUqdJg1PxRT2RSN_XKdLCPjaYaY,2
|
|
|
2
2
|
shell_lite/ast_nodes.py,sha256=W2oefXuRjqnQybR5ZcdPU0qC5gxHZHcotQc3LAVDLM0,6129
|
|
3
3
|
shell_lite/cli.py,sha256=14Kq1ohSXS3p-xdh0DPi7eXskUtSX81huSyGhktoOMA,250
|
|
4
4
|
shell_lite/compiler.py,sha256=t2Imae9h03v3GIIKrCo16qCDDLKSxrpjrp83tv0SzUQ,24982
|
|
5
|
-
shell_lite/interpreter.py,sha256=
|
|
5
|
+
shell_lite/interpreter.py,sha256=zQE7NopelZeHYT94ZbZYGTBSd_ZgaOCWNU86ugUwYuw,75964
|
|
6
6
|
shell_lite/js_compiler.py,sha256=yEGIkkIvHGU7o1htHEqlQr6BE0wL35PtL5PssNld9fc,5606
|
|
7
7
|
shell_lite/lexer.py,sha256=cNLk_N59a7eKQaQp7Mqcnxy1um64-QgtDEi2eAsAWKE,14913
|
|
8
|
-
shell_lite/main.py,sha256=
|
|
8
|
+
shell_lite/main.py,sha256=Vg-BUReR3JsK-sdcwFYUIx5vy8AkSLmqfsOQRWAVFdU,20150
|
|
9
9
|
shell_lite/parser.py,sha256=qsR2wQUWjUPXbXgnmv8pmOgfX99lYYH6tpxKH3PEnfQ,88471
|
|
10
10
|
shell_lite/parser_gbp.py,sha256=IV5lD1IipDOqgoC6UdVpFnuWQBb73WmEAYMigDGTfcQ,16555
|
|
11
11
|
shell_lite/runtime.py,sha256=pSjBeA1dTQ-a94q3FLdv9lqZurdd6MJmfhFGHhOoQEM,16057
|
|
12
|
-
shell_lite/
|
|
13
|
-
shell_lite/
|
|
14
|
-
shell_lite/
|
|
15
|
-
shell_lite-0.5.3.
|
|
16
|
-
shell_lite-0.5.3.
|
|
17
|
-
shell_lite-0.5.3.
|
|
18
|
-
shell_lite-0.5.3.1.dist-info/entry_points.txt,sha256=tglL8tjyPIh1W85j6zFpNZjMpQe_xC-k-7BOhHLWfxc,45
|
|
19
|
-
shell_lite-0.5.3.1.dist-info/top_level.txt,sha256=hIln5ltrok_Mn3ijlQeqMFF6hHBHCyhzqCO7KL358cg,11
|
|
20
|
-
shell_lite-0.5.3.1.dist-info/RECORD,,
|
|
12
|
+
shell_lite-0.5.3.2.dist-info/LICENSE,sha256=LlK8rVgwqMiti6NfaXa8xfvXAwfYe5SVrvcz3YpwHgg,37277
|
|
13
|
+
shell_lite-0.5.3.2.dist-info/METADATA,sha256=ReF60tgHn2PTAYXb-W2lKM3B8F25iq-l8SukauYzKrc,10586
|
|
14
|
+
shell_lite-0.5.3.2.dist-info/WHEEL,sha256=hPN0AlP2dZM_3ZJZWP4WooepkmU9wzjGgCLCeFjkHLA,92
|
|
15
|
+
shell_lite-0.5.3.2.dist-info/entry_points.txt,sha256=tglL8tjyPIh1W85j6zFpNZjMpQe_xC-k-7BOhHLWfxc,45
|
|
16
|
+
shell_lite-0.5.3.2.dist-info/top_level.txt,sha256=hIln5ltrok_Mn3ijlQeqMFF6hHBHCyhzqCO7KL358cg,11
|
|
17
|
+
shell_lite-0.5.3.2.dist-info/RECORD,,
|
|
File without changes
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import llvmlite.binding as llvm
|
|
2
|
-
from .codegen import LLVMCompiler
|
|
3
|
-
from ..lexer import Lexer
|
|
4
|
-
from ..parser import Parser
|
|
5
|
-
import os
|
|
6
|
-
def build_llvm(filename: str):
|
|
7
|
-
print(f"Compiling {filename} with LLVM Backend...")
|
|
8
|
-
with open(filename, 'r', encoding='utf-8') as f:
|
|
9
|
-
source = f.read()
|
|
10
|
-
lexer = Lexer(source)
|
|
11
|
-
tokens = lexer.tokenize()
|
|
12
|
-
parser = Parser(tokens)
|
|
13
|
-
statements = parser.parse()
|
|
14
|
-
compiler = LLVMCompiler()
|
|
15
|
-
module = compiler.compile(statements)
|
|
16
|
-
llvm_ir = str(module)
|
|
17
|
-
print("\n--- Generated LLVM IR ---")
|
|
18
|
-
print(llvm_ir)
|
|
19
|
-
print("-------------------------\n")
|
|
20
|
-
ll_filename = os.path.splitext(filename)[0] + ".ll"
|
|
21
|
-
with open(ll_filename, 'w') as f:
|
|
22
|
-
f.write(llvm_ir)
|
|
23
|
-
print(f"[SUCCESS] Generated LLVM IR: {ll_filename}")
|
|
24
|
-
print("\nTo compile to executable, you can use Clang:")
|
|
25
|
-
print(f" clang {ll_filename} -o {os.path.splitext(filename)[0]}.exe")
|
|
26
|
-
"""
|
|
27
|
-
try:
|
|
28
|
-
print("Initializing LLVM...")
|
|
29
|
-
llvm.initialize()
|
|
30
|
-
llvm.initialize_native_target()
|
|
31
|
-
llvm.initialize_native_asmprinter()
|
|
32
|
-
print("LLVM Initialized.")
|
|
33
|
-
print("Creating Target...")
|
|
34
|
-
target = llvm.Target.from_default_triple()
|
|
35
|
-
print(f"Target Triple: {target}")
|
|
36
|
-
target_machine = target.create_target_machine()
|
|
37
|
-
except Exception as e:
|
|
38
|
-
print(f"Native binding skipped due to: {e}")
|
|
39
|
-
"""
|
|
@@ -1,311 +0,0 @@
|
|
|
1
|
-
from llvmlite import ir
|
|
2
|
-
from ..ast_nodes import *
|
|
3
|
-
class LLVMCompiler:
|
|
4
|
-
def __init__(self):
|
|
5
|
-
self.module = ir.Module(name="shell_lite_module")
|
|
6
|
-
self.module.triple = "x86_64-pc-windows-msvc" # Assume Windows for now based on user OS
|
|
7
|
-
self.int32 = ir.IntType(32)
|
|
8
|
-
self.char_ptr = ir.IntType(8).as_pointer()
|
|
9
|
-
voidptr_ty = ir.IntType(8).as_pointer()
|
|
10
|
-
printf_ty = ir.FunctionType(self.int32, [voidptr_ty], var_arg=True)
|
|
11
|
-
self.printf = ir.Function(self.module, printf_ty, name="printf")
|
|
12
|
-
malloc_ty = ir.FunctionType(voidptr_ty, [self.int32])
|
|
13
|
-
self.malloc = ir.Function(self.module, malloc_ty, name="malloc")
|
|
14
|
-
free_ty = ir.FunctionType(ir.VoidType(), [voidptr_ty])
|
|
15
|
-
self.free = ir.Function(self.module, free_ty, name="free")
|
|
16
|
-
strlen_ty = ir.FunctionType(self.int32, [voidptr_ty])
|
|
17
|
-
self.strlen = ir.Function(self.module, strlen_ty, name="strlen")
|
|
18
|
-
strcpy_ty = ir.FunctionType(voidptr_ty, [voidptr_ty, voidptr_ty])
|
|
19
|
-
self.strcpy = ir.Function(self.module, strcpy_ty, name="strcpy")
|
|
20
|
-
strcat_ty = ir.FunctionType(voidptr_ty, [voidptr_ty, voidptr_ty])
|
|
21
|
-
self.strcat = ir.Function(self.module, strcat_ty, name="strcat")
|
|
22
|
-
fopen_ty = ir.FunctionType(voidptr_ty, [voidptr_ty, voidptr_ty])
|
|
23
|
-
self.fopen = ir.Function(self.module, fopen_ty, name="fopen")
|
|
24
|
-
fclose_ty = ir.FunctionType(self.int32, [voidptr_ty])
|
|
25
|
-
self.fclose = ir.Function(self.module, fclose_ty, name="fclose")
|
|
26
|
-
fwrite_ty = ir.FunctionType(self.int32, [voidptr_ty, self.int32, self.int32, voidptr_ty])
|
|
27
|
-
self.fwrite = ir.Function(self.module, fwrite_ty, name="fwrite")
|
|
28
|
-
fread_ty = ir.FunctionType(self.int32, [voidptr_ty, self.int32, self.int32, voidptr_ty])
|
|
29
|
-
self.fread = ir.Function(self.module, fread_ty, name="fread")
|
|
30
|
-
fgets_ty = ir.FunctionType(voidptr_ty, [voidptr_ty, self.int32, voidptr_ty])
|
|
31
|
-
self.fgets = ir.Function(self.module, fgets_ty, name="fgets")
|
|
32
|
-
fseek_ty = ir.FunctionType(self.int32, [voidptr_ty, self.int32, self.int32])
|
|
33
|
-
self.fseek = ir.Function(self.module, fseek_ty, name="fseek")
|
|
34
|
-
ftell_ty = ir.FunctionType(self.int32, [voidptr_ty])
|
|
35
|
-
self.ftell = ir.Function(self.module, ftell_ty, name="ftell")
|
|
36
|
-
rewind_ty = ir.FunctionType(ir.VoidType(), [voidptr_ty])
|
|
37
|
-
self.rewind = ir.Function(self.module, rewind_ty, name="rewind")
|
|
38
|
-
get_stdin_ty = ir.FunctionType(voidptr_ty, [self.int32])
|
|
39
|
-
self.get_stdin = ir.Function(self.module, get_stdin_ty, name="__acrt_iob_func")
|
|
40
|
-
system_ty = ir.FunctionType(self.int32, [voidptr_ty])
|
|
41
|
-
self.system = ir.Function(self.module, system_ty, name="system")
|
|
42
|
-
func_type = ir.FunctionType(self.int32, [], var_arg=False)
|
|
43
|
-
self.main_func = ir.Function(self.module, func_type, name="main")
|
|
44
|
-
block = self.main_func.append_basic_block(name="entry")
|
|
45
|
-
self.builder = ir.IRBuilder(block)
|
|
46
|
-
self.scopes = [{}]
|
|
47
|
-
self.loop_stack = []
|
|
48
|
-
self.str_constants = {}
|
|
49
|
-
def _get_scope(self):
|
|
50
|
-
return self.scopes[-1]
|
|
51
|
-
def _alloca(self, name, typ=None):
|
|
52
|
-
if typ is None: typ = self.int32
|
|
53
|
-
with self.builder.goto_entry_block():
|
|
54
|
-
ptr = self.builder.alloca(typ, size=None, name=name)
|
|
55
|
-
return ptr
|
|
56
|
-
def compile(self, statements):
|
|
57
|
-
for stmt in statements:
|
|
58
|
-
self.visit(stmt)
|
|
59
|
-
self.builder.ret(ir.Constant(self.int32, 0))
|
|
60
|
-
return self.module
|
|
61
|
-
def visit(self, node):
|
|
62
|
-
method_name = f'visit_{type(node).__name__}'
|
|
63
|
-
visitor = getattr(self, method_name, self.generic_visit)
|
|
64
|
-
return visitor(node)
|
|
65
|
-
def generic_visit(self, node):
|
|
66
|
-
print(f"Warning: LLVM Backend does not support {type(node).__name__} yet.")
|
|
67
|
-
return None
|
|
68
|
-
def visit_Number(self, node: Number):
|
|
69
|
-
return ir.Constant(self.int32, int(node.value))
|
|
70
|
-
def visit_String(self, node: String):
|
|
71
|
-
return self._get_string_constant(node.value)
|
|
72
|
-
def visit_BinOp(self, node: BinOp):
|
|
73
|
-
left = self.visit(node.left)
|
|
74
|
-
right = self.visit(node.right)
|
|
75
|
-
op = node.op
|
|
76
|
-
if op == '+':
|
|
77
|
-
is_str_op = False
|
|
78
|
-
if left.type == self.char_ptr or right.type == self.char_ptr:
|
|
79
|
-
is_str_op = True
|
|
80
|
-
if is_str_op:
|
|
81
|
-
if left.type == self.int32:
|
|
82
|
-
left = self.builder.inttoptr(left, self.char_ptr, name="cast_l")
|
|
83
|
-
if right.type == self.int32:
|
|
84
|
-
right = self.builder.inttoptr(right, self.char_ptr, name="cast_r")
|
|
85
|
-
if is_str_op:
|
|
86
|
-
len1 = self.builder.call(self.strlen, [left], name="len1")
|
|
87
|
-
len2 = self.builder.call(self.strlen, [right], name="len2")
|
|
88
|
-
total_len = self.builder.add(len1, len2, name="total_len")
|
|
89
|
-
total_len_null = self.builder.add(total_len, ir.Constant(self.int32, 1), name="alloc_len")
|
|
90
|
-
new_str = self.builder.call(self.malloc, [total_len_null], name="new_str")
|
|
91
|
-
self.builder.call(self.strcpy, [new_str, left])
|
|
92
|
-
self.builder.call(self.strcat, [new_str, right])
|
|
93
|
-
return new_str
|
|
94
|
-
return self.builder.add(left, right, name="addtmp")
|
|
95
|
-
elif op == '-':
|
|
96
|
-
return self.builder.sub(left, right, name="subtmp")
|
|
97
|
-
elif op == '*':
|
|
98
|
-
return self.builder.mul(left, right, name="multmp")
|
|
99
|
-
elif op == '/':
|
|
100
|
-
return self.builder.sdiv(left, right, name="divtmp")
|
|
101
|
-
elif op == '==' or op == 'is':
|
|
102
|
-
return self.builder.icmp_signed('==', left, right, name="eqtmp")
|
|
103
|
-
elif op == '!=' or op == 'is not':
|
|
104
|
-
return self.builder.icmp_signed('!=', left, right, name="netmp")
|
|
105
|
-
elif op == '<':
|
|
106
|
-
return self.builder.icmp_signed('<', left, right, name="lttmp")
|
|
107
|
-
elif op == '<=':
|
|
108
|
-
return self.builder.icmp_signed('<=', left, right, name="letmp")
|
|
109
|
-
elif op == '>':
|
|
110
|
-
return self.builder.icmp_signed('>', left, right, name="gttmp")
|
|
111
|
-
elif op == '>=':
|
|
112
|
-
return self.builder.icmp_signed('>=', left, right, name="getmp")
|
|
113
|
-
else:
|
|
114
|
-
raise Exception(f"Unknown operator: {op}")
|
|
115
|
-
def visit_If(self, node: If):
|
|
116
|
-
cond_val = self.visit(node.condition)
|
|
117
|
-
if cond_val.type != ir.IntType(1):
|
|
118
|
-
cond_val = self.builder.icmp_signed('!=', cond_val, ir.Constant(self.int32, 0), name="ifcond")
|
|
119
|
-
then_bb = self.builder.append_basic_block(name="then")
|
|
120
|
-
else_bb = self.builder.append_basic_block(name="else")
|
|
121
|
-
merge_bb = self.builder.append_basic_block(name="ifcont")
|
|
122
|
-
self.builder.cbranch(cond_val, then_bb, else_bb)
|
|
123
|
-
self.builder.position_at_end(then_bb)
|
|
124
|
-
for stmt in node.body:
|
|
125
|
-
self.visit(stmt)
|
|
126
|
-
if not self.builder.block.is_terminated:
|
|
127
|
-
self.builder.branch(merge_bb)
|
|
128
|
-
self.builder.position_at_end(else_bb)
|
|
129
|
-
if node.else_body:
|
|
130
|
-
for stmt in node.else_body:
|
|
131
|
-
self.visit(stmt)
|
|
132
|
-
if not self.builder.block.is_terminated:
|
|
133
|
-
self.builder.branch(merge_bb)
|
|
134
|
-
self.builder.position_at_end(merge_bb)
|
|
135
|
-
def visit_While(self, node: While):
|
|
136
|
-
cond_bb = self.builder.append_basic_block(name="loop.cond")
|
|
137
|
-
body_bb = self.builder.append_basic_block(name="loop.body")
|
|
138
|
-
after_bb = self.builder.append_basic_block(name="loop.after")
|
|
139
|
-
self.loop_stack.append((cond_bb, after_bb))
|
|
140
|
-
self.builder.branch(cond_bb)
|
|
141
|
-
self.builder.position_at_end(cond_bb)
|
|
142
|
-
cond_val = self.visit(node.condition)
|
|
143
|
-
if cond_val.type != ir.IntType(1):
|
|
144
|
-
cond_val = self.builder.icmp_signed('!=', cond_val, ir.Constant(self.int32, 0), name="loopcond")
|
|
145
|
-
self.builder.cbranch(cond_val, body_bb, after_bb)
|
|
146
|
-
self.builder.position_at_end(body_bb)
|
|
147
|
-
for stmt in node.body:
|
|
148
|
-
self.visit(stmt)
|
|
149
|
-
self.builder.branch(cond_bb) # Loop back
|
|
150
|
-
self.builder.position_at_end(after_bb)
|
|
151
|
-
self.loop_stack.pop()
|
|
152
|
-
def visit_Repeat(self, node: Repeat):
|
|
153
|
-
count_val = self.visit(node.count)
|
|
154
|
-
import random
|
|
155
|
-
uid = random.randint(0, 10000)
|
|
156
|
-
i_ptr = self._alloca(f"_loop_i_{uid}")
|
|
157
|
-
self.builder.store(ir.Constant(self.int32, 0), i_ptr)
|
|
158
|
-
cond_bb = self.builder.append_basic_block(name="repeat.cond")
|
|
159
|
-
body_bb = self.builder.append_basic_block(name="repeat.body")
|
|
160
|
-
after_bb = self.builder.append_basic_block(name="repeat.after")
|
|
161
|
-
self.loop_stack.append((cond_bb, after_bb))
|
|
162
|
-
self.builder.branch(cond_bb)
|
|
163
|
-
self.builder.position_at_end(cond_bb)
|
|
164
|
-
curr_i = self.builder.load(i_ptr, name="i_load")
|
|
165
|
-
cmp = self.builder.icmp_signed('<', curr_i, count_val, name="loopcheck")
|
|
166
|
-
self.builder.cbranch(cmp, body_bb, after_bb)
|
|
167
|
-
self.builder.position_at_end(body_bb)
|
|
168
|
-
for stmt in node.body:
|
|
169
|
-
self.visit(stmt)
|
|
170
|
-
curr_i_Body = self.builder.load(i_ptr)
|
|
171
|
-
next_i = self.builder.add(curr_i_Body, ir.Constant(self.int32, 1), name="inc_i")
|
|
172
|
-
self.builder.store(next_i, i_ptr)
|
|
173
|
-
self.builder.branch(cond_bb)
|
|
174
|
-
self.builder.position_at_end(after_bb)
|
|
175
|
-
self.loop_stack.pop()
|
|
176
|
-
def visit_FunctionDef(self, node: FunctionDef):
|
|
177
|
-
arg_types = [self.int32] * len(node.args)
|
|
178
|
-
arg_types = []
|
|
179
|
-
for arg in node.args:
|
|
180
|
-
name, _, hint = arg # arg is tuple
|
|
181
|
-
if True: # FORCE ALL ARGS TO STRINGS FOR SHELL LITE (Phase 7 Fix)
|
|
182
|
-
arg_types.append(self.char_ptr)
|
|
183
|
-
else:
|
|
184
|
-
arg_types.append(self.int32)
|
|
185
|
-
func_ty = ir.FunctionType(self.int32, arg_types) # Return int32 (or pointer casted)
|
|
186
|
-
func = ir.Function(self.module, func_ty, name=node.name)
|
|
187
|
-
old_builder = self.builder
|
|
188
|
-
block = func.append_basic_block(name="entry")
|
|
189
|
-
self.builder = ir.IRBuilder(block)
|
|
190
|
-
self.scopes.append({}) # New scope
|
|
191
|
-
for i, arg in enumerate(func.args):
|
|
192
|
-
arg_name = node.args[i][0]
|
|
193
|
-
arg.name = arg_name
|
|
194
|
-
ptr = self.builder.alloca(arg.type, name=arg_name)
|
|
195
|
-
self.builder.store(arg, ptr)
|
|
196
|
-
self.scopes[-1][arg_name] = ptr
|
|
197
|
-
for stmt in node.body:
|
|
198
|
-
self.visit(stmt)
|
|
199
|
-
if not self.builder.block.is_terminated:
|
|
200
|
-
self.builder.ret(ir.Constant(self.int32, 0))
|
|
201
|
-
self.scopes.pop()
|
|
202
|
-
self.builder = old_builder
|
|
203
|
-
def visit_Return(self, node: Return):
|
|
204
|
-
val = self.visit(node.value)
|
|
205
|
-
if val.type == self.char_ptr:
|
|
206
|
-
val = self.builder.ptrtoint(val, self.int32)
|
|
207
|
-
self.builder.ret(val)
|
|
208
|
-
def visit_Call(self, node: Call):
|
|
209
|
-
if node.name in self.module.globals:
|
|
210
|
-
func = self.module.globals[node.name]
|
|
211
|
-
elif node.name == 'read':
|
|
212
|
-
if len(node.args) > 0:
|
|
213
|
-
return self.visit_FileRead(FileRead(node.args[0]))
|
|
214
|
-
else:
|
|
215
|
-
return ir.Constant(self.int32, 0)
|
|
216
|
-
else:
|
|
217
|
-
print(f"Warning: Function {node.name} not found")
|
|
218
|
-
return ir.Constant(self.int32, 0)
|
|
219
|
-
args = [self.visit(a) for a in node.args]
|
|
220
|
-
return self.builder.call(func, args, name="calltmp")
|
|
221
|
-
def visit_Assign(self, node: Assign):
|
|
222
|
-
value = self.visit(node.value)
|
|
223
|
-
scope = self._get_scope()
|
|
224
|
-
if node.name not in scope:
|
|
225
|
-
ptr = self._alloca(node.name, typ=value.type)
|
|
226
|
-
scope[node.name] = ptr
|
|
227
|
-
else:
|
|
228
|
-
ptr = scope[node.name]
|
|
229
|
-
self.builder.store(value, ptr)
|
|
230
|
-
return value
|
|
231
|
-
def visit_Execute(self, node: Execute):
|
|
232
|
-
cmd = self.visit(node.code)
|
|
233
|
-
self.builder.call(self.system, [cmd])
|
|
234
|
-
return ir.Constant(self.int32, 0)
|
|
235
|
-
def visit_Stop(self, node: Stop):
|
|
236
|
-
if not self.loop_stack:
|
|
237
|
-
print("Error: stop used outside of loop")
|
|
238
|
-
return
|
|
239
|
-
after_bb = self.loop_stack[-1][1]
|
|
240
|
-
self.builder.branch(after_bb)
|
|
241
|
-
dead_bb = self.builder.append_basic_block(name="dead")
|
|
242
|
-
self.builder.position_at_end(dead_bb)
|
|
243
|
-
def visit_Skip(self, node: Skip):
|
|
244
|
-
if not self.loop_stack:
|
|
245
|
-
print("Error: skip used outside of loop")
|
|
246
|
-
return
|
|
247
|
-
cond_bb = self.loop_stack[-1][0]
|
|
248
|
-
self.builder.branch(cond_bb)
|
|
249
|
-
dead_bb = self.builder.append_basic_block(name="dead")
|
|
250
|
-
self.builder.position_at_end(dead_bb)
|
|
251
|
-
def _get_stdin_handle(self):
|
|
252
|
-
return self.builder.call(self.get_stdin, [ir.Constant(self.int32, 0)])
|
|
253
|
-
def visit_Input(self, node: Input):
|
|
254
|
-
buffer_len = ir.Constant(self.int32, 256)
|
|
255
|
-
buffer = self.builder.call(self.malloc, [buffer_len], name="input_buf")
|
|
256
|
-
stdin = self._get_stdin_handle()
|
|
257
|
-
self.builder.call(self.fgets, [buffer, buffer_len, stdin])
|
|
258
|
-
return buffer
|
|
259
|
-
def visit_FileWrite(self, node: FileWrite):
|
|
260
|
-
path = self.visit(node.path)
|
|
261
|
-
content = self.visit(node.content)
|
|
262
|
-
mode = self._get_string_constant("w")
|
|
263
|
-
fp = self.builder.call(self.fopen, [path, mode], name="fp")
|
|
264
|
-
length = self.builder.call(self.strlen, [content])
|
|
265
|
-
self.builder.call(self.fwrite, [content, ir.Constant(self.int32, 1), length, fp])
|
|
266
|
-
self.builder.call(self.fclose, [fp])
|
|
267
|
-
return ir.Constant(self.int32, 0)
|
|
268
|
-
def visit_FileRead(self, node: FileRead):
|
|
269
|
-
path = self.visit(node.path)
|
|
270
|
-
mode = self._get_string_constant("rb") # Binary to avoid text translation issues? Or "r"
|
|
271
|
-
fp = self.builder.call(self.fopen, [path, mode], name="fp")
|
|
272
|
-
self.builder.call(self.fseek, [fp, ir.Constant(self.int32, 0), ir.Constant(self.int32, 2)])
|
|
273
|
-
size = self.builder.call(self.ftell, [fp], name="fsize")
|
|
274
|
-
self.builder.call(self.rewind, [fp])
|
|
275
|
-
alloc_size = self.builder.add(size, ir.Constant(self.int32, 1))
|
|
276
|
-
buffer = self.builder.call(self.malloc, [alloc_size], name="fbuf")
|
|
277
|
-
self.builder.call(self.fread, [buffer, ir.Constant(self.int32, 1), size, fp])
|
|
278
|
-
null_term_ptr = self.builder.gep(buffer, [size])
|
|
279
|
-
self.builder.store(ir.Constant(ir.IntType(8), 0), null_term_ptr)
|
|
280
|
-
self.builder.call(self.fclose, [fp])
|
|
281
|
-
return buffer
|
|
282
|
-
def visit_VarAccess(self, node: VarAccess):
|
|
283
|
-
scope = self._get_scope()
|
|
284
|
-
if node.name in scope:
|
|
285
|
-
ptr = scope[node.name]
|
|
286
|
-
return self.builder.load(ptr, name=node.name)
|
|
287
|
-
else:
|
|
288
|
-
raise Exception(f"Variable '{node.name}' not defined")
|
|
289
|
-
def _get_string_constant(self, text):
|
|
290
|
-
text += '\0'
|
|
291
|
-
if text in self.str_constants:
|
|
292
|
-
return self.str_constants[text]
|
|
293
|
-
byte_arr = bytearray(text.encode("utf8"))
|
|
294
|
-
c_str_ty = ir.ArrayType(ir.IntType(8), len(byte_arr))
|
|
295
|
-
global_var = ir.GlobalVariable(self.module, c_str_ty, name=f".str_{len(self.str_constants)}")
|
|
296
|
-
global_var.linkage = 'internal'
|
|
297
|
-
global_var.global_constant = True
|
|
298
|
-
global_var.initializer = ir.Constant(c_str_ty, byte_arr)
|
|
299
|
-
ptr = self.builder.bitcast(global_var, self.char_ptr)
|
|
300
|
-
self.str_constants[text] = ptr
|
|
301
|
-
return ptr
|
|
302
|
-
def visit_Print(self, node: Print):
|
|
303
|
-
value = self.visit(node.expression)
|
|
304
|
-
if value.type == self.char_ptr:
|
|
305
|
-
fmt_str = self._get_string_constant("%s\n")
|
|
306
|
-
self.builder.call(self.printf, [fmt_str, value])
|
|
307
|
-
else:
|
|
308
|
-
if value.type != self.int32:
|
|
309
|
-
pass
|
|
310
|
-
fmt_str = self._get_string_constant("%d\n")
|
|
311
|
-
self.builder.call(self.printf, [fmt_str, value])
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|