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 cast(self, ot, itemps, otemps): if type(ot) == Double: return f'scoreboard players operation {otemps[0]} {NAMESPACE} = {itemps[0]} {NAMESPACE}\n' if cname(ot) == 'Int': return f'scoreboard players operation $val {NAMESPACE} = {itemps[0]} {NAMESPACE}\nfunction {NAMESPACE}:f2i\nscoreboard players operation {otemps[0]} {NAMESPACE} = $out {NAMESPACE}\n' if cname(ot) == 'Pointer': return f'scoreboard players operation $val {NAMESPACE} = {itemps[0]} {NAMESPACE}\nfunction {NAMESPACE}:f2i\nscoreboard players operation {otemps[0]} {NAMESPACE} = $out {NAMESPACE}\nscoreboard players operation {otemps[0]} {NAMESPACE} *= ${ot.ptr.size} {NAMESPACE}\n' if cname(ot) == 'Complex': return f'scoreboard players operation {otemps[0]} {NAMESPACE} = {itemps[0]} {NAMESPACE}\nscoreboard players set {otemps[1]} {NAMESPACE} 0\n' raise NotImplementedError(ot)
def generate_head(vars, store, vtypes): code = '' code += f'gamerule maxCommandChainLength 200000\n' code += f'scoreboard objectives add {NAMESPACE} dummy\n' \ f'scoreboard players set $-1 {NAMESPACE} -1\n' code += f'scoreboard players set $65536 {NAMESPACE} 65536\n' code += f'scoreboard players set $256 {NAMESPACE} 256\n' code += f'scoreboard players set $128 {NAMESPACE} 128\n' code += f'scoreboard players set $64 {NAMESPACE} 64\n' code += f'data modify storage {NAMESPACE}:main temps set value []\n' code += f'data modify storage {NAMESPACE}:main setjmp set value []\n' code += f'scoreboard players set $32 {NAMESPACE} 32\n' code += f'scoreboard players set $2 {NAMESPACE} 2\n' code += f'scoreboard players set $3 {NAMESPACE} 3\n' code += f'scoreboard players set $7 {NAMESPACE} 7\n' code += f'scoreboard players set $5 {NAMESPACE} 5\n' code += f'scoreboard players set $6 {NAMESPACE} 6\n' code += f'scoreboard players set $4 {NAMESPACE} 4\n' code += f'scoreboard players set $8 {NAMESPACE} 8\n' code += f'scoreboard players set $stackSize {NAMESPACE} 0\n' # NOTE: multiplied by 1024 code += f'data modify storage {NAMESPACE}:main lstack set value []\n' code += f'scoreboard players set $1 {NAMESPACE} 1\n' code += f'scoreboard players set $1024 {NAMESPACE} 1024\n' code += f'scoreboard players set $1073741824 {NAMESPACE} 1073741824\n' code += f'scoreboard players set $16777216 {NAMESPACE} 16777216\n' code += f'scoreboard players set $8388608 {NAMESPACE} 8388608\n' code += f'scoreboard players set $-inf {NAMESPACE} -2147483648\n' code += f'scoreboard players set $returned {NAMESPACE} 0\n' code += f'scoreboard players set $broken {NAMESPACE} 0\n' code += f'scoreboard players set $lasta {NAMESPACE} -1\n' code += f'scoreboard players set $lastb {NAMESPACE} -1\n' code += f'scoreboard players set $setjmpctr {NAMESPACE} -1\n' code += f'scoreboard players set $1048576 {NAMESPACE} 1048576\n' code += f'scoreboard players set $61681 {NAMESPACE} 61681\n' code += f'scoreboard players set $33554432 {NAMESPACE} 33554432\n' code += f'scoreboard players set $16777216 {NAMESPACE} 16777216\n' code += f'scoreboard players set $134217728 {NAMESPACE} 134217728\n' code += f'scoreboard players set $16 {NAMESPACE} 16\n' code += f'scoreboard players set $2097152 {NAMESPACE} 2097152\n' code += f'scoreboard players set $2048 {NAMESPACE} 2048\n' code += f'scoreboard players set $4096 {NAMESPACE} 4096\n' code += init_heap(HEAP_SIZE) for var_name in vars: var = vars[var_name] var_type = var.type vtypes[var_name] = get_type(var_type) store[var_name] = [get_temp() for _ in range(vtypes[var_name].size)] gtemps.extend(store[var_name]) if cname(var_type) == 'ArrayDecl': size = int(var_type.dim.value) code += f'scoreboard players set {store[var_name][0]} {NAMESPACE} {get_position()}\n' register_space(size * vtypes[var_name].ptr.size) else: for varrr in store[var_name]: code += f'scoreboard players set {varrr} {NAMESPACE} 0\n' for var_name in vars: var = vars[var_name] if var.init is not None: code += generate_expression(store[var_name], var.init, vtypes, store, True, False)[0] return code
def update(self, types): for val in self.values: if cname(self.values[val]) == 'str': self.values[val] = types[val] else: self.values[val].update(types) self.size = max(map(lambda x: x.size, self.values.values()))
def get_type(var_type, vs=None, vt=None, allow_unprocessed=False): while cname(var_type) == 'Decl': var_type = var_type.type if cname(var_type) in ['ArrayDecl', 'PtrDecl']: return Pointer(get_type(var_type.type)) elif cname(var_type) == 'TypeDecl' and cname( var_type.type) == 'IdentifierType': name = ' '.join(var_type.type.names) if allow_unprocessed and name not in types: return name return types[name] elif cname(var_type) == 'TypeDecl' and cname(var_type.type) == 'Enum': for i, val in enumerate(var_type.type.values): vt[val.name] = Int() vs[val.name] = [f'${i}'] types[f'enum {var_type.type.name}'] = Int() return Int() elif cname(var_type) == 'TypeDecl' and cname(var_type.type) == 'Struct': if var_type.type.decls is not None: things = {} for val in var_type.type.decls: things[val.name] = get_type(val.type, allow_unprocessed=True) ty = Struct(things) types[f'struct {var_type.type.name}'] = ty return ty else: return f'struct {var_type.type.name}' elif cname(var_type) == 'Union': things = {} for val in var_type.decls: things[val.name] = get_type(val.type, allow_unprocessed=True) return Union(things) elif cname(var_type) == 'FuncDecl': return Function([get_type(x.type) for x in var_type.args.params], get_type(var_type.type)) print(var_type) print(var_type.coord) raise NotImplementedError()
def cast(t1, t2): t1, t2 = sorted([t1, t2], key=cname) # hahaha sort go brrr tt1, tt2 = cname(t1), cname(t2) if tt1 == tt2: return t1 if tt1 == 'Int' and tt2 == 'Pointer': return t2 if tt1 == 'Char' and tt2 == 'Int': return t2 if tt1 == 'Complex' and tt2 == 'Pointer': return t2 if tt1 == 'Complex' and tt2 == 'Double': return t1 if tt1 == 'Double' and tt2 == 'Int': return t1 if tt1 == 'Complex' and tt2 == 'Int': return t1 if tt1 == 'Void' or tt2 == 'Void': return t1 raise NotImplementedError(t1, t2)
def cast(self, ot, itemps, otemps): if type(ot) == Int or (cname(ot) == 'Pointer' and ot.ptr.size == 1): return f'scoreboard players operation {otemps[0]} {NAMESPACE} = {itemps[0]} {NAMESPACE}\n' if cname(ot) == 'Pointer': return f'scoreboard players operation {otemps[0]} {NAMESPACE} = {itemps[0]} {NAMESPACE}\nscoreboard players operation {otemps[0]} {NAMESPACE} *= ${ot.ptr.size} {NAMESPACE}\n' code = '' if cname(ot) == 'Complex': ot = Double() code += f'scoreboard players set {otemps[1]} {NAMESPACE} 0\n' # 0i if cname(ot) == 'Double': code += f'execute store result score $sign {NAMESPACE} if score {itemps[0]} {NAMESPACE} matches ..-1\n' code += f'execute if score {itemps[0]} {NAMESPACE} matches 0 run scoreboard players set {otemps[0]} {NAMESPACE} 0\n' # * 1325400064 code += f'execute if score {itemps[0]} {NAMESPACE} matches -2147483648 run scoreboard players set {otemps[0]} {NAMESPACE} -1325400064\n' # * 1325400064 code += f'scoreboard players operation $sig {NAMESPACE} = {itemps[0]} {NAMESPACE}\n' code += f'execute if score $sign {NAMESPACE} matches 1 run scoreboard players operation $sig {NAMESPACE} *= $-1 {NAMESPACE}\n' code += f'scoreboard players set $exp {NAMESPACE} 156\n' code += f'function {NAMESPACE}:norm_round_pack\n' code += f'scoreboard players operation {otemps[0]} {NAMESPACE} = $out {NAMESPACE}\n' return code print(ot, itemps, otemps) raise NotImplementedError(ot)
def main(): argparser = argparse.ArgumentParser(description='Compile C to a Minecraft datapack') argparser.add_argument('file', metavar='Cfile', type=pathlib.Path, help='Path to the C file') argparser.add_argument('target', metavar='target', type=pathlib.Path, help='Location to write functions in') argparser.add_argument('--preprop', dest='preprop', action='store_const', const=True, default=False, help='Don\'t run the C preprocessor on the file') argparser.add_argument('--file-input', help='Take constant input from file', dest='finput', metavar='file', default=False, type=pathlib.Path) program_args = argparser.parse_args() if program_args.preprop: preprocessed = open(program_args.file).read() else: preprocessed = subprocess.check_output( ['gcc', '-nostdinc', '-E', program_args.file, f'-I{os.path.dirname(os.path.abspath(__file__))}/libc']).decode() print(program_args.target) if program_args.finput: inp = list(reversed(program_args.finput.open('rb').read())) try: shutil.rmtree(program_args.target / 'functions') except IOError: pass os.mkdir(program_args.target / 'functions') os.mkdir(program_args.target / 'functions' / 'tree') copy_stdlib(program_args.target / 'functions') os.chdir(program_args.target / 'functions') parser = CParser() parsed = parser.parse(preprocessed) obj_name = {} vtypes = {} vars = {} methods = {} for global_definition in parsed.ext: if cname(global_definition) == 'Typedef': add_type(global_definition.name, get_type(global_definition.type, obj_name, vtypes)) elif cname(global_definition) == 'Decl' and cname(global_definition.type) != 'FuncDecl': vars[global_definition.name] = global_definition global varaddr elif cname(global_definition) == 'Decl' and cname(global_definition.type) == 'FuncDecl': return_types[global_definition.name] = get_type(global_definition.type.type) arguments[global_definition.name] = parse_arguments(global_definition.type.args) elif cname(global_definition) == 'FuncDef': return_types[global_definition.decl.name] = get_type(global_definition.decl.type.type) arguments[global_definition.decl.name] = parse_arguments(global_definition.decl.type.args) # print(functions) methods[global_definition.decl.name] = global_definition else: print(cname(global_definition)) update_types() file = open('main.mcfunction', 'w') file.write(generate_head(vars, obj_name, vtypes)) for method in methods: f = open(f'method_{method.lower()}.mcfunction', 'w') set_rtype(return_types[method]) args = methods[method].decl.type.args if args is None: args = [] clear_used() reset_locals() j = 0 for arg in args: if cname(arg) == 'EllipsisParam': j += 10 for i in range(10): create_local() break var_type = arg.type vtypes[arg.name] = get_type(var_type) obj_name[arg.name] = [create_local() for i in range(get_type(arg.type).size)] j += vtypes[arg.name].size new_cid() f.write(generate_expression([], methods[method].body, vtypes, obj_name, False, True)[0]) f.write(f'scoreboard players set $returned {NAMESPACE} 0') f.close() generate_trees() if program_args.finput: file.write(f'data modify storage {NAMESPACE}:main input set value {inp}\n') file.write(f'data modify storage {NAMESPACE}:main rec set value []\n') file.write(f'data modify storage {NAMESPACE}:main ibuffer set value []\n') for strg in stringss: for i, c in enumerate(stringss[strg]): # TODO: change it to direct access to the heap, as index is known in compile time. file.write(f'scoreboard players set $index {NAMESPACE} {strg + i}\n') file.write(f'scoreboard players set $value {NAMESPACE} {c}\n') file.write(f'function {NAMESPACE}:set_heap\n') file.write(f'function {NAMESPACE}:method_main\n') file.close() goto_postprocess() remove_zerolines() inline_oneline() make_pausable({'method_getc', 'method__get_setjmp'}) remove_unused()
def parse_arguments(args): if args is None: args = [] return [get_type(a.type) for a in args if cname(a) != 'EllipsisParam']
def generate_expression(target, expression, vtypes, variables_name, copy_strings=False, ignore_output=False): if not ignore_output: if cname(expression) == 'ID': return id_expression(expression, target, variables_name, vtypes) elif cname(expression) == 'Constant': if expression.type == 'int': return parse_int(expression, target) elif expression.type == 'char': return parse_char(expression, target) elif expression.type == 'string': return parse_string_const(copy_strings, expression, target) elif expression.type == 'double': return parse_double(expression, target) elif cname(expression) == 'InitList': assert copy_strings code = '' types = [] ttes = [] for expr in expression.exprs: c1, t1, tt1 = generate_expression(None, expr, vtypes, variables_name, True, False) types.append(t1) ttes.extend(tt1) code += c1 code += f'scoreboard players operation $index {NAMESPACE} = {target[0]} {NAMESPACE}\n' for co, c in enumerate(ttes): code += f'scoreboard players operation $value {NAMESPACE} = {c} {NAMESPACE}\n' code += f'function {NAMESPACE}:set_heap\n' code += f'scoreboard players add $index {NAMESPACE} 1\n' return code, Pointer(Int()), target else: if cname(expression) == 'Compound': return compound_expression(copy_strings, expression, target, variables_name, vtypes) elif cname(expression) == 'For': return for_expression(copy_strings, expression, target, variables_name, vtypes) elif cname(expression) == 'If': return if_expression(copy_strings, expression, target, variables_name, vtypes) elif cname(expression) == 'While': return while_expression(copy_strings, expression, target, variables_name, vtypes) elif cname(expression) == 'Return': code = '' if expression.expr is not None: c1, t1, tt1 = generate_expression(None, expression.expr, vtypes, variables_name, copy_strings, False) code += c1 code += t1.cast(get_rtype(), tt1, [f'$r{i}' for i in range(get_rtype().size)]) for ttt in tt1: used_temps.remove(ttt) code += f'scoreboard players set $returned {NAMESPACE} 1\n' return code, Void(), [] elif cname(expression) == 'Break': code = f'scoreboard players set $broken {NAMESPACE} 1\n' return code, Void(), [] elif cname(expression) == 'Label': code = f'label {get_cid()}__{expression.name}\n' c1, t1, tt1 = generate_expression(None, expression.stmt, vtypes, variables_name, copy_strings, True) code += c1 return code, t1, tt1 elif cname(expression) == 'Goto': return f'goto {get_cid()}__{expression.name}\nscoreboard players set $returned {NAMESPACE} 1\n', Void( ), [] if cname(expression) == 'Decl': if expression.init is None: return '', Void(), [] code = '' dname = expression.name out_type = vtypes[dname] targets = variables_name[dname] c3, t3, tt3 = generate_expression(None, expression.init, vtypes, variables_name, copy_strings, False) for ttt in tt3: used_temps.remove(ttt) code += c3 code += t3.cast(out_type, tt3, targets) return code, Void(), [] if cname(expression) == 'Assignment': start, targets, end, out_type = assignment_target( expression.lvalue, vtypes, variables_name) if target is None: target = [get_temp() for _ in range(len(targets))] used_temps.extend(target) code = '' code += start c3, t3, tt3 = generate_expression(None, expression.rvalue, vtypes, variables_name, copy_strings, False) for ttt in tt3: used_temps.remove(ttt) if end != '': for ttt in targets: if ttt in used_temps: used_temps.remove(ttt) code += c3 if expression.op == '=': code += t3.cast(out_type, tt3, targets) if not ignore_output: for t1, t2 in zip(target, targets): code += f'scoreboard players operation {t1} {NAMESPACE} = {t2} {NAMESPACE}\n' elif expression.op in ['+=', '*=']: if not target: target = [get_temp() for _ in range(len(targets))] used_temps.extend(target) code += t3.cast(out_type, tt3, target) c4, t4, tt4 = generate_expression(None, expression.lvalue, vtypes, variables_name, copy_strings, False) code += c4 code += out_type.binary(expression.op[0], target, tt4, targets) for ttt in tt4: used_temps.remove(ttt) for t1, t2 in zip(target, targets): code += f'scoreboard players operation {t1} {NAMESPACE} = {t2} {NAMESPACE}\n' elif expression.op == '|=': if not target: target = [get_temp() for _ in range(len(targets))] used_temps.extend(target) code += t3.cast(out_type, tt3, target) n = int(expression.rvalue.value) assert n & (n - 1) == 0, 'Powers of two' code += f'scoreboard players operation $temp {NAMESPACE} = {targets[0]} {NAMESPACE}\n' code += f'scoreboard players operation $temp {NAMESPACE} /= ${n} {NAMESPACE}\n' code += f'scoreboard players operation $temp {NAMESPACE} %= %2 {NAMESPACE}\n' code += f'execute if score $temp {NAMESPACE} matches 0.. run scoreboard players add {targets[0]} {NAMESPACE} {n}\n' for t1, t2 in zip(target, targets): code += f'scoreboard players operation {t1} {NAMESPACE} = {t2} {NAMESPACE}\n' else: raise NotImplementedError(expression) code += end return code, out_type, target elif cname(expression) == 'TernaryOp': return ternary_expression(copy_strings, expression, target, variables_name, vtypes) elif cname(expression) == 'BinaryOp': return binary_expression(copy_strings, expression, target, variables_name, vtypes) elif cname(expression) == 'ExprList': code = '' for expr in expression.exprs[:-1]: c1, t1, tt1 = generate_expression([], expr, vtypes, variables_name, copy_strings, True) for ttt in tt1: used_temps.remove(ttt) code += c1 c1, t1, tt1 = generate_expression(target, expression.exprs[-1], vtypes, variables_name, copy_strings, False) code += c1 return code, t1, tt1 elif cname(expression) == 'Cast': c1, t1, tt1 = generate_expression(target, expression.expr, vtypes, variables_name, copy_strings, False) type_cast = get_type(expression.to_type.type) target = [get_temp() for _ in range(type_cast.size)] used_temps.extend(target) c1 += t1.cast(type_cast, tt1, target) for ttt in tt1: used_temps.remove(ttt) return c1, type_cast, target elif cname(expression) == 'UnaryOp': if expression.op == 'p++': return operator_unary(copy_strings, expression, variables_name, vtypes, '+', True) elif expression.op == 'p--': return operator_unary(copy_strings, expression, variables_name, vtypes, '-', True) elif expression.op == '++': return operator_unary(copy_strings, expression, variables_name, vtypes, '+', False) elif expression.op == '--': return operator_unary(copy_strings, expression, variables_name, vtypes, '-', False) elif expression.op == '-': c1, t1, tt1 = generate_expression(None, expression.expr, vtypes, variables_name, copy_strings, False) code = c1 code += t1.negate(tt1) return code, t1, tt1 elif expression.op == '!': c1, t1, tt1 = generate_expression(None, expression.expr, vtypes, variables_name, copy_strings, False) code = c1 targett = get_temp() used_temps.append(targett) code += t1.cast(Int(), tt1, [targett]) for ttt in tt1: used_temps.remove(ttt) code += f'execute store result score {targett} {NAMESPACE} if score {targett} {NAMESPACE} matches 0\n' return code, Int(), [targett] elif expression.op == '*': return dereference_unary(copy_strings, expression, variables_name, vtypes) elif expression.op == 'sizeof': tv = get_temp() used_temps.append(tv) return f'scoreboard players set {tv} {NAMESPACE} {get_type(expression.expr.type).size}\n', Int( ), [tv] elif expression.op == '&': return address_unary(expression, variables_name, vtypes) raise NotImplementedError(expression) elif cname(expression) == 'ArrayRef': c1, t1, tt1 = generate_expression( None, BinaryOp('+', expression.name, expression.subscript), vtypes, variables_name, copy_strings, False) code = c1 assert type(t1) == Pointer code += f'scoreboard players operation $index {NAMESPACE} = {tt1[0]} {NAMESPACE}\n' targets = [get_temp() for _ in range(t1.ptr.size)] used_temps.extend(targets) for t in targets: code += f'function {NAMESPACE}:get_heap\n' code += f'scoreboard players operation {t} {NAMESPACE} = $value {NAMESPACE}\n' code += f'scoreboard players add $index {NAMESPACE} 1\n' for ttt in tt1: used_temps.remove(ttt) return code, t1.ptr, targets elif cname(expression) == 'FuncCall': return funccall_expression(copy_strings, expression, variables_name, vtypes) elif cname(expression) == 'StructRef': if expression.type == '->': c1, t1, tt1 = generate_expression(None, expression.name, vtypes, variables_name, copy_strings, False) code = '' code += c1 for t in tt1: used_temps.remove(t) assert type(t1) == Pointer assert type(t1.ptr) == Struct out_type = t1.ptr.get_field_type(expression.field.name) offset = t1.ptr.get_field_offset(expression.field.name) target = [get_temp() for _ in range(out_type.size)] used_temps.extend(target) code += f'scoreboard players operation $index {NAMESPACE} = {tt1[0]} {NAMESPACE}\n' code += f'scoreboard players add $index {NAMESPACE} {offset}\n' for t in target: code += f'function {NAMESPACE}:get_heap\n' code += f'scoreboard players operation {t} {NAMESPACE} = $value {NAMESPACE}\n' code += f'scoreboard players add $index {NAMESPACE} 1\n' return code, out_type, target else: assert expression.type == '.' c1, t1, tt1 = generate_expression(None, expression.name, vtypes, variables_name, copy_strings, False) code = c1 assert type(t1) == Struct out_type = t1.get_field_type(expression.field.name) offset = t1.get_field_offset(expression.field.name) return_variables = tt1[offset:offset + out_type.size] for t in tt1: if t not in return_variables: used_temps.remove(t) return code, out_type, return_variables elif cname(expression) == 'EmptyStatement': return '', Void(), [] print(expression, get_cid()) raise NotImplementedError(cname(expression))
def assignment_target(target, vtypes, variables_name): from globals_consts import cname, BinaryOp, NAMESPACE from expression import generate_expression if cname(target) == 'ID': return '', variables_name[target.name], '', vtypes[target.name] elif cname(target) == 'ArrayRef': code = '' c, t, out = generate_expression(None, BinaryOp('+', target.name, target.subscript), vtypes, variables_name, False, False) if cname(t) != 'Pointer' or len(out) != 1: raise NotImplementedError(target) outtargs = [get_temp() for _ in range(t.ptr.size)] used_temps.extend(outtargs) code += c code += f'scoreboard players operation $index {NAMESPACE} = {out[0]} {NAMESPACE}\n' for target in outtargs: code += f'scoreboard players operation $value {NAMESPACE} = {target} {NAMESPACE}\n' code += f'function {NAMESPACE}:set_heap\n' code += f'scoreboard players add $index {NAMESPACE} 1\n' for tt in out: used_temps.remove(tt) return '', outtargs, code, t.ptr elif cname(target) == 'UnaryOp': if target.op == '*': code = '' c, t, out = generate_expression(None, target.expr, vtypes, variables_name, False, False) outtargs = [get_temp() for _ in range(t.ptr.size)] used_temps.extend(outtargs) if cname(t) != 'Pointer' or len(out) != 1: raise NotImplementedError(target) code += c code += f'scoreboard players operation $index {NAMESPACE} = {out[0]} {NAMESPACE}\n' for target in outtargs: code += f'scoreboard players operation $value {NAMESPACE} = {target} {NAMESPACE}\n' code += f'function {NAMESPACE}:set_heap\n' code += f'scoreboard players add $index {NAMESPACE} 1\n' for tt in out: used_temps.remove(tt) return '', outtargs, code, t.ptr elif cname(target) == 'StructRef': if target.type == '->': c1, t1, tt1 = generate_expression(None, target.name, vtypes, variables_name, False, False) code = '' code += c1 for t in tt1: used_temps.remove(t) assert type(t1) == Pointer assert type(t1.ptr) == Struct out_type = t1.ptr.get_field_type(target.field.name) offset = t1.ptr.get_field_offset(target.field.name) target = [get_temp() for _ in range(out_type.size)] used_temps.extend(target) code += f'scoreboard players operation $index {NAMESPACE} = {tt1[0]} {NAMESPACE}\n' code += f'scoreboard players add $index {NAMESPACE} {offset}\n' for t in target: code += f'scoreboard players operation $value {NAMESPACE} = {t} {NAMESPACE}\n' code += f'function {NAMESPACE}:set_heap\n' code += f'scoreboard players add $index {NAMESPACE} 1\n' return '', target, code, out_type elif target.type == '.': out_type = vtypes[target.name.name] print(out_type, target) out_typ = out_type.get_field_type(target.field.name) offset = out_type.get_field_offset(target.field.name) return_variables = variables_name[target.name.name][offset:offset + out_typ.size] return '', return_variables, '', out_typ print(target) raise NotImplementedError(cname(target), target)