Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Else if #13

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/main/antlr/SimpleLanguage.g4
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ statement
| expression NEWLINE # expressionStmt
| functionDefinition NEWLINE # functionDefinitionStmt
| classDefinition NEWLINE # classDefinitionStmt
| IF LPAREN expression RPAREN thenBlock=block (ELSE elseBlock=block)? NEWLINE # ifStmt
| IF LPAREN ifExpression=expression RPAREN ifThenBlock=block (ELSE IF LPAREN elseIfExpression=expression RPAREN elseIfThenBlock=block)* (ELSE elseBlock=block)? NEWLINE # ifStmt
| WHILE LPAREN expression RPAREN body=block NEWLINE # whileStmt
| RETURN expression NEWLINE # returnStatement
| NEWLINE # newlineStmt
Expand Down
8 changes: 5 additions & 3 deletions src/main/kotlin/ast/AstNodes.kt
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,13 @@ data class FunctionDeclarationStatement(
}

data class IfStatement(
val condition: Expression,
val thenBlock: Block,
val ifCondition: Expression,
val elseIfConditions: List<Expression>?,
val ifThenBlock: Block,
val elseIfThenBlocks: List<Block>?,
val elseBlock: Block?
) : Statement {
override val children = listOfNotNull(condition, thenBlock, elseBlock)
override val children = listOfNotNull(ifCondition, ifThenBlock, elseBlock) + elseIfConditions.orEmpty() + elseIfThenBlocks.orEmpty()

override fun <T> acceptVisitor(visitor: AstVisitor<T>): T = visitor.visitIfStatement(this)
}
Expand Down
40 changes: 38 additions & 2 deletions src/main/kotlin/codegen/dsl/ControlFlow.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ package codegen.dsl
import codegen.ChunkBuilder
import codegen.Code

fun ChunkBuilder.ifStatement(condition: Code, thenCode: Code, elseCode: Code = {}) {
fun ChunkBuilder.ifStatement(ifCondition: Code, thenCode: Code, elseCode: Code = {}) {
val afterThen = looseLabel("after then")
val afterIf = looseLabel("after if")

// IF
+condition // CONDITION
+ifCondition // CONDITION
jumpForwardIfFalse(afterThen)
// THEN
pop() // pop CONDITION
Expand All @@ -23,6 +23,42 @@ fun ChunkBuilder.ifStatement(condition: Code, thenCode: Code, elseCode: Code = {
putLabel(afterIf)
}

fun ChunkBuilder.ifStatement(ifConditions: List<Code>, thenCodes: List<Code>, elseCode: Code = {}) {
val afterAllThen = looseLabel("after then")
val afterAllIf = looseLabel("after all if")
val afterIf = mutableListOf<ChunkBuilder.Label>()

for ((index, condition) in ifConditions.withIndex()) {
afterIf.add(looseLabel("after $index if"))
}

var currentAfterCondition: ChunkBuilder.Label? = null

for ((index, condition) in ifConditions.withIndex()) {
currentAfterCondition = looseLabel("after $index")
+condition
jumpForwardIfFalse(afterIf[index])
pop()
+thenCodes[index]
jumpTo(afterAllIf)
putLabel(afterIf[index])
}

// +ifCondition
// jumpForwardIfFalse(afterAllThen)
//
// pop()
// +thenCode
//
// jumpTo(afterIf)

putLabel(afterAllThen)
pop()
+elseCode

putLabel(afterAllIf)
}

fun ChunkBuilder.whileLoop(condition: Code, body: Code) {
val beforeLoop = looseLabel("before loop")
val afterBody = looseLabel("after body")
Expand Down
25 changes: 22 additions & 3 deletions src/main/kotlin/compiler/Compiler.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import codegen.instructions.SetFieldInstruction
import resolve.*
import stdlib.BuiltInFunction
import stdlib.addBuiltInFunction
import java.util.concurrent.locks.Condition

fun compile(
builtInFunctions: List<BuiltInFunction>,
Expand Down Expand Up @@ -116,10 +117,28 @@ private class CompilerVisitor(builtInFunctions: List<BuiltInFunction>, private v
}

override fun visitIfStatement(ifStatement: IfStatement): Code = {
val condition = visit(ifStatement.condition)
val thenCode = visit(ifStatement.thenBlock)
val ifCondition = visit(ifStatement.ifCondition)
val elseIfConditions = ifStatement.elseIfConditions?.map { visit(it) }
val ifThenCode = visit(ifStatement.ifThenBlock)
val elseIfThenCodes = ifStatement.elseIfThenBlocks?.map { visit(it) }
val elseCode = ifStatement.elseBlock?.let { visit(it) } ?: {}
ifStatement(condition, thenCode, elseCode)

val conditions: MutableList<Code>
if (elseIfConditions != null) {
conditions = elseIfConditions.toMutableList()
conditions.add(0, ifCondition)
} else {
conditions = mutableListOf(ifCondition)
}

val thenCodes: MutableList<Code>
if (elseIfThenCodes != null) {
thenCodes = elseIfThenCodes.toMutableList()
thenCodes.add(0, ifThenCode)
} else {
thenCodes = mutableListOf(ifThenCode)
}
ifStatement(conditions, thenCodes, elseCode)
}

override fun visitWhileStatement(whileStatement: WhileStatement): Code = {
Expand Down
16 changes: 13 additions & 3 deletions src/main/kotlin/parsing/AstBuilder.kt
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,20 @@ class AstBuilder : SimpleLanguageBaseVisitor<AstNode?>() {
}

override fun visitIfStmt(ctx: SimpleLanguageParser.IfStmtContext?): IfStatement {
val condition = visit(ctx!!.expression()) as Expression
val thenBlock = visitBlock(ctx.thenBlock)
// val condition = visit(ctx!!.expression()) as Expression
// val thenBlock = visitBlock(ctx.thenBlock)
// val elseBlock = ctx.elseBlock?.let { visitBlock(it) }
// return IfStatement(condition, thenBlock, elseBlock)

val ifCondition = visit(ctx!!.ifExpression) as Expression
val elseIfConditionContexts = ctx.expression().drop(1)
val elseIfConditions = elseIfConditionContexts.map { visit(it) as Expression }
val ifThenBlock = visitBlock(ctx.ifThenBlock)
val elseIfThenBlockContexts = ctx.block().drop(1)
val elseIfThenBlocks = elseIfThenBlockContexts.map { visitBlock(it) }
val elseBlock = ctx.elseBlock?.let { visitBlock(it) }
return IfStatement(condition, thenBlock, elseBlock)

return IfStatement(ifCondition, elseIfConditions, ifThenBlock, elseIfThenBlocks, elseBlock)
}

override fun visitWhileStmt(ctx: SimpleLanguageParser.WhileStmtContext?): AstNode {
Expand Down
2 changes: 1 addition & 1 deletion src/main/kotlin/stdlib/BuiltInFunctions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ object FactFunction : BuiltInFunction {
override val arity: Int = 1
override val code: Code = {
ifStatement(
condition = {
ifCondition = {
equal({ getLocalVariable(1) }, { literal(1) })
},
thenCode = {
Expand Down