Mako/parser/tests/assignments_test.go

191 lines
5.2 KiB
Go

package parser_test
import (
"testing"
"git.sharkk.net/Sharkk/Mako/parser"
)
func TestAssignStatements(t *testing.T) {
tests := []struct {
input string
expectedIdentifier string
expectedValue any
isExpression bool
}{
{"x = 42", "x", 42.0, false},
{"name = \"test\"", "name", "test", false},
{"flag = true", "flag", true, false},
{"ptr = nil", "ptr", nil, false},
{"result = 3 + 4", "result", "(3.00 + 4.00)", true},
}
for _, tt := range tests {
t.Run(tt.input, func(t *testing.T) {
l := parser.NewLexer(tt.input)
p := parser.NewParser(l)
program := p.ParseProgram()
checkParserErrors(t, p)
if len(program.Statements) != 1 {
t.Fatalf("expected 1 statement, got %d", len(program.Statements))
}
stmt, ok := program.Statements[0].(*parser.Assignment)
if !ok {
t.Fatalf("expected Assignment, got %T", program.Statements[0])
}
// Check that Target is an Identifier
ident, ok := stmt.Target.(*parser.Identifier)
if !ok {
t.Fatalf("expected Identifier for Target, got %T", stmt.Target)
}
if ident.Value != tt.expectedIdentifier {
t.Errorf("expected identifier %s, got %s", tt.expectedIdentifier, ident.Value)
}
if tt.isExpression {
if stmt.Value.String() != tt.expectedValue.(string) {
t.Errorf("expected expression %s, got %s", tt.expectedValue.(string), stmt.Value.String())
}
} else {
switch expected := tt.expectedValue.(type) {
case float64:
testNumberLiteral(t, stmt.Value, expected)
case string:
testStringLiteral(t, stmt.Value, expected)
case bool:
testBooleanLiteral(t, stmt.Value, expected)
case nil:
testNilLiteral(t, stmt.Value)
}
}
})
}
}
func TestMemberAccessAssignment(t *testing.T) {
tests := []struct {
input string
expected string
description string
}{
{"table.key = 42", "table.key = 42.00", "dot notation assignment"},
{"arr[1] = \"hello\"", "arr[1.00] = \"hello\"", "bracket notation assignment"},
{"obj.nested.deep = true", "obj.nested.deep = true", "chained dot assignment"},
{"matrix[1][2] = 3.14", "matrix[1.00][2.00] = 3.14", "chained bracket assignment"},
{"data[\"key\"].value = nil", "data[\"key\"].value = nil", "mixed access assignment"},
}
for _, tt := range tests {
t.Run(tt.description, func(t *testing.T) {
l := parser.NewLexer(tt.input)
p := parser.NewParser(l)
program := p.ParseProgram()
checkParserErrors(t, p)
if len(program.Statements) != 1 {
t.Fatalf("expected 1 statement, got %d", len(program.Statements))
}
stmt, ok := program.Statements[0].(*parser.Assignment)
if !ok {
t.Fatalf("expected Assignment, got %T", program.Statements[0])
}
if stmt.String() != tt.expected {
t.Errorf("expected %s, got %s", tt.expected, stmt.String())
}
})
}
}
func TestMemberAccessExpressions(t *testing.T) {
tests := []struct {
input string
expected string
description string
}{
{"echo table.key", "echo table.key", "dot access"},
{"echo arr[1]", "echo arr[1.00]", "bracket access"},
{"echo obj.nested.deep", "echo obj.nested.deep", "chained dot access"},
{"echo matrix[1][2]", "echo matrix[1.00][2.00]", "chained bracket access"},
{"echo data[\"key\"].value", "echo data[\"key\"].value", "mixed access"},
{"echo table.key + arr[0]", "echo (table.key + arr[0.00])", "member access in expression"},
}
for _, tt := range tests {
t.Run(tt.description, func(t *testing.T) {
l := parser.NewLexer(tt.input)
p := parser.NewParser(l)
program := p.ParseProgram()
checkParserErrors(t, p)
if len(program.Statements) != 1 {
t.Fatalf("expected 1 statement, got %d", len(program.Statements))
}
if program.Statements[0].String() != tt.expected {
t.Errorf("expected %s, got %s", tt.expected, program.Statements[0].String())
}
})
}
}
func TestTableAssignments(t *testing.T) {
tests := []struct {
input string
identifier string
pairCount int
isArray bool
description string
}{
{"arr = {1, 2, 3}", "arr", 3, true, "array assignment"},
{"hash = {x = 1, y = 2}", "hash", 2, false, "hash assignment"},
{"empty = {}", "empty", 0, true, "empty table assignment"},
}
for _, tt := range tests {
t.Run(tt.description, func(t *testing.T) {
l := parser.NewLexer(tt.input)
p := parser.NewParser(l)
program := p.ParseProgram()
checkParserErrors(t, p)
if len(program.Statements) != 1 {
t.Fatalf("expected 1 statement, got %d", len(program.Statements))
}
stmt, ok := program.Statements[0].(*parser.Assignment)
if !ok {
t.Fatalf("expected Assignment, got %T", program.Statements[0])
}
// Check that Target is an Identifier
ident, ok := stmt.Target.(*parser.Identifier)
if !ok {
t.Fatalf("expected Identifier for Target, got %T", stmt.Target)
}
if ident.Value != tt.identifier {
t.Errorf("expected identifier %s, got %s", tt.identifier, ident.Value)
}
table, ok := stmt.Value.(*parser.TableLiteral)
if !ok {
t.Fatalf("expected TableLiteral, got %T", stmt.Value)
}
if len(table.Pairs) != tt.pairCount {
t.Errorf("expected %d pairs, got %d", tt.pairCount, len(table.Pairs))
}
if table.IsArray() != tt.isArray {
t.Errorf("expected IsArray() = %t, got %t", tt.isArray, table.IsArray())
}
})
}
}