Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Code generation #20

Merged
merged 9 commits into from
Jul 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ out/
trees/
.project
.vscode/
src/parser/.antlr/
src/parser/.antlr/
code.asm
37 changes: 34 additions & 3 deletions src/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,16 @@
import org.antlr.v4.gui.TreeViewer;
import org.antlr.v4.runtime.*;

import java.nio.file.StandardOpenOption;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import ast.*;
import ast.nodes.*;
import parser.*;
import parser.Python3Lexer;
import parser.Python3Parser;
import semanticanalysis.*;
import semanticanalysis.Share;
import svm.*;

public class Main {

Expand Down Expand Up @@ -52,7 +57,7 @@ public static void main(String[] args) {
Python3VisitorImpl visitor = new Python3VisitorImpl();
SymbolTable ST = new SymbolTable();
Node ast = visitor.visit(tree);
ArrayList<SemanticError> errorsWithDup = ast.checkSemantics(ST, 0);
ArrayList<SemanticError> errorsWithDup = ast.checkSemantics(ST, 0, null);
ArrayList<SemanticError> errors = Share.removeDuplicates(errorsWithDup);
if (!errors.isEmpty()) {
System.out.println("You had " + errors.size() + " errors:");
Expand All @@ -62,6 +67,32 @@ public static void main(String[] args) {
} else {
System.out.println("Visualizing AST...");
System.out.println(ast.toPrint(""));
System.out.println("Creating VM code...");
String prog = ast.codeGeneration();
String asmFile = "code.asm";
Path file = Paths.get(asmFile);
if (!Files.exists(file)) {
Files.createFile(file);
}
Files.write(file, prog.getBytes(), StandardOpenOption.TRUNCATE_EXISTING);
System.out.println("Done!");

CharStream inputASM = CharStreams.fromFileName(asmFile);
SVMLexer lexerASM = new SVMLexer(inputASM);
CommonTokenStream tokensASM = new CommonTokenStream(lexerASM);
SVMParser parserASM = new SVMParser(tokensASM);

SVMVisitorImpl visitorSVM = new SVMVisitorImpl();
visitorSVM.visit(parserASM.assembly());

System.out.println("You had: " + lexerASM.lexicalErrors + " lexical errors and "
+ parserASM.getNumberOfSyntaxErrors() + " syntax errors.");
if (lexerASM.lexicalErrors > 0 || parserASM.getNumberOfSyntaxErrors() > 0)
System.exit(1);

System.out.println("Starting Virtual Machine...");
ExecuteVM vm = new ExecuteVM(visitorSVM.code);
vm.cpu();
}
} catch (Exception e) {
e.printStackTrace();
Expand Down
3 changes: 1 addition & 2 deletions src/ParseAll.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,11 @@ public static void main(String[] args) {

Python3Parser.RootContext tree = parser.root();
String treeStr = tree.toStringTree();
// System.out.println(treeStr);

Python3VisitorImpl visitor = new Python3VisitorImpl();
SymbolTable ST = new SymbolTable();
Node ast = visitor.visit(tree);
ArrayList<SemanticError> errorsWithDup = ast.checkSemantics(ST, 0);
ArrayList<SemanticError> errorsWithDup = ast.checkSemantics(ST, 0, null);
ArrayList<SemanticError> errors = Share.removeDuplicates(errorsWithDup);
if (!errors.isEmpty()) {
System.out.println();
Expand Down
32 changes: 22 additions & 10 deletions src/ast/Python3VisitorImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -336,32 +336,32 @@ public Node visitBlock(BlockContext ctx) {
}

/**
* Returns a `CompNode`. It should never be null.
* Returns a `CompOpNode`. It should never be null.
*
* ``` comp_op : '<' | '>' | '==' | '>=' | '<=' | '<>' | '!=' | 'in' | 'not'
* 'in' | 'is' | 'is' 'not' ; ```
*/
public Node visitComp_op(Comp_opContext ctx) {
Node comp = null;
if (ctx.LESS_THAN() != null) {
comp = new CompNode(ctx.LESS_THAN());
comp = new CompOpNode(ctx.LESS_THAN());
} else if (ctx.GREATER_THAN() != null) {
comp = new CompNode(ctx.GREATER_THAN());
comp = new CompOpNode(ctx.GREATER_THAN());
} else if (ctx.EQUALS() != null) {
comp = new CompNode(ctx.EQUALS());
comp = new CompOpNode(ctx.EQUALS());
} else if (ctx.GT_EQ() != null) {
comp = new CompNode(ctx.GT_EQ());
comp = new CompOpNode(ctx.GT_EQ());
} else if (ctx.LT_EQ() != null) {
comp = new CompNode(ctx.LT_EQ());
comp = new CompOpNode(ctx.LT_EQ());
} else if (ctx.NOT_EQ_2() != null) {
// We're ignoring NOT_EQ_1() because no one uses `<>`
comp = new CompNode(ctx.NOT_EQ_2());
comp = new CompOpNode(ctx.NOT_EQ_2());
} else if (ctx.IN() != null) {
comp = new CompNode(ctx.IN());
comp = new CompOpNode(ctx.IN());
} else if (ctx.NOT() != null) {
comp = new CompNode(ctx.NOT());
comp = new CompOpNode(ctx.NOT());
} else if (ctx.IS() != null) {
comp = new CompNode(ctx.IS());
comp = new CompOpNode(ctx.IS());
}

return comp;
Expand Down Expand Up @@ -396,6 +396,14 @@ public Node visitExpr(ExprContext ctx) {
op = ctx.NOT().toString();
}

if (ctx.AND() != null) {
op = ctx.AND().toString();
}

if (ctx.OR() != null) {
op = ctx.OR().toString();
}

if (ctx.STAR() != null) {
op = ctx.STAR().toString();
}
Expand All @@ -404,6 +412,10 @@ public Node visitExpr(ExprContext ctx) {
op = ctx.DIV().toString();
}

if (ctx.MOD() != null) {
op = ctx.MOD().toString();
}

if (ctx.atom() != null) {
atom = visit(ctx.atom());
}
Expand Down
15 changes: 8 additions & 7 deletions src/ast/nodes/ArglistNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,16 @@ public ArglistNode(ArrayList<Node> arguments) {
}

@Override
public ArrayList<SemanticError> checkSemantics(SymbolTable ST, int _nesting) {
public ArrayList<SemanticError> checkSemantics(SymbolTable ST, int _nesting, FunctionType ft) {
ArrayList<SemanticError> errors = new ArrayList<>();

for (var arg : arguments) {
if (arg instanceof ExprNode) {
ExprNode argExpr = (ExprNode) arg;
String argName = argExpr.getId();
errors.addAll(arg.checkSemantics(ST, _nesting, ft));

// TODO: check fucking IntType for params
// TODO: remove fucking comments
// TODO: check IntType for params
if (argName != null) {
if (Arrays.asList(bif).contains(argName)) {
continue;
Expand All @@ -40,8 +40,6 @@ public ArrayList<SemanticError> checkSemantics(SymbolTable ST, int _nesting) {
if (ST.nslookup(argName) < 0 && argExpr.typeCheck() instanceof AtomType) {
errors.add(new SemanticError("name '" + argName + "' is not defined."));
}
} else {
errors.addAll(arg.checkSemantics(ST, _nesting));
}
}
}
Expand All @@ -58,10 +56,13 @@ public Type typeCheck() {
return new VoidType();
}

// TODO: add code generation for arglist node
@Override
public String codeGeneration() {
return "";
String str = "";
for (Node arg : arguments) {
str += arg.codeGeneration() + "pushr A0\n";
}
return str;
}

@Override
Expand Down
65 changes: 48 additions & 17 deletions src/ast/nodes/AssignmentNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import ast.types.*;
import java.util.ArrayList;

import semanticanalysis.STentry;
import semanticanalysis.SemanticError;
import semanticanalysis.SymbolTable;

Expand All @@ -14,35 +16,45 @@ public class AssignmentNode implements Node {
private final Node assign;
private final ExprListNode rhr;

// Useful for code gen
private int offset;
private boolean alreadyDef;

public AssignmentNode(Node lhr, Node assign, Node rhr) {
this.lhr = (ExprListNode) lhr;
this.assign = assign;
this.rhr = (ExprListNode) rhr;
this.alreadyDef = false;
}

@Override
public ArrayList<SemanticError> checkSemantics(SymbolTable ST, int _nesting) {
public ArrayList<SemanticError> checkSemantics(SymbolTable ST, int _nesting, FunctionType ft) {
ArrayList<SemanticError> errors = new ArrayList<>();

// errors.addAll(lhr.checkSemantics(ST, _nesting));
errors.addAll(assign.checkSemantics(ST, _nesting));
errors.addAll(rhr.checkSemantics(ST, _nesting));
// DO NOT CHECK lhr
errors.addAll(assign.checkSemantics(ST, _nesting, ft));
errors.addAll(rhr.checkSemantics(ST, _nesting, ft));

int lsize = lhr.getSize();

// FIXME: unused variable
// int rsize = rhr.getSize();
// if (lsize == rsize) {
for (int i = 0; i < lsize; i++) {
ExprNode latom = (ExprNode) lhr.getElem(i);
ST.insert(latom.getId(), new AtomType(), _nesting, "");
// ExprNode ratom = (ExprNode) rhr.getElem(i);
}
// } else {
// FIX: sgravata da più problemi che altro
// errors.add(new SemanticError("ValueError: different size of left or right side assignment"));
// }
ExprNode leftAtom = (ExprNode) lhr.getElem(i);
STentry e = ST.lookup(leftAtom.getId());
if (ft != null) {
ft.addLocalVar();
}

if (e == null) {
ST.insert(leftAtom.getId(), new AtomType(), _nesting, "");
e = ST.lookup(leftAtom.getId());
} else {
int ns = e.getNesting();
if (_nesting == ns) {
this.alreadyDef = true;
}
}
offset = e.getOffset();
}
return errors;
}

Expand All @@ -52,10 +64,29 @@ public Type typeCheck() {
return rhr.typeCheck();
}

// TODO: add code generation for assignment
@Override
public String codeGeneration() {
return "";
String rhrString = rhr.codeGeneration();

String lhrString = "";
ExprNode leftAtom = (ExprNode) lhr.getElem(0);

// The code generation for the left atom returns a `store A0 0(T1)` at
// the end but we do not want that command.
// So, we'll have a string with the substring + the offset.
String leftAtomCode = leftAtom.codeGeneration();
lhrString += leftAtomCode.substring(0, leftAtomCode.length() - 17) + offset;

// If the variable name is previously defined it'll load the variable
// from the `0(T1)`, otherwise it'll push the `A0` register at the top
// of the stack.
if (!this.alreadyDef) {
lhrString += "\npushr A0\n";
} else {
lhrString += "\nload A0 0(T1)\n";
}

return rhrString + lhrString;
}

@Override
Expand Down
Loading