|
|
|
|
@ -10,6 +10,11 @@ import kotlin.test.Test
|
|
|
|
|
|
|
|
|
|
class InterpreterTest {
|
|
|
|
|
|
|
|
|
|
@BeforeTest
|
|
|
|
|
fun setUp() {
|
|
|
|
|
Lox.resetError()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
fun `validate interpreter`() {
|
|
|
|
|
val code = """
|
|
|
|
|
@ -195,7 +200,10 @@ print c;
|
|
|
|
|
val statements = parser.parse()
|
|
|
|
|
assertEquals(7, statements.size)
|
|
|
|
|
|
|
|
|
|
Interpreter().interpret(statements)
|
|
|
|
|
val interpreter = Interpreter()
|
|
|
|
|
val resolver = Resolver(interpreter)
|
|
|
|
|
resolver.resolve(statements)
|
|
|
|
|
interpreter.interpret(statements)
|
|
|
|
|
val output = outputStreamCaptor.toString().trim()
|
|
|
|
|
assertEquals("inner a\nouter b\nglobal c\nouter a\nouter b\nglobal c\nglobal a\nglobal b\nglobal c", output)
|
|
|
|
|
} finally {
|
|
|
|
|
@ -331,7 +339,13 @@ for (var b = 1; a < 10000; b = temp + b) {
|
|
|
|
|
val statements = parser.parse()
|
|
|
|
|
assertEquals(3, statements.size)
|
|
|
|
|
|
|
|
|
|
Interpreter().interpret(statements)
|
|
|
|
|
val interpreter = Interpreter()
|
|
|
|
|
|
|
|
|
|
val resolver = Resolver(interpreter)
|
|
|
|
|
resolver.resolve(statements)
|
|
|
|
|
|
|
|
|
|
interpreter.interpret(statements)
|
|
|
|
|
|
|
|
|
|
val output = outputStreamCaptor.toString().trim()
|
|
|
|
|
assertEquals("0\n" +
|
|
|
|
|
"1\n" +
|
|
|
|
|
@ -408,7 +422,12 @@ sayHi("Dear", "Reader");
|
|
|
|
|
val statements = parser.parse()
|
|
|
|
|
assertEquals(2, statements.size)
|
|
|
|
|
|
|
|
|
|
Interpreter().interpret(statements)
|
|
|
|
|
val interpreter = Interpreter()
|
|
|
|
|
|
|
|
|
|
val resolver = Resolver(interpreter)
|
|
|
|
|
resolver.resolve(statements)
|
|
|
|
|
|
|
|
|
|
interpreter.interpret(statements)
|
|
|
|
|
val output = outputStreamCaptor.toString().trim()
|
|
|
|
|
assertEquals("Hi, Dear Reader!", output)
|
|
|
|
|
} finally {
|
|
|
|
|
@ -438,7 +457,13 @@ print fib(10);
|
|
|
|
|
val statements = parser.parse()
|
|
|
|
|
assertEquals(2, statements.size)
|
|
|
|
|
|
|
|
|
|
Interpreter().interpret(statements)
|
|
|
|
|
val interpreter = Interpreter()
|
|
|
|
|
|
|
|
|
|
val resolver = Resolver(interpreter)
|
|
|
|
|
resolver.resolve(statements)
|
|
|
|
|
|
|
|
|
|
interpreter.interpret(statements)
|
|
|
|
|
|
|
|
|
|
val output = outputStreamCaptor.toString().trim()
|
|
|
|
|
assertEquals("55", output)
|
|
|
|
|
} finally {
|
|
|
|
|
@ -470,7 +495,12 @@ print fib(10);
|
|
|
|
|
val statements = parser.parse()
|
|
|
|
|
assertEquals(2, statements.size)
|
|
|
|
|
|
|
|
|
|
Interpreter().interpret(statements)
|
|
|
|
|
val interpreter = Interpreter()
|
|
|
|
|
|
|
|
|
|
val resolver = Resolver(interpreter)
|
|
|
|
|
resolver.resolve(statements)
|
|
|
|
|
|
|
|
|
|
interpreter.interpret(statements)
|
|
|
|
|
val output = outputStreamCaptor.toString().trim()
|
|
|
|
|
assertEquals("55", output)
|
|
|
|
|
} finally {
|
|
|
|
|
@ -504,7 +534,13 @@ print fib(10);
|
|
|
|
|
val statements = parser.parse()
|
|
|
|
|
assertEquals(2, statements.size)
|
|
|
|
|
|
|
|
|
|
Interpreter().interpret(statements)
|
|
|
|
|
val interpreter = Interpreter()
|
|
|
|
|
|
|
|
|
|
val resolver = Resolver(interpreter)
|
|
|
|
|
resolver.resolve(statements)
|
|
|
|
|
|
|
|
|
|
interpreter.interpret(statements)
|
|
|
|
|
|
|
|
|
|
val output = outputStreamCaptor.toString().trim()
|
|
|
|
|
assertEquals("55", output)
|
|
|
|
|
} finally {
|
|
|
|
|
@ -542,7 +578,12 @@ counter();
|
|
|
|
|
val statements = parser.parse()
|
|
|
|
|
assertEquals(5, statements.size)
|
|
|
|
|
|
|
|
|
|
Interpreter().interpret(statements)
|
|
|
|
|
val interpreter = Interpreter()
|
|
|
|
|
|
|
|
|
|
val resolver = Resolver(interpreter)
|
|
|
|
|
resolver.resolve(statements)
|
|
|
|
|
|
|
|
|
|
interpreter.interpret(statements)
|
|
|
|
|
val output = outputStreamCaptor.toString().trim()
|
|
|
|
|
assertEquals("1\n2\n3", output)
|
|
|
|
|
} finally {
|
|
|
|
|
@ -580,11 +621,152 @@ counter();
|
|
|
|
|
val statements = parser.parse()
|
|
|
|
|
assertEquals(5, statements.size)
|
|
|
|
|
|
|
|
|
|
Interpreter().interpret(statements)
|
|
|
|
|
val interpreter = Interpreter()
|
|
|
|
|
|
|
|
|
|
val resolver = Resolver(interpreter)
|
|
|
|
|
resolver.resolve(statements)
|
|
|
|
|
|
|
|
|
|
interpreter.interpret(statements)
|
|
|
|
|
val output = outputStreamCaptor.toString().trim()
|
|
|
|
|
assertEquals("1\n1\n1", output)
|
|
|
|
|
} finally {
|
|
|
|
|
System.setOut(standardOut)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
fun `Initiate a variable with the same name as a function should not work`() {
|
|
|
|
|
val code = """
|
|
|
|
|
fun a() {
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var a = a();
|
|
|
|
|
|
|
|
|
|
print a;
|
|
|
|
|
"""
|
|
|
|
|
val scanner = Scanner(code)
|
|
|
|
|
val tokens = scanner.scanTokens()
|
|
|
|
|
val parser = Parser(tokens)
|
|
|
|
|
val statements = parser.parse()
|
|
|
|
|
assertEquals(3, statements.size)
|
|
|
|
|
|
|
|
|
|
val interpreter = Interpreter()
|
|
|
|
|
val resolver = Resolver(interpreter)
|
|
|
|
|
resolver.resolve(statements)
|
|
|
|
|
assert(Lox.hadError())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
fun `Initiate a variable with the same name from an outer scope variable should not work`() {
|
|
|
|
|
val code = """
|
|
|
|
|
var a = 1;
|
|
|
|
|
{
|
|
|
|
|
var a = a;
|
|
|
|
|
print a;
|
|
|
|
|
}
|
|
|
|
|
"""
|
|
|
|
|
assert(!Lox.hadError())
|
|
|
|
|
val scanner = Scanner(code)
|
|
|
|
|
val tokens = scanner.scanTokens()
|
|
|
|
|
val parser = Parser(tokens)
|
|
|
|
|
val statements = parser.parse()
|
|
|
|
|
assertEquals(2, statements.size)
|
|
|
|
|
|
|
|
|
|
val interpreter = Interpreter()
|
|
|
|
|
val resolver = Resolver(interpreter)
|
|
|
|
|
resolver.resolve(statements)
|
|
|
|
|
assert(Lox.hadError())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
fun `Initiate a variable with the same name from an outer scope function should not work`() {
|
|
|
|
|
val code = """
|
|
|
|
|
fun a() {
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
var a = a;
|
|
|
|
|
print a;
|
|
|
|
|
}
|
|
|
|
|
"""
|
|
|
|
|
val scanner = Scanner(code)
|
|
|
|
|
val tokens = scanner.scanTokens()
|
|
|
|
|
val parser = Parser(tokens)
|
|
|
|
|
val statements = parser.parse()
|
|
|
|
|
assertEquals(2, statements.size)
|
|
|
|
|
|
|
|
|
|
val interpreter = Interpreter()
|
|
|
|
|
val resolver = Resolver(interpreter)
|
|
|
|
|
resolver.resolve(statements)
|
|
|
|
|
assert(Lox.hadError())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
fun `Initiate a variable with the same name from an outer scope function should not work with shadowing`() {
|
|
|
|
|
val code = """
|
|
|
|
|
fun a() {
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
fun a() {
|
|
|
|
|
return 2;
|
|
|
|
|
}
|
|
|
|
|
var a = a;
|
|
|
|
|
print a;
|
|
|
|
|
}
|
|
|
|
|
"""
|
|
|
|
|
val scanner = Scanner(code)
|
|
|
|
|
val tokens = scanner.scanTokens()
|
|
|
|
|
val parser = Parser(tokens)
|
|
|
|
|
val statements = parser.parse()
|
|
|
|
|
assertEquals(2, statements.size)
|
|
|
|
|
|
|
|
|
|
val interpreter = Interpreter()
|
|
|
|
|
val resolver = Resolver(interpreter)
|
|
|
|
|
resolver.resolve(statements)
|
|
|
|
|
assert(Lox.hadError())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
fun `Closures should work with shadowing and outer scope variables with the same name`() {
|
|
|
|
|
val standardOut = System.out
|
|
|
|
|
val outputStreamCaptor = ByteArrayOutputStream()
|
|
|
|
|
|
|
|
|
|
System.setOut(PrintStream(outputStreamCaptor))
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
val code = """
|
|
|
|
|
var a = "global";
|
|
|
|
|
{
|
|
|
|
|
fun showA() {
|
|
|
|
|
print a;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
showA();
|
|
|
|
|
var a = "block";
|
|
|
|
|
showA();
|
|
|
|
|
}
|
|
|
|
|
"""
|
|
|
|
|
val scanner = Scanner(code)
|
|
|
|
|
val tokens = scanner.scanTokens()
|
|
|
|
|
val parser = Parser(tokens)
|
|
|
|
|
val statements = parser.parse()
|
|
|
|
|
assertEquals(2, statements.size)
|
|
|
|
|
|
|
|
|
|
val interpreter = Interpreter()
|
|
|
|
|
|
|
|
|
|
val resolver = Resolver(interpreter)
|
|
|
|
|
resolver.resolve(statements)
|
|
|
|
|
|
|
|
|
|
interpreter.interpret(statements)
|
|
|
|
|
val output = outputStreamCaptor.toString().trim()
|
|
|
|
|
assertEquals("global\nglobal", output)
|
|
|
|
|
} finally {
|
|
|
|
|
System.setOut(standardOut)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|