me.enerccio.sp.compiler.Bytecode.java Source code

Java tutorial

Introduction

Here is the source code for me.enerccio.sp.compiler.Bytecode.java

Source

/*
 * SimplePython - embeddable python interpret in java
 * Copyright (c) Peter Vanusanik, All rights reserved.
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 3.0 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library.
 */
package me.enerccio.sp.compiler;

import java.util.List;

import me.enerccio.sp.compiler.PythonBytecode.AcceptIter;
import me.enerccio.sp.compiler.PythonBytecode.BinaryOperator;
import me.enerccio.sp.compiler.PythonBytecode.Call;
import me.enerccio.sp.compiler.PythonBytecode.Debug;
import me.enerccio.sp.compiler.PythonBytecode.Del;
import me.enerccio.sp.compiler.PythonBytecode.DelAttr;
import me.enerccio.sp.compiler.PythonBytecode.Dup;
import me.enerccio.sp.compiler.PythonBytecode.ECall;
import me.enerccio.sp.compiler.PythonBytecode.GetAttr;
import me.enerccio.sp.compiler.PythonBytecode.GetIter;
import me.enerccio.sp.compiler.PythonBytecode.Goto;
import me.enerccio.sp.compiler.PythonBytecode.Import;
import me.enerccio.sp.compiler.PythonBytecode.IsInstance;
import me.enerccio.sp.compiler.PythonBytecode.JumpIfFalse;
import me.enerccio.sp.compiler.PythonBytecode.JumpIfNoReturn;
import me.enerccio.sp.compiler.PythonBytecode.JumpIfNone;
import me.enerccio.sp.compiler.PythonBytecode.JumpIfTrue;
import me.enerccio.sp.compiler.PythonBytecode.KCall;
import me.enerccio.sp.compiler.PythonBytecode.KwArg;
import me.enerccio.sp.compiler.PythonBytecode.Load;
import me.enerccio.sp.compiler.PythonBytecode.LoadBuiltin;
import me.enerccio.sp.compiler.PythonBytecode.LoadDynamic;
import me.enerccio.sp.compiler.PythonBytecode.LoadFuture;
import me.enerccio.sp.compiler.PythonBytecode.LoadGlobal;
import me.enerccio.sp.compiler.PythonBytecode.MakeFirst;
import me.enerccio.sp.compiler.PythonBytecode.MakeFuture;
import me.enerccio.sp.compiler.PythonBytecode.Nop;
import me.enerccio.sp.compiler.PythonBytecode.OpenLocals;
import me.enerccio.sp.compiler.PythonBytecode.Pop;
import me.enerccio.sp.compiler.PythonBytecode.Push;
import me.enerccio.sp.compiler.PythonBytecode.PushEnvironment;
import me.enerccio.sp.compiler.PythonBytecode.PushException;
import me.enerccio.sp.compiler.PythonBytecode.PushFrame;
import me.enerccio.sp.compiler.PythonBytecode.PushLocalContext;
import me.enerccio.sp.compiler.PythonBytecode.PushLocals;
import me.enerccio.sp.compiler.PythonBytecode.RCall;
import me.enerccio.sp.compiler.PythonBytecode.Raise;
import me.enerccio.sp.compiler.PythonBytecode.Reraise;
import me.enerccio.sp.compiler.PythonBytecode.ResolveArgs;
import me.enerccio.sp.compiler.PythonBytecode.ResolveClosure;
import me.enerccio.sp.compiler.PythonBytecode.Return;
import me.enerccio.sp.compiler.PythonBytecode.Save;
import me.enerccio.sp.compiler.PythonBytecode.SaveDynamic;
import me.enerccio.sp.compiler.PythonBytecode.SaveGlobal;
import me.enerccio.sp.compiler.PythonBytecode.SaveLocal;
import me.enerccio.sp.compiler.PythonBytecode.SetAttr;
import me.enerccio.sp.compiler.PythonBytecode.SetupLoop;
import me.enerccio.sp.compiler.PythonBytecode.SwapStack;
import me.enerccio.sp.compiler.PythonBytecode.TestFuture;
import me.enerccio.sp.compiler.PythonBytecode.TruthValue;
import me.enerccio.sp.compiler.PythonBytecode.UnpackKwArg;
import me.enerccio.sp.compiler.PythonBytecode.UnpackSequence;
import me.enerccio.sp.compiler.PythonBytecode.Yield;
import me.enerccio.sp.types.ModuleObject.ModuleData;

