org.whole.examples.lang.imp.visitors.ImpBytecodeGeneratorVisitor.java Source code

Java tutorial

Introduction

Here is the source code for org.whole.examples.lang.imp.visitors.ImpBytecodeGeneratorVisitor.java

Source

/**
 * Copyright 2004-2014 Riccardo Solmi. All rights reserved.
 * This file is part of the Whole Platform.
 *
 * The Whole Platform 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 of the License, or
 * (at your option) any later version.
 *
 * The Whole Platform 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 the Whole Platform. If not, see <http://www.gnu.org/licenses/>.
 */
package org.whole.examples.lang.imp.visitors;

import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.whole.examples.lang.imp.model.Addition;
import org.whole.examples.lang.imp.model.And;
import org.whole.examples.lang.imp.model.BooleanLiteral;
import org.whole.examples.lang.imp.model.Division;
import org.whole.examples.lang.imp.model.DoWhileStatement;
import org.whole.examples.lang.imp.model.Equals;
import org.whole.examples.lang.imp.model.ForStatement;
import org.whole.examples.lang.imp.model.FunctionDeclaration;
import org.whole.examples.lang.imp.model.GreaterOrEquals;
import org.whole.examples.lang.imp.model.GreaterThan;
import org.whole.examples.lang.imp.model.IfElseStatement;
import org.whole.examples.lang.imp.model.IfStatement;
import org.whole.examples.lang.imp.model.IntLiteral;
import org.whole.examples.lang.imp.model.LessOrEquals;
import org.whole.examples.lang.imp.model.LessThan;
import org.whole.examples.lang.imp.model.Multiplication;
import org.whole.examples.lang.imp.model.Name;
import org.whole.examples.lang.imp.model.Not;
import org.whole.examples.lang.imp.model.NotEquals;
import org.whole.examples.lang.imp.model.Or;
import org.whole.examples.lang.imp.model.PrintStatement;
import org.whole.examples.lang.imp.model.PrintlnStatement;
import org.whole.examples.lang.imp.model.ReturnStatement;
import org.whole.examples.lang.imp.model.StringLiteral;
import org.whole.examples.lang.imp.model.Subtraction;
import org.whole.examples.lang.imp.model.WhileStatement;

/**
 * @author Riccardo Solmi
 */
public class ImpBytecodeGeneratorVisitor extends ImpTraverseAllVisitor implements Opcodes {
    protected String name;
    protected int resultType = TYPE_V;
    public static final int TYPE_V = 0;
    public static final int TYPE_B = 1;
    public static final int TYPE_I = 2;
    public static final int TYPE_A = 3;

    public ImpBytecodeGeneratorVisitor(BytecodeGeneratorOperation operation) {
        setOperation(operation);
    }

    public BytecodeGeneratorOperation getOperation() {
        return (BytecodeGeneratorOperation) super.getOperation();
    }

    protected ClassVisitor cv() {
        return getOperation().getClassVisitor();
    }

    public MethodVisitor mv() {
        return getOperation().getMethodVisitor();
    }

    public void setMethodVisitor(MethodVisitor methodVisitor) {
        getOperation().setMethodVisitor(methodVisitor);
    }

    public void visit(FunctionDeclaration entity) {
        entity.getType().accept(this);
        entity.getName().accept(this);
        entity.getParameters().accept(this);

        MethodVisitor mv = cv().visitMethod(ACC_PUBLIC, name, "()V", null, null);
        mv.visitCode();
        setMethodVisitor(mv);

        entity.getBody().accept(this);

        mv.visitInsn(RETURN);
        mv.visitMaxs(0, 0);
        mv.visitEnd();
    }

    public void visit(ReturnStatement entity) {
        resultType = TYPE_V;
        entity.getExp().accept(this);
        switch (resultType) {
        case TYPE_V:
            mv().visitInsn(RETURN);
            break;
        case TYPE_B:
            mv().visitInsn(IRETURN);
            break;
        case TYPE_I:
            mv().visitInsn(IRETURN);
            break;
        case TYPE_A:
            mv().visitInsn(ARETURN);
            break;
        }
    }

