From 2f0439868b19326f34e6a5de3aa96b7d74fce58f Mon Sep 17 00:00:00 2001 From: geno Date: Tue, 9 Jul 2024 18:35:19 +0200 Subject: [PATCH] recursive function works --- src/ast/nodes/AtomNode.java | 18 ++- src/ast/nodes/ExprNode.java | 188 ++++++++++++++++++++++------ src/ast/nodes/FuncdefNode.java | 13 +- src/ast/nodes/IfNode.java | 24 ++-- src/ast/nodes/ReturnStmtNode.java | 15 ++- src/ast/nodes/RootNode.java | 4 +- src/ast/nodes/TestlistCompNode.java | 7 +- src/codegen/Label.java | 9 ++ src/svm/ExecuteVM.java | 14 ++- src/svm/SVMVisitorImpl.java | 1 + test/3-3.py | 5 +- 11 files changed, 229 insertions(+), 69 deletions(-) diff --git a/src/ast/nodes/AtomNode.java b/src/ast/nodes/AtomNode.java index 2457c10..8ac1c38 100644 --- a/src/ast/nodes/AtomNode.java +++ b/src/ast/nodes/AtomNode.java @@ -14,8 +14,9 @@ public class AtomNode implements Node { protected String val; protected TestlistCompNode exprlist; - + // very scatchy + protected int ns; protected int offset; public AtomNode(String val, Node exprlist) { @@ -40,7 +41,9 @@ public ArrayList checkSemantics(SymbolTable ST, int _nesting) { errors.add(new SemanticError("name '" + getId() + "' is not defined.")); } else { // System.out.println("exist " + getId()); - if ((typeCheck() instanceof AtomType)){ + if ((typeCheck() instanceof AtomType)) { + int varNs = ST.lookup(getId()).getNesting(); + ns = _nesting - varNs; offset = ST.lookup(getId()).getOffset(); } } @@ -98,9 +101,9 @@ public Type typeCheck() { @Override public String codeGeneration() { String baseData = "storei A0 "; - String baseAccess = "load A0 "; + // String baseAccess = "load A0 "; - if(exprlist != null) { + if (exprlist != null) { return exprlist.codeGeneration(); } if (typeCheck() instanceof IntType) { @@ -110,7 +113,12 @@ public String codeGeneration() { return baseData + boolValue(getId()) + "\n"; } if (typeCheck() instanceof AtomType) { - return baseAccess + String.valueOf(offset) + "(FP)\n" ; + String str = "move AL T1\n"; + for (int i = 0; i < ns; i++) { + str += "store T1 0(T1)\n"; + } + str += "subi T1 " + (offset - 1) + "\nstore A0 0(T1)\n"; + return str; } return "Error: could not parse an atom\n"; } diff --git a/src/ast/nodes/ExprNode.java b/src/ast/nodes/ExprNode.java index 8dbc8d3..5b7cfdd 100644 --- a/src/ast/nodes/ExprNode.java +++ b/src/ast/nodes/ExprNode.java @@ -61,7 +61,8 @@ public ArrayList checkSemantics(SymbolTable ST, int _nesting) { // check if the atom is a function if (atom != null && !trailers.isEmpty()) { - + + System.out.println("EVAL ATOM " + atom.getId()); // check if the atom is not a built-in function if (!Arrays.asList(bif).contains(atom.getId())) { @@ -84,19 +85,22 @@ public ArrayList checkSemantics(SymbolTable ST, int _nesting) { FunctionType ft = (FunctionType) fun.getType(); paramNumber = ft.getParamNumber(); funL = ft.getLabel(); + System.out.println("FUN " + funL); int argNumber = trailer.getArgumentNumber(); if (paramNumber != argNumber) { errors.add(new SemanticError(funName + "() takes " + String.valueOf(paramNumber) + " positional arguments but " + String.valueOf(argNumber) + " were given.")); } + for (var t : trailers) { + errors.addAll(t.checkSemantics(ST, _nesting)); + } } } } else { for (var trailer : trailers) { errors.addAll(trailer.checkSemantics(ST, _nesting)); } - } } else if (atom != null) { errors.addAll(atom.checkSemantics(ST, _nesting)); @@ -126,18 +130,29 @@ public Type typeCheck() { @Override public String codeGeneration() { // check function call + if (atom != null && !trailers.isEmpty()) { TrailerNode trailer = (TrailerNode) trailers.get(0); String trailerS = trailer.codeGeneration(); // check if the atom is a built-in function - if (Arrays.asList(bif).contains(atom.getId())) { - // TODO: AGGIUNGERE COMMENTI PER SPIEGARE GESTIONE PRINT - return trailerS; - } + // if (Arrays.asList(bif).contains(atom.getId())) { + // // TODO: AGGIUNGERE COMMENTI PER SPIEGARE GESTIONE PRINT + // return trailerS; + // } // taken from slide 56 of CodeGeneration.pdf - String parNum = String.valueOf(paramNumber + 1); - return "pushr FP\n" + trailerS + "move SP FP\naddi FP " + parNum + "\njsub " + funL + "\n"; + // String parNum = String.valueOf(paramNumber + 1); + System.out.println("LABEL " + funL); + return "pushr FP\n" + + "move SP FP\n" + + "addi FP 1\n" + + "move AL T1\n" + + "pushr T1\n" + // slide 62, non implementiamo il for loop perché non supportiamo funzioni + // annidate + trailerS + + "move FP AL\n" + + "subi AL 1\n" + + "jsub " + funL + "\n"; } // check operation @@ -159,14 +174,28 @@ public String codeGeneration() { default: return "Error: operation " + op + " not supported\n"; } - } // check comp operation if (compOp != null) { CompOpNode cmpOp = (CompOpNode) compOp; String op = cmpOp.getOp(); - return boolOpCodeGen(exprs.get(0), exprs.get(1), op); + switch (op) { + case "==": + return eqCodeGen(exprs.get(0), exprs.get(1)); + case "!=": + return neqCodeGen(exprs.get(0), exprs.get(1)); + case "<": + return lsCodeGen(exprs.get(0), exprs.get(1)); + case "<=": + return leqCodeGen(exprs.get(0), exprs.get(1)); + case ">": + return gtCodeGen(exprs.get(0), exprs.get(1)); + case ">=": + return gteCodeGen(exprs.get(0), exprs.get(1)); + default: + return "Error: operation " + op + " not supported\n"; + } } if (atom != null) { @@ -275,41 +304,118 @@ public String notCodeGen(Node expr) { return exprs + "storei T1 1\nsub T1 A0\npopr A0\n"; } - public String boolOpCodeGen(Node leftE, Node rightE, String op) { + public String eqCodeGen(Node leftE, Node rightE) { String truel = Label.newBasic("true"); String endl = Label.newBasic("end"); String ls = leftE.codeGeneration(); String rs = rightE.codeGeneration(); - String ops; - switch (op) { - case ">": - ops = "bgt"; - break; - case "<": - ops = "blt"; - break; - case ">=": - ops = "bge"; - break; - case "<=": - ops = "ble"; - break; - case "==": - ops = "beq"; - break; - case "!=": - // inverse of == - return ls + "pushr A0\n" + - rs + "popr T1\n" + - "beq T1 A0 " + truel + "\nstorei A0 1\nb " + endl + "\n" + // storei A0 1 instead of storei A0 0 - truel + ":\nstorei A0 0\n" + endl + ":\n"; // storei A0 0 instead of storei A0 1 - default: - return "Error: operation " + op + " not supported\n"; - } - return ls + "pushr A0\n" + - rs + "popr T1\n" + - ops + " T1 A0 " + truel + "\nstorei A0 0\nb " + endl + "\n" + - truel + ":\nstorei A0 1\n" + endl + ":\n"; + return ls + + "pushr A0\n" + + rs + + "popr T1\n" + + "beq T1 A0 " + truel + "\n" + + "storei A0 0\n" + + "b " + endl + "\n" + + truel + ":\n" + + "storei A0 1\n" + + endl + ":\n"; + } + + public String neqCodeGen(Node leftE, Node rightE) { + String truel = Label.newBasic("true"); + String endl = Label.newBasic("end"); + String ls = leftE.codeGeneration(); + String rs = rightE.codeGeneration(); + return ls + + "pushr A0\n" + + rs + + "popr T1\n" + + "beq T1 A0 " + truel + "\n" + + "storei A0 1\n" + + "b " + endl + "\n" + // storei A0 1 instead of storei A0 0 + truel + ":\n" + + "storei A0 0\n" + // storei A0 0 instead of storei A0 1 + endl + ":\n"; + } + + public String lsCodeGen(Node leftE, Node rightE) { + String truel = Label.newBasic("true"); + String truel2 = Label.newBasic("true"); + String endl = Label.newBasic("end"); + String ls = leftE.codeGeneration(); + String rs = rightE.codeGeneration(); + return ls + + "pushr A0\n" + + rs + + "popr T1\n" + + "bleq T1 A0 " + truel + "\n" + + "storei A0 0\n" + + "b " + endl + "\n" + + truel + ":\n" + + "beq T1 A0 " + truel2 + "\n" + + "storei A0 1\n" + + "b " + endl + "\n" + + truel2 + ":\n" + + "storei A0 0\n" + + "b " + endl + "\n" + + endl + ":\n"; + } + + public String leqCodeGen(Node leftE, Node rightE) { + String truel = Label.newBasic("true"); + String endl = Label.newBasic("end"); + String ls = leftE.codeGeneration(); + String rs = rightE.codeGeneration(); + return ls + + "pushr A0\n" + + rs + + "popr T1\n" + + "bleq T1 A0 " + truel + "\n" + + "storei A0 0\n" + + "b " + endl + "\n" + + truel + ":\n" + + "storei A0 1\n" + + endl + ":\n"; + } + + public String gtCodeGen(Node leftE, Node rightE) { + String truel = Label.newBasic("true"); + String endl = Label.newBasic("end"); + String ls = leftE.codeGeneration(); + String rs = rightE.codeGeneration(); + return ls + + "pushr A0\n" + + rs + + "popr T1\n" + + "bleq A0 T1 " + truel + "\n" + // inverto A0 e T1 rispetto a leq + "storei A0 0\n" + + "b " + endl + "\n" + + truel + ":\n" + + "storei A0 1\n" + + endl + ":\n"; + } + + public String gteCodeGen(Node leftE, Node rightE) { + String truel = Label.newBasic("true"); + String truel2 = Label.newBasic("true"); + String endl = Label.newBasic("end"); + String ls = leftE.codeGeneration(); + String rs = rightE.codeGeneration(); + return ls + + "pushr A0\n" + + rs + + "popr T1\n" + + "bleq T1 A0 " + truel + "\n" + + "storei A0 1\n" + + "b " + endl + "\n" + + truel + ":\n" + + "beq T1 A0 " + truel2 + "\n" + + "storei A0 0\n" + + "b " + endl + "\n" + + truel2 + ":\n" + + "storei A0 1\n" + + "b " + endl + "\n" + + endl + ":\n"; } } diff --git a/src/ast/nodes/FuncdefNode.java b/src/ast/nodes/FuncdefNode.java index c9f744e..cd35dc8 100644 --- a/src/ast/nodes/FuncdefNode.java +++ b/src/ast/nodes/FuncdefNode.java @@ -44,12 +44,11 @@ public ArrayList checkSemantics(SymbolTable ST, int _nesting) { ST.insert(funName, ft, _nesting + 1, ""); + // Offset is increased for the possible return value if (paramlist != null) { errors.addAll(paramlist.checkSemantics(ST, _nesting + 1)); } - // TODO: think to the offset - // Offset is increased for the possible return value ST.increaseoffset(); errors.addAll(block.checkSemantics(ST, _nesting + 1)); @@ -67,14 +66,18 @@ public Type typeCheck() { return new VoidType(); } - // taken from slide 56 of CodeGeneration.pdf + // taken from slide 56 of CodeGeneration.pdf @Override public String codeGeneration() { Label.setFuntrace(this.name.toString()); String blockS = block.codeGeneration(); - String skipL = Label.newBasic("skip"); // nel block c'è il return che mette a posto l'RA - return "b " + skipL + "\n" + funLabel + ":\npushr RA\n" + blockS + skipL + ":\n"; + + String funS = funLabel + ":\n" + + "pushr RA\n" + + blockS; + Label.addFunDef(funS); + return ""; } @Override diff --git a/src/ast/nodes/IfNode.java b/src/ast/nodes/IfNode.java index 77afe74..9aa6e7a 100644 --- a/src/ast/nodes/IfNode.java +++ b/src/ast/nodes/IfNode.java @@ -41,8 +41,8 @@ public Type typeCheck() { Type thenexp = thenBranch.typeCheck(); Type elseexp = elseBranch.typeCheck(); if (thenexp.getClass().equals(elseexp.getClass())) { - return thenexp; - }else { + return thenexp; + } else { System.out.println("Type Error: incompatible types in then and else branches."); return new ErrorType(); } @@ -59,12 +59,22 @@ public String codeGeneration() { String guardS = guard.codeGeneration(); String thenS = thenBranch.codeGeneration(); - String elseS = elseBranch.codeGeneration(); + String elseS = ""; + if (elseBranch != null) { + elseS = elseBranch.codeGeneration(); + } - // Assumo che la guardia sia un dato booleano o una operazione booleana che mette in A0 il valore true (1) o false (0) - return guardS + "storei T1 1\nbeq A0 T1 " + thenLabel + "\n" + // Controllo che A0 sia true (1). Se vero faccio jump alla - elseS + "b " + endLabel + "\n" + // thenBranch, altrimenti eseguo la elseBranch e jumpo alla fine - thenLabel + ":\n" + thenS + endLabel + ":\n"; + // Assumo che la guardia sia un dato booleano o una operazione booleana che + // mette in A0 il valore true (1) o false (0) + return guardS + + "storei T1 1\n" + + "beq A0 T1 " + thenLabel + "\n" + // Controllo che A0 sia true (1). Se vero faccio jump alla + // thenBranch, altrimenti eseguo la elseBranch e jumpo alla fine + elseS + + "b " + endLabel + "\n" + + thenLabel + ":\n" + + thenS + + endLabel + ":\n"; } @Override diff --git a/src/ast/nodes/ReturnStmtNode.java b/src/ast/nodes/ReturnStmtNode.java index 38c7267..1c4604f 100644 --- a/src/ast/nodes/ReturnStmtNode.java +++ b/src/ast/nodes/ReturnStmtNode.java @@ -17,7 +17,7 @@ public class ReturnStmtNode implements Node { private final Node exprList; // VERY scatchy - private int pm; + private int paramNumber; public ReturnStmtNode(Node exprList) { this.exprList = exprList; @@ -30,7 +30,7 @@ public ArrayList checkSemantics(SymbolTable ST, int _nesting) { String id = Label.getFuntrace(); STentry ftEntry = ST.lookup(id); FunctionType ft = (FunctionType) ftEntry.getType(); - this.pm = ft.getParamNumber(); + this.paramNumber = ft.getParamNumber(); if (this.exprList != null) { errors.addAll(this.exprList.checkSemantics(ST, _nesting)); } @@ -50,8 +50,15 @@ public Type typeCheck() { @Override public String codeGeneration() { String expS = exprList.codeGeneration(); - String paramNS = String.valueOf(pm); - return expS + "popr RA\naddi SP " + paramNS + "\npopr FP\nrsub RA\n"; + return expS + + "popr RA\n" + + "addi SP " + paramNumber + "\n" + + "pop\n" + + "store FP 0(FP)\n" + + "move FP AL\n" + + "subi AL 1\n" + + "pop\n" + + "rsub RA\n"; } @Override diff --git a/src/ast/nodes/RootNode.java b/src/ast/nodes/RootNode.java index e3c8c1d..c4dd0bb 100644 --- a/src/ast/nodes/RootNode.java +++ b/src/ast/nodes/RootNode.java @@ -1,6 +1,8 @@ package ast.nodes; import ast.types.*; +import codegen.Label; + import java.util.ArrayList; import java.util.HashMap; import semanticanalysis.*; @@ -52,7 +54,7 @@ public String codeGeneration() { str += child.codeGeneration(); } - return str + "halt"; + return str + "halt\n" + Label.getFunDef(); } @Override diff --git a/src/ast/nodes/TestlistCompNode.java b/src/ast/nodes/TestlistCompNode.java index d92637c..5ca202e 100644 --- a/src/ast/nodes/TestlistCompNode.java +++ b/src/ast/nodes/TestlistCompNode.java @@ -30,10 +30,13 @@ public ArrayList checkSemantics(SymbolTable ST, int _nesting) { ST.insert(id, t, _nesting, ""); // errors.addAll(comp.checkSemantics(ST, _nesting)); } else { - // if comp is not set, then exprs is a list of 1 or more element + // TODO: controllare per bene questo ramo + // if comp is not set, then exprs is a list of 1 or more element) for (var param : exprs) { var exp = (ExprNode) param; - ST.insert(exp.getId(), exp.typeCheck(), _nesting, ""); + if (exp.getId() != null) { + ST.insert(exp.getId(), exp.typeCheck(), _nesting, ""); + } errors.addAll(param.checkSemantics(ST, _nesting)); } } diff --git a/src/codegen/Label.java b/src/codegen/Label.java index c06d7e1..1b6a98a 100644 --- a/src/codegen/Label.java +++ b/src/codegen/Label.java @@ -3,6 +3,7 @@ public class Label { private static String funtrace = "root"; + private static String funDef = ""; private static int labelCounter = 0; private static int functionLabelCounter = 0; @@ -18,6 +19,14 @@ public static String getFuntrace() { return funtrace; } + public static void addFunDef(String s) { + funDef += s; + } + + public static String getFunDef() { + return funDef; + } + /** * Create a new basic label. Use this method to define labels for if, while and * for statemests. diff --git a/src/svm/ExecuteVM.java b/src/svm/ExecuteVM.java index 353fdc8..f14bb4f 100755 --- a/src/svm/ExecuteVM.java +++ b/src/svm/ExecuteVM.java @@ -1,5 +1,7 @@ package svm; +import java.util.concurrent.TimeUnit; + public class ExecuteVM { public static final int CODESIZE = 1000 ; @@ -27,7 +29,7 @@ public void StampaMem(int _j){ for (int i = MEMSIZE-1; i > sp ; i--){ System.out.print("\t" + memory[i]) ; } - System.out.println("\t ------" + "SP = " + sp + ", FP = " + fp + ", AL = " + al + ", RA = " + ra + ", A0 = " + a0 + ", T1 = " + t1 ) ; + System.out.println(" ----- " + "SP = " + sp + ", FP = " + fp + ", AL = " + al + ", RA = " + ra + ", A0 = " + a0 + ", T1 = " + t1 ) ; } public int read(String _strg) { @@ -100,6 +102,12 @@ public void cpu() { int j = 0 ; while ( true ) { + // try { + // TimeUnit.SECONDS.sleep(1); + // } catch (InterruptedException e) { + // // TODO Auto-generated catch block + // e.printStackTrace(); + // } StampaMem(j) ; j=j+1 ; AssemblyClass bytecode = code[ip] ; // fetch int tmp ; @@ -118,7 +126,7 @@ public void cpu() { ip = ip+1 ; break; case SVMParser.LOAD: - tmp = read(bytecode.getArg3()) - Integer.parseInt(bytecode.getArg2()) ; // was + + tmp = read(bytecode.getArg3()) + Integer.parseInt(bytecode.getArg2()) ; // was + if ((tmp < 0) || (tmp >= MEMSIZE)) { System.out.println("\nError: Null pointer exception1"); return; @@ -132,7 +140,7 @@ public void cpu() { ip = ip+1 ; break; case SVMParser.STORE: - tmp = read(bytecode.getArg3()) - Integer.parseInt(bytecode.getArg2()) ; // was + + tmp = read(bytecode.getArg3()) + Integer.parseInt(bytecode.getArg2()) ; // was + if ((tmp < 0) || (tmp >= MEMSIZE)) { System.out.println("\nError: Null pointer exception2"); return; diff --git a/src/svm/SVMVisitorImpl.java b/src/svm/SVMVisitorImpl.java index 391b986..749a977 100644 --- a/src/svm/SVMVisitorImpl.java +++ b/src/svm/SVMVisitorImpl.java @@ -23,6 +23,7 @@ public Void visitAssembly(SVMParser.AssemblyContext ctx) { if (code[tmp] == null) { code[tmp] = new AssemblyClass(labelAdd.get(s), null, null, null); } else { + System.out.println(labelRef); code[tmp].setArg1(labelAdd.get(s).toString()); } } diff --git a/test/3-3.py b/test/3-3.py index 6738186..0ea01ca 100644 --- a/test/3-3.py +++ b/test/3-3.py @@ -1,5 +1,8 @@ def fibonacci(n): - return n + if (n <= 2): + return 1 + else: + return (fibonacci(n-1) + fibonacci(n-2)) fibonacci(6)