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
This commit is contained in:
Tristan B. Velloza Kildaire 2022-12-17 19:02:14 +02:00
parent 2140747a36
commit d1b3319a74
6 changed files with 74 additions and 80 deletions

View File

@ -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 "<TODO: Base emit: "~to!(string)(instruction)~">";
}

View File

@ -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;
}
}

View File

@ -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()

View File

@ -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
{

View File

@ -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);
}
}

View File

@ -11,6 +11,8 @@ int apple(int arg1, int arg2)
k=arg1+arg2;
simple_functions.k=arg1+arg2;
return arg1;
}
int banana(int arg1)