- Fixed missing flushing for issue #65 (see "Flushing fix ")
- Added unit test for flushing fix

VariableDeclaration (Instruction)

- Added support for the embedding of a VariableAssignmentInstr inside (added a getter too) (a part of issue #66)
- Conditional support for if statements: Added two new instructions (IfStatementInstruction and BranchInstruction). See issue #64

DGen

- Added depth increment/decrement on enter/leave scope of `transform()`
- Correct tabbing for nested if-statements using new method `genTabs(ulong)` (which uses the above mechanism). Makes code emitted for if statements (issue #64) look nicer.
- Updated VariableDeclarations (with assignments) handling in `transform()` in the manner similar to BinOpInstr (see issue #66)
- Added a TODO for formatting BinOpInstr's `transform()` a little more aesthetically nicer
- Added code emitting support for if statements (the `IfStatementInstruction` instruction) (see issue #64)
- Updated `emitEntryPoint()` to only emit testing C code for the correct input test file

Parser

- `parseIf()` now returns an instance of IfStatement which couples multiple `Branch` objects consisting of `Statement[]` and `Expression`
- Ensured that each `Statement` of the generated `Statement[]` from `parseBody()` for a given `Branch` is parented to said Branch using `parentToContainer()`
- Ensured each generated `Branch` in `Branch[]` is parented to the generated `IfStatement` using `parentToContainer()`
- `parseBody()` now adds to its `Statement[]` build-up array the generated `IfStatement` from the call to `parseIf()`

Check

- Added support for back-mapping `SymbolType.EQUALS` to `getCharacter(SymbolType)`

Data

- Added `Branch` parser node which is a Container for body statements (`Statement[]`)
- Added `IfStatement` parser node which is a Container of `Statement[]` which are actually `Branch[]`

TypeChecker

- Moved import for `reverse` to top of module
- Implemented `tailPopInstr()` method which will pop from the back of the `codeQueue` "scratchpad"
- Fixes handling of `StaticVariableDeclaration` and `VariableAssignmentNode` (fixes issue #66)
- Added handling for IfStatement entities (if statement support #64)

Resolution

- Added a debug statement to `resolveUp(Container, string)` to print out the container to lookup from and the name being looked up

Dependency

- Added a default `toString()` to the DNode class which prints `[DNode: <entity toString()]`
- Added a TODO and debug print related to issues #9
- Disabled InitScope.STATIC check for now as it caused issues with if statement parsing (probably due to VIRTUAL being default and therefore skipping if statment processing) - issue #69
- Cleaned up handling of Entity type `Variable` (variable declarations) - removed repeated code
- Undid the VarAss->(depends on)->VarDec, reverted back to VarDec->(depends on)->VarAss, fixed by #66 (and closes it and #11)
- Added support for `IfStatement` (if statements) in `generalPass(Container, Context)`

Test cases

- Added new test case testing nested if statements (`nested_conditions.t`)
- Added another test case for if statements, `simple_conditions.t`
This commit is contained in:
Tristan B. Velloza Kildaire 2022-12-19 15:37:55 +02:00
parent beb068a33c
commit 4f899c69e2
11 changed files with 593 additions and 51 deletions

View File

@ -31,11 +31,29 @@ public final class DCodeEmitter : CodeEmitter
super(typeChecker, file);
}
private ulong transformDepth = 0;
private string genTabs(ulong count)
{
string tabStr;
for(ulong i = 0; i < count; i++)
{
tabStr~="\t";
}
return tabStr;
}
public override string transform(const Instruction instruction)
{
import std.stdio;
writeln("\n");
gprintln("transform(): "~to!(string)(instruction));
transformDepth++;
// At any return decrement the depth
scope(exit)
{
transformDepth--;
}
/* VariableAssignmentInstr */
if(cast(VariableAssignmentInstr)instruction)
@ -94,10 +112,12 @@ public final class DCodeEmitter : CodeEmitter
varDecWantsConsumeVarAss = true;
// Fetch the variable assignment instruction
gprintln("Before crash: "~to!(string)(getCurrentInstruction()));
nextInstruction();
Instruction varAssInstr = getCurrentInstruction();
// gprintln("Before crash: "~to!(string)(getCurrentInstruction()));
// nextInstruction();
// Instruction varAssInstr = getCurrentInstruction();
VariableAssignmentInstr varAssInstr = varDecInstr.getAssignmentInstr();
// Generate the code to emit
return varDecInstr.varType~" "~renamedSymbol~" = "~transform(varAssInstr)~";";
}
@ -139,6 +159,8 @@ public final class DCodeEmitter : CodeEmitter
BinOpInstr binOpInstr = cast(BinOpInstr)instruction;
// TODO: I like having `lhs == rhs` for `==` or comparators but not spaces for `lhs+rhs`
return transform(binOpInstr.lhs)~to!(string)(getCharacter(binOpInstr.operator))~transform(binOpInstr.rhs);
}
/* FuncCallInstr */
@ -199,6 +221,56 @@ public final class DCodeEmitter : CodeEmitter
return "return "~transform(returnExpressionInstr)~";";
}
/**
* If statements (IfStatementInstruction)
*/
else if(cast(IfStatementInstruction)instruction)
{
IfStatementInstruction ifStatementInstruction = cast(IfStatementInstruction)instruction;
BranchInstruction[] branchInstructions = ifStatementInstruction.getBranchInstructions();
gprintln("Holla"~to!(string)(branchInstructions));
string emit;
for(ulong i = 0; i < branchInstructions.length; i++)
{
BranchInstruction curBranchInstr = branchInstructions[i];
if(curBranchInstr.hasConditionInstr())
{
Value conditionInstr = cast(Value)curBranchInstr.getConditionInstr();
string hStr = (i == 0) ? "if" : genTabs(transformDepth)~"else if";
emit~=hStr~"("~transform(conditionInstr)~")\n";
emit~=genTabs(transformDepth)~"{\n";
foreach(Instruction branchBodyInstr; curBranchInstr.getBodyInstructions())
{
emit~=genTabs(transformDepth)~"\t"~transform(branchBodyInstr)~"\n";
}
emit~=genTabs(transformDepth)~"}\n";
}
else
{
emit~=genTabs(transformDepth)~"else\n";
emit~=genTabs(transformDepth)~"{\n";
foreach(Instruction branchBodyInstr; curBranchInstr.getBodyInstructions())
{
emit~=genTabs(transformDepth)~"\t"~transform(branchBodyInstr)~"\n";
}
emit~=genTabs(transformDepth)~"}\n";
}
}
return emit;
}
return "<TODO: Base emit: "~to!(string)(instruction)~">";
}
@ -379,6 +451,8 @@ public final class DCodeEmitter : CodeEmitter
{
//TODO: Implement me
if(cmp(typeChecker.getModule().getName(), "simple_functions") == 0)
{
// NOTE: Remove this printf
file.writeln(`
// NOTE: The below is testing code and should be removed
@ -390,6 +464,16 @@ int main()
printf("k: %u\n", t_7b6d477c5859059f16bc9da72fc8cc3b);
return 0;
}`);
}
else
{
file.writeln(`
int main()
{
return 0;
}
`);
}
}

View File

@ -80,15 +80,26 @@ public final class VariableDeclaration : StorageDeclaration
/* Type of the variable being declared */
public const string varType;
/* VariableAssignmentInstr-instruction to be assigned */
private VariableAssignmentInstr varAssInstr;
//TODO: This must take in type information
this(string varName, byte len, string varType)
this(string varName, byte len, string varType, VariableAssignmentInstr varAssInstr)
{
this.varName = varName;
this.length = len;
this.varType = varType;
this.varAssInstr = varAssInstr;
addInfo = "varName: "~varName;
}
public VariableAssignmentInstr getAssignmentInstr()
{
return varAssInstr;
}
}
public final class FetchValueVar : Value
@ -288,4 +299,50 @@ public final class ReturnInstruction : Instruction
{
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 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;
}
}