    public static String paramType(int resultType) {
        switch (resultType) {
        case TYPE_V:
            return "";
        case TYPE_B:
            return "I";
        case TYPE_I:
            return "I";
        case TYPE_A:
            return "Ljava/lang/String;";
        default:
            return "";
        }
    }

    public void visit(IfStatement entity) {
        entity.getCondition().accept(this);
        Label iffalse = new Label();
        mv().visitJumpInsn(IF_ICMPNE, iffalse);
        entity.getTrueBody().accept(this);
        mv().visitLabel(iffalse);
    }

    public void visit(IfElseStatement entity) {
        entity.getCondition().accept(this);
        Label iftrue = new Label();
        Label end = new Label();
        mv().visitJumpInsn(IF_ICMPEQ, iftrue);
        entity.getFalseBody().accept(this);
        mv().visitJumpInsn(GOTO, end);
        mv().visitLabel(iftrue);
        entity.getTrueBody().accept(this);
        mv().visitLabel(end);
    }

    public void visit(WhileStatement entity) {
        Label loop = new Label();
        Label end = new Label();
        mv().visitLabel(loop);
        entity.getCondition().accept(this);
        mv().visitJumpInsn(IF_ICMPNE, end);
        entity.getTrueBody().accept(this);
        mv().visitJumpInsn(GOTO, loop);
        mv().visitLabel(end);
    }

    public void visit(DoWhileStatement entity) {
        Label loop = new Label();
        mv().visitLabel(loop);
        entity.getTrueBody().accept(this);
        entity.getCondition().accept(this);
        mv().visitJumpInsn(IF_ICMPEQ, loop);
    }

    public void visit(ForStatement entity) {
        entity.getInitializer().accept(this);
        Label loop = new Label();
        Label end = new Label();
        mv().visitLabel(loop);
        entity.getCondition().accept(this);
        mv().visitJumpInsn(IF_ICMPNE, end);
        entity.getTrueBody().accept(this);
        entity.getUpdater().accept(this);
        mv().visitJumpInsn(GOTO, loop);
        mv().visitLabel(end);
    }

