Skip to content

Commit 0e27bce

Browse files
committed
[ coverage ] Improve test coverages
1 parent d0cf8ca commit 0e27bce

File tree

10 files changed

+108
-87
lines changed

10 files changed

+108
-87
lines changed

src/main/kotlin/org/lice/Lice.kt

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,10 @@ package org.lice
88

99
import org.lice.core.SymbolList
1010
import org.lice.parse.*
11-
import org.lice.repl.Main
1211
import org.lice.util.InterpretException
1312
import org.lice.util.ParseException
1413
import java.io.File
15-
import java.nio.file.Path
16-
import java.nio.file.Paths
14+
import java.nio.file.*
1715

1816
object Lice {
1917
@JvmOverloads
@@ -25,7 +23,7 @@ object Lice {
2523
@JvmOverloads
2624
@JvmStatic
2725
fun run(file: Path, symbolList: SymbolList = SymbolList()) =
28-
Main.interpret(file, symbolList)
26+
run(String(Files.readAllBytes(file)), symbolList)
2927

3028
@JvmOverloads
3129
@JvmStatic
@@ -39,4 +37,9 @@ object Lice {
3937
}
4038
return null
4139
}
40+
41+
@JvmOverloads
42+
@JvmStatic
43+
fun runBarely(code: String, symbolList: SymbolList = SymbolList()) =
44+
Parser.parseTokenStream(Lexer(code)).accept(Sema(symbolList)).eval()
4245
}

src/main/kotlin/org/lice/parse/ASTNode.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ class ASTAtomicNode internal constructor(metaData: MetaData, val token: Token) :
2222
Token.TokenType.DoubleNumber -> ValueNode(token.strValue.toDouble(), metaData)
2323
Token.TokenType.StringLiteral -> ValueNode(token.strValue, metaData)
2424
Token.TokenType.Identifier -> SymbolNode(sema.symbolList, token.strValue, metaData)
25-
Token.TokenType.LispKwd, Token.TokenType.EOI -> throw ParseException("")
25+
Token.TokenType.LispKwd, Token.TokenType.EOI ->
26+
throw ParseException("Unexpected token '${token.strValue}'", metaData)
2627
}
2728
}
2829

