Instruction
- Implemented new instruction `CastedValueInstruction` - Added import for `Type` DGen - Implemented primitive type casting code generation in `transform()` - Added import for `Type` and `Primitive` Parser - Implemented `parseCast()` which is called by `parseExpression()` Check - Added new symbol type `SymbolType.CAST` Expressions - Implemented new expression type `CastedExpression` Typechecker - Implemented processing of `CastedExpression` in the expression section, along with correct type/instruction pushes and pops Dependency - Implemented dependency generation of `CastedExpression` in `expressionPass()` Test cases - Added test file `simple_cast.t`
This commit is contained in:
parent
c1ba609609
commit
113386ebe2
|
@ -17,6 +17,7 @@ import compiler.codegen.mapper : SymbolMapper;
|
|||
import compiler.symbols.data : SymbolType, Variable, Function, VariableParameter;
|
||||
import compiler.symbols.check : getCharacter;
|
||||
import misc.utils : Stack;
|
||||
import compiler.symbols.typing.core : Type, Primitive;
|
||||
|
||||
public final class DCodeEmitter : CodeEmitter
|
||||
{
|
||||
|
@ -401,6 +402,42 @@ public final class DCodeEmitter : CodeEmitter
|
|||
/* Transform the expression */
|
||||
emit ~= transform(valueInstruction)~";";
|
||||
|
||||
return emit;
|
||||
}
|
||||
/**
|
||||
* Type casting instruction (CastedValueInstruction)
|
||||
*/
|
||||
else if(cast(CastedValueInstruction)instruction)
|
||||
{
|
||||
CastedValueInstruction castedValueInstruction = cast(CastedValueInstruction)instruction;
|
||||
Type castingTo = castedValueInstruction.getCastToType();
|
||||
|
||||
// TODO: Dependent on type being casted one must handle different types, well differently (as is case for atleast OOP)
|
||||
|
||||
Value uncastedInstruction = castedValueInstruction.getEmbeddedInstruction();
|
||||
|
||||
|
||||
string emit;
|
||||
|
||||
/* Handling of primitive types */
|
||||
if(cast(Primitive)castingTo)
|
||||
{
|
||||
/* Add the actual cast */
|
||||
emit ~= "("~to!(string)(castingTo)~")";
|
||||
|
||||
/* The expression being casted */
|
||||
emit ~= transform(uncastedInstruction);
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: Implement this
|
||||
gprintln("Non-primitive type casting not yet implemented", DebugType.ERROR);
|
||||
assert(false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
return emit;
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ import std.string : cmp;
|
|||
import compiler.symbols.data : SymbolType;
|
||||
import compiler.symbols.check : getCharacter;
|
||||
import gogga;
|
||||
import compiler.symbols.typing.core : Type;
|
||||
|
||||
public class Instruction
|
||||
{
|
||||
|
@ -454,4 +455,28 @@ public final class DiscardInstruction : Instruction
|
|||
{
|
||||
return exprInstr;
|
||||
}
|
||||
}
|
||||
|
||||
public final class CastedValueInstruction : Value
|
||||
{
|
||||
/* The uncasted original instruction that must be executed-then-trimmed (casted) */
|
||||
private Value uncastedValue;
|
||||
|
||||
private Type castToType;
|
||||
|
||||
this(Value uncastedValue, Type castToType)
|
||||
{
|
||||
this.uncastedValue = uncastedValue;
|
||||
this.castToType = castToType;
|
||||
}
|
||||
|
||||
public Value getEmbeddedInstruction()
|
||||
{
|
||||
return uncastedValue;
|
||||
}
|
||||
|
||||
public Type getCastToType()
|
||||
{
|
||||
return castToType;
|
||||
}
|
||||
}
|
|
@ -986,6 +986,36 @@ public final class Parser
|
|||
*/
|
||||
|
||||
|
||||
private CastedExpression parseCast()
|
||||
{
|
||||
CastedExpression castedExpression;
|
||||
|
||||
/* Consume the `cast` */
|
||||
nextToken();
|
||||
|
||||
/* Expect an `(` open brace */
|
||||
expect(SymbolType.LBRACE, getCurrentToken());
|
||||
nextToken();
|
||||
|
||||
/* Expect a type */
|
||||
expect(SymbolType.IDENT_TYPE, getCurrentToken());
|
||||
string toType = getCurrentToken().getToken();
|
||||
nextToken();
|
||||
|
||||
/* Expect a `)` closing brace */
|
||||
expect(SymbolType.RBRACE, getCurrentToken());
|
||||
nextToken();
|
||||
|
||||
/* Get the expression to cast */
|
||||
Expression uncastedExpression = parseExpression();
|
||||
|
||||
|
||||
castedExpression = new CastedExpression(toType, uncastedExpression);
|
||||
|
||||
return castedExpression;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parses an expression
|
||||
*
|
||||
|
@ -1065,6 +1095,12 @@ public final class Parser
|
|||
/* Get the next token */
|
||||
nextToken();
|
||||
}
|
||||
/* If it is a cast operator */
|
||||
else if(symbol == SymbolType.CAST)
|
||||
{
|
||||
CastedExpression castedExpression = parseCast();
|
||||
addRetExp(castedExpression);
|
||||
}
|
||||
/* If it is a maths operator */
|
||||
/* TODO: Handle all operators here (well most), just include bit operators */
|
||||
else if (isMathOp(getCurrentToken()) || isBinaryOp(getCurrentToken()))
|
||||
|
|
|
@ -58,6 +58,7 @@ public enum SymbolType
|
|||
SMALLER_THAN,
|
||||
GREATER_THAN_OR_EQUALS,
|
||||
SMALLER_THAN_OR_EQUALS,
|
||||
CAST,
|
||||
UNKNOWN
|
||||
}
|
||||
|
||||
|
@ -326,6 +327,11 @@ public SymbolType getSymbolType(Token tokenIn)
|
|||
{
|
||||
return SymbolType.NEW;
|
||||
}
|
||||
/* cast keyword */
|
||||
else if(cmp(token, "cast") == 0)
|
||||
{
|
||||
return SymbolType.CAST;
|
||||
}
|
||||
/* discard keyword */
|
||||
else if(cmp(token, "discard") == 0)
|
||||
{
|
||||
|
|
|
@ -138,4 +138,26 @@ public final class NewExpression : Expression
|
|||
{
|
||||
return funcCall;
|
||||
}
|
||||
}
|
||||
|
||||
public final class CastedExpression : Expression
|
||||
{
|
||||
private Expression uncastedExpression;
|
||||
private string toType;
|
||||
|
||||
this(string toType, Expression uncastedExpression)
|
||||
{
|
||||
this.toType = toType;
|
||||
this.uncastedExpression = uncastedExpression;
|
||||
}
|
||||
|
||||
public string getToType()
|
||||
{
|
||||
return toType;
|
||||
}
|
||||
|
||||
public Expression getEmbeddedExpression()
|
||||
{
|
||||
return uncastedExpression;
|
||||
}
|
||||
}
|
|
@ -737,6 +737,40 @@ public final class TypeChecker
|
|||
addInstr(funcCallInstr);
|
||||
addType(getType(func.parentOf(), func.getType()));
|
||||
}
|
||||
/* Type cast operator */
|
||||
else if(cast(CastedExpression)statement)
|
||||
{
|
||||
CastedExpression castedExpression = cast(CastedExpression)statement;
|
||||
gprintln("Context: "~to!(string)(castedExpression.context));
|
||||
gprintln("ParentOf: "~to!(string)(castedExpression.parentOf()));
|
||||
Type castToType = getType(castedExpression.context.container, castedExpression.getToType());
|
||||
|
||||
/* Pop the type associated with the embedded expression */
|
||||
Type typeBeingCasted = popType(); // TODO: Is there anything we would want to do with this?
|
||||
gprintln("TypeCast [FromType: "~to!(string)(typeBeingCasted)~", ToType: "~to!(string)(castToType)~"]");
|
||||
|
||||
/* Push the type to cast to onto the stack such that we typify the associated instruction */
|
||||
addType(castToType);
|
||||
|
||||
/**
|
||||
* Codegen
|
||||
*
|
||||
* 1. Pop off the current value instruction corresponding to the embedding
|
||||
* 2. Create a new CastedValueInstruction instruction
|
||||
* 3. Set the context
|
||||
* 4. Add to front of code queue
|
||||
*/
|
||||
Value uncastedInstruction = cast(Value)popInstr();
|
||||
assert(uncastedInstruction);
|
||||
|
||||
printCodeQueue();
|
||||
printTypeQueue();
|
||||
|
||||
CastedValueInstruction castedValueInstruction = new CastedValueInstruction(uncastedInstruction, castToType);
|
||||
castedValueInstruction.context = castedExpression.context;
|
||||
|
||||
addInstr(castedValueInstruction);
|
||||
}
|
||||
}
|
||||
/* VariableAssigbmentDNode */
|
||||
else if(cast(compiler.typecheck.dependency.variables.VariableAssignmentNode)dnode)
|
||||
|
|
|
@ -1095,6 +1095,22 @@ public class DNodeGenerator
|
|||
/* TODO: Add specific DNode type dependent on the type of operator */
|
||||
dnode.needs(expressionNode);
|
||||
}
|
||||
/**
|
||||
* Type cast operator (CastedExpression)
|
||||
*/
|
||||
else if(cast(CastedExpression)exp)
|
||||
{
|
||||
CastedExpression castedExpression = cast(CastedExpression)exp;
|
||||
|
||||
// Set the context as we need to grab it later in the typechecker
|
||||
castedExpression.context = context;
|
||||
|
||||
/* Extract the embedded expression and pass it */
|
||||
Expression uncastedExpression = castedExpression.getEmbeddedExpression();
|
||||
DNode uncastedExpressionDNode = expressionPass(uncastedExpression, context);
|
||||
|
||||
dnode.needs(uncastedExpressionDNode);
|
||||
}
|
||||
else
|
||||
{
|
||||
// dnode = new DNode(this, exp);
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
module simple_cast;
|
||||
|
||||
int myInt;
|
||||
|
||||
void function()
|
||||
{
|
||||
byte myByte = cast(byte)myInt;
|
||||
}
|
Loading…
Reference in New Issue