コード例 #1
0
ファイル: funccall_expr.py プロジェクト: Command-Master/MCCC
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
コード例 #2
0
ファイル: compound_expr.py プロジェクト: Command-Master/MCCC
def compound_expression(copy_strings, expression, target, variables_name,
                        vtypes):
    from expression import generate_expression
    code = ''
    pausable = expression.block_items[:-1]
    returns = 'Return' in str(pausable)  # lolol
    breaks = 'Break' in str(pausable)  # lolol
    gotos = 'Goto' in str(pausable)  # lolol
    to_free = []
    clocals = 0
    for e in expression.block_items:
        if cname(e) == 'Decl':
            name = e.name
            ctype = e.type
            vtypes[name] = get_type(ctype)
            cvals = []
            for _ in range(vtypes[name].size):
                cvals.append(create_local())
                clocals += 1
            variables_name[name] = cvals
            if cname(ctype) == 'ArrayDecl':
                alloc_size = int(ctype.dim.value)
                assert alloc_size < 1024, 'Too big local array, make it global!'
                code += f'''data modify storage {NAMESPACE}:main temp set from storage {NAMESPACE}:main alloc[{{used:0}}].index
execute store result score $r0 {NAMESPACE} run data get storage {NAMESPACE}:main temp
function {NAMESPACE}:tree/mark_used
scoreboard players operation {cvals[0]} {NAMESPACE} = $r0 {NAMESPACE}
scoreboard players operation {cvals[0]} {NAMESPACE} *= $1024 {NAMESPACE}
scoreboard players add {cvals[0]} {NAMESPACE} 536870912
'''
                to_free.append(cvals[0])
    if not (returns or breaks or gotos):
        for e in expression.block_items:
            c1, t1, tt1 = generate_expression([], e, vtypes, variables_name,
                                              copy_strings, True)
            code += c1
            if tt1 is not None:
                for ttt in tt1:
                    used_temps.remove(ttt)
    else:
        for e in expression.block_items:
            cf = get_temp_func()
            cff = open(f'{cf}.mcfunction', 'w')
            c1, t1, tt1 = generate_expression([], e, vtypes, variables_name,
                                              copy_strings, True)
            cff.write(c1)
            if tt1 is not None:
                for ttt in tt1:
                    used_temps.remove(ttt)
            code += f'execute if score $returned {NAMESPACE} matches 0 if score $broken {NAMESPACE} matches 0 run function {NAMESPACE}:{cf}\n'
    if target is None:
        target = []
    remove_locals(clocals)
    for tof in to_free:
        code += f'scoreboard players operation $index {NAMESPACE} = {tof} {NAMESPACE}\n'
        code += f'function {NAMESPACE}:tree/free\n'
    return code, Void(), target
コード例 #3
0
ファイル: c_double.py プロジェクト: Command-Master/MCCC
 def cast(self, ot, itemps, otemps):
     if type(ot) == Double:
         return f'scoreboard players operation {otemps[0]} {NAMESPACE} = {itemps[0]} {NAMESPACE}\n'
     if cname(ot) == 'Int':
         return f'scoreboard players operation $val {NAMESPACE} = {itemps[0]} {NAMESPACE}\nfunction {NAMESPACE}:f2i\nscoreboard players operation {otemps[0]} {NAMESPACE} = $out {NAMESPACE}\n'
     if cname(ot) == 'Pointer':
         return f'scoreboard players operation $val {NAMESPACE} = {itemps[0]} {NAMESPACE}\nfunction {NAMESPACE}:f2i\nscoreboard players operation {otemps[0]} {NAMESPACE} = $out {NAMESPACE}\nscoreboard players operation {otemps[0]} {NAMESPACE} *= ${ot.ptr.size} {NAMESPACE}\n'
     if cname(ot) == 'Complex':
         return f'scoreboard players operation {otemps[0]} {NAMESPACE} = {itemps[0]} {NAMESPACE}\nscoreboard players set {otemps[1]} {NAMESPACE} 0\n'
     raise NotImplementedError(ot)
