def if_expression(copy_strings, expression, target, variables_name, vtypes): from expression import generate_expression code = '' c1, t1, tt1 = generate_expression(None, expression.cond, vtypes, variables_name, copy_strings, False) code += c1 tv = get_temp() used_temps.append(tv) code += t1.cast(Int(), tt1, [tv]) if_true = get_temp_func() if_true_f = open(f'{if_true}.mcfunction', 'w') c2, t2, tt2 = generate_expression(None, expression.iftrue, vtypes, variables_name, copy_strings, True) if expression.iffalse is not None: if_false = get_temp_func() if_false_f = open(f'{if_false}.mcfunction', 'w') c3, t3, tt3 = generate_expression(None, expression.iffalse, vtypes, variables_name, copy_strings, True) if_false_f.write(c3) if_false_f.close() if tt3 is not None: for ttt in tt3: used_temps.remove(ttt) code += f'execute if score {tv} {NAMESPACE} matches 0 run function {NAMESPACE}:{if_false}\n' if_true_f.write(c2) if_true_f.close() code += f'execute unless score {tv} {NAMESPACE} matches 0 run function {NAMESPACE}:{if_true}\n' used_temps.remove(tv) for ttt in tt1: used_temps.remove(ttt) for ttt in tt2: used_temps.remove(ttt) return code, Void(), target
def for_expression(copy_strings, expression, target, variables_name, vtypes): from expression import generate_expression code = '' if expression.init is not None: c1, t1, tt1 = generate_expression([], expression.init, vtypes, variables_name, copy_strings, True) code += c1 for ttt in tt1: used_temps.remove(ttt) temp_name = get_temp_func() code += f'function {NAMESPACE}:{temp_name}\n' new = open(f'{temp_name}.mcfunction', 'w') a, b, c = generate_expression([], expression.stmt, vtypes, variables_name, copy_strings, True) for t in c: used_temps.remove(t) if expression.cond is not None: nc, nt, temps = generate_expression(None, expression.cond, vtypes, variables_name, copy_strings, False) new.write(nc) t2 = get_temp_func() new.write( f'execute unless score {temps[0]} {NAMESPACE} matches 0 if score $broken {NAMESPACE} matches 0 run function {NAMESPACE}:{t2}\n' ) new.write( f'execute unless score {temps[0]} {NAMESPACE} matches 0 if score $returned {NAMESPACE} matches 0 if score $broken {NAMESPACE} matches 0 run function {NAMESPACE}:{temp_name}\n' ) for temp in temps: used_temps.remove(temp) f2 = open(f'{t2}.mcfunction', 'w') f2.write(a) if expression.next is not None: a, b, c = generate_expression(None, expression.next, vtypes, variables_name, copy_strings, True) for t in c: used_temps.remove(t) f2.write(a) f2.close() else: new.write(a) if expression.next is not None: a, b, c = generate_expression(None, expression.next, vtypes, variables_name, copy_strings, True) for t in c: used_temps.remove(t) new.write(a) new.write( f'execute if score $broken {NAMESPACE} matches 0 run function {NAMESPACE}:{temp_name}\n' ) new.close() if target is None: target = [] code += f'scoreboard players set $broken {NAMESPACE} 0\n' return code, Void(), target
def goto_postprocess(): labels = {} gotoers = {} for file in os.listdir('.'): if file == 'main.mcfunction': continue if os.path.isdir(file): continue content = open(file).read() m = re.findall(r'label (.*)', content) content = re.split(r'label .*', content) fname = file file = open(file, 'w') file.write(content[0].strip()) for a, b in zip(m, content[1:]): new_file = get_temp_func() file.write(f'\nfunction {NAMESPACE}:{new_file}') file.close() file = open(new_file + '.mcfunction', 'a') file.write(b.strip()) labels[a] = new_file file.write('\n') if len(m) != 0: gotoers[fname[:-len('.mcfunction')]] = file print(gotoers) while len(gotoers) > 0: ng = {} print(gotoers) for a in gotoers: c = get_callers(a) assert len(c) == 1, 'Too many callers for label' oc = c[0] c = c[0] + '.mcfunction' content = open(c).read().split(f'function {NAMESPACE}:{a}') assert len(content) == 2, 'Too many callers for label' file = open(c, 'w') file.write(content[0] + f'function {NAMESPACE}:{a}') file.close() new_file = get_temp_func() gotoers[a].write(f'\nfunction {NAMESPACE}:{new_file}') gotoers[a].close() file = open(new_file + '.mcfunction', 'w') file.write(content[1]) if not oc.startswith('method_'): ng[oc] = file gotoers = ng for file in os.listdir('.'): if file == 'main.mcfunction': continue if os.path.isdir(file): continue content = open(file).read() open(file, 'w').write( re.sub(r'goto (.*)', lambda a: f'function {NAMESPACE}:{labels[a.group(1)]}', content))
def binary_expression(copy_strings, expression, target, variables_name, vtypes): from expression import generate_expression c1, t1, tt1 = generate_expression(None, expression.left, vtypes, variables_name, copy_strings, False) c2, t2, tt2 = generate_expression(None, expression.right, vtypes, variables_name, copy_strings, False) for ttt in tt1: used_temps.remove(ttt) for ttt in tt2: used_temps.remove(ttt) ot = cast(t1, t2) rt = ot if expression.op in ['<', '>', '<=', '>=', '==', '!=', '&&']: rt = Int() if target is None or target == []: target = [get_temp() for _ in range(ot.size)] used_temps.extend(target) code = '' if expression.op in ['&&', '||']: if expression.op == '&&': code += c1 code += t1.cast(ot, tt1, target) f2 = get_temp_func() f2h = open(f'{f2}.mcfunction', 'w') f2h.write(c2) f2h.write(t2.cast(ot, tt2, target)) f2h.close() code += f'execute unless score {target[0]} {NAMESPACE} matches 0 run function {NAMESPACE}:{f2}\n' elif expression.op == '||': code += c1 code += t1.cast(ot, tt1, target) f2 = get_temp_func() f2h = open(f'{f2}.mcfunction', 'w') f2h.write(c2) f2h.write(t2.cast(ot, tt2, target)) f2h.close() code += f'execute if score {target[0]} {NAMESPACE} matches 0 run function {NAMESPACE}:{f2}\n' else: if ot == t1: code += c1 code += c2 code += t2.cast(ot, tt2, target) code += ot.binary(expression.op, tt1, target, target) else: code += c1 code += t1.cast(ot, tt1, target) code += c2 code += ot.binary(expression.op, target, tt2, target) return code, rt, target
def funccall_expression(copy_strings, expression, variables_name, vtypes): from expression import generate_expression arguments = [] code = '' # print(vtypes) direct = True if expression.name.name in vtypes: crtype = vtypes[expression.name.name].ptr.ret_type funcargs = vtypes[expression.name.name].ptr.args direct = False else: crtype = return_types[expression.name.name] funcargs = fargs[expression.name.name] if expression.args is not None: for i, expr in enumerate(expression.args.exprs): c1, t1, tt1 = generate_expression(None, expr, vtypes, variables_name, copy_strings, False) code += c1 if i < len(funcargs) and cname(funcargs[i]) != cname(t1): ctemps = [get_temp() for _ in range(funcargs[i].size)] code += t1.cast(funcargs[i], tt1, ctemps) arguments.extend(ctemps) used_temps.extend(ctemps) for arg in tt1: used_temps.remove(arg) else: arguments.extend(tt1) for arg in arguments: used_temps.remove(arg) code += save_temps(used_temps) code += save_locals(local_size()) for i, arg in enumerate(arguments): code += f'scoreboard players operation $l{i} {NAMESPACE} = {arg} {NAMESPACE}\n' if direct: code += f'function {NAMESPACE}:method_{expression.name.name.lower()}\n' else: if (crtype, tuple(funcargs)) not in functrees: functrees[(crtype, tuple(funcargs))] = get_temp_func() possibilities = list( filter( lambda x: return_types[x] == crtype and fargs[x] == funcargs, list(return_types))) assert len(possibilities), 'No function of matching type' if len(possibilities) == 1: functrees[(crtype, tuple(funcargs))] = possibilities[0] else: code += f'scoreboard players operation $func_id {NAMESPACE} = {variables_name[expression.name.name][0]} {NAMESPACE}\n' raise NotImplementedError() # print(possibilities) # print(return_types, crtype, fargs, funcargs) code += f'function {NAMESPACE}:method_{functrees[(crtype, tuple(funcargs))]}\n' code += unsave_temps(used_temps) code += unsave_locals(local_size()) targets = [get_temp() for _ in range(crtype.size)] used_temps.extend(targets) for i, t in enumerate(targets): code += f'scoreboard players operation {t} {NAMESPACE} = $r{i} {NAMESPACE}\n' return code, crtype, targets
def compound_expression(copy_strings, expression, target, variables_name, vtypes): from expression import generate_expression code = '' pausable = expression.block_items[:-1] returns = 'Return' in str(pausable) # lolol breaks = 'Break' in str(pausable) # lolol gotos = 'Goto' in str(pausable) # lolol to_free = [] clocals = 0 for e in expression.block_items: if cname(e) == 'Decl': name = e.name ctype = e.type vtypes[name] = get_type(ctype) cvals = [] for _ in range(vtypes[name].size): cvals.append(create_local()) clocals += 1 variables_name[name] = cvals if cname(ctype) == 'ArrayDecl': alloc_size = int(ctype.dim.value) assert alloc_size < 1024, 'Too big local array, make it global!' code += f'''data modify storage {NAMESPACE}:main temp set from storage {NAMESPACE}:main alloc[{{used:0}}].index execute store result score $r0 {NAMESPACE} run data get storage {NAMESPACE}:main temp function {NAMESPACE}:tree/mark_used scoreboard players operation {cvals[0]} {NAMESPACE} = $r0 {NAMESPACE} scoreboard players operation {cvals[0]} {NAMESPACE} *= $1024 {NAMESPACE} scoreboard players add {cvals[0]} {NAMESPACE} 536870912 ''' to_free.append(cvals[0]) if not (returns or breaks or gotos): for e in expression.block_items: c1, t1, tt1 = generate_expression([], e, vtypes, variables_name, copy_strings, True) code += c1 if tt1 is not None: for ttt in tt1: used_temps.remove(ttt) else: for e in expression.block_items: cf = get_temp_func() cff = open(f'{cf}.mcfunction', 'w') c1, t1, tt1 = generate_expression([], e, vtypes, variables_name, copy_strings, True) cff.write(c1) if tt1 is not None: for ttt in tt1: used_temps.remove(ttt) code += f'execute if score $returned {NAMESPACE} matches 0 if score $broken {NAMESPACE} matches 0 run function {NAMESPACE}:{cf}\n' if target is None: target = [] remove_locals(clocals) for tof in to_free: code += f'scoreboard players operation $index {NAMESPACE} = {tof} {NAMESPACE}\n' code += f'function {NAMESPACE}:tree/free\n' return code, Void(), target
def ternary_expression(copy_strings, expression, target, variables_name, vtypes): from expression import generate_expression code = '' c1, t1, tt1 = generate_expression(None, expression.cond, vtypes, variables_name, copy_strings, False) code += c1 tv = get_temp() used_temps.append(tv) code += t1.cast(Int(), tt1, [tv]) if_true = get_temp_func() if_false = get_temp_func() if_true_f = open(f'{if_true}.mcfunction', 'w') if_false_f = open(f'{if_false}.mcfunction', 'w') c2, t2, tt2 = generate_expression(None, expression.iffalse, vtypes, variables_name, copy_strings, False) c3, t3, tt3 = generate_expression(None, expression.iftrue, vtypes, variables_name, copy_strings, False) ot = cast(t2, t3) if target is None: target = [get_temp() for _ in range(ot.size)] used_temps.extend(target) if_true_f.write(c3) if len(target) != 0: if_true_f.write(t3.cast(ot, tt3, target)) if_false_f.write(c2) if len(target) != 0: if_false_f.write(t2.cast(ot, tt2, target)) if_true_f.close() if_false_f.close() used_temps.remove(tv) for ttt in tt1: used_temps.remove(ttt) for ttt in tt2: used_temps.remove(ttt) for ttt in tt3: used_temps.remove(ttt) code += f'execute if score {tv} {NAMESPACE} matches 0 run function {NAMESPACE}:{if_false}\n' code += f'execute unless score {tv} {NAMESPACE} matches 0 run function {NAMESPACE}:{if_true}\n' return code, ot, target
def while_expression(copy_strings, expression, target, variables_name, vtypes): from expression import generate_expression code = '' c1, t1, tt1 = generate_expression(None, expression.cond, vtypes, variables_name, copy_strings, False) code += c1 tv = get_temp() used_temps.append(tv) code += t1.cast(Int(), tt1, [tv]) loop = get_temp_func() loop_f = open(f'{loop}.mcfunction', 'w') if_true = get_temp_func() if_true_f = open(f'{if_true}.mcfunction', 'w') c2, t2, tt2 = generate_expression(None, expression.stmt, vtypes, variables_name, copy_strings, True) if_true_f.write(c2) if_true_f.write(f'function {NAMESPACE}:{loop}\n') if_true_f.close() code += f'execute unless score {tv} {NAMESPACE} matches 0 if score $returned {NAMESPACE} matches 0 if score $broken {NAMESPACE} matches 0 run function {NAMESPACE}:{if_true}\n' loop_f.write(code) loop_f.close() used_temps.remove(tv) for ttt in tt1: used_temps.remove(ttt) for ttt in tt2: used_temps.remove(ttt) return f'function {NAMESPACE}:{loop}\n' \ f'scoreboard players set $broken {NAMESPACE} 0\n', Void(), target