Instruction
- Make the name of the function const and public for FuncCallInstr CodeEmitter - Added methods `getCursor()`, `getSelectedQueueLength()` and `getQueueLength()` - Removed old queue-specific methods DGen - Added emitting for FuncCallInstr instruction (function call support) - Now emit globals first BEFORE function definitions - Added debug prints per instruction to know what instruction is currently being transform()'d - After emitting sections add newlines between each to make for neater C code - `emitEntryPoint()` now adds a test for `simple_function_decls.t` (This should be removed soon) - Removed incorrect TODO in `finalize()` Dependency - Make the `nodePool` static, to ensure pooling carries over across multiple `DNodeGenerator` instances - Fixed handling of function calls in `expressionPass()` - do NOT add a so-called `FunctionDefNode` (remember functions are defined by `addFuncDef()`) - Set the Context of standalone variable assignments to the Context of the Variable entity representing the variable being assigned to TypeChecker - Assign the Context object stored in the `FunctionCall` statement to the `FuncCallInstr` Test cases - Updated test case `simple_function_decls.t`
This commit is contained in:
parent
8a481fb0ac
commit
2a12c310a6
|
@ -20,6 +20,7 @@ import std.conv : to;
|
|||
public abstract class CodeEmitter
|
||||
{
|
||||
protected TypeChecker typeChecker;
|
||||
protected File file;
|
||||
|
||||
/**
|
||||
* The selected queue is the queue to be used
|
||||
|
@ -88,6 +89,20 @@ public abstract class CodeEmitter
|
|||
return selectedQueue[queueCursor];
|
||||
}
|
||||
|
||||
public final ulong getCursor()
|
||||
{
|
||||
return queueCursor;
|
||||
}
|
||||
|
||||
public final ulong getSelectedQueueLength()
|
||||
{
|
||||
return selectedQueue.length;
|
||||
}
|
||||
|
||||
public final ulong getQueueLength()
|
||||
{
|
||||
return selectedQueue.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Required queues
|
||||
|
@ -100,67 +115,16 @@ public abstract class CodeEmitter
|
|||
*/
|
||||
private Instruction[][string] functionBodyInstrs;
|
||||
|
||||
|
||||
protected File file;
|
||||
|
||||
public final ulong getQueueLength()
|
||||
public final ulong getFunctionDefinitionsCount()
|
||||
{
|
||||
return selectedQueue.length;
|
||||
return functionBodyInstrs.keys().length;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public final string[] getFunctionDefinitionNames()
|
||||
{
|
||||
return functionBodyInstrs.keys();
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: Make some sort of like cursor object here that lets you move for function
|
||||
* or actually just have a function cuirsor
|
||||
*/
|
||||
private ulong globalCurrentFunctionDefintionCodeQueueIdx = 0;
|
||||
private string currentFunctionDefinitionName;
|
||||
|
||||
/**
|
||||
* Moves thr cursor (for the CFDCQ) back to the starting
|
||||
* position (zero)
|
||||
*/
|
||||
public final void resetCFDCQCursor()
|
||||
{
|
||||
globalCurrentFunctionDefintionCodeQueueIdx = 0;
|
||||
}
|
||||
|
||||
public final bool hasFunctionDefinitionInstructions()
|
||||
{
|
||||
return globalCurrentFunctionDefintionCodeQueueIdx < functionBodyInstrs[currentFunctionDefinitionName].length;
|
||||
}
|
||||
|
||||
public final void nextFunctionDefinitionCode()
|
||||
{
|
||||
globalCurrentFunctionDefintionCodeQueueIdx++;
|
||||
}
|
||||
|
||||
public final void previousFunctionDefinitionCode()
|
||||
{
|
||||
globalCurrentFunctionDefintionCodeQueueIdx--;
|
||||
}
|
||||
|
||||
public final Instruction getCurrentFunctionDefinitionInstruction()
|
||||
{
|
||||
return functionBodyInstrs[currentFunctionDefinitionName][globalCurrentFunctionDefintionCodeQueueIdx];
|
||||
}
|
||||
|
||||
public final void setCurrentFunctionDefinition(string functionDefinitionName)
|
||||
{
|
||||
currentFunctionDefinitionName = functionDefinitionName;
|
||||
}
|
||||
|
||||
|
||||
this(TypeChecker typeChecker, File file)
|
||||
{
|
||||
this.typeChecker = typeChecker;
|
||||
|
|
|
@ -33,15 +33,20 @@ public final class DCodeEmitter : CodeEmitter
|
|||
|
||||
public override string transform(const Instruction instruction)
|
||||
{
|
||||
import std.stdio;
|
||||
writeln("\n");
|
||||
gprintln("transform(): "~to!(string)(instruction));
|
||||
|
||||
/* VariableAssignmentInstr */
|
||||
if(cast(VariableAssignmentInstr)instruction)
|
||||
{
|
||||
gprintln("type: VariableAssignmentInstr");
|
||||
|
||||
VariableAssignmentInstr varAs = cast(VariableAssignmentInstr)instruction;
|
||||
Context context = varAs.getContext();
|
||||
|
||||
gprintln("Is ContextNull?: "~to!(string)(context is null));
|
||||
gprintln("Wazza contect: "~to!(string)(context.container));
|
||||
auto typedEntityVariable = context.tc.getResolver().resolveBest(context.getContainer(), varAs.varName); //TODO: Remove `auto`
|
||||
string typedEntityVariableName = context.tc.getResolver().generateName(context.getContainer(), typedEntityVariable);
|
||||
|
||||
|
@ -66,6 +71,8 @@ public final class DCodeEmitter : CodeEmitter
|
|||
/* VariableDeclaration */
|
||||
else if(cast(VariableDeclaration)instruction)
|
||||
{
|
||||
gprintln("type: VariableDeclaration");
|
||||
|
||||
VariableDeclaration varDecInstr = cast(VariableDeclaration)instruction;
|
||||
Context context = varDecInstr.getContext();
|
||||
|
||||
|
@ -89,6 +96,7 @@ public final class DCodeEmitter : CodeEmitter
|
|||
varDecWantsConsumeVarAss = true;
|
||||
|
||||
// Fetch the variable assignment instruction
|
||||
gprintln("Before crash: "~to!(string)(getCurrentInstruction()));
|
||||
nextInstruction();
|
||||
Instruction varAssInstr = getCurrentInstruction();
|
||||
|
||||
|
@ -103,6 +111,8 @@ public final class DCodeEmitter : CodeEmitter
|
|||
/* LiteralValue */
|
||||
else if(cast(LiteralValue)instruction)
|
||||
{
|
||||
gprintln("type: LiteralValue");
|
||||
|
||||
LiteralValue literalValueInstr = cast(LiteralValue)instruction;
|
||||
|
||||
return to!(string)(literalValueInstr.data);
|
||||
|
@ -110,6 +120,8 @@ public final class DCodeEmitter : CodeEmitter
|
|||
/* FetchValueVar */
|
||||
else if(cast(FetchValueVar)instruction)
|
||||
{
|
||||
gprintln("type: FetchValueVar");
|
||||
|
||||
FetchValueVar fetchValueVarInstr = cast(FetchValueVar)instruction;
|
||||
Context context = fetchValueVarInstr.getContext();
|
||||
|
||||
|
@ -123,10 +135,56 @@ public final class DCodeEmitter : CodeEmitter
|
|||
/* BinOpInstr */
|
||||
else if(cast(BinOpInstr)instruction)
|
||||
{
|
||||
gprintln("type: BinOpInstr");
|
||||
|
||||
BinOpInstr binOpInstr = cast(BinOpInstr)instruction;
|
||||
|
||||
return transform(binOpInstr.lhs)~to!(string)(getCharacter(binOpInstr.operator))~transform(binOpInstr.rhs);
|
||||
}
|
||||
/* FuncCallInstr */
|
||||
else if(cast(FuncCallInstr)instruction)
|
||||
{
|
||||
gprintln("type: FuncCallInstr");
|
||||
|
||||
FuncCallInstr funcCallInstr = cast(FuncCallInstr)instruction;
|
||||
Context context = funcCallInstr.getContext();
|
||||
assert(context);
|
||||
|
||||
Function functionToCall = cast(Function)context.tc.getResolver().resolveBest(context.getContainer(), funcCallInstr.functionName); //TODO: Remove `auto`
|
||||
|
||||
// TODO: SymbolLookup?
|
||||
|
||||
string emit = functionToCall.getName()~"(";
|
||||
|
||||
//TODO: Insert argument passimng code here
|
||||
//NOTE: Typechecker must have checked for passing arguments to a function that doesn't take any, for example
|
||||
|
||||
//NOTE (Behaviour): We may want to actually have an preinliner for these arguments
|
||||
//such to enforce a certain ordering. I believe this should be done in the emitter stage,
|
||||
//so it is best placed here
|
||||
if(functionToCall.hasParams())
|
||||
{
|
||||
Value[] argumentInstructions = funcCallInstr.getEvaluationInstructions();
|
||||
string argumentString;
|
||||
|
||||
for(ulong argIdx = 0; argIdx < argumentInstructions.length; argIdx++)
|
||||
{
|
||||
Value currentArgumentInstr = argumentInstructions[argIdx];
|
||||
argumentString~=transform(currentArgumentInstr);
|
||||
|
||||
if(argIdx != (argumentInstructions.length-1))
|
||||
{
|
||||
argumentString~=", ";
|
||||
}
|
||||
}
|
||||
|
||||
emit~=argumentString;
|
||||
}
|
||||
|
||||
emit ~= ")";
|
||||
|
||||
return emit;
|
||||
}
|
||||
|
||||
return "<TODO: Base emit: "~to!(string)(instruction)~">";
|
||||
}
|
||||
|
@ -139,12 +197,13 @@ public final class DCodeEmitter : CodeEmitter
|
|||
|
||||
emitStaticAllocations();
|
||||
|
||||
gprintln("Function definitions needed: "~to!(string)(1)); //TODO: fix counter here
|
||||
emitCodeQueue();
|
||||
|
||||
emitFunctionDefinitions();
|
||||
|
||||
gprintln("\n\n\n");
|
||||
|
||||
emitCodeQueue();
|
||||
// emitCodeQueue();
|
||||
|
||||
gprintln("\n\n\n");
|
||||
|
||||
|
@ -194,6 +253,8 @@ public final class DCodeEmitter : CodeEmitter
|
|||
{
|
||||
selectQueue(QueueType.ALLOC_QUEUE);
|
||||
gprintln("Static allocations needed: "~to!(string)(getQueueLength()));
|
||||
|
||||
file.writeln();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -201,6 +262,8 @@ public final class DCodeEmitter : CodeEmitter
|
|||
*/
|
||||
private void emitFunctionDefinitions()
|
||||
{
|
||||
gprintln("Function definitions needed: "~to!(string)(getFunctionDefinitionsCount()));
|
||||
|
||||
Instruction[][string] functionBodyInstrs = typeChecker.getFunctionBodyCodeQueues();
|
||||
|
||||
string[] functionNames = getFunctionDefinitionNames();
|
||||
|
@ -210,9 +273,8 @@ public final class DCodeEmitter : CodeEmitter
|
|||
foreach(string currentFunctioName; functionNames)
|
||||
{
|
||||
emitFunctionDefinition(currentFunctioName);
|
||||
file.writeln();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private string generateSignature(Function func)
|
||||
|
@ -251,13 +313,10 @@ public final class DCodeEmitter : CodeEmitter
|
|||
|
||||
private void emitFunctionDefinition(string functionName)
|
||||
{
|
||||
// // Reset the cursor
|
||||
// resetCFDCQCursor();
|
||||
|
||||
// // Set the function we want to examine in CodeEmitter
|
||||
// setCurrentFunctionDefinition(functionName);
|
||||
selectQueue(QueueType.FUNCTION_DEF_QUEUE, functionName);
|
||||
|
||||
gprintln("emotFunctionDefinition(): Function: "~functionName~", with "~to!(string)(getSelectedQueueLength())~" many instructions");
|
||||
|
||||
//TODO: Look at nested definitions or nah? (Context!!)
|
||||
//TODO: And what about methods defined in classes? Those should technically be here too
|
||||
Function functionEntity = cast(Function)typeChecker.getResolver().resolveBest(typeChecker.getModule(), functionName); //TODO: Remove `auto`
|
||||
|
@ -296,15 +355,23 @@ public final class DCodeEmitter : CodeEmitter
|
|||
|
||||
nextInstruction();
|
||||
}
|
||||
|
||||
file.writeln();
|
||||
}
|
||||
|
||||
private void emitEntryPoint()
|
||||
{
|
||||
//TODO: Implement me
|
||||
|
||||
// NOTE: Remove this printf
|
||||
file.writeln(`
|
||||
// NOTE: The below is testing code and should be removed
|
||||
#include<stdio.h>
|
||||
int main()
|
||||
{
|
||||
printf("k: %u\n", t_0c9714cea1ccdfdd0345347c86885620);
|
||||
banana(1);
|
||||
printf("k: %u\n", t_0c9714cea1ccdfdd0345347c86885620);
|
||||
return 0;
|
||||
}`);
|
||||
}
|
||||
|
@ -326,21 +393,18 @@ int main()
|
|||
//NOTE: Change to system compiler (maybe, we need to choose a good C compiler)
|
||||
Pid ccPID = spawnProcess(["clang", "-o", "tlang.out", file.name()]);
|
||||
|
||||
//NOTE: Case where it exited and Pid now inavlid (if it happens it would throw processexception surely)?
|
||||
int code = wait(ccPID);
|
||||
gprintln(code);
|
||||
|
||||
if(code)
|
||||
{
|
||||
//NOTE: Make this a TLang exception
|
||||
throw new Exception("The CC exited with a non-zero exit code");
|
||||
throw new Exception("The CC exited with a non-zero exit code ("~to!(string)(code)~")");
|
||||
}
|
||||
}
|
||||
catch(ProcessException e)
|
||||
{
|
||||
gprintln("NOTE: Case where it exited and Pid now inavlid (if it happens it would throw processexception surely)?", DebugType.ERROR);
|
||||
assert(false);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -244,7 +244,7 @@ public class FuncCallInstr : CallInstr
|
|||
/* Per-argument instrructions */
|
||||
private Value[] evaluationInstructions;
|
||||
|
||||
private string functionName;
|
||||
public const string functionName;
|
||||
|
||||
this(string functionName, ulong argEvalInstrsSize)
|
||||
{
|
||||
|
|
|
@ -713,12 +713,14 @@ public final class TypeChecker
|
|||
/**
|
||||
* TODO:
|
||||
*
|
||||
* 1. Create FUncCallInstr
|
||||
* 1. Create FuncCallInstr
|
||||
* 2. Evaluate args and process them?! wait done elsewhere yeah!!!
|
||||
* 3. Pop arts into here
|
||||
* 4. AddInstr(combining those args)
|
||||
* 5. DOne
|
||||
*/
|
||||
funcCallInstr.context = funcCall.getContext();
|
||||
|
||||
addInstr(funcCallInstr);
|
||||
addType(getType(func.parentOf(), func.getType()));
|
||||
}
|
||||
|
|
|
@ -410,7 +410,7 @@ public class DNodeGenerator
|
|||
*
|
||||
* This holds unique pool entries
|
||||
*/
|
||||
private DNode[] nodePool;
|
||||
private static DNode[] nodePool;
|
||||
|
||||
this(TypeChecker tc)
|
||||
{
|
||||
|
@ -582,12 +582,21 @@ public class DNodeGenerator
|
|||
FunctionCall funcCall = cast(FunctionCall)exp;
|
||||
gprintln("FuncCall: "~funcCall.getName());
|
||||
|
||||
|
||||
/* TODO: We need to fetch the cached function definition here and call it */
|
||||
Entity funcEntity = resolver.resolveWithin(context.container, funcCall.getName());
|
||||
DNode funcDefDNode = retrieveFunctionDefinitionNode(tc.getResolver().generateName(tc.getModule(), funcEntity));
|
||||
gprintln("FuncCall (FuncDefNode): "~to!(string)(funcDefDNode));
|
||||
dnode.needs(funcDefDNode); /* NOTE: New code as of 4th October 2022 */
|
||||
Entity funcEntity = resolver.resolveBest(context.container, funcCall.getName());
|
||||
assert(funcEntity);
|
||||
|
||||
// FIXME: The below is failing (we probably need a forward look ahead?)
|
||||
// OR use the addFuncDef list?
|
||||
//WAIT! We don't need a funcDefNode actually. No, we lierally do not.
|
||||
//Remmeber, they are done in a seperate pass, what we need is just our FUncCall DNode
|
||||
// WHICH we have below as `dnode`!!!!
|
||||
// DNode funcDefDNode = retrieveFunctionDefinitionNode(tc.getResolver().generateName(tc.getModule(), funcEntity));
|
||||
// gprintln("FuncCall (FuncDefNode): "~to!(string)(funcDefDNode));
|
||||
// dnode.needs(funcDefDNode); /* NOTE: New code as of 4th October 2022 */
|
||||
|
||||
//NOTE: Check if we need to set a context here to that of the context we occuring in
|
||||
funcCall.context = context;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -1276,9 +1285,6 @@ public class DNodeGenerator
|
|||
{
|
||||
VariableAssignmentStdAlone vAsStdAl = cast(VariableAssignmentStdAlone)entity;
|
||||
|
||||
/* Set the Context */
|
||||
vAsStdAl.setContext(context);
|
||||
|
||||
/* TODO: CHeck avriable name even */
|
||||
gprintln("YEAST ENJOYER");
|
||||
|
||||
|
@ -1286,10 +1292,14 @@ public class DNodeGenerator
|
|||
// FIXME: The below assert fails for function definitions trying to refer to global values
|
||||
// as a reoslveBest (up) is needed. We should firstly check if within fails, if so,
|
||||
// resolveBest, if that fails, then it is an error (see #46)
|
||||
assert(tc.getResolver().resolveWithin(c, vAsStdAl.getVariableName()));
|
||||
assert(tc.getResolver().resolveBest(c, vAsStdAl.getVariableName()));
|
||||
gprintln("YEAST ENJOYER");
|
||||
Variable variable = cast(Variable)tc.getResolver().resolveWithin(c, vAsStdAl.getVariableName());
|
||||
Variable variable = cast(Variable)tc.getResolver().resolveBest(c, vAsStdAl.getVariableName());
|
||||
assert(variable);
|
||||
|
||||
/* Set the context of the assignment to the Context of the Variable being assigned to */
|
||||
vAsStdAl.setContext(variable.getContext());
|
||||
|
||||
/* Pool the variable */
|
||||
DNode varDecDNode = pool(variable);
|
||||
|
||||
|
@ -1394,14 +1404,14 @@ public class DNodeGenerator
|
|||
/* 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);
|
||||
// Context funcContext = new Context(tc.getModule(), InitScope.STATIC);
|
||||
// DNode funcDefDNode = generalPass(func, funcContext);
|
||||
|
||||
|
||||
/**
|
||||
* Save the function dnode for lookup later
|
||||
*/
|
||||
saveFunctionDefinitionNode(funcDefDNode);
|
||||
// saveFunctionDefinitionNode(funcDefDNode);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ module simple_function_decls;
|
|||
int j = 21;
|
||||
int k = 22;
|
||||
|
||||
int apple(int j)
|
||||
int apple(int j, int arg2)
|
||||
{
|
||||
int h = 69;
|
||||
}
|
||||
|
@ -11,5 +11,7 @@ int apple(int j)
|
|||
int banana(int j)
|
||||
{
|
||||
int h = 64;
|
||||
k=1;
|
||||
|
||||
k=1+h+apple(1, apple(2, 3));
|
||||
|
||||
}
|
Loading…
Reference in New Issue