View File

@ -163,6 +163,13 @@ public final class Lexer
/* Check for case of `==` (where we are on the first `=` sign) */
if(currentChar == '=' && isForward() && sourceCode[position+1] == '=')
{
/* Flush any current token (if exists) */
if(currentToken.length)
{
currentTokens ~= new Token(currentToken, line, column);
currentToken = "";
}
// Create the `==` token
currentTokens ~= new Token("==", line, column);
@ -808,6 +815,14 @@ unittest
currentLexer.performLex();
gprintln("Collected "~to!(string)(currentLexer.getTokens()));
assert(currentLexer.getTokens() == [new Token("==", 0, 0), new Token(",", 0, 0), new Token("=", 0, 0), new Token("==", 0, 0)]);
// Test flushing of previous token
import std.algorithm.comparison;
sourceCode = "i==i=\n";
currentLexer = new Lexer(sourceCode);
currentLexer.performLex();
gprintln("Collected "~to!(string)(currentLexer.getTokens()));
assert(currentLexer.getTokens() == [new Token("i", 0, 0), new Token("==", 0, 0), new Token("i", 0, 0), new Token("=", 0, 0)]);
}
/**

View File

@ -107,13 +107,20 @@ public final class Parser
* Parses if statements
*
* TODO: Check kanban
* TOOD: THis should return something
*/
private void parseIf()
private IfStatement parseIf()
{
gprintln("parseIf(): Enter", DebugType.WARNING);
IfStatement ifStmt;
Branch[] branches;
while (hasTokens())
{
{
Expression currentBranchCondition;
Statement[] currentBranchBody;
/* This will only be called once (it is what caused a call to parseIf()) */
if (getSymbolType(getCurrentToken()) == SymbolType.IF)
{
@ -125,7 +132,7 @@ public final class Parser
nextToken();
/* Parse an expression (for the condition) */
parseExpression();
currentBranchCondition = parseExpression();
expect(SymbolType.RBRACE, getCurrentToken());
/* Opening { */
@ -133,9 +140,14 @@ public final class Parser
expect(SymbolType.OCURLY, getCurrentToken());
/* Parse the if' statement's body AND expect a closing curly */
parseBody();
currentBranchBody = parseBody();
expect(SymbolType.CCURLY, getCurrentToken());
nextToken();
/* Create a branch node */
Branch branch = new Branch(currentBranchCondition, currentBranchBody);
parentToContainer(branch, currentBranchBody);
branches ~= branch;
}
/* If we get an else as the next symbol */
else if (getSymbolType(getCurrentToken()) == SymbolType.ELSE)
@ -154,7 +166,7 @@ public final class Parser
nextToken();
/* Parse an expression (for the condition) */
parseExpression();
currentBranchCondition = parseExpression();
expect(SymbolType.RBRACE, getCurrentToken());
/* Opening { */
@ -162,18 +174,28 @@ public final class Parser
expect(SymbolType.OCURLY, getCurrentToken());
/* Parse the if' statement's body AND expect a closing curly */
parseBody();
currentBranchBody = parseBody();
expect(SymbolType.CCURLY, getCurrentToken());
nextToken();
/* Create a branch node */
Branch branch = new Branch(currentBranchCondition, currentBranchBody);
parentToContainer(branch, currentBranchBody);
branches ~= branch;
}
/* Check for opening curly (just an "else" statement) */
else if (getSymbolType(getCurrentToken()) == SymbolType.OCURLY)
{
/* Parse the if' statement's body (starting with `{` AND expect a closing curly */
parseBody();
currentBranchBody = parseBody();
expect(SymbolType.CCURLY, getCurrentToken());
nextToken();
/* Create a branch node */
Branch branch = new Branch(null, currentBranchBody);
parentToContainer(branch, currentBranchBody);
branches ~= branch;
/* Exit, this is the end of the if statement as an else is reached */
break;
}
@ -191,6 +213,13 @@ public final class Parser
}
gprintln("parseIf(): Leave", DebugType.WARNING);
/* Create the if statement with the branches */
ifStmt = new IfStatement(branches);
parentToContainer(ifStmt, cast(Statement[])branches);
return ifStmt;
}
private void parseWhile()
@ -490,7 +519,7 @@ public final class Parser
/* If it is a branch */
else if (symbol == SymbolType.IF)
{
parseIf();
statements ~= parseIf();
}
/* If it is a while loop */
else if (symbol == SymbolType.WHILE)

