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 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 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 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 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 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 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
from c_int import Int from c_pointer import Pointer from c_struct import Struct from c_union import Union from globals_consts import cname from c_double import Double from c_complex import Complex from c_void import Void from c_function import Function types = { 'int': Int(), 'char': Int(), 'double': Double(), 'complex': Complex(), 'void': Void(), 'float': Double() } 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
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 cast(self, ot, itemps, otemps): if type(ot) == Pointer: return f'scoreboard players operation {otemps[0]} {NAMESPACE} = {itemps[0]} {NAMESPACE}\n' return Int.cast(None, ot, itemps, otemps)
def binary(self, op, in1, in2, oval): # in1 op= in2 return Int.binary(None, op, in1, in2, oval)