tlang/source/tlang/compiler/codegen/instruction.d

652 lines
14 KiB
D

module tlang.compiler.codegen.instruction;
import std.conv : to;
import tlang.compiler.typecheck.dependency.core : Context;
import std.string : cmp;
import tlang.compiler.symbols.data : SymbolType;
import tlang.compiler.symbols.check : getCharacter;
import gogga;
import tlang.compiler.symbols.typing.core : Type;
public class Instruction
{
/* Context for the Instruction (used in emitter for name resolution) */
private Context context; //TODO: Make this private and add a setCOntext
protected string addInfo;
public override string toString()
{
return "[Instruction: "~this.classinfo.name~":"~addInfo~"]";
}
private final string produceToStrEnclose(string addInfo)
{
return "[Instruction: "~this.classinfo.name~":"~addInfo~"]";
}
public final Context getContext()
{
return context;
}
public final void setContext(Context context)
{
this.context = context;
}
}
public class FetchInst : Instruction
{
}
public class Value : Instruction
{
/* The type of the Value this instruction produces */
private Type type;
public final void setInstrType(Type type)
{
this.type = type;
}
public final Type getInstrType()
{
return type;
}
}
public class StorageDeclaration : Instruction
{
}
public class ClassStaticInitAllocate : Instruction
{
this(string className)
{
addInfo = "classStaticInitAllocate: "~className;
}
}
public class VariableAssignmentInstr : Instruction
{
/* Name of variable being declared */
public string varName; /*TODO: Might not be needed */
public Value data;
this(string varName, Value data)
{
this.varName = varName;
this.data = data;
addInfo = "assignTo: "~varName~", valInstr: "~data.toString();
}
}
public final class VariableDeclaration : StorageDeclaration
{
/* Name of variable being declared */
public const string varName;
/* Length */
public const byte length;
/* Type of the variable being declared */
public const Type varType;
/* Value-instruction to be assigned */
private Value varAssInstr;
//TODO: This must take in type information
this(string varName, byte len, Type varType, Value varAssInstr)
{
this.varName = varName;
this.length = len;
this.varType = varType;
this.varAssInstr = varAssInstr;
addInfo = "varName: "~varName;
}
public Value getAssignmentInstr()
{
return varAssInstr;
}
}
public final class FetchValueVar : Value
{
/* Name of variable to fetch from */
public string varName;
/* Length */
public byte length;
this(string varName, byte len)
{
this.varName = varName;
this.length = len;
addInfo = "fetchVarValName: "~varName~", VarLen: "~to!(string)(length);
}
}
/* Used for integers */
public final class LiteralValue : Value
{
/* Data */
private string data;
this(string data, Type type)
{
this.data = data;
this.type = type;
addInfo = "Data: "~to!(string)(data)~", Type: "~to!(string)(type);
}
public string getLiteralValue()
{
return data;
}
public override string toString()
{
return produceToStrEnclose("Data: "~to!(string)(data)~", Type: "~to!(string)(type));
}
}
public final class LiteralValueFloat : Value
{
/* Data */
private string data;
this(string data, Type type)
{
this.data = data;
this.type = type;
addInfo = "Data: "~to!(string)(data)~", Type: "~to!(string)(type);
}
public string getLiteralValue()
{
return data;
}
public override string toString()
{
return produceToStrEnclose("Data: "~to!(string)(data)~", Type: "~to!(string)(type));
}
}
/* FIXME: Implement this */
/**
* TODO: This should take in:
*
* 1. The string literal
* 2. It should assign it to an interning pool and get the ID (associate one with the string literal if equal/in-the-pool)
*/
public final class StringLiteral : Value
{
/* String interning pool */
private static int[string] internmentCamp;
private static int rollCount = 0;
private string stringLiteral;
this(string stringLiteral)
{
this.stringLiteral = stringLiteral;
/* Intern the string */
intern(stringLiteral);
addInfo = "StrLit: `"~stringLiteral~"`, InternID: "~to!(string)(intern(stringLiteral));
}
public static int intern(string strLit)
{
/* Search for the string (if it exists return it's pool ID) */
foreach(string curStrLit; internmentCamp.keys())
{
if(cmp(strLit, curStrLit) == 0)
{
return internmentCamp[strLit];
}
}
/* If not, create a new entry (pool it) and return */
internmentCamp[strLit] = rollCount;
rollCount++; /* TODO: Overflow check */
return rollCount-1;
}
public string getStringLiteral()
{
return stringLiteral;
}
}
/**
* BinOpInstr instruction
*
* Any sort of Binary Operator
*/
public class BinOpInstr : Value
{
public const Instruction lhs;
public const Instruction rhs;
public const SymbolType operator;
this(Instruction lhs, Instruction rhs, SymbolType operator)
{
this.lhs = lhs;
this.rhs = rhs;
this.operator = operator;
addInfo = "BinOpType: "~to!(string)(operator)~", LhsValInstr: "~lhs.toString()~", RhsValInstr: "~rhs.toString();
}
}
/**
* UnaryOpInstr instruction
*
* Any sort of Unary Operator
*/
public class UnaryOpInstr : Value
{
private Value exp;
private SymbolType operator;
this(Value exp, SymbolType operator)
{
this.exp = exp;
this.operator = operator;
addInfo = "UnaryOpType: "~to!(string)(operator)~", Instr: "~exp.toString();
}
public SymbolType getOperator()
{
return operator;
}
public Value getOperand()
{
return exp;
}
}
/**
* 2022 New things
*
*/
//public class CallInstr : Instruction
public class CallInstr : Value
{
}
public class FuncCallInstr : CallInstr
{
/* Per-argument instrructions */
private Value[] evaluationInstructions;
public const string functionName;
this(string functionName, ulong argEvalInstrsSize)
{
this.functionName = functionName;
evaluationInstructions.length = argEvalInstrsSize;
updateAddInfo();
}
/**
* FuncCallInstr is built-bit-by-bit so toString information will change
*/
private void updateAddInfo()
{
addInfo = "FunctionName: "~functionName ~" EvalInstrs: "~ to!(string)(getEvaluationInstructions());
}
public void setEvalInstr(ulong argPos, Value instr)
{
evaluationInstructions[argPos] = instr;
updateAddInfo();
}
public Value[] getEvaluationInstructions()
{
return evaluationInstructions;
}
}
public final class ReturnInstruction : Instruction
{
private Value returnExprInstr;
this(Value returnExprInstr)
{
this.returnExprInstr = returnExprInstr;
}
public Value getReturnExpInstr()
{
return returnExprInstr;
}
}
public final class IfStatementInstruction : Instruction
{
private BranchInstruction[] branchInstructions;
this(BranchInstruction[] branchInstructions)
{
this.branchInstructions = branchInstructions;
addInfo = "Branches: "~to!(string)(branchInstructions);
}
public BranchInstruction[] getBranchInstructions()
{
return branchInstructions;
}
}
public final class WhileLoopInstruction : Instruction
{
private BranchInstruction branchInstruction;
this(BranchInstruction branchInstruction)
{
this.branchInstruction = branchInstruction;
addInfo = "Branch: "~to!(string)(branchInstruction);
}
public BranchInstruction getBranchInstruction()
{
return branchInstruction;
}
}
public final class ForLoopInstruction : Instruction
{
private Instruction preRunInstruction;
private BranchInstruction branchInstruction;
private bool hasPostIterate;
this(BranchInstruction branchInstruction, Instruction preRunInstruction = null, bool hasPostIterate = false)
{
this.branchInstruction = branchInstruction;
this.preRunInstruction = preRunInstruction;
addInfo = (hasPreRunInstruction() ? "PreRun: "~to!(string)(preRunInstruction)~", " : "")~"Branch: "~to!(string)(branchInstruction);
this.hasPostIterate = hasPostIterate;
}
public bool hasPostIterationInstruction()
{
return hasPostIterate;
}
public Instruction getPreRunInstruction()
{
return preRunInstruction;
}
public bool hasPreRunInstruction()
{
return !(preRunInstruction is null);
}
public BranchInstruction getBranchInstruction()
{
return branchInstruction;
}
}
public final class BranchInstruction : Instruction
{
private Value branchConditionInstr;
private Instruction[] bodyInstructions;
this(Value conditionInstr, Instruction[] bodyInstructions)
{
this.branchConditionInstr = conditionInstr;
this.bodyInstructions = bodyInstructions;
addInfo = "CondInstr: "~to!(string)(branchConditionInstr)~", BBodyInstrs: "~to!(string)(bodyInstructions);
}
public bool hasConditionInstr()
{
return !(branchConditionInstr is null);
}
public Value getConditionInstr()
{
return branchConditionInstr;
}
public Instruction[] getBodyInstructions()
{
return bodyInstructions;
}
}
public final class PointerDereferenceAssignmentInstruction : Instruction
{
private Value pointerEvalInstr;
private Value assigmnetExprInstr;
private ulong derefCount;
this(Value pointerEvalInstr, Value assigmnetExprInstr, ulong derefCount)
{
this.pointerEvalInstr = pointerEvalInstr;
this.assigmnetExprInstr = assigmnetExprInstr;
this.derefCount = derefCount;
}
public Value getPointerEvalInstr()
{
return pointerEvalInstr;
}
public Value getAssExprInstr()
{
return assigmnetExprInstr;
}
public ulong getDerefCount()
{
return derefCount;
}
}
public final class DiscardInstruction : Instruction
{
private Value exprInstr;
this(Value exprInstr)
{
this.exprInstr = exprInstr;
}
public Value getExpressionInstruction()
{
return exprInstr;
}
}
public final class CastedValueInstruction : Value
{
/* The uncasted original instruction that must be executed-then-trimmed (casted) */
private Value uncastedValue;
this(Value uncastedValue, Type castToType)
{
this.uncastedValue = uncastedValue;
this.type = castToType;
}
public Value getEmbeddedInstruction()
{
return uncastedValue;
}
public Type getCastToType()
{
return type;
}
}
public final class ArrayIndexInstruction : Value
{
/* Index-to instruction */
private Value indexTo;
/* The index */
private Value index;
this(Value indexTo, Value index)
{
this.indexTo = indexTo;
this.index = index;
}
public Value getIndexInstr()
{
return index;
}
public Value getIndexedToInstr()
{
return indexTo;
}
public override string toString()
{
return "ArrayIndexInstr [IndexTo: "~indexTo.toString()~", Index: "~index.toString()~"]";
}
}
//TODO: ArrayIndexAssignmentInstruction
public final class ArrayIndexAssignmentInstruction : Instruction
{
// TODO: We then need the left hand side array evaluation instruction (a pointer value basically)
// private Value arrayPtrEval;
// TODO: We then also need a `Value` field for the index expression instruction
// private Value index;
// NOTE: We now to the above to using an ArrayIndexInstruction
private ArrayIndexInstruction arrayPtrEval;
// TODO: We then also need another `Value` field for the expression instruction
// ... being assigned into the pointer-array
private Value assignment;
this(ArrayIndexInstruction arrayPtrEval, Value assignment)
{
this.arrayPtrEval = arrayPtrEval;
// this.index = index;
this.assignment = assignment;
}
public ArrayIndexInstruction getArrayPtrEval()
{
return arrayPtrEval;
}
public Value getAssignmentInstr()
{
return assignment;
}
}
// TODO: StackArrayIndexInstruction
public final class StackArrayIndexInstruction : Value
{
/* Index-to instruction */
private Value indexTo;
/* The index */
private Value index;
this(Value indexTo, Value index)
{
this.indexTo = indexTo;
this.index = index;
}
public Value getIndexInstr()
{
return index;
}
public Value getIndexedToInstr()
{
return indexTo;
}
public override string toString()
{
return "StackArrayIndexInstr [IndexTo: "~indexTo.toString()~", Index: "~index.toString()~"]";
}
}
// TODO: StackArrayIndexAssignmentInstruction
public final class StackArrayIndexAssignmentInstruction : Instruction
{
// TODO: We need a `string` field here which is looked up with the
// ... associated context of this instruction and refers to the
// ... stack-array being index-assigned into
private string arrayName;
// TODO: We then also need a `Value` field for the index expression instruction
private Value index;
// TODO: We then also need another `Value` field for the expression instruction
// ... being assigned into the stack-array at said index
private Value assignment;
this(string arrayName, Value index, Value assignment)
{
this.arrayName = arrayName;
this.index = index;
this.assignment = assignment;
}
public string getArrayName()
{
return arrayName;
}
public Value getIndexInstr()
{
return index;
}
public Value getAssignedValue()
{
return assignment;
}
public override string toString()
{
return "StackArrayASSIGN [name: "~arrayName~", index: "~index.toString()~", Assignment: "~assignment.toString()~"]";
}
}