From 701381d04c2ae256f615481b405a523b0f92cd3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vanja=20Stojanovi=C4=87?= Date: Mon, 24 Apr 2023 14:44:38 +0200 Subject: [PATCH] =?UTF-8?q?Neki=20pa=20=C5=BEe=20dela=20zdj=20pr=20pizdi?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .vscode/launch.json | 4 +- src/compiler/.DS_Store | Bin 8196 -> 8196 bytes src/compiler/frm/FrameEvaluator.java | 89 +++++++++++++++++++---- src/compiler/seman/type/TypeChecker.java | 48 ++++++------ test.pns | 62 +++++++++++++++- 5 files changed, 158 insertions(+), 45 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 9d13468..1e0bfe1 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -17,7 +17,7 @@ "request": "launch", "mainClass": "Main", "projectName": "PINSCompiler_aaffa8a2", - "args": "PINS --exec TYP --dump TYP test.pns" + "args": "PINS --exec FRM --dump FRM test.pns" }, { "type": "java", @@ -25,7 +25,7 @@ "request": "launch", "mainClass": "App", "projectName": "PINSCompiler_aaffa8a2", - "args": "test ./ TestsRunner/tests/5-typ.tst -v" + "args": "test ./ TestsRunner/tests/6-frm-1.tst -v" }, { "type": "java", diff --git a/src/compiler/.DS_Store b/src/compiler/.DS_Store index d136feac6f5d6b347de2c1afb1b8fde7a0dc4fa7..99fdbf32ab3072198315ae79c54695822d5c1af6 100644 GIT binary patch delta 14 VcmZp1XmQwZUy#vg^8-N@J^(9l1u_5t delta 16 XcmZp1XmQwZUvRRyh{I-ip{Kk6H~t14 diff --git a/src/compiler/frm/FrameEvaluator.java b/src/compiler/frm/FrameEvaluator.java index d4ddb83..6c2f222 100644 --- a/src/compiler/frm/FrameEvaluator.java +++ b/src/compiler/frm/FrameEvaluator.java @@ -8,6 +8,7 @@ import static common.RequireNonNull.requireNonNull; import compiler.common.Visitor; +import compiler.frm.Access.Local; import compiler.parser.ast.def.*; import compiler.parser.ast.def.FunDef.Parameter; import compiler.parser.ast.expr.*; @@ -17,6 +18,10 @@ import compiler.seman.common.NodeDescription; import compiler.seman.type.type.Type; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Stream; + public class FrameEvaluator implements Visitor { /** * Opis definicij funkcij in njihovih klicnih zapisov. @@ -44,9 +49,14 @@ public class FrameEvaluator implements Visitor { private int staticLevel; /* - * Števec za stack offset + * Lista stackOffseta trenutnega staticLevel-a oz. funkcijskega klica + */ + private List stackOffset; + + /* + * Lista funkcijskih klicev */ - private int stackOffset; + private List functionCalls; public FrameEvaluator( NodeDescription frames, @@ -58,19 +68,27 @@ public FrameEvaluator( this.accesses = accesses; this.definitions = definitions; this.types = types; - staticLevel = 1; - stackOffset = 0; + + staticLevel = 0; + stackOffset = new ArrayList(); + + functionCalls = new ArrayList(); } @Override public void visit(Call call) { - if (staticLevel == 1) { + if (staticLevel == 0) { accesses.store(new Access.Global(types.valueFor(definitions.valueFor(call).get()).get().sizeInBytes(), frames.valueFor(definitions.valueFor(call).get()).get().label), call); } else { accesses.store(new Access.Local(types.valueFor(definitions.valueFor(call).get()).get().sizeInBytes(), - stackOffset, staticLevel), call); + stackOffset.get(staticLevel - 1).getTopLocVarOffset(), staticLevel), call); } + + int argSize = call.arguments.stream() + .map(argument -> types.valueFor(argument).get().sizeInBytesAsParam()) + .reduce(0, Integer::sum); + functionCalls.set(staticLevel - 1, Math.max(functionCalls.get(staticLevel - 1).intValue(), argSize)); } @Override @@ -144,21 +162,30 @@ public void visit(Defs defs) { @Override public void visit(FunDef funDef) { + stackOffset.add(new StackOffsets()); + functionCalls.add(Integer.valueOf(0)); compiler.frm.Frame.Builder Builder = null; - if (staticLevel == 1) { - Builder = new Frame.Builder(Frame.Label.named(funDef.name), staticLevel); + if (staticLevel == 0) { + Builder = new Frame.Builder(Frame.Label.named(funDef.name), ++staticLevel); } else { - Builder = new Frame.Builder(Frame.Label.nextAnonymous(), staticLevel); + Builder = new Frame.Builder(Frame.Label.nextAnonymous(), ++staticLevel); } for (Parameter param : funDef.parameters) { param.accept(this); Builder.addParameter(types.valueFor(param).get().sizeInBytesAsParam()); } - staticLevel++; funDef.body.accept(this); + + for (Integer Int : stackOffset.get(staticLevel - 1).locVarStackOffset) { + Builder.addLocalVariable(-Int.intValue()); + } + Builder.addFunctionCall(functionCalls.get(staticLevel - 1).intValue()); + staticLevel--; frames.store(Builder.build(), funDef); + stackOffset.remove(staticLevel); + functionCalls.remove(staticLevel); } @Override @@ -167,21 +194,28 @@ public void visit(TypeDef typeDef) { @Override public void visit(VarDef varDef) { - if (staticLevel == 1) { + if (staticLevel == 0) { accesses.store( new Access.Global(types.valueFor(varDef).get().sizeInBytes(), Frame.Label.named(varDef.name)), varDef); } else { - accesses.store(new Access.Local(types.valueFor(varDef).get().sizeInBytes(), stackOffset, staticLevel), + stackOffset.get(staticLevel - 1).addLocVarToStack(types.valueFor(varDef).get().sizeInBytes()); + accesses.store( + new Access.Local(types.valueFor(varDef).get().sizeInBytes(), + stackOffset.get(staticLevel - 1).getTopLocVarOffset(), + staticLevel), varDef); - stackOffset += types.valueFor(varDef).get().sizeInBytes(); } } @Override public void visit(Parameter parameter) { - accesses.store(new Access.Parameter(types.valueFor(parameter).get().sizeInBytesAsParam(), stackOffset, staticLevel), parameter); - stackOffset += types.valueFor(parameter).get().sizeInBytesAsParam(); + stackOffset.get(staticLevel - 1).addParamToStack(types.valueFor(parameter).get().sizeInBytesAsParam()); + accesses.store( + new Access.Parameter(types.valueFor(parameter).get().sizeInBytesAsParam(), + stackOffset.get(staticLevel - 1).paramStackOffset, + staticLevel), + parameter); } @Override @@ -195,4 +229,29 @@ public void visit(Atom atom) { @Override public void visit(TypeName name) { } + + /* + * Razred za hranjenje podatke o skladu vsake funkcije + */ + private class StackOffsets { + public int paramStackOffset; + public ArrayList locVarStackOffset; + + public StackOffsets() { + paramStackOffset = 0; + locVarStackOffset = new ArrayList(); + } + + public void addParamToStack(int size) { + paramStackOffset += size; + } + + public void addLocVarToStack(int size) { + locVarStackOffset.add(Integer.valueOf(-size)); + } + + public int getTopLocVarOffset() { + return locVarStackOffset.stream().reduce(0, Integer::sum); + } + } } diff --git a/src/compiler/seman/type/TypeChecker.java b/src/compiler/seman/type/TypeChecker.java index 796bfa7..d4cb90b 100644 --- a/src/compiler/seman/type/TypeChecker.java +++ b/src/compiler/seman/type/TypeChecker.java @@ -30,16 +30,23 @@ public class TypeChecker implements Visitor { * Opis vozlišč, ki jim priredimo podatkovne tipe. */ private NodeDescription types; + private List visited; public TypeChecker(NodeDescription definitions, NodeDescription types) { requireNonNull(definitions, types); this.definitions = definitions; this.types = types; + this.visited = new ArrayList<>(); } @Override public void visit(Call call) { - types.store(types.valueFor(definitions.valueFor(call).get()).get(), call); + Optional funDefReturnType = types.valueFor(definitions.valueFor(call).get()); + if (funDefReturnType.isEmpty()) { + ((FunDef) definitions.valueFor(call).get()).accept(this); + funDefReturnType = types.valueFor(definitions.valueFor(call).get()); + } + types.store(funDefReturnType.get().asFunction().get().returnType, call); call.arguments.forEach(arg -> { arg.accept(this); }); @@ -218,21 +225,8 @@ public void visit(Where where) { @Override public void visit(Defs defs) { defs.definitions.forEach(def -> { - if (def instanceof TypeDef typeDef) { - typeDef.accept(this); - } - }); - - defs.definitions.forEach(def -> { - if (def instanceof FunDef funDef) { - funDef.accept(this); - } else if (def instanceof TypeDef typeDef) { - - } else if (def instanceof VarDef varDef) { - varDef.accept(this); - } else { - Report.error(def.position, "Non-valid definition!"); - } + if (!visited.contains(def)) + def.accept(this); }); } @@ -258,13 +252,14 @@ public void visit(FunDef funDef) { @Override public void visit(TypeDef typeDef) { + checkRecursion(typeDef); typeDef.type.accept(this); types.store(types.valueFor(typeDef.type).get(), typeDef); - definitions.store(typeDef, typeDef.type); } @Override public void visit(VarDef varDef) { + checkRecursion(varDef); varDef.type.accept(this); types.store(types.valueFor(varDef.type).get(), varDef); } @@ -299,14 +294,17 @@ public void visit(Atom atom) { @Override public void visit(TypeName name) { - try { - Optional temp = definitions.valueFor(name); - if (temp.isEmpty()) - throw new Exception("null"); - Type neki = types.valueFor(temp.get()).get(); - types.store(neki, name); - } catch (Exception e) { - Report.error(name.position, "The type is not defined!"); + Def nameDef = definitions.valueFor(name).get(); + if (types.valueFor(nameDef).isEmpty()) { + nameDef.accept(this); + } + types.store(types.valueFor(nameDef).get(), name); + } + + private void checkRecursion(Def def) { + if (visited.contains(def)) { + Report.error(def.position, "Definition recursion detected!"); } + visited.add(def); } } diff --git a/test.pns b/test.pns index 942bfa6..ffcf919 100644 --- a/test.pns +++ b/test.pns @@ -1,3 +1,59 @@ -fun f(x:integer, y:integer): integer = g(x, y); -fun g(x:integer, y:integer): integer = f(x,y); -fun h(z: integer, y:string): logical = f(z,z) \ No newline at end of file +fun main(args:arr[100]int):int = ( + # najde najbolj pogost element v tabeli + # tabela ima elemente vrednosti od 1 do 10 vključno + + # napolnimo tabelo pogostosti z ničlami + {for i = 0, 10, 1: + {pogostost[i] = 0} + }, + + # preštejemo koliko je katerih elementov + {for i = 0, 100, 1: + {pogostost[args[i-1]] = pogostost[args[i-1]] + 1} + }, + + # poiščemo največjo vrednost v tabeli pogostosti + {max = najvecji(pogostost)}, + + # poiščemo indeks največje vrednosti v tabeli pogostosti + {max_index = index(pogostost, max)}, + + # vrnemo največji element + max_index+1 +) {where + var pogostost:arr[10]int; + var i:int; + var max:int; + var max_index:int; + + # definirane funkcije + fun najvecji(array:arr[10]int):int = ( + {max = 0}, + {for i = 0, 10, 1: + {if array[i] > max then + {max = array[i]} + } + }, + max + ) {where + var i:int; + var max:int + }; + + fun index(array:arr[10]int, value:int):int = ( + {returnValue = -1}, + {for i = 0, 10, 1: + {if array[i] == value & returnValue == -1 then + {returnValue = i} + } + }, + returnValue + ) {where + var i:int; + var returnValue:int + } +}; + +typ int:integer; +typ str:string; +typ bool:logical \ No newline at end of file