def parse_char(expression, target): if target is None: target = [get_temp()] used_temps.extend(target) v = parse_string(expression.value) return f'scoreboard players set {target[0]} {NAMESPACE} {ord(v)}\n', Int( ), 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 parse_double(expression, target): dval = float(expression.value) if target is None: target = [get_temp()] used_temps.extend(target) ival = struct.unpack('<I', struct.pack('<f', dval))[0] # hahaha eval struct return f'scoreboard players set {target[0]} {NAMESPACE} {ival}\n', Double( ), target
def parse_int(expression, target): if target is None: target = [get_temp()] used_temps.extend(target) v = expression.value if v.lower().startswith('0x'): v = int(v, 16) elif v.startswith('0'): v = int(v, 8) return f'scoreboard players set {target[0]} {NAMESPACE} {v}\n', Int( ), 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 id_expression(expression, target, variables_name, vtypes): if expression.name == 'I': out_type = Complex() if target is None: target = [get_temp() for _ in range(out_type.size)] used_temps.extend(target) return Complex().get_value(1j, target), Complex(), target elif expression.name == 'stdin': out_type = Int() if target is None: target = [get_temp() for _ in range(out_type.size)] used_temps.extend(target) return f'scoreboard players set {target[0]} {NAMESPACE} 0\n', Int( ), target else: if expression.name in vtypes: out_type = vtypes[expression.name] out_source = variables_name[expression.name] else: out_type = Pointer( Function(fargs[expression.name], return_types[expression.name])) if target is None: target = [get_temp()] used_temps.extend(target) return f'scoreboard players set {target[0]} {NAMESPACE} {list(return_types).index(expression.name)}\n', out_type, target if target is None: target = [get_temp() for _ in range(out_type.size)] used_temps.extend(target) return ''.join( f'scoreboard players operation {a} {NAMESPACE} = {b} {NAMESPACE}\n' for a, b in zip(target, out_source)), out_type, 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 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 parse_string_const(copy_strings, expression, target): if copy_strings: a = eval('b' + expression.value) code = '' a = list(a) # + [0] - initalized to 0 anyway, no need to specify this code += f'scoreboard players operation $index {NAMESPACE} = {target[0]} {NAMESPACE}\n' for co, c in enumerate(a): code += f'scoreboard players set $value {NAMESPACE} {c}\n' code += f'function {NAMESPACE}:set_heap\n' code += f'scoreboard players add $index {NAMESPACE} 1\n' return code, Pointer(Int()), target else: a = parse_string(expression.value).encode() # a = eval('b' + expression.value) if target is None: target = [get_temp()] used_temps.extend(target) code = f'scoreboard players set {target[0]} {NAMESPACE} {get_position()}\n' a = list(a) + [0] stringss[get_position()] = a register_space(len(a)) return code, Pointer(Int()), target
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)