コード例 #4
0
def generate_head(vars, store, vtypes):
    code = ''
    code += f'gamerule maxCommandChainLength 200000\n'
    code += f'scoreboard objectives add {NAMESPACE} dummy\n' \
            f'scoreboard players set $-1 {NAMESPACE} -1\n'
    code += f'scoreboard players set $65536 {NAMESPACE} 65536\n'
    code += f'scoreboard players set $256 {NAMESPACE} 256\n'
    code += f'scoreboard players set $128 {NAMESPACE} 128\n'
    code += f'scoreboard players set $64 {NAMESPACE} 64\n'
    code += f'data modify storage {NAMESPACE}:main temps set value []\n'
    code += f'data modify storage {NAMESPACE}:main setjmp set value []\n'
    code += f'scoreboard players set $32 {NAMESPACE} 32\n'
    code += f'scoreboard players set $2 {NAMESPACE} 2\n'
    code += f'scoreboard players set $3 {NAMESPACE} 3\n'
    code += f'scoreboard players set $7 {NAMESPACE} 7\n'
    code += f'scoreboard players set $5 {NAMESPACE} 5\n'
    code += f'scoreboard players set $6 {NAMESPACE} 6\n'
    code += f'scoreboard players set $4 {NAMESPACE} 4\n'
    code += f'scoreboard players set $8 {NAMESPACE} 8\n'
    code += f'scoreboard players set $stackSize {NAMESPACE} 0\n'  # NOTE: multiplied by 1024
    code += f'data modify storage {NAMESPACE}:main lstack set value []\n'
    code += f'scoreboard players set $1 {NAMESPACE} 1\n'
    code += f'scoreboard players set $1024 {NAMESPACE} 1024\n'
    code += f'scoreboard players set $1073741824 {NAMESPACE} 1073741824\n'
    code += f'scoreboard players set $16777216 {NAMESPACE} 16777216\n'
    code += f'scoreboard players set $8388608 {NAMESPACE} 8388608\n'
    code += f'scoreboard players set $-inf {NAMESPACE} -2147483648\n'
    code += f'scoreboard players set $returned {NAMESPACE} 0\n'
    code += f'scoreboard players set $broken {NAMESPACE} 0\n'
    code += f'scoreboard players set $lasta {NAMESPACE} -1\n'
    code += f'scoreboard players set $lastb {NAMESPACE} -1\n'
    code += f'scoreboard players set $setjmpctr {NAMESPACE} -1\n'
    code += f'scoreboard players set $1048576 {NAMESPACE} 1048576\n'
    code += f'scoreboard players set $61681 {NAMESPACE} 61681\n'
    code += f'scoreboard players set $33554432 {NAMESPACE} 33554432\n'
    code += f'scoreboard players set $16777216 {NAMESPACE} 16777216\n'
    code += f'scoreboard players set $134217728 {NAMESPACE} 134217728\n'
    code += f'scoreboard players set $16 {NAMESPACE} 16\n'
    code += f'scoreboard players set $2097152 {NAMESPACE} 2097152\n'
    code += f'scoreboard players set $2048 {NAMESPACE} 2048\n'
    code += f'scoreboard players set $4096 {NAMESPACE} 4096\n'
    code += init_heap(HEAP_SIZE)
    for var_name in vars:
        var = vars[var_name]
        var_type = var.type
        vtypes[var_name] = get_type(var_type)
        store[var_name] = [get_temp() for _ in range(vtypes[var_name].size)]
        gtemps.extend(store[var_name])
        if cname(var_type) == 'ArrayDecl':
            size = int(var_type.dim.value)
            code += f'scoreboard players set {store[var_name][0]} {NAMESPACE} {get_position()}\n'
            register_space(size * vtypes[var_name].ptr.size)
        else:
            for varrr in store[var_name]:
                code += f'scoreboard players set {varrr} {NAMESPACE} 0\n'
    for var_name in vars:
        var = vars[var_name]
        if var.init is not None:
            code += generate_expression(store[var_name], var.init, vtypes, store, True, False)[0]
    return code
コード例 #5
0
ファイル: c_union.py プロジェクト: Command-Master/MCCC
 def update(self, types):
     for val in self.values:
         if cname(self.values[val]) == 'str':
             self.values[val] = types[val]
         else:
             self.values[val].update(types)
     self.size = max(map(lambda x: x.size, self.values.values()))
コード例 #6
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()
コード例 #7
0
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
    if tt1 == 'Complex' and tt2 == 'Double':
        return t1
    if tt1 == 'Double' and tt2 == 'Int':
        return t1
    if tt1 == 'Complex' and tt2 == 'Int':
        return t1
    if tt1 == 'Void' or tt2 == 'Void':
        return t1
    raise NotImplementedError(t1, t2)
コード例 #8
0
 def cast(self, ot, itemps, otemps):
     if type(ot) == Int or (cname(ot) == 'Pointer' and ot.ptr.size == 1):
         return f'scoreboard players operation {otemps[0]} {NAMESPACE} = {itemps[0]} {NAMESPACE}\n'
     if cname(ot) == 'Pointer':
         return f'scoreboard players operation {otemps[0]} {NAMESPACE} = {itemps[0]} {NAMESPACE}\nscoreboard players operation {otemps[0]} {NAMESPACE} *= ${ot.ptr.size} {NAMESPACE}\n'
     code = ''
     if cname(ot) == 'Complex':
         ot = Double()
         code += f'scoreboard players set {otemps[1]} {NAMESPACE} 0\n'  # 0i
     if cname(ot) == 'Double':
         code += f'execute store result score $sign {NAMESPACE} if score {itemps[0]} {NAMESPACE} matches ..-1\n'
         code += f'execute if score {itemps[0]} {NAMESPACE} matches 0 run scoreboard players set {otemps[0]} {NAMESPACE} 0\n'  # * 1325400064
         code += f'execute if score {itemps[0]} {NAMESPACE} matches -2147483648 run scoreboard players set {otemps[0]} {NAMESPACE} -1325400064\n'  # * 1325400064
         code += f'scoreboard players operation $sig {NAMESPACE} = {itemps[0]} {NAMESPACE}\n'
         code += f'execute if score $sign {NAMESPACE} matches 1 run scoreboard players operation $sig {NAMESPACE} *= $-1 {NAMESPACE}\n'
         code += f'scoreboard players set $exp {NAMESPACE} 156\n'
         code += f'function {NAMESPACE}:norm_round_pack\n'
         code += f'scoreboard players operation {otemps[0]} {NAMESPACE} = $out {NAMESPACE}\n'
         return code
     print(ot, itemps, otemps)
     raise NotImplementedError(ot)