    public void visit(PrintStatement entity) {
        mv().visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
        entity.getExp().accept(this);
        mv().visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "print", "(" + paramType(resultType) + ")V");
    }

    public void visit(PrintlnStatement entity) {
        mv().visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
        entity.getExp().accept(this);
        mv().visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(" + paramType(resultType) + ")V");
    }

    public void visit(BooleanLiteral entity) {
        mv().visitInsn(entity.wBooleanValue() ? ICONST_1 : ICONST_0);
        resultType = TYPE_B;
    }

    public void visit(IntLiteral entity) {
        mv().visitLdcInsn(new Integer(entity.wIntValue()));
        resultType = TYPE_I;
    }

    public void visit(StringLiteral entity) {
        mv().visitLdcInsn(entity.wStringValue());
        resultType = TYPE_A;
    }

    public void visit(Name entity) {
        name = entity.getValue();
    }

    public void visit(Addition entity) {
        entity.getExp1().accept(this);
        entity.getExp2().accept(this);
        mv().visitInsn(IADD);
        resultType = TYPE_I;
    }

    public void visit(Subtraction entity) {
        entity.getExp1().accept(this);
        entity.getExp2().accept(this);
        mv().visitInsn(ISUB);
        resultType = TYPE_I;
    }

    public void visit(Multiplication entity) {
        entity.getExp1().accept(this);
        entity.getExp2().accept(this);
        mv().visitInsn(IMUL);
        resultType = TYPE_I;
    }

    public void visit(Division entity) {
        entity.getExp1().accept(this);
        entity.getExp2().accept(this);
        mv().visitInsn(IDIV);
        resultType = TYPE_I;
    }

    public void visit(And entity) {
        entity.getExp1().accept(this);
        mv().visitInsn(DUP);
        Label end = new Label();
        mv().visitJumpInsn(IFEQ, end);
        mv().visitInsn(POP);
        entity.getExp2().accept(this);
        mv().visitLabel(end);
        resultType = TYPE_B;
    }

    public void visit(Or entity) {
        entity.getExp1().accept(this);
        mv().visitInsn(DUP);
        Label end = new Label();
        mv().visitJumpInsn(IFNE, end);
        mv().visitInsn(POP);
        entity.getExp2().accept(this);
        mv().visitLabel(end);
        resultType = TYPE_B;
    }

    public void visit(Not entity) {
        mv().visitInsn(ICONST_1);
        entity.getExp().accept(this);
        mv().visitInsn(ISUB);
        resultType = TYPE_B;
    }

    public void visit(Equals entity) {
        entity.getExp1().accept(this);
        entity.getExp2().accept(this);
        Label iftrue = new Label();
        Label end = new Label();
        mv().visitJumpInsn(IF_ICMPEQ, iftrue);
        mv().visitInsn(ICONST_0);
        mv().visitJumpInsn(GOTO, end);
        mv().visitLabel(iftrue);
        mv().visitInsn(ICONST_1);
        mv().visitLabel(end);
        resultType = TYPE_B;
    }

    public void visit(NotEquals entity) {
        entity.getExp1().accept(this);
        entity.getExp2().accept(this);
        Label iftrue = new Label();
        Label end = new Label();
        mv().visitJumpInsn(IF_ICMPNE, iftrue);
        mv().visitInsn(ICONST_0);
        mv().visitJumpInsn(GOTO, end);
        mv().visitLabel(iftrue);
        mv().visitInsn(ICONST_1);
        mv().visitLabel(end);
        resultType = TYPE_B;
    }

    public void visit(LessThan entity) {
        entity.getExp1().accept(this);
        entity.getExp2().accept(this);
        Label iftrue = new Label();
        Label end = new Label();
        mv().visitJumpInsn(IF_ICMPLT, iftrue);
        mv().visitInsn(ICONST_0);
        mv().visitJumpInsn(GOTO, end);
        mv().visitLabel(iftrue);
        mv().visitInsn(ICONST_1);
        mv().visitLabel(end);
        resultType = TYPE_B;
    }

    public void visit(LessOrEquals entity) {
        entity.getExp1().accept(this);
        entity.getExp2().accept(this);
        Label iftrue = new Label();
        Label end = new Label();
        mv().visitJumpInsn(IF_ICMPLE, iftrue);
        mv().visitInsn(ICONST_0);
        mv().visitJumpInsn(GOTO, end);
        mv().visitLabel(iftrue);
        mv().visitInsn(ICONST_1);
        mv().visitLabel(end);
        resultType = TYPE_B;
    }

    public void visit(GreaterThan entity) {
        entity.getExp1().accept(this);
        entity.getExp2().accept(this);
        Label iftrue = new Label();
        Label end = new Label();
        mv().visitJumpInsn(IF_ICMPGT, iftrue);
        mv().visitInsn(ICONST_0);
        mv().visitJumpInsn(GOTO, end);
        mv().visitLabel(iftrue);
        mv().visitInsn(ICONST_1);
        mv().visitLabel(end);
        resultType = TYPE_B;
    }

    public void visit(GreaterOrEquals entity) {
        entity.getExp1().accept(this);
        entity.getExp2().accept(this);
        Label iftrue = new Label();
        Label end = new Label();
        mv().visitJumpInsn(IF_ICMPGE, iftrue);
        mv().visitInsn(ICONST_0);
        mv().visitJumpInsn(GOTO, end);
        mv().visitLabel(iftrue);
        mv().visitInsn(ICONST_1);
        mv().visitLabel(end);
        resultType = TYPE_B;
    }
}