mirror of https://github.com/tbklang/tlang.git
171 lines
4.1 KiB
D
171 lines
4.1 KiB
D
module compiler.codegen.emit.core;
|
|
|
|
import compiler.symbols.data;
|
|
import compiler.typecheck.core;
|
|
import std.container.slist : SList;
|
|
import compiler.codegen.instruction;
|
|
import std.stdio;
|
|
import std.file;
|
|
import compiler.codegen.instruction : Instruction;
|
|
import std.range : walkLength;
|
|
import gogga;
|
|
import std.conv : to;
|
|
import compiler.configuration : CompilerConfiguration;
|
|
import compiler.codegen.mapper.core : SymbolMapper;
|
|
|
|
/**
|
|
* TODO: Perhaps have an interface that can emit(Context/Parent, Statement)
|
|
*/
|
|
|
|
/* TODO: Module linking (general overhaul required) */
|
|
|
|
public abstract class CodeEmitter
|
|
{
|
|
protected TypeChecker typeChecker;
|
|
protected File file;
|
|
protected CompilerConfiguration config;
|
|
protected SymbolMapper mapper;
|
|
|
|
/**
|
|
* The selected queue is the queue to be used
|
|
* when using the cursor instructions such as
|
|
* `nextInstruction()`, `previousInstruction()`
|
|
* etc.
|
|
*/
|
|
private Instruction[] selectedQueue;
|
|
|
|
public enum QueueType
|
|
{
|
|
ALLOC_QUEUE,
|
|
GLOBALS_QUEUE,
|
|
FUNCTION_DEF_QUEUE
|
|
}
|
|
|
|
private ulong queueCursor = 0;
|
|
|
|
public final void selectQueue(QueueType queueType, string funcDefName = "")
|
|
{
|
|
// Move the cursor back to the starting position
|
|
resetCursor();
|
|
|
|
if(queueType == QueueType.ALLOC_QUEUE)
|
|
{
|
|
selectedQueue = initQueue;
|
|
}
|
|
else if(queueType == QueueType.GLOBALS_QUEUE)
|
|
{
|
|
selectedQueue = globalCodeQueue;
|
|
}
|
|
else
|
|
{
|
|
//TODO: Ensure valid name by lookup via tc
|
|
|
|
selectedQueue = functionBodyInstrs[funcDefName];
|
|
}
|
|
}
|
|
|
|
public final void resetCursor()
|
|
{
|
|
queueCursor = 0;
|
|
}
|
|
|
|
public final void nextInstruction()
|
|
{
|
|
// TODO: Sanity check on length
|
|
|
|
queueCursor++;
|
|
}
|
|
|
|
public final void previousInstruction()
|
|
{
|
|
// TODO: Sanity check on lenght
|
|
|
|
queueCursor--;
|
|
}
|
|
|
|
public final bool hasInstructions()
|
|
{
|
|
return queueCursor < selectedQueue.length;
|
|
}
|
|
|
|
public final Instruction getCurrentInstruction()
|
|
{
|
|
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
|
|
*/
|
|
private Instruction[] initQueue;
|
|
private Instruction[] globalCodeQueue;
|
|
|
|
/**
|
|
* Required queues (maps to them)
|
|
*/
|
|
private Instruction[][string] functionBodyInstrs;
|
|
|
|
public final ulong getFunctionDefinitionsCount()
|
|
{
|
|
return functionBodyInstrs.keys().length;
|
|
}
|
|
|
|
public final string[] getFunctionDefinitionNames()
|
|
{
|
|
return functionBodyInstrs.keys();
|
|
}
|
|
|
|
// TODO: Add allow for custom symbol mapper, use an interface or rather base class mechanism for it
|
|
this(TypeChecker typeChecker, File file, CompilerConfiguration config, SymbolMapper mapper)
|
|
{
|
|
this.typeChecker = typeChecker;
|
|
|
|
/* Extract the allocation queue, the code queue */
|
|
initQueue = typeChecker.getInitQueue();
|
|
globalCodeQueue = typeChecker.getGlobalCodeQueue();
|
|
|
|
/* Extract the function definitions string-queue mapping */
|
|
functionBodyInstrs = typeChecker.getFunctionBodyCodeQueues();
|
|
gprintln("CodeEmitter: Got number of function defs: "~to!(string)(functionBodyInstrs));
|
|
|
|
this.file = file;
|
|
this.config = config;
|
|
|
|
this.mapper = mapper;
|
|
}
|
|
|
|
/**
|
|
* Begins the emit process
|
|
*/
|
|
public abstract void emit();
|
|
|
|
/**
|
|
* Finalizes the emitting process (only
|
|
* to be called after the `emit()` finishes)
|
|
*/
|
|
public abstract void finalize();
|
|
|
|
/**
|
|
* Transforms or emits a single Instruction
|
|
* and returns the transformation
|
|
*
|
|
* Params:
|
|
* instruction = The Instruction to transform/emit
|
|
* Returns: The Instruction emit as a string
|
|
*/
|
|
public abstract string transform(Instruction instruction);
|
|
} |