def _generate_arguments(max_depth=None): # normal arguments num_args = random.randrange(4) args = [_generate_arg() for _ in range(num_args)] defaults = [ random.choice([generate_expression(max_depth=max_depth - 1)]) for _ in range(random.randrange(num_args + 1)) ] # starred args and kwargs kwarg = random.choice([_generate_arg()] + [None] * 4) vararg = random.choice([_generate_arg()] + [None] * 4) # keyword-only arguments num_kwonlyargs = random.randrange(3) kwonlyargs = [_generate_arg() for _ in range(num_kwonlyargs)] kw_defaults = [ random.choice([generate_expression(max_depth=max_depth - 1), None]) for _ in range(num_kwonlyargs) ] return ast.arguments(args=args, vararg=vararg, kwonlyargs=kwonlyargs, kwarg=kwarg, defaults=defaults, kw_defaults=kw_defaults)
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 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 generate_dict(max_depth=None): from expression import generate_expression length = random.randrange(MAX_LIST_LENGTH) keys = [ generate_expression(max_depth=max_depth - 1) for _ in range(length) ] values = [ generate_expression(max_depth=max_depth - 1) for _ in range(length) ] return ast.Dict(keys, values)
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 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 generate_tuple(max_depth=None): from expression import generate_expression length = random.randrange(MAX_LIST_LENGTH) elts = [ generate_expression(max_depth=max_depth - 1) for _ in range(length) ] return ast.Tuple(elts, ast.Load())
def generate_set(max_depth=None): from expression import generate_expression length = random.randrange(MAX_LIST_LENGTH) elts = [ generate_expression(max_depth=max_depth - 1) for _ in range(length) ] return ast.Set(elts)
def generate_augmented_assign(max_depth=None): value = generate_expression(max_depth=max_depth) target = generate_variable(max_depth=max_depth, ctx=ast.Store()) op = random.choice(binary_ops)() return ast.AugAssign(target, op, value)
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 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 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
def dereference_unary(copy_strings, expression, variables_name, vtypes): from expression import generate_expression c1, t1, tt1 = generate_expression(None, expression.expr, 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 ttt in tt1: used_temps.remove(ttt) 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' return code, t1.ptr, targets
def operator_unary(copy_strings, expression, variables_name, vtypes, op, pre): from expression import generate_expression code = '' c1, t1, tt1 = generate_expression(None, expression.expr, vtypes, variables_name, copy_strings, False) code += c1 start, targets, end, out_type = assignment_target(expression.expr, vtypes, variables_name) if end != '': for ttt in targets: if ttt in used_temps: used_temps.remove(ttt) code += start c2 = out_type.get_value(1, targets) code += c2 code += out_type.binary(op, tt1, targets, targets) code += end if not pre: for t1, t2 in zip(targets, tt1): code += f'scoreboard players operation {t2} {NAMESPACE} = {t1} {NAMESPACE}\n' return code, out_type, tt1
def generate_async_for(max_depth=None): target = generate_variable_or_tuple() iter = generate_expression(max_depth=max_depth) body = generate_block(max_depth=max_depth) orelse = random.choice([generate_block(max_depth=max_depth), []]) return ast.AsyncFor(target, iter, body, orelse)
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 generate_return(max_depth=None): return ast.Return(generate_expression(max_depth=max_depth - 1))
def generate_yield(max_depth=None): return ast.Expr(ast.Yield(generate_expression(max_depth=max_depth - 1)))
def generate_await(max_depth=None): return ast.Expr(ast.Await(generate_expression(max_depth=max_depth - 1)))
def generate_annotated_assign(max_depth=None): value = generate_expression(max_depth=max_depth) target = generate_variable(max_depth=max_depth, ctx=ast.Store()) annotation = generate_variable(max_depth=max_depth) return ast.AnnAssign(target, annotation, value, 1)
def generate_assert(max_depth=None): test = generate_expression(max_depth=max_depth) msg = random.choice([generate_string(), None]) return ast.Assert(test, msg)
def generate_assign(max_depth=None): value = generate_expression(max_depth=max_depth) targets = [ generate_variable_or_tuple(max_depth=max_depth, ctx=ast.Store()) ] return ast.Assign(targets, value)
def generate_while(max_depth=None): test = generate_expression(max_depth=max_depth) body = generate_block(max_depth=max_depth) orelse = random.choice([generate_block(max_depth=max_depth), []]) return ast.While(test, body, orelse)
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)
def _generate_with_item(max_depth=None): context_expr = generate_expression(max_depth=max_depth) optional_vars = generate_variable_or_tuple() return ast.withitem(context_expr, optional_vars)