|
@@ -264,6 +264,76 @@ func TestGlobalLetStatements(t *testing.T) {
|
|
|
runCompilerTests(t, tests)
|
|
runCompilerTests(t, tests)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+func TestLetStatement(t *testing.T) {
|
|
|
|
|
+ tests := []compilerTestCase{
|
|
|
|
|
+ {
|
|
|
|
|
+ input: `let num = 55; fn(){num};`,
|
|
|
|
|
+ expectedConstants: []interface{}{
|
|
|
|
|
+ 55,
|
|
|
|
|
+ []code.Instructions{
|
|
|
|
|
+ code.Make(code.OpGetGlobal, 0),
|
|
|
|
|
+ code.Make(code.OpReturnValue),
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ expectedInstructions: []code.Instructions{
|
|
|
|
|
+ code.Make(code.OpConstant, 0),
|
|
|
|
|
+ code.Make(code.OpSetGlobal, 0),
|
|
|
|
|
+ code.Make(code.OpConstant, 1),
|
|
|
|
|
+ code.Make(code.OpPop),
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ input: `
|
|
|
|
|
+ fn () {
|
|
|
|
|
+ let num = 55;
|
|
|
|
|
+ num;
|
|
|
|
|
+ }
|
|
|
|
|
+ `,
|
|
|
|
|
+ expectedConstants: []interface{}{
|
|
|
|
|
+ 55,
|
|
|
|
|
+ []code.Instructions{
|
|
|
|
|
+ code.Make(code.OpConstant, 0),
|
|
|
|
|
+ code.Make(code.OpSetLocal, 0),
|
|
|
|
|
+ code.Make(code.OpGetLocal, 0),
|
|
|
|
|
+ code.Make(code.OpReturnValue),
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ expectedInstructions: []code.Instructions{
|
|
|
|
|
+ code.Make(code.OpConstant, 1),
|
|
|
|
|
+ code.Make(code.OpPop),
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ input: `
|
|
|
|
|
+ fn () {
|
|
|
|
|
+ let a = 55;
|
|
|
|
|
+ let b = 77;
|
|
|
|
|
+ a + b;
|
|
|
|
|
+ }
|
|
|
|
|
+ `,
|
|
|
|
|
+ expectedConstants: []interface{}{
|
|
|
|
|
+ 55, 77,
|
|
|
|
|
+ []code.Instructions{
|
|
|
|
|
+ code.Make(code.OpConstant, 0),
|
|
|
|
|
+ code.Make(code.OpSetLocal, 0),
|
|
|
|
|
+ code.Make(code.OpConstant, 1),
|
|
|
|
|
+ code.Make(code.OpSetLocal, 1),
|
|
|
|
|
+ code.Make(code.OpGetLocal, 0),
|
|
|
|
|
+ code.Make(code.OpGetLocal, 1),
|
|
|
|
|
+ code.Make(code.OpAdd),
|
|
|
|
|
+ code.Make(code.OpReturnValue),
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ expectedInstructions: []code.Instructions{
|
|
|
|
|
+ code.Make(code.OpConstant, 2),
|
|
|
|
|
+ code.Make(code.OpPop),
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ runCompilerTests(t, tests)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
func TestStringExpression(t *testing.T) {
|
|
func TestStringExpression(t *testing.T) {
|
|
|
tests := []compilerTestCase{
|
|
tests := []compilerTestCase{
|
|
|
{
|
|
{
|
|
@@ -474,8 +544,12 @@ func TestCompilerScopes(t *testing.T) {
|
|
|
if compiler.scopeIndex != 0 {
|
|
if compiler.scopeIndex != 0 {
|
|
|
t.Errorf("scopeIndex wrong. got=%d, want=%d", compiler.scopeIndex, 0)
|
|
t.Errorf("scopeIndex wrong. got=%d, want=%d", compiler.scopeIndex, 0)
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ globalSymbolTable := compiler.symbolTable
|
|
|
|
|
+
|
|
|
compiler.emit(code.OpMul)
|
|
compiler.emit(code.OpMul)
|
|
|
|
|
|
|
|
|
|
+ // enterScope ======================================================================================================
|
|
|
compiler.enterScope()
|
|
compiler.enterScope()
|
|
|
if compiler.scopeIndex != 1 {
|
|
if compiler.scopeIndex != 1 {
|
|
|
t.Errorf("scopeIndex wrong. got=%d, want=%d", compiler.scopeIndex, 0)
|
|
t.Errorf("scopeIndex wrong. got=%d, want=%d", compiler.scopeIndex, 0)
|
|
@@ -491,10 +565,23 @@ func TestCompilerScopes(t *testing.T) {
|
|
|
if last.Opcode != code.OpSub {
|
|
if last.Opcode != code.OpSub {
|
|
|
t.Errorf("lastInstruction.Opcde wrong. got=%d, want=%d", last.Opcode, code.OpSub)
|
|
t.Errorf("lastInstruction.Opcde wrong. got=%d, want=%d", last.Opcode, code.OpSub)
|
|
|
}
|
|
}
|
|
|
|
|
+ if compiler.symbolTable.Outer != globalSymbolTable {
|
|
|
|
|
+ t.Errorf("compiler did not enclose symboTable")
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
compiler.leaveScope()
|
|
compiler.leaveScope()
|
|
|
if compiler.scopeIndex != 0 {
|
|
if compiler.scopeIndex != 0 {
|
|
|
t.Errorf("scopeIndex wrong. got=%d, want=%d", compiler.scopeIndex, 0)
|
|
t.Errorf("scopeIndex wrong. got=%d, want=%d", compiler.scopeIndex, 0)
|
|
|
}
|
|
}
|
|
|
|
|
+ // leaveScope ======================================================================================================
|
|
|
|
|
+
|
|
|
|
|
+ if compiler.symbolTable != globalSymbolTable {
|
|
|
|
|
+ t.Errorf("compiler did not restore global symbol table")
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if compiler.symbolTable.Outer != nil {
|
|
|
|
|
+ t.Errorf("compiler modified global symbol table incorrectly")
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
compiler.emit(code.OpAdd)
|
|
compiler.emit(code.OpAdd)
|
|
|
if len(compiler.scopes[compiler.scopeIndex].instructions) != 2 {
|
|
if len(compiler.scopes[compiler.scopeIndex].instructions) != 2 {
|