2023-02-05 18:21:26 +00:00
|
|
|
module tlang.compiler.codegen.instruction;
|
2021-10-26 16:17:53 +01:00
|
|
|
|
|
|
|
import std.conv : to;
|
2023-02-05 18:21:26 +00:00
|
|
|
import tlang.compiler.typecheck.dependency.core : Context;
|
2022-07-26 08:58:25 +01:00
|
|
|
import std.string : cmp;
|
2023-02-05 18:21:26 +00:00
|
|
|
import tlang.compiler.symbols.data : SymbolType;
|
|
|
|
import tlang.compiler.symbols.check : getCharacter;
|
2022-12-12 11:12:03 +00:00
|
|
|
import gogga;
|
2023-02-05 18:21:26 +00:00
|
|
|
import tlang.compiler.symbols.typing.core : Type;
|
2021-10-26 16:17:53 +01:00
|
|
|
|
|
|
|
public class Instruction
|
|
|
|
{
|
2021-11-09 13:49:59 +00:00
|
|
|
/* Context for the Instruction (used in emitter for name resolution) */
|
2023-02-03 14:13:40 +00:00
|
|
|
private Context context; //TODO: Make this private and add a setCOntext
|
2021-11-09 13:49:59 +00:00
|
|
|
|
2021-10-26 16:17:53 +01:00
|
|
|
protected string addInfo;
|
|
|
|
|
2023-02-01 14:48:12 +00:00
|
|
|
public override string toString()
|
|
|
|
{
|
|
|
|
return "[Instruction: "~this.classinfo.name~":"~addInfo~"]";
|
|
|
|
}
|
|
|
|
|
|
|
|
private final string produceToStrEnclose(string addInfo)
|
2021-10-26 16:17:53 +01:00
|
|
|
{
|
|
|
|
return "[Instruction: "~this.classinfo.name~":"~addInfo~"]";
|
|
|
|
}
|
2022-12-11 16:12:46 +00:00
|
|
|
|
2022-12-12 13:14:43 +00:00
|
|
|
public final Context getContext()
|
|
|
|
{
|
|
|
|
return context;
|
|
|
|
}
|
2023-02-01 15:26:39 +00:00
|
|
|
|
|
|
|
public final void setContext(Context context)
|
|
|
|
{
|
|
|
|
this.context = context;
|
|
|
|
}
|
2021-10-26 16:17:53 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public class FetchInst : Instruction
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
public class Value : Instruction
|
|
|
|
{
|
2023-02-01 12:55:23 +00:00
|
|
|
/* 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;
|
|
|
|
}
|
2021-10-26 16:17:53 +01:00
|
|
|
}
|
|
|
|
|
2022-12-11 16:12:46 +00:00
|
|
|
public class StorageDeclaration : Instruction
|
2021-10-26 16:17:53 +01:00
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2021-11-10 15:15:27 +00:00
|
|
|
public class ClassStaticInitAllocate : Instruction
|
|
|
|
{
|
|
|
|
this(string className)
|
|
|
|
{
|
|
|
|
addInfo = "classStaticInitAllocate: "~className;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-26 19:32:47 +01:00
|
|
|
public class VariableAssignmentInstr : Instruction
|
|
|
|
{
|
|
|
|
/* Name of variable being declared */
|
|
|
|
public string varName; /*TODO: Might not be needed */
|
|
|
|
|
2023-02-01 12:55:23 +00:00
|
|
|
public Value data;
|
2021-10-26 19:32:47 +01:00
|
|
|
|
2023-01-30 17:03:48 +00:00
|
|
|
this(string varName, Value data)
|
2021-10-26 19:32:47 +01:00
|
|
|
{
|
|
|
|
this.varName = varName;
|
|
|
|
this.data = data;
|
|
|
|
|
2021-10-26 19:36:39 +01:00
|
|
|
addInfo = "assignTo: "~varName~", valInstr: "~data.toString();
|
2021-10-26 19:32:47 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-11 16:12:46 +00:00
|
|
|
public final class VariableDeclaration : StorageDeclaration
|
2021-10-26 16:17:53 +01:00
|
|
|
{
|
|
|
|
/* Name of variable being declared */
|
2022-12-11 17:10:29 +00:00
|
|
|
public const string varName;
|
2021-10-26 16:17:53 +01:00
|
|
|
|
|
|
|
/* Length */
|
2022-12-11 17:10:29 +00:00
|
|
|
public const byte length;
|
2021-10-26 16:17:53 +01:00
|
|
|
|
2022-12-11 16:46:05 +00:00
|
|
|
/* Type of the variable being declared */
|
2023-01-15 10:36:54 +00:00
|
|
|
public const Type varType;
|
2022-12-11 16:46:05 +00:00
|
|
|
|
2023-02-04 10:41:30 +00:00
|
|
|
/* Value-instruction to be assigned */
|
|
|
|
private Value varAssInstr;
|
2022-12-19 13:37:55 +00:00
|
|
|
|
2022-12-11 16:40:12 +00:00
|
|
|
//TODO: This must take in type information
|
2023-02-04 10:41:30 +00:00
|
|
|
this(string varName, byte len, Type varType, Value varAssInstr)
|
2021-10-26 16:17:53 +01:00
|
|
|
{
|
|
|
|
this.varName = varName;
|
|
|
|
this.length = len;
|
2022-12-11 16:46:05 +00:00
|
|
|
this.varType = varType;
|
2021-10-26 19:32:47 +01:00
|
|
|
|
2022-12-19 13:37:55 +00:00
|
|
|
this.varAssInstr = varAssInstr;
|
|
|
|
|
2021-10-26 19:32:47 +01:00
|
|
|
addInfo = "varName: "~varName;
|
2021-10-26 16:17:53 +01:00
|
|
|
}
|
2022-12-19 13:37:55 +00:00
|
|
|
|
2023-02-04 10:41:30 +00:00
|
|
|
public Value getAssignmentInstr()
|
2022-12-19 13:37:55 +00:00
|
|
|
{
|
|
|
|
return varAssInstr;
|
|
|
|
}
|
|
|
|
|
2021-10-26 16:17:53 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
2021-10-26 19:44:10 +01:00
|
|
|
|
|
|
|
addInfo = "fetchVarValName: "~varName~", VarLen: "~to!(string)(length);
|
2021-10-26 16:17:53 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-08-11 09:26:30 +01:00
|
|
|
/* Used for integers */
|
2021-10-26 16:17:53 +01:00
|
|
|
public final class LiteralValue : Value
|
|
|
|
{
|
|
|
|
/* Data */
|
2023-02-04 12:25:39 +00:00
|
|
|
private string data;
|
2021-10-26 16:17:53 +01:00
|
|
|
|
2023-01-30 17:03:48 +00:00
|
|
|
this(string data, Type type)
|
2021-10-26 16:17:53 +01:00
|
|
|
{
|
|
|
|
this.data = data;
|
2023-01-30 17:03:48 +00:00
|
|
|
this.type = type;
|
2021-10-26 16:17:53 +01:00
|
|
|
|
2023-01-30 17:03:48 +00:00
|
|
|
addInfo = "Data: "~to!(string)(data)~", Type: "~to!(string)(type);
|
2022-08-11 09:26:30 +01:00
|
|
|
}
|
2023-02-01 14:48:12 +00:00
|
|
|
|
2023-02-04 12:25:39 +00:00
|
|
|
public string getLiteralValue()
|
|
|
|
{
|
|
|
|
return data;
|
|
|
|
}
|
|
|
|
|
2023-02-01 14:48:12 +00:00
|
|
|
public override string toString()
|
|
|
|
{
|
|
|
|
return produceToStrEnclose("Data: "~to!(string)(data)~", Type: "~to!(string)(type));
|
|
|
|
}
|
2022-08-11 09:26:30 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public final class LiteralValueFloat : Value
|
|
|
|
{
|
|
|
|
/* Data */
|
2023-02-04 12:25:39 +00:00
|
|
|
private string data;
|
2022-08-11 09:26:30 +01:00
|
|
|
|
2023-01-30 17:03:48 +00:00
|
|
|
this(string data, Type type)
|
2022-08-11 09:26:30 +01:00
|
|
|
{
|
|
|
|
this.data = data;
|
2023-01-30 17:03:48 +00:00
|
|
|
this.type = type;
|
2022-08-11 09:26:30 +01:00
|
|
|
|
2023-01-30 17:03:48 +00:00
|
|
|
addInfo = "Data: "~to!(string)(data)~", Type: "~to!(string)(type);
|
2021-10-26 16:17:53 +01:00
|
|
|
}
|
2023-02-01 15:13:23 +00:00
|
|
|
|
2023-02-04 12:25:39 +00:00
|
|
|
public string getLiteralValue()
|
|
|
|
{
|
|
|
|
return data;
|
|
|
|
}
|
|
|
|
|
2023-02-01 15:13:23 +00:00
|
|
|
public override string toString()
|
|
|
|
{
|
|
|
|
return produceToStrEnclose("Data: "~to!(string)(data)~", Type: "~to!(string)(type));
|
|
|
|
}
|
2021-10-26 16:17:53 +01:00
|
|
|
}
|
|
|
|
|
2022-07-25 18:30:07 +01:00
|
|
|
/* 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
|
|
|
|
{
|
2022-07-26 08:58:25 +01:00
|
|
|
/* String interning pool */
|
|
|
|
private static int[string] internmentCamp;
|
|
|
|
private static int rollCount = 0;
|
|
|
|
private string stringLiteral;
|
|
|
|
|
|
|
|
|
|
|
|
this(string stringLiteral)
|
2022-07-25 18:30:07 +01:00
|
|
|
{
|
2022-07-26 08:58:25 +01:00
|
|
|
this.stringLiteral = stringLiteral;
|
|
|
|
|
|
|
|
/* Intern the string */
|
|
|
|
intern(stringLiteral);
|
|
|
|
|
|
|
|
addInfo = "StrLit: `"~stringLiteral~"`, InternID: "~to!(string)(intern(stringLiteral));
|
|
|
|
}
|
2022-07-25 18:30:07 +01:00
|
|
|
|
2022-07-26 08:58:25 +01:00
|
|
|
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;
|
2022-07-25 18:30:07 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-26 16:17:53 +01:00
|
|
|
/**
|
2021-10-26 21:03:48 +01:00
|
|
|
* BinOpInstr instruction
|
2021-10-26 16:17:53 +01:00
|
|
|
*
|
2021-10-26 21:03:48 +01:00
|
|
|
* Any sort of Binary Operator
|
2021-10-26 16:17:53 +01:00
|
|
|
*/
|
2022-04-07 23:34:50 +01:00
|
|
|
public class BinOpInstr : Value
|
2021-10-26 16:17:53 +01:00
|
|
|
{
|
2022-12-12 13:36:07 +00:00
|
|
|
public const Instruction lhs;
|
|
|
|
public const Instruction rhs;
|
|
|
|
public const SymbolType operator;
|
2021-10-26 16:17:53 +01:00
|
|
|
|
2021-10-26 21:03:48 +01:00
|
|
|
this(Instruction lhs, Instruction rhs, SymbolType operator)
|
2021-10-26 16:17:53 +01:00
|
|
|
{
|
|
|
|
this.lhs = lhs;
|
|
|
|
this.rhs = rhs;
|
2022-12-12 09:13:38 +00:00
|
|
|
this.operator = operator;
|
2021-10-26 19:58:42 +01:00
|
|
|
|
2021-10-26 21:03:48 +01:00
|
|
|
addInfo = "BinOpType: "~to!(string)(operator)~", LhsValInstr: "~lhs.toString()~", RhsValInstr: "~rhs.toString();
|
2021-10-26 16:17:53 +01:00
|
|
|
}
|
2022-02-15 13:04:16 +00:00
|
|
|
}
|
|
|
|
|
2022-04-12 09:52:18 +01:00
|
|
|
/**
|
|
|
|
* UnaryOpInstr instruction
|
|
|
|
*
|
|
|
|
* Any sort of Unary Operator
|
|
|
|
*/
|
|
|
|
public class UnaryOpInstr : Value
|
|
|
|
{
|
2023-02-04 12:25:39 +00:00
|
|
|
private Value exp;
|
2022-04-12 09:52:18 +01:00
|
|
|
private SymbolType operator;
|
|
|
|
|
2023-02-04 12:25:39 +00:00
|
|
|
this(Value exp, SymbolType operator)
|
2022-04-12 09:52:18 +01:00
|
|
|
{
|
|
|
|
this.exp = exp;
|
2022-12-12 09:13:38 +00:00
|
|
|
this.operator = operator;
|
2022-04-12 09:52:18 +01:00
|
|
|
|
|
|
|
addInfo = "UnaryOpType: "~to!(string)(operator)~", Instr: "~exp.toString();
|
|
|
|
}
|
2023-01-12 08:53:48 +00:00
|
|
|
|
|
|
|
public SymbolType getOperator()
|
|
|
|
{
|
|
|
|
return operator;
|
|
|
|
}
|
|
|
|
|
2023-02-04 12:25:39 +00:00
|
|
|
public Value getOperand()
|
2023-01-12 08:53:48 +00:00
|
|
|
{
|
|
|
|
return exp;
|
|
|
|
}
|
2022-04-12 09:52:18 +01:00
|
|
|
}
|
|
|
|
|
2022-02-15 13:04:16 +00:00
|
|
|
/**
|
|
|
|
* 2022 New things
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2022-02-18 12:32:45 +00:00
|
|
|
//public class CallInstr : Instruction
|
|
|
|
public class CallInstr : Value
|
2022-02-15 13:04:16 +00:00
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
public class FuncCallInstr : CallInstr
|
|
|
|
{
|
2022-02-18 12:32:45 +00:00
|
|
|
/* Per-argument instrructions */
|
2022-02-20 13:36:22 +00:00
|
|
|
private Value[] evaluationInstructions;
|
2022-02-18 12:32:45 +00:00
|
|
|
|
2022-12-16 12:53:33 +00:00
|
|
|
public const string functionName;
|
2022-02-18 12:32:45 +00:00
|
|
|
|
|
|
|
this(string functionName, ulong argEvalInstrsSize)
|
|
|
|
{
|
|
|
|
this.functionName = functionName;
|
|
|
|
evaluationInstructions.length = argEvalInstrsSize;
|
|
|
|
|
2022-02-20 13:35:18 +00:00
|
|
|
updateAddInfo();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* FuncCallInstr is built-bit-by-bit so toString information will change
|
|
|
|
*/
|
|
|
|
private void updateAddInfo()
|
|
|
|
{
|
|
|
|
addInfo = "FunctionName: "~functionName ~" EvalInstrs: "~ to!(string)(getEvaluationInstructions());
|
2022-02-18 12:32:45 +00:00
|
|
|
}
|
|
|
|
|
2022-02-20 13:36:22 +00:00
|
|
|
public void setEvalInstr(ulong argPos, Value instr)
|
2022-02-18 12:32:45 +00:00
|
|
|
{
|
|
|
|
evaluationInstructions[argPos] = instr;
|
2022-02-20 13:35:18 +00:00
|
|
|
updateAddInfo();
|
|
|
|
}
|
|
|
|
|
2022-02-20 13:36:22 +00:00
|
|
|
public Value[] getEvaluationInstructions()
|
2022-02-20 13:35:18 +00:00
|
|
|
{
|
|
|
|
return evaluationInstructions;
|
2022-02-18 12:32:45 +00:00
|
|
|
}
|
2022-12-17 17:02:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public final class ReturnInstruction : Instruction
|
|
|
|
{
|
|
|
|
private Value returnExprInstr;
|
|
|
|
|
|
|
|
this(Value returnExprInstr)
|
|
|
|
{
|
|
|
|
this.returnExprInstr = returnExprInstr;
|
|
|
|
}
|
|
|
|
|
|
|
|
public Value getReturnExpInstr()
|
|
|
|
{
|
|
|
|
return returnExprInstr;
|
|
|
|
}
|
2022-12-19 13:37:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public final class IfStatementInstruction : Instruction
|
|
|
|
{
|
|
|
|
private BranchInstruction[] branchInstructions;
|
|
|
|
|
|
|
|
this(BranchInstruction[] branchInstructions)
|
|
|
|
{
|
|
|
|
this.branchInstructions = branchInstructions;
|
|
|
|
|
|
|
|
addInfo = "Branches: "~to!(string)(branchInstructions);
|
|
|
|
}
|
|
|
|
|
|
|
|
public BranchInstruction[] getBranchInstructions()
|
|
|
|
{
|
|
|
|
return branchInstructions;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-04 10:03:50 +00:00
|
|
|
public final class WhileLoopInstruction : Instruction
|
|
|
|
{
|
|
|
|
private BranchInstruction branchInstruction;
|
|
|
|
|
|
|
|
this(BranchInstruction branchInstruction)
|
|
|
|
{
|
|
|
|
this.branchInstruction = branchInstruction;
|
|
|
|
|
|
|
|
addInfo = "Branch: "~to!(string)(branchInstruction);
|
|
|
|
}
|
|
|
|
|
|
|
|
public BranchInstruction getBranchInstruction()
|
|
|
|
{
|
|
|
|
return branchInstruction;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-11 08:43:29 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-19 13:37:55 +00:00
|
|
|
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;
|
|
|
|
}
|
2023-01-12 08:53:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
2023-01-13 08:49:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public final class DiscardInstruction : Instruction
|
|
|
|
{
|
|
|
|
private Value exprInstr;
|
|
|
|
|
|
|
|
this(Value exprInstr)
|
|
|
|
{
|
|
|
|
this.exprInstr = exprInstr;
|
|
|
|
}
|
|
|
|
|
|
|
|
public Value getExpressionInstruction()
|
|
|
|
{
|
|
|
|
return exprInstr;
|
|
|
|
}
|
2023-01-14 16:40:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
2023-02-03 14:13:40 +00:00
|
|
|
this.type = castToType;
|
2023-01-14 16:40:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public Value getEmbeddedInstruction()
|
|
|
|
{
|
|
|
|
return uncastedValue;
|
|
|
|
}
|
|
|
|
|
|
|
|
public Type getCastToType()
|
|
|
|
{
|
2023-02-03 14:13:40 +00:00
|
|
|
return type;
|
2023-01-14 16:40:08 +00:00
|
|
|
}
|
Array support (#1)
* Parser
- Added ability for `parseName()` to recognize array types
- Added array type handling to `parseTypedDeclaration()`
- Removed unneeded `derefCount` and comment in `parseTypedDeclaration()`
Check
- Added new symbol types `OBRACKET` and `CBRACKET`
* Tets cases
- We will now be using `simple_arrays2.t` as our testing bench for array support
* Dependency
- When a variable declaration has a kind-of type we are unaware of then print out an error message before asserting `false`
* Builtins
- `getBuiltInType(TypeChecker, string)` will now return a `Pointer` object for arrays of which the type was `<componentType>[]` (non-stack bound) as effectively they are pointers with a different syntax -doing it here means that it is transparent and typechecking, code gen and emit will just see a pointer type which makes life a lot easier
* Builtins
- Added information about the current bug faced in issue #81 (third sub-issue)
* Test cases
- Updated test case `simple_arrays2.t` to show case bug sub-issue 3 in issue #81
* Builtins
- Removed seperate handling of `<componentType>[]` and incorporated it into the pointer check, now we have fixed sub-issue 3 of issue #81
Test cases
- Updated test case `simple_arrays2.t` to showcase the aforementioned fix
* Builtins
- Updated TODO
* Builtins
- Removed comment as now fixed
* Array
- Added `getComponentType()` method which will return the array's element type
* Dependency
- When processing the `Array` type which is now to be seen as a stack-based array (fixed size), error out in processing it during variable declarations
* Builtins
- Added `bool isStackArray(string)` in order to check if a given type string is designated as a stack-array type or not
- `Type getBuiltInType(TypeChecker, string)` now can generate the `StackArray` type including the component type and the size of the stack allocation
Parser
- Added support to`parseTypedDeclaration` to be able to parse stack-based array types
- Added terminator `]` to `parseExpression()`
DGen
- Added stack-based array type transformation support to `string typeTransform(Type)`
- Added transformation support for stack-based arrays for the `VariableDeclaration` instruction
StackArray
- Renamed `Array` type to `StackArray`
` The `StackArray` type now has an `arraySize` field and is included in the constructor's paremeters
- Added a `getAllocatedSize()` method to retrieve the `arraySize` field
Dependency
- Temporarily enabled the `StackArray` type in dependency processing for `VariableDeclarations` such that we can continue through the pipeline
Test cases
- Updated `simple_arrays.t` to test stack-based array types
* Tets cases
- Added new test case for testing (later) multi-dimensional stack-arrays
* Parser
- Working on adding array index assignment support
Test cases
- Added test case to test array assignments with
* Parser
- We can now detect when infact we are doing an array-indexed assignment and when not, we then flip` arrayIndexing` to `true` if that is the case and ensure that `=` SymbolType.ASSIGN is not triggering the varaible-declaration-with-assignment but rather eters a different branch based on this boolean
- Set the identifier being assigned to (in the array indexing case) to the `type` with the `[]...` stripped
Notes
- Added a TODO file `wip.txt` with notes about what is to be done for adding full array support
* Parser
- Handle the case whereby `SymbolType.ASSIGN` or `SymbolType.IDENT_TYPE` is not found by throwing an error
* Parser
- Moved logic for array assignments into the branch for it (deferred it)
* Data
- Added new work-in-progress parser node type `ArrayAssignment`
Parser
- Added TODO about the type of returned parse node needing to be updated down the line
Notes
- Updated `wip.txt` with more thoughts
* Expressions
- Added new parse node (a sub-type of `Expression`) for representing array indexing; `ArrayIndex`
Data
- Fixed compilation error caused by missing semi-colon
* Parser
- Added support for array accesses/indexing in `parseExpression()`
- Added a token-rerun mechanism that lets us replay the needed tokens which needed to be looked ahead in order to determine an array access was about to occur
* Parser
- Removed now-completed TODO relating to array accesses in `parseExpression()`
* Parser
- Added right-hand side expression parsing for array assignments
Test cases
- Updated test case to test both array expressions on the left-hand side of an assignment and as a free-standing expression on the right hand side
Data
- Implemeneted `ArrayAssignment` which is to be used for assigning into arrays
* Instruction
- Added new instruction for indexing into arrays, a new `Value`-type instruction called `ArrayIndexInstruction`
* DGen
- Handle `ArrayIndexInstruction` which is for whenever you index into a point-based array (an expression like `myArray[i]` is now being supported in emit (first steps))
* Instructions
- Added a new instruction type, `StackArrayINdexInstruction`, which is used to know when we are indexing into a stack-based array rather than a pointer-based array (just to be able to disambiguate between the two)
- Added a work-in-progress type `StackArrayIndexAssignmentInstruction` which will be used for assigning to stack arrays at a given index
* Instructions
- Added implementation for `StackArrayIndexAssignmentInstruction` which represents the assignment of some `Value` instruction to a stack-based array (indicated by the `arrayName` string field) at the index indicated by the provided `Value` instruction
* DGen
- Added a stub emitter for `ArrayIndexInstruction` (pointer-based array indexing)
- Added a stub emitter for `StackArrayINdexInstruction` (stack-array based array indexing)
* INstructions
- Added `getArrayName()`, `getIndexInstr()` and `getAssignedValue()` to `StackArrayIndexAssignmentInstruction`
* Instructions
- Added `ArrayIndexAssignmentInstruction` which is intended to be used for when one wants to assign into a pointer-based array
- It embeds a `Value` instruction which is what is to be assigned and then an `ArrayIndexInstruction` representing the base of the poiinter-based array (base address) coupled with an "index" (offset)
- Added a `toString()` override for `StackArrayIndexAssignmentInstruction`
* Test cases
- Added `complex_stack_arrays1.t`
- This tests a stack array of a fixed size of `int[]` (basically `int*`) and assigneing into it
* Test cases
- Added `simple_arrays4.t` which makes an `int[]` (which is an `int*`) and then assignes into it at `i` whilst referring to itself at `i` and doing a binary operation
* Test cases
- Added `simple_stack_arrays2.t` which tests a stack array of a fixed size and then assigns into it a value
* Test cases
- Added `simple_stack_arrays4.t` which just tests assigning to a stack array of a fixed size BUT referring to said stack array itself as part of the assignment expression
* DGen
- Removed TODO comment for `ArrayIndexInstruction` transformation branch
- Added a description for when the `ArrayIndexInstruction` branch is activated for a transformation
- Implemented transformation for `ArrayIndexInstruction`
- Added comment on when `ArrayIndexAssignmentInstruction` activates
- Implemented transformation for `ArrayIndexAssignmentInstruction`
- Added comment for when the `StackArrayIndexInstruction` branch activates
- Implemented transformation for `StackArrayIndexInstruction`
- Added comment for when `StackArrayIndexAssignmentInstruction` branch activates
- Implemented transformation for `StackArrayIndexAssignmentInstruction`
* Dependency
- Added dependency node generation for the `ArrayIndex`
- This will pool the `ArrayIndex` parser-node
- This will then set the context of the parser-node to the current context
- The index expression will be depended upon
- The indexed expression (the entity being indexed) will be depended upon
---
- Added dependency generation for `ArrayAssignment`
- The `ArrayAssignment` parser node will be pooled
- The `ArrayAssignment` will have its context set to the current context
- The assigned expression will be depended upon
- The entity being indexed will be depended upon
- The index expression will be depended upon
* Parser
- Added a branch to `parseName()` which handles array assignments's semicolon consumption and token cursor movement to the next token
- Updated `parseTypedDeclaration()` to return an object of type `Statement` rather than `TypedEntity`
- Disabled the intentional `assert(false)` when handling array assignments
- Assign the generated `ArrayAssignment` to the `generated` variable
- Updated `parseExtern()` to cast to `TypedEntity` to ensure that the `Statement` returned is of that sub-type (added an assertion to then check this fact)
* Typechecker/Codegen
- Implemented `isStackArray(Value)` which checks if the given `Value` instruction is a `FetchValueVar`, then extracts the `Variable` being referred to in said instruction and checks if its declared type is that of `StackArray`
- Implemented code generation for `ArrayAssignment`
- Implemented code generation for `ArrayIndex`
* Test cases
- WIP: Added `simple_stack_array_coerce.t` as we want to add coercion for this now
* Typecheck
- Added rudimentary check for checking if an argument is a stack array, and if the parameter (to a function call) is a pointer and if so then returns whether they have matching component types in a new function named `canCoerceStackArray(Type, Type)`
* Typecheck
- Fixed `canCoerceStackArray(Type, Type)` to actually coerce the first type first into a pointer type (coercing the stack array's component type to `<compType>*`) and THEN apply the `isSameType(Type, Type)` check
* Typecheck
- Hoisted up `canCoerceStackArray(Type, Type)` to the class-level of `TypeChecker`
- Removed debug prints from `canCoerceStackArray(Type, Type)`
- Added a TODO where the check should be done in the `FunctionCall` branch of the `DNode` processor
* TypeChecker
- Added a seperate check for function call `DNode` processing which now checks if we can coerce the stack-array-based argument to the pointer-based type parameter
Notes
- Emit now fails as we haven't implement an emit for this case, so we need to do that.
- Also, should we change the type of what is being passed in - perhaps that actually makes sense here - we haven't fully coerced it actually
* TypeChecker
- Updated `canCoerceStackArray(Type, Type)` to now take in `canCoerceStackArray(Type, Type, ref Type)` to set the newly created coerced type
- Fixed bug whereby if the coercion succeeded we didn't actually add to the list of evaluation-instructions in the `FuncCallInstr` object, hence there would be a `null` Instruction object appearing in the code emit phase.
- Added some NOTEs which we can clean up this code using
* TypeChecker
- Cleaned up commented-out code
* Added CI/CD test for 'simple_stack_array_coerce.t'
* Added CI/CD test for 'complex_stack_arrays1.t'
* Added CI/CD semantic tests (WIP) for 'simple_stack_array_coerce.t' and 'complex_stack_arrays1.t'
* Added CI/CD semantic tests (WIP) for 'simple_arrays2.t' and 'simple_arrays4.t'
* Added CI/CD semantic tests (WIP) for 'simple_arrays2.t' and 'simple_arrays4.t'
* Added CI/CD semantic tests (WIP) for 'simple_arrays2.t' and 'simple_arrays4.t'
* Fixed filepath for test 'simple_arrays.t'
* Fixed typechecking tests for arrays
* DGen
- Added instrumentation for `simple_stack_array_coerce.t`
Test cases
- Updated `simple_stack_array_coerce.t` to update the array passed in a manner such that we can sum the two elements later, return it and assert to ensure it is set correctly
* Parser
- Had to ensure the old identifier code was removed too, was too early; therefore this now-dead code was removed
* Test cases
- Added this test (even though it is a bad test, the syntax ie wrong)
* Test cases
- Update `simple_stack_arrsys4.t` to return an `int` such that we can verify it works.
- Also added more tests to it.
DGen
- Added semantic test code generation for `simple_stack_arrays4.t`
CI
- Re-organised tests for semantics in emit for arrays into those "Which have semantic tests" and "those which don't (yet)"
- Added semantic/emit test for `simple_stack_arrays4.t`
* Test cases
- Updated `simple_arrays2.t` to test casting of complex array types
* Test cases
- Updated `complex_stack_arrays1.t`
* Test cases
- Added new test for testing pointer syntax; `simple_stack_array_coerce_ptr_syntax.t`
- FIXME: It is broken as we don't have the latest pointer code - that must still be finished
* Test cases
- Added test case `simple_stack_array_ceorce_wrong.t` where coercion must fail
* Test cases
- Added `simple_pointer_array_syntax.t` which should test the `int[] == int*` stuff
* DGen
- Made semantic test for `simple_pointer_array_syntax.t`
Test cases
- Added a test for `simple_pointer_array_syntax.t.t`
* Branding
- Added logo here
* Test cases
- Addes semantic code emit instrucmentation for `simple_stack_array_coerce_ptr_syntax.t`
* Pipelines
- Added test case for `source/tlang/testing/simple_stack_array_coerce_wrong.t` for typechecking phase
* Test cases
- Added test case `complex_stack_array_coerce.t`
* Test cases
- Added extensive positive test case `complex_stack_array_coerce_permutation_good.t` which has a lot of different ways to write `int**` (think `int*[]` etc)
- Added negative test cases `complex_stack_array_coerce_bad1.t`, `complex_stack_array_coerce_bad2.t` and `complex_stack_array_coerce_bad3.t`
2023-04-20 10:21:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
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()~"]";
|
|
|
|
}
|
2021-10-26 16:17:53 +01:00
|
|
|
}
|