CoreEmitter
- All operations regarding moving through (iterating over) instructions are now to be done via the instructions provided by CodeEmitter, moveback, moveforward etc. DGen - Re-worked the system to use new CodeEmitter semantics - Variable assignments in declarations are oneshot now which makes it more compact, semantically better and also valid C --- Tests - Updated the `simple_variables.t` test case to have many binary operations chained
This commit is contained in:
parent
e64a9ef5d1
commit
01bdb145e2
|
@ -7,6 +7,7 @@ import compiler.codegen.instruction;
|
||||||
import std.stdio;
|
import std.stdio;
|
||||||
import std.file;
|
import std.file;
|
||||||
import compiler.codegen.instruction : Instruction;
|
import compiler.codegen.instruction : Instruction;
|
||||||
|
import std.range : walkLength;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO: Perhaps have an interface that can emit(Context/Parent, Statement)
|
* TODO: Perhaps have an interface that can emit(Context/Parent, Statement)
|
||||||
|
@ -21,37 +22,63 @@ public abstract class CodeEmitter
|
||||||
/**
|
/**
|
||||||
* Required queues
|
* Required queues
|
||||||
*/
|
*/
|
||||||
protected SList!(Instruction) initQueue;
|
private Instruction[] initQueue;
|
||||||
protected SList!(Instruction) codeQueue;
|
private Instruction[] codeQueue;
|
||||||
|
|
||||||
alias instructions = codeQueue;
|
// alias instructions = codeQueue;
|
||||||
|
|
||||||
protected File file;
|
protected File file;
|
||||||
|
|
||||||
|
|
||||||
protected string currentEmitBuildUp;
|
private ulong codeQueueIdx = 0;
|
||||||
|
|
||||||
public void buildEmit(string data)
|
|
||||||
|
public final Instruction getCurrentCodeInstruction()
|
||||||
{
|
{
|
||||||
currentEmitBuildUp~=data;
|
return codeQueue[codeQueueIdx];
|
||||||
}
|
}
|
||||||
|
|
||||||
public void flushEmit()
|
public final bool hasCodeInstructions()
|
||||||
{
|
{
|
||||||
file.writeln(currentEmitBuildUp);
|
return codeQueueIdx < codeQueue.length;
|
||||||
currentEmitBuildUp = "";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final void nextCodeInstruction()
|
||||||
|
{
|
||||||
|
codeQueueIdx++;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void previousCodeInstruction()
|
||||||
|
{
|
||||||
|
codeQueueIdx--;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public final ulong getInitQueueLen()
|
||||||
|
{
|
||||||
|
return initQueue.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final ulong getCodeQueueLen()
|
||||||
|
{
|
||||||
|
return codeQueue.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
this(TypeChecker typeChecker, File file)
|
this(TypeChecker typeChecker, File file)
|
||||||
{
|
{
|
||||||
this.typeChecker = typeChecker;
|
this.typeChecker = typeChecker;
|
||||||
|
|
||||||
/* Extract the allocation queue, the code queue */
|
/* Extract the allocation queue, the code queue */
|
||||||
initQueue = typeChecker.getInitQueue();
|
foreach(Instruction currentInstruction; typeChecker.getInitQueue())
|
||||||
codeQueue = typeChecker.getCodeQueue();
|
{
|
||||||
|
initQueue~=currentInstruction;
|
||||||
|
}
|
||||||
|
foreach(Instruction currentInstruction; typeChecker.getCodeQueue())
|
||||||
|
{
|
||||||
|
codeQueue~=currentInstruction;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
this.file = file;
|
this.file = file;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,10 @@ public final class DCodeEmitter : CodeEmitter
|
||||||
private Stack!(Instruction) varAssStack;
|
private Stack!(Instruction) varAssStack;
|
||||||
|
|
||||||
|
|
||||||
|
// Set to true when processing a variable declaration
|
||||||
|
// which expects an assignment. Set to false when
|
||||||
|
// said variable assignment has been processed
|
||||||
|
private bool varDecWantsConsumeVarAss = false;
|
||||||
|
|
||||||
|
|
||||||
this(TypeChecker typeChecker, File file)
|
this(TypeChecker typeChecker, File file)
|
||||||
|
@ -42,22 +45,24 @@ public final class DCodeEmitter : CodeEmitter
|
||||||
Context context = varAs.getContext();
|
Context context = varAs.getContext();
|
||||||
|
|
||||||
gprintln("Is ContextNull?: "~to!(string)(context is null));
|
gprintln("Is ContextNull?: "~to!(string)(context is null));
|
||||||
Variable typedEntityVariable = cast(Variable)context.tc.getResolver().resolveBest(context.getContainer(), varAs.varName); //TODO: Remove `auto`
|
auto typedEntityVariable = context.tc.getResolver().resolveBest(context.getContainer(), varAs.varName); //TODO: Remove `auto`
|
||||||
string typedEntityVariableName = context.tc.getResolver().generateName(context.getContainer(), typedEntityVariable);
|
string typedEntityVariableName = context.tc.getResolver().generateName(context.getContainer(), typedEntityVariable);
|
||||||
|
|
||||||
|
|
||||||
import compiler.codegen.mapper : SymbolMapper;
|
import compiler.codegen.mapper : SymbolMapper;
|
||||||
string renamedSymbol = SymbolMapper.symbolLookup(context.getContainer(), typedEntityVariableName);
|
string renamedSymbol = SymbolMapper.symbolLookup(context.getContainer(), typedEntityVariableName);
|
||||||
|
|
||||||
/* TODO: Add check for variable assigmen tto here */
|
|
||||||
if(typedEntityVariable.getAssignment())
|
// If we are needed as part of a VariabvleDeclaration-with-assignment
|
||||||
|
if(varDecWantsConsumeVarAss)
|
||||||
{
|
{
|
||||||
//TODO: Set a field here that gets checked for VariableDeclaration instruction
|
// Generate the code to emit (only the RHS of the = sign)
|
||||||
//to return only RHS (and not assignment with variable)
|
string emitCode = transform(varAs.data);
|
||||||
//It will then reset said bit
|
|
||||||
//TODO: We will also then need a peak (cursor rather than an iterator I think)
|
// Reset flag
|
||||||
//and in such case the VariableDeclaration branch (under that bit set - once again)
|
varDecWantsConsumeVarAss = false;
|
||||||
//must then progress the cursor (such that we skip it next time)
|
|
||||||
|
return emitCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -69,7 +74,7 @@ public final class DCodeEmitter : CodeEmitter
|
||||||
VariableDeclaration varDecInstr = cast(VariableDeclaration)instruction;
|
VariableDeclaration varDecInstr = cast(VariableDeclaration)instruction;
|
||||||
Context context = varDecInstr.getContext();
|
Context context = varDecInstr.getContext();
|
||||||
|
|
||||||
auto typedEntityVariable = context.tc.getResolver().resolveBest(context.getContainer(), varDecInstr.varName); //TODO: Remove `auto`
|
Variable typedEntityVariable = cast(Variable)context.tc.getResolver().resolveBest(context.getContainer(), varDecInstr.varName); //TODO: Remove `auto`
|
||||||
string typedEntityVariableName = context.tc.getResolver().generateName(context.getContainer(), typedEntityVariable);
|
string typedEntityVariableName = context.tc.getResolver().generateName(context.getContainer(), typedEntityVariable);
|
||||||
|
|
||||||
//NOTE: We should remove all dots from generated symbol names as it won't be valid C (I don't want to say C because
|
//NOTE: We should remove all dots from generated symbol names as it won't be valid C (I don't want to say C because
|
||||||
|
@ -88,6 +93,31 @@ public final class DCodeEmitter : CodeEmitter
|
||||||
|
|
||||||
/* TODO: I like the hold technique */
|
/* TODO: I like the hold technique */
|
||||||
|
|
||||||
|
/* TODO: Add check for variable assigmen tto here */
|
||||||
|
if(typedEntityVariable.getAssignment())
|
||||||
|
{
|
||||||
|
//TODO: Set a field here that gets checked for VariableDeclaration instruction
|
||||||
|
//to return only RHS (and not assignment with variable)
|
||||||
|
//It will then reset said bit
|
||||||
|
//TODO: We will also then need a peak (cursor rather than an iterator I think)
|
||||||
|
//and in such case the VariableDeclaration branch (under that bit set - once again)
|
||||||
|
//must then progress the cursor (such that we skip it next time)
|
||||||
|
varDecWantsConsumeVarAss = true;
|
||||||
|
|
||||||
|
// Fetch the variable assignment instruction
|
||||||
|
nextCodeInstruction();
|
||||||
|
Instruction varAssInstr = getCurrentCodeInstruction();
|
||||||
|
|
||||||
|
// Generate the code to emit
|
||||||
|
string emit = varDecInstr.varType~" "~renamedSymbol~" = "~transform(varAssInstr)~";";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return emit;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return varDecInstr.varType~" "~renamedSymbol~";";
|
return varDecInstr.varType~" "~renamedSymbol~";";
|
||||||
|
@ -115,11 +145,11 @@ public final class DCodeEmitter : CodeEmitter
|
||||||
// Emit header comment (NOTE: Change this to a useful piece of text)
|
// Emit header comment (NOTE: Change this to a useful piece of text)
|
||||||
emitHeaderComment("Place any extra information by code generator here"); // NOTE: We can pass a string with extra information to it if we want to
|
emitHeaderComment("Place any extra information by code generator here"); // NOTE: We can pass a string with extra information to it if we want to
|
||||||
|
|
||||||
gprintln("Static allocations needed: "~to!(string)(walkLength(initQueue[])));
|
gprintln("Static allocations needed: "~to!(string)(getInitQueueLen()));
|
||||||
emitStaticAllocations(initQueue);
|
emitStaticAllocations();
|
||||||
|
|
||||||
gprintln("Code emittings needed: "~to!(string)(walkLength(codeQueue[])));
|
gprintln("Code emittings needed: "~to!(string)(getCodeQueueLen()));
|
||||||
emitCodeQueue(codeQueue);
|
emitCodeQueue();
|
||||||
|
|
||||||
//TODO: Emit function definitions
|
//TODO: Emit function definitions
|
||||||
|
|
||||||
|
@ -163,21 +193,19 @@ public final class DCodeEmitter : CodeEmitter
|
||||||
* Params:
|
* Params:
|
||||||
* initQueue = The allocation queue to emit static allocations from
|
* initQueue = The allocation queue to emit static allocations from
|
||||||
*/
|
*/
|
||||||
private void emitStaticAllocations(SList!(Instruction) initQueue)
|
private void emitStaticAllocations()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void emitCodeQueue(SList!(Instruction) codeQueue)
|
private void emitCodeQueue()
|
||||||
{
|
{
|
||||||
//TODO: Implement me
|
while(hasCodeInstructions())
|
||||||
//NOTE: I think that every `Instruction` will need an `emit()` method
|
|
||||||
//of which sometimes can be recursive for instructions that are nested
|
|
||||||
|
|
||||||
foreach(Instruction currentInstruction; codeQueue)
|
|
||||||
{
|
{
|
||||||
// file.writeln(currentInstruction.emit());
|
Instruction currentInstruction = getCurrentCodeInstruction();
|
||||||
file.writeln(transform(currentInstruction));
|
file.writeln(transform(currentInstruction));
|
||||||
|
|
||||||
|
nextCodeInstruction();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
module simple_variables;
|
module simple_variables;
|
||||||
|
|
||||||
|
|
||||||
int x = 1+2;
|
int x = 1+2+2+1;
|
||||||
int y = 2;
|
int y = 2;
|
Loading…
Reference in New Issue