Compare commits
No commits in common. "22b738a4f076d6c3ce3adca45be01db0284fdf8a" and "5492aa6f63a2d008e13cadabaf0f79ba8785be70" have entirely different histories.
22b738a4f0
...
5492aa6f63
@ -8,7 +8,7 @@ project(libabacus)
|
|||||||
|
|
||||||
add_compile_options(-pedantic -Wall)
|
add_compile_options(-pedantic -Wall)
|
||||||
|
|
||||||
add_library(abacus STATIC src/lexer.c src/util.c src/table.c src/parser.c src/libabacus.c src/tree.c src/debug.c src/parsetype.c src/reserved.c src/trie.c src/refcount.c src/ref_vec.c src/ref_trie.c src/basetype.c src/value.c src/custom.c src/interpreter.c src/function_list.c src/free_functions.c)
|
add_library(abacus STATIC src/lexer.c src/util.c src/table.c src/parser.c src/libabacus.c src/tree.c src/debug.c src/parsetype.c src/reserved.c src/trie.c src/refcount.c src/ref_vec.c src/ref_trie.c src/basetype.c src/value.c src/custom.c src/interpreter.c src/function_list.c)
|
||||||
add_executable(libabacus src/main.c)
|
add_executable(libabacus src/main.c)
|
||||||
add_executable(interactive src/interactive.c)
|
add_executable(interactive src/interactive.c)
|
||||||
add_subdirectory(external/liblex)
|
add_subdirectory(external/liblex)
|
||||||
|
@ -1,43 +0,0 @@
|
|||||||
#ifndef LIBABACUS_FREE_FUNCTIONS_H
|
|
||||||
#define LIBABACUS_FREE_FUNCTIONS_H
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Free functions. Because a lot of the reference
|
|
||||||
* counting operations require free functions,
|
|
||||||
* and redeclaring them in mutliple files makes no
|
|
||||||
* sense (also, it doesn't link :^) ), we
|
|
||||||
* put them all here.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Frees a libab_function.
|
|
||||||
* @param func the function to free.
|
|
||||||
*/
|
|
||||||
void free_function(void* func);
|
|
||||||
/**
|
|
||||||
* Frees a libab_function_list.
|
|
||||||
* @param func_list the function list to free.
|
|
||||||
*/
|
|
||||||
void free_function_list(void* func_list);
|
|
||||||
/**
|
|
||||||
* Frees a unit. This is a no-op.
|
|
||||||
* @param unit the unit to free.
|
|
||||||
*/
|
|
||||||
void free_unit(void* unit);
|
|
||||||
/**
|
|
||||||
* Frees a parsetype.
|
|
||||||
* @param parsetype the parsetype to free.
|
|
||||||
*/
|
|
||||||
void free_parsetype(void* parsetype);
|
|
||||||
/**
|
|
||||||
* Frees a table.
|
|
||||||
* @param table the table to free.
|
|
||||||
*/
|
|
||||||
void free_table(void* table);
|
|
||||||
/**
|
|
||||||
* Frees a value.
|
|
||||||
* @param value the value to free.
|
|
||||||
*/
|
|
||||||
void free_value(void* value);
|
|
||||||
|
|
||||||
#endif
|
|
@ -8,16 +8,6 @@
|
|||||||
|
|
||||||
struct libab_s;
|
struct libab_s;
|
||||||
|
|
||||||
/**
|
|
||||||
* Scope moe used to determine how the interpreter handles
|
|
||||||
* scoping.
|
|
||||||
*/
|
|
||||||
enum libab_interpreter_scope_mode_e {
|
|
||||||
SCOPE_NORMAL,
|
|
||||||
SCOPE_FORCE,
|
|
||||||
SCOPE_NONE
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The interpreter struct used to encapsulate
|
* The interpreter struct used to encapsulate
|
||||||
* any interpreter-specific data.
|
* any interpreter-specific data.
|
||||||
@ -30,7 +20,6 @@ struct libab_interpreter_s {
|
|||||||
libab_ref value_unit;
|
libab_ref value_unit;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef enum libab_interpreter_scope_mode_e libab_interpreter_scope_mode;
|
|
||||||
typedef struct libab_interpreter_s libab_interpreter;
|
typedef struct libab_interpreter_s libab_interpreter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -43,13 +32,11 @@ libab_result libab_interpreter_init(libab_interpreter* intr, struct libab_s* ab)
|
|||||||
* Uses the interpreter to run the given parse tree.
|
* Uses the interpreter to run the given parse tree.
|
||||||
* @param intr the interpreter to use to run the code.
|
* @param intr the interpreter to use to run the code.
|
||||||
* @param tree the tree to run.
|
* @param tree the tree to run.
|
||||||
* @param mode the scope mode to use.
|
|
||||||
* @param into the reference into which the result of the execution will be
|
* @param into the reference into which the result of the execution will be
|
||||||
* stored.
|
* stored.
|
||||||
* @return the result of the execution.
|
* @return the result of the execution.
|
||||||
*/
|
*/
|
||||||
libab_result libab_interpreter_run(libab_interpreter* intr, libab_tree* tree,
|
libab_result libab_interpreter_run(libab_interpreter* intr, libab_tree* tree,
|
||||||
libab_interpreter_scope_mode mode,
|
|
||||||
libab_ref* into);
|
libab_ref* into);
|
||||||
/**
|
/**
|
||||||
* Calls a function with the given parameters.
|
* Calls a function with the given parameters.
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
#include "refcount.h"
|
#include "refcount.h"
|
||||||
#include "result.h"
|
#include "result.h"
|
||||||
#include <stdarg.h>
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A node in the trie.
|
* A node in the trie.
|
||||||
@ -76,16 +75,6 @@ libab_result libab_ref_trie_put(libab_ref_trie* trie, const char* key,
|
|||||||
*/
|
*/
|
||||||
void libab_ref_trie_get(const libab_ref_trie* trie, const char* key,
|
void libab_ref_trie_get(const libab_ref_trie* trie, const char* key,
|
||||||
libab_ref* into);
|
libab_ref* into);
|
||||||
/**
|
|
||||||
* Calls the given function on every element in the reference-counted
|
|
||||||
* tree.
|
|
||||||
* @param trie the trie to run the operation on.
|
|
||||||
* @param func the function to call.
|
|
||||||
* return the result of the functions, and any necessary allocations.
|
|
||||||
*/
|
|
||||||
libab_result libab_ref_trie_foreach(const libab_ref_trie* trie,
|
|
||||||
libab_result (*func)(const libab_ref*, const char*, va_list),
|
|
||||||
...);
|
|
||||||
/**
|
/**
|
||||||
* Releases the trie, decrementing the refcounts of all
|
* Releases the trie, decrementing the refcounts of all
|
||||||
* the values stored inside.
|
* the values stored inside.
|
||||||
|
@ -1,31 +0,0 @@
|
|||||||
#include "free_functions.h"
|
|
||||||
#include "custom.h"
|
|
||||||
#include "function_list.h"
|
|
||||||
#include "parsetype.h"
|
|
||||||
#include "table.h"
|
|
||||||
#include "value.h"
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
void free_function(void* func) {
|
|
||||||
libab_function_free(func);
|
|
||||||
free(func);
|
|
||||||
}
|
|
||||||
void free_function_list(void* function_list) {
|
|
||||||
libab_function_list_free(function_list);
|
|
||||||
free(function_list);
|
|
||||||
}
|
|
||||||
void free_unit(void* unit) {
|
|
||||||
|
|
||||||
}
|
|
||||||
void free_parsetype(void* parsetype) {
|
|
||||||
libab_parsetype_free(parsetype);
|
|
||||||
free(parsetype);
|
|
||||||
}
|
|
||||||
void free_table(void* table) {
|
|
||||||
libab_table_free(table);
|
|
||||||
free(table);
|
|
||||||
}
|
|
||||||
void free_value(void* value) {
|
|
||||||
libab_value_free(value);
|
|
||||||
free(value);
|
|
||||||
}
|
|
@ -1,7 +1,6 @@
|
|||||||
#include "libabacus.h"
|
#include "libabacus.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "value.h"
|
#include "value.h"
|
||||||
#include "free_functions.h"
|
|
||||||
|
|
||||||
libab_result libab_interpreter_init(libab_interpreter* intr, libab* ab) {
|
libab_result libab_interpreter_init(libab_interpreter* intr, libab* ab) {
|
||||||
libab_result result;
|
libab_result result;
|
||||||
@ -74,28 +73,6 @@ int _interpreter_type_contains_placeholders(libab_ref* type) {
|
|||||||
return placeholder;
|
return placeholder;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _interpreter_search_type_param(libab_ref_trie* params,
|
|
||||||
libab_ref* scope,
|
|
||||||
const char* name,
|
|
||||||
libab_ref* into) {
|
|
||||||
libab_ref_trie_get(params, name, into);
|
|
||||||
|
|
||||||
if(libab_ref_get(into) == NULL) {
|
|
||||||
libab_table_search_type_param(libab_ref_get(scope), name, into);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
libab_parsetype* _interpreter_search_type_param_raw(libab_ref_trie* params,
|
|
||||||
libab_ref* scope,
|
|
||||||
const char* name) {
|
|
||||||
libab_ref into;
|
|
||||||
libab_parsetype* to_return;
|
|
||||||
_interpreter_search_type_param(params, scope, name, &into);
|
|
||||||
to_return = libab_ref_get(&into);
|
|
||||||
libab_ref_free(&into);
|
|
||||||
return to_return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compares the two types, filling in any missing type parameters
|
* Compares the two types, filling in any missing type parameters
|
||||||
* in the respective type tries.
|
* in the respective type tries.
|
||||||
@ -108,13 +85,13 @@ libab_parsetype* _interpreter_search_type_param_raw(libab_ref_trie* params,
|
|||||||
libab_result _interpreter_compare_types(libab_ref* left_type,
|
libab_result _interpreter_compare_types(libab_ref* left_type,
|
||||||
libab_ref* right_type,
|
libab_ref* right_type,
|
||||||
libab_ref_trie* left_params,
|
libab_ref_trie* left_params,
|
||||||
libab_ref_trie* right_params,
|
libab_ref_trie* right_params) {
|
||||||
libab_ref* scope) {
|
|
||||||
libab_result result = LIBAB_SUCCESS;
|
libab_result result = LIBAB_SUCCESS;
|
||||||
int left_placeholder;
|
int left_placeholder;
|
||||||
int right_placeholder;
|
int right_placeholder;
|
||||||
libab_parsetype* left = libab_ref_get(left_type);
|
libab_parsetype* left = libab_ref_get(left_type);
|
||||||
libab_parsetype* right = libab_ref_get(right_type);
|
libab_parsetype* right = libab_ref_get(right_type);
|
||||||
|
libab_ref param_type;
|
||||||
|
|
||||||
left_placeholder = left->variant & LIBABACUS_TYPE_F_PLACE;
|
left_placeholder = left->variant & LIBABACUS_TYPE_F_PLACE;
|
||||||
right_placeholder = right->variant & LIBABACUS_TYPE_F_PLACE;
|
right_placeholder = right->variant & LIBABACUS_TYPE_F_PLACE;
|
||||||
@ -123,7 +100,9 @@ libab_result _interpreter_compare_types(libab_ref* left_type,
|
|||||||
} else {
|
} else {
|
||||||
if (left_placeholder) {
|
if (left_placeholder) {
|
||||||
const char* name = left->data_u.name;
|
const char* name = left->data_u.name;
|
||||||
left = _interpreter_search_type_param_raw(left_params, scope, name);
|
libab_ref_trie_get(left_params, name, ¶m_type);
|
||||||
|
left = libab_ref_get(¶m_type);
|
||||||
|
libab_ref_free(¶m_type);
|
||||||
if (left == NULL) {
|
if (left == NULL) {
|
||||||
if (!_interpreter_type_contains_placeholders(right_type)) {
|
if (!_interpreter_type_contains_placeholders(right_type)) {
|
||||||
result = libab_ref_trie_put(left_params, name, right_type);
|
result = libab_ref_trie_put(left_params, name, right_type);
|
||||||
@ -133,7 +112,9 @@ libab_result _interpreter_compare_types(libab_ref* left_type,
|
|||||||
}
|
}
|
||||||
} else if (right_placeholder) {
|
} else if (right_placeholder) {
|
||||||
const char* name = right->data_u.name;
|
const char* name = right->data_u.name;
|
||||||
right = _interpreter_search_type_param_raw(right_params, scope, name);
|
libab_ref_trie_get(right_params, name, ¶m_type);
|
||||||
|
right = libab_ref_get(¶m_type);
|
||||||
|
libab_ref_free(¶m_type);
|
||||||
if (right == NULL) {
|
if (right == NULL) {
|
||||||
if (!_interpreter_type_contains_placeholders(left_type)) {
|
if (!_interpreter_type_contains_placeholders(left_type)) {
|
||||||
result = libab_ref_trie_put(right_params, name, left_type);
|
result = libab_ref_trie_put(right_params, name, left_type);
|
||||||
@ -167,7 +148,7 @@ libab_result _interpreter_compare_types(libab_ref* left_type,
|
|||||||
libab_ref_vec_index(&left->children, index, &temp_left);
|
libab_ref_vec_index(&left->children, index, &temp_left);
|
||||||
libab_ref_vec_index(&right->children, index, &temp_right);
|
libab_ref_vec_index(&right->children, index, &temp_right);
|
||||||
result = _interpreter_compare_types(
|
result = _interpreter_compare_types(
|
||||||
&temp_left, &temp_right, left_params, right_params, scope);
|
&temp_left, &temp_right, left_params, right_params);
|
||||||
libab_ref_free(&temp_left);
|
libab_ref_free(&temp_left);
|
||||||
libab_ref_free(&temp_right);
|
libab_ref_free(&temp_right);
|
||||||
}
|
}
|
||||||
@ -178,6 +159,11 @@ libab_result _interpreter_compare_types(libab_ref* left_type,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _free_parsetype(void* parsetype) {
|
||||||
|
libab_parsetype_free(parsetype);
|
||||||
|
free(parsetype);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copies a type, substituting type parameters for their copies
|
* Copies a type, substituting type parameters for their copies
|
||||||
* from the parameter trie.
|
* from the parameter trie.
|
||||||
@ -188,7 +174,6 @@ libab_result _interpreter_compare_types(libab_ref* left_type,
|
|||||||
*/
|
*/
|
||||||
libab_result _interpreter_copy_resolved_type(libab_ref* type,
|
libab_result _interpreter_copy_resolved_type(libab_ref* type,
|
||||||
libab_ref_trie* params,
|
libab_ref_trie* params,
|
||||||
libab_ref* scope,
|
|
||||||
libab_ref* into) {
|
libab_ref* into) {
|
||||||
libab_result result = LIBAB_SUCCESS;
|
libab_result result = LIBAB_SUCCESS;
|
||||||
libab_parsetype* copy;
|
libab_parsetype* copy;
|
||||||
@ -196,7 +181,7 @@ libab_result _interpreter_copy_resolved_type(libab_ref* type,
|
|||||||
|
|
||||||
original = libab_ref_get(type);
|
original = libab_ref_get(type);
|
||||||
if (original->variant & LIBABACUS_TYPE_F_PLACE) {
|
if (original->variant & LIBABACUS_TYPE_F_PLACE) {
|
||||||
_interpreter_search_type_param(params, scope, original->data_u.name, into);
|
libab_ref_trie_get(params, original->data_u.name, into);
|
||||||
} else if ((copy = malloc(sizeof(*copy)))) {
|
} else if ((copy = malloc(sizeof(*copy)))) {
|
||||||
size_t index = 0;
|
size_t index = 0;
|
||||||
copy->variant = original->variant;
|
copy->variant = original->variant;
|
||||||
@ -209,7 +194,7 @@ libab_result _interpreter_copy_resolved_type(libab_ref* type,
|
|||||||
index++) {
|
index++) {
|
||||||
libab_ref_vec_index(&original->children, index, &temp_child);
|
libab_ref_vec_index(&original->children, index, &temp_child);
|
||||||
result = _interpreter_copy_resolved_type(&temp_child, params,
|
result = _interpreter_copy_resolved_type(&temp_child, params,
|
||||||
scope, &child_copy);
|
&child_copy);
|
||||||
if (result == LIBAB_SUCCESS) {
|
if (result == LIBAB_SUCCESS) {
|
||||||
result = libab_ref_vec_insert(©->children, &child_copy);
|
result = libab_ref_vec_insert(©->children, &child_copy);
|
||||||
}
|
}
|
||||||
@ -223,9 +208,9 @@ libab_result _interpreter_copy_resolved_type(libab_ref* type,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (result == LIBAB_SUCCESS) {
|
if (result == LIBAB_SUCCESS) {
|
||||||
result = libab_ref_new(into, copy, free_parsetype);
|
result = libab_ref_new(into, copy, _free_parsetype);
|
||||||
if (result != LIBAB_SUCCESS) {
|
if (result != LIBAB_SUCCESS) {
|
||||||
free_parsetype(copy);
|
_free_parsetype(copy);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -249,11 +234,10 @@ libab_result _interpreter_copy_resolved_type(libab_ref* type,
|
|||||||
*/
|
*/
|
||||||
libab_result _interpreter_resolve_type_params(libab_ref* type,
|
libab_result _interpreter_resolve_type_params(libab_ref* type,
|
||||||
libab_ref_trie* params,
|
libab_ref_trie* params,
|
||||||
libab_ref* scope,
|
|
||||||
libab_ref* into) {
|
libab_ref* into) {
|
||||||
libab_result result = LIBAB_SUCCESS;
|
libab_result result = LIBAB_SUCCESS;
|
||||||
if (_interpreter_type_contains_placeholders(type)) {
|
if (_interpreter_type_contains_placeholders(type)) {
|
||||||
result = _interpreter_copy_resolved_type(type, params, scope, into);
|
result = _interpreter_copy_resolved_type(type, params, into);
|
||||||
} else {
|
} else {
|
||||||
libab_ref_copy(type, into);
|
libab_ref_copy(type, into);
|
||||||
}
|
}
|
||||||
@ -270,9 +254,7 @@ libab_result _interpreter_resolve_type_params(libab_ref* type,
|
|||||||
*/
|
*/
|
||||||
libab_result _interpreter_check_types(libab_ref_vec* reference_types,
|
libab_result _interpreter_check_types(libab_ref_vec* reference_types,
|
||||||
libab_ref_vec* params,
|
libab_ref_vec* params,
|
||||||
libab_ref_vec* types,
|
libab_ref_vec* types) {
|
||||||
libab_ref* scope,
|
|
||||||
libab_ref_trie* param_map) {
|
|
||||||
libab_result result = LIBAB_SUCCESS;
|
libab_result result = LIBAB_SUCCESS;
|
||||||
libab_ref_trie function_params;
|
libab_ref_trie function_params;
|
||||||
|
|
||||||
@ -295,11 +277,11 @@ libab_result _interpreter_check_types(libab_ref_vec* reference_types,
|
|||||||
right_temp =
|
right_temp =
|
||||||
&((libab_value*)libab_ref_get(&right_value_temp))->type;
|
&((libab_value*)libab_ref_get(&right_value_temp))->type;
|
||||||
result = _interpreter_compare_types(
|
result = _interpreter_compare_types(
|
||||||
&left_temp, right_temp, &function_params, &child_params, scope);
|
&left_temp, right_temp, &function_params, &child_params);
|
||||||
|
|
||||||
if (result == LIBAB_SUCCESS) {
|
if (result == LIBAB_SUCCESS) {
|
||||||
result = _interpreter_resolve_type_params(
|
result = _interpreter_resolve_type_params(
|
||||||
right_temp, &child_params, scope, &produced_type);
|
right_temp, &child_params, &produced_type);
|
||||||
if (result != LIBAB_SUCCESS) {
|
if (result != LIBAB_SUCCESS) {
|
||||||
libab_ref_free(&produced_type);
|
libab_ref_free(&produced_type);
|
||||||
}
|
}
|
||||||
@ -317,10 +299,9 @@ libab_result _interpreter_check_types(libab_ref_vec* reference_types,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(result == LIBAB_SUCCESS) {
|
|
||||||
*param_map = function_params;
|
|
||||||
} else {
|
|
||||||
libab_ref_trie_free(&function_params);
|
libab_ref_trie_free(&function_params);
|
||||||
|
|
||||||
|
if (result != LIBAB_SUCCESS) {
|
||||||
libab_ref_vec_clear(types);
|
libab_ref_vec_clear(types);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -339,29 +320,23 @@ libab_result _interpreter_check_types(libab_ref_vec* reference_types,
|
|||||||
*/
|
*/
|
||||||
libab_result _interpreter_find_match(libab_function_list* function_values,
|
libab_result _interpreter_find_match(libab_function_list* function_values,
|
||||||
libab_ref_vec* params,
|
libab_ref_vec* params,
|
||||||
libab_ref_vec* new_types,
|
libab_ref_vec* new_types, libab_ref* match,
|
||||||
libab_ref_trie* param_map,
|
|
||||||
libab_ref* match,
|
|
||||||
int partial) {
|
int partial) {
|
||||||
libab_result result = LIBAB_SUCCESS;
|
libab_result result = LIBAB_SUCCESS;
|
||||||
size_t index = 0;
|
size_t index = 0;
|
||||||
size_t list_size = libab_function_list_size(function_values);
|
size_t list_size = libab_function_list_size(function_values);
|
||||||
int found_match = 0;
|
int found_match = 0;
|
||||||
libab_ref_trie temp_param_map;
|
|
||||||
libab_ref_vec temp_new_types;
|
libab_ref_vec temp_new_types;
|
||||||
libab_ref temp_function_value;
|
libab_ref temp_function_value;
|
||||||
libab_value* temp_value;
|
|
||||||
libab_parsetype* temp_function_type;
|
libab_parsetype* temp_function_type;
|
||||||
libab_function* temp_function;
|
|
||||||
|
|
||||||
libab_ref_null(match);
|
libab_ref_null(match);
|
||||||
result = libab_ref_vec_init(&temp_new_types);
|
result = libab_ref_vec_init(&temp_new_types);
|
||||||
|
|
||||||
for (; index < list_size && result == LIBAB_SUCCESS; index++) {
|
for (; index < list_size && result == LIBAB_SUCCESS; index++) {
|
||||||
libab_function_list_index(function_values, index, &temp_function_value);
|
libab_function_list_index(function_values, index, &temp_function_value);
|
||||||
temp_value = libab_ref_get(&temp_function_value);
|
temp_function_type = libab_ref_get(
|
||||||
temp_function_type = libab_ref_get(&temp_value->type);
|
&((libab_value*)libab_ref_get(&temp_function_value))->type);
|
||||||
temp_function = libab_ref_get(&temp_value->data);
|
|
||||||
|
|
||||||
if (((temp_function_type->children.size == params->size + 1) &&
|
if (((temp_function_type->children.size == params->size + 1) &&
|
||||||
!partial) ||
|
!partial) ||
|
||||||
@ -369,7 +344,7 @@ libab_result _interpreter_find_match(libab_function_list* function_values,
|
|||||||
partial)) {
|
partial)) {
|
||||||
/* We found a function that has the correct number of parameters. */
|
/* We found a function that has the correct number of parameters. */
|
||||||
result = _interpreter_check_types(
|
result = _interpreter_check_types(
|
||||||
&temp_function_type->children, params, &temp_new_types, &temp_function->scope, &temp_param_map);
|
&temp_function_type->children, params, &temp_new_types);
|
||||||
if (result == LIBAB_MISMATCHED_TYPE) {
|
if (result == LIBAB_MISMATCHED_TYPE) {
|
||||||
/* Mismatch is OK. */
|
/* Mismatch is OK. */
|
||||||
result = LIBAB_SUCCESS;
|
result = LIBAB_SUCCESS;
|
||||||
@ -381,7 +356,6 @@ libab_result _interpreter_find_match(libab_function_list* function_values,
|
|||||||
* new_types, and use new memory for temp list. */
|
* new_types, and use new memory for temp list. */
|
||||||
found_match = 1;
|
found_match = 1;
|
||||||
*new_types = temp_new_types;
|
*new_types = temp_new_types;
|
||||||
*param_map = temp_param_map;
|
|
||||||
libab_ref_free(match);
|
libab_ref_free(match);
|
||||||
libab_ref_copy(&temp_function_value, match);
|
libab_ref_copy(&temp_function_value, match);
|
||||||
result = libab_ref_vec_init(&temp_new_types);
|
result = libab_ref_vec_init(&temp_new_types);
|
||||||
@ -393,17 +367,13 @@ libab_result _interpreter_find_match(libab_function_list* function_values,
|
|||||||
* initialized, and the call is ambigous. Free all data. */
|
* initialized, and the call is ambigous. Free all data. */
|
||||||
libab_ref_vec_free(new_types);
|
libab_ref_vec_free(new_types);
|
||||||
libab_ref_vec_free(&temp_new_types);
|
libab_ref_vec_free(&temp_new_types);
|
||||||
libab_ref_trie_free(param_map);
|
|
||||||
libab_ref_trie_free(&temp_param_map);
|
|
||||||
result = LIBAB_AMBIGOUS_CALL;
|
result = LIBAB_AMBIGOUS_CALL;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Something bad happened. Free data as best as we can. */
|
/* Something bad happened. Free data as best as we can. */
|
||||||
libab_ref_vec_free(&temp_new_types);
|
libab_ref_vec_free(&temp_new_types);
|
||||||
if (found_match) {
|
if (found_match)
|
||||||
libab_ref_vec_free(new_types);
|
libab_ref_vec_free(new_types);
|
||||||
libab_ref_trie_free(param_map);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -469,48 +439,16 @@ libab_result _interpreter_cast_params(libab_ref_vec* params,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
libab_result _interpreter_run(struct interpreter_state* state, libab_tree* tree,
|
|
||||||
libab_ref* into, libab_ref* scope,
|
|
||||||
libab_interpreter_scope_mode scope_mode);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calls a tree-based function with the given parameters.
|
* Calls a tree-based function with the given parameters.
|
||||||
* @param tree the tree function to call.
|
* @param tree the tree function to call.
|
||||||
* @param the parameters to give to the function.
|
* @param the parameters to give to the function.
|
||||||
* @param scope the scope used for the call.
|
|
||||||
* @param into the reference to store the result into;
|
* @param into the reference to store the result into;
|
||||||
* @return the result of the call.
|
* @return the result of the call.
|
||||||
*/
|
*/
|
||||||
libab_result _interpreter_call_tree(struct interpreter_state* state,
|
libab_result _interpreter_call_tree(libab_tree* tree, libab_ref_vec* params,
|
||||||
libab_tree* tree,
|
|
||||||
libab_ref_vec* params,
|
|
||||||
libab_ref* scope,
|
|
||||||
libab_ref* into) {
|
libab_ref* into) {
|
||||||
libab_ref new_scope;
|
libab_result result = LIBAB_SUCCESS;
|
||||||
libab_tree* child;
|
|
||||||
libab_ref param;
|
|
||||||
libab_table* new_scope_raw;
|
|
||||||
size_t i;
|
|
||||||
libab_result result = libab_create_table(&new_scope, scope);
|
|
||||||
|
|
||||||
if(result == LIBAB_SUCCESS) {
|
|
||||||
new_scope_raw = libab_ref_get(&new_scope);
|
|
||||||
for(i = 0; i < tree->children.size - 1 && result == LIBAB_SUCCESS; i++) {
|
|
||||||
child = vec_index(&tree->children, i);
|
|
||||||
libab_ref_vec_index(params, i, ¶m);
|
|
||||||
result = libab_put_table_value(new_scope_raw, child->string_value, ¶m);
|
|
||||||
libab_ref_free(¶m);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(result == LIBAB_SUCCESS) {
|
|
||||||
result = _interpreter_run(state,
|
|
||||||
vec_index(&tree->children, tree->children.size - 1),
|
|
||||||
into, &new_scope, SCOPE_NONE);
|
|
||||||
}
|
|
||||||
|
|
||||||
libab_ref_free(&new_scope);
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -525,13 +463,12 @@ libab_result _interpreter_call_tree(struct interpreter_state* state,
|
|||||||
libab_result _interpreter_call_behavior(struct interpreter_state* state,
|
libab_result _interpreter_call_behavior(struct interpreter_state* state,
|
||||||
libab_behavior* behavior,
|
libab_behavior* behavior,
|
||||||
libab_ref_vec* params,
|
libab_ref_vec* params,
|
||||||
libab_ref* scope,
|
|
||||||
libab_ref* into) {
|
libab_ref* into) {
|
||||||
libab_result result = LIBAB_SUCCESS;
|
libab_result result = LIBAB_SUCCESS;
|
||||||
if (behavior->variant == BIMPL_INTERNAL) {
|
if (behavior->variant == BIMPL_INTERNAL) {
|
||||||
result = behavior->data_u.internal(state->ab, params, into);
|
result = behavior->data_u.internal(state->ab, params, into);
|
||||||
} else {
|
} else {
|
||||||
result = _interpreter_call_tree(state, behavior->data_u.tree, params, scope, into);
|
result = _interpreter_call_tree(behavior->data_u.tree, params, into);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -542,21 +479,19 @@ libab_result _interpreter_call_behavior(struct interpreter_state* state,
|
|||||||
* @param into the reference to store the copy into.
|
* @param into the reference to store the copy into.
|
||||||
*/
|
*/
|
||||||
libab_result _interpreter_copy_function_basic(libab_ref* function,
|
libab_result _interpreter_copy_function_basic(libab_ref* function,
|
||||||
libab_ref* scope,
|
|
||||||
libab_ref* into) {
|
libab_ref* into) {
|
||||||
libab_function* func = libab_ref_get(function);
|
libab_function* func = libab_ref_get(function);
|
||||||
void (*free_function)(void*) = function->count->free_func;
|
void (*free_function)(void*) = function->count->free_func;
|
||||||
return libab_create_function_behavior(into, free_function, &func->behavior, scope);
|
return libab_create_function_behavior(into, free_function, &func->behavior, &func->scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
libab_result _interpreter_copy_function_with_params(libab_ref* function,
|
libab_result _interpreter_copy_function_with_params(libab_ref* function,
|
||||||
libab_ref_vec* params,
|
libab_ref_vec* params,
|
||||||
libab_ref* scope,
|
|
||||||
libab_ref* into) {
|
libab_ref* into) {
|
||||||
int index = 0;
|
int index = 0;
|
||||||
libab_ref param;
|
libab_ref param;
|
||||||
libab_function* func;
|
libab_function* func;
|
||||||
libab_result result = _interpreter_copy_function_basic(function, scope, into);
|
libab_result result = _interpreter_copy_function_basic(function, into);
|
||||||
func = libab_ref_get(into);
|
func = libab_ref_get(into);
|
||||||
|
|
||||||
for(; index < params->size && result == LIBAB_SUCCESS; index++) {
|
for(; index < params->size && result == LIBAB_SUCCESS; index++) {
|
||||||
@ -620,7 +555,6 @@ libab_result _interpreter_copy_type_offset(libab_ref* type,
|
|||||||
libab_result _interpreter_partially_apply(struct interpreter_state* state,
|
libab_result _interpreter_partially_apply(struct interpreter_state* state,
|
||||||
libab_ref* function,
|
libab_ref* function,
|
||||||
libab_ref_vec* params,
|
libab_ref_vec* params,
|
||||||
libab_ref* scope,
|
|
||||||
libab_ref* into) {
|
libab_ref* into) {
|
||||||
libab_result result = LIBAB_SUCCESS;
|
libab_result result = LIBAB_SUCCESS;
|
||||||
libab_value* value;
|
libab_value* value;
|
||||||
@ -629,7 +563,7 @@ libab_result _interpreter_partially_apply(struct interpreter_state* state,
|
|||||||
|
|
||||||
value = libab_ref_get(function);
|
value = libab_ref_get(function);
|
||||||
libab_ref_null(&new_type);
|
libab_ref_null(&new_type);
|
||||||
result = _interpreter_copy_function_with_params(&value->data, params, scope, &new_function);
|
result = _interpreter_copy_function_with_params(&value->data, params, &new_function);
|
||||||
if(result == LIBAB_SUCCESS) {
|
if(result == LIBAB_SUCCESS) {
|
||||||
libab_ref_free(&new_type);
|
libab_ref_free(&new_type);
|
||||||
result = _interpreter_copy_type_offset(&value->type, 0, &new_type);
|
result = _interpreter_copy_type_offset(&value->type, 0, &new_type);
|
||||||
@ -647,44 +581,6 @@ libab_result _interpreter_partially_apply(struct interpreter_state* state,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
libab_result _interpreter_foreach_insert_param(const libab_ref* param,
|
|
||||||
const char* key,
|
|
||||||
va_list args) {
|
|
||||||
libab_result result = LIBAB_SUCCESS;
|
|
||||||
libab_table_entry* entry;
|
|
||||||
|
|
||||||
if ((entry = malloc(sizeof(*entry)))) {
|
|
||||||
entry->variant = ENTRY_TYPE_PARAM;
|
|
||||||
libab_ref_copy(param, &entry->data_u.type_param);
|
|
||||||
} else {
|
|
||||||
result = LIBAB_MALLOC;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(result == LIBAB_SUCCESS) {
|
|
||||||
result = libab_table_put(libab_ref_get(va_arg(args, libab_ref*)), key, entry);
|
|
||||||
if(result != LIBAB_SUCCESS) {
|
|
||||||
libab_ref_free(&entry->data_u.type_param);
|
|
||||||
free(entry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
libab_result _interpreter_create_scope(libab_ref* into,
|
|
||||||
libab_ref* parent_scope,
|
|
||||||
libab_ref_trie* param_map) {
|
|
||||||
libab_result result = libab_create_table(into, parent_scope);
|
|
||||||
if (result == LIBAB_SUCCESS) {
|
|
||||||
result = libab_ref_trie_foreach(param_map, _interpreter_foreach_insert_param, into);
|
|
||||||
|
|
||||||
if(result != LIBAB_SUCCESS) {
|
|
||||||
libab_ref_free(into);
|
|
||||||
libab_ref_null(into);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* Calls a function with the given, compatible paramters.
|
* Calls a function with the given, compatible paramters.
|
||||||
* @param state the state to use to call the function.
|
* @param state the state to use to call the function.
|
||||||
@ -696,32 +592,21 @@ libab_result _interpreter_create_scope(libab_ref* into,
|
|||||||
libab_result _interpreter_perform_function_call(struct interpreter_state* state,
|
libab_result _interpreter_perform_function_call(struct interpreter_state* state,
|
||||||
libab_ref* to_call,
|
libab_ref* to_call,
|
||||||
libab_ref_vec* params,
|
libab_ref_vec* params,
|
||||||
libab_ref_trie* param_map,
|
|
||||||
libab_ref* into) {
|
libab_ref* into) {
|
||||||
libab_result result = LIBAB_SUCCESS;
|
libab_result result = LIBAB_SUCCESS;
|
||||||
libab_value* function_value;
|
libab_value* function_value;
|
||||||
libab_function* function;
|
libab_function* function;
|
||||||
libab_parsetype* function_type;
|
libab_parsetype* function_type;
|
||||||
libab_ref new_scope;
|
|
||||||
size_t new_params;
|
size_t new_params;
|
||||||
|
|
||||||
function_value = libab_ref_get(to_call);
|
function_value = libab_ref_get(to_call);
|
||||||
function = libab_ref_get(&function_value->data);
|
function = libab_ref_get(&function_value->data);
|
||||||
function_type = libab_ref_get(&function_value->type);
|
function_type = libab_ref_get(&function_value->type);
|
||||||
new_params = params->size - function->params.size;
|
new_params = params->size - function->params.size;
|
||||||
|
if (function_type->children.size - new_params == 1) {
|
||||||
result = _interpreter_create_scope(&new_scope, &function->scope, param_map);
|
result = _interpreter_call_behavior(state, &function->behavior, params, into);
|
||||||
|
|
||||||
if(result != LIBAB_SUCCESS) {
|
|
||||||
libab_ref_null(into);
|
|
||||||
} else if (function_type->children.size - new_params == 1) {
|
|
||||||
result = _interpreter_call_behavior(state, &function->behavior, params, &new_scope, into);
|
|
||||||
} else {
|
} else {
|
||||||
result = _interpreter_partially_apply(state, to_call, params, &new_scope, into);
|
result = _interpreter_partially_apply(state, to_call, params, into);
|
||||||
}
|
}
|
||||||
|
|
||||||
libab_ref_free(&new_scope);
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -736,9 +621,7 @@ libab_result _interpreter_perform_function_call(struct interpreter_state* state,
|
|||||||
*/
|
*/
|
||||||
libab_result _interpreter_cast_and_perform_function_call(
|
libab_result _interpreter_cast_and_perform_function_call(
|
||||||
struct interpreter_state* state,
|
struct interpreter_state* state,
|
||||||
libab_ref* to_call, libab_ref_vec* params,
|
libab_ref* to_call, libab_ref_vec* params, libab_ref_vec* new_types,
|
||||||
libab_ref_vec* new_types,
|
|
||||||
libab_ref_trie* param_map,
|
|
||||||
libab_ref* into) {
|
libab_ref* into) {
|
||||||
libab_result result;
|
libab_result result;
|
||||||
libab_ref_vec new_params;
|
libab_ref_vec new_params;
|
||||||
@ -753,7 +636,7 @@ libab_result _interpreter_cast_and_perform_function_call(
|
|||||||
|
|
||||||
if (result == LIBAB_SUCCESS) {
|
if (result == LIBAB_SUCCESS) {
|
||||||
result = _interpreter_perform_function_call(state, to_call,
|
result = _interpreter_perform_function_call(state, to_call,
|
||||||
&new_params, param_map, into);
|
&new_params, into);
|
||||||
}
|
}
|
||||||
|
|
||||||
libab_ref_vec_free(&new_params);
|
libab_ref_vec_free(&new_params);
|
||||||
@ -776,14 +659,13 @@ libab_result _interpreter_call_function_list(struct interpreter_state* state,
|
|||||||
libab_result result = LIBAB_SUCCESS;
|
libab_result result = LIBAB_SUCCESS;
|
||||||
libab_ref_vec new_types;
|
libab_ref_vec new_types;
|
||||||
libab_ref to_call;
|
libab_ref to_call;
|
||||||
libab_ref_trie param_map;
|
|
||||||
libab_ref_null(into);
|
libab_ref_null(into);
|
||||||
|
|
||||||
result =
|
result =
|
||||||
_interpreter_find_match(list, params, &new_types, ¶m_map, &to_call, 0);
|
_interpreter_find_match(list, params, &new_types, &to_call, 0);
|
||||||
if (result == LIBAB_SUCCESS) {
|
if (result == LIBAB_SUCCESS) {
|
||||||
if (libab_ref_get(&to_call) == NULL) {
|
if (libab_ref_get(&to_call) == NULL) {
|
||||||
result = _interpreter_find_match(list, params, &new_types, ¶m_map,
|
result = _interpreter_find_match(list, params, &new_types,
|
||||||
&to_call, 1);
|
&to_call, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -795,8 +677,7 @@ libab_result _interpreter_call_function_list(struct interpreter_state* state,
|
|||||||
if (result == LIBAB_SUCCESS) {
|
if (result == LIBAB_SUCCESS) {
|
||||||
libab_ref_free(into);
|
libab_ref_free(into);
|
||||||
result = _interpreter_cast_and_perform_function_call(state, &to_call, params,
|
result = _interpreter_cast_and_perform_function_call(state, &to_call, params,
|
||||||
&new_types, ¶m_map, into);
|
&new_types, into);
|
||||||
libab_ref_trie_free(¶m_map);
|
|
||||||
libab_ref_vec_free(&new_types);
|
libab_ref_vec_free(&new_types);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -819,26 +700,22 @@ libab_result _interpreter_call_function(struct interpreter_state* state,
|
|||||||
libab_ref* into) {
|
libab_ref* into) {
|
||||||
libab_result result = LIBAB_SUCCESS;
|
libab_result result = LIBAB_SUCCESS;
|
||||||
libab_ref_vec temp_new_types;
|
libab_ref_vec temp_new_types;
|
||||||
libab_ref_trie param_map;
|
|
||||||
libab_value* function_value;
|
libab_value* function_value;
|
||||||
libab_parsetype* function_type;
|
libab_parsetype* function_type;
|
||||||
libab_function* function_instance;
|
|
||||||
|
|
||||||
function_value = libab_ref_get(function);
|
function_value = libab_ref_get(function);
|
||||||
function_type = libab_ref_get(&function_value->type);
|
function_type = libab_ref_get(&function_value->type);
|
||||||
function_instance = libab_ref_get(&function_value->data);
|
|
||||||
libab_ref_null(into);
|
libab_ref_null(into);
|
||||||
|
|
||||||
result = libab_ref_vec_init(&temp_new_types);
|
result = libab_ref_vec_init(&temp_new_types);
|
||||||
if (result == LIBAB_SUCCESS) {
|
if (result == LIBAB_SUCCESS) {
|
||||||
result = _interpreter_check_types(&function_type->children,
|
result = _interpreter_check_types(&function_type->children,
|
||||||
params, &temp_new_types, &function_instance->scope, ¶m_map);
|
params, &temp_new_types);
|
||||||
|
|
||||||
if (result == LIBAB_SUCCESS) {
|
if (result == LIBAB_SUCCESS) {
|
||||||
libab_ref_free(into);
|
libab_ref_free(into);
|
||||||
result = _interpreter_cast_and_perform_function_call(
|
result = _interpreter_cast_and_perform_function_call(
|
||||||
state, function, params, &temp_new_types, ¶m_map, into);
|
state, function, params, &temp_new_types, into);
|
||||||
libab_ref_trie_free(¶m_map);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
libab_ref_vec_free(&temp_new_types);
|
libab_ref_vec_free(&temp_new_types);
|
||||||
@ -879,6 +756,10 @@ libab_result _interpreter_try_call(struct interpreter_state* state,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
libab_result _interpreter_run(struct interpreter_state* state, libab_tree* tree,
|
||||||
|
libab_ref* into, libab_ref* scope,
|
||||||
|
int force_scope);
|
||||||
|
|
||||||
libab_result _interpreter_require_value(libab_ref* scope, const char* name,
|
libab_result _interpreter_require_value(libab_ref* scope, const char* name,
|
||||||
libab_ref* into) {
|
libab_ref* into) {
|
||||||
libab_result result = LIBAB_SUCCESS;
|
libab_result result = LIBAB_SUCCESS;
|
||||||
@ -906,7 +787,7 @@ libab_result _interpreter_call_operator(struct interpreter_state* state,
|
|||||||
if (result == LIBAB_SUCCESS) {
|
if (result == LIBAB_SUCCESS) {
|
||||||
/* Get first parameter. */
|
/* Get first parameter. */
|
||||||
result =
|
result =
|
||||||
_interpreter_run(state, va_arg(args, libab_tree*), &temp, scope, SCOPE_NORMAL);
|
_interpreter_run(state, va_arg(args, libab_tree*), &temp, scope, 0);
|
||||||
|
|
||||||
if (result == LIBAB_SUCCESS) {
|
if (result == LIBAB_SUCCESS) {
|
||||||
result = libab_ref_vec_insert(¶ms, &temp);
|
result = libab_ref_vec_insert(¶ms, &temp);
|
||||||
@ -917,7 +798,7 @@ libab_result _interpreter_call_operator(struct interpreter_state* state,
|
|||||||
/* If infix, get second parameter. */
|
/* If infix, get second parameter. */
|
||||||
if (result == LIBAB_SUCCESS && to_call->variant == OPERATOR_INFIX) {
|
if (result == LIBAB_SUCCESS && to_call->variant == OPERATOR_INFIX) {
|
||||||
result = _interpreter_run(state, va_arg(args, libab_tree*), &temp,
|
result = _interpreter_run(state, va_arg(args, libab_tree*), &temp,
|
||||||
scope, SCOPE_NORMAL);
|
scope, 0);
|
||||||
|
|
||||||
if (result == LIBAB_SUCCESS) {
|
if (result == LIBAB_SUCCESS) {
|
||||||
result = libab_ref_vec_insert(¶ms, &temp);
|
result = libab_ref_vec_insert(¶ms, &temp);
|
||||||
@ -943,7 +824,7 @@ libab_result _interpreter_call_operator(struct interpreter_state* state,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
libab_result _interpreter_run_call_node(struct interpreter_state* state,
|
libab_result _interpreter_run_function_node(struct interpreter_state* state,
|
||||||
libab_tree* tree, libab_ref* into,
|
libab_tree* tree, libab_ref* into,
|
||||||
libab_ref* scope) {
|
libab_ref* scope) {
|
||||||
libab_result result = LIBAB_SUCCESS;
|
libab_result result = LIBAB_SUCCESS;
|
||||||
@ -959,7 +840,7 @@ libab_result _interpreter_run_call_node(struct interpreter_state* state,
|
|||||||
count++) {
|
count++) {
|
||||||
libab_ref_free(¶m);
|
libab_ref_free(¶m);
|
||||||
child = vec_index(&tree->children, count);
|
child = vec_index(&tree->children, count);
|
||||||
result = _interpreter_run(state, child, ¶m, scope, SCOPE_NORMAL);
|
result = _interpreter_run(state, child, ¶m, scope, 0);
|
||||||
|
|
||||||
if (result == LIBAB_SUCCESS) {
|
if (result == LIBAB_SUCCESS) {
|
||||||
result = libab_ref_vec_insert(¶ms, ¶m);
|
result = libab_ref_vec_insert(¶ms, ¶m);
|
||||||
@ -974,7 +855,7 @@ libab_result _interpreter_run_call_node(struct interpreter_state* state,
|
|||||||
if (result == LIBAB_SUCCESS) {
|
if (result == LIBAB_SUCCESS) {
|
||||||
result = _interpreter_run(
|
result = _interpreter_run(
|
||||||
state, vec_index(&tree->children, tree->children.size - 1), &callee,
|
state, vec_index(&tree->children, tree->children.size - 1), &callee,
|
||||||
scope, SCOPE_NORMAL);
|
scope, 0);
|
||||||
if (result != LIBAB_SUCCESS) {
|
if (result != LIBAB_SUCCESS) {
|
||||||
libab_ref_vec_free(¶ms);
|
libab_ref_vec_free(¶ms);
|
||||||
}
|
}
|
||||||
@ -991,119 +872,12 @@ libab_result _interpreter_run_call_node(struct interpreter_state* state,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
int _interpreter_compare_function_param(
|
|
||||||
const void* left, const void* right) {
|
|
||||||
const libab_tree* data = right;
|
|
||||||
return data->variant == TREE_FUN_PARAM;
|
|
||||||
}
|
|
||||||
|
|
||||||
int _interpreter_foreach_resolve_function_param(
|
|
||||||
void* data, va_list args) {
|
|
||||||
libab_tree* tree = data;
|
|
||||||
libab_ref* scope = va_arg(args, libab_ref*);
|
|
||||||
libab_parsetype* type = libab_ref_get(&tree->type);
|
|
||||||
|
|
||||||
return libab_resolve_parsetype(type, libab_ref_get(scope));
|
|
||||||
}
|
|
||||||
|
|
||||||
libab_result _interpreter_resolve_function_params(
|
|
||||||
struct interpreter_state* state, libab_tree* tree,
|
|
||||||
libab_ref* scope) {
|
|
||||||
return vec_foreach(&tree->children, NULL, _interpreter_compare_function_param,
|
|
||||||
_interpreter_foreach_resolve_function_param, scope);
|
|
||||||
}
|
|
||||||
|
|
||||||
int _interpreter_foreach_insert_function_param(
|
|
||||||
void* data, va_list args) {
|
|
||||||
libab_tree* tree = data;
|
|
||||||
libab_ref_vec* into = va_arg(args, libab_ref_vec*);
|
|
||||||
return libab_ref_vec_insert(into, &tree->type);
|
|
||||||
}
|
|
||||||
|
|
||||||
libab_result _interpreter_create_function_type(
|
|
||||||
struct interpreter_state* state, libab_tree* tree, libab_parsetype** type) {
|
|
||||||
libab_result result = LIBAB_SUCCESS;
|
|
||||||
libab_basetype* funciton_type = libab_get_basetype_function(state->ab);
|
|
||||||
|
|
||||||
if((*type = malloc(sizeof(**type)))) {
|
|
||||||
(*type)->variant = LIBABACUS_TYPE_F_PARENT | LIBABACUS_TYPE_F_RESOLVED;
|
|
||||||
(*type)->data_u.base = funciton_type;
|
|
||||||
result = libab_ref_vec_init(&(*type)->children);
|
|
||||||
} else {
|
|
||||||
result = LIBAB_MALLOC;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(result == LIBAB_SUCCESS) {
|
|
||||||
result = vec_foreach(&tree->children, NULL, _interpreter_compare_function_param,
|
|
||||||
_interpreter_foreach_insert_function_param, &(*type)->children);
|
|
||||||
if(result == LIBAB_SUCCESS) {
|
|
||||||
result = libab_ref_vec_insert(&(*type)->children, &tree->type);
|
|
||||||
}
|
|
||||||
if(result != LIBAB_SUCCESS) {
|
|
||||||
libab_ref_vec_free(&(*type)->children);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(result != LIBAB_SUCCESS) {
|
|
||||||
free(*type);
|
|
||||||
*type = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
libab_result _interpreter_wrap_function_type(
|
|
||||||
struct interpreter_state* state, libab_tree* tree, libab_ref* into) {
|
|
||||||
libab_parsetype* type;
|
|
||||||
libab_result result = _interpreter_create_function_type(state, tree, &type);
|
|
||||||
|
|
||||||
if(result == LIBAB_SUCCESS) {
|
|
||||||
result = libab_ref_new(into, type, free_parsetype);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(result != LIBAB_SUCCESS) {
|
|
||||||
libab_ref_null(into);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
libab_result _interpreter_create_function_value(
|
|
||||||
struct interpreter_state* state, libab_tree* tree,
|
|
||||||
libab_ref* scope, libab_ref* into) {
|
|
||||||
libab_result result = LIBAB_SUCCESS;
|
|
||||||
libab_ref function, type;
|
|
||||||
|
|
||||||
libab_ref_null(&type);
|
|
||||||
libab_ref_null(into);
|
|
||||||
result = libab_create_function_tree(&function, free_function, tree, scope);
|
|
||||||
|
|
||||||
if(result == LIBAB_SUCCESS) {
|
|
||||||
libab_ref_free(&type);
|
|
||||||
result = _interpreter_wrap_function_type(state, tree, &type);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(result == LIBAB_SUCCESS) {
|
|
||||||
libab_ref_free(into);
|
|
||||||
result = libab_create_value_ref(into, &function, &type);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(result != LIBAB_SUCCESS) {
|
|
||||||
libab_ref_free(into);
|
|
||||||
libab_ref_null(into);
|
|
||||||
}
|
|
||||||
libab_ref_free(&function);
|
|
||||||
libab_ref_free(&type);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
libab_result _interpreter_run(struct interpreter_state* state, libab_tree* tree,
|
libab_result _interpreter_run(struct interpreter_state* state, libab_tree* tree,
|
||||||
libab_ref* into, libab_ref* scope,
|
libab_ref* into, libab_ref* scope,
|
||||||
libab_interpreter_scope_mode mode) {
|
int force_scope) {
|
||||||
libab_result result = LIBAB_SUCCESS;
|
libab_result result = LIBAB_SUCCESS;
|
||||||
libab_ref new_scope;
|
libab_ref new_scope;
|
||||||
int needs_scope = (mode == SCOPE_FORCE) ||
|
int needs_scope = libab_tree_has_scope(tree->variant) || force_scope;
|
||||||
(mode == SCOPE_NORMAL && libab_tree_has_scope(tree->variant));
|
|
||||||
|
|
||||||
if (needs_scope) {
|
if (needs_scope) {
|
||||||
result = libab_create_table(&new_scope, scope);
|
result = libab_create_table(&new_scope, scope);
|
||||||
@ -1118,7 +892,7 @@ libab_result _interpreter_run(struct interpreter_state* state, libab_tree* tree,
|
|||||||
while (result == LIBAB_SUCCESS && index < tree->children.size) {
|
while (result == LIBAB_SUCCESS && index < tree->children.size) {
|
||||||
libab_ref_free(into);
|
libab_ref_free(into);
|
||||||
result = _interpreter_run(state, vec_index(&tree->children, index),
|
result = _interpreter_run(state, vec_index(&tree->children, index),
|
||||||
into, scope, SCOPE_NORMAL);
|
into, scope, 0);
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
} else if (tree->variant == TREE_NUM) {
|
} else if (tree->variant == TREE_NUM) {
|
||||||
@ -1128,7 +902,7 @@ libab_result _interpreter_run(struct interpreter_state* state, libab_tree* tree,
|
|||||||
} else if (tree->variant == TREE_ID) {
|
} else if (tree->variant == TREE_ID) {
|
||||||
result = _interpreter_require_value(scope, tree->string_value, into);
|
result = _interpreter_require_value(scope, tree->string_value, into);
|
||||||
} else if (tree->variant == TREE_CALL) {
|
} else if (tree->variant == TREE_CALL) {
|
||||||
result = _interpreter_run_call_node(state, tree, into, scope);
|
result = _interpreter_run_function_node(state, tree, into, scope);
|
||||||
} else if (tree->variant == TREE_OP) {
|
} else if (tree->variant == TREE_OP) {
|
||||||
libab_operator* to_call = libab_table_search_operator(
|
libab_operator* to_call = libab_table_search_operator(
|
||||||
libab_ref_get(scope), tree->string_value, OPERATOR_INFIX);
|
libab_ref_get(scope), tree->string_value, OPERATOR_INFIX);
|
||||||
@ -1145,22 +919,6 @@ libab_result _interpreter_run(struct interpreter_state* state, libab_tree* tree,
|
|||||||
libab_ref_get(scope), tree->string_value, OPERATOR_POSTFIX);
|
libab_ref_get(scope), tree->string_value, OPERATOR_POSTFIX);
|
||||||
result = _interpreter_call_operator(state, to_call, into, scope,
|
result = _interpreter_call_operator(state, to_call, into, scope,
|
||||||
vec_index(&tree->children, 0));
|
vec_index(&tree->children, 0));
|
||||||
} else if (tree->variant == TREE_FUN) {
|
|
||||||
libab_ref function;
|
|
||||||
result =
|
|
||||||
_interpreter_create_function_value(state, tree, scope, &function);
|
|
||||||
|
|
||||||
if(result == LIBAB_SUCCESS) {
|
|
||||||
result = libab_put_table_value(libab_ref_get(scope),
|
|
||||||
tree->string_value, &function);
|
|
||||||
if(result != LIBAB_SUCCESS) {
|
|
||||||
libab_ref_free(&function);
|
|
||||||
libab_ref_null(&function);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
libab_ref_copy(&function, into);
|
|
||||||
libab_ref_free(&function);
|
|
||||||
} else {
|
} else {
|
||||||
libab_get_unit_value(state->ab, into);
|
libab_get_unit_value(state->ab, into);
|
||||||
}
|
}
|
||||||
@ -1173,13 +931,12 @@ libab_result _interpreter_run(struct interpreter_state* state, libab_tree* tree,
|
|||||||
}
|
}
|
||||||
|
|
||||||
libab_result libab_interpreter_run(libab_interpreter* intr, libab_tree* tree,
|
libab_result libab_interpreter_run(libab_interpreter* intr, libab_tree* tree,
|
||||||
libab_interpreter_scope_mode mode,
|
|
||||||
libab_ref* into) {
|
libab_ref* into) {
|
||||||
struct interpreter_state state;
|
struct interpreter_state state;
|
||||||
libab_result result;
|
libab_result result;
|
||||||
|
|
||||||
_interpreter_init(&state, intr);
|
_interpreter_init(&state, intr);
|
||||||
result = _interpreter_run(&state, tree, into, &state.ab->table, mode);
|
result = _interpreter_run(&state, tree, into, &state.ab->table, 1);
|
||||||
_interpreter_free(&state);
|
_interpreter_free(&state);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -5,16 +5,29 @@
|
|||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "value.h"
|
#include "value.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "free_functions.h"
|
|
||||||
|
|
||||||
static libab_basetype _basetype_function_list = {free_function_list, NULL, 0};
|
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_param _basetype_function_params[] = {{BT_LIST, NULL}};
|
||||||
|
|
||||||
static libab_basetype _basetype_function = {free_function,
|
static libab_basetype _basetype_function = {_free_function,
|
||||||
_basetype_function_params, 1};
|
_basetype_function_params, 1};
|
||||||
|
|
||||||
static libab_basetype _basetype_unit = { free_unit, NULL, 0 };
|
void _free_unit(void* unit) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static libab_basetype _basetype_unit = { _free_unit, NULL, 0 };
|
||||||
|
|
||||||
libab_result _prepare_types(libab* ab, void (*free_function)(void*));
|
libab_result _prepare_types(libab* ab, void (*free_function)(void*));
|
||||||
|
|
||||||
@ -154,7 +167,7 @@ libab_result _create_value_function_internal(libab_ref* into, libab_ref* type,
|
|||||||
libab_ref* scope) {
|
libab_ref* scope) {
|
||||||
libab_ref function_ref;
|
libab_ref function_ref;
|
||||||
libab_result result =
|
libab_result result =
|
||||||
libab_create_function_internal(&function_ref, free_function, func, scope);
|
libab_create_function_internal(&function_ref, _free_function, func, scope);
|
||||||
libab_ref_null(into);
|
libab_ref_null(into);
|
||||||
if (result == LIBAB_SUCCESS) {
|
if (result == LIBAB_SUCCESS) {
|
||||||
libab_ref_free(into);
|
libab_ref_free(into);
|
||||||
@ -394,7 +407,7 @@ libab_result libab_run(libab* ab, const char* string, libab_ref* value) {
|
|||||||
|
|
||||||
if (result == LIBAB_SUCCESS) {
|
if (result == LIBAB_SUCCESS) {
|
||||||
libab_ref_free(value);
|
libab_ref_free(value);
|
||||||
result = libab_interpreter_run(&ab->intr, root, SCOPE_NORMAL, value);
|
result = libab_interpreter_run(&ab->intr, root, value);
|
||||||
libab_tree_free_recursive(root);
|
libab_tree_free_recursive(root);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,65 +134,6 @@ void libab_ref_trie_get(const libab_ref_trie* trie, const char* key,
|
|||||||
libab_ref_null(into);
|
libab_ref_null(into);
|
||||||
}
|
}
|
||||||
|
|
||||||
libab_result _ref_trie_foreach(libab_ref_trie_node* node,
|
|
||||||
char** str, size_t* str_size, size_t depth,
|
|
||||||
libab_result (*func)(const libab_ref*, const char*, va_list),
|
|
||||||
va_list args) {
|
|
||||||
va_list args_copy;
|
|
||||||
libab_result result = LIBAB_SUCCESS;
|
|
||||||
if(node == NULL) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(depth + 1 >= *str_size) {
|
|
||||||
char* new_str = realloc(*str, (*str_size) *= 2);
|
|
||||||
if(new_str) {
|
|
||||||
*str = new_str;
|
|
||||||
} else {
|
|
||||||
result = LIBAB_MALLOC;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result == LIBAB_SUCCESS) {
|
|
||||||
(*str)[depth] = node->key;
|
|
||||||
(*str)[depth + 1] = '\0';
|
|
||||||
|
|
||||||
if(libab_ref_get(&node->ref)) {
|
|
||||||
va_copy(args_copy, args);
|
|
||||||
result = func(&node->ref, (*str), args_copy);
|
|
||||||
va_end(args_copy);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(result == LIBAB_SUCCESS)
|
|
||||||
result = _ref_trie_foreach(node->child, str, str_size, depth + 1, func, args);
|
|
||||||
if(result == LIBAB_SUCCESS)
|
|
||||||
result = _ref_trie_foreach(node->next, str, str_size, depth, func, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
libab_result libab_ref_trie_foreach(const libab_ref_trie* trie,
|
|
||||||
libab_result (*func)(const libab_ref*, const char*, va_list),
|
|
||||||
...) {
|
|
||||||
va_list args;
|
|
||||||
libab_result result = LIBAB_SUCCESS;
|
|
||||||
char* str;
|
|
||||||
size_t string_size = 4;
|
|
||||||
|
|
||||||
if((str = malloc(sizeof(*str) * 4))) {
|
|
||||||
va_start(args, func);
|
|
||||||
result = _ref_trie_foreach(trie->head, &str, &string_size, 0, func, args);
|
|
||||||
va_end(args);
|
|
||||||
} else {
|
|
||||||
result = LIBAB_MALLOC;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(str);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void libab_ref_trie_free(libab_ref_trie* trie) {
|
void libab_ref_trie_free(libab_ref_trie* trie) {
|
||||||
_libab_ref_trie_free(trie->head);
|
_libab_ref_trie_free(trie->head);
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ int libab_tree_has_string(libab_tree_variant variant) {
|
|||||||
int libab_tree_has_scope(libab_tree_variant variant) {
|
int libab_tree_has_scope(libab_tree_variant variant) {
|
||||||
return variant == TREE_BASE || variant == TREE_BLOCK ||
|
return variant == TREE_BASE || variant == TREE_BLOCK ||
|
||||||
variant == TREE_IF || variant == TREE_WHILE ||
|
variant == TREE_IF || variant == TREE_WHILE ||
|
||||||
variant == TREE_DOWHILE;
|
variant == TREE_DOWHILE || variant == TREE_FUN;
|
||||||
}
|
}
|
||||||
|
|
||||||
int libab_tree_has_type(libab_tree_variant variant) {
|
int libab_tree_has_type(libab_tree_variant variant) {
|
||||||
|
11
src/types.c
Normal file
11
src/types.c
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#include "types.h"
|
||||||
|
|
||||||
|
libab_result libab_array_init(libab_array* array) {
|
||||||
|
return libab_ref_vec_init(&array->elems);
|
||||||
|
}
|
||||||
|
|
||||||
|
libab_result libab_array_insert(libab_array* array, libab_ref* value) {
|
||||||
|
return libab_ref_vec_insert(&array->elems, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void libab_array_free(libab_array* array) { libab_ref_vec_free(&array->elems); }
|
21
src/util.c
21
src/util.c
@ -2,7 +2,6 @@
|
|||||||
#include "value.h"
|
#include "value.h"
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "free_functions.h"
|
|
||||||
|
|
||||||
libab_result libab_convert_lex_result(liblex_result to_convert) {
|
libab_result libab_convert_lex_result(liblex_result to_convert) {
|
||||||
libab_result result = LIBAB_SUCCESS;
|
libab_result result = LIBAB_SUCCESS;
|
||||||
@ -131,16 +130,21 @@ libab_result libab_instantiate_basetype(libab_basetype* to_instantiate,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _free_table(void* data) {
|
||||||
|
libab_table_free(data);
|
||||||
|
free(data);
|
||||||
|
}
|
||||||
|
|
||||||
libab_result libab_create_table(libab_ref* into, libab_ref* parent) {
|
libab_result libab_create_table(libab_ref* into, libab_ref* parent) {
|
||||||
libab_table* table;
|
libab_table* table;
|
||||||
libab_result result = LIBAB_SUCCESS;
|
libab_result result = LIBAB_SUCCESS;
|
||||||
if ((table = malloc(sizeof(*table)))) {
|
if ((table = malloc(sizeof(*table)))) {
|
||||||
libab_table_init(table);
|
libab_table_init(table);
|
||||||
libab_table_set_parent(table, parent);
|
libab_table_set_parent(table, parent);
|
||||||
result = libab_ref_new(into, table, free_table);
|
result = libab_ref_new(into, table, _free_table);
|
||||||
|
|
||||||
if (result != LIBAB_SUCCESS) {
|
if (result != LIBAB_SUCCESS) {
|
||||||
free_table(table);
|
_free_table(table);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
result = LIBAB_MALLOC;
|
result = LIBAB_MALLOC;
|
||||||
@ -152,16 +156,21 @@ libab_result libab_create_table(libab_ref* into, libab_ref* parent) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _free_value(void* value) {
|
||||||
|
libab_value_free(value);
|
||||||
|
free(value);
|
||||||
|
}
|
||||||
|
|
||||||
libab_result libab_create_value_ref(libab_ref* into, libab_ref* data,
|
libab_result libab_create_value_ref(libab_ref* into, libab_ref* data,
|
||||||
libab_ref* type) {
|
libab_ref* type) {
|
||||||
libab_value* value;
|
libab_value* value;
|
||||||
libab_result result = LIBAB_SUCCESS;
|
libab_result result = LIBAB_SUCCESS;
|
||||||
if ((value = malloc(sizeof(*value)))) {
|
if ((value = malloc(sizeof(*value)))) {
|
||||||
libab_value_init_ref(value, data, type);
|
libab_value_init_ref(value, data, type);
|
||||||
result = libab_ref_new(into, value, free_value);
|
result = libab_ref_new(into, value, _free_value);
|
||||||
|
|
||||||
if (result != LIBAB_SUCCESS) {
|
if (result != LIBAB_SUCCESS) {
|
||||||
free_value(value);
|
_free_value(value);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
result = LIBAB_MALLOC;
|
result = LIBAB_MALLOC;
|
||||||
@ -185,7 +194,7 @@ libab_result libab_create_value_raw(libab_ref* into, void* data,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (result == LIBAB_SUCCESS) {
|
if (result == LIBAB_SUCCESS) {
|
||||||
result = libab_ref_new(into, value, free_value);
|
result = libab_ref_new(into, value, _free_value);
|
||||||
if (result != LIBAB_SUCCESS) {
|
if (result != LIBAB_SUCCESS) {
|
||||||
libab_value_free(value);
|
libab_value_free(value);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user