4 Commits

Author SHA1 Message Date
7443722dd5 Unit tests 2026-03-18 15:21:58 +11:00
3f678e0cd7 Fix code skipping when using use 2026-03-17 19:45:16 +11:00
76f342adf8 Fix buffer sizes 2026-03-17 18:45:16 +11:00
832c6c7bf9 Fix use segfault 2026-03-17 18:35:37 +11:00
11 changed files with 131 additions and 63 deletions

View File

@@ -15,6 +15,8 @@ int currentInstruction = 0;
bool isMainScopeGlobal = true;
char* getFileContents(const char* filename);
[[noreturn]] void customError(GroundArg type, GroundArg what, GroundInstruction* where, int whereLine, int exitCode) {
printf("Ground runtime error:\n ErrorType: ");
printGroundArg(&type);
@@ -1181,11 +1183,11 @@ GroundValue interpretGroundInstruction(GroundInstruction inst, GroundScope* scop
char buf[256];
switch (value->type) {
case INT: {
snprintf(buf, sizeof(buf) * 256, "%" PRId64, value->data.intVal);
snprintf(buf, sizeof(buf), "%" PRId64, value->data.intVal);
break;
}
case DOUBLE: {
snprintf(buf, sizeof(buf) * 256, "%f", value->data.doubleVal);
snprintf(buf, sizeof(buf), "%f", value->data.doubleVal);
break;
}
case STRING: {
@@ -1886,17 +1888,17 @@ GroundValue interpretGroundInstruction(GroundInstruction inst, GroundScope* scop
char* envPath = getenv("GROUND_LIBS");
if (envPath) {
snprintf(path, sizeof(path), "%s/%s", envPath, libName);
snprintf(path, sizeof(path), "%s/%s.grnd", envPath, libName);
if (access(path, F_OK) == 0) found = 1;
}
if (!found) {
snprintf(path, sizeof(path), "/usr/lib/ground/%s", libName);
snprintf(path, sizeof(path), "/usr/lib/ground/%s.grnd", libName);
if (access(path, F_OK) == 0) found = 1;
}
if (!found) {
snprintf(path, sizeof(path), "%s", libName);
snprintf(path, sizeof(path), "%s.grnd", libName);
if (access(path, F_OK) == 0) found = 1;
}
@@ -1905,29 +1907,26 @@ GroundValue interpretGroundInstruction(GroundInstruction inst, GroundScope* scop
snprintf(errorMsg, sizeof(errorMsg), "Could not find library: %s", libName);
runtimeError(FIXME, errorMsg, in, currentInstruction);
}
char* fileContents = getFileContents(path);
GroundProgram program = parseFile(fileContents);
free(fileContents);
GroundScope newScope = {
.variables = scope->variables,
.labels = malloc(sizeof(GroundLabel*)),
.isMainScope = false
};
*newScope.labels = NULL;
int ci = currentInstruction;
FILE* f = fopen(path, "r");
if (!f) {
runtimeError(FIXME, "Failed to open file", in, currentInstruction);
}
fseek(f, 0, SEEK_END);
long fsize = ftell(f);
fseek(f, 0, SEEK_SET);
char* content = malloc(fsize + 1);
if (!content) {
fclose(f);
runtimeError(FIXME, "Failed to allocate memory for file content", in, currentInstruction);
}
fread(content, 1, fsize, f);
fclose(f);
content[fsize] = 0;
GroundProgram program = parseFile(content);
free(content);
interpretGroundProgram(&program, scope);
freeGroundProgram(&program);
interpretGroundProgram(&program, &newScope);
currentInstruction = ci;
break;
}

View File

@@ -1,27 +1,15 @@
set &x 5
PAUSE
fun !dingle -function -int &a
PAUSE
fun !capture -int -int &b
PAUSE
add $a $b &tmp
add $tmp $x &tmp
return $tmp
endfun
return $capture
endfun
set &x 10
call !dingle 3 &result
PAUSE
call !result 5 &y
println $y
println $y $x

View File

@@ -1,4 +1,4 @@
set &x "dingus"
PAUSE
println $x
drop &x
PAUSE
println $x

4
tests/lib.grnd Normal file
View File

@@ -0,0 +1,4 @@
fun !lib_PrintHello -int
println "Hello"
return 0
endfun

View File

@@ -1,5 +1,6 @@
# A cool list
setlist &favWords "hello" "there" "general" "kenobi"
setlist &favWords "hello" "there" "general"
listappend &favWords "kenobi"
println $favWords
set &count 0

5
tests/log.txt Normal file
View File

@@ -0,0 +1,5 @@
[hello, there, general, hello]
hello
there
general
 ,WV

View File

@@ -1,11 +0,0 @@
fun !dingle -int
endfun
set &x 5
set &y "dingle"
PAUSE
println "continuing"
println "step through here"
println "step again"
println "and again"

View File

@@ -18,7 +18,7 @@ fun !fib -int -int &n -function &fib
endfun
# Main program
println "Computing fib(30) recursively..."
call !fib 30 $fib &answer
println "Computing fib(20) recursively..."
call !fib 20 $fib &answer
println "Result:" $answer
end

View File

@@ -2,10 +2,10 @@ input &str
getstrsize $str &size
set &idx 0
@loop
getstrcharat $str $idx &char
println $char
add 1 $idx &idx
equal $idx $size &cond
if $cond %loopend
jump %loop
getstrcharat $str $idx &char
println $char
add 1 $idx &idx
equal $idx $size &cond
if $cond %loopend
jump %loop
@loopend

80
tests/unit.sh Executable file
View File

@@ -0,0 +1,80 @@
#!/usr/bin/env bash
echo "" > log.txt
for f in *.grnd; do
[ -e "$f" ] || continue # skip if no files match
# Files to skip over
if [[ "$f" == "lib.grnd" ]] ||
[[ "$f" == "string.grnd" ]] ||
[[ "$f" == "test.grnd" ]] ||
[[ "$f" == "to1000.grnd" ]] ||
[[ "$f" == "uhoh.grnd" ]];
then continue
fi
echo "Running $f"
ground "$f" > log.txt
FILE="log.txt"
FAILED="\033[31mFailed:\n\033[0m"
if [[ "$f" == "closure.grnd" ]]; then
if !(cmp -s "$FILE" <(printf "13 10\n"));
then printf $FAILED
exit 1
fi
elif [[ "$f" == "convs.grnd" ]]; then
if !(cmp -s "$FILE" <(printf "32\n12\n3.140000\na\n97\n"));
then printf $FAILED
exit 1
fi
elif [[ "$f" == "drop.grnd" ]]; then
if !(cmp -s "$FILE" <(printf "dingus\nGround runtime error:\n ErrorType: UnknownVariable\n ErrorInstruction: println \$x\n ErrorLine: 4\n"));
then printf "\033[31mFailed\n\033[0m"
exit 1
fi
elif [[ "$f" == "error.grnd" ]]; then
if !(cmp -s "$FILE" <(printf "Ground runtime error:\n ErrorType: Hello\n ErrorContext: [1, 2, 3, Hi!]\n ErrorInstruction: error \"Hello\" [1, 2, 3, Hi!] 1\n ErrorLine: 2\n"));
then printf $FAILED
exit 1
fi
elif [[ "$f" == "fib.grnd" ]]; then
if !(cmp -s "$FILE" <(printf "Fibonacci result: 7540113804746346429\n"));
then printf $FAILED
exit 1
fi
elif [[ "$f" == "function.grnd" ]]; then
if !(cmp -s "$FILE" <(printf "dingle\n1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n"));
then printf $FAILED
exit 1
fi
elif [[ "$f" == "list.grnd" ]]; then
if !(cmp -s "$FILE" <(printf "[hello, there, general, kenobi]\nhello\nthere\ngeneral\nkenobi\n"));
then printf $FAILED
exit 1
fi
elif [[ "$f" == "recursivefib.grnd" ]]; then
if !(cmp -s "$FILE" <(printf "Computing fib(20) recursively...\nResult: 6765\n"));
then printf $FAILED
exit 1
fi
elif [[ "$f" == "simple.grnd" ]]; then
if !(cmp -s "$FILE" <(printf "dingus\ndinglefart\n5.840000\n464773025\n5164.120000\n"));
then printf $FAILED
exit 1
fi
elif [[ "$f" == "struct.grnd" ]]; then
if !(cmp -s "$FILE" <(printf "53\n32\n"));
then printf $FAILED
exit 1
fi
elif [[ "$f" == "use.grnd" ]]; then
if !(cmp -s "$FILE" <(printf "Hello\n"));
then printf $FAILED
exit 1
fi
else
printf "\033[31mCould not find test case\n\033[0m"
exit 1
fi
done
printf "\033[32mAll tests passed!\n\033[0m"
exit 0

2
tests/use.grnd Normal file
View File

@@ -0,0 +1,2 @@
use "lib"
call !lib_PrintHello &tmp