mirror of
https://github.com/krgamestudios/Toy.git
synced 2026-04-15 14:54:07 +10:00
Reworked generic structures, read more
The following structures are now more independant: - Toy_Array - Toy_Stack - Toy_Bucket - Toy_String I reworked a lot of the memory allocation, so now there are more direct calls to malloc() or realloc(), rather than relying on the macros from toy_memory.h. I've also split toy_memory into proper array and bucket files, because it makes more sense this way, rather than having them both jammed into one file. This means the eventual hashtable structure can also stand on its own. Toy_Array is a new wrapper around raw array pointers, and all of the structures have their metadata embedded into their allocated memory now, using variable length array members. A lot of 'capacity' and 'count' variables were changed to 'size_t' types, but this doesn't seem to be a problem anywhere. If the workflow fails, then I'll leave it for tonight - I'm too tired, and I don't want to overdo myself.
This commit is contained in:
28
repl/main.c
28
repl/main.c
@@ -1,6 +1,7 @@
|
|||||||
#include "toy.h"
|
#include "toy.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
//utilities
|
//utilities
|
||||||
@@ -18,7 +19,7 @@ unsigned char* readFile(char* path, int* size) {
|
|||||||
rewind(file);
|
rewind(file);
|
||||||
|
|
||||||
//make some space
|
//make some space
|
||||||
unsigned char* buffer = TOY_ALLOCATE(unsigned char, *size + 1);
|
unsigned char* buffer = malloc(*size + 1);
|
||||||
if (buffer == NULL) {
|
if (buffer == NULL) {
|
||||||
fclose(file);
|
fclose(file);
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -127,14 +128,20 @@ CmdLine parseCmdLine(int argc, const char* argv[]) {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (cmd.infile != NULL) { //don't leak
|
if (cmd.infile != NULL) { //don't leak
|
||||||
TOY_FREE_ARRAY(char, cmd.infile, strlen(cmd.infile));
|
free(cmd.infile);
|
||||||
}
|
}
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
|
|
||||||
//total space to reserve - it's actually longer than needed, due to the exe name being removed
|
//total space to reserve - it's actually longer than needed, due to the exe name being removed
|
||||||
cmd.infileLength = strlen(argv[0]) + strlen(argv[i]);
|
cmd.infileLength = strlen(argv[0]) + strlen(argv[i]);
|
||||||
cmd.infile = TOY_ALLOCATE(char, cmd.infileLength);
|
cmd.infile = malloc(cmd.infileLength);
|
||||||
|
|
||||||
|
if (cmd.infile == NULL) {
|
||||||
|
fprintf(stderr, TOY_CC_ERROR "ERROR: Failed to allocate space while parsing the command line, exiting\n" TOY_CC_RESET);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
dir(cmd.infile, argv[0]);
|
dir(cmd.infile, argv[0]);
|
||||||
APPEND(cmd.infile, argv[i]);
|
APPEND(cmd.infile, argv[i]);
|
||||||
FLIPSLASH(cmd.infile);
|
FLIPSLASH(cmd.infile);
|
||||||
@@ -167,7 +174,8 @@ int main(int argc, const char* argv[]) {
|
|||||||
int size;
|
int size;
|
||||||
unsigned char* source = readFile(cmd.infile, &size);
|
unsigned char* source = readFile(cmd.infile, &size);
|
||||||
|
|
||||||
TOY_FREE_ARRAY(char, cmd.infile, cmd.infileLength); //clean this up, since it's no longer needed
|
free(cmd.infile);
|
||||||
|
|
||||||
cmd.infile = NULL;
|
cmd.infile = NULL;
|
||||||
cmd.infileLength = 0;
|
cmd.infileLength = 0;
|
||||||
|
|
||||||
@@ -195,15 +203,13 @@ int main(int argc, const char* argv[]) {
|
|||||||
Toy_Parser parser;
|
Toy_Parser parser;
|
||||||
Toy_bindParser(&parser, &lexer);
|
Toy_bindParser(&parser, &lexer);
|
||||||
|
|
||||||
Toy_Bucket* bucket = NULL;
|
Toy_Bucket* bucket = Toy_allocateBucket(sizeof(Toy_Ast) * 32);
|
||||||
TOY_BUCKET_INIT(Toy_Ast, bucket, 32);
|
|
||||||
Toy_Ast* ast = Toy_scanParser(&bucket, &parser);
|
Toy_Ast* ast = Toy_scanParser(&bucket, &parser);
|
||||||
|
|
||||||
Toy_Bytecode bc = Toy_compileBytecode(ast);
|
Toy_Bytecode bc = Toy_compileBytecode(ast);
|
||||||
|
|
||||||
//run the setup
|
//run the setup
|
||||||
Toy_VM vm;
|
Toy_VM vm;
|
||||||
Toy_initVM(&vm);
|
|
||||||
Toy_bindVM(&vm, bc.ptr, bc.capacity);
|
Toy_bindVM(&vm, bc.ptr, bc.capacity);
|
||||||
|
|
||||||
//run
|
//run
|
||||||
@@ -211,8 +217,8 @@ int main(int argc, const char* argv[]) {
|
|||||||
|
|
||||||
//debugging result
|
//debugging result
|
||||||
printf("printing the stack result\n\ntype\tvalue\n");
|
printf("printing the stack result\n\ntype\tvalue\n");
|
||||||
for (int i = 0; i < vm.stack.count; i++) {
|
for (int i = 0; i < vm.stack->count; i++) {
|
||||||
Toy_Value v = vm.stack.ptr[i];
|
Toy_Value v = ((Toy_Value*)(vm.stack + 1))[i];
|
||||||
|
|
||||||
printf(" %d\t ", v.type);
|
printf(" %d\t ", v.type);
|
||||||
|
|
||||||
@@ -247,8 +253,8 @@ int main(int argc, const char* argv[]) {
|
|||||||
|
|
||||||
//cleanup
|
//cleanup
|
||||||
Toy_freeVM(&vm);
|
Toy_freeVM(&vm);
|
||||||
TOY_BUCKET_FREE(bucket);
|
Toy_freeBucket(&bucket);
|
||||||
TOY_FREE_ARRAY(unsigned char, source, size);
|
free(source);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
usageCmdLine(argc, argv);
|
usageCmdLine(argc, argv);
|
||||||
|
|||||||
12
source/toy.h
12
source/toy.h
@@ -3,17 +3,21 @@
|
|||||||
//general utilities
|
//general utilities
|
||||||
#include "toy_common.h"
|
#include "toy_common.h"
|
||||||
#include "toy_console_colors.h"
|
#include "toy_console_colors.h"
|
||||||
#include "toy_memory.h"
|
|
||||||
|
|
||||||
//building blocks
|
//basic structures
|
||||||
#include "toy_value.h"
|
#include "toy_value.h"
|
||||||
|
#include "toy_array.h"
|
||||||
|
#include "toy_stack.h"
|
||||||
|
#include "toy_bucket.h"
|
||||||
|
#include "toy_string.h"
|
||||||
|
//TODO: hashtable
|
||||||
|
|
||||||
|
//IR structures and other components
|
||||||
#include "toy_ast.h"
|
#include "toy_ast.h"
|
||||||
#include "toy_routine.h"
|
#include "toy_routine.h"
|
||||||
#include "toy_stack.h"
|
|
||||||
|
|
||||||
//pipeline
|
//pipeline
|
||||||
#include "toy_lexer.h"
|
#include "toy_lexer.h"
|
||||||
#include "toy_parser.h"
|
#include "toy_parser.h"
|
||||||
#include "toy_bytecode.h"
|
#include "toy_bytecode.h"
|
||||||
#include "toy_vm.h"
|
#include "toy_vm.h"
|
||||||
|
|
||||||
|
|||||||
25
source/toy_array.c
Normal file
25
source/toy_array.c
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
#include "toy_array.h"
|
||||||
|
#include "toy_console_colors.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
Toy_Array* Toy_resizeArray(Toy_Array* paramArray, size_t capacity) {
|
||||||
|
if (capacity == 0) {
|
||||||
|
free(paramArray);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_Array* array = realloc(paramArray, capacity + sizeof(Toy_Array));
|
||||||
|
|
||||||
|
if (array == NULL) {
|
||||||
|
fprintf(stderr, TOY_CC_ERROR "ERROR: Failed to allocate a 'Toy_Array' of %d capacity\n" TOY_CC_RESET, (int)capacity);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
array->capacity = capacity;
|
||||||
|
array->count = paramArray == NULL ? 0 :
|
||||||
|
(array->count > capacity ? capacity : array->count); //truncate lost data
|
||||||
|
|
||||||
|
return array;
|
||||||
|
}
|
||||||
25
source/toy_array.h
Normal file
25
source/toy_array.h
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "toy_common.h"
|
||||||
|
|
||||||
|
//standard generic array
|
||||||
|
typedef struct Toy_Array { //32 | 64 BITNESS
|
||||||
|
size_t capacity; //4 | 4
|
||||||
|
size_t count; //4 | 4
|
||||||
|
char data[]; //- | -
|
||||||
|
} Toy_Array; //8 | 8
|
||||||
|
|
||||||
|
TOY_API Toy_Array* Toy_resizeArray(Toy_Array* array, size_t capacity);
|
||||||
|
|
||||||
|
#define TOY_ALLOCATE_ARRAY(type, count) \
|
||||||
|
Toy_resizeArray(NULL, sizeof(type)*(count))
|
||||||
|
|
||||||
|
#define TOY_FREE_ARRAY(type, array) \
|
||||||
|
Toy_resizeArray(array, 0)
|
||||||
|
|
||||||
|
#define TOY_ADJUST_ARRAY(type, array, newCapacity) \
|
||||||
|
Toy_resizeArray(array, sizeof(type) * newCapacity)
|
||||||
|
|
||||||
|
#define TOY_DOUBLE_ARRAY_CAPACITY(type, array) \
|
||||||
|
Toy_resizeArray(array, sizeof(type) * array->capacity < 8 ? sizeof(type) * 8 : sizeof(type) * array->capacity * 2)
|
||||||
|
|
||||||
@@ -1,25 +1,25 @@
|
|||||||
#include "toy_ast.h"
|
#include "toy_ast.h"
|
||||||
|
|
||||||
void Toy_private_initAstBlock(Toy_Bucket** bucket, Toy_Ast** handle) {
|
void Toy_private_initAstBlock(Toy_Bucket** bucket, Toy_Ast** handle) {
|
||||||
(*handle) = (Toy_Ast*)Toy_partBucket(bucket, sizeof(Toy_Ast));
|
Toy_Ast* tmp = (Toy_Ast*)Toy_partitionBucket(bucket, sizeof(Toy_Ast));
|
||||||
|
|
||||||
(*handle)->block.type = TOY_AST_BLOCK;
|
tmp->type = TOY_AST_BLOCK;
|
||||||
(*handle)->block.child = NULL;
|
tmp->block.child = NULL;
|
||||||
(*handle)->block.next = NULL;
|
tmp->block.next = NULL;
|
||||||
(*handle)->block.tail = NULL;
|
tmp->block.tail = NULL;
|
||||||
|
|
||||||
|
(*handle) = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Toy_private_appendAstBlock(Toy_Bucket** bucket, Toy_Ast** handle, Toy_Ast* child) {
|
void Toy_private_appendAstBlock(Toy_Bucket** bucket, Toy_Ast* block, Toy_Ast* child) {
|
||||||
//type check
|
|
||||||
|
|
||||||
//first, check if we're an empty head
|
//first, check if we're an empty head
|
||||||
if ((*handle)->block.child == NULL) {
|
if (block->block.child == NULL) {
|
||||||
(*handle)->block.child = child;
|
block->block.child = child;
|
||||||
return; //NOTE: first call on an empty head skips any memory allocations
|
return; //NOTE: first call on an empty head skips any memory allocations
|
||||||
}
|
}
|
||||||
|
|
||||||
//run (or jump) until we hit the current tail
|
//run (or jump) until we hit the current tail
|
||||||
Toy_Ast* iter = (*handle)->block.tail ? (*handle)->block.tail : (*handle);
|
Toy_Ast* iter = block->block.tail ? block->block.tail : block;
|
||||||
|
|
||||||
while(iter->block.next != NULL) {
|
while(iter->block.next != NULL) {
|
||||||
iter = iter->block.next;
|
iter = iter->block.next;
|
||||||
@@ -30,21 +30,23 @@ void Toy_private_appendAstBlock(Toy_Bucket** bucket, Toy_Ast** handle, Toy_Ast*
|
|||||||
|
|
||||||
//store the child in the new link, prep the tail pointer
|
//store the child in the new link, prep the tail pointer
|
||||||
iter->block.next->block.child = child;
|
iter->block.next->block.child = child;
|
||||||
(*handle)->block.tail = iter->block.next;
|
block->block.tail = iter->block.next;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Toy_private_emitAstValue(Toy_Bucket** bucket, Toy_Ast** handle, Toy_Value value) {
|
void Toy_private_emitAstValue(Toy_Bucket** bucket, Toy_Ast** handle, Toy_Value value) {
|
||||||
(*handle) = (Toy_Ast*)Toy_partBucket(bucket, sizeof(Toy_Ast));
|
Toy_Ast* tmp = (Toy_Ast*)Toy_partitionBucket(bucket, sizeof(Toy_Ast));
|
||||||
|
|
||||||
(*handle)->value.type = TOY_AST_VALUE;
|
tmp->type = TOY_AST_VALUE;
|
||||||
(*handle)->value.value = value;
|
tmp->value.value = value;
|
||||||
|
|
||||||
|
(*handle) = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: flag range checks
|
//TODO: flag range checks
|
||||||
void Toy_private_emitAstUnary(Toy_Bucket** bucket, Toy_Ast** handle, Toy_AstFlag flag) {
|
void Toy_private_emitAstUnary(Toy_Bucket** bucket, Toy_Ast** handle, Toy_AstFlag flag) {
|
||||||
Toy_Ast* tmp = (Toy_Ast*)Toy_partBucket(bucket, sizeof(Toy_Ast));
|
Toy_Ast* tmp = (Toy_Ast*)Toy_partitionBucket(bucket, sizeof(Toy_Ast));
|
||||||
|
|
||||||
tmp->unary.type = TOY_AST_UNARY;
|
tmp->type = TOY_AST_UNARY;
|
||||||
tmp->unary.flag = flag;
|
tmp->unary.flag = flag;
|
||||||
tmp->unary.child = *handle;
|
tmp->unary.child = *handle;
|
||||||
|
|
||||||
@@ -52,9 +54,9 @@ void Toy_private_emitAstUnary(Toy_Bucket** bucket, Toy_Ast** handle, Toy_AstFlag
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Toy_private_emitAstBinary(Toy_Bucket** bucket, Toy_Ast** handle, Toy_AstFlag flag, Toy_Ast* right) {
|
void Toy_private_emitAstBinary(Toy_Bucket** bucket, Toy_Ast** handle, Toy_AstFlag flag, Toy_Ast* right) {
|
||||||
Toy_Ast* tmp = (Toy_Ast*)Toy_partBucket(bucket, sizeof(Toy_Ast));
|
Toy_Ast* tmp = (Toy_Ast*)Toy_partitionBucket(bucket, sizeof(Toy_Ast));
|
||||||
|
|
||||||
tmp->binary.type = TOY_AST_BINARY;
|
tmp->type = TOY_AST_BINARY;
|
||||||
tmp->binary.flag = flag;
|
tmp->binary.flag = flag;
|
||||||
tmp->binary.left = *handle; //left-recursive
|
tmp->binary.left = *handle; //left-recursive
|
||||||
tmp->binary.right = right;
|
tmp->binary.right = right;
|
||||||
@@ -63,28 +65,34 @@ void Toy_private_emitAstBinary(Toy_Bucket** bucket, Toy_Ast** handle, Toy_AstFla
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Toy_private_emitAstGroup(Toy_Bucket** bucket, Toy_Ast** handle) {
|
void Toy_private_emitAstGroup(Toy_Bucket** bucket, Toy_Ast** handle) {
|
||||||
Toy_Ast* tmp = (Toy_Ast*)Toy_partBucket(bucket, sizeof(Toy_Ast));
|
Toy_Ast* tmp = (Toy_Ast*)Toy_partitionBucket(bucket, sizeof(Toy_Ast));
|
||||||
|
|
||||||
tmp->group.type = TOY_AST_GROUP;
|
tmp->type = TOY_AST_GROUP;
|
||||||
tmp->group.child = (*handle);
|
tmp->group.child = (*handle);
|
||||||
|
|
||||||
(*handle) = tmp;
|
(*handle) = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Toy_private_emitAstPass(Toy_Bucket** bucket, Toy_Ast** handle) {
|
void Toy_private_emitAstPass(Toy_Bucket** bucket, Toy_Ast** handle) {
|
||||||
(*handle) = (Toy_Ast*)Toy_partBucket(bucket, sizeof(Toy_Ast));
|
Toy_Ast* tmp = (Toy_Ast*)Toy_partitionBucket(bucket, sizeof(Toy_Ast));
|
||||||
|
|
||||||
(*handle)->pass.type = TOY_AST_PASS;
|
tmp->type = TOY_AST_PASS;
|
||||||
|
|
||||||
|
(*handle) = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Toy_private_emitAstError(Toy_Bucket** bucket, Toy_Ast** handle) {
|
void Toy_private_emitAstError(Toy_Bucket** bucket, Toy_Ast** handle) {
|
||||||
(*handle) = (Toy_Ast*)Toy_partBucket(bucket, sizeof(Toy_Ast));
|
Toy_Ast* tmp = (Toy_Ast*)Toy_partitionBucket(bucket, sizeof(Toy_Ast));
|
||||||
|
|
||||||
(*handle)->error.type = TOY_AST_ERROR;
|
tmp->type = TOY_AST_ERROR;
|
||||||
|
|
||||||
|
(*handle) = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Toy_private_emitAstEnd(Toy_Bucket** bucket, Toy_Ast** handle) {
|
void Toy_private_emitAstEnd(Toy_Bucket** bucket, Toy_Ast** handle) {
|
||||||
(*handle) = (Toy_Ast*)Toy_partBucket(bucket, sizeof(Toy_Ast));
|
Toy_Ast* tmp = (Toy_Ast*)Toy_partitionBucket(bucket, sizeof(Toy_Ast));
|
||||||
|
|
||||||
(*handle)->error.type = TOY_AST_END;
|
tmp->type = TOY_AST_END;
|
||||||
|
|
||||||
|
(*handle) = tmp;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "toy_common.h"
|
#include "toy_common.h"
|
||||||
#include "toy_memory.h"
|
|
||||||
|
|
||||||
|
#include "toy_bucket.h"
|
||||||
#include "toy_value.h"
|
#include "toy_value.h"
|
||||||
|
|
||||||
//each major type
|
//each major type
|
||||||
@@ -55,18 +55,6 @@ typedef enum Toy_AstFlag {
|
|||||||
//the root AST type
|
//the root AST type
|
||||||
typedef union Toy_Ast Toy_Ast;
|
typedef union Toy_Ast Toy_Ast;
|
||||||
|
|
||||||
void Toy_private_initAstBlock(Toy_Bucket** bucket, Toy_Ast** handle);
|
|
||||||
void Toy_private_appendAstBlock(Toy_Bucket** bucket, Toy_Ast** handle, Toy_Ast* child);
|
|
||||||
|
|
||||||
void Toy_private_emitAstValue(Toy_Bucket** bucket, Toy_Ast** handle, Toy_Value value);
|
|
||||||
void Toy_private_emitAstUnary(Toy_Bucket** bucket, Toy_Ast** handle, Toy_AstFlag flag);
|
|
||||||
void Toy_private_emitAstBinary(Toy_Bucket** bucket, Toy_Ast** handle,Toy_AstFlag flag, Toy_Ast* right);
|
|
||||||
void Toy_private_emitAstGroup(Toy_Bucket** bucket, Toy_Ast** handle);
|
|
||||||
|
|
||||||
void Toy_private_emitAstPass(Toy_Bucket** bucket, Toy_Ast** handle);
|
|
||||||
void Toy_private_emitAstError(Toy_Bucket** bucket, Toy_Ast** handle);
|
|
||||||
void Toy_private_emitAstEnd(Toy_Bucket** bucket, Toy_Ast** handle);
|
|
||||||
|
|
||||||
typedef struct Toy_AstBlock {
|
typedef struct Toy_AstBlock {
|
||||||
Toy_AstType type;
|
Toy_AstType type;
|
||||||
Toy_Ast* child; //begin encoding the line
|
Toy_Ast* child; //begin encoding the line
|
||||||
@@ -121,3 +109,15 @@ union Toy_Ast { //32 | 64 BITNESS
|
|||||||
Toy_AstError error; //4 | 4
|
Toy_AstError error; //4 | 4
|
||||||
Toy_AstEnd end; //4 | 4
|
Toy_AstEnd end; //4 | 4
|
||||||
}; //16 | 32
|
}; //16 | 32
|
||||||
|
|
||||||
|
void Toy_private_initAstBlock(Toy_Bucket** bucket, Toy_Ast** handle);
|
||||||
|
void Toy_private_appendAstBlock(Toy_Bucket** bucket, Toy_Ast* block, Toy_Ast* child);
|
||||||
|
|
||||||
|
void Toy_private_emitAstValue(Toy_Bucket** bucket, Toy_Ast** handle, Toy_Value value);
|
||||||
|
void Toy_private_emitAstUnary(Toy_Bucket** bucket, Toy_Ast** handle, Toy_AstFlag flag);
|
||||||
|
void Toy_private_emitAstBinary(Toy_Bucket** bucket, Toy_Ast** handle,Toy_AstFlag flag, Toy_Ast* right);
|
||||||
|
void Toy_private_emitAstGroup(Toy_Bucket** bucket, Toy_Ast** handle);
|
||||||
|
|
||||||
|
void Toy_private_emitAstPass(Toy_Bucket** bucket, Toy_Ast** handle);
|
||||||
|
void Toy_private_emitAstError(Toy_Bucket** bucket, Toy_Ast** handle);
|
||||||
|
void Toy_private_emitAstEnd(Toy_Bucket** bucket, Toy_Ast** handle);
|
||||||
68
source/toy_bucket.c
Normal file
68
source/toy_bucket.c
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
#include "toy_bucket.h"
|
||||||
|
#include "toy_console_colors.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
//buckets of fun
|
||||||
|
Toy_Bucket* Toy_allocateBucket(size_t capacity) {
|
||||||
|
if (capacity == 0) {
|
||||||
|
fprintf(stderr, TOY_CC_ERROR "ERROR: Cannot allocate a 'Toy_Bucket' with zero capacity\n" TOY_CC_RESET);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_Bucket* bucket = malloc(sizeof(Toy_Bucket) + capacity);
|
||||||
|
|
||||||
|
if (bucket == NULL) {
|
||||||
|
fprintf(stderr, TOY_CC_ERROR "ERROR: Failed to allocate a 'Toy_Bucket' of %d capacity\n" TOY_CC_RESET, (int)capacity);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
//initialize the bucket
|
||||||
|
bucket->next = NULL;
|
||||||
|
bucket->capacity = capacity;
|
||||||
|
bucket->count = 0;
|
||||||
|
|
||||||
|
return bucket;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* Toy_partitionBucket(Toy_Bucket** bucketHandle, size_t amount) {
|
||||||
|
if ((*bucketHandle) == NULL) {
|
||||||
|
fprintf(stderr, TOY_CC_ERROR "ERROR: Expected a 'Toy_Bucket', received NULL\n" TOY_CC_RESET);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
//if you try to allocate too much space
|
||||||
|
if ((*bucketHandle)->capacity < amount) {
|
||||||
|
fprintf(stderr, TOY_CC_ERROR "ERROR: Failed to partition a 'Toy_Bucket': requested %d from a bucket of %d capacity\n" TOY_CC_RESET, (int)amount, (int)((*bucketHandle)->capacity));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
//if you're out of space in this bucket
|
||||||
|
if ((*bucketHandle)->capacity < (*bucketHandle)->count + amount) {
|
||||||
|
//move to the next bucket
|
||||||
|
Toy_Bucket* tmp = Toy_allocateBucket((*bucketHandle)->capacity);
|
||||||
|
tmp->next = (*bucketHandle); //it's buckets all the way down
|
||||||
|
(*bucketHandle) = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
//track the new count, and return the specified memory space
|
||||||
|
(*bucketHandle)->count += amount;
|
||||||
|
return ((*bucketHandle)->data + (*bucketHandle)->count - amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Toy_freeBucket(Toy_Bucket** bucketHandle) {
|
||||||
|
Toy_Bucket* iter = (*bucketHandle);
|
||||||
|
|
||||||
|
while (iter != NULL) {
|
||||||
|
//run down the chain
|
||||||
|
Toy_Bucket* last = iter;
|
||||||
|
iter = iter->next;
|
||||||
|
|
||||||
|
//clear the previous bucket from memory
|
||||||
|
free(last);
|
||||||
|
}
|
||||||
|
|
||||||
|
//for safety
|
||||||
|
(*bucketHandle) = NULL;
|
||||||
|
}
|
||||||
22
source/toy_bucket.h
Normal file
22
source/toy_bucket.h
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "toy_common.h"
|
||||||
|
|
||||||
|
//NOTE: this structure has restrictions on it's usage:
|
||||||
|
// - It can only expand until it is freed
|
||||||
|
// - It cannot be copied around within RAM
|
||||||
|
// - It cannot allocate more memory than it has capacity
|
||||||
|
// If each of these rules are followed, the bucket is actually more efficient than any other option
|
||||||
|
|
||||||
|
//a custom allocator
|
||||||
|
typedef struct Toy_Bucket { //32 | 64 BITNESS
|
||||||
|
struct Toy_Bucket* next; //4 | 8
|
||||||
|
size_t capacity; //4 | 4
|
||||||
|
size_t count; //4 | 4
|
||||||
|
char data[]; //- | -
|
||||||
|
} Toy_Bucket; //12 | 16
|
||||||
|
|
||||||
|
TOY_API Toy_Bucket* Toy_allocateBucket(size_t capacity);
|
||||||
|
TOY_API void* Toy_partitionBucket(Toy_Bucket** bucketHandle, size_t amount);
|
||||||
|
TOY_API void Toy_freeBucket(Toy_Bucket** bucketHandle);
|
||||||
|
|
||||||
@@ -1,21 +1,26 @@
|
|||||||
#include "toy_bytecode.h"
|
#include "toy_bytecode.h"
|
||||||
#include "toy_console_colors.h"
|
#include "toy_console_colors.h"
|
||||||
|
|
||||||
#include "toy_memory.h"
|
|
||||||
#include "toy_routine.h"
|
#include "toy_routine.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
//utils
|
//utils
|
||||||
static void expand(Toy_Bytecode* bc, int amount) {
|
static void expand(Toy_Bytecode* bc, size_t amount) {
|
||||||
if (bc->count + amount > bc->capacity) {
|
if (bc->count + amount > bc->capacity) {
|
||||||
int oldCapacity = bc->capacity;
|
|
||||||
|
|
||||||
while (bc->count + amount > bc->capacity) {
|
while (bc->count + amount > bc->capacity) { //expand as much as needed
|
||||||
bc->capacity = TOY_GROW_CAPACITY(bc->capacity);
|
bc->capacity = bc->capacity < 8 ? 8 : bc->capacity * 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
bc->ptr = realloc(bc->ptr, bc->capacity);
|
||||||
|
|
||||||
|
if (bc->ptr == NULL) {
|
||||||
|
fprintf(stderr, TOY_CC_ERROR "ERROR: Failed to allocate a 'Toy_Bytecode' of %d capacity\n" TOY_CC_RESET, (int)(bc->capacity));
|
||||||
|
exit(1);
|
||||||
}
|
}
|
||||||
bc->ptr = TOY_GROW_ARRAY(unsigned char, bc->ptr, oldCapacity, bc->capacity);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -32,7 +37,7 @@ static void writeBytecodeHeader(Toy_Bytecode* bc) {
|
|||||||
|
|
||||||
//check strlen for the build string
|
//check strlen for the build string
|
||||||
const char* build = Toy_private_version_build();
|
const char* build = Toy_private_version_build();
|
||||||
int len = (int)strlen(build) + 1;
|
size_t len = strlen(build) + 1;
|
||||||
|
|
||||||
//BUGFIX: ensure the end of the header has 4-byte alignment
|
//BUGFIX: ensure the end of the header has 4-byte alignment
|
||||||
if (len % 4 != 1) { //1 to fill the 4th byte above
|
if (len % 4 != 1) { //1 to fill the 4th byte above
|
||||||
@@ -42,6 +47,8 @@ static void writeBytecodeHeader(Toy_Bytecode* bc) {
|
|||||||
expand(bc, len);
|
expand(bc, len);
|
||||||
memcpy(bc->ptr + bc->count, build, len);
|
memcpy(bc->ptr + bc->count, build, len);
|
||||||
bc->count += len;
|
bc->count += len;
|
||||||
|
|
||||||
|
bc->ptr[bc->count] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
static void writeBytecodeBody(Toy_Bytecode* bc, Toy_Ast* ast) {
|
static void writeBytecodeBody(Toy_Bytecode* bc, Toy_Ast* ast) {
|
||||||
@@ -50,7 +57,7 @@ static void writeBytecodeBody(Toy_Bytecode* bc, Toy_Ast* ast) {
|
|||||||
//eventually, the bytecode may support multiple modules packed into one file
|
//eventually, the bytecode may support multiple modules packed into one file
|
||||||
void* module = Toy_compileRoutine(ast);
|
void* module = Toy_compileRoutine(ast);
|
||||||
|
|
||||||
int len = ((int*)module)[0];
|
size_t len = (size_t)(((int*)module)[0]);
|
||||||
|
|
||||||
expand(bc, len);
|
expand(bc, len);
|
||||||
memcpy(bc->ptr + bc->count, module, len);
|
memcpy(bc->ptr + bc->count, module, len);
|
||||||
@@ -74,5 +81,5 @@ Toy_Bytecode Toy_compileBytecode(Toy_Ast* ast) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Toy_freeBytecode(Toy_Bytecode bc) {
|
void Toy_freeBytecode(Toy_Bytecode bc) {
|
||||||
TOY_FREE_ARRAY(unsigned char, bc.ptr, bc.capacity);
|
free(bc.ptr);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,8 +5,8 @@
|
|||||||
|
|
||||||
typedef struct Toy_Bytecode {
|
typedef struct Toy_Bytecode {
|
||||||
unsigned char* ptr;
|
unsigned char* ptr;
|
||||||
int capacity;
|
size_t capacity;
|
||||||
int count;
|
size_t count;
|
||||||
} Toy_Bytecode;
|
} Toy_Bytecode;
|
||||||
|
|
||||||
TOY_API Toy_Bytecode Toy_compileBytecode(Toy_Ast* ast);
|
TOY_API Toy_Bytecode Toy_compileBytecode(Toy_Ast* ast);
|
||||||
|
|||||||
@@ -312,7 +312,7 @@ Toy_Token Toy_private_scanLexer(Toy_Lexer* lexer) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void trim(char** s, int* l) { //util
|
static void trim(char** s, size_t* l) { //util
|
||||||
while( isspace(( (*((unsigned char**)(s)))[(*l) - 1] )) ) (*l)--;
|
while( isspace(( (*((unsigned char**)(s)))[(*l) - 1] )) ) (*l)--;
|
||||||
while(**s && isspace( **(unsigned char**)(s)) ) { (*s)++; (*l)--; }
|
while(**s && isspace( **(unsigned char**)(s)) ) { (*s)++; (*l)--; }
|
||||||
}
|
}
|
||||||
@@ -321,22 +321,22 @@ static void trim(char** s, int* l) { //util
|
|||||||
void Toy_private_printToken(Toy_Token* token) {
|
void Toy_private_printToken(Toy_Token* token) {
|
||||||
//print errors
|
//print errors
|
||||||
if (token->type == TOY_TOKEN_ERROR) {
|
if (token->type == TOY_TOKEN_ERROR) {
|
||||||
printf(TOY_CC_ERROR "ERROR: \t%d\t%.*s\n" TOY_CC_RESET, token->line, token->length, token->lexeme);
|
printf(TOY_CC_ERROR "ERROR: \t%d\t%.*s\n" TOY_CC_RESET, (int)token->line, (int)token->length, token->lexeme);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//read pass token, even though it isn't generated
|
//read pass token, even though it isn't generated
|
||||||
if (token->type == TOY_TOKEN_PASS) {
|
if (token->type == TOY_TOKEN_PASS) {
|
||||||
printf(TOY_CC_NOTICE "PASS: \t%d\t%.*s\n" TOY_CC_RESET, token->line, token->length, token->lexeme);
|
printf(TOY_CC_NOTICE "PASS: \t%d\t%.*s\n" TOY_CC_RESET, (int)token->line, (int)token->length, token->lexeme);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//print the line number
|
//print the line number
|
||||||
printf("\t%d\t%d\t", token->type, token->line);
|
printf("\t%d\t%d\t", token->type, (int)token->line);
|
||||||
|
|
||||||
//print based on type
|
//print based on type
|
||||||
if (token->type == TOY_TOKEN_IDENTIFIER || token->type == TOY_TOKEN_LITERAL_INTEGER || token->type == TOY_TOKEN_LITERAL_FLOAT || token->type == TOY_TOKEN_LITERAL_STRING) {
|
if (token->type == TOY_TOKEN_IDENTIFIER || token->type == TOY_TOKEN_LITERAL_INTEGER || token->type == TOY_TOKEN_LITERAL_FLOAT || token->type == TOY_TOKEN_LITERAL_STRING) {
|
||||||
printf("%.*s\t", token->length, token->lexeme);
|
printf("%.*s\t", (int)token->length, token->lexeme);
|
||||||
} else {
|
} else {
|
||||||
const char* keyword = Toy_private_findKeywordByType(token->type);
|
const char* keyword = Toy_private_findKeywordByType(token->type);
|
||||||
|
|
||||||
@@ -344,9 +344,9 @@ void Toy_private_printToken(Toy_Token* token) {
|
|||||||
printf("%s", keyword);
|
printf("%s", keyword);
|
||||||
} else {
|
} else {
|
||||||
char* str = (char*)token->lexeme; //strip const-ness for trimming
|
char* str = (char*)token->lexeme; //strip const-ness for trimming
|
||||||
int length = token->length;
|
size_t length = token->length;
|
||||||
trim(&str, &length);
|
trim(&str, &length);
|
||||||
printf("%.*s", length, str);
|
printf("%.*s", (int)length, str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,17 +5,17 @@
|
|||||||
|
|
||||||
//lexers are bound to a string of code
|
//lexers are bound to a string of code
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int start; //start of the current token
|
size_t start; //start of the current token
|
||||||
int current; //current position of the lexer
|
size_t current; //current position of the lexer
|
||||||
int line; //track this for error handling
|
size_t line; //track this for error handling
|
||||||
const char* source;
|
const char* source;
|
||||||
} Toy_Lexer;
|
} Toy_Lexer;
|
||||||
|
|
||||||
//tokens are intermediaries between lexers and parsers
|
//tokens are intermediaries between lexers and parsers
|
||||||
typedef struct {
|
typedef struct {
|
||||||
Toy_TokenType type;
|
Toy_TokenType type;
|
||||||
int length;
|
size_t length;
|
||||||
int line;
|
size_t line;
|
||||||
const char* lexeme;
|
const char* lexeme;
|
||||||
} Toy_Token;
|
} Toy_Token;
|
||||||
|
|
||||||
|
|||||||
@@ -1,93 +0,0 @@
|
|||||||
#include "toy_memory.h"
|
|
||||||
|
|
||||||
#include "toy_console_colors.h"
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
void* Toy_reallocate(void* pointer, size_t oldSize, size_t newSize) {
|
|
||||||
if (newSize == 0) {
|
|
||||||
free(pointer);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void* result = realloc(pointer, newSize);
|
|
||||||
|
|
||||||
if (result == NULL) {
|
|
||||||
fprintf(stderr, TOY_CC_ERROR "[internal] ERROR: Memory allocation error (requested %d, replacing %d)\n" TOY_CC_RESET, (int)newSize, (int)oldSize);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
//buckets of fun
|
|
||||||
void Toy_initBucket(Toy_Bucket** bucketHandle, size_t capacity) {
|
|
||||||
if (capacity == 0) {
|
|
||||||
fprintf(stderr, TOY_CC_ERROR "[internal] ERROR: Cannot init a bucket with zero capacity\n" TOY_CC_RESET);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
(*bucketHandle) = malloc(sizeof(Toy_Bucket)); //TODO: rework the bucket, so there's only one malloc() call instead of two when partitioning
|
|
||||||
|
|
||||||
if ((*bucketHandle) == NULL) {
|
|
||||||
fprintf(stderr, TOY_CC_ERROR "[internal] ERROR: Failed to allocate space for a bucket\n" TOY_CC_RESET);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
//initialize the bucket
|
|
||||||
(*bucketHandle)->next = NULL;
|
|
||||||
(*bucketHandle)->contents = NULL; //leave until the first partition
|
|
||||||
(*bucketHandle)->capacity = capacity;
|
|
||||||
(*bucketHandle)->count = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void* Toy_partBucket(Toy_Bucket** bucketHandle, size_t space) {
|
|
||||||
if ((*bucketHandle) == NULL) {
|
|
||||||
fprintf(stderr, TOY_CC_ERROR "[internal] ERROR: Expected bucket, received NULL\n" TOY_CC_RESET);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
//if you try to allocate too much space
|
|
||||||
if ((*bucketHandle)->capacity < space) {
|
|
||||||
fprintf(stderr, TOY_CC_ERROR "[internal] ERROR: Failed to partition bucket memory, not enough capacity: needed %d, only %d available\n" TOY_CC_RESET, (int)space, (int)((*bucketHandle)->capacity));
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
//if out of space in the current bucket
|
|
||||||
if ((*bucketHandle)->capacity < (*bucketHandle)->count + space) {
|
|
||||||
//move to the next bucket
|
|
||||||
Toy_Bucket* tmp = NULL;
|
|
||||||
Toy_initBucket(&tmp, (*bucketHandle)->capacity);
|
|
||||||
tmp->next = (*bucketHandle);
|
|
||||||
(*bucketHandle) = tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
//if no space allocated for the current bucket
|
|
||||||
if ((*bucketHandle)->contents == NULL) {
|
|
||||||
//allocate space for the current bucket
|
|
||||||
(*bucketHandle)->contents = malloc((*bucketHandle)->capacity);
|
|
||||||
|
|
||||||
//double check
|
|
||||||
if ((*bucketHandle)->contents == NULL) {
|
|
||||||
fprintf(stderr, TOY_CC_ERROR "[internal] ERROR: Failed to allocate space for bucket contents\n" TOY_CC_RESET);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//track the new count, and return the specified memory space
|
|
||||||
(*bucketHandle)->count += space;
|
|
||||||
return ((*bucketHandle)->contents + (*bucketHandle)->count - space);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Toy_freeBucket(Toy_Bucket** bucketHandle) {
|
|
||||||
while ((*bucketHandle) != NULL) {
|
|
||||||
//run down the chain
|
|
||||||
Toy_Bucket* ptr = (*bucketHandle);
|
|
||||||
(*bucketHandle) = (*bucketHandle)->next;
|
|
||||||
|
|
||||||
//clear the previous bucket from memory
|
|
||||||
free(ptr->contents);
|
|
||||||
free(ptr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "toy_common.h"
|
|
||||||
|
|
||||||
//standard movable array for general use
|
|
||||||
#define TOY_GROW_CAPACITY(capacity) \
|
|
||||||
((capacity) < 8 ? 8 : (capacity) * 2)
|
|
||||||
|
|
||||||
#define TOY_ALLOCATE(type, count) \
|
|
||||||
(type*)Toy_reallocate(NULL, 0, sizeof(type)*(count))
|
|
||||||
|
|
||||||
#define TOY_FREE(type, pointer) \
|
|
||||||
(type*)Toy_reallocate(pointer, sizeof(type), 0)
|
|
||||||
|
|
||||||
#define TOY_GROW_ARRAY(type, pointer, oldSize, newSize) \
|
|
||||||
(type*)Toy_reallocate(pointer, sizeof(type)*oldSize, sizeof(type)*newSize)
|
|
||||||
|
|
||||||
#define TOY_SHRINK_ARRAY(type, pointer, oldCount, count) \
|
|
||||||
(type*)Toy_reallocate((type*)pointer, sizeof(type)*(oldCount), sizeof(type)*(count))
|
|
||||||
|
|
||||||
#define TOY_FREE_ARRAY(type, pointer, oldSize) \
|
|
||||||
(type*)Toy_reallocate(pointer, sizeof(type)*oldSize, 0)
|
|
||||||
|
|
||||||
TOY_API void* Toy_reallocate(void* pointer, size_t oldSize, size_t newSize);
|
|
||||||
|
|
||||||
//immobile "bucket" memory structure for custom allocators
|
|
||||||
#define TOY_BUCKET_INIT(type, bucket, count) \
|
|
||||||
Toy_initBucket(&(bucket), sizeof(type)*(count))
|
|
||||||
|
|
||||||
#define TOY_BUCKET_PART(type, bucket) \
|
|
||||||
(type*)Toy_partBucket(&(bucket), sizeof(type))
|
|
||||||
|
|
||||||
#define TOY_BUCKET_FREE(bucket) \
|
|
||||||
Toy_freeBucket(&(bucket))
|
|
||||||
|
|
||||||
typedef struct Toy_Bucket {
|
|
||||||
struct Toy_Bucket* next;
|
|
||||||
void* contents;
|
|
||||||
size_t capacity;
|
|
||||||
size_t count;
|
|
||||||
} Toy_Bucket;
|
|
||||||
|
|
||||||
TOY_API void Toy_initBucket(Toy_Bucket** bucketHandle, size_t capacity);
|
|
||||||
TOY_API void* Toy_partBucket(Toy_Bucket** bucketHandle, size_t space);
|
|
||||||
TOY_API void Toy_freeBucket(Toy_Bucket** bucketHandle);
|
|
||||||
@@ -10,14 +10,14 @@ static void printError(Toy_Parser* parser, Toy_Token token, const char* errorMsg
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(stderr, TOY_CC_ERROR "[Line %d] Error ", token.line);
|
fprintf(stderr, TOY_CC_ERROR "[Line %d] Error ", (int)token.line);
|
||||||
|
|
||||||
//check type
|
//check type
|
||||||
if (token.type == TOY_TOKEN_EOF) {
|
if (token.type == TOY_TOKEN_EOF) {
|
||||||
fprintf(stderr, "at end");
|
fprintf(stderr, "at end");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
fprintf(stderr, "at '%.*s'", token.length, token.lexeme);
|
fprintf(stderr, "at '%.*s'", (int)token.length, token.lexeme);
|
||||||
}
|
}
|
||||||
|
|
||||||
//finally
|
//finally
|
||||||
@@ -232,7 +232,7 @@ static Toy_AstFlag atomic(Toy_Bucket** bucket, Toy_Parser* parser, Toy_Ast** roo
|
|||||||
//filter the '_' character
|
//filter the '_' character
|
||||||
char buffer[parser->previous.length];
|
char buffer[parser->previous.length];
|
||||||
|
|
||||||
int i = 0, o = 0;
|
size_t i = 0, o = 0;
|
||||||
do {
|
do {
|
||||||
buffer[i] = parser->previous.lexeme[o];
|
buffer[i] = parser->previous.lexeme[o];
|
||||||
if (buffer[i] != '_') i++;
|
if (buffer[i] != '_') i++;
|
||||||
@@ -249,7 +249,7 @@ static Toy_AstFlag atomic(Toy_Bucket** bucket, Toy_Parser* parser, Toy_Ast** roo
|
|||||||
//filter the '_' character
|
//filter the '_' character
|
||||||
char buffer[parser->previous.length];
|
char buffer[parser->previous.length];
|
||||||
|
|
||||||
int i = 0, o = 0;
|
size_t i = 0, o = 0;
|
||||||
do {
|
do {
|
||||||
buffer[i] = parser->previous.lexeme[o];
|
buffer[i] = parser->previous.lexeme[o];
|
||||||
if (buffer[i] != '_') i++;
|
if (buffer[i] != '_') i++;
|
||||||
@@ -542,11 +542,11 @@ static void makeBlockStmt(Toy_Bucket** bucket, Toy_Parser* parser, Toy_Ast** roo
|
|||||||
|
|
||||||
Toy_Ast* err = NULL;
|
Toy_Ast* err = NULL;
|
||||||
Toy_private_emitAstError(bucket, &err);
|
Toy_private_emitAstError(bucket, &err);
|
||||||
Toy_private_appendAstBlock(bucket, root, err);
|
Toy_private_appendAstBlock(bucket, *root, err);
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Toy_private_appendAstBlock(bucket, root, stmt);
|
Toy_private_appendAstBlock(bucket, *root, stmt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "toy_common.h"
|
#include "toy_common.h"
|
||||||
#include "toy_memory.h"
|
|
||||||
#include "toy_lexer.h"
|
#include "toy_lexer.h"
|
||||||
#include "toy_ast.h"
|
#include "toy_ast.h"
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
#include "toy_routine.h"
|
#include "toy_routine.h"
|
||||||
#include "toy_console_colors.h"
|
#include "toy_console_colors.h"
|
||||||
|
|
||||||
#include "toy_memory.h"
|
|
||||||
#include "toy_opcodes.h"
|
#include "toy_opcodes.h"
|
||||||
#include "toy_value.h"
|
#include "toy_value.h"
|
||||||
|
|
||||||
@@ -10,23 +9,26 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
//utils
|
//utils
|
||||||
static void expand(void** handle, int* capacity, int* count, int amount) {
|
static void expand(void** handle, size_t* capacity, size_t* count, size_t amount) {
|
||||||
if ((*count) + amount > (*capacity)) {
|
if ((*count) + amount > (*capacity)) {
|
||||||
int oldCapacity = (*capacity);
|
|
||||||
|
|
||||||
while ((*count) + amount > (*capacity)) {
|
while ((*count) + amount > (*capacity)) {
|
||||||
(*capacity) = TOY_GROW_CAPACITY(*capacity);
|
(*capacity) = (*capacity) < 8 ? 8 : (*capacity) * 2;
|
||||||
|
}
|
||||||
|
(*handle) = realloc((*handle), (*capacity));
|
||||||
|
|
||||||
|
if ((*handle) == NULL) {
|
||||||
|
fprintf(stderr, TOY_CC_ERROR "ERROR: Failed to allocate a 'Toy_Routine' of %d capacity\n" TOY_CC_RESET, (int)(*capacity));
|
||||||
|
exit(1);
|
||||||
}
|
}
|
||||||
(*handle) = TOY_GROW_ARRAY(unsigned char, (*handle), oldCapacity, (*capacity));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void emitByte(void** handle, int* capacity, int* count, unsigned char byte) {
|
static void emitByte(void** handle, size_t* capacity, size_t* count, unsigned char byte) {
|
||||||
expand(handle, capacity, count, 1);
|
expand(handle, capacity, count, 1);
|
||||||
((unsigned char*)(*handle))[(*count)++] = byte;
|
((unsigned char*)(*handle))[(*count)++] = byte;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void emitInt(void** handle, int* capacity, int* count, int bytes) {
|
static void emitInt(void** handle, size_t* capacity, size_t* count, size_t bytes) {
|
||||||
char* ptr = (char*)&bytes;
|
char* ptr = (char*)&bytes;
|
||||||
emitByte(handle, capacity, count, *(ptr++));
|
emitByte(handle, capacity, count, *(ptr++));
|
||||||
emitByte(handle, capacity, count, *(ptr++));
|
emitByte(handle, capacity, count, *(ptr++));
|
||||||
@@ -34,7 +36,7 @@ static void emitInt(void** handle, int* capacity, int* count, int bytes) {
|
|||||||
emitByte(handle, capacity, count, *(ptr++));
|
emitByte(handle, capacity, count, *(ptr++));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void emitFloat(void** handle, int* capacity, int* count, float bytes) {
|
static void emitFloat(void** handle, size_t* capacity, size_t* count, float bytes) {
|
||||||
char* ptr = (char*)&bytes;
|
char* ptr = (char*)&bytes;
|
||||||
emitByte(handle, capacity, count, *(ptr++));
|
emitByte(handle, capacity, count, *(ptr++));
|
||||||
emitByte(handle, capacity, count, *(ptr++));
|
emitByte(handle, capacity, count, *(ptr++));
|
||||||
@@ -281,8 +283,8 @@ static void* writeRoutine(Toy_Routine* rt, Toy_Ast* ast) {
|
|||||||
//TODO: data
|
//TODO: data
|
||||||
|
|
||||||
//write the header and combine the parts
|
//write the header and combine the parts
|
||||||
void* buffer = TOY_ALLOCATE(unsigned char, 16);
|
void* buffer = NULL;
|
||||||
int capacity = 0, count = 0;
|
size_t capacity = 0, count = 0;
|
||||||
// int paramAddr = 0, codeAddr = 0, jumpsAddr = 0, dataAddr = 0, subsAddr = 0;
|
// int paramAddr = 0, codeAddr = 0, jumpsAddr = 0, dataAddr = 0, subsAddr = 0;
|
||||||
int codeAddr = 0;
|
int codeAddr = 0;
|
||||||
|
|
||||||
@@ -357,12 +359,13 @@ void* Toy_compileRoutine(Toy_Ast* ast) {
|
|||||||
//build
|
//build
|
||||||
void * buffer = writeRoutine(&rt, ast);
|
void * buffer = writeRoutine(&rt, ast);
|
||||||
|
|
||||||
|
|
||||||
//cleanup the temp object
|
//cleanup the temp object
|
||||||
TOY_FREE_ARRAY(unsigned char, rt.param, rt.paramCapacity);
|
free(rt.param);
|
||||||
TOY_FREE_ARRAY(unsigned char, rt.code, rt.codeCapacity);
|
free(rt.code);
|
||||||
TOY_FREE_ARRAY(int, rt.jumps, rt.jumpsCapacity);
|
free(rt.jumps);
|
||||||
TOY_FREE_ARRAY(unsigned char, rt.data, rt.dataCapacity);
|
free(rt.data);
|
||||||
TOY_FREE_ARRAY(unsigned char, rt.subs, rt.subsCapacity);
|
free(rt.subs);
|
||||||
|
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,24 +6,24 @@
|
|||||||
//internal structure that holds the individual parts of a compiled routine
|
//internal structure that holds the individual parts of a compiled routine
|
||||||
typedef struct Toy_Routine {
|
typedef struct Toy_Routine {
|
||||||
unsigned char* param; //c-string params in sequence (could be moved below the jump table?)
|
unsigned char* param; //c-string params in sequence (could be moved below the jump table?)
|
||||||
int paramCapacity;
|
size_t paramCapacity;
|
||||||
int paramCount;
|
size_t paramCount;
|
||||||
|
|
||||||
unsigned char* code; //the instruction set
|
unsigned char* code; //the instruction set
|
||||||
int codeCapacity;
|
size_t codeCapacity;
|
||||||
int codeCount;
|
size_t codeCount;
|
||||||
|
|
||||||
int* jumps; //each 'jump' is the starting address of an element within 'data'
|
size_t* jumps; //each 'jump' is the starting address of an element within 'data'
|
||||||
int jumpsCapacity;
|
size_t jumpsCapacity;
|
||||||
int jumpsCount;
|
size_t jumpsCount;
|
||||||
|
|
||||||
unsigned char* data; //{type,val} tuples of data
|
unsigned char* data; //{type,val} tuples of data
|
||||||
int dataCapacity;
|
size_t dataCapacity;
|
||||||
int dataCount;
|
size_t dataCount;
|
||||||
|
|
||||||
unsigned char* subs; //subroutines, recursively
|
unsigned char* subs; //subroutines, recursively
|
||||||
int subsCapacity;
|
size_t subsCapacity;
|
||||||
int subsCount;
|
size_t subsCount;
|
||||||
} Toy_Routine;
|
} Toy_Routine;
|
||||||
|
|
||||||
TOY_API void* Toy_compileRoutine(Toy_Ast* ast);
|
TOY_API void* Toy_compileRoutine(Toy_Ast* ast);
|
||||||
@@ -1,72 +1,86 @@
|
|||||||
#include "toy_stack.h"
|
#include "toy_stack.h"
|
||||||
#include "toy_console_colors.h"
|
#include "toy_console_colors.h"
|
||||||
|
|
||||||
#include "toy_memory.h"
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
//a good chunk of space
|
//a good chunk of space - 'count' actually tracks the number of values
|
||||||
#define MIN_SIZE 64
|
#define MIN_CAPACITY 64
|
||||||
|
|
||||||
TOY_API void Toy_initStack(Toy_Stack* stack) {
|
Toy_Stack* Toy_allocateStack() {
|
||||||
stack->ptr = NULL;
|
Toy_Stack* stack = malloc(MIN_CAPACITY * sizeof(Toy_Value) + sizeof(Toy_Stack));
|
||||||
stack->capacity = 0;
|
|
||||||
stack->count = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Toy_preallocateStack(Toy_Stack* stack) {
|
if (stack == NULL) {
|
||||||
stack->capacity = MIN_SIZE;
|
fprintf(stderr, TOY_CC_ERROR "ERROR: Failed to allocate a 'Toy_Stack' of %d capacity (%d space in memory)\n" TOY_CC_RESET, MIN_CAPACITY, (int)(MIN_CAPACITY * sizeof(Toy_Value) + sizeof(Toy_Stack)));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
stack->capacity = MIN_CAPACITY;
|
||||||
stack->count = 0;
|
stack->count = 0;
|
||||||
|
|
||||||
stack->ptr = TOY_ALLOCATE(Toy_Value, stack->capacity);
|
return stack;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Toy_freeStack(Toy_Stack* stack) {
|
void Toy_freeStack(Toy_Stack* stack) {
|
||||||
//TODO: slip in a call to free the complex values here
|
//TODO: slip in a call to free the complex values here
|
||||||
|
|
||||||
TOY_FREE_ARRAY(Toy_Value, stack->ptr, stack->capacity);
|
free(stack);
|
||||||
|
|
||||||
Toy_initStack(stack);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Toy_pushStack(Toy_Stack* stack, Toy_Value value) {
|
void Toy_pushStack(Toy_Stack** stack, Toy_Value value) {
|
||||||
//don't go overboard - limit to 1mb
|
//don't go overboard - limit to 1mb of capacity used
|
||||||
if (stack->count >= 1024 * 1024 / sizeof(Toy_Value)) {
|
if ((*stack)->count >= 1024 * 1024 / sizeof(Toy_Value)) {
|
||||||
fprintf(stderr, TOY_CC_ERROR "ERROR: Stack overflow, exiting\n" TOY_CC_RESET);
|
fprintf(stderr, TOY_CC_ERROR "ERROR: Stack overflow\n" TOY_CC_RESET);
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
//expand the capacity if needed
|
//expand the capacity if needed
|
||||||
if (stack->count + 1 > stack->capacity) {
|
if ((*stack)->count + 1 > (*stack)->capacity) {
|
||||||
int oldCapacity = stack->capacity;
|
while ((*stack)->count + 1 > (*stack)->capacity) {
|
||||||
stack->capacity = stack->capacity < MIN_SIZE ? MIN_SIZE : stack->capacity * 2; //similar to TOY_GROW_CAPACITY, with a bigger initial size
|
(*stack)->capacity = (*stack)->capacity < MIN_CAPACITY ? MIN_CAPACITY : (*stack)->capacity * 2;
|
||||||
stack->ptr = TOY_GROW_ARRAY(Toy_Value, stack->ptr, oldCapacity, stack->capacity);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
stack->ptr[stack->count++] = value;
|
size_t newCapacity = (*stack)->capacity;
|
||||||
|
|
||||||
|
(*stack) = realloc((*stack), newCapacity * sizeof(Toy_Value) + sizeof(Toy_Stack));
|
||||||
|
|
||||||
|
if ((*stack) == NULL) {
|
||||||
|
fprintf(stderr, TOY_CC_ERROR "ERROR: Failed to reallocate a 'Toy_Stack' of %d capacity (%d space in memory)\n" TOY_CC_RESET, (int)newCapacity, (int)(newCapacity * sizeof(Toy_Value) + sizeof(Toy_Stack)));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Note: "pointer arithmetic in C/C++ is type-relative"
|
||||||
|
((Toy_Value*)((*stack) + 1))[(*stack)->count++] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
Toy_Value Toy_peekStack(Toy_Stack* stack) {
|
Toy_Value Toy_peekStack(Toy_Stack** stack) {
|
||||||
if (stack->count <= 0) {
|
if ((*stack)->count == 0) {
|
||||||
fprintf(stderr, TOY_CC_ERROR "ERROR: Stack underflow, exiting\n" TOY_CC_RESET);
|
fprintf(stderr, TOY_CC_ERROR "ERROR: Stack underflow\n" TOY_CC_RESET);
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return stack->ptr[stack->count - 1];
|
return ((Toy_Value*)((*stack) + 1))[(*stack)->count - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
Toy_Value Toy_popStack(Toy_Stack* stack) {
|
Toy_Value Toy_popStack(Toy_Stack** stack) {
|
||||||
if (stack->count <= 0) {
|
if ((*stack)->count == 0) {
|
||||||
fprintf(stderr, TOY_CC_ERROR "ERROR: Stack underflow, exiting\n" TOY_CC_RESET);
|
fprintf(stderr, TOY_CC_ERROR "ERROR: Stack underflow\n" TOY_CC_RESET);
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
//shrink if possible
|
//shrink if possible
|
||||||
if (stack->count > MIN_SIZE && stack->count < stack->capacity / 4) {
|
if ((*stack)->count > MIN_CAPACITY && (*stack)->count < (*stack)->capacity / 4) {
|
||||||
stack->ptr = TOY_SHRINK_ARRAY(Toy_Value, stack->ptr, stack->capacity, stack->capacity / 2);
|
(*stack)->capacity /= 2;
|
||||||
stack->capacity /= 2;
|
size_t newCapacity = (*stack)->capacity;
|
||||||
|
|
||||||
|
(*stack) = realloc((*stack), (*stack)->capacity * sizeof(Toy_Value) + sizeof(Toy_Stack));
|
||||||
|
|
||||||
|
if ((*stack) == NULL) {
|
||||||
|
fprintf(stderr, TOY_CC_ERROR "ERROR: Failed to reallocate a 'Toy_Stack' of %d capacity (%d space in memory)\n" TOY_CC_RESET, (int)newCapacity, (int)(newCapacity * sizeof(Toy_Value) + sizeof(Toy_Stack)));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return stack->ptr[--stack->count];
|
return ((Toy_Value*)((*stack) + 1))[--(*stack)->count];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,16 +3,15 @@
|
|||||||
#include "toy_common.h"
|
#include "toy_common.h"
|
||||||
#include "toy_value.h"
|
#include "toy_value.h"
|
||||||
|
|
||||||
typedef struct Toy_Stack {
|
typedef struct Toy_Stack { //32 | 64 BITNESS
|
||||||
Toy_Value* ptr;
|
size_t capacity; //4 | 4
|
||||||
int capacity;
|
size_t count; //4 | 4
|
||||||
int count;
|
char data[]; //- | -
|
||||||
} Toy_Stack;
|
} Toy_Stack; //8 | 8
|
||||||
|
|
||||||
TOY_API void Toy_initStack(Toy_Stack* stack); //null memory
|
TOY_API Toy_Stack* Toy_allocateStack();
|
||||||
TOY_API void Toy_preallocateStack(Toy_Stack* stack); //non-null memory, ready to go
|
|
||||||
TOY_API void Toy_freeStack(Toy_Stack* stack);
|
TOY_API void Toy_freeStack(Toy_Stack* stack);
|
||||||
|
|
||||||
TOY_API void Toy_pushStack(Toy_Stack* stack, Toy_Value value);
|
TOY_API void Toy_pushStack(Toy_Stack** stack, Toy_Value value);
|
||||||
TOY_API Toy_Value Toy_peekStack(Toy_Stack* stack);
|
TOY_API Toy_Value Toy_peekStack(Toy_Stack** stack);
|
||||||
TOY_API Toy_Value Toy_popStack(Toy_Stack* stack);
|
TOY_API Toy_Value Toy_popStack(Toy_Stack** stack);
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ Toy_String* Toy_createString(Toy_Bucket** bucket, const char* cstring) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Toy_String* Toy_createStringLength(Toy_Bucket** bucket, const char* cstring, int length) {
|
Toy_String* Toy_createStringLength(Toy_Bucket** bucket, const char* cstring, int length) {
|
||||||
Toy_String* ret = (Toy_String*)Toy_partBucket(bucket, sizeof(Toy_String) + length + 1); //TODO: compensate for partitioning more space than bucket capacity
|
Toy_String* ret = (Toy_String*)Toy_partitionBucket(bucket, sizeof(Toy_String) + length + 1); //TODO: compensate for partitioning more space than bucket capacity
|
||||||
|
|
||||||
ret->type = TOY_STRING_LEAF;
|
ret->type = TOY_STRING_LEAF;
|
||||||
ret->length = length;
|
ret->length = length;
|
||||||
@@ -67,7 +67,7 @@ Toy_String* Toy_deepCopyString(Toy_Bucket** bucket, Toy_String* str) {
|
|||||||
fprintf(stderr, TOY_CC_ERROR "ERROR: Can't deep copy a string with refcount below or equal to zero\n" TOY_CC_RESET);
|
fprintf(stderr, TOY_CC_ERROR "ERROR: Can't deep copy a string with refcount below or equal to zero\n" TOY_CC_RESET);
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
Toy_String* ret = (Toy_String*)Toy_partBucket(bucket, sizeof(Toy_String) + str->length + 1); //TODO: compensate for partitioning more space than bucket capacity
|
Toy_String* ret = (Toy_String*)Toy_partitionBucket(bucket, sizeof(Toy_String) + str->length + 1); //TODO: compensate for partitioning more space than bucket capacity
|
||||||
|
|
||||||
//TODO
|
//TODO
|
||||||
ret->type = TOY_STRING_LEAF;
|
ret->type = TOY_STRING_LEAF;
|
||||||
@@ -85,7 +85,7 @@ Toy_String* Toy_concatString(Toy_Bucket** bucket, Toy_String* left, Toy_String*
|
|||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
Toy_String* ret = (Toy_String*)Toy_partBucket(bucket, sizeof(Toy_String));
|
Toy_String* ret = (Toy_String*)Toy_partitionBucket(bucket, sizeof(Toy_String));
|
||||||
|
|
||||||
ret->type = TOY_STRING_NODE;
|
ret->type = TOY_STRING_NODE;
|
||||||
ret->length = left->length + right->length;
|
ret->length = left->length + right->length;
|
||||||
@@ -117,7 +117,7 @@ char* Toy_getStringRawBuffer(Toy_String* str) {
|
|||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
char* buffer = TOY_ALLOCATE(char, str->length + 1);
|
char* buffer = malloc(str->length + 1);
|
||||||
|
|
||||||
deepCopyUtil(buffer, str);
|
deepCopyUtil(buffer, str);
|
||||||
buffer[str->length] = '\0';
|
buffer[str->length] = '\0';
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#include "toy_common.h"
|
#include "toy_common.h"
|
||||||
|
|
||||||
#include "toy_memory.h"
|
#include "toy_bucket.h"
|
||||||
|
|
||||||
//rope pattern
|
//rope pattern
|
||||||
typedef struct Toy_String { //32 | 64 BITNESS
|
typedef struct Toy_String { //32 | 64 BITNESS
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
#include "toy_value.h"
|
#include "toy_value.h"
|
||||||
|
|
||||||
#include "toy_console_colors.h"
|
#include "toy_console_colors.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
#include "toy_vm.h"
|
#include "toy_vm.h"
|
||||||
#include "toy_console_colors.h"
|
#include "toy_console_colors.h"
|
||||||
|
|
||||||
#include "toy_memory.h"
|
|
||||||
#include "toy_opcodes.h"
|
#include "toy_opcodes.h"
|
||||||
#include "toy_value.h"
|
#include "toy_value.h"
|
||||||
|
|
||||||
@@ -278,30 +277,6 @@ static void process(Toy_VM* vm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//exposed functions
|
//exposed functions
|
||||||
void Toy_initVM(Toy_VM* vm) {
|
|
||||||
vm->bc = NULL;
|
|
||||||
vm->bcSize = 0;
|
|
||||||
|
|
||||||
vm->routine = NULL;
|
|
||||||
vm->routineSize = 0;
|
|
||||||
|
|
||||||
vm->paramCount = 0;
|
|
||||||
vm->jumpsCount = 0;
|
|
||||||
vm->dataCount = 0;
|
|
||||||
vm->subsCount = 0;
|
|
||||||
|
|
||||||
vm->paramAddr = 0;
|
|
||||||
vm->codeAddr = 0;
|
|
||||||
vm->jumpsAddr = 0;
|
|
||||||
vm->dataAddr = 0;
|
|
||||||
vm->subsAddr = 0;
|
|
||||||
|
|
||||||
vm->routineCounter = 0;
|
|
||||||
|
|
||||||
//init the scope & stack
|
|
||||||
Toy_initStack(&vm->stack);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Toy_bindVM(Toy_VM* vm, unsigned char* bytecode, int bytecodeSize) {
|
void Toy_bindVM(Toy_VM* vm, unsigned char* bytecode, int bytecodeSize) {
|
||||||
if (bytecode[0] != TOY_VERSION_MAJOR || bytecode[1] > TOY_VERSION_MINOR) {
|
if (bytecode[0] != TOY_VERSION_MAJOR || bytecode[1] > TOY_VERSION_MINOR) {
|
||||||
fprintf(stderr, TOY_CC_ERROR "ERROR: Wrong bytecode version found: expected %d.%d.%d found %d.%d.%d, exiting\n" TOY_CC_RESET, TOY_VERSION_MAJOR, TOY_VERSION_MINOR, TOY_VERSION_PATCH, bytecode[0], bytecode[1], bytecode[2]);
|
fprintf(stderr, TOY_CC_ERROR "ERROR: Wrong bytecode version found: expected %d.%d.%d found %d.%d.%d, exiting\n" TOY_CC_RESET, TOY_VERSION_MAJOR, TOY_VERSION_MINOR, TOY_VERSION_PATCH, bytecode[0], bytecode[1], bytecode[2]);
|
||||||
@@ -331,7 +306,7 @@ void Toy_bindVM(Toy_VM* vm, unsigned char* bytecode, int bytecodeSize) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Toy_bindVMToRoutine(Toy_VM* vm, unsigned char* routine) {
|
void Toy_bindVMToRoutine(Toy_VM* vm, unsigned char* routine) {
|
||||||
Toy_initVM(vm);
|
Toy_resetVM(vm);
|
||||||
|
|
||||||
vm->routine = routine;
|
vm->routine = routine;
|
||||||
|
|
||||||
@@ -362,7 +337,7 @@ void Toy_bindVMToRoutine(Toy_VM* vm, unsigned char* routine) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//preallocate the scope & stack
|
//preallocate the scope & stack
|
||||||
Toy_preallocateStack(&vm->stack);
|
vm->stack = Toy_allocateStack();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Toy_runVM(Toy_VM* vm) {
|
void Toy_runVM(Toy_VM* vm) {
|
||||||
@@ -377,11 +352,36 @@ void Toy_runVM(Toy_VM* vm) {
|
|||||||
|
|
||||||
void Toy_freeVM(Toy_VM* vm) {
|
void Toy_freeVM(Toy_VM* vm) {
|
||||||
//clear the stack
|
//clear the stack
|
||||||
Toy_freeStack(&vm->stack);
|
Toy_freeStack(vm->stack);
|
||||||
|
|
||||||
//TODO: clear the scope
|
//TODO: clear the scope
|
||||||
|
|
||||||
//free the bytecode
|
//free the bytecode
|
||||||
TOY_FREE_ARRAY(unsigned char, vm->bc, vm->bcSize);
|
|
||||||
Toy_initVM(vm);
|
free(vm->bc);
|
||||||
|
Toy_resetVM(vm);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Toy_resetVM(Toy_VM* vm) {
|
||||||
|
vm->bc = NULL;
|
||||||
|
vm->bcSize = 0;
|
||||||
|
|
||||||
|
vm->routine = NULL;
|
||||||
|
vm->routineSize = 0;
|
||||||
|
|
||||||
|
vm->paramCount = 0;
|
||||||
|
vm->jumpsCount = 0;
|
||||||
|
vm->dataCount = 0;
|
||||||
|
vm->subsCount = 0;
|
||||||
|
|
||||||
|
vm->paramAddr = 0;
|
||||||
|
vm->codeAddr = 0;
|
||||||
|
vm->jumpsAddr = 0;
|
||||||
|
vm->dataAddr = 0;
|
||||||
|
vm->subsAddr = 0;
|
||||||
|
|
||||||
|
vm->routineCounter = 0;
|
||||||
|
|
||||||
|
//init the scope & stack
|
||||||
|
vm->stack = NULL;
|
||||||
}
|
}
|
||||||
@@ -30,15 +30,14 @@ typedef struct Toy_VM {
|
|||||||
//TODO: needs string util for identifiers
|
//TODO: needs string util for identifiers
|
||||||
|
|
||||||
//stack - immediate-level values only
|
//stack - immediate-level values only
|
||||||
Toy_Stack stack;
|
Toy_Stack* stack;
|
||||||
} Toy_VM;
|
} Toy_VM;
|
||||||
|
|
||||||
TOY_API void Toy_initVM(Toy_VM* vm);
|
|
||||||
|
|
||||||
TOY_API void Toy_bindVM(Toy_VM* vm, unsigned char* bytecode, int bytecodeSize); //process the version data
|
TOY_API void Toy_bindVM(Toy_VM* vm, unsigned char* bytecode, int bytecodeSize); //process the version data
|
||||||
TOY_API void Toy_bindVMToRoutine(Toy_VM* vm, unsigned char* routine); //process the routine only
|
TOY_API void Toy_bindVMToRoutine(Toy_VM* vm, unsigned char* routine); //process the routine only
|
||||||
|
|
||||||
TOY_API void Toy_runVM(Toy_VM* vm);
|
TOY_API void Toy_runVM(Toy_VM* vm);
|
||||||
TOY_API void Toy_freeVM(Toy_VM* vm);
|
TOY_API void Toy_freeVM(Toy_VM* vm);
|
||||||
|
TOY_API void Toy_resetVM(Toy_VM* vm);
|
||||||
|
|
||||||
//TODO: inject extra data
|
//TODO: inject extra data
|
||||||
|
|||||||
52
tests/cases/test_array.c
Normal file
52
tests/cases/test_array.c
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
#include "toy_array.h"
|
||||||
|
#include "toy_console_colors.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int test_resizeArray() {
|
||||||
|
//test single pointer
|
||||||
|
{
|
||||||
|
Toy_Array* array = TOY_ALLOCATE_ARRAY(int, 1);
|
||||||
|
TOY_FREE_ARRAY(int, array);
|
||||||
|
}
|
||||||
|
|
||||||
|
//test single pointer array
|
||||||
|
{
|
||||||
|
Toy_Array* array = TOY_ALLOCATE_ARRAY(int, 10);
|
||||||
|
|
||||||
|
//check you can access the memory
|
||||||
|
array->data[1] = 42;
|
||||||
|
|
||||||
|
TOY_FREE_ARRAY(int, array);
|
||||||
|
}
|
||||||
|
|
||||||
|
//test multiple pointer arrays
|
||||||
|
{
|
||||||
|
Toy_Array* array1 = TOY_ALLOCATE_ARRAY(int, 10);
|
||||||
|
Toy_Array* array2 = TOY_ALLOCATE_ARRAY(int, 10);
|
||||||
|
|
||||||
|
array1->data[1] = 42; //access the given memory
|
||||||
|
array2->data[1] = 42; //access the given memory
|
||||||
|
|
||||||
|
TOY_FREE_ARRAY(int, array1);
|
||||||
|
TOY_FREE_ARRAY(int, array2);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
//run each test set, returning the total errors given
|
||||||
|
int total = 0, res = 0;
|
||||||
|
|
||||||
|
{
|
||||||
|
res = test_resizeArray();
|
||||||
|
total += res;
|
||||||
|
|
||||||
|
if (res == 0) {
|
||||||
|
printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return total;
|
||||||
|
}
|
||||||
@@ -162,7 +162,7 @@ int test_type_emission(Toy_Bucket** bucket) {
|
|||||||
Toy_private_emitAstBinary(bucket, &ast, TOY_AST_FLAG_ADD, right);
|
Toy_private_emitAstBinary(bucket, &ast, TOY_AST_FLAG_ADD, right);
|
||||||
Toy_private_emitAstGroup(bucket, &ast);
|
Toy_private_emitAstGroup(bucket, &ast);
|
||||||
|
|
||||||
Toy_private_appendAstBlock(bucket, &block, ast);
|
Toy_private_appendAstBlock(bucket, block, ast);
|
||||||
}
|
}
|
||||||
|
|
||||||
//check if it worked
|
//check if it worked
|
||||||
@@ -216,10 +216,9 @@ int main() {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
{
|
{
|
||||||
Toy_Bucket* bucket = NULL;
|
Toy_Bucket* bucket = Toy_allocateBucket(sizeof(Toy_Ast) * 32);
|
||||||
TOY_BUCKET_INIT(Toy_Ast, bucket, 32);
|
|
||||||
res = test_type_emission(&bucket);
|
res = test_type_emission(&bucket);
|
||||||
TOY_BUCKET_FREE(bucket);
|
Toy_freeBucket(&bucket);
|
||||||
if (res == 0) {
|
if (res == 0) {
|
||||||
printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET);
|
printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,46 +1,13 @@
|
|||||||
#include "toy_memory.h"
|
#include "toy_bucket.h"
|
||||||
#include "toy_console_colors.h"
|
#include "toy_console_colors.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
int test_reallocate() {
|
|
||||||
//test single pointer
|
|
||||||
{
|
|
||||||
int* integer = TOY_ALLOCATE(int, 1);
|
|
||||||
TOY_FREE(int, integer);
|
|
||||||
}
|
|
||||||
|
|
||||||
//test single pointer array
|
|
||||||
{
|
|
||||||
int* array = TOY_ALLOCATE(int, 10);
|
|
||||||
|
|
||||||
//check you can access the memory
|
|
||||||
array[1] = 42;
|
|
||||||
|
|
||||||
TOY_FREE_ARRAY(int, array, 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
//test multiple pointer arrays
|
|
||||||
{
|
|
||||||
int* array1 = TOY_ALLOCATE(int, 10);
|
|
||||||
int* array2 = TOY_ALLOCATE(int, 10);
|
|
||||||
|
|
||||||
array1[1] = 42; //access the given memory
|
|
||||||
array2[1] = 42; //access the given memory
|
|
||||||
|
|
||||||
TOY_FREE_ARRAY(int, array1, 10);
|
|
||||||
TOY_FREE_ARRAY(int, array2, 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int test_buckets() {
|
int test_buckets() {
|
||||||
//test initializing and freeing a bucket
|
//test initializing and freeing a bucket
|
||||||
{
|
{
|
||||||
//init
|
//init
|
||||||
Toy_Bucket* bucket = NULL;
|
Toy_Bucket* bucket = Toy_allocateBucket(sizeof(int) * 32);
|
||||||
TOY_BUCKET_INIT(int, bucket, 32);
|
|
||||||
|
|
||||||
//check
|
//check
|
||||||
if (bucket == NULL || bucket->capacity != 32 * sizeof(int)) {
|
if (bucket == NULL || bucket->capacity != 32 * sizeof(int)) {
|
||||||
@@ -49,20 +16,19 @@ int test_buckets() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//cleanup
|
//cleanup
|
||||||
TOY_BUCKET_FREE(bucket);
|
Toy_freeBucket(&bucket);
|
||||||
}
|
}
|
||||||
|
|
||||||
//test partitioning a bucket, several times
|
//test partitioning a bucket, several times
|
||||||
{
|
{
|
||||||
//init
|
//init
|
||||||
Toy_Bucket* bucket = NULL;
|
Toy_Bucket* bucket = Toy_allocateBucket(sizeof(int) * 32);
|
||||||
TOY_BUCKET_INIT(int, bucket, 32);
|
|
||||||
|
|
||||||
//grab some memory
|
//grab some memory
|
||||||
int* a = TOY_BUCKET_PART(int, bucket);
|
int* a = Toy_partitionBucket(&bucket, sizeof(int));
|
||||||
int* b = TOY_BUCKET_PART(int, bucket);
|
int* b = Toy_partitionBucket(&bucket, sizeof(int));
|
||||||
int* c = TOY_BUCKET_PART(int, bucket);
|
int* c = Toy_partitionBucket(&bucket, sizeof(int));
|
||||||
int* d = TOY_BUCKET_PART(int, bucket);
|
int* d = Toy_partitionBucket(&bucket, sizeof(int));
|
||||||
|
|
||||||
//check
|
//check
|
||||||
if (bucket == NULL || bucket->count != 4 * sizeof(int)) {
|
if (bucket == NULL || bucket->count != 4 * sizeof(int)) {
|
||||||
@@ -71,22 +37,21 @@ int test_buckets() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//cleanup
|
//cleanup
|
||||||
TOY_BUCKET_FREE(bucket);
|
Toy_freeBucket(&bucket);
|
||||||
}
|
}
|
||||||
|
|
||||||
//test partitioning a bucket, several times, with an internal expansion
|
//test partitioning a bucket, several times, with an internal expansion
|
||||||
{
|
{
|
||||||
//init
|
//init
|
||||||
Toy_Bucket* bucket = NULL;
|
Toy_Bucket* bucket = Toy_allocateBucket(sizeof(int) * 4);
|
||||||
TOY_BUCKET_INIT(int, bucket, 4);
|
|
||||||
|
|
||||||
//grab some memory
|
//grab some memory
|
||||||
int* a = TOY_BUCKET_PART(int, bucket);
|
int* a = Toy_partitionBucket(&bucket, sizeof(int));
|
||||||
int* b = TOY_BUCKET_PART(int, bucket);
|
int* b = Toy_partitionBucket(&bucket, sizeof(int));
|
||||||
int* c = TOY_BUCKET_PART(int, bucket);
|
int* c = Toy_partitionBucket(&bucket, sizeof(int));
|
||||||
int* d = TOY_BUCKET_PART(int, bucket);
|
int* d = Toy_partitionBucket(&bucket, sizeof(int));
|
||||||
int* e = TOY_BUCKET_PART(int, bucket);
|
int* e = Toy_partitionBucket(&bucket, sizeof(int));
|
||||||
int* f = TOY_BUCKET_PART(int, bucket);
|
int* f = Toy_partitionBucket(&bucket, sizeof(int));
|
||||||
|
|
||||||
//checks - please note that the top-most bucket is what is being filled - older buckets are further along
|
//checks - please note that the top-most bucket is what is being filled - older buckets are further along
|
||||||
if (
|
if (
|
||||||
@@ -101,20 +66,19 @@ int test_buckets() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//cleanup
|
//cleanup
|
||||||
TOY_BUCKET_FREE(bucket);
|
Toy_freeBucket(&bucket);
|
||||||
}
|
}
|
||||||
|
|
||||||
//test partitioning a bucket, several times, with an internal expansion, and awkward sizes
|
//test partitioning a bucket, several times, with an internal expansion, and awkward sizes
|
||||||
{
|
{
|
||||||
//init
|
//init
|
||||||
Toy_Bucket* bucket = NULL;
|
Toy_Bucket* bucket = Toy_allocateBucket(32);
|
||||||
Toy_initBucket(&bucket, 32);
|
|
||||||
|
|
||||||
//grab some memory
|
//grab some memory
|
||||||
void* a = Toy_partBucket(&bucket, 16);
|
void* a = Toy_partitionBucket(&bucket, 16);
|
||||||
void* b = Toy_partBucket(&bucket, 10);
|
void* b = Toy_partitionBucket(&bucket, 10);
|
||||||
void* c = Toy_partBucket(&bucket, 10);
|
void* c = Toy_partitionBucket(&bucket, 10);
|
||||||
void* d = Toy_partBucket(&bucket, 10);
|
void* d = Toy_partitionBucket(&bucket, 10);
|
||||||
|
|
||||||
//checks - awkward and mismatched sizes is not officially supported, but it should work
|
//checks - awkward and mismatched sizes is not officially supported, but it should work
|
||||||
if (
|
if (
|
||||||
@@ -129,7 +93,7 @@ int test_buckets() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//cleanup
|
//cleanup
|
||||||
TOY_BUCKET_FREE(bucket);
|
Toy_freeBucket(&bucket);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -139,19 +103,14 @@ int main() {
|
|||||||
//run each test set, returning the total errors given
|
//run each test set, returning the total errors given
|
||||||
int total = 0, res = 0;
|
int total = 0, res = 0;
|
||||||
|
|
||||||
res = test_reallocate();
|
{
|
||||||
total += res;
|
|
||||||
|
|
||||||
if (res == 0) {
|
|
||||||
printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET);
|
|
||||||
}
|
|
||||||
|
|
||||||
res = test_buckets();
|
res = test_buckets();
|
||||||
total += res;
|
total += res;
|
||||||
|
|
||||||
if (res == 0) {
|
if (res == 0) {
|
||||||
printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET);
|
printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return total;
|
return total;
|
||||||
}
|
}
|
||||||
@@ -26,7 +26,7 @@ int test_bytecode_header(Toy_Bucket** bucket) {
|
|||||||
strcmp((char*)(bc.ptr + 3), TOY_VERSION_BUILD) != 0)
|
strcmp((char*)(bc.ptr + 3), TOY_VERSION_BUILD) != 0)
|
||||||
{
|
{
|
||||||
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to write the bytecode header correctly:\n" TOY_CC_RESET);
|
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to write the bytecode header correctly:\n" TOY_CC_RESET);
|
||||||
fprintf(stderr, TOY_CC_ERROR "\t%d.%d.%d.%s\n" TOY_CC_RESET, bc.ptr[0], bc.ptr[1], bc.ptr[2], (char*)(bc.ptr + 3));
|
fprintf(stderr, TOY_CC_ERROR "\t%d.%d.%d.%s\n" TOY_CC_RESET, (int)(bc.ptr[0]), (int)(bc.ptr[1]), (int)(bc.ptr[2]), (char*)(bc.ptr + 3));
|
||||||
fprintf(stderr, TOY_CC_ERROR "\t%d.%d.%d.%s\n" TOY_CC_RESET, TOY_VERSION_MAJOR, TOY_VERSION_MINOR, TOY_VERSION_PATCH, TOY_VERSION_BUILD);
|
fprintf(stderr, TOY_CC_ERROR "\t%d.%d.%d.%s\n" TOY_CC_RESET, TOY_VERSION_MAJOR, TOY_VERSION_MINOR, TOY_VERSION_PATCH, TOY_VERSION_BUILD);
|
||||||
|
|
||||||
//cleanup and return
|
//cleanup and return
|
||||||
@@ -35,7 +35,7 @@ int test_bytecode_header(Toy_Bucket** bucket) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (bc.count % 4 != 0) {
|
if (bc.count % 4 != 0) {
|
||||||
fprintf(stderr, TOY_CC_ERROR "ERROR: bytecode size is not a multiple of 4, size is: %d\n" TOY_CC_RESET, bc.count);
|
fprintf(stderr, TOY_CC_ERROR "ERROR: bytecode size is not a multiple of 4, size is: %d\n" TOY_CC_RESET, (int)bc.count);
|
||||||
|
|
||||||
//cleanup and return
|
//cleanup and return
|
||||||
Toy_freeBytecode(bc);
|
Toy_freeBytecode(bc);
|
||||||
@@ -65,7 +65,7 @@ int test_bytecode_from_source(Toy_Bucket** bucket) {
|
|||||||
|
|
||||||
//check bytecode alignment
|
//check bytecode alignment
|
||||||
if (bc.count % 4 != 0) {
|
if (bc.count % 4 != 0) {
|
||||||
fprintf(stderr, TOY_CC_ERROR "ERROR: bytecode alignment is not a multiple of 4 (size is %d), source: %s\n" TOY_CC_RESET, bc.count, source);
|
fprintf(stderr, TOY_CC_ERROR "ERROR: bytecode alignment is not a multiple of 4 (size is %d), source: %s\n" TOY_CC_RESET, (int)bc.count, source);
|
||||||
|
|
||||||
//cleanup and return
|
//cleanup and return
|
||||||
Toy_freeBytecode(bc);
|
Toy_freeBytecode(bc);
|
||||||
@@ -175,10 +175,9 @@ int main() {
|
|||||||
int total = 0, res = 0;
|
int total = 0, res = 0;
|
||||||
|
|
||||||
{
|
{
|
||||||
Toy_Bucket* bucket = NULL;
|
Toy_Bucket* bucket = Toy_allocateBucket(sizeof(Toy_Ast) * 32);
|
||||||
TOY_BUCKET_INIT(Toy_Ast, bucket, 32);
|
|
||||||
res = test_bytecode_header(&bucket);
|
res = test_bytecode_header(&bucket);
|
||||||
TOY_BUCKET_FREE(bucket);
|
Toy_freeBucket(&bucket);
|
||||||
if (res == 0) {
|
if (res == 0) {
|
||||||
printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET);
|
printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET);
|
||||||
}
|
}
|
||||||
@@ -186,10 +185,9 @@ int main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
Toy_Bucket* bucket = NULL;
|
Toy_Bucket* bucket = Toy_allocateBucket(sizeof(Toy_Ast) * 32);
|
||||||
TOY_BUCKET_INIT(Toy_Ast, bucket, 32);
|
|
||||||
res = test_bytecode_from_source(&bucket);
|
res = test_bytecode_from_source(&bucket);
|
||||||
TOY_BUCKET_FREE(bucket);
|
Toy_freeBucket(&bucket);
|
||||||
if (res == 0) {
|
if (res == 0) {
|
||||||
printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET);
|
printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -578,10 +578,9 @@ int main() {
|
|||||||
int total = 0, res = 0;
|
int total = 0, res = 0;
|
||||||
|
|
||||||
{
|
{
|
||||||
Toy_Bucket* bucket = NULL;
|
Toy_Bucket* bucket = Toy_allocateBucket(sizeof(Toy_Ast) * 32);
|
||||||
TOY_BUCKET_INIT(Toy_Ast, bucket, 32);
|
|
||||||
res = test_simple_empty_parsers(&bucket);
|
res = test_simple_empty_parsers(&bucket);
|
||||||
TOY_BUCKET_FREE(bucket);
|
Toy_freeBucket(&bucket);
|
||||||
if (res == 0) {
|
if (res == 0) {
|
||||||
printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET);
|
printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET);
|
||||||
}
|
}
|
||||||
@@ -589,10 +588,9 @@ int main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
Toy_Bucket* bucket = NULL;
|
Toy_Bucket* bucket = Toy_allocateBucket(sizeof(Toy_Ast) * 32);
|
||||||
TOY_BUCKET_INIT(Toy_Ast, bucket, 32);
|
|
||||||
res = test_values(&bucket);
|
res = test_values(&bucket);
|
||||||
TOY_BUCKET_FREE(bucket);
|
Toy_freeBucket(&bucket);
|
||||||
if (res == 0) {
|
if (res == 0) {
|
||||||
printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET);
|
printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET);
|
||||||
}
|
}
|
||||||
@@ -600,10 +598,9 @@ int main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
Toy_Bucket* bucket = NULL;
|
Toy_Bucket* bucket = Toy_allocateBucket(sizeof(Toy_Ast) * 32);
|
||||||
TOY_BUCKET_INIT(Toy_Ast, bucket, 32);
|
|
||||||
res = test_unary(&bucket);
|
res = test_unary(&bucket);
|
||||||
TOY_BUCKET_FREE(bucket);
|
Toy_freeBucket(&bucket);
|
||||||
if (res == 0) {
|
if (res == 0) {
|
||||||
printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET);
|
printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET);
|
||||||
}
|
}
|
||||||
@@ -611,10 +608,9 @@ int main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
Toy_Bucket* bucket = NULL;
|
Toy_Bucket* bucket = Toy_allocateBucket(sizeof(Toy_Ast) * 32);
|
||||||
TOY_BUCKET_INIT(Toy_Ast, bucket, 32);
|
|
||||||
res = test_binary(&bucket);
|
res = test_binary(&bucket);
|
||||||
TOY_BUCKET_FREE(bucket);
|
Toy_freeBucket(&bucket);
|
||||||
if (res == 0) {
|
if (res == 0) {
|
||||||
printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET);
|
printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET);
|
||||||
}
|
}
|
||||||
@@ -622,10 +618,9 @@ int main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
Toy_Bucket* bucket = NULL;
|
Toy_Bucket* bucket = Toy_allocateBucket(sizeof(Toy_Ast) * 32);
|
||||||
TOY_BUCKET_INIT(Toy_Ast, bucket, 32);
|
|
||||||
res = test_precedence(&bucket);
|
res = test_precedence(&bucket);
|
||||||
TOY_BUCKET_FREE(bucket);
|
Toy_freeBucket(&bucket);
|
||||||
if (res == 0) {
|
if (res == 0) {
|
||||||
printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET);
|
printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include "toy_parser.h"
|
#include "toy_parser.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
//tests
|
//tests
|
||||||
@@ -32,7 +33,7 @@ int test_routine_header_and_values(Toy_Bucket** bucket) {
|
|||||||
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine header, ast: PASS\n" TOY_CC_RESET);
|
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine header, ast: PASS\n" TOY_CC_RESET);
|
||||||
|
|
||||||
//cleanup and return
|
//cleanup and return
|
||||||
TOY_FREE_ARRAY(unsigned char, buffer, len);
|
free(buffer);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,12 +47,12 @@ int test_routine_header_and_values(Toy_Bucket** bucket) {
|
|||||||
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine code, ast: PASS\n" TOY_CC_RESET);
|
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine code, ast: PASS\n" TOY_CC_RESET);
|
||||||
|
|
||||||
//cleanup and return
|
//cleanup and return
|
||||||
TOY_FREE_ARRAY(unsigned char, buffer, len);
|
free(buffer);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//cleanup
|
//cleanup
|
||||||
TOY_FREE_ARRAY(unsigned char, buffer, len);
|
free(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
//rerun the test with a more complex ast, derived from a snippet of source
|
//rerun the test with a more complex ast, derived from a snippet of source
|
||||||
@@ -81,7 +82,7 @@ int test_routine_header_and_values(Toy_Bucket** bucket) {
|
|||||||
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine header, source: %s\n" TOY_CC_RESET, source);
|
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine header, source: %s\n" TOY_CC_RESET, source);
|
||||||
|
|
||||||
//cleanup and return
|
//cleanup and return
|
||||||
TOY_FREE_ARRAY(unsigned char, buffer, len);
|
free(buffer);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,12 +96,12 @@ int test_routine_header_and_values(Toy_Bucket** bucket) {
|
|||||||
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine code, source: %s\n" TOY_CC_RESET, source);
|
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine code, source: %s\n" TOY_CC_RESET, source);
|
||||||
|
|
||||||
//cleanup and return
|
//cleanup and return
|
||||||
TOY_FREE_ARRAY(unsigned char, buffer, len);
|
free(buffer);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//cleanup
|
//cleanup
|
||||||
TOY_FREE_ARRAY(unsigned char, buffer, len);
|
free(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
//produce a null value
|
//produce a null value
|
||||||
@@ -130,7 +131,7 @@ int test_routine_header_and_values(Toy_Bucket** bucket) {
|
|||||||
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine header, source: %s\n" TOY_CC_RESET, source);
|
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine header, source: %s\n" TOY_CC_RESET, source);
|
||||||
|
|
||||||
//cleanup and return
|
//cleanup and return
|
||||||
TOY_FREE_ARRAY(unsigned char, buffer, len);
|
free(buffer);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -148,12 +149,12 @@ int test_routine_header_and_values(Toy_Bucket** bucket) {
|
|||||||
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine code, source: %s\n" TOY_CC_RESET, source);
|
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine code, source: %s\n" TOY_CC_RESET, source);
|
||||||
|
|
||||||
//cleanup and return
|
//cleanup and return
|
||||||
TOY_FREE_ARRAY(unsigned char, buffer, len);
|
free(buffer);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//cleanup
|
//cleanup
|
||||||
TOY_FREE_ARRAY(unsigned char, buffer, len);
|
free(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
//produce a boolean value
|
//produce a boolean value
|
||||||
@@ -183,7 +184,7 @@ int test_routine_header_and_values(Toy_Bucket** bucket) {
|
|||||||
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine header, source: %s\n" TOY_CC_RESET, source);
|
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine header, source: %s\n" TOY_CC_RESET, source);
|
||||||
|
|
||||||
//cleanup and return
|
//cleanup and return
|
||||||
TOY_FREE_ARRAY(unsigned char, buffer, len);
|
free(buffer);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -201,12 +202,12 @@ int test_routine_header_and_values(Toy_Bucket** bucket) {
|
|||||||
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine code, source: %s\n" TOY_CC_RESET, source);
|
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine code, source: %s\n" TOY_CC_RESET, source);
|
||||||
|
|
||||||
//cleanup and return
|
//cleanup and return
|
||||||
TOY_FREE_ARRAY(unsigned char, buffer, len);
|
free(buffer);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//cleanup
|
//cleanup
|
||||||
TOY_FREE_ARRAY(unsigned char, buffer, len);
|
free(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
//produce an integer value
|
//produce an integer value
|
||||||
@@ -236,7 +237,7 @@ int test_routine_header_and_values(Toy_Bucket** bucket) {
|
|||||||
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine header, source: %s\n" TOY_CC_RESET, source);
|
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine header, source: %s\n" TOY_CC_RESET, source);
|
||||||
|
|
||||||
//cleanup and return
|
//cleanup and return
|
||||||
TOY_FREE_ARRAY(unsigned char, buffer, len);
|
free(buffer);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -255,12 +256,12 @@ int test_routine_header_and_values(Toy_Bucket** bucket) {
|
|||||||
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine code, source: %s\n" TOY_CC_RESET, source);
|
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine code, source: %s\n" TOY_CC_RESET, source);
|
||||||
|
|
||||||
//cleanup and return
|
//cleanup and return
|
||||||
TOY_FREE_ARRAY(unsigned char, buffer, len);
|
free(buffer);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//cleanup
|
//cleanup
|
||||||
TOY_FREE_ARRAY(unsigned char, buffer, len);
|
free(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
//produce a float value
|
//produce a float value
|
||||||
@@ -290,7 +291,7 @@ int test_routine_header_and_values(Toy_Bucket** bucket) {
|
|||||||
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine header, source: %s\n" TOY_CC_RESET, source);
|
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine header, source: %s\n" TOY_CC_RESET, source);
|
||||||
|
|
||||||
//cleanup and return
|
//cleanup and return
|
||||||
TOY_FREE_ARRAY(unsigned char, buffer, len);
|
free(buffer);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -309,12 +310,12 @@ int test_routine_header_and_values(Toy_Bucket** bucket) {
|
|||||||
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine code, source: %s\n" TOY_CC_RESET, source);
|
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine code, source: %s\n" TOY_CC_RESET, source);
|
||||||
|
|
||||||
//cleanup and return
|
//cleanup and return
|
||||||
TOY_FREE_ARRAY(unsigned char, buffer, len);
|
free(buffer);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//cleanup
|
//cleanup
|
||||||
TOY_FREE_ARRAY(unsigned char, buffer, len);
|
free(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -352,7 +353,7 @@ int test_routine_binary(Toy_Bucket** bucket) {
|
|||||||
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine header, source: %s\n" TOY_CC_RESET, source);
|
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine header, source: %s\n" TOY_CC_RESET, source);
|
||||||
|
|
||||||
//cleanup and return
|
//cleanup and return
|
||||||
TOY_FREE_ARRAY(unsigned char, buffer, len);
|
free(buffer);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -383,12 +384,12 @@ int test_routine_binary(Toy_Bucket** bucket) {
|
|||||||
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine code, source: %s\n" TOY_CC_RESET, source);
|
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine code, source: %s\n" TOY_CC_RESET, source);
|
||||||
|
|
||||||
//cleanup and return
|
//cleanup and return
|
||||||
TOY_FREE_ARRAY(unsigned char, buffer, len);
|
free(buffer);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//cleanup
|
//cleanup
|
||||||
TOY_FREE_ARRAY(unsigned char, buffer, len);
|
free(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
//produce a simple comparison
|
//produce a simple comparison
|
||||||
@@ -418,7 +419,7 @@ int test_routine_binary(Toy_Bucket** bucket) {
|
|||||||
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine header, source: %s\n" TOY_CC_RESET, source);
|
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine header, source: %s\n" TOY_CC_RESET, source);
|
||||||
|
|
||||||
//cleanup and return
|
//cleanup and return
|
||||||
TOY_FREE_ARRAY(unsigned char, buffer, len);
|
free(buffer);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -449,12 +450,12 @@ int test_routine_binary(Toy_Bucket** bucket) {
|
|||||||
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine code, source: %s\n" TOY_CC_RESET, source);
|
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine code, source: %s\n" TOY_CC_RESET, source);
|
||||||
|
|
||||||
//cleanup and return
|
//cleanup and return
|
||||||
TOY_FREE_ARRAY(unsigned char, buffer, len);
|
free(buffer);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//cleanup
|
//cleanup
|
||||||
TOY_FREE_ARRAY(unsigned char, buffer, len);
|
free(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
//produce a simple comparison
|
//produce a simple comparison
|
||||||
@@ -484,7 +485,7 @@ int test_routine_binary(Toy_Bucket** bucket) {
|
|||||||
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine header, source: %s\n" TOY_CC_RESET, source);
|
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine header, source: %s\n" TOY_CC_RESET, source);
|
||||||
|
|
||||||
//cleanup and return
|
//cleanup and return
|
||||||
TOY_FREE_ARRAY(unsigned char, buffer, len);
|
free(buffer);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -520,12 +521,12 @@ int test_routine_binary(Toy_Bucket** bucket) {
|
|||||||
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine code, source: %s\n" TOY_CC_RESET, source);
|
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine code, source: %s\n" TOY_CC_RESET, source);
|
||||||
|
|
||||||
//cleanup and return
|
//cleanup and return
|
||||||
TOY_FREE_ARRAY(unsigned char, buffer, len);
|
free(buffer);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//cleanup
|
//cleanup
|
||||||
TOY_FREE_ARRAY(unsigned char, buffer, len);
|
free(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
//produce a more complex algorithm
|
//produce a more complex algorithm
|
||||||
@@ -555,7 +556,7 @@ int test_routine_binary(Toy_Bucket** bucket) {
|
|||||||
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine header, source: %s\n" TOY_CC_RESET, source);
|
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine header, source: %s\n" TOY_CC_RESET, source);
|
||||||
|
|
||||||
//cleanup and return
|
//cleanup and return
|
||||||
TOY_FREE_ARRAY(unsigned char, buffer, len);
|
free(buffer);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -612,12 +613,12 @@ int test_routine_binary(Toy_Bucket** bucket) {
|
|||||||
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine code, source: %s\n" TOY_CC_RESET, source);
|
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine code, source: %s\n" TOY_CC_RESET, source);
|
||||||
|
|
||||||
//cleanup and return
|
//cleanup and return
|
||||||
TOY_FREE_ARRAY(unsigned char, buffer, len);
|
free(buffer);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//cleanup
|
//cleanup
|
||||||
TOY_FREE_ARRAY(unsigned char, buffer, len);
|
free(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -628,10 +629,9 @@ int main() {
|
|||||||
int total = 0, res = 0;
|
int total = 0, res = 0;
|
||||||
|
|
||||||
{
|
{
|
||||||
Toy_Bucket* bucket = NULL;
|
Toy_Bucket* bucket = Toy_allocateBucket(sizeof(Toy_Ast) * 32);
|
||||||
TOY_BUCKET_INIT(Toy_Ast, bucket, 32);
|
|
||||||
res = test_routine_header_and_values(&bucket);
|
res = test_routine_header_and_values(&bucket);
|
||||||
TOY_BUCKET_FREE(bucket);
|
Toy_freeBucket(&bucket);
|
||||||
if (res == 0) {
|
if (res == 0) {
|
||||||
printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET);
|
printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET);
|
||||||
}
|
}
|
||||||
@@ -639,10 +639,9 @@ int main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
Toy_Bucket* bucket = NULL;
|
Toy_Bucket* bucket = Toy_allocateBucket(sizeof(Toy_Ast) * 32);
|
||||||
TOY_BUCKET_INIT(Toy_Ast, bucket, 32);
|
|
||||||
res = test_routine_binary(&bucket);
|
res = test_routine_binary(&bucket);
|
||||||
TOY_BUCKET_FREE(bucket);
|
Toy_freeBucket(&bucket);
|
||||||
if (res == 0) {
|
if (res == 0) {
|
||||||
printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET);
|
printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,40 +3,40 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
int test_stack_with_init() {
|
int test_stack_basics() {
|
||||||
//init and free the stack
|
//allocate and free the stack
|
||||||
{
|
{
|
||||||
Toy_Stack stack;
|
Toy_Stack* stack = Toy_allocateStack();
|
||||||
Toy_initStack(&stack);
|
|
||||||
|
|
||||||
//check if it worked
|
//check if it worked
|
||||||
if (
|
if (
|
||||||
stack.ptr != NULL ||
|
stack == NULL ||
|
||||||
stack.capacity != 0 ||
|
stack->capacity != 64 ||
|
||||||
stack.count != 0)
|
stack->count != 0)
|
||||||
{
|
{
|
||||||
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to init Toy_Stack\n" TOY_CC_RESET);
|
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to allocate Toy_Stack\n" TOY_CC_RESET);
|
||||||
|
Toy_freeStack(stack);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Toy_freeStack(&stack);
|
Toy_freeStack(stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
//push, peek and pop stack
|
//push, peek and pop stack
|
||||||
{
|
{
|
||||||
Toy_Stack stack;
|
Toy_Stack* stack = Toy_allocateStack();
|
||||||
Toy_initStack(&stack);
|
|
||||||
|
|
||||||
//check if it worked (push)
|
//check if it worked (push)
|
||||||
Toy_pushStack(&stack, TOY_VALUE_TO_INTEGER(42));
|
Toy_pushStack(&stack, TOY_VALUE_TO_INTEGER(42));
|
||||||
Toy_pushStack(&stack, TOY_VALUE_TO_INTEGER(69));
|
Toy_pushStack(&stack, TOY_VALUE_TO_INTEGER(69));
|
||||||
Toy_pushStack(&stack, TOY_VALUE_TO_INTEGER(420));
|
Toy_pushStack(&stack, TOY_VALUE_TO_INTEGER(420));
|
||||||
if (
|
if (
|
||||||
stack.ptr == NULL ||
|
stack == NULL ||
|
||||||
stack.capacity != 64 ||
|
stack->capacity != 64 ||
|
||||||
stack.count != 3)
|
stack->count != 3)
|
||||||
{
|
{
|
||||||
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to push Toy_Stack\n" TOY_CC_RESET);
|
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to push Toy_Stack\n" TOY_CC_RESET);
|
||||||
|
Toy_freeStack(stack);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,19 +47,21 @@ int test_stack_with_init() {
|
|||||||
TOY_VALUE_AS_INTEGER(top1) != 420)
|
TOY_VALUE_AS_INTEGER(top1) != 420)
|
||||||
{
|
{
|
||||||
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to peek Toy_Stack\n" TOY_CC_RESET);
|
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to peek Toy_Stack\n" TOY_CC_RESET);
|
||||||
|
Toy_freeStack(stack);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//check if it worked (pop)
|
//check if it worked (pop)
|
||||||
Toy_Value top2 = Toy_popStack(&stack);
|
Toy_Value top2 = Toy_popStack(&stack);
|
||||||
if (
|
if (
|
||||||
stack.ptr == NULL ||
|
stack == NULL ||
|
||||||
stack.capacity != 64 ||
|
stack->capacity != 64 ||
|
||||||
stack.count != 2 ||
|
stack->count != 2 ||
|
||||||
TOY_VALUE_IS_INTEGER(top2) != true ||
|
TOY_VALUE_IS_INTEGER(top2) != true ||
|
||||||
TOY_VALUE_AS_INTEGER(top2) != 420)
|
TOY_VALUE_AS_INTEGER(top2) != 420)
|
||||||
{
|
{
|
||||||
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to pop Toy_Stack\n" TOY_CC_RESET);
|
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to pop Toy_Stack\n" TOY_CC_RESET);
|
||||||
|
Toy_freeStack(stack);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,86 +72,38 @@ int test_stack_with_init() {
|
|||||||
TOY_VALUE_AS_INTEGER(top3) != 69)
|
TOY_VALUE_AS_INTEGER(top3) != 69)
|
||||||
{
|
{
|
||||||
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to pop then peek Toy_Stack\n" TOY_CC_RESET);
|
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to pop then peek Toy_Stack\n" TOY_CC_RESET);
|
||||||
|
Toy_freeStack(stack);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Toy_freeStack(&stack);
|
Toy_freeStack(stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int test_stack_with_preallocate() {
|
int test_stack_stress() {
|
||||||
//preallocate and free the stack
|
//stress the stack's contents
|
||||||
{
|
{
|
||||||
Toy_Stack stack;
|
Toy_Stack* stack = Toy_allocateStack();
|
||||||
Toy_preallocateStack(&stack);
|
|
||||||
|
//allocate 500 values
|
||||||
|
for (int i = 0; i < 500; i++) {
|
||||||
|
Toy_pushStack(&stack, TOY_VALUE_TO_INTEGER(i));
|
||||||
|
}
|
||||||
|
|
||||||
//check if it worked
|
//check if it worked
|
||||||
if (
|
if (
|
||||||
stack.ptr == NULL ||
|
stack == NULL ||
|
||||||
stack.capacity != 64 ||
|
stack->capacity != 512 ||
|
||||||
stack.count != 0)
|
stack->count != 500)
|
||||||
{
|
{
|
||||||
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to preallocate Toy_Stack\n" TOY_CC_RESET);
|
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to stress the Toy_Stack\n" TOY_CC_RESET);
|
||||||
|
Toy_freeStack(stack);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Toy_freeStack(&stack);
|
Toy_freeStack(stack);
|
||||||
}
|
|
||||||
|
|
||||||
//push, peek and pop stack
|
|
||||||
{
|
|
||||||
Toy_Stack stack;
|
|
||||||
Toy_initStack(&stack);
|
|
||||||
|
|
||||||
//check if it worked (push)
|
|
||||||
Toy_pushStack(&stack, TOY_VALUE_TO_INTEGER(42));
|
|
||||||
Toy_pushStack(&stack, TOY_VALUE_TO_INTEGER(69));
|
|
||||||
Toy_pushStack(&stack, TOY_VALUE_TO_INTEGER(420));
|
|
||||||
if (
|
|
||||||
stack.ptr == NULL ||
|
|
||||||
stack.capacity != 64 ||
|
|
||||||
stack.count != 3)
|
|
||||||
{
|
|
||||||
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to push Toy_Stack\n" TOY_CC_RESET);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
//check if it worked (peek)
|
|
||||||
Toy_Value top1 = Toy_peekStack(&stack);
|
|
||||||
if (
|
|
||||||
TOY_VALUE_IS_INTEGER(top1) != true ||
|
|
||||||
TOY_VALUE_AS_INTEGER(top1) != 420)
|
|
||||||
{
|
|
||||||
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to peek Toy_Stack\n" TOY_CC_RESET);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
//check if it worked (pop)
|
|
||||||
Toy_Value top2 = Toy_popStack(&stack);
|
|
||||||
if (
|
|
||||||
stack.ptr == NULL ||
|
|
||||||
stack.capacity != 64 ||
|
|
||||||
stack.count != 2 ||
|
|
||||||
TOY_VALUE_IS_INTEGER(top2) != true ||
|
|
||||||
TOY_VALUE_AS_INTEGER(top2) != 420)
|
|
||||||
{
|
|
||||||
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to pop Toy_Stack\n" TOY_CC_RESET);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
//check if it worked (post-pop peek)
|
|
||||||
Toy_Value top3 = Toy_peekStack(&stack);
|
|
||||||
if (
|
|
||||||
TOY_VALUE_IS_INTEGER(top3) != true ||
|
|
||||||
TOY_VALUE_AS_INTEGER(top3) != 69)
|
|
||||||
{
|
|
||||||
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to pop then peek Toy_Stack\n" TOY_CC_RESET);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
Toy_freeStack(&stack);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -160,7 +114,7 @@ int main() {
|
|||||||
int total = 0, res = 0;
|
int total = 0, res = 0;
|
||||||
|
|
||||||
{
|
{
|
||||||
res = test_stack_with_init();
|
res = test_stack_basics();
|
||||||
if (res == 0) {
|
if (res == 0) {
|
||||||
printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET);
|
printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET);
|
||||||
}
|
}
|
||||||
@@ -168,7 +122,7 @@ int main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
res = test_stack_with_preallocate();
|
res = test_stack_stress();
|
||||||
if (res == 0) {
|
if (res == 0) {
|
||||||
printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET);
|
printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
#include "toy_string.h"
|
#include "toy_string.h"
|
||||||
#include "toy_console_colors.h"
|
#include "toy_console_colors.h"
|
||||||
|
|
||||||
#include "toy_memory.h"
|
#include "toy_bucket.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
int test_sizeof_string_64bit() {
|
int test_sizeof_string_64bit() {
|
||||||
@@ -34,8 +35,7 @@ int test_string_allocation() {
|
|||||||
//allocate a single string from a c-string
|
//allocate a single string from a c-string
|
||||||
{
|
{
|
||||||
//setup
|
//setup
|
||||||
Toy_Bucket* bucket = NULL;
|
Toy_Bucket* bucket = Toy_allocateBucket(1024);
|
||||||
Toy_initBucket(&bucket, 1024);
|
|
||||||
|
|
||||||
const char* cstring = "Hello world";
|
const char* cstring = "Hello world";
|
||||||
Toy_String* str = Toy_createString(&bucket, cstring);
|
Toy_String* str = Toy_createString(&bucket, cstring);
|
||||||
@@ -77,8 +77,7 @@ int test_string_allocation() {
|
|||||||
//copy and deep copy a string
|
//copy and deep copy a string
|
||||||
{
|
{
|
||||||
//setup
|
//setup
|
||||||
Toy_Bucket* bucket = NULL;
|
Toy_Bucket* bucket = Toy_allocateBucket(1024);
|
||||||
Toy_initBucket(&bucket, 1024);
|
|
||||||
|
|
||||||
const char* cstring = "Hello world";
|
const char* cstring = "Hello world";
|
||||||
Toy_String* str = Toy_createString(&bucket, cstring);
|
Toy_String* str = Toy_createString(&bucket, cstring);
|
||||||
@@ -104,8 +103,7 @@ int test_string_allocation() {
|
|||||||
//allocate a zero-length string
|
//allocate a zero-length string
|
||||||
{
|
{
|
||||||
//setup
|
//setup
|
||||||
Toy_Bucket* bucket = NULL;
|
Toy_Bucket* bucket = Toy_allocateBucket(1024);
|
||||||
Toy_initBucket(&bucket, 1024);
|
|
||||||
|
|
||||||
const char* cstring = "";
|
const char* cstring = "";
|
||||||
Toy_String* str = Toy_createString(&bucket, cstring);
|
Toy_String* str = Toy_createString(&bucket, cstring);
|
||||||
@@ -133,8 +131,7 @@ int test_string_allocation() {
|
|||||||
|
|
||||||
int test_string_concatenation() {
|
int test_string_concatenation() {
|
||||||
//one big bucket o' fun
|
//one big bucket o' fun
|
||||||
Toy_Bucket* bucket = NULL;
|
Toy_Bucket* bucket = Toy_allocateBucket(1024);
|
||||||
Toy_initBucket(&bucket, 1024);
|
|
||||||
|
|
||||||
//concatenate two strings, and check the refcounts
|
//concatenate two strings, and check the refcounts
|
||||||
{
|
{
|
||||||
@@ -191,12 +188,12 @@ int test_string_concatenation() {
|
|||||||
strcmp(buffer, "Hello world") != 0)
|
strcmp(buffer, "Hello world") != 0)
|
||||||
{
|
{
|
||||||
fprintf(stderr, TOY_CC_ERROR "ERROR: Failed to get the raw buffer from concatenated string\n" TOY_CC_RESET);
|
fprintf(stderr, TOY_CC_ERROR "ERROR: Failed to get the raw buffer from concatenated string\n" TOY_CC_RESET);
|
||||||
TOY_FREE_ARRAY(char, buffer, result->length + 1);
|
free(buffer);
|
||||||
Toy_freeBucket(&bucket);
|
Toy_freeBucket(&bucket);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
TOY_FREE_ARRAY(char, buffer, result->length + 1);
|
free(buffer);
|
||||||
Toy_freeString(result);
|
Toy_freeString(result);
|
||||||
Toy_freeString(first);
|
Toy_freeString(first);
|
||||||
Toy_freeString(second);
|
Toy_freeString(second);
|
||||||
@@ -224,8 +221,7 @@ int test_string_with_stressed_bucket() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
//setup
|
//setup
|
||||||
Toy_Bucket* bucket = NULL;
|
Toy_Bucket* bucket = Toy_allocateBucket(128);//deliberately too much data for one bucket
|
||||||
Toy_initBucket(&bucket, 128); //deliberately too short for one bucket
|
|
||||||
|
|
||||||
//stress
|
//stress
|
||||||
Toy_String* str = Toy_createString(&bucket, testData[0]);
|
Toy_String* str = Toy_createString(&bucket, testData[0]);
|
||||||
@@ -250,7 +246,7 @@ int test_string_with_stressed_bucket() {
|
|||||||
strlen(buffer) != 36)
|
strlen(buffer) != 36)
|
||||||
{
|
{
|
||||||
fprintf(stderr, TOY_CC_ERROR "ERROR: Unexpected state of the raw buffer after string stress test: '%s'\n" TOY_CC_RESET, buffer);
|
fprintf(stderr, TOY_CC_ERROR "ERROR: Unexpected state of the raw buffer after string stress test: '%s'\n" TOY_CC_RESET, buffer);
|
||||||
Toy_reallocate(buffer, 0, 0); //direct call to free, regardless of size
|
free(buffer);
|
||||||
Toy_freeBucket(&bucket);
|
Toy_freeBucket(&bucket);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -258,13 +254,13 @@ int test_string_with_stressed_bucket() {
|
|||||||
if (bucket->next == NULL) //just to make sure
|
if (bucket->next == NULL) //just to make sure
|
||||||
{
|
{
|
||||||
fprintf(stderr, TOY_CC_ERROR "ERROR: Unexpected state of the bucket after string stress test\n" TOY_CC_RESET);
|
fprintf(stderr, TOY_CC_ERROR "ERROR: Unexpected state of the bucket after string stress test\n" TOY_CC_RESET);
|
||||||
Toy_reallocate(buffer, 0, 0); //direct call to free, regardless of size
|
free(buffer);
|
||||||
Toy_freeBucket(&bucket);
|
Toy_freeBucket(&bucket);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//clean up
|
//clean up
|
||||||
TOY_FREE_ARRAY(char, buffer, str->length);
|
free(buffer);
|
||||||
Toy_freeBucket(&bucket);
|
Toy_freeBucket(&bucket);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -41,7 +41,6 @@ int test_setup_and_teardown(Toy_Bucket** bucket) {
|
|||||||
|
|
||||||
//run the setup
|
//run the setup
|
||||||
Toy_VM vm;
|
Toy_VM vm;
|
||||||
Toy_initVM(&vm);
|
|
||||||
Toy_bindVM(&vm, bc.ptr, bc.capacity);
|
Toy_bindVM(&vm, bc.ptr, bc.capacity);
|
||||||
|
|
||||||
//check the header size
|
//check the header size
|
||||||
@@ -93,14 +92,14 @@ int test_simple_execution(Toy_Bucket** bucket) {
|
|||||||
|
|
||||||
//run the setup
|
//run the setup
|
||||||
Toy_VM vm;
|
Toy_VM vm;
|
||||||
Toy_initVM(&vm);
|
|
||||||
Toy_bindVM(&vm, bc.ptr, bc.capacity);
|
Toy_bindVM(&vm, bc.ptr, bc.capacity);
|
||||||
|
|
||||||
//run
|
//run
|
||||||
Toy_runVM(&vm);
|
Toy_runVM(&vm);
|
||||||
|
|
||||||
//check the final state of the stack
|
//check the final state of the stack
|
||||||
if (vm.stack.count != 1 ||
|
if (vm.stack == NULL ||
|
||||||
|
vm.stack->count != 1 ||
|
||||||
TOY_VALUE_IS_INTEGER( Toy_peekStack(&vm.stack) ) != true ||
|
TOY_VALUE_IS_INTEGER( Toy_peekStack(&vm.stack) ) != true ||
|
||||||
TOY_VALUE_AS_INTEGER( Toy_peekStack(&vm.stack) ) != 21
|
TOY_VALUE_AS_INTEGER( Toy_peekStack(&vm.stack) ) != 21
|
||||||
)
|
)
|
||||||
@@ -124,10 +123,9 @@ int main() {
|
|||||||
int total = 0, res = 0;
|
int total = 0, res = 0;
|
||||||
|
|
||||||
{
|
{
|
||||||
Toy_Bucket* bucket = NULL;
|
Toy_Bucket* bucket = Toy_allocateBucket(sizeof(Toy_Ast) * 32);
|
||||||
TOY_BUCKET_INIT(Toy_Ast, bucket, 32);
|
|
||||||
res = test_setup_and_teardown(&bucket);
|
res = test_setup_and_teardown(&bucket);
|
||||||
TOY_BUCKET_FREE(bucket);
|
Toy_freeBucket(&bucket);
|
||||||
if (res == 0) {
|
if (res == 0) {
|
||||||
printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET);
|
printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET);
|
||||||
}
|
}
|
||||||
@@ -135,10 +133,9 @@ int main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
Toy_Bucket* bucket = NULL;
|
Toy_Bucket* bucket = Toy_allocateBucket(sizeof(Toy_Ast) * 32);
|
||||||
TOY_BUCKET_INIT(Toy_Ast, bucket, 32);
|
|
||||||
res = test_simple_execution(&bucket);
|
res = test_simple_execution(&bucket);
|
||||||
TOY_BUCKET_FREE(bucket);
|
Toy_freeBucket(&bucket);
|
||||||
if (res == 0) {
|
if (res == 0) {
|
||||||
printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET);
|
printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user