Instruction
- Removed all `emit()` methods (this is now done in the language-specific emitter - DGen) CoreEmitter - Added docstrings - Added required `transform(Instruction)` method which must transform each provided Instruction into a string (a.k.a. do the actual emit()-ting) DGen - Migrated C-emit code into the overrided `transform(Instruction)` method
This commit is contained in:
parent
092e4e4130
commit
b0d9d2aabe
|
@ -6,6 +6,7 @@ import std.container.slist : SList;
|
|||
import compiler.codegen.instruction;
|
||||
import std.stdio;
|
||||
import std.file;
|
||||
import compiler.codegen.instruction : Instruction;
|
||||
|
||||
/**
|
||||
* TODO: Perhaps have an interface that can emit(Context/Parent, Statement)
|
||||
|
@ -40,7 +41,24 @@ public abstract class CodeEmitter
|
|||
this.file = file;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
|
@ -12,6 +12,10 @@ import gogga;
|
|||
import std.range : walkLength;
|
||||
import std.string : wrap;
|
||||
import std.process : spawnProcess, Pid, ProcessException, wait;
|
||||
import compiler.typecheck.dependency.core : Context;
|
||||
import compiler.codegen.mapper : SymbolMapper;
|
||||
import compiler.symbols.data : SymbolType;
|
||||
import compiler.symbols.check : getCharacter;
|
||||
|
||||
public final class DCodeEmitter : CodeEmitter
|
||||
{
|
||||
|
@ -20,31 +24,64 @@ public final class DCodeEmitter : CodeEmitter
|
|||
super(typeChecker, file);
|
||||
}
|
||||
|
||||
public override void finalize()
|
||||
public override string transform(const Instruction instruction)
|
||||
{
|
||||
try
|
||||
/* VariableAssignmentInstr */
|
||||
if(cast(VariableAssignmentInstr)instruction)
|
||||
{
|
||||
//NOTE: Change to system compiler (maybe, we need to choose a good C compiler)
|
||||
Pid ccPID = spawnProcess(["gcc", "-o", "tlang.out", file.name()]);
|
||||
VariableAssignmentInstr varAs = cast(VariableAssignmentInstr)instruction;
|
||||
Context context = varAs.getContext();
|
||||
|
||||
//NOTE: Case where it exited and Pid now inavlid (if it happens it would throw processexception surely)?
|
||||
int code = wait(ccPID);
|
||||
gprintln(code);
|
||||
gprintln("Is ContextNull?: "~to!(string)(context is null));
|
||||
auto typedEntityVariable = context.tc.getResolver().resolveBest(context.getContainer(), varAs.varName); //TODO: Remove `auto`
|
||||
string typedEntityVariableName = context.tc.getResolver().generateName(context.getContainer(), typedEntityVariable);
|
||||
|
||||
if(code)
|
||||
{
|
||||
//NOTE: Make this a TLang exception
|
||||
throw new Exception("The CC exited with a non-zero exit code");
|
||||
}
|
||||
|
||||
import compiler.codegen.mapper : SymbolMapper;
|
||||
string renamedSymbol = SymbolMapper.symbolLookup(context.getContainer(), typedEntityVariableName);
|
||||
|
||||
|
||||
return renamedSymbol~" = "~transform(varAs.data)~";";
|
||||
}
|
||||
catch(ProcessException e)
|
||||
/* VariableDeclaration */
|
||||
else if(cast(VariableDeclaration)instruction)
|
||||
{
|
||||
gprintln("NOTE: Case where it exited and Pid now inavlid (if it happens it would throw processexception surely)?", DebugType.ERROR);
|
||||
assert(false);
|
||||
VariableDeclaration varDecInstr = cast(VariableDeclaration)instruction;
|
||||
Context context = varDecInstr.getContext();
|
||||
|
||||
auto typedEntityVariable = context.tc.getResolver().resolveBest(context.getContainer(), varDecInstr.varName); //TODO: Remove `auto`
|
||||
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
|
||||
// a custom CodeEmitter should be allowed, so let's call it a general rule)
|
||||
//
|
||||
//simple_variables.x -> simple_variables_x
|
||||
//NOTE: We may need to create a symbol table actually and add to that and use that as these names
|
||||
//could get out of hand (too long)
|
||||
// NOTE: Best would be identity-mapping Entity's to a name
|
||||
import compiler.codegen.mapper : SymbolMapper;
|
||||
string renamedSymbol = SymbolMapper.symbolLookup(context.getContainer(), varDecInstr.varName);
|
||||
|
||||
return varDecInstr.varType~" "~renamedSymbol~";";
|
||||
}
|
||||
/* LiteralValue */
|
||||
else if(cast(LiteralValue)instruction)
|
||||
{
|
||||
LiteralValue literalValueInstr = cast(LiteralValue)instruction;
|
||||
|
||||
return to!(string)(literalValueInstr.data);
|
||||
}
|
||||
/* BinOpInstr */
|
||||
else if(cast(BinOpInstr)instruction)
|
||||
{
|
||||
BinOpInstr binOpInstr = cast(BinOpInstr)instruction;
|
||||
|
||||
return transform(binOpInstr.lhs)~to!(string)(getCharacter(binOpInstr.operator))~transform(binOpInstr.rhs);
|
||||
}
|
||||
return "<TODO: Base emit>";
|
||||
}
|
||||
|
||||
|
||||
public override void emit()
|
||||
{
|
||||
// Emit header comment (NOTE: Change this to a useful piece of text)
|
||||
|
@ -111,7 +148,8 @@ public final class DCodeEmitter : CodeEmitter
|
|||
|
||||
foreach(Instruction currentInstruction; codeQueue)
|
||||
{
|
||||
file.writeln(currentInstruction.emit());
|
||||
// file.writeln(currentInstruction.emit());
|
||||
file.writeln(transform(currentInstruction));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -125,4 +163,39 @@ int main()
|
|||
return 0;
|
||||
}`);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public override void finalize()
|
||||
{
|
||||
try
|
||||
{
|
||||
//NOTE: Change to system compiler (maybe, we need to choose a good C compiler)
|
||||
Pid ccPID = spawnProcess(["gcc", "-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");
|
||||
}
|
||||
}
|
||||
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);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -8,11 +8,6 @@ import compiler.symbols.data : SymbolType;
|
|||
import compiler.symbols.check : getCharacter;
|
||||
import gogga;
|
||||
|
||||
/**
|
||||
* TODO: We should actually remove the emits from here probably and rather do those in DGen
|
||||
* as they are C specific
|
||||
*/
|
||||
|
||||
public class Instruction
|
||||
{
|
||||
/* Context for the Instruction (used in emitter for name resolution) */
|
||||
|
@ -30,11 +25,6 @@ public class Instruction
|
|||
return "[Instruction: "~this.classinfo.name~":"~addInfo~"]";
|
||||
}
|
||||
|
||||
public string emit()
|
||||
{
|
||||
return "TODO: This instruction has not provided an emit text yet! (This is an error!)";
|
||||
}
|
||||
|
||||
public final Context getContext()
|
||||
{
|
||||
return context;
|
||||
|
@ -69,7 +59,7 @@ public class VariableAssignmentInstr : Instruction
|
|||
/* Name of variable being declared */
|
||||
public string varName; /*TODO: Might not be needed */
|
||||
|
||||
public Instruction data;
|
||||
public const Instruction data;
|
||||
|
||||
this(string varName, Instruction data)
|
||||
{
|
||||
|
@ -78,21 +68,6 @@ public class VariableAssignmentInstr : Instruction
|
|||
|
||||
addInfo = "assignTo: "~varName~", valInstr: "~data.toString();
|
||||
}
|
||||
|
||||
public override string emit()
|
||||
{
|
||||
gprintln("Is ContextNull?: "~to!(string)(context is null));
|
||||
auto typedEntityVariable = context.tc.getResolver().resolveBest(context.getContainer(), varName); //TODO: Remove `auto`
|
||||
string typedEntityVariableName = context.tc.getResolver().generateName(context.getContainer(), typedEntityVariable);
|
||||
|
||||
|
||||
import compiler.codegen.mapper : SymbolMapper;
|
||||
string renamedSymbol = SymbolMapper.symbolLookup(context.getContainer(), typedEntityVariableName);
|
||||
|
||||
|
||||
return renamedSymbol~" = "~data.emit()~";";
|
||||
// return "<TODO: VarAssAssignment ("~data.emit()~")";
|
||||
}
|
||||
}
|
||||
|
||||
public final class VariableDeclaration : StorageDeclaration
|
||||
|
@ -115,33 +90,6 @@ public final class VariableDeclaration : StorageDeclaration
|
|||
|
||||
addInfo = "varName: "~varName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Emits a string of the form:
|
||||
*
|
||||
* <varType> <varName>;
|
||||
*
|
||||
* Returns: The emitted code
|
||||
*/
|
||||
public override string emit()
|
||||
{
|
||||
auto typedEntityVariable = context.tc.getResolver().resolveBest(context.getContainer(), varName); //TODO: Remove `auto`
|
||||
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
|
||||
// a custom CodeEmitter should be allowed, so let's call it a general rule)
|
||||
//
|
||||
//simple_variables.x -> simple_variables_x
|
||||
//NOTE: We may need to create a symbol table actually and add to that and use that as these names
|
||||
//could get out of hand (too long)
|
||||
// NOTE: Best would be identity-mapping Entity's to a name
|
||||
string renamedSymbol = symbolRename(typedEntityVariableName);
|
||||
|
||||
import compiler.codegen.mapper : SymbolMapper;
|
||||
renamedSymbol = SymbolMapper.symbolLookup(context.getContainer(), varName);
|
||||
|
||||
return varType~" "~renamedSymbol~";";
|
||||
}
|
||||
}
|
||||
|
||||
public final class FetchValueVar : Value
|
||||
|
@ -175,11 +123,6 @@ public final class LiteralValue : Value
|
|||
|
||||
addInfo = "Data: "~to!(string)(data)~", Length: "~to!(string)(len);
|
||||
}
|
||||
|
||||
public override string emit()
|
||||
{
|
||||
return to!(string)(data);
|
||||
}
|
||||
}
|
||||
|
||||
public final class LiteralValueFloat : Value
|
||||
|
@ -253,9 +196,9 @@ public final class StringLiteral : Value
|
|||
*/
|
||||
public class BinOpInstr : Value
|
||||
{
|
||||
private Instruction lhs;
|
||||
private Instruction rhs;
|
||||
private SymbolType operator;
|
||||
public const Instruction lhs;
|
||||
public const Instruction rhs;
|
||||
public const SymbolType operator;
|
||||
|
||||
this(Instruction lhs, Instruction rhs, SymbolType operator)
|
||||
{
|
||||
|
@ -265,11 +208,6 @@ public class BinOpInstr : Value
|
|||
|
||||
addInfo = "BinOpType: "~to!(string)(operator)~", LhsValInstr: "~lhs.toString()~", RhsValInstr: "~rhs.toString();
|
||||
}
|
||||
|
||||
public override string emit()
|
||||
{
|
||||
return lhs.emit()~to!(string)(getCharacter(operator))~rhs.emit();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue