Files
Toy/tests/units/test_function.c
T

147 lines
3.2 KiB
C

#include "toy_vm.h"
#include "toy_console_colors.h"
#include "toy_lexer.h"
#include "toy_parser.h"
#include "toy_compiler.h"
#include "toy_print.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//define a function in one bytecode, invoke it in another
const char* sourceAlpha = "\n\
//using the classic closure approach\n\
fn makeCounter() {\n\
var counter: Int = 0;\n\
\
fn increment() {\n\
return ++counter;\n\
}\n\
\n\
return increment;\n\
}\n\
";
const char* sourceBeta = "\n\
var tally = makeCounter();\n\
\n\
while (true) {\n\
var result = tally();\n\
\n\
print result;\n\
\n\
if (result >= 10) {\n\
return result;\n\
}\n\
}\n\
";
//utils
unsigned char* makeCodeFromSource(Toy_Bucket** bucketHandle, const char* source) {
Toy_Lexer lexer;
Toy_bindLexer(&lexer, source);
Toy_Parser parser;
Toy_bindParser(&parser, &lexer);
Toy_Ast* ast = Toy_scanParser(bucketHandle, &parser);
return Toy_compileToBytecode(ast);
}
//tests
int test_functions_from_bytecodes(void) {
//do the thing
{
//setup
Toy_Bucket* bucket = Toy_allocateBucket(TOY_BUCKET_IDEAL);
Toy_String* makeCounterString = Toy_createStringLength(&bucket, "makeCounter", 11);
Toy_VM vm;
Toy_initVM(&vm);
//run alpha
unsigned char* alpha = makeCodeFromSource(&bucket, sourceAlpha);
Toy_bindVM(&vm, alpha, NULL);
Toy_runVM(&vm);
//check for the function was declared
if (Toy_isDeclaredScope(vm.scope, makeCounterString) != true) {
fprintf(stderr, TOY_CC_ERROR "ERROR: Failed to create the function '%s' from source\n" TOY_CC_RESET, makeCounterString->leaf.data);
Toy_freeString(makeCounterString);
Toy_freeVM(&vm);
Toy_freeBucket(&bucket);
free(alpha);
return -1;
}
//get the function and clean up
Toy_Value fnValue = Toy_copyValue(&bucket, *Toy_accessScopeAsPointer(vm.scope, makeCounterString));
Toy_resetVM(&vm, false, true);
//run beta
unsigned char* beta = makeCodeFromSource(&bucket, sourceBeta);
Toy_bindVM(&vm, beta, NULL);
Toy_declareScope(vm.scope, makeCounterString, TOY_VALUE_ANY, fnValue, true);
Toy_runVM(&vm);
//examine the results
if (vm.stack->count != 1 ||
TOY_VALUE_IS_INTEGER(vm.stack->data[0]) != true ||
TOY_VALUE_AS_INTEGER(vm.stack->data[0]) != 10
)
{
fprintf(stderr, TOY_CC_ERROR "ERROR: Unexpected result found in function results\n" TOY_CC_RESET);
Toy_freeString(makeCounterString);
Toy_freeVM(&vm);
Toy_freeBucket(&bucket);
free(alpha);
free(beta);
return -1;
}
Toy_resetVM(&vm, false, true);
//cleanup
Toy_freeValue(fnValue);
Toy_freeString(makeCounterString);
Toy_freeVM(&vm);
Toy_freeBucket(&bucket);
free(alpha);
free(beta);
}
//all good
return 0;
}
int test_functions_from_callbacks(void) {
//TODO: Test not yet implemented
printf(TOY_CC_WARN "WIP test not yet implemented: %s\n" TOY_CC_RESET, __FILE__);
return 0;
}
int main(void) {
//run each test set, returning the total errors given
int total = 0, res = 0;
{
res = test_functions_from_bytecodes();
if (res == 0) {
printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET);
}
total += res;
}
{
res = test_functions_from_callbacks();
if (res == 0) {
printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET);
}
total += res;
}
return total;
}