Institute of Computer Science
  1. Courses
  2. 2017/18 spring
  3. Automata, Languages and Compilers (LTAT.03.006)
ET
Log in

Automata, Languages and Compilers 2017/18 spring

  • Üldinfo
  1. Õppekorraldus
  2. Eksam
  3. Reeglid
  4. Töövahendid
  5. Projekt
  • Kava
  1. Soojendus
  2. Regulaaravaldised
  3. Olekumasinad
  4. Lõplikud automaadid
  5. Avaldise struktuur
  6. Grammatikad ja lekser
  7. Käsitsi parsimine
  8. ANTLR intro
  9. AST loomine
  10. Interpretaator
  11. Semantiline analüüs
  12. Kompilaator
  • Moodle
  • Bitbucket
  • Fleep!

Kompilaatori kodutöö, vihje 2

package week12;

import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Type;
import week11.AktkBinding;
import week9.AktkAst;
import week9.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 {
	private final AstNode ast;
	private Map<VariableBinding, Integer> variableIndices;
	private MethodVisitor mv;

	public AktkCompiler(AstNode ast) {
		this.ast = ast;
	}

	public static void main(String[] args) throws IOException {
		// lihtsam viis "käsurea parameetrite andmiseks":
		//args = new String[] {"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 = new String(Files.readAllBytes(sourceFile), "UTF-8");

		// 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) {
		return new AktkCompiler(ast).createClass(className);
	}

	private byte[] createClass(String className) {
		variableIndices = new HashMap<>();

		ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);

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

		// main meetod
		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
		generateCode(ast);
		mv.visitInsn(RETURN);
		mv.visitMaxs(0, 0);
		mv.visitEnd();


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

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

	private int getVariableIndex(VariableBinding binding) {
		Integer index = variableIndices.get(binding);
		if (index != null) {
			return index;
		}
		else {
			// muutuja 0 on meie main-meetodi parameeter

			index = variableIndices.size()+1;
			variableIndices.put(binding, index);
			return index;
		}
	}

	private void generateCode(AstNode node) {
		if (node instanceof Block) {
			for (Statement stmt : ((Block)node).getStatements()) {
				generateCode(stmt);
			}
		}
		else if (node instanceof Assignment) {
			// 1) genereeri avaldise väärtustamise kood
			// 2) genereeri väärtuse muutujasse salvestamise kood
		}
		else if (node instanceof ExpressionStatement) {
			// NB! Ära unusta, et ExpressionStatement viskab arvutatud väärtuse minema
		}
		else if (node instanceof IntegerLiteral) {

		}
		else if (node instanceof Variable) {

		}
		else if (node instanceof VariableDeclaration) {

		}
		else if (node instanceof FunctionCall) {
			FunctionCall call = (FunctionCall) node;

			if (call.getFunctionName().equals("-") && call.getArguments().size() == 1) {
				// unaarne miinus
			}
			else if (call.isArithmeticOperation()) {

			}
			else if (call.isComparisonOperation()) {

			}
			else {

			}
		}
		else if (node instanceof IfStatement) {
			IfStatement stmt = (IfStatement) node;

			Label doneLabel = new Label();
			Label elseLabel = new Label();

			// ...
		}
		else if (node instanceof WhileStatement) {

		}
		else {
			assert node instanceof StringLiteral;

			throw new UnsupportedOperationException("Seda konstrutsiooni praegu me ei toeta");
		}
	}

	private void generateNormalFunctionCall(FunctionCall call) {

	}

	private void generateArithmeticOrLogicOperation(FunctionCall call) {

	}

	private void generateComparisonOperation(FunctionCall call) {
		// JVM int-ide võrdlusoperatsioonide valikus on kõik operatsioonid seotud jumpidega.
		// Kui sa ei taha avaldise väärtustamise koodi siduda if-lausega
		// siis ma kasuta jumpe lihtsalt selleks, et tekitada stacki tippu
		// kas 0 või 1
	}
}
  • 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