Institute of Computer Science
  1. Main page
  2. Automata, Languages and Compilers
ET
Log in

Automata, Languages and Compilers

  • Üldinfo
  • Ajakava
  • Eksami näidised
  • Teemad
    • 1. Soojendus
    • 2. Regulaaravaldised
    • 3. Automaadid
    • 4. Avaldise struktuur
    • 5. Grammatikad ja lekser
    • 6. Käsitsi parsimine
    • 7. ANTLRiga töötamine
    • 8. Interpretaator
    • 9. Kompilaator
    • 10. Edasi!
  • Süvendus
  • GitHub
  • Moodle
  • Zulip
  • Zoom

Kompilaatori kodutöö, vihje 2

package week10;

import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import week9.AktkBinding;
import week7.AktkAst;
import week7.ast.*;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;

import static org.objectweb.asm.Opcodes.*;


public class AktkCompiler {

    public static void main(String[] args) throws IOException {
        // lihtsam viis "käsurea parameetrite andmiseks":
        //args = new String[] {"inputs/yks_pluss_yks.aktk"};

        if (args.length != 1) {
            throw new IllegalArgumentException("Sellele programmile tuleb anda parameetriks kompileeritava AKTK faili nimi");
        }

        Path sourceFile = Paths.get(args[0]);
        if (!Files.isRegularFile(sourceFile)) {
            throw new IllegalArgumentException("Ei leia faili nimega '" + sourceFile + "'");
        }

        String className = sourceFile.getFileName().toString().replace(".aktk", "");
        Path classFile = sourceFile.toAbsolutePath().getParent().resolve(className + ".class");

        createClassFile(sourceFile, className, classFile);
    }

    private static void createClassFile(Path sourceFile, String className, Path classFile) throws IOException {
        // loen faili sisu muutujasse
        String source = Files.readString(sourceFile);

        // parsin ja moodustan AST'i
        AstNode ast = AktkAst.createAst(source);

        // seon muutujad
        AktkBinding.bind(ast);

        // kompileerin
        byte[] bytes = createClass(ast, className);
        Files.write(classFile, bytes);
    }

    public static byte[] createClass(AstNode ast, String className) {
        ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);

        // Klassi attribuudid
        cw.visit(V1_8, ACC_PUBLIC + ACC_SUPER, className, null, "java/lang/Object", null);
        cw.visitSource(null, null);

        // main meetod
        MethodVisitor mv = cw.visitMethod(
                ACC_PUBLIC + ACC_STATIC,                     // modifikaatorid
                "main",                                        // meetodi nimi
                "([Ljava/lang/String;)V",                    // meetodi kirjeldaja
                null,                                         // geneerikute info
                new String[] { "java/io/IOException" });
        mv.visitCode();
        // terve AKTK programm tuleb kompileerida main meetodi sisse
        new AktkCompilerVisitor(mv).visit(ast);
        mv.visitInsn(RETURN);
        mv.visitMaxs(0, 0);
        mv.visitEnd();


        // klassi lõpetamine
        cw.visitEnd();

        // klassi baidijada genereerimine
        return cw.toByteArray();
    }

    private static class AktkCompilerVisitor extends AstVisitor.VoidVisitor {

        private final MethodVisitor mv;
        private final Map<VariableBinding, Integer> variableIndices = new HashMap<>();

        private AktkCompilerVisitor(MethodVisitor mv) {
            this.mv = mv;
        }

        private int getVariableIndex(VariableBinding binding) {
            // Kasuta teadaolevat indeksit, kui see on olemas,
            // või leia järgmine vaba indeks ja salvesta see.
            // Esimene muutuja saab indeksi 1, sest indeksil 0 on main meetodi parameeter (String args[]).
            return variableIndices.computeIfAbsent(binding, ignoreBinding -> variableIndices.size() + 1);
        }

        @Override
        protected void visitVoid(Assignment assignment) {
            // 1) genereeri avaldise väärtustamise kood
            // 2) genereeri väärtuse muutujasse salvestamise kood
        }

        @Override
        protected void visitVoid(Block block) {
            for (Statement stmt : block.getStatements()) {
                visit(stmt);
            }
        }

        @Override
        protected void visitVoid(ExpressionStatement expressionStatement) {
            // NB! Ära unusta, et ExpressionStatement viskab arvutatud väärtuse minema
        }

        @Override
        protected void visitVoid(FunctionCall functionCall) {
            // genereeri argumentide väärtustamise kood

            if (functionCall.isArithmeticOperation()) {
                compileArithmeticOperation(functionCall);
            }
            else if (functionCall.isComparisonOperation()) {
                compileComparisonOperation(functionCall);
            }
            else {
                compileBuiltinFunction(functionCall);
            }
        }

        private void compileArithmeticOperation(FunctionCall functionCall) {

        }

        private void compileComparisonOperation(FunctionCall call) {

        }

        private void compileBuiltinFunction(FunctionCall functionCall) {

        }

        @Override
        protected void visitVoid(FunctionDefinition functionDefinition) {
            throw new UnsupportedOperationException("cannot compile function definitions");
        }

        @Override
        protected void visitVoid(IfStatement ifStatement) {
            Label doneLabel = new Label();
            Label elseLabel = new Label();
            // ...
        }

        @Override
        protected void visitVoid(IntegerLiteral integerLiteral) {

        }

        @Override
        protected void visitVoid(ReturnStatement returnStatement) {
            throw new UnsupportedOperationException("cannot compile return statements");
        }

        @Override
        protected void visitVoid(StringLiteral stringLiteral) {
            throw new UnsupportedOperationException("cannot compile strings");
        }

        @Override
        protected void visitVoid(Variable variable) {

        }

        @Override
        protected void visitVoid(VariableDeclaration variableDeclaration) {

        }

        @Override
        protected void visitVoid(WhileStatement whileStatement) {

        }
    }
}
  • Institute of Computer Science
  • Faculty of Science and Technology
  • University of Tartu
In case of technical problems or questions write to:

Contact the course organizers with the organizational and course content questions.
The proprietary copyrights of educational materials belong to the University of Tartu. The use of educational materials is permitted for the purposes and under the conditions provided for in the copyright law for the free use of a work. When using educational materials, the user is obligated to give credit to the author of the educational materials.
The use of educational materials for other purposes is allowed only with the prior written consent of the University of Tartu.
Terms of use for the Courses environment