View File

@ -497,6 +497,10 @@ public string getCharacter(SymbolType symbolIn)
{
return "}";
}
else if(symbolIn == SymbolType.EQUALS)
{
return "==";
}
else
{
gprintln("getCharacter: No back-mapping for "~to!(string)(symbolIn), DebugType.ERROR);

View File

@ -550,4 +550,119 @@ public final class ReturnStmt : Statement
{
return returnExpression;
}
}
/**
* IfStatement
*/
public final class IfStatement : Entity, Container
{
private Branch[] branches;
private static ulong ifStmtContainerRollingNameCounter = 0;
this(Branch[] branches)
{
ifStmtContainerRollingNameCounter++;
super("ifStmt_"~to!(string)(ifStmtContainerRollingNameCounter));
this.branches = branches;
weight = 2;
}
public Branch[] getBranches()
{
return branches;
}
public override void addStatement(Statement statement)
{
branches ~= cast(Branch)statement;
}
public override void addStatements(Statement[] statements)
{
branches ~= cast(Branch[])statements;
}
public override Statement[] getStatements()
{
return cast(Statement[])branches;
}
public override string toString()
{
return "IfStmt";
}
}
/**
* Branch
*
* Represents a condition and code attached to
* run on said condition
*
* NOTE: I feel as though this should be a container
* with a `generalPass` applied to it in `dependency/core.d`
*/
public final class Branch : Entity, Container
{
private Expression branchCondition;
private Statement[] branchBody;
private static ulong branchContainerRollingNameCounter = 0;
this(Expression condition, Statement[] branch)
{
branchContainerRollingNameCounter++;
super("branch_"~to!(string)(branchContainerRollingNameCounter));
this.branchCondition = condition;
this.branchBody = branch;
}
/**
* Effectively checks if this branch is an 'else' branch
*
* Returns: <code>true</code> if so, <code>false</code>
* otherwise
*/
public bool hasCondition()
{
return !(branchCondition is null);
}
public Expression getCondition()
{
return branchCondition;
}
public Statement[] getBody()
{
return branchBody;
}
public override void addStatement(Statement statement)
{
branchBody ~= statement;
}
public override void addStatements(Statement[] statements)
{
branchBody ~= statements;
}
public override Statement[] getStatements()
{
return branchBody;
}
public override string toString()
{
return "Branch";
}
}

