Esempio n. 1
0
 def send_msg(regclass, is_tail_call=False):
     arity = rpc('K', 2)
     args = [['reg', 'X', i] for i in range(intpc(2))]
     msg = ['record/prenormalized', arity, args]
     ozpickle.normalize_record(msg)
     return OpCall(rpc(regclass, 1), [msg], is_tail_call=is_tail_call)
Esempio n. 2
0
def decode(opcode, arr, pc, ks):
    def rpc(regclass, delta):
        num = arr[pc+delta]
        if regclass == 'K':
            return ks[num]
        else:
            return ['reg', regclass, num]

    def intpc(delta):
        return arr[pc+delta]

    def pattern_match(regclass):
        value = rpc(regclass, 1)
        pattern_value = ks[intpc(2)]
        patterns = []
        target_pcs = []
        for _, _, (pattern, dpc) in ks[intpc(2)][2]:
            patterns.append(pattern)
            target_pcs.append(pc + 3 + dpc)
        return OpCondBranch(value, patterns, target_pcs)

    def cond_branch(dfalse, delse):
        base = pc + 4
        return OpCondBranch(rpc('X', 1),
                            [True, False],
                            [base, base + dfalse],
                            else_pc=base + delse)

    def equals_integer():
        base = pc + 4
        return OpCondBranch(rpc('X', 1), [intpc(2)], [base], else_pc=base+intpc(3))

    def call(regclass, is_tail_call=False):
        args = [['reg', 'X', i] for i in range(intpc(2))]
        return OpCall(rpc(regclass, 1), args, is_tail_call=is_tail_call)

    def send_msg(regclass, is_tail_call=False):
        arity = rpc('K', 2)
        args = [['reg', 'X', i] for i in range(intpc(2))]
        msg = ['record/prenormalized', arity, args]
        ozpickle.normalize_record(msg)
        return OpCall(rpc(regclass, 1), [msg], is_tail_call=is_tail_call)

    def call_builtin():
        args_count = intpc(2)
        args = [rpc('X', n) for n in range(3, 3+args_count)]
        return (2 + args_count, OpCall(rpc('K', 1), args))

    DECODERS = {
        0x00: lambda: (0, OpSkip()),
        0x01: lambda: (2, OpMove(rpc('X', 1), rpc('X', 2))),
        0x02: lambda: (2, OpMove(rpc('X', 1), rpc('Y', 2))),
        0x03: lambda: (2, OpMove(rpc('Y', 1), rpc('X', 2))),
        0x04: lambda: (2, OpMove(rpc('Y', 1), rpc('Y', 2))),
        0x05: lambda: (2, OpMove(rpc('G', 1), rpc('X', 2))),
        0x06: lambda: (2, OpMove(rpc('G', 1), rpc('Y', 2))),
        0x07: lambda: (2, OpMove(rpc('K', 1), rpc('X', 2))),
        0x08: lambda: (2, OpMove(rpc('K', 1), rpc('Y', 2))),
        0x09: lambda: (4, OpMoveMove(rpc('X', 1), rpc('Y', 2), rpc('X', 3), rpc('Y', 4))),
        0x0a: lambda: (4, OpMoveMove(rpc('Y', 1), rpc('X', 2), rpc('Y', 3), rpc('X', 4))),
        0x0b: lambda: (4, OpMoveMove(rpc('Y', 1), rpc('X', 2), rpc('X', 3), rpc('Y', 4))),
        0x0c: lambda: (4, OpMoveMove(rpc('X', 1), rpc('Y', 2), rpc('Y', 3), rpc('X', 4))),
        0x0d: lambda: (1, OpAllocate([['reg', 'Y', n] for n in range(intpc(1))])),
        0x0f: lambda: (1, OpCreateVar(rpc('X', 1))),
        0x10: lambda: (1, OpCreateVar(rpc('Y', 1))),
        0x11: lambda: (2, OpCreateVarMove(rpc('X', 1), rpc('X', 2))),
        0x12: lambda: (2, OpCreateVarMove(rpc('Y', 1), rpc('X', 2))),
        0x18: lambda: (0, OpSetupExceptionHandler()),
        0x19: lambda: (0, OpPopExceptionHandler()),
        0x20: lambda: (1, OpCall(rpc('K', 1), [])),
        0x21: lambda: (2, OpCall(rpc('K', 1), [rpc('X', 2)])),
        0x22: lambda: (3, OpCall(rpc('K', 1), [rpc('X', n) for n in range(2, 4)])),
        0x23: lambda: (4, OpCall(rpc('K', 1), [rpc('X', n) for n in range(2, 5)])),
        0x24: lambda: (5, OpCall(rpc('K', 1), [rpc('X', n) for n in range(2, 6)])),
        0x25: lambda: (6, OpCall(rpc('K', 1), [rpc('X', n) for n in range(2, 7)])),
        0x26: call_builtin,
        0x27: lambda: (2, call('X')),
        0x28: lambda: (2, call('Y')),
        0x29: lambda: (2, call('G')),
        0x2a: lambda: (2, call('K')),
        0x2b: lambda: (2, call('X', is_tail_call=True)),
        0x2c: lambda: (2, call('Y', is_tail_call=True)),
        0x2d: lambda: (2, call('G', is_tail_call=True)),
        0x2e: lambda: (2, call('K', is_tail_call=True)),
        0x30: lambda: (3, send_msg('X')),
        0x31: lambda: (3, send_msg('Y')),
        0x32: lambda: (3, send_msg('G')),
        0x33: lambda: (3, send_msg('K')),
        0x34: lambda: (3, send_msg('X', is_tail_call=True)),
        0x35: lambda: (3, send_msg('Y', is_tail_call=True)),
        0x36: lambda: (3, send_msg('G', is_tail_call=True)),
        0x37: lambda: (3, send_msg('K', is_tail_call=True)),
        0x40: lambda: (0, OpReturn()),
        0x41: lambda: (1, OpBranch(pc + 2 + intpc(1))),
        0x42: lambda: (1, OpBranch(pc + 2 - intpc(1))),
        0x43: lambda: (3, cond_branch(intpc(2), intpc(3))),
        0x44: lambda: (3, cond_branch(intpc(2), -intpc(3))),
        0x45: lambda: (3, cond_branch(-intpc(2), intpc(3))),
        0x46: lambda: (3, cond_branch(-intpc(2), -intpc(3))),
        0x47: lambda: (2, pattern_match('X')),
        0x48: lambda: (2, pattern_match('Y')),
        0x49: lambda: (2, pattern_match('G')),
        0x50: lambda: (2, OpMove(rpc('X', 1), rpc('X', 2), is_unify=True)),
        0x51: lambda: (2, OpMove(rpc('X', 1), rpc('Y', 2), is_unify=True)),
        0x52: lambda: (2, OpMove(rpc('X', 1), rpc('G', 2), is_unify=True)),
        0x53: lambda: (2, OpMove(rpc('X', 1), rpc('K', 2), is_unify=True)),
        0x54: lambda: (2, OpMove(rpc('Y', 1), rpc('Y', 2), is_unify=True)),
        0x55: lambda: (2, OpMove(rpc('Y', 1), rpc('G', 2), is_unify=True)),
        0x56: lambda: (2, OpMove(rpc('Y', 1), rpc('K', 2), is_unify=True)),
        0x57: lambda: (2, OpMove(rpc('G', 1), rpc('G', 2), is_unify=True)),
        0x58: lambda: (2, OpMove(rpc('G', 1), rpc('K', 2), is_unify=True)),
        0x59: lambda: (2, OpMove(rpc('K', 1), rpc('K', 2), is_unify=True)),
        0x80: lambda: (3, equals_integer()),
        0x81: lambda: (3, OpInlineBinArith(rpc('X', 1), '+', rpc('X', 2), rpc('X', 3))),
        0x82: lambda: (3, OpInlineBinArith(rpc('X', 1), '-', rpc('X', 2), rpc('X', 3))),
        0x83: lambda: (2, OpInlineBinArith(rpc('X', 1), '+', 1, rpc('X', 2))),
        0x84: lambda: (2, OpInlineBinArith(rpc('X', 1), '-', 1, rpc('X', 2))),
        0x90: lambda: (2, OpInlineGetClass(rpc('X', 1), rpc('X', 2))),
    }

    try:
        if opcode in DECODERS:
            return DECODERS[opcode]()

        # create struct
        elif opcode & ~0x1f == 0x60:
            what = ['abstraction', 'cons', 'tuple', 'record/prenormalized'][opcode & 3]

            (target, is_unify) = [
                ('X', False),
                ('Y', False),
                ('X', True),
                ('Y', True),
                ('G', True),
                ('K', True),
            ][(opcode >> 2) & 7]

            length = intpc(2)
            label = rpc('K', 1) if what != 'cons' else None
            pre_ops = []
            contents = []

            i = 0
            pc_delta = 4
            while i < length:
                sub_op = intpc(pc_delta)

                if sub_op < 6:
                    regclass = ['X', 'Y', 'G', 'K', '?X', '?Y'][sub_op]
                    contents.append(rpc(regclass, pc_delta+1))
                    i += 1
                elif sub_op == 6:
                    count = intpc(pc_delta+1)
                    contents.extend([['patmatwildcard']] * count)
                    i += count
                else:
                    raise ValueError('Unknown sub-opcode for OpCreateStruct')

                pc_delta += 2

            if what == 'cons':
                src = contents
                src.insert(0, 'cons')
            elif what == 'abstraction':
                src = ['abstraction', None, {
                    'codearea': label,
                    'gs': contents
                }]
            else:
                src = [what, label, contents]
                ozpickle.normalize_record(src)

            return (pc_delta-1, OpMove(src, rpc(target, 3), is_unify=is_unify))

    except Exception as e:
        print(e)
        pass

    if opcode <= 0x90 and opcode not in DECODERS:
        raise ValueError(hex(opcode))

    length = len(arr) - pc - 1
    return (length, OpUnknown(arr[pc:]))