src/main/kotlin/org/lice/parse/Lexer.kt

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,15 @@ class Lexer(sourceCode: String) {
77

88
private val sourceCode = sourceCode.toCharArray()
99
private var line = 1
10-
private var col = 1
11-
private var charIndex = 0
10+
private var col: Int
11+
private var charIndex: Int
1212
private var tokenBuffer: MutableList<Token> = arrayListOf()
13-
private var currentTokenIndex = 0
13+
private var currentTokenIndex: Int = 0
1414

1515
init {
16+
this.col = 1
17+
this.charIndex = 0
18+
1619
doSplitTokens()
1720
}
1821

@@ -171,9 +174,12 @@ class Lexer(sourceCode: String) {
171174
nextChar()
172175
} else {
173176
when (peekOneChar()) {
177+
'0' -> builder.append('\u0000')
174178
'n' -> builder.append('\n')
175179
'f' -> builder.append('\u000C')
176180
't' -> builder.append('\t')
181+
'v' -> builder.append('\u000B')
182+
'r' -> builder.append('\u000D')
177183
'\\' -> builder.append('\\')
178184
'"' -> builder.append('\"')
179185
else -> throw ParseException("Illegal conversion sequence \\${peekOneChar()}",
@@ -215,7 +221,7 @@ class Lexer(sourceCode: String) {
215221
private const val binDigits = "01"
216222
private const val octDigits = "01234567"
217223
private const val decDigits = "0123456789"
218-
private const val hexDigits = "0123456789ABCDEF"
224+
private const val hexDigits = "0123456789ABCDEFabcdef"
219225
private const val blanks = " \u000C\n\t\r,"
220226
private const val lispSymbols = "()"
221227
private const val tokenDelimiters = blanks + lispSymbols + ";\u0000"

src/main/kotlin/org/lice/repl/Main.kt

Lines changed: 8 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,18 @@
1+
@file:JvmName("Main")
2+
13
package org.lice.repl
24

5+
import org.lice.Lice
36
import org.lice.core.SymbolList
47
import org.lice.lang.Echoer
5-
import org.lice.parse.*
6-
import org.lice.util.InterpretException
7-
import org.lice.util.ParseException
8-
import java.nio.file.*
8+
import java.nio.file.Paths
99

1010
/**
1111
* @author ice1000
1212
*/
1313

14-
object Main {
15-
16-
/**
17-
* interpret code in a file
18-
*/
19-
fun interpret(file: Path, symbolList: SymbolList): Any? {
20-
val code = String(Files.readAllBytes(file))
21-
try {
22-
return Parser.parseTokenStream(Lexer(code)).accept(Sema(symbolList)).eval()
23-
} catch (e: ParseException) {
24-
e.prettyPrint(code.split("\n"))
25-
} catch (e: InterpretException) {
26-
e.prettyPrint(code.split("\n"))
27-
}
28-
return null
29-
}
30-
31-
@JvmStatic
32-
fun main(vararg args: String) {
33-
Echoer.openOutput()
34-
if (args.isEmpty()) println("Please specify an input file.")
35-
else interpret(Paths.get(args.first()), SymbolList())
36-
}
14+
fun main(args: Array<String>) {
15+
Echoer.openOutput()
16+
if (args.isEmpty()) println("Please specify an input file.")
17+
else Lice.run(Paths.get(args.first()), SymbolList())
3718
}

src/main/kotlin/org/lice/util/Error.kt

Lines changed: 32 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -12,42 +12,50 @@ package org.lice.util
1212

1313
import org.lice.model.MetaData
1414

15-
private fun exceptionPrettyPrint(string: String, meta: MetaData, cachedCodeLines: List<String>) {
16-
System.err.println("Error " + string)
17-
if (meta.beginLine != -1)
18-
System.err.print("At " + meta.beginLine)
19-
if (meta.beginIndex != -1) {
20-
System.err.print(":" + meta.beginIndex)
21-
}
22-
System.err.println(": " + string)
23-
System.err.println(cachedCodeLines[meta.beginLine-1])
24-
if (meta.beginIndex != -1) {
25-
for (i: Int in meta.beginIndex.downTo(2))
26-
System.err.print(' ')
27-
System.err.print('^')
28-
if (meta.endIndex != -1) {
29-
for (i: Int in meta.endIndex.downTo(meta.beginIndex+2))
30-
System.err.print('~')
15+
open class LiceException(string: String, @JvmField protected val meta: MetaData) : RuntimeException(string) {
16+
protected fun prettify(cachedCodeLines: List<String>): String {
17+
val builder = StringBuilder()
18+
builder.appendln("Error " + message)
19+
if (meta.beginLine != -1)
20+
builder.append("At " + meta.beginLine)
21+
if (meta.beginIndex != -1) {
22+
builder.append(":" + meta.beginIndex)
23+
}
24+
builder.appendln(": " + message)
25+
if (meta.beginLine != -1) {
26+
builder.appendln(cachedCodeLines[meta.beginLine - 1])
27+
}
28+
if (meta.beginIndex != -1) {
29+
for (i in meta.beginIndex.downTo(2))
30+
builder.append(' ')
31+
builder.append('^')
32+
if (meta.endIndex != -1) {
33+
for (i in meta.endIndex.downTo(meta.beginIndex + 2))
34+
builder.append('~')
35+
}
36+
builder.appendln()
3137
}
32-
System.err.println()
38+
builder.appendln()
39+
return builder.toString()
3340
}
34-
System.err.println()
3541
}
3642

37-
class ParseException(private val string: String, private val meta: MetaData = MetaData()) : RuntimeException(string) {
43+
class ParseException(string: String, meta: MetaData = MetaData()) : LiceException(string, meta) {
3844
fun prettyPrint(cachedCodeLines: List<String>) {
39-
exceptionPrettyPrint(string, meta, cachedCodeLines)
45+
prettify(cachedCodeLines).let(System.err::println)
4046
}
4147
}
4248

43-
class InterpretException(private val string: String, private val meta: MetaData = MetaData()) : RuntimeException(string) {
49+
class InterpretException(string: String, meta: MetaData = MetaData()) :
50+
LiceException(string, meta) {
4451
fun prettyPrint(cachedCodeLines: List<String>) {
45-
exceptionPrettyPrint(string, meta, cachedCodeLines)
52+
prettify(cachedCodeLines).let(System.err::println)
4653
}
4754

4855
companion object Factory {
49-
fun undefinedVariable(name: String, meta: MetaData): Nothing
50-
= throw InterpretException("undefined variable: $name", meta)
56+
fun undefinedVariable(
57+
name: String,
58+
meta: MetaData): Nothing = throw InterpretException("undefined variable: $name", meta)
5159

5260
fun notSymbol(meta: MetaData): Nothing =
5361
throw InterpretException("type mismatch: symbol expected.", meta)

src/test/kotlin/org/lice/parse/IntegratedTest.kt

Lines changed: 39 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
package org.lice.parse
22

3-
import junit.framework.TestCase.assertEquals
43
import org.intellij.lang.annotations.Language
54
import org.junit.Test
5+
import org.lice.Lice
6+
import org.lice.core.SymbolList
7+
import org.lice.evalTo
8+
import kotlin.test.assertFails
69

710
class IntegratedTest {
811
@Test
9-
fun Test1() {
12+
fun test1() {
1013
@Language("Lice")
1114
val srcCode = """
1215
(def fibonacci n
@@ -19,15 +22,15 @@ class IntegratedTest {
1922
(while (< i 20)
2023
(|>
2124
(print (fibonacci i))
22-
(print ("
23-
"))
25+
(print ("\n"))
2426
(-> i (+ i 1))))
27+
(fibonacci 10)
2528
"""
26-
Parser.parseTokenStream(Lexer(srcCode)).accept(Sema()).eval()
29+
srcCode evalTo 55
2730
}
2831

2932
@Test
30-
fun Test2() {
33+
fun test2() {
3134
@Language("Lice")
3235
val srcCode = """
3336
(print (+ 1 1) "\n")
@@ -47,22 +50,21 @@ class IntegratedTest {
4750
4851
(str->sym "ass")
4952
50-
(print (format "ass %s can", "we") "
51-
")
53+
(print (format "ass %s can", "we") "\n")
5254
"""
5355
Parser.parseTokenStream(Lexer(srcCode)).accept(Sema()).eval()
5456
}
5557

5658
@Test
57-
fun Test3() {
59+
fun test3() {
5860
/// Intentionally empty translation unit
5961
val srcCode = """
6062
"""
61-
Parser.parseTokenStream(Lexer(srcCode)).accept(Sema()).eval()
63+
srcCode evalTo null
6264
}
6365

6466
@Test
65-
fun Test4() {
67+
fun test4() {
6668
val srcCode = """
6769
; defining functions
6870
(def check
@@ -117,13 +119,33 @@ class IntegratedTest {
117119
; calling the extern function
118120
(equals 1 1)
119121
"""
120-
Parser.parseTokenStream(Lexer(srcCode)).accept(Sema()).eval()
122+
Lice.runBarely(srcCode)
121123
}
122124

123-
@Test(timeout = 500)
124-
fun Test5() {
125-
assertEquals(233, Parser.parseTokenStream(Lexer("233")).accept(Sema()).eval())
126-
assertEquals(0x233, Parser.parseTokenStream(Lexer("0x233")).accept(Sema()).eval())
127-
assertEquals(0b10101, Parser.parseTokenStream(Lexer("0b10101")).accept(Sema()).eval())
125+
@Test
126+
fun test5() {
127+
"233" evalTo 233
128+
"0x233" evalTo 0x233
129+
"0b10101" evalTo 0b10101
130+
}
131+
132+
@Test
133+
fun failTests() {
134+
assertFails { Lice.runBarely("1a") }
135+
assertFails { Lice.runBarely("0xz") }
136+
assertFails { Lice.runBarely("0b2") }
137+
assertFails { Lice.runBarely("0o9") }
138+
assertFails { Lice.runBarely("undefined-variable") }
139+
assertFails { Lice.runBarely("(+ (->str 1))") }
140+
assertFails { Lice.runBarely("(def)") }
141+
assertFails { Lice.runBarely("(def name)") }
142+
assertFails { Lice.runBarely("(-> name)") }
143+
assertFails { Lice.runBarely("(; 1)") }
144+
assertFails { Lice.runBarely(""""\g"""") }
145+
assertFails { Lice.runBarely("(") }
146+
assertFails { Lice.runBarely(")") }
147+
assertFails { Lice.runBarely("\"") }
148+
assertFails { SymbolList().extractLiceFunction("undefined-function")(emptyList()) }
149+
assertFails { SymbolList().extractLiceVariable("undefined-variable") }
128150
}
129151
}

src/test/kotlin/org/lice/parse/LexIdentifierTest.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import org.junit.Assert.assertEquals
66

77
class LexIdentifierTest {
88

9-
@Test(timeout = 100)
9+
@Test
1010
fun testLexIdentifier() {
1111
val srcCode = "Fuck@dentifier"
1212
val l = Lexer(srcCode)
@@ -15,7 +15,7 @@ class LexIdentifierTest {
1515
assertEquals(Token.TokenType.EOI, l.peekOneToken().type)
1616
}
1717

18-
@Test(timeout = 100)
18+
@Test
1919
fun testLexIdentifiers() {
2020
val srcCode = "Fuck@dentifier _Yet1A2not->her@dentifier"
2121
val l = Lexer(srcCode)
@@ -27,7 +27,7 @@ class LexIdentifierTest {
2727
assertEquals(Token.TokenType.EOI, l.peekOneToken().type)
2828
}
2929

30-
@Test(timeout = 100)
30+
@Test
3131
fun testLexIdentifiers2() {
3232
val srcCode = "Fuck@dentifier,_Yet1A2not->her@dentifier"
3333
val l = Lexer(srcCode)

src/test/kotlin/org/lice/parse/LexProgramTest.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import org.junit.Assert.assertEquals
55
import org.junit.Test
66

77
class LexProgramTest {
8-
@Test(timeout = 100)
8+
@Test
99
fun test1() {
1010
@Language("Lice")
1111
val src = """
@@ -65,7 +65,7 @@ class LexProgramTest {
6565
l.nextToken()
6666
}
6767

68-
@Test(timeout = 100)
68+
@Test
6969
fun test2() {
7070
@Language("Lice")
7171
val src = """

src/test/kotlin/org/lice/parse/LexStringTest.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ class LexStringTest {
1313
@JvmField
1414
var thrown: ExpectedException = ExpectedException.none()
1515

16-
@Test(timeout = 100)
16+
@Test
1717
fun testLexString() {
1818
@Language("Lice")
1919
val srcCode = """"String""""
@@ -23,7 +23,7 @@ class LexStringTest {
2323
assertEquals(Token.TokenType.EOI, l.peekOneToken().type)
2424
}
2525

26-
@Test(timeout = 100)
26+
@Test
2727
fun testLexConversionSequence() {
2828
@Language("Lice")
2929
val srcCode = "\"Str\\ning\""
@@ -33,15 +33,15 @@ class LexStringTest {
3333
assertEquals(Token.TokenType.EOI, l.peekOneToken().type)
3434
}
3535

36-
@Test(timeout = 200)
36+
@Test
3737
fun testLexConversionSequenceFailed() {
3838
thrown.expect(ParseException::class.java)
3939
@Language("Lice")
4040
val srcCode = "\"\\q\""
4141
val l = Lexer(srcCode)
4242
}
4343

44-
@Test(timeout = 200)
44+
@Test
4545
fun testMissingQuote() {
4646
thrown.expect(ParseException::class.java)
4747
val srcCode = "\"String without closing quote"

src/test/kotlin/org/lice/parse/LexerSandbox.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ package org.lice.parse
33
import org.junit.Test
44

55
class LexerSandbox {
6-
@Test(timeout = 2000)
6+
@Test
77
fun run() {
88
val srcCode = """
99
"""

0 commit comments

Comments
 (0)