Arvutiteaduse instituut
Courses.cs.ut.ee Arvutiteaduse instituut Tartu Ülikool
  1. Esileht
  2. Automaadid, keeled ja translaatorid
EN
Logi sisse

Automaadid, keeled ja translaatorid

  • Ü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 week7.AktkAst;
import week7.ast.*;
import week9.AktkBinding;

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.List;
import java.util.Map;

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


public class AktkCompiler {

    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
        Statement ast = AktkAst.createAst(source);

        // seon muutujad
        AktkBinding.bind(ast);

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

    public static byte[] createClass(Statement statement, 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 AktkCompiler(mv).compileStatement(statement);

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

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

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


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

    public AktkCompiler(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);
    }

    private void compileStatement(Statement statement) {
        switch (statement) {
            case Assignment assignment -> {
                // 1) genereeri avaldise väärtustamise kood
                // 2) genereeri väärtuse muutujasse salvestamise kood
            }
            case Block(List<Statement> statements) -> {
                for (Statement stmt : statements) {
                    compileStatement(stmt);
                }
            }
            case ExpressionStatement(Expression expression) -> {
                // NB! Ära unusta, et ExpressionStatement viskab arvutatud väärtuse minema
            }
            case FunctionDefinition _ ->
                    throw new UnsupportedOperationException("cannot compile function definitions");
            case IfStatement(Expression condition, Block thenBranch, Block elseBranch) -> {
                Label doneLabel = new Label();
                Label elseLabel = new Label();
                // ...
            }
            case ReturnStatement _ -> throw new UnsupportedOperationException("cannot compile return statements");
            case VariableDeclaration variableDeclaration -> {

            }
            case WhileStatement(Expression condition, Block body) -> {

            }
        }
    }

    private void compileExpression(Expression expression) {
        switch (expression) {
            case FunctionCall functionCall -> {
                // genereeri argumentide väärtustamise kood

                if (functionCall.isArithmeticOperation()) {
                    compileArithmeticOperation(functionCall);
                } else if (functionCall.isComparisonOperation()) {
                    compileComparisonOperation(functionCall);
                } else {
                    compileBuiltinFunction(functionCall);
                }
            }
            case IntegerLiteral(Integer value) -> {

            }
            case StringLiteral(String value) -> throw new UnsupportedOperationException("cannot compile strings");
            case Variable variable -> {

            }
        }
    }

    private void compileArithmeticOperation(FunctionCall functionCall) {

    }

    private void compileComparisonOperation(FunctionCall call) {

    }

    private void compileBuiltinFunction(FunctionCall functionCall) {

    }
}
  • Arvutiteaduse instituut
  • Loodus- ja täppisteaduste valdkond
  • Tartu Ülikool
Tehniliste probleemide või küsimuste korral kirjuta:

Kursuse sisu ja korralduslike küsimustega pöörduge kursuse korraldajate poole.
Õppematerjalide varalised autoriõigused kuuluvad Tartu Ülikoolile. Õppematerjalide kasutamine on lubatud autoriõiguse seaduses ettenähtud teose vaba kasutamise eesmärkidel ja tingimustel. Õppematerjalide kasutamisel on kasutaja kohustatud viitama õppematerjalide autorile.
Õppematerjalide kasutamine muudel eesmärkidel on lubatud ainult Tartu Ülikooli eelneval kirjalikul nõusolekul.
Courses’i keskkonna kasutustingimused