import org.antlr.v4.runtime.Token;

/**
 * Bytecode enum, containing types of bytecodes and their numerical value.
 * 
 * @author Enerccio
 *
 */
public enum Bytecode {
    // System
    NOP(0), PUSH_ENVIRONMENT(8), RESOLVE_CLOSURE(10), PUSH_LOCAL_CONTEXT(11), IMPORT(12), RESOLVE_ARGS(
            13), PUSH_FRAME(15), PUSH_EXCEPTION(16), OPEN_LOCALS(17), PUSH_LOCALS(18),

    // control
    POP(31), PUSH(32), CALL(33), KCALL(34), RCALL(35), ECALL(36), DUP(37), SWAP_STACK(38), JUMPIFTRUE(
            39), JUMPIFFALSE(40), JUMPIFNONE(
                    41), JUMPIFNORETURN(42), GOTO(43), RETURN(44), SAVE_LOCAL(45), TRUTH_VALUE(46), MAKE_FIRST(47),
    // variables
    LOAD(64), LOADGLOBAL(65), SAVE(66), SAVEGLOBAL(67), UNPACK_SEQUENCE(68), LOADDYNAMIC(69), SAVEDYNAMIC(
            70), LOADBUILTIN(71),
    // special call-related
    KWARG(80), UNPACK_KWARG(81), MAKE_FUTURE(82), TEST_FUTURE(83), LOAD_FUTURE(84),
    // exceptions
    RAISE(85), RERAISE(86),
    // macros
    GETATTR(89), SETATTR(90), ISINSTANCE(91),
    // frames
    YIELD(96),
    // delete
    DEL(104), DELATTR(105),

    // loops, iterators, boolean stuff
    SETUP_LOOP(128), GET_ITER(129), ACCEPT_ITER(130),

    // math macros
    ADD(164), SUB(165), MUL(166), DIV(167), MOD(168), AND(169), OR(170), XOR(171), POW(172), RSHIFT(173), LSHIFT(
            174), LT(175), LE(176), GE(177), GT(178), EQ(179), NE(180), DCOLON(181), QM(182), RARROW(183), AT(184),

    // debugger only bytecodes
    D_STARTFUNC(250), D_RETURN(251),;

    Bytecode(int id) {
        this.id = id;
    }

    public static final String NO_FUNCTION = "<module>";

    public final int id;

    private static final Bytecode[] bytecodes;

    static {
        bytecodes = new Bytecode[256];
        for (Bytecode b : values())
            bytecodes[b.id] = b;
    }

    /**
     * Transforms int into bytecode or null if no such bytecode exists
     * 
     * @param intValue
     * @return
     */
    public static Bytecode fromNumber(int intValue) {
        Bytecode b = bytecodes[intValue];
        if (b == null)
            throw new NullPointerException("bytecode not found: " + intValue);
        return b;
    }

