from .sonnum import Sonnum from .activity import Activity from .soundnode import * 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): py_src = [] for ln in snm_src.split('\n'): tablevel = 0 while ln.startswith('\t'): tablevel += 1 ln = ln[1:] if ln.startswith(';'): if '=>' in ln: name_src, name_trg = ln[1:].split('=>') ln = f'{name_src}.act("link", 0, 0, {name_src}, {name_trg}, [0, 1])' elif '->' in ln: name_src, name_trg = ln[1:].split('->') ln = f'{name_src}.act("link", 0, 0, {name_src}, {name_trg}, [0, 2])' elif '=/>' in ln: name_src, name_trg = ln[1:].split('=/>') ln = f'{name_src}.act("unlink", 0, 0, {name_src}, {name_trg}, [0, 1])' elif '-/>' in ln: name_src, name_trg = ln[1:].split('-/>') ln = f'{name_src}.act("unlink", 0, 0, {name_src}, {name_trg}, [0, 2])' elif '>>' in ln: name_src, name_trg = ln[1:].split('>>') name_src, pin_src = name_src.split(':') name_trg, pin_trg = name_trg.split(':') ln = f'{name_src}.act("link", 0, 0, {name_src}, {name_trg}, [{pin_src}, {pin_trg}])' elif '::>' in ln: tickdata, cmd = ln[1:].split(' ',1) if '-' in tickdata: starttick, endtick = tickdata.split('-', 1) else: starttick = tickdata endtick = starttick name_src, name_trg = cmd.split('::>') name_src, pin_src, rangepair_src = name_src.split(':') pin_trg, rangepair_trg = name_trg.split(':') from_src, from_trg = rangepair_src.split('/') to_src, to_trg = rangepair_trg.split('/') ln = f'{name_src}.act("rerange", sec({starttick}), sec({endtick}), {name_src}, {name_src}, [{pin_src}, {pin_trg}, {from_src}, {from_trg}, {to_src}, {to_trg}])' elif ':>' in ln: tickdata, cmd = ln[1:].split(' ',1) if '-' in tickdata: starttick, endtick = tickdata.split('-', 1) else: starttick = tickdata endtick = starttick name_src, pin_trg = cmd.split(':>') name_src, pin_src = name_src.split(':') ln = f'{name_src}.act("copy", sec({starttick}), sec({endtick}), {name_src}, None, [{pin_src}, {pin_trg}])' else: ln = ln[1:] tickdata, cmd = ln.split(' ',1) if '-' in tickdata: starttick, endtick = tickdata.split('-', 1) else: starttick = tickdata endtick = starttick cmdcore, cmdargs = cmd.split('(', 1) cmdargs = cmdargs[:-1] cmdparts = cmdcore.split('.') operand = cmdparts.pop(-1) nodenames = '.'.join(cmdparts) print(operand, nodenames) if '>' in nodenames: src_nodename, trg_nodename = nodenames.split('>') else: src_nodename = nodenames trg_nodename = nodenames if operand.startswith('@'): operand = operand[1:] ln = f'{src_nodename}.{operand}(sec({starttick}), sec({endtick}), [{cmdargs}])' else: ln = f'{src_nodename}.act("{operand}", sec({starttick}), sec({endtick}), {src_nodename}, {trg_nodename}, [{cmdargs}])' ln = tablevel*'\t' + ln py_src.append(ln) else: ln = tablevel*'\t' + ln py_src.append(ln) print('\n'.join(py_src)) 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')