コード例 #9
0
def main():
    argparser = argparse.ArgumentParser(description='Compile C to a Minecraft datapack')
    argparser.add_argument('file', metavar='Cfile', type=pathlib.Path, help='Path to the C file')
    argparser.add_argument('target', metavar='target', type=pathlib.Path, help='Location to write functions in')
    argparser.add_argument('--preprop', dest='preprop', action='store_const', const=True, default=False,
                           help='Don\'t run the C preprocessor on the file')
    argparser.add_argument('--file-input', help='Take constant input from file', dest='finput', metavar='file',
                           default=False, type=pathlib.Path)
    program_args = argparser.parse_args()
    if program_args.preprop:
        preprocessed = open(program_args.file).read()
    else:
        preprocessed = subprocess.check_output(
            ['gcc', '-nostdinc', '-E', program_args.file, f'-I{os.path.dirname(os.path.abspath(__file__))}/libc']).decode()
    print(program_args.target)
    if program_args.finput:
        inp = list(reversed(program_args.finput.open('rb').read()))
    try:
        shutil.rmtree(program_args.target / 'functions')
    except IOError:
        pass
    os.mkdir(program_args.target / 'functions')
    os.mkdir(program_args.target / 'functions' / 'tree')
    copy_stdlib(program_args.target / 'functions')
    os.chdir(program_args.target / 'functions')
    parser = CParser()
    parsed = parser.parse(preprocessed)
    obj_name = {}
    vtypes = {}
    vars = {}
    methods = {}
    for global_definition in parsed.ext:
        if cname(global_definition) == 'Typedef':
            add_type(global_definition.name, get_type(global_definition.type, obj_name, vtypes))
        elif cname(global_definition) == 'Decl' and cname(global_definition.type) != 'FuncDecl':
            vars[global_definition.name] = global_definition
            global varaddr
        elif cname(global_definition) == 'Decl' and cname(global_definition.type) == 'FuncDecl':
            return_types[global_definition.name] = get_type(global_definition.type.type)
            arguments[global_definition.name] = parse_arguments(global_definition.type.args)
        elif cname(global_definition) == 'FuncDef':
            return_types[global_definition.decl.name] = get_type(global_definition.decl.type.type)
            arguments[global_definition.decl.name] = parse_arguments(global_definition.decl.type.args)
            # print(functions)
            methods[global_definition.decl.name] = global_definition
        else:
            print(cname(global_definition))
    update_types()
    file = open('main.mcfunction', 'w')
    file.write(generate_head(vars, obj_name, vtypes))
    for method in methods:
        f = open(f'method_{method.lower()}.mcfunction', 'w')
        set_rtype(return_types[method])
        args = methods[method].decl.type.args
        if args is None:
            args = []
        clear_used()
        reset_locals()
        j = 0
        for arg in args:
            if cname(arg) == 'EllipsisParam':
                j += 10
                for i in range(10): create_local()
                break
            var_type = arg.type
            vtypes[arg.name] = get_type(var_type)
            obj_name[arg.name] = [create_local() for i in range(get_type(arg.type).size)]
            j += vtypes[arg.name].size
        new_cid()
        f.write(generate_expression([], methods[method].body, vtypes, obj_name, False, True)[0])
        f.write(f'scoreboard players set $returned {NAMESPACE} 0')
        f.close()
    generate_trees()
    if program_args.finput:
        file.write(f'data modify storage {NAMESPACE}:main input set value {inp}\n')
    file.write(f'data modify storage {NAMESPACE}:main rec set value []\n')
    file.write(f'data modify storage {NAMESPACE}:main ibuffer set value []\n')

    for strg in stringss:
        for i, c in enumerate(stringss[strg]):
            # TODO: change it to direct access to the heap, as index is known in compile time.
            file.write(f'scoreboard players set $index {NAMESPACE} {strg + i}\n')
            file.write(f'scoreboard players set $value {NAMESPACE} {c}\n')
            file.write(f'function {NAMESPACE}:set_heap\n')
    file.write(f'function {NAMESPACE}:method_main\n')
    file.close()
    goto_postprocess()
    remove_zerolines()
    inline_oneline()
    make_pausable({'method_getc', 'method__get_setjmp'})
    remove_unused()
コード例 #10
0
def parse_arguments(args):
    if args is None:
        args = []
    return [get_type(a.type) for a in args if cname(a) != 'EllipsisParam']
コード例 #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 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)