From d1b3319a74efc4ed37c6b492a5d374f93e3f3e74 Mon Sep 17 00:00:00 2001 From: "Tristan B. Velloza Kildaire" Date: Sat, 17 Dec 2022 19:02:14 +0200 Subject: [PATCH] Instruction - Added new instruction type `ReturnInstruction` Data - Adjusted return statement parser node weighting to 2 (makes it on the same level as normal body statements) Dependency - Added dependency generation for return statements - Removed old commented-out code in the function-definition generation section of `generalPass()` TypeChecker/Codegen - Added code generation for return statements DGen - Added code emitting for return statements (`ReturnInstruction`) Test cases - Updated test case `simple_functions.t` to test return statements --- source/tlang/compiler/codegen/emit/dgen.d | 14 +++ source/tlang/compiler/codegen/instruction.d | 16 +++ source/tlang/compiler/symbols/data.d | 3 + source/tlang/compiler/typecheck/core.d | 22 +++++ .../compiler/typecheck/dependency/core.d | 97 ++++--------------- source/tlang/testing/simple_functions.t | 2 + 6 files changed, 74 insertions(+), 80 deletions(-) diff --git a/source/tlang/compiler/codegen/emit/dgen.d b/source/tlang/compiler/codegen/emit/dgen.d index 2f5bfdb2..f3545b6e 100644 --- a/source/tlang/compiler/codegen/emit/dgen.d +++ b/source/tlang/compiler/codegen/emit/dgen.d @@ -185,6 +185,20 @@ public final class DCodeEmitter : CodeEmitter return emit; } + /* ReturnInstruction */ + else if(cast(ReturnInstruction)instruction) + { + gprintln("type: ReturnInstruction"); + + ReturnInstruction returnInstruction = cast(ReturnInstruction)instruction; + Context context = returnInstruction.getContext(); + assert(context); + + /* Get the return expression instruction */ + Value returnExpressionInstr = returnInstruction.getReturnExpInstr(); + + return "return "~transform(returnExpressionInstr)~";"; + } return ""; } diff --git a/source/tlang/compiler/codegen/instruction.d b/source/tlang/compiler/codegen/instruction.d index b8f85fca..72266b94 100644 --- a/source/tlang/compiler/codegen/instruction.d +++ b/source/tlang/compiler/codegen/instruction.d @@ -272,4 +272,20 @@ public class FuncCallInstr : CallInstr { return evaluationInstructions; } +} + + +public final class ReturnInstruction : Instruction +{ + private Value returnExprInstr; + + this(Value returnExprInstr) + { + this.returnExprInstr = returnExprInstr; + } + + public Value getReturnExpInstr() + { + return returnExprInstr; + } } \ No newline at end of file diff --git a/source/tlang/compiler/symbols/data.d b/source/tlang/compiler/symbols/data.d index 1122e8a5..3fef67d3 100644 --- a/source/tlang/compiler/symbols/data.d +++ b/source/tlang/compiler/symbols/data.d @@ -541,6 +541,9 @@ public final class ReturnStmt : Statement this(Expression returnExpression) { this.returnExpression = returnExpression; + + /* Statement level weighting is 2 */ + weight = 2; } public Expression getReturnExpression() diff --git a/source/tlang/compiler/typecheck/core.d b/source/tlang/compiler/typecheck/core.d index 9cb40cc1..5e1db16b 100644 --- a/source/tlang/compiler/typecheck/core.d +++ b/source/tlang/compiler/typecheck/core.d @@ -836,6 +836,28 @@ public final class TypeChecker addInstrB(vAInstr); } + /** + * Return statement (ReturnStmt) + */ + else if(cast(ReturnStmt)statement) + { + ReturnStmt returnStatement = cast(ReturnStmt)statement; + + /** + * Codegen + * + * 1. Pop the expression on the stack + * 2. Create a new ReturnInstruction with the expression instruction + * embedded in it + * 3. Set the Context of the instruction + * 4. Add this instruction back + */ + Value returnExpressionInstr = cast(Value)popInstr(); + assert(returnExpressionInstr); + ReturnInstruction returnInstr = new ReturnInstruction(returnExpressionInstr); + returnInstr.context = returnStatement.getContext(); + addInstrB(returnInstr); + } /* Case of no matches */ else { diff --git a/source/tlang/compiler/typecheck/dependency/core.d b/source/tlang/compiler/typecheck/dependency/core.d index 8d021b52..a6910803 100644 --- a/source/tlang/compiler/typecheck/dependency/core.d +++ b/source/tlang/compiler/typecheck/dependency/core.d @@ -1334,99 +1334,36 @@ public class DNodeGenerator } } /** - * Function declarations - * Status: Not done (TODO) + * Function definitions */ else if(cast(Function)entity) { // /* Grab the function */ Function func = cast(Function)entity; - // /* Set the context to be STATIC and relative to this Module */ - // Context d = new Context( cast(Container)modulle, InitScope.STATIC); - // func.setContext(d); - - // /* Pass the function declaration */ - // DNode funcDep = FunctionPass(func); - - // /* TODO: Surely we only require the module, it doesn't need us? */ - // /* TODO: Perhaps, no, it needs us to make it into the tree */ - // /* TODO: But NOT it's subcompnents */ - // funcDep.needs(moduleDNode); - // moduleDNode.needs(funcDep); /* TODO: Nah fam looks weird */ - - /** - * TODO: - * - * Perhaps all function calls should look up this node - * via pooling it and then they should depend on it - * which depends on module init - * - * Then whatever depends on function call will have module dependent - * on it, which does this but morr round about but seems to make more - * sense, idk - */ - - /** - * SOLUTION - * - * DOn;'t process declarations - * Process function calls, then look up the Function (declaration) - * and go through it pooling and seeing it's needs - */ - - /** - * Other SOLUTION - * - * We go through and process the declaration and get - * what each variable depends on, we then return this - * And we have a function that does that for us - * but WE DON'T IMPLEMENT THAT HERE IN modulePass() - * - * Rather each call will do it, and because we pool - * we will add DNOdes that then flatten out - */ - - /** - * EVEN BETTER (+PREVIOUS SOLUTION) - * - * We process it here yet we do not - * add thre entity themselves as dnodes - * only their dependents and return that - * Accounting ONLY for external dependencies - * WE STORE THIS INA FUNCTIONMAP - * - * We DO call this here - * - * On a FUNCTION **CALL** do a normal pass on - * the FUNCTIONMAP entity, in a way that doesn't - * add to our tree for Modulle. Effectively - * giving us a uniue dependecny tree per call - * which is fine for checking things and also - * for (what is to come - code generation) AS - * THEN we want duplication. Calling something - * twice means two sets of instructions, not one - * (as a result from pooled dependencies or USING - * the same pool) - */ - /* Add funtion definition */ gprintln("Hello"); addFunctionDef(tc, func); + } + /** + * Return statement + */ + else if(cast(ReturnStmt)entity) + { + ReturnStmt returnStatement = cast(ReturnStmt)entity; + returnStatement.setContext(context); - /* TODO: Hoist stuff from pre-processing */ + DNode returnStatementDNode = pool(returnStatement); - /* TODO: New code from 1st October */ - /* Recurse downwards */ - /* FIXME: The context container must be fixed, see passClazz, we pass the euiavlent of `func` in there */ - // Context funcContext = new Context(tc.getModule(), InitScope.STATIC); - // DNode funcDefDNode = generalPass(func, funcContext); + /* Process the return expression */ + Expression returnExpression = returnStatement.getReturnExpression(); + DNode returnExpressionDNode = expressionPass(returnExpression, context); + /* Make return depend on the return expression */ + returnStatementDNode.needs(returnExpressionDNode); - /** - * Save the function dnode for lookup later - */ - // saveFunctionDefinitionNode(funcDefDNode); + /* Make this container depend on this return statement */ + node.needs(returnStatementDNode); } } diff --git a/source/tlang/testing/simple_functions.t b/source/tlang/testing/simple_functions.t index f1d2db0d..938f7ef3 100644 --- a/source/tlang/testing/simple_functions.t +++ b/source/tlang/testing/simple_functions.t @@ -11,6 +11,8 @@ int apple(int arg1, int arg2) k=arg1+arg2; simple_functions.k=arg1+arg2; + + return arg1; } int banana(int arg1)