Skip to content

Commit

Permalink
Fix nate's triangle
Browse files Browse the repository at this point in the history
  • Loading branch information
camdenorrb committed Jan 3, 2022
1 parent 08de336 commit ea04b8e
Show file tree
Hide file tree
Showing 11 changed files with 227 additions and 14 deletions.
2 changes: 2 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ repositories {
dependencies {
implementation(platform(kotlin("bom")))
implementation(kotlin("stdlib-jdk8"))
implementation(kotlin("reflect"))

implementation("org.capnproto:runtime:0.1.11")
implementation("com.guardsquare:proguard-core:8.0.3")
//implementation("tech.poder.ir:PoderTechIR:+")
Expand Down
67 changes: 65 additions & 2 deletions src/main/kotlin/dev/twelveoclock/lang/crescent/Main.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import dev.twelveoclock.lang.crescent.compiler.CrescentIRCompiler
import dev.twelveoclock.lang.crescent.lexers.CrescentLexer
import dev.twelveoclock.lang.crescent.parsers.CrescentParser
import dev.twelveoclock.lang.crescent.vm.CrescentIRVM
import dev.twelveoclock.lang.crescent.vm.CrescentVM
import kotlin.io.path.Path


Expand All @@ -12,11 +13,73 @@ object Main {
// TODO: Replace all checkEquals in project with check and a custom message
@JvmStatic
fun main(args: Array<String>) {
testCode()
testCodeVM2()
}


private fun testCode() {

private fun testCodeVM() {

val code =
"""
fun main {
var i = 0
while (i < 2) {
println("${'$'}meow")
i += 1
}
}
""".trimIndent()

println("Here")
val tokens = CrescentLexer.invoke(code)
println(tokens)
val file = CrescentParser.invoke(Path(""), tokens)
println(file.mainFunction?.innerCode)
CrescentVM(listOf(file), file).invoke()
}

private fun testCodeVM2() {

val code =
"""
fun triangle(n: Any, k: Any){
if (n < 0){
return
}
triangle(n-1, k+1);
var x;
var y;
while (x < k){
print(" ")
x = x + 1
}
while (y < n){
print("* ")
y = y+1
}
println()
}
fun main(){
triangle(5, 0)
}
""".trimIndent()

println("Here")
val tokens = CrescentLexer.invoke(code)
println(tokens)
val file = CrescentParser.invoke(Path(""), tokens)
println(file.mainFunction?.innerCode)
CrescentVM(listOf(file), file).invoke()
}

private fun testCodeIR() {

val code =
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ class CrescentAST {
) : Variable {

override fun toString(): String {
return "$visibility ${if (isFinal) "val" else "var"} $name: ${type::class.simpleName} = $value"
return "$visibility ${if (isFinal) "val" else "var"} $name: $type = $value"
}

}
Expand Down Expand Up @@ -274,7 +274,7 @@ class CrescentAST {
value class Basic(val name: String) : Type {

override fun toString(): String {
return name
return "Basic($name)"
}

}
Expand All @@ -283,7 +283,7 @@ class CrescentAST {
value class Array(val type: Type) : Type {

override fun toString(): String {
return "[${type}]"
return "Array[${type}]"
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,12 @@ interface CrescentToken {
@JvmInline
value class Number(
val number: kotlin.Number
) : Data
) : Data {

override fun toString(): kotlin.String {
return "Number(${number} ${number::class.simpleName})"
}
}

// TODO: Take in expressions
@JvmInline
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,12 @@ object CrescentLexer {
val peek = charIterator.peekNext()

// If is negative number
/*
if (!charIterator.peekBack(2).isDigit() && next == '-' && (peek.isDigit() || (peek == '.' && charIterator.peekNext(2).isDigit()))) {
isANumber = true
"-${readNumber(charIterator)}"
}
else if (peek == '=' || next == '-' && peek == '>') {
else*/if (peek == '=' || next == '-' && peek == '>') {
"$next${charIterator.next()}"
}
else {
Expand Down Expand Up @@ -105,6 +106,9 @@ object CrescentLexer {

tokens += when (key) {

// Semicolons
";" -> continue

// Parenthesis
"(" -> CrescentToken.Parenthesis.OPEN
")" -> CrescentToken.Parenthesis.CLOSE
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1084,6 +1084,7 @@ object CrescentParser {
}

else -> {

if (nodes.isNotEmpty()) {
if (peekNext is CrescentToken.Operator) {
if (peekNext == CrescentToken.Operator.RETURN) {
Expand Down
10 changes: 4 additions & 6 deletions src/main/kotlin/dev/twelveoclock/lang/crescent/vm/CrescentVM.kt
Original file line number Diff line number Diff line change
Expand Up @@ -168,10 +168,10 @@ class CrescentVM(val files: List<Node.File>, val mainFile: Node.File) {

context.variables[node.name] =
if (node.isFinal) {
BlockContext.Variable.Val(node.name, Instance(findType(value), value))
BlockContext.Variable.Val(node.name, Instance(node.type, value))
}
else {
BlockContext.Variable.Var(node.name, Instance(findType(value), value))
BlockContext.Variable.Var(node.name, Instance(node.type, value))
}
}

Expand Down Expand Up @@ -251,10 +251,8 @@ class CrescentVM(val files: List<Node.File>, val mainFile: Node.File) {
CrescentToken.Operator.ASSIGN -> {

val value = runNode(stack.pop(), context)
val pop2 = stack.pop()


when (pop2) {
when (val pop2 = stack.pop()) {

is Node.GetCall -> {
checkEquals(1, pop2.arguments.size)
Expand All @@ -271,7 +269,7 @@ class CrescentVM(val files: List<Node.File>, val mainFile: Node.File) {
val valueType = findType(value)

check(variable.instance.type == valueType) {
"Variable ${variable.name} cannot be assigned to a value of type $valueType"
"Variable ${variable.name}: ${variable.instance.type} cannot be assigned to a value of type $valueType"
}

check(variable is BlockContext.Variable.Var) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -385,4 +385,47 @@ internal class CrescentLexerTests {
)
}


@Test
fun nateTriangle() {

val tokens = CrescentLexer.invoke(TestCode.nateTriangle)

println(tokens)

assertContentEquals(
listOf(
FUN, Key("triangle"), Parenthesis.OPEN, Key("n"), TYPE_PREFIX, Key("Any"), COMMA, Key("k"), TYPE_PREFIX, Key("Any"), Parenthesis.CLOSE, Bracket.OPEN,

IF, Parenthesis.OPEN, Key("n"), GREATER_EQUALS_COMPARE, Data.Number(0.toByte()), Parenthesis.CLOSE, Bracket.OPEN,

Key("triangle"), Parenthesis.OPEN, Key("n"), SUB, Data.Number((1).toByte()), COMMA, Key("k"), ADD, Data.Number(1.toByte()), Parenthesis.CLOSE,

VAR, Key("x"), TYPE_PREFIX, Key("I32"), ASSIGN, Data.Number(0.toByte()),
VAR, Key("y"), TYPE_PREFIX, Key("I32"), ASSIGN, Data.Number(0.toByte()),

WHILE, Parenthesis.OPEN, Key("x"), LESSER_COMPARE, Key("k"), Parenthesis.CLOSE, Bracket.OPEN,
Key("print"), Parenthesis.OPEN, Data.String(" "), Parenthesis.CLOSE,
Key("x"), ASSIGN, Key("x"), ADD, Data.Number(1.toByte()),
Bracket.CLOSE,

WHILE, Parenthesis.OPEN, Key("y"), LESSER_COMPARE, Key("n"), Parenthesis.CLOSE, Bracket.OPEN,
Key("print"), Parenthesis.OPEN, Data.String("* "), Parenthesis.CLOSE,
Key("y"), ASSIGN, Key("y"), ADD, Data.Number(1.toByte()),
Bracket.CLOSE,

Key("println"), Parenthesis.OPEN, Parenthesis.CLOSE,

Bracket.CLOSE,

Bracket.CLOSE,

FUN, Key("main"), Parenthesis.OPEN, Parenthesis.CLOSE, Bracket.OPEN,
Key("triangle"), Parenthesis.OPEN, Data.Number(5.toByte()), COMMA, Data.Number(0.toByte()), Parenthesis.CLOSE,
Bracket.CLOSE
),
tokens
)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -579,4 +579,50 @@ internal class CrescentParserTests {
)
}

@Test
fun nateTriangle() {

val tokens = CrescentLexer.invoke(TestCode.nateTriangle)
val crescentFile = CrescentParser.invoke(Path.of("example.crescent"), tokens)

assertContentEquals(
listOf(
Statement.If(
predicate = Expression(listOf(Identifier("n"), I8(0), GREATER_EQUALS_COMPARE)),
block = Statement.Block(listOf(

IdentifierCall("triangle", listOf(
Expression(listOf(Identifier("n"), I8(1), SUB)),
Expression(listOf(Identifier("k"), I8(1), ADD)),
)),

Variable.Basic("x", false, Visibility.PUBLIC, Type.Basic("I32"), I8(0)),
Variable.Basic("y", false, Visibility.PUBLIC, Type.Basic("I32"), I8(0)),

Statement.While(
predicate = Expression(listOf(Identifier("x"), Identifier("k"), LESSER_COMPARE)),
block = Statement.Block(listOf(
IdentifierCall("print", listOf(String(" "))),
Expression(listOf(Identifier("x"), Identifier("x"), I8(1), ADD, ASSIGN))
))
),

Statement.While(
predicate = Expression(listOf(Identifier("y"), Identifier("n"), LESSER_COMPARE)),
block = Statement.Block(listOf(
IdentifierCall("print", listOf(String("* "))),
Expression(listOf(Identifier("y"), Identifier("y"), I8(1), ADD, ASSIGN))
))
),

IdentifierCall("println", emptyList())
)),
elseBlock = null
)
),
crescentFile.functions["triangle"]!!.innerCode.nodes
)

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,6 @@ internal class CrescentVMTests {

val file = CrescentParser.invoke(Path("example.crescent"), CrescentLexer.invoke(TestCode.stringInterpolation))

println(file.mainFunction?.innerCode)
assertEquals(
"""
000
Expand All @@ -176,4 +175,25 @@ internal class CrescentVMTests {
}


@Test
fun nateTriangle() {

val file = CrescentParser.invoke(Path("example.crescent"), CrescentLexer.invoke(TestCode.nateTriangle))

assertEquals(
"""
*
* *
* * *
* * * *
* * * * *
""".trimIndent(),
collectSystemOut(true) {
CrescentVM(listOf(file), file).invoke()
}
)
}

}
31 changes: 31 additions & 0 deletions src/test/kotlin/dev/twelveoclock/lang/crescent/data/TestCode.kt
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,37 @@ internal object TestCode {
import ::Thing2 as Thing3
"""

const val nateTriangle =
"""
fun triangle(n: Any, k: Any){
if (n >= 0){
triangle(n-1, k+1);
var x: I32 = 0;
var y: I32 = 0;
while (x < k){
print(" ")
x = x + 1
}
while (y < n){
print("* ")
y = y + 1
}
println()
}
}
fun main() {
triangle(5, 0)
}
"""

const val katCircle =
"""
"""


// This breaks Crescent due to the parenthesis in the while
/*
Expand Down

0 comments on commit ea04b8e

Please sign in to comment.