sonnum/pysonnum/compiler.py
2025-09-16 23:16:48 +03:00

162 lines
No EOL
3.6 KiB
Python

from .sonnum import Sonnum
from .activity import Activity
import random
class SonnumCompiler:
def __init__(self):
self.sonnum = Sonnum(self) # {order: name}
self.activities = []
def list_activities(self):
print('ACTIVITY LISTING')
for activity in self.activities:
print(activity)
def list_bytecode(self):
print('BYTECODE LISTING')
for activity in self.activities:
print(list(activity.to_bytes()))
def add_activity(self, name, tick_start, tick_end, src_node, trg_node, operands):
a = Activity(self.sonnum, name, tick_start, tick_end, src_node, trg_node, operands)
self.activities.append(a)
def transpile_snm_to_py(self, snm_src):
return snm_src
py_src = []
for ln in snm_src.split('\n'):
tablevel = 0
while ln.startswith('\t'):
tablevel += 1
ln = ln[1:]
if ln.startswith(';'):
if ln.endswith('*'):
name = self.sanitize_operand(ln[1:-1])
ln = f"i_create_simple(self, self.sonnum, '{name}')"
elif ln.endswith('!'):
ticklen = self.sanitize_operand(ln[1:-1])
ln = f"i_end_tick(self, self.sonnum, {ticklen})"
elif ln.endswith('@'):
name = self.sanitize_operand(ln[1:-1])
ln = f"i_create_relay(self, self.sonnum, '{name}')"
elif '=>' in ln:
name_src, name_trg = ln[1:].split('=>')
ln = f"i_wire(self, self.sonnum, '{name_src}', '{name_trg}')"
elif '->' in ln:
name_src, name_trg = ln[1:].split('->')
ln = f"i_air(self, self.sonnum, '{name_src}', '{name_trg}')"
else:
if '; ' in ln:
tickdata, ln = ln[1:].split('; ',1)
if '-' in tickdata:
starttick, endtick = tickdata.split('-', 1)
else:
starttick = tickdata
endtick = starttick
starttick = self.sanitize_operand(starttick)
endtick = self.sanitize_operand(endtick)
lst = ln.split(' ')
src_node_name = lst.pop(0)
instr = lst.pop(0)
operands = [self.sanitize_operand(op) for op in lst]
ln = f"i_{instr}(self, self.sonnum, {starttick}, {endtick}, '{src_node_name}', "+', '.join(operands)+")"
else:
pass
ln = tablevel*'\t' + ln
py_src.append(ln)
else:
ln = tablevel*'\t' + ln
py_src.append(ln)
return '\n'.join(py_src)
def run_transpiled_code(self, py_src):
c = self
s = self.sonnum
exec(py_src)
def sort_activities(self):
new = []
to_delete = []
for activity in self.activities:
if activity.name == 'endtick':
new.append(activity)
to_delete.append(activity)
for activity in to_delete:
self.activities.remove(activity)
to_delete = []
for activity in self.activities:
if activity.name == 'create':
new.append(activity)
to_delete.append(activity)
for activity in to_delete:
self.activities.remove(activity)
to_delete = []
for activity in self.activities:
if activity.name in ('wire','air','pin'):
new.append(activity)
to_delete.append(activity)
for activity in to_delete:
self.activities.remove(activity)
self.activities.sort(key=lambda x: x.tick_start, reverse = False)
new.extend(self.activities)
self.activities = new
def compile_to_smnb(self, snm_src, fn):
py_src = self.transpile_snm_to_py(snm_src)
self.run_transpiled_code(py_src)
self.sort_activities()
self.list_activities()
bytecode = []
for activity in self.activities:
bytecode.append(activity.to_bytes())
with open(fn, 'wb') as fl:
fl.write(b''.join(bytecode))
#C = SonnumCompiler()
#snm = C.compile_to_smnb(TEST, '../zigsonnum/test.snmb')