Ejemplo n.º 1
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
Ejemplo n.º 2
0
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
Ejemplo n.º 3
0
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
Ejemplo n.º 4
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
Ejemplo n.º 5
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
Ejemplo n.º 6
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
Ejemplo n.º 7
0
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
Ejemplo n.º 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
Ejemplo n.º 9
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
Ejemplo n.º 10
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))
Ejemplo n.º 11
0
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)