Instruction

- Added new instruction `DiscardInstruction`

DGen

- Added ability to transform `DiscardInstruction`

Parser

- Implemented `parseDiscard()`
- Removed a TODO
- Added a unittest testing the new `parseDiscard()`
- Typo fixes here and there in unittests

Data

- Added new parser node `DiscardStatement`

Typechecker

- Added codegen for `DiscardStatement` type

Dependency

- Added dependency processing for `DiscardStatement` type

Tests

- Added new test case `simple_discard.t`
This commit is contained in:
Tristan B. Velloza Kildaire 2023-01-13 10:49:47 +02:00
parent 1dd70911d0
commit 6333fdcd42
7 changed files with 184 additions and 10 deletions

View File

@ -386,6 +386,21 @@ public final class DCodeEmitter : CodeEmitter
emit ~= transform(rhsAssExprInstr)~";";
return emit;
}
/**
* Discard instruction (DiscardInstruction)
*/
else if(cast(DiscardInstruction)instruction)
{
DiscardInstruction discardInstruction = cast(DiscardInstruction)instruction;
Value valueInstruction = discardInstruction.getExpressionInstruction();
string emit;
/* Transform the expression */
emit ~= transform(valueInstruction)~";";
return emit;
}

View File

@ -439,4 +439,19 @@ public final class PointerDereferenceAssignmentInstruction : Instruction
{
return derefCount;
}
}
public final class DiscardInstruction : Instruction
{
private Value exprInstr;
this(Value exprInstr)
{
this.exprInstr = exprInstr;
}
public Value getExpressionInstruction()
{
return exprInstr;
}
}

View File

@ -963,7 +963,7 @@ public final class Parser
*
* TODO: Remove discard and implement the needed mirrors
*/
private Expression parseDiscard()
private DiscardStatement parseDiscard()
{
/* Consume the `discard` */
nextToken();
@ -975,7 +975,10 @@ public final class Parser
expect(SymbolType.SEMICOLON, getCurrentToken());
nextToken();
return expression;
/* Create a `discard` statement */
DiscardStatement discardStatement = new DiscardStatement(expression);
return discardStatement;
}
/**
@ -1648,6 +1651,12 @@ public final class Parser
/* Parse the return statement */
statement = parseReturn();
}
/* If it is a `discard` statement */
else if(symbol == SymbolType.DISCARD)
{
/* Parse the discard statement */
statement = parseDiscard();
}
/* If it is a dereference assigment (a `*`) */
else if(symbol == SymbolType.STAR)
{
@ -1735,8 +1744,6 @@ public final class Parser
Module modulle;
/* TODO: Do parsing here */
/* Expect `module` and module name and consume them (and `;`) */
expect(SymbolType.MODULE, getCurrentToken());
nextToken();
@ -1819,9 +1826,10 @@ public final class Parser
/* If it is a `discard` statement */
else if(symbol == SymbolType.DISCARD)
{
Expression expression = parseDiscard();
/* Parse the3 discard statement */
Statement statement = parseDiscard();
modulle.addStatement(expression);
modulle.addStatement(statement);
}
else
{
@ -2030,6 +2038,66 @@ class myClass2
}
}
/**
* Discard statement test case
*/
unittest
{
import std.stdio;
import compiler.lexer;
import compiler.typecheck.core;
string sourceCode = `
module parser_discard;
void function()
{
discard function();
}
`;
Lexer currentLexer = new Lexer(sourceCode);
assert(currentLexer.performLex());
Parser parser = new Parser(currentLexer.getTokens());
try
{
Module modulle = parser.parse();
/* Module name must be parser_discard */
assert(cmp(modulle.getName(), "parser_discard")==0);
TypeChecker tc = new TypeChecker(modulle);
/* Find the function named `function` */
Entity func = tc.getResolver().resolveBest(modulle, "function");
assert(func);
assert(cast(Function)func); // Ensure it is a Funciton
/* Get the function's body */
Container funcContainer = cast(Container)func;
assert(funcContainer);
Statement[] functionStatements = funcContainer.getStatements();
assert(functionStatements.length == 1);
/* First statement should be a discard */
DiscardStatement discard = cast(DiscardStatement)functionStatements[0];
assert(discard);
/* The statement being discarded should be a function call */
FunctionCall functionCall = cast(FunctionCall)discard.getExpression();
assert(functionCall);
}
catch(TError e)
{
assert(false);
}
}
/**
* Function definition test case
*/
@ -2062,7 +2130,7 @@ int myFunction(int i, int j)
{
Module modulle = parser.parse();
/* Module name must be parser_while */
/* Module name must be parser_function_def */
assert(cmp(modulle.getName(), "parser_function_def")==0);
TypeChecker tc = new TypeChecker(modulle);
@ -2245,7 +2313,7 @@ int thing()
{
Module modulle = parser.parse();
/* Module name must be parser_while */
/* Module name must be simple_pointer */
assert(cmp(modulle.getName(), "simple_pointer")==0);
TypeChecker tc = new TypeChecker(modulle);
@ -2329,7 +2397,7 @@ void function()
{
Module modulle = parser.parse();
/* Module name must be parser_while */
/* Module name must be parser_for */
assert(cmp(modulle.getName(), "parser_for")==0);
TypeChecker tc = new TypeChecker(modulle);
@ -2451,7 +2519,7 @@ void function()
{
Module modulle = parser.parse();
/* Module name must be parser_while */
/* Module name must be parser_if */
assert(cmp(modulle.getName(), "parser_if")==0);
TypeChecker tc = new TypeChecker(modulle);

View File

@ -872,4 +872,27 @@ public final class Branch : Entity, Container
{
return "Branch";
}
}
public final class DiscardStatement : Statement
{
private Expression expression;
this(Expression expression)
{
this.expression = expression;
/* Weighted as 2 */
weight = 2;
}
public Expression getExpression()
{
return expression;
}
public override string toString()
{
return "[DiscardStatement: (Exp: "~expression.toString()~")]";
}
}

View File

@ -1097,6 +1097,29 @@ public final class TypeChecker
pointerDereferenceAssignmentInstruction.context = ptrDerefAss.context;
addInstrB(pointerDereferenceAssignmentInstruction);
}
/**
* Discard statement (DiscardStatement)
*/
else if(cast(DiscardStatement)statement)
{
DiscardStatement discardStatement = cast(DiscardStatement)statement;
/* Pop off a Value instruction */
Value exprInstr = cast(Value)popInstr();
assert(exprInstr);
/**
* Code gen
*
* 1. Create the DiscardInstruction containing the Value instruction
* `exprInstr`
* 2. Set the context
* 3. Add the instruction
*/
DiscardInstruction discardInstruction = new DiscardInstruction(exprInstr);
discardInstruction.context = discardStatement.context;
addInstrB(discardInstruction);
}
/* Case of no matches */
else
{

View File

@ -1497,6 +1497,25 @@ public class DNodeGenerator
return ptrAssDerefDNode;
}
/**
* Discard statement (DiscardStatement)
*/
else if(cast(DiscardStatement)entity)
{
DiscardStatement discardStatement = cast(DiscardStatement)entity;
discardStatement.setContext(context);
DNode discardStatementDNode = pool(discardStatement);
gprintln("Implement discard statement!", DebugType.ERROR);
/* Pass the expression */
Expression discardExpression = discardStatement.getExpression();
DNode discardExpresionDNode = expressionPass(discardExpression, context);
discardStatementDNode.needs(discardExpresionDNode);
return discardStatementDNode;
}
return null;
}

View File

@ -0,0 +1,11 @@
module simple_discard;
void hello()
{
}
int myEntry()
{
discard hello();
}