View File

@ -13,6 +13,7 @@ import compiler.symbols.typing.core;
import compiler.typecheck.dependency.core;
import compiler.codegen.instruction;
import std.container.slist;
import std.algorithm : reverse;
/**
* The Parser only makes sure syntax
@ -272,6 +273,23 @@ public final class TypeChecker
return poppedInstr;
}
/* Pops from the tail of the code queue and returns it */
public Instruction tailPopInstr()
{
Instruction poppedInstr;
if(!codeQueue.empty)
{
// Perhaps there is a nicer way to tail popping
codeQueue.reverse();
poppedInstr = codeQueue.front();
codeQueue.removeFront();
codeQueue.reverse();
}
return poppedInstr;
}
public bool isInstrEmpty()
{
return codeQueue.empty;
@ -761,7 +779,7 @@ public final class TypeChecker
VariableAssignmentInstr varAssInstr = new VariableAssignmentInstr(variableName, valueInstr);
varAssInstr.context = variableAssignmentContext;
addInstrB(varAssInstr);
addInstr(varAssInstr);
}
/* TODO: Add support */
/**
@ -782,7 +800,21 @@ public final class TypeChecker
Variable variablePNode = cast(Variable)dnode.getEntity();
gprintln("HELLO FELLA");
string variableName = resolver.generateName(modulle, variablePNode);
VariableDeclaration varDecInstr = new VariableDeclaration(variableName, 4, variablePNode.getType());
gprintln("HELLO FELLA (name): "~variableName);
// CHeck if this variable declaration has an assignment attached
VariableAssignmentInstr assignmentInstr;
if(variablePNode.getAssignment())
{
Instruction poppedInstr = popInstr();
assignmentInstr = cast(VariableAssignmentInstr)poppedInstr;
assert(assignmentInstr);
}
VariableDeclaration varDecInstr = new VariableDeclaration(variableName, 4, variablePNode.getType(), assignmentInstr);
/* NEW CODE (9th November 2021) Set the context */
varDecInstr.context = variablePNode.context;
@ -791,7 +823,7 @@ public final class TypeChecker
addInstrB(varDecInstr);
}
/* TODO: Add class init, see #8 */
@ -835,6 +867,8 @@ public final class TypeChecker
vAInstr.context = vasa.getContext();
addInstrB(vAInstr);
gprintln("VariableAssignmentStdAlone", DebugType.ERROR);
}
/**
* Return statement (ReturnStmt)
@ -858,6 +892,92 @@ public final class TypeChecker
returnInstr.context = returnStatement.getContext();
addInstrB(returnInstr);
}
/**
* If statement (IfStatement)
*/
else if(cast(IfStatement)statement)
{
IfStatement ifStatement = cast(IfStatement)statement;
BranchInstruction[] branchInstructions;
/* Get the if statement's branches */
Branch[] branches = ifStatement.getBranches();
assert(branches.length > 0);
/**
* 1. These would be added stack wise, so we need to pop them like backwards
* 2. Then a reversal at the end (generated instructions list)
*
* FIXME: EIther used siggned or the hack below lmao, out of boounds
*/
for(ulong branchIdx = branches.length-1; true; branchIdx--)
{
Branch branch = branches[branchIdx];
// Pop off an expression instruction (if it exists)
Value branchConditionInstr;
if(branch.hasCondition())
{
Instruction instr = popInstr();
gprintln("BranchIdx: "~to!(string)(branchIdx));
gprintln("Instr is: "~to!(string)(instr));
branchConditionInstr = cast(Value)instr;
assert(branchConditionInstr);
}
// Get the number of body instructions to pop
ulong bodyCount = branch.getBody().length;
ulong i = 0;
Instruction[] bodyInstructions;
while(i < bodyCount)
{
Instruction bodyInstr = tailPopInstr();
bodyInstructions~=bodyInstr;
gprintln("tailPopp'd("~to!(string)(i)~"/"~to!(string)(bodyCount-1)~"): "~to!(string)(bodyInstr));
i++;
}
// Reverse the body instructions (correct ordering)
bodyInstructions=reverse(bodyInstructions);
// Create the branch instruction (coupling the condition instruction and body instructions)
branchInstructions~=new BranchInstruction(branchConditionInstr, bodyInstructions);
if(branchIdx == 0)
{
break;
}
}
// TODO: Reverse the list to be in the correct order (it was computed backwards)
branchInstructions=reverse(branchInstructions);
/**
* Code gen
*
* 1. Create the IfStatementInstruction containing the BranchInstruction[](s)
* 2. Set the context
* 3. Add the instruction
*/
IfStatementInstruction ifStatementInstruction = new IfStatementInstruction(branchInstructions);
ifStatementInstruction.context = ifStatement.getContext();
addInstrB(ifStatementInstruction);
gprintln("If!");
}
/* Branch */
else if(cast(Branch)statement)
{
Branch branch = cast(Branch)statement;
gprintln("Look at that y'all, cause this is it: "~to!(string)(branch));
}
/* Case of no matches */
else
{

View File

@ -299,6 +299,11 @@ public class DNode
return true;
}
public override string toString()
{
return "[DNode: "~to!(string)(entity)~"]";
}
}
@ -697,9 +702,12 @@ public class DNodeGenerator
/* What we need to do is set the variable itself me thinks */
/* NOTE: But the above seems to also be needed */
/* FIXME: Remove the context sets below */
/* NOTE: Fix is below I think (it doesn't crash then) */
/* Set context for expression and the variable itself */
varExp.setContext(context);
gprintln("Context (after): "~to!(string)(varExp.getContext().getContainer()));
Entity bruh = tc.getResolver().resolveBest(context.getContainer(), path);
bruh.setContext(context);
@ -1171,12 +1179,15 @@ public class DNodeGenerator
gprintln("generalPass(): Processing entity: "~entity.toString());
Entity ent = cast(Entity)entity;
if(ent && ent.getModifierType() != InitScope.STATIC && ignoreInitScope)
{
writeln("Did we just skip someone?");
writeln(ent);
continue;
}
// NOTE: COme back to and re-enable when this makes sense (IF it even needs to be here)
// if(ent && ent.getModifierType() != InitScope.STATIC && ignoreInitScope)
// {
// writeln("Did we just skip someone?");
// writeln("InitScope: "~to!(string)(ent.getModifierType()));
// writeln(ent);
// //TODO: Come back to this and check it!!!!! Maybe this can be removed!
// continue;
// }
/**
* Variable paremeters (for functions)
@ -1243,25 +1254,9 @@ public class DNodeGenerator
}
/* Set this variable as a dependency of this module */
// node.needs(variableDNode);
/* Set as visited */
variableDNode.markVisited();
/**
* FIXME
*
* I propose a major restructuring of variable and assignments
* along with typecheck and the way it does things. It doesn't
* make sense that varNode -> (depends on) varAss. No, varAss
* depends on varNode. Doing so would also then give us
* the correct ordering and NO swapping would be required.
*
*/
/* If there is an assignment attached to this */
if(variable.getAssignment())
{
@ -1278,21 +1273,12 @@ public class DNodeGenerator
VariableAssignmentNode varAssignNode = new VariableAssignmentNode(this, varAssign);
varAssignNode.needs(expressionNode);
/* This assignment is now dependent on the variable declaration */
varAssignNode.needs(variableDNode);
/* The current container is dependent on this running */
node.needs(varAssignNode);
continue;
}
/* If there is no assignment */
else
{
/* The current container is dependent on this variable declaration */
node.needs(variableDNode);
/* The variable declaration is dependant on the assignment */
variableDNode.needs(varAssignNode);
}
/* The current container is dependent on this variable declaration */
node.needs(variableDNode);
}
/**
* Variable asignments
@ -1365,7 +1351,56 @@ public class DNodeGenerator
/* Make this container depend on this return statement */
node.needs(returnStatementDNode);
}
/**
* If statements
*/
else if(cast(IfStatement)entity)
{
IfStatement ifStatement = cast(IfStatement)entity;
ifStatement.setContext(context);
DNode ifStatementDNode = pool(ifStatement);
/* Add each branch as a dependency */
foreach(Branch branch; ifStatement.getBranches())
{
DNode branchDNode = pool(branch);
// Set context of branch (it is parented by the IfStmt)
// NOTE: This is dead code as the above is done by Parser and
// we need not set context here, only matters at the generalPass
// call later (context being passed in) as a starting point
branch.setContext(new Context(ifStatement, context.initScope));
// Extract the potential branch condition
Expression branchCondition = branch.getCondition();
// Check if this branch has a condition
if(!(branchCondition is null))
{
// We use container of IfStmt and nt IfStmt otself as nothing can really be
// contained in it that the condition expression would be able to lookup
DNode branchConditionDNode = expressionPass(branchCondition, context);
branchDNode.needs(branchConditionDNode);
}
gprintln("branch parentOf(): "~to!(string)(branch.parentOf()));
assert(branch.parentOf());
gprintln("branch generalPass(context="~to!(string)(context.getContainer())~")");
// When generalPass()'ing a branch's body we don't want to pass in `context`
// as that is containing the branch container and hence we skip anything IN the
// branch container
// NOTE: Check initScope
Context branchContext = new Context(branch, context.initScope);
DNode branchStatementsDNode = generalPass(branch, branchContext);
branchDNode.needs(branchStatementsDNode);
/* Make the if statement depend on this branch */
ifStatementDNode.needs(branchDNode);
}
/* Make this container depend on this if statement */
node.needs(ifStatementDNode);
}
}
return node;

View File

@ -217,6 +217,7 @@ public final class Resolver
// }
/* Try find the Entity within the current Contaier */
gprintln("resolveUp("~to!(string)(currentContainer)~", "~name~")");
Entity entity = resolveWithin(currentContainer, name);
gprintln("Poes");
gprintln(entity);

View File

@ -0,0 +1,32 @@
module nested_conditionals;
void banana()
{
int i = 1;
if(i == 1)
{
int pp = 22+2;
if(i == 2+1+i+pp)
{
if(i == 3+i)
{
i=23;
}
else if(1 == 1)
{
i=50;
if(50 == 5+2)
{
i=51;
}
}
else
{
i=6969696;
}
}
}
}

View File

@ -0,0 +1,50 @@
module simple_conditions;
int other(int arg1, int arg2)
{
return 50;
}
void function(int i)
{
int apple = 69;
if(i == 1)
{
apple = 2;
i = i +3;
if(i == 40)
{
}
else if(i == 41)
{
}
else
{
}
}
else if(i == 2)
{
i = i +2;
}
else
{
}
int banana = 24;
banana=2+i;
if(banana == 2+2+other(2,2))
{
banana=2;
banana=3;
banana = other(2,3)+other(3,4);
}
int pp = other(80,81);
}