Add a function for preparing for execution.

This commit is contained in:
Danila Fedorin 2018-05-01 21:48:15 -07:00
parent 51e9a11a1f
commit 1e215ecfa5
2 changed files with 124 additions and 7 deletions

View File

@ -31,6 +31,7 @@ struct libab_s {
* to run a tree.
*/
libab_interpreter intr;
/**
* The table used to store top-level
* things like functions and operators.
@ -41,6 +42,22 @@ struct libab_s {
* The allocator used to construct number instances.
*/
libab_impl impl;
/**
* The number type instance.
*/
libab_ref type_num;
/**
* The function list type instance.
*/
libab_ref type_function_list;
/**
* Internal; the number basetype. This cannot be a static
* variable like other built-in types because it has a free function
* specified by the user.
*/
libab_basetype basetype_num;
};
typedef struct libab_s libab;
@ -49,9 +66,12 @@ typedef struct libab_s libab;
* Initializes the libabacus struct as well
* as all its internal structures such as the lexer.
* @param ab the libabacus instance used to keep state.
* @param parse_function function used to parse a number.
* @param free_function function used to free the parsed number.
* @return the result of the initialization.
*/
libab_result libab_init(libab* ab);
libab_result libab_init(libab* ab, void* (*parse_function)(const char*),
void (*free_function)(void*));
/**
* Registers an operator with libabacus.
* @param ab the libabacus instance to reigster the operator with.

View File

@ -4,26 +4,50 @@
#include "util.h"
#include <stdlib.h>
libab_result libab_init(libab* ab) {
libab_result _prepare_types(libab* ab, void (*free_function)(void*));
libab_result libab_init(libab* ab, void* (*parse_function)(const char*),
void (*free_function)(void*)) {
int parser_initialized = 0;
int lexer_initialized = 0;
libab_ref null_ref;
libab_result result;
libab_ref_null(&null_ref);
libab_ref_null(&ab->type_num);
libab_ref_null(&ab->type_function_list);
ab->impl.parse_num = parse_function;
result = libab_create_table(&ab->table, &null_ref);
if (result == LIBAB_SUCCESS) {
result = _prepare_types(ab, free_function);
}
if(result == LIBAB_SUCCESS) {
parser_initialized = 1;
libab_parser_init(&ab->parser, &ab->table);
libab_interpreter_init(&ab->intr, &ab->table, &ab->impl);
result = libab_lexer_init(&ab->lexer);
}
if (result == LIBAB_SUCCESS) {
lexer_initialized = 1;
result = libab_register_reserved_operators(&ab->lexer);
}
if (result != LIBAB_SUCCESS) {
libab_ref_free(&ab->table);
libab_parser_free(&ab->parser);
libab_lexer_free(&ab->lexer);
libab_ref_free(&ab->type_num);
libab_ref_free(&ab->type_function_list);
if(parser_initialized) {
libab_parser_free(&ab->parser);
libab_interpreter_free(&ab->intr);
}
if(lexer_initialized) {
libab_lexer_free(&ab->lexer);
}
}
libab_ref_free(&null_ref);
@ -40,7 +64,7 @@ void _sanitize(char* to, const char* from, size_t buffer_size) {
to[index] = '\0';
}
void _initialize_behavior(libab* ab, libab_behavior* behavior, libab_ref* type,
void _initialize_behavior(libab_behavior* behavior, libab_ref* type,
libab_function_ptr func) {
behavior->impl.variant = BIMPL_INTERNAL;
behavior->impl.data_u.internal = func;
@ -59,7 +83,7 @@ libab_result _register_operator(libab* ab, const char* op,
new_entry->data_u.op.precedence = precedence;
new_entry->data_u.op.associativity = associativity;
new_entry->data_u.op.type = token_type;
_initialize_behavior(ab, &(new_entry->data_u.op.behavior), type, func);
_initialize_behavior(&(new_entry->data_u.op.behavior), type, func);
} else {
result = LIBAB_MALLOC;
}
@ -110,7 +134,7 @@ libab_result libab_register_function(libab* ab, const char* name,
libab_table_entry* new_entry;
if ((new_entry = malloc(sizeof(*new_entry)))) {
new_entry->variant = ENTRY_FUN;
_initialize_behavior(ab, &(new_entry->data_u.function.behavior), type,
_initialize_behavior(&(new_entry->data_u.function.behavior), type,
func);
} else {
result = LIBAB_MALLOC;
@ -149,6 +173,77 @@ libab_result libab_register_basetype(libab* ab, const char* name,
return result;
}
void _free_function_list(void* function_list) {
libab_function_list_free(function_list);
free(function_list);
}
static libab_basetype _basetype_function_list = {
_free_function_list,
NULL,
0
};
void _free_function(void* function) {
libab_function_free(function);
free(function);
}
static libab_basetype_param _basetype_function_params[] = {
{ BT_LIST, NULL }
};
static libab_basetype _basetype_function = {
_free_function,
_basetype_function_params,
1
};
libab_result _prepare_types(libab* ab, void (*free_function)(void*)) {
libab_result result = LIBAB_SUCCESS;
ab->basetype_num.count = 0;
ab->basetype_num.params = NULL;
ab->basetype_num.free_function = free_function;
libab_ref_null(&ab->type_num);
libab_ref_null(&ab->type_function_list);
if (result == LIBAB_SUCCESS) {
libab_ref_free(&ab->type_num);
result = libab_instantiate_basetype(&ab->basetype_num,
&ab->type_num, 0);
}
if (result == LIBAB_SUCCESS) {
libab_ref_free(&ab->type_function_list);
result = libab_instantiate_basetype(&_basetype_function_list,
&ab->type_function_list, 0);
}
if (result == LIBAB_SUCCESS) {
result = libab_register_basetype(ab, "num", &ab->basetype_num);
}
if (result == LIBAB_SUCCESS) {
result = libab_register_basetype(ab, "function", &_basetype_function);
}
if (result == LIBAB_SUCCESS) {
result = libab_register_basetype(ab, "function_list",
&_basetype_function_list);
}
if(result != LIBAB_SUCCESS) {
libab_ref_free(&ab->type_num);
libab_ref_free(&ab->type_function_list);
libab_ref_null(&ab->type_num);
libab_ref_null(&ab->type_function_list);
}
return result;
}
libab_result libab_create_type(libab* ab, libab_ref* into, const char* type) {
libab_result result;
ll tokens;
@ -164,6 +259,8 @@ libab_result libab_create_type(libab* ab, libab_ref* into, const char* type) {
libab_result libab_free(libab* ab) {
libab_ref_free(&ab->table);
libab_ref_free(&ab->type_num);
libab_ref_free(&ab->type_function_list);
libab_parser_free(&ab->parser);
libab_interpreter_free(&ab->intr);
return libab_lexer_free(&ab->lexer);