package
week12;
import
org.objectweb.asm.ClassWriter;
import
org.objectweb.asm.Label;
import
org.objectweb.asm.MethodVisitor;
import
week11.AktkBinding;
import
week9.AktkAst;
import
week9.ast.*;
import
java.io.IOException;
import
java.nio.charset.StandardCharsets;
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 {
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 {
String source =
new
String(Files.readAllBytes(sourceFile), StandardCharsets.UTF_8);
AstNode ast = AktkAst.createAst(source);
AktkBinding.bind(ast);
byte
[] bytes = createClass(ast, className);
Files.write(classFile, bytes);
}
public
static
byte
[] createClass(AstNode ast, String className) {
ClassWriter cw =
new
ClassWriter(ClassWriter.COMPUTE_FRAMES);
cw.visit(V1_8, ACC_PUBLIC + ACC_SUPER, className,
null
,
"java/lang/Object"
,
null
);
cw.visitSource(
null
,
null
);
MethodVisitor mv = cw.visitMethod(
ACC_PUBLIC + ACC_STATIC,
"main"
,
"([Ljava/lang/String;)V"
,
null
,
new
String[] {
"java/io/IOException"
});
mv.visitCode();
new
AktkCompilerVisitor(mv).visit(ast);
mv.visitInsn(RETURN);
mv.visitMaxs(
0
,
0
);
mv.visitEnd();
cw.visitEnd();
return
cw.toByteArray();
}
private
static
class
AktkCompilerVisitor
extends
AstVisitor.VoidVisitor {
private
final
Map<VariableBinding, Integer> variableIndices =
new
HashMap<>();;
private
final
MethodVisitor mv;
private
AktkCompilerVisitor(MethodVisitor mv) {
this
.mv = mv;
}
private
int
getVariableIndex(VariableBinding binding) {
Integer index = variableIndices.get(binding);
if
(index !=
null
) {
return
index;
}
else
{
index = variableIndices.size()+
1
;
variableIndices.put(binding, index);
return
index;
}
}
@Override
protected
void
visitVoid(Assignment assignment) {
}
@Override
protected
void
visitVoid(Block block) {
for
(Statement stmt : block.getStatements()) {
visit(stmt);
}
}
@Override
protected
void
visitVoid(ExpressionStatement expressionStatement) {
}
@Override
protected
void
visitVoid(FunctionCall functionCall) {
if
(functionCall.getFunctionName().equals(
"-"
) && functionCall.getArguments().size() ==
1
) {
}
else
if
(functionCall.isArithmeticOperation()) {
}
else
if
(functionCall.isComparisonOperation()) {
}
else
{
}
}
private
void
generateNormalFunctionCall(FunctionCall call) {
}
private
void
generateArithmeticOrLogicOperation(FunctionCall call) {
}
private
void
generateComparisonOperation(FunctionCall call) {
}
@Override
protected
void
visitVoid(FunctionDefinition functionDefinition) {
throw
new
UnsupportedOperationException();
}
@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();
}
@Override
protected
void
visitVoid(StringLiteral stringLiteral) {
throw
new
UnsupportedOperationException();
}
@Override
protected
void
visitVoid(Variable variable) {
}
@Override
protected
void
visitVoid(VariableDeclaration variableDeclaration) {
}
@Override
protected
void
visitVoid(WhileStatement whileStatement) {
}
}
}