    /**
     * Creates new PythonBytecode object based on the bytecode, sets the source
     * information based on the token.
     * 
     * @param b
     * @param t
     *            may be null
     * @return
     */
    public static PythonBytecode makeBytecode(Bytecode b, Token t, String functionName, ModuleData module) {
        PythonBytecode bytecode = null;

        switch (b) {
        case CALL:
            bytecode = new Call();

            break;
        case DEL:
            bytecode = new Del();

            break;
        case TEST_FUTURE:
            bytecode = new TestFuture();

            break;
        case DELATTR:
            bytecode = new DelAttr();

            break;
        case RESOLVE_CLOSURE:
            bytecode = new ResolveClosure();

            break;
        case LOADBUILTIN:
            bytecode = new LoadBuiltin();

            break;
        case PUSH_LOCALS:
            bytecode = new PushLocals();

            break;
        case RCALL:
            bytecode = new RCall();

            break;
        case KCALL:
            bytecode = new KCall();

            break;
        case ECALL:
            bytecode = new ECall();

            break;
        case ACCEPT_ITER:
            bytecode = new AcceptIter();

            break;
        case TRUTH_VALUE:
            bytecode = new TruthValue();

            break;
        case DUP:
            bytecode = new Dup();

            break;
        case GOTO:
            bytecode = new Goto();

            break;
        case JUMPIFFALSE:
            bytecode = new JumpIfFalse();

            break;
        case JUMPIFTRUE:
            bytecode = new JumpIfTrue();

            break;
        case JUMPIFNONE:
            bytecode = new JumpIfNone();

            break;
        case JUMPIFNORETURN:
            bytecode = new JumpIfNoReturn();

            break;
        case LOAD:
            bytecode = new Load();

            break;
        case LOADGLOBAL:
            bytecode = new LoadGlobal();

            break;
        case LOAD_FUTURE:
            bytecode = new LoadFuture();

            break;
        case MAKE_FUTURE:
            bytecode = new MakeFuture();

            break;
        case NOP:
            bytecode = new Nop();

            break;
        case POP:
            bytecode = new Pop();

            break;
        case MAKE_FIRST:
            bytecode = new MakeFirst();

            break;
        case PUSH:
            bytecode = new Push();

            break;
        case PUSH_ENVIRONMENT:
            bytecode = new PushEnvironment();

            break;
        case RETURN:
            bytecode = new Return();

            break;
        case SAVE:
            bytecode = new Save();

            break;
        case SAVEGLOBAL:
            bytecode = new SaveGlobal();

            break;
        case SAVEDYNAMIC:
            bytecode = new SaveDynamic();

            break;
        case LOADDYNAMIC:
            bytecode = new LoadDynamic();

            break;
        case IMPORT:
            bytecode = new Import();

            break;
        case SWAP_STACK:
            bytecode = new SwapStack();

            break;
        case KWARG:
            bytecode = new KwArg();

            break;
        case UNPACK_KWARG:
            bytecode = new UnpackKwArg();

            break;
        case UNPACK_SEQUENCE:
            bytecode = new UnpackSequence();

            break;
        case PUSH_LOCAL_CONTEXT:
            bytecode = new PushLocalContext();

            break;
        case RESOLVE_ARGS:
            bytecode = new ResolveArgs();

            break;
        case GETATTR:
            bytecode = new GetAttr();

            break;
        case SETATTR:
            bytecode = new SetAttr();

            break;
        case ISINSTANCE:
            bytecode = new IsInstance();

            break;
        case RAISE:
            bytecode = new Raise();

            break;
        case RERAISE:
            bytecode = new Reraise();

            break;
        case PUSH_FRAME:
            bytecode = new PushFrame();

            break;
        case PUSH_EXCEPTION:
            bytecode = new PushException();

            break;
        case SAVE_LOCAL:
            bytecode = new SaveLocal();

            break;
        case SETUP_LOOP:
            bytecode = new SetupLoop();

            break;
        case GET_ITER:
            bytecode = new GetIter();

            break;
        case YIELD:
            bytecode = new Yield();

            break;
        case OPEN_LOCALS:
            bytecode = new OpenLocals();

            break;
        case ADD:
        case AND:
        case DIV:
        case EQ:
        case GE:
        case GT:
        case LE:
        case LSHIFT:
        case LT:
        case MOD:
        case MUL:
        case NE:
        case OR:
        case POW:
        case RSHIFT:
        case SUB:
        case XOR:
        case DCOLON:
        case QM:
        case RARROW:
        case AT:
            bytecode = new BinaryOperator(b);

            break;
        case D_STARTFUNC:
        case D_RETURN:
            bytecode = new Debug(b);

            break;
        }

        if (module == null)
            throw new RuntimeException("Module cannot be null. Create static ModuleProvider if necessary.");
        bytecode.debugModule = module;
        bytecode.debugFunction = functionName == null ? NO_FUNCTION : functionName;
        if (t != null) {
            bytecode.debugLine = t.getLine();
            bytecode.debugCharacter = t.getCharPositionInLine();
            bytecode.debugFunction = functionName;
        }

        return bytecode;
    }

    /**
     * Disassembles the list of bytecodes
     * 
     * @param bcl
     * @return
     */
    public static String dis(List<PythonBytecode> bcl) {
        return dis(bcl, 0);
    }

    /**
     * Disassembles single bytecode
     * 
     * @param i
     * @param bc
     * @return
     */
    public static String dis(int i, PythonBytecode bc) {
        String s = bc.toString();
        int cut = s.length();
        if (cut > 80)
            cut = 80;
        return String.format("%05d \t%s", i, s.substring(0, cut));
    }

    /**
     * Disassembles the list of bytecodes from offset bytecode
     * 
     * @param i
     * @param bc
     * @return
     */
    public static String dis(List<PythonBytecode> bcl, int offset) {
        StringBuilder b = new StringBuilder();
        for (int i = offset; i < bcl.size(); i++) {
            PythonBytecode bc = bcl.get(i);
            b.append(dis(i, bc));
            b.append("\n");
        }
        return b.toString();
    }
}