예제 #1
0
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
예제 #2
0
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
예제 #3
0
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
예제 #4
0
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()
예제 #5
0
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
예제 #6
0
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
예제 #7
0
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
예제 #8
0
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
예제 #9
0
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
예제 #10
0
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
예제 #11
0
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))
예제 #12
0
 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)
예제 #13
0
 def binary(self, op, in1, in2, oval):  # in1 op= in2
     return Int.binary(None, op, in1, in2, oval)