248 lines
5.2 KiB
Go
248 lines
5.2 KiB
Go
package tests
|
|
|
|
import (
|
|
"testing"
|
|
|
|
assert "git.sharkk.net/Go/Assert"
|
|
"git.sharkk.net/Sharkk/Mako/compiler"
|
|
"git.sharkk.net/Sharkk/Mako/lexer"
|
|
"git.sharkk.net/Sharkk/Mako/parser"
|
|
"git.sharkk.net/Sharkk/Mako/vm"
|
|
)
|
|
|
|
// Helper function to execute Mako code
|
|
func executeMakoWithErrors(code string) (*vm.VM, []string) {
|
|
lex := lexer.New(code)
|
|
p := parser.New(lex)
|
|
program := p.ParseProgram()
|
|
errors := p.Errors()
|
|
bytecode := compiler.Compile(program)
|
|
virtualMachine := vm.New()
|
|
virtualMachine.Run(bytecode)
|
|
return virtualMachine, errors
|
|
}
|
|
|
|
func TestTypeConversions(t *testing.T) {
|
|
// Test automatic type conversions in operations
|
|
_, errors := executeMakoWithErrors(`
|
|
// String concatenation
|
|
echo "Hello " + "World"; // Should work
|
|
|
|
// Using boolean in a condition
|
|
if true then
|
|
echo "Boolean works in condition";
|
|
end
|
|
|
|
// Numeric conditions
|
|
if 1 then
|
|
echo "Numeric 1 is truthy";
|
|
end
|
|
|
|
if 0 then
|
|
echo "This should not execute";
|
|
else
|
|
echo "Numeric 0 is falsy";
|
|
end
|
|
`)
|
|
|
|
assert.Equal(t, 0, len(errors))
|
|
}
|
|
|
|
func TestEdgeCases(t *testing.T) {
|
|
// Test edge cases that might cause issues
|
|
_, errors := executeMakoWithErrors(`
|
|
// Division by zero
|
|
// echo 5 / 0; // Should not crash VM, would just return null
|
|
|
|
// Deep nesting
|
|
table = {
|
|
level1 = {
|
|
level2 = {
|
|
level3 = {
|
|
level4 = {
|
|
value = "Deep nesting"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
echo table["level1"]["level2"]["level3"]["level4"]["value"];
|
|
|
|
// Empty tables
|
|
emptyTable = {};
|
|
echo emptyTable["nonexistent"]; // Should return null
|
|
|
|
// Table with invalid access
|
|
someTable = { key = "value" };
|
|
// echo someTable[123]; // Should not crash
|
|
`)
|
|
|
|
assert.Equal(t, 0, len(errors))
|
|
}
|
|
|
|
func TestErrorHandling(t *testing.T) {
|
|
// Test error handling in the parser
|
|
_, errors := executeMakoWithErrors(`
|
|
// Invalid syntax - missing semicolon
|
|
x = 5
|
|
y = 10;
|
|
`)
|
|
|
|
// Should have at least one error
|
|
assert.True(t, len(errors) > 0)
|
|
|
|
// Test parser recovery
|
|
_, errors = executeMakoWithErrors(`
|
|
// Missing end keyword
|
|
if x < 10 then
|
|
echo "x is less than 10";
|
|
// end - missing
|
|
`)
|
|
|
|
// Should have at least one error
|
|
assert.True(t, len(errors) > 0)
|
|
}
|
|
|
|
func TestNestedScopes(t *testing.T) {
|
|
// Test nested scopes and variable shadowing
|
|
_, errors := executeMakoWithErrors(`
|
|
x = "global";
|
|
|
|
{
|
|
echo x; // Should be "global"
|
|
x = "outer";
|
|
echo x; // Should be "outer"
|
|
|
|
{
|
|
echo x; // Should be "outer"
|
|
x = "inner";
|
|
echo x; // Should be "inner"
|
|
|
|
{
|
|
echo x; // Should be "inner"
|
|
x = "innermost";
|
|
echo x; // Should be "innermost"
|
|
}
|
|
|
|
echo x; // Should be "inner" again
|
|
}
|
|
|
|
echo x; // Should be "outer" again
|
|
}
|
|
|
|
echo x; // Should be "global" again
|
|
`)
|
|
|
|
assert.Equal(t, 0, len(errors))
|
|
}
|
|
|
|
func TestComplexExpressions(t *testing.T) {
|
|
// Test complex expressions with multiple operators
|
|
_, errors := executeMakoWithErrors(`
|
|
// Arithmetic precedence
|
|
result = 5 + 10 * 2; // Should be 25, not 30
|
|
echo result;
|
|
|
|
// Parentheses override precedence
|
|
result = (5 + 10) * 2; // Should be 30
|
|
echo result;
|
|
|
|
// Combined comparison and logical operators
|
|
x = 5;
|
|
y = 10;
|
|
z = 15;
|
|
|
|
result = x < y and y < z; // Should be true
|
|
echo result;
|
|
|
|
result = x > y or y < z; // Should be true
|
|
echo result;
|
|
|
|
result = not (x > y); // Should be true
|
|
echo result;
|
|
|
|
// Complex conditional
|
|
if x < y and y < z then
|
|
echo "Condition passed";
|
|
end
|
|
`)
|
|
|
|
assert.Equal(t, 0, len(errors))
|
|
}
|
|
|
|
func TestNestedTables(t *testing.T) {
|
|
// Test nested tables and complex access patterns
|
|
_, errors := executeMakoWithErrors(`
|
|
// Define a nested table
|
|
config = {
|
|
server = {
|
|
host = "localhost",
|
|
port = 8080,
|
|
settings = {
|
|
timeout = 30,
|
|
retries = 3
|
|
}
|
|
},
|
|
database = {
|
|
host = "db.example.com",
|
|
port = 5432,
|
|
credentials = {
|
|
username = "admin",
|
|
password = "secret"
|
|
}
|
|
}
|
|
};
|
|
|
|
// Access nested values
|
|
echo config["server"]["host"];
|
|
echo config["server"]["settings"]["timeout"];
|
|
echo config["database"]["credentials"]["username"];
|
|
|
|
// Update nested values
|
|
config["server"]["settings"]["timeout"] = 60;
|
|
echo config["server"]["settings"]["timeout"];
|
|
|
|
// Add new nested values
|
|
config["logging"] = {
|
|
level = "info",
|
|
file = "app.log"
|
|
};
|
|
echo config["logging"]["level"];
|
|
`)
|
|
|
|
assert.Equal(t, 0, len(errors))
|
|
}
|
|
|
|
func TestTableAsArguments(t *testing.T) {
|
|
// Test using tables as arguments
|
|
_, errors := executeMakoWithErrors(`
|
|
// Define a table
|
|
person = {
|
|
name = "John",
|
|
age = 30
|
|
};
|
|
|
|
// Use as index
|
|
lookup = {
|
|
John = "Developer",
|
|
Jane = "Designer"
|
|
};
|
|
|
|
// Access using value from another table
|
|
role = lookup[person["name"]];
|
|
echo role; // Should print "Developer"
|
|
|
|
// Test table as complex index
|
|
matrix = {};
|
|
matrix[{x=0, y=0}] = "origin";
|
|
echo matrix[{x=0, y=0}]; // This might not work as expected yet
|
|
`)
|
|
|
|
// Check if there are errors related to complex table indexing
|
|
// The test might legitimately fail as complex indexing with tables
|
|
// depends on the implementation details of how table equality is defined
|
|
// If it works without errors, that's fine too
|
|
t.Logf("Found %d errors in table indexing test", len(errors))
|
|
}
|