Created
December 8, 2023 22:42
-
-
Save oreyg/95b21f3ceafc14a7c4f60d8e348c12d7 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "hscript.h" | |
#include <ctype.h> | |
#include <string.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <inttypes.h> | |
#include <assert.h> | |
HSId HScript_new_id() | |
{ | |
int lr = rand() * -1; | |
int hr = rand(); | |
uint32_t* plr = (uint32_t*)(&lr); | |
uint32_t* phr = (uint32_t*)(&hr); | |
return ((size_t)(*phr) << 32) | (*plr); | |
} | |
uint64_t inline HScript_to_pot(uint64_t n) | |
{ | |
if (n == 0) | |
{ | |
return 1; | |
} | |
--n; | |
n |= n >> 1; | |
n |= n >> 2; | |
n |= n >> 4; | |
n |= n >> 8; | |
n |= n >> 16; | |
n |= n >> 32; | |
return n + 1; | |
} | |
//#define HScript_resize_auto(x, co, ct) HScript_resize(x, sizeof((*(x)[0])), co, ct) | |
//#define HScript_grow(x, co) HScript_resize_auto(x, co, co + 1) | |
//#define HScript_shrink(x, co) HScript_resize_auto(x, co, co - 1) | |
static inline bool HScript_resize(void** buffer, size_t block_size, size_t original_block_count, size_t target_block_count) | |
{ | |
HS_ASSERT_RETURN(buffer != NULL, false); | |
if (target_block_count == 0 && (*buffer) != NULL) | |
{ | |
free(*buffer); | |
(*buffer) = NULL; | |
return true; | |
} | |
const size_t orig_pot = HScript_to_pot(block_size * original_block_count); | |
const size_t next_pot = HScript_to_pot(block_size * target_block_count); | |
if (orig_pot != next_pot) | |
{ | |
void* new_mem = realloc(*buffer, next_pot); | |
if (new_mem) | |
{ | |
(*buffer) = new_mem; | |
} | |
return new_mem != NULL; | |
} | |
return true; | |
} | |
static inline void HScript_to_uppercase(char* uppercase, size_t max_uppercase) | |
{ | |
for (size_t i = 0; i < max_uppercase; ++i) | |
{ | |
uppercase[i] = toupper(uppercase[i]); | |
} | |
uppercase[max_uppercase - 1] = 0; | |
} | |
static inline int HScript_compare_id_defn(const HSDefn* first, const HSDefn* second) | |
{ | |
return first->id < second->id ? -1 : first->id == second->id ? 0 : 1; | |
} | |
static inline int HScript_compare_id_node(const HSNode* first, const HSNode* second) | |
{ | |
return first->node_id < second->node_id ? -1 : first->node_id == second->node_id ? 0 : 1; | |
} | |
static inline int HScript_compare_id_link(const HSLink* first, const HSLink* second) | |
{ | |
return first->id < second->id ? -1 : first->id == second->id ? 0 : 1; | |
} | |
static inline int HScript_compare_func(const HSFuncReg* first, const HSFuncReg* second) | |
{ | |
return strcmp(first->fun_name, second->fun_name); | |
} | |
int HScript_compare_defn_name(const HSDefn* first, const HSDefn* second) | |
{ | |
return strcmp(first->name, second->name); | |
} | |
int HScript_compare_defn_name2(const void* first, const void* second) | |
{ | |
return strcmp((*(HSDefn**)(first))->name, (*(HSDefn**)second)->name); | |
} | |
static void HScript_process_unresolved(HSFnContext* context) | |
{ | |
printf("Unresolved function called\n"); | |
} | |
// MurMur64 | |
uint64_t HScript_hash64(const void* key, size_t len, uint64_t seed) | |
{ | |
const uint64_t m = 0xc6a4a7935bd1e995ULL; | |
const int r = 47; | |
uint64_t h = seed ^ (len * m); | |
const uint64_t* data = (const uint64_t*)key; | |
const uint64_t* end = data + (len / 8); | |
while (data != end) | |
{ | |
uint64_t k = *data++; | |
k *= m; | |
k ^= k >> r; | |
k *= m; | |
h ^= k; | |
h *= m; | |
} | |
const unsigned char* data2 = (const unsigned char*)data; | |
switch (len & 7) | |
{ | |
case 7: h ^= (uint64_t)(data2[6]) << 48; | |
case 6: h ^= (uint64_t)(data2[5]) << 40; | |
case 5: h ^= (uint64_t)(data2[4]) << 32; | |
case 4: h ^= (uint64_t)(data2[3]) << 24; | |
case 3: h ^= (uint64_t)(data2[2]) << 16; | |
case 2: h ^= (uint64_t)(data2[1]) << 8; | |
case 1: h ^= (uint64_t)(data2[0]); | |
h *= m; | |
}; | |
h ^= h >> r; | |
h *= m; | |
h ^= h >> r; | |
return h; | |
} | |
bool HScript_index_defn_names(HSRawContext* context, HSIndex* str) | |
{ | |
const bool success = HScript_resize(&str->obj, sizeof(uintptr_t*), str->arr_size, context->defns_size); | |
if (success) | |
{ | |
for (size_t i = 0; i < context->defns_size; i++) | |
{ | |
str->obj[i] = (uintptr_t)&context->defns[i]; | |
} | |
qsort(str->obj, context->defns_size, sizeof(uintptr_t*), HScript_compare_defn_name2); | |
str->arr_size = context->defns_size; | |
return true; | |
} | |
else | |
{ | |
HS_ASSERT_RETURN(false, false); | |
} | |
return false; | |
} | |
void HScript_index_initialize(HSIndex* str) | |
{ | |
str->obj = 0; | |
str->arr_size = 0; | |
} | |
void HScript_index_reset(HSIndex* str) | |
{ | |
if (str->obj) | |
{ | |
free(str->obj); | |
} | |
str->arr_size = 0; | |
} | |
ESArgType HScript_parse_typename(const char* type, size_t size) | |
{ | |
char uppercase[HS_TYPE_MAX_SIZE]; | |
memset(uppercase, 0, HS_TYPE_MAX_SIZE); | |
strncpy_s(uppercase, HS_TYPE_MAX_SIZE, type, size); | |
HScript_to_uppercase(uppercase, HS_TYPE_MAX_SIZE); | |
if (strncmp(uppercase, "EXECUTION", HS_TYPE_MAX_SIZE) == 0) | |
{ | |
return HS_EXECUTION; | |
} | |
else if (strncmp(uppercase, "INT", HS_TYPE_MAX_SIZE) == 0) | |
{ | |
return HS_INT; | |
} | |
else if (strncmp(uppercase, "FLOAT", HS_TYPE_MAX_SIZE) == 0) | |
{ | |
return HS_FLOAT; | |
} | |
else if (strncmp(uppercase, "BOOLEAN", HS_TYPE_MAX_SIZE) == 0) | |
{ | |
return HS_BOOLEAN; | |
} | |
else if (strncmp(uppercase, "ENTITY", HS_TYPE_MAX_SIZE) == 0) | |
{ | |
return HS_ENTITY; | |
} | |
else if (strncmp(uppercase, "OBJECT", HS_TYPE_MAX_SIZE) == 0) | |
{ | |
return HS_OBJECT; | |
} | |
else if (strncmp(uppercase, "ARRAY", HS_TYPE_MAX_SIZE) == 0) | |
{ | |
return HS_ARRAY; | |
} | |
else if (strncmp(uppercase, "BOOL", HS_TYPE_MAX_SIZE) == 0) | |
{ | |
return HS_BOOLEAN; | |
} | |
else if (strncmp(uppercase, "EXEC", HS_TYPE_MAX_SIZE) == 0) | |
{ | |
return HS_EXECUTION; | |
} | |
else if (strncmp(uppercase, "I", HS_TYPE_MAX_SIZE) == 0) | |
{ | |
return HS_INT; | |
} | |
else if (strncmp(uppercase, "F", HS_TYPE_MAX_SIZE) == 0) | |
{ | |
return HS_FLOAT; | |
} | |
else if (strncmp(uppercase, "B", HS_TYPE_MAX_SIZE) == 0) | |
{ | |
return HS_BOOLEAN; | |
} | |
else if (strncmp(uppercase, "E", HS_TYPE_MAX_SIZE) == 0) | |
{ | |
return HS_EXECUTION; | |
} | |
return HS_TYPE_ERROR; | |
} | |
HSDefn* HScript_defn_find(HSDefn* defns, size_t defn_count, HSId id) | |
{ | |
//for (size_t i = 0; i < defn_count; i++) | |
//{ | |
// if (defns[i].id == id) | |
// { | |
// return &defns[i]; | |
// } | |
//} | |
// | |
//return NULL; | |
HSDefn search_defn; | |
search_defn.id = id; | |
return bsearch(&search_defn, defns, defn_count, sizeof(HSDefn), HScript_compare_id_defn); | |
} | |
HSNode* HScript_node_find(HSNode* nodes, size_t node_count, HSId id) | |
{ | |
//for (size_t i = 0; i < node_count; i++) | |
//{ | |
// if (nodes[i].node_id == id) | |
// { | |
// return &nodes[i]; | |
// } | |
//} | |
// | |
//return NULL; | |
HSNode search_node; | |
search_node.node_id = id; | |
return bsearch(&search_node, nodes, node_count, sizeof(HSNode), HScript_compare_id_node); | |
} | |
HSDefnArg* HScript_defn_find_argument(HSDefn* defn, const char* name) | |
{ | |
for (size_t i = 0; i < defn->i_size; i++) | |
{ | |
HSDefnArg* arg = &defn->inputs[i]; | |
if (strcmp(arg->name, name) == 0) | |
{ | |
return arg; | |
} | |
} | |
for (size_t i = 0; i < defn->o_size; i++) | |
{ | |
HSDefnArg* arg = &defn->outputs[i]; | |
if (strcmp(arg->name, name) == 0) | |
{ | |
return arg; | |
} | |
} | |
return NULL; | |
} | |
HSNodeArg* HScript_node_find_argument(HSNode* node, const char* name) | |
{ | |
for (size_t i = 0; i < node->args_size; i++) | |
{ | |
HSNodeArg* arg = &node->args[i]; | |
if (strcmp(arg->name, name) == 0) | |
{ | |
return arg; | |
} | |
} | |
return NULL; | |
} | |
HSLink* HScript_link_find_source(HSLink* links, size_t link_count, HSId id, const char* name) | |
{ | |
for (size_t i = 0; i < link_count; i++) | |
{ | |
if (links[i].node_source_id == id && strcmp(links[i].arg_source_name, name) == 0) | |
{ | |
return &links[i]; | |
} | |
} | |
return NULL; | |
} | |
HSLink* HScript_link_find_target(HSLink* links, size_t link_count, HSId id, const char* name) | |
{ | |
for (size_t i = 0; i < link_count; i++) | |
{ | |
if (links[i].node_target_id == id && strcmp(links[i].arg_target_name, name) == 0) | |
{ | |
return &links[i]; | |
} | |
} | |
return NULL; | |
} | |
HSFuncReg* HScript_func_find(HSFuncReg* funcs, size_t func_count, const char* name) | |
{ | |
for (size_t i = 0; i < func_count; i++) | |
{ | |
if (strcmp(funcs[i].fun_name, name) == 0) | |
{ | |
return &funcs[i]; | |
} | |
} | |
return NULL; | |
} | |
bool HScript_validate_next_node(HSNodeError* error, HSDefn* defns, size_t defn_count, HSNode* nodes, size_t node_count) | |
{ | |
for (size_t i = error->next_idx; i < node_count; i++) | |
{ | |
HSNode* node = &nodes[i]; | |
HSDefn* defn = HScript_defn_find(defns, defn_count, node->defn_id); | |
error->next_idx = i + 1; | |
error->next_arg_idx = 0; | |
error->proc_node = node; | |
error->proc_defn = defn; | |
if (defn == NULL) | |
{ | |
error->node_id = node->node_id; | |
error->node_arg_name = ""; | |
error->node_arg_type = HS_TYPE_ERROR; | |
error->defn_arg_type = HS_TYPE_ERROR; | |
error->state = HS_NODE_DEF_MISSING; | |
return i < node_count; | |
} | |
if (HScript_validate_next_node_arg(error)) | |
{ | |
return true; | |
} | |
} | |
error->node_id = HS_NIL_VALUE; | |
error->node_arg_name = ""; | |
error->node_arg_type = HS_TYPE_ERROR; | |
error->defn_arg_type = HS_TYPE_ERROR; | |
error->next_idx = node_count; | |
error->next_arg_idx = 0; | |
error->proc_node = NULL; | |
error->proc_defn = NULL; | |
error->state = HS_NODE_SUCCESS; | |
return false; | |
} | |
bool HScript_validate_next_link(HSLinkError* error, HSNode* nodes, size_t node_count, HSLink* links, size_t link_count) | |
{ | |
for (size_t i = error->next_idx; i < link_count; i++) | |
{ | |
HSLink* link = &links[i]; | |
// TO-DO: Check that there are no duplicate links | |
HSNode* node_source = HScript_node_find(nodes, node_count, link->node_source_id); | |
HSNode* node_target = HScript_node_find(nodes, node_count, link->node_target_id); | |
ESArgType source_type = HS_TYPE_ERROR; | |
if (node_source != NULL) | |
{ | |
HSNodeArg* arg = HScript_node_find_argument(node_source, link->arg_source_name); | |
if (arg != NULL) | |
{ | |
source_type = arg->type; | |
} | |
} | |
ESArgType target_type = HS_TYPE_ERROR; | |
if (node_target != NULL) | |
{ | |
HSNodeArg* arg = HScript_node_find_argument(node_target, link->arg_target_name); | |
if (arg != NULL) | |
{ | |
target_type = arg->type; | |
} | |
} | |
if (node_source == NULL) | |
{ | |
error->link_id = link->id; | |
error->source_node_id = link->node_source_id; | |
error->target_node_id = link->node_target_id; | |
error->source_node = node_source; | |
error->target_node = node_target; | |
error->source_name = link->arg_source_name; | |
error->source_name = link->arg_target_name; | |
error->source_type = source_type; | |
error->target_type = target_type; | |
error->state = HS_LINK_SOURCE_NODE_MISSING; | |
error->next_idx = i + 1; | |
return true; | |
} | |
else if (source_type == HS_TYPE_ERROR) | |
{ | |
error->link_id = link->id; | |
error->source_node_id = link->node_source_id; | |
error->target_node_id = link->node_target_id; | |
error->source_node = node_source; | |
error->target_node = node_target; | |
error->source_name = link->arg_source_name; | |
error->source_name = link->arg_target_name; | |
error->source_type = source_type; | |
error->target_type = target_type; | |
error->state = HS_LINK_SOURCE_ARG_MISSING; | |
error->next_idx = i + 1; | |
return true; | |
} | |
if (node_target == NULL) | |
{ | |
error->link_id = link->id; | |
error->source_node_id = link->node_source_id; | |
error->target_node_id = link->node_target_id; | |
error->source_node = node_source; | |
error->target_node = node_target; | |
error->source_name = link->arg_source_name; | |
error->source_name = link->arg_target_name; | |
error->source_type = source_type; | |
error->target_type = target_type; | |
error->state = HS_LINK_TARGET_NODE_MISSING; | |
error->next_idx = i + 1; | |
return true; | |
} | |
else if (target_type == HS_TYPE_ERROR) | |
{ | |
error->link_id = link->id; | |
error->source_node_id = link->node_source_id; | |
error->target_node_id = link->node_target_id; | |
error->source_node = node_source; | |
error->target_node = node_target; | |
error->source_name = link->arg_source_name; | |
error->source_name = link->arg_target_name; | |
error->source_type = source_type; | |
error->target_type = target_type; | |
error->state = HS_LINK_TARGET_ARG_MISSING; | |
error->next_idx = i + 1; | |
return true; | |
} | |
if (node_source != NULL && node_target != NULL && source_type != target_type) | |
{ | |
error->link_id = link->id; | |
error->source_node_id = link->node_source_id; | |
error->target_node_id = link->node_target_id; | |
error->source_node = node_source; | |
error->target_node = node_target; | |
error->source_name = link->arg_source_name; | |
error->source_name = link->arg_target_name; | |
error->source_type = source_type; | |
error->target_type = target_type; | |
error->state = HS_LINK_TYPE_MISMATCH; | |
error->next_idx = i + 1; | |
return true; | |
} | |
} | |
error->link_id = HS_NIL_VALUE; | |
error->source_node_id = HS_NIL_VALUE; | |
error->target_node_id = HS_NIL_VALUE; | |
error->source_node = NULL; | |
error->target_node = NULL; | |
error->source_name = ""; | |
error->source_name = ""; | |
error->source_type = HS_TYPE_ERROR; | |
error->target_type = HS_TYPE_ERROR; | |
error->state = HS_LINK_SUCCESS; | |
error->next_idx = node_count; | |
return false; | |
} | |
bool HScript_validate_next_defn(HSDefnError* error, HSDefn* defns, size_t defn_count, size_t start_idx) | |
{ | |
error->defn_id = HS_NIL_VALUE; | |
return false; | |
} | |
bool HScript_validate_next_node_arg(HSNodeError* error) | |
{ | |
HSNode* node = error->proc_node; | |
HSDefn* defn = error->proc_defn; | |
for (size_t j = error->next_arg_idx; j < node->args_size; j++) | |
{ | |
HSNodeArg* node_arg = &node->args[j]; | |
HSDefnArg* defn_arg = HScript_defn_find_argument(defn, node_arg->name); | |
if (defn_arg == NULL) | |
{ | |
error->node_arg_name = node_arg->name; | |
error->node_arg_type = node_arg->type; | |
error->defn_arg_type = HS_TYPE_ERROR; | |
error->state = HS_NODE_ARG_NAME_MISMATCH; | |
error->next_arg_idx = j + 1; | |
return j < node->args_size; | |
} | |
if (defn_arg->type != node_arg->type) | |
{ | |
error->node_arg_name = node_arg->name; | |
error->node_arg_type = node_arg->type; | |
error->defn_arg_type = defn_arg->type; | |
error->state = HS_NODE_ARG_TYPE_MISMATCH; | |
error->next_arg_idx = j + 1; | |
return j < node->args_size; | |
} | |
} | |
error->node_arg_name = ""; | |
error->node_arg_type = HS_TYPE_ERROR; | |
error->defn_arg_type = HS_TYPE_ERROR; | |
error->state = HS_NODE_ARG_TYPE_MISMATCH; | |
error->next_arg_idx = node->args_size; | |
return false; | |
} | |
bool HScript_stringify_argument_type(ESArgType argument_type, char* buffer, size_t size) | |
{ | |
if (size < 32) | |
{ | |
return false; | |
} | |
memset(buffer, 0, size); | |
switch (argument_type) | |
{ | |
case HS_EXECUTION: | |
{ | |
const char str[] = "execution"; | |
strncpy_s(buffer, sizeof(str), str, size); | |
} | |
break; | |
case HS_INT: | |
{ | |
const char str[] = "integer"; | |
strncpy_s(buffer, sizeof(str), str, size); | |
} | |
break; | |
case HS_FLOAT: | |
{ | |
const char str[] = "float"; | |
strncpy_s(buffer, sizeof(str), str, size); | |
} | |
break; | |
case HS_BOOLEAN: | |
{ | |
const char str[] = "boolean"; | |
strncpy_s(buffer, sizeof(str), str, size); | |
} | |
break; | |
case HS_ENTITY: | |
{ | |
const char str[] = "entity"; | |
strncpy_s(buffer, sizeof(str), str, size); | |
} | |
break; | |
case HS_OBJECT: | |
{ | |
const char str[] = "object"; | |
strncpy_s(buffer, sizeof(str), str, size); | |
} | |
break; | |
case HS_STRUCT: | |
{ | |
const char str[] = "struct"; | |
strncpy_s(buffer, sizeof(str), str, size); | |
} | |
break; | |
case HS_ARRAY: | |
{ | |
const char str[] = "array"; | |
strncpy_s(buffer, sizeof(str), str, size); | |
} | |
break; | |
default: | |
{ | |
const char str[] = "error"; | |
strncpy_s(buffer, sizeof(str), str, size); | |
} | |
} | |
return true; | |
} | |
bool HScript_stringify_node_error(HSNodeError* error, char* buffer, size_t size) | |
{ | |
if (size < 256) | |
{ | |
return false; | |
} | |
memset(buffer, 0, size); | |
switch (error->state) | |
{ | |
case HS_NODE_DEF_MISSING: | |
{ | |
snprintf(buffer, size, "Can't find definition for node with Id '%llu'.", error->node_id); | |
} | |
break; | |
case HS_NODE_ARG_NAME_MISMATCH: | |
{ | |
snprintf(buffer, size, "Can't find argument '%s' for node with Id '%llu'.", error->node_arg_name, error->node_id); | |
} | |
break; | |
case HS_NODE_ARG_TYPE_MISMATCH: | |
{ | |
char node_arg_typename[32]; | |
char defn_arg_typename[32]; | |
if (HScript_stringify_argument_type(error->node_arg_type, node_arg_typename, sizeof(node_arg_typename)) && | |
HScript_stringify_argument_type(error->defn_arg_type, defn_arg_typename, sizeof(defn_arg_typename))) | |
{ | |
snprintf(buffer, size, "Type mismatch in argument '%s': '%s' and '%s' for node with Id '%llu'.", error->node_arg_name, node_arg_typename, defn_arg_typename, error->node_id); | |
} | |
else | |
{ | |
return false; | |
} | |
} | |
break; | |
default: | |
{ | |
const char str[] = "Can't process error."; | |
strncpy_s(buffer, sizeof(str), str, size); | |
} | |
} | |
return true; | |
} | |
bool HScript_stringify_link_error(HSLinkError* error, char* buffer, size_t size) | |
{ | |
if (size < 256) | |
{ | |
return false; | |
} | |
switch (error->state) | |
{ | |
case HS_LINK_SOURCE_NODE_MISSING: | |
{ | |
snprintf(buffer, size, "Can't find source node for link with Id '%llu'.", error->link_id); | |
} | |
break; | |
case HS_LINK_TARGET_NODE_MISSING: | |
{ | |
snprintf(buffer, size, "Can't find target node for link with Id '%llu'.", error->link_id); | |
} | |
break; | |
case HS_LINK_SOURCE_ARG_MISSING: | |
{ | |
snprintf(buffer, size, "Can't find source argument '%s' for link with Id '%llu'.", error->source_name, error->link_id); | |
} | |
break; | |
case HS_LINK_TARGET_ARG_MISSING: | |
{ | |
snprintf(buffer, size, "Can't find target argument '%s' for link with Id '%llu'.", error->target_name, error->link_id); | |
} | |
break; | |
case HS_LINK_TYPE_MISMATCH: | |
{ | |
char source_type[32]; | |
char target_type[32]; | |
if (HScript_stringify_argument_type(error->source_type, source_type, sizeof(source_type)) && | |
HScript_stringify_argument_type(error->target_type, target_type, sizeof(target_type))) | |
{ | |
snprintf(buffer, size, "Type mismatch between arguments '%s' ('%s') and '%s' ('%s').", error->source_name, source_type, error->target_name, target_type); | |
} | |
else | |
{ | |
return false; | |
} | |
} | |
break; | |
default: | |
{ | |
const char str[] = "Can't process error."; | |
strncpy_s(buffer, sizeof(str), str, size); | |
} | |
} | |
return true; | |
} | |
bool HScript_rawcontext_build_nodes(HSRawContext* context) | |
{ | |
// -- Populate defaults start | |
for (size_t i = 0; i < context->nodes_size; i++) | |
{ | |
HSNode* node = &context->nodes[i]; | |
HSDefn* defn = HScript_defn_find(context->defns, context->defns_size, node->defn_id); | |
if (!defn) | |
{ | |
continue; | |
} | |
for (size_t j = 0; j < defn->i_size; j++) | |
{ | |
HSNodeArg* arg = HScript_node_find_argument(node, defn->inputs[j].name); | |
if (arg == NULL) | |
{ | |
HSNodeArg new_arg; | |
new_arg.name = defn->inputs[j].name; | |
new_arg.type = defn->inputs[j].type; | |
new_arg.value = defn->inputs[j].value; | |
new_arg.dflt = true; | |
HScript_node_arg_push(context, node, &new_arg); | |
} | |
} | |
for (size_t j = 0; j < defn->o_size; j++) | |
{ | |
HSNodeArg* arg = HScript_node_find_argument(node, defn->outputs[j].name); | |
if (arg == NULL) | |
{ | |
HSNodeArg new_arg; | |
new_arg.name = defn->outputs[j].name; | |
new_arg.type = defn->outputs[j].type; | |
new_arg.value = defn->outputs[j].value; | |
new_arg.dflt = true; | |
HScript_node_arg_push(context, node, &new_arg); | |
} | |
} | |
HSFuncReg* func = HScript_func_find(context->funcs, context->funcs_size, defn->name); | |
if (func) | |
{ | |
node->func = func->fun_ptr; | |
} | |
else | |
{ | |
node->func = HScript_process_unresolved; | |
} | |
} | |
// Arguments in nodes should match the order in which they are declared | |
for (size_t i = 0; i < context->nodes_size; i++) | |
{ | |
HSNode* node = &context->nodes[i]; | |
HSDefn* defn = HScript_defn_find(context->defns, context->defns_size, node->defn_id); | |
if (!defn) | |
{ | |
continue; | |
} | |
node->i_size = defn->i_size; | |
for (size_t j = 0; j < defn->i_size; j++) | |
{ | |
HSNodeArg* arg = HScript_node_find_argument(node, defn->inputs[j].name); | |
const size_t arg_idx = (arg - node->args); | |
if (arg != NULL && (node->args - arg) != j) | |
{ | |
HSNodeArg tmp = node->args[j]; | |
node->args[j] = (*arg); | |
(*arg) = tmp; | |
} | |
} | |
for (size_t j = 0; j < defn->o_size; j++) | |
{ | |
HSNodeArg* arg = HScript_node_find_argument(node, defn->outputs[j].name); | |
const size_t tgt_idx = j + defn->i_size; | |
const size_t arg_idx = arg - node->args; | |
if (arg != NULL && arg_idx != tgt_idx) | |
{ | |
HSNodeArg tmp = node->args[tgt_idx]; | |
node->args[tgt_idx] = (*arg); | |
(*arg) = tmp; | |
} | |
} | |
} | |
// -- Populate defaults end | |
return true; | |
} | |
bool HScript_rawcontext_build_links(HSRawContext* context) | |
{ | |
// -- Link all nodes | |
for (size_t i = 0; i < context->nodes_size; i++) | |
{ | |
HSNode* node = &context->nodes[i]; | |
for (size_t j = 0; j < node->args_size; j++) | |
{ | |
node->args[j].cnode = 0; | |
node->args[j].carg = 0; | |
} | |
} | |
for (size_t i = 0; i < context->links_size; i++) | |
{ | |
HSLink* link = &context->links[i]; | |
HSNode* source_node = HScript_node_find(context->nodes, context->nodes_size, link->node_source_id); | |
if (source_node == NULL) | |
{ | |
continue; | |
} | |
HSNodeArg* source_arg = HScript_node_find_argument(source_node, link->arg_source_name); | |
if (source_arg == NULL) | |
{ | |
continue; | |
} | |
HSNode* target_node = HScript_node_find(context->nodes, context->nodes_size, link->node_target_id); | |
if (target_node == NULL) | |
{ | |
continue; | |
} | |
HSNodeArg* target_arg = HScript_node_find_argument(target_node, link->arg_target_name); | |
if (target_arg == NULL) | |
{ | |
continue; | |
} | |
uintptr_t source_idx = (uintptr_t)(source_arg - source_node->args); | |
uintptr_t target_idx = (uintptr_t)(target_arg - target_node->args); | |
source_arg->cnode = target_node; | |
source_arg->carg = target_idx; | |
target_arg->cnode = source_node; | |
target_arg->carg = source_idx; | |
} | |
// -- Link all nodes end | |
return true; | |
} | |
bool HScript_rawcontext_build_string(HSRawContext* context) | |
{ | |
// -- String copy start | |
size_t string_len = 0; | |
// Calc string lengths for definitions | |
for (size_t i = 0; i < context->defns_size; i++) | |
{ | |
HSDefn* defn = &context->defns[i]; | |
string_len += strnlen_s(defn->name, 1024) + 1; | |
// Inputs | |
for (size_t j = 0; j < defn->i_size; j++) | |
{ | |
HSDefnArg* arg = &defn->inputs[j]; | |
string_len += strnlen_s(arg->name, 1024) + 1; | |
} | |
// Outputs | |
for (size_t j = 0; j < defn->o_size; j++) | |
{ | |
HSDefnArg* arg = &defn->outputs[j]; | |
string_len += strnlen_s(arg->name, 1024) + 1; | |
} | |
} | |
// Calc string lengths for nodes | |
for (size_t i = 0; i < context->nodes_size; i++) | |
{ | |
HSNode* node = &context->nodes[i]; | |
for (size_t j = 0; j < node->args_size; j++) | |
{ | |
HSNodeArg* arg = &node->args[j]; | |
string_len += strnlen_s(arg->name, 1024) + 1; | |
} | |
} | |
// Calc string lenghts for links | |
for (size_t i = 0; i < context->links_size; i++) | |
{ | |
HSLink* link = &context->links[i]; | |
string_len += strnlen_s(link->arg_source_name, 1024) + 1; | |
string_len += strnlen_s(link->arg_target_name, 1024) + 1; | |
} | |
// Calc string lenghts for funcs | |
for (size_t i = 0; i < context->funcs_size; i++) | |
{ | |
HSFuncReg* func = &context->funcs[i]; | |
string_len += strnlen_s(func->fun_name, 1024) + 1; | |
} | |
const size_t pot_size = HScript_to_pot(string_len); | |
char* buffer = malloc(pot_size); | |
HS_ASSERT_RETURN(buffer != NULL, false); | |
memset(buffer, 0, pot_size); | |
string_len = 0; | |
#define HSScript_move_str_to_buff(arg) {\ | |
const size_t len = strnlen_s(arg, 1024) + 1; \ | |
memcpy(buffer + string_len, arg, len); \ | |
arg = buffer + string_len; \ | |
string_len += len; \ | |
} | |
// String copy for defns | |
for (size_t i = 0; i < context->defns_size; i++) | |
{ | |
HSDefn* defn = &context->defns[i]; | |
HSScript_move_str_to_buff(defn->name); | |
for (size_t j = 0; j < defn->i_size; j++) | |
{ | |
HSScript_move_str_to_buff(defn->inputs[j].name); | |
} | |
for (size_t j = 0; j < defn->o_size; j++) | |
{ | |
HSScript_move_str_to_buff(defn->outputs[j].name); | |
} | |
} | |
// String copy for nodes | |
for (size_t i = 0; i < context->nodes_size; i++) | |
{ | |
HSNode* node = &context->nodes[i]; | |
for (size_t j = 0; j < node->args_size; j++) | |
{ | |
HSScript_move_str_to_buff(node->args[j].name); | |
} | |
} | |
// String copy for links | |
for (size_t i = 0; i < context->links_size; i++) | |
{ | |
HSScript_move_str_to_buff(context->links[i].arg_source_name); | |
HSScript_move_str_to_buff(context->links[i].arg_target_name); | |
} | |
// String copy for funcs | |
for (size_t i = 0; i < context->funcs_size; i++) | |
{ | |
HSScript_move_str_to_buff(context->funcs[i].fun_name); | |
} | |
#undef HSScript_move_str_to_buff | |
if (context->string_pool != NULL) | |
{ | |
free(context->string_pool); | |
} | |
context->string_pool = buffer; | |
context->string_pool_size = string_len; | |
// -- String copy end | |
return true; | |
} | |
bool HScript_rawcontext_commit(HSRawContext* context) | |
{ | |
// -- Sort all data start | |
qsort(context->defns, context->defns_size, sizeof(HSDefn), HScript_compare_id_defn); | |
qsort(context->nodes, context->nodes_size, sizeof(HSNode), HScript_compare_id_node); | |
qsort(context->links, context->links_size, sizeof(HSLink), HScript_compare_id_link); | |
qsort(context->funcs, context->funcs_size, sizeof(HSFuncReg), HScript_compare_func); | |
// -- Sort all data end | |
HScript_rawcontext_build_nodes(context); | |
HScript_rawcontext_build_links(context); | |
HScript_rawcontext_build_string(context); | |
return true; | |
} | |
bool HScript_rawcontext_clone(HSRawContext* first, HSRawContext* second) | |
{ | |
//Don't forget to call rawcontext reset | |
HS_ASSERT_RETURN(second->defns == NULL && | |
second->funcs == NULL && | |
second->links == NULL && | |
second->nodes == NULL && | |
second->string_pool == NULL, false); | |
if (first->funcs) | |
{ | |
const bool bfunc = HScript_resize(&second->funcs, sizeof(HSFuncReg), 0, first->funcs_size); | |
HS_ASSERT_RETURN(bfunc, false); | |
memcpy(second->funcs, first->funcs, first->funcs_size * sizeof(HSFuncReg)); | |
second->funcs_size = first->funcs_size; | |
} | |
if (first->defns) | |
{ | |
const bool bdefn = HScript_resize(&second->defns, sizeof(HSDefn), 0, first->defns_size); | |
HS_ASSERT_RETURN(bdefn, false); | |
memcpy(second->defns, first->defns, first->defns_size * sizeof(HSDefn)); | |
second->defns_size = first->defns_size; | |
} | |
if (first->nodes) | |
{ | |
const bool bnode = HScript_resize(&second->nodes, sizeof(HSNode), 0, first->nodes_size); | |
HS_ASSERT_RETURN(bnode, false); | |
memcpy(second->nodes, first->nodes, first->nodes_size * sizeof(HSNode)); | |
second->nodes_size = first->nodes_size; | |
} | |
if (first->links) | |
{ | |
const bool blink = HScript_resize(&second->links, sizeof(HSLink), 0, first->links_size); | |
HS_ASSERT_RETURN(blink, false); | |
memcpy(second->links, first->links, first->links_size * sizeof(HSLink)); | |
second->links_size = first->links_size; | |
} | |
HScript_rawcontext_commit(first); | |
return true; | |
} | |
void HSFn_context_reset(HSFnContext* context) | |
{ | |
memset(context, 0, sizeof(HSFnContext)); | |
} | |
void HSFn_push_bytes(HSFnContext* context, HSByte* data, const uint32_t size) | |
{ | |
HS_ASSERT_VOID(size > 0); | |
HS_ASSERT_VOID(context->stack_pos + size < HS_FNCTX_STACK_DEFAULT_SIZE); | |
HS_ASSERT_VOID(context->stpop_len < HS_FNCTX_STACK_DEFAULT_DEPTH); | |
context->stpop[context->stpop_len] = context->stack_pos; | |
context->stpop_len++; | |
memcpy(&context->stack[context->stack_pos], data, size); | |
context->stack_pos += size; | |
} | |
bool HSFn_pop_bytes(HSFnContext* context, HSByte** data, uint32_t* size) | |
{ | |
if (context->stpop_len == 0) | |
{ | |
(*size) = 0; | |
(*data) = NULL; | |
// Make sure that your function pushed all data | |
HS_ASSERT_RETURN(false, false); | |
} | |
(*size) = context->stack_pos - context->stpop[context->stpop_len - 1]; | |
(*data) = &context->stack[context->stack_pos - (*size)]; | |
context->stpop_len--; | |
context->stack_pos = context->stpop[context->stpop_len]; | |
return true; | |
} | |
void HSFn_push_int(HSFnContext* context, int arg) | |
{ | |
HSFn_push_bytes(context, (HSByte*)&arg, sizeof(int)); | |
} | |
void HSFn_push_float(HSFnContext* context, float arg) | |
{ | |
HSFn_push_bytes(context, (HSByte*)&arg, sizeof(float)); | |
} | |
void HSFn_push_pstr(HSFnContext* context, const char* arg) | |
{ | |
HSFn_push_bytes(context, (HSByte*)&arg, sizeof(const char*)); | |
} | |
void HSFn_push_bool(HSFnContext* context, bool arg) | |
{ | |
HSFn_push_bytes(context, (HSByte*)&arg, sizeof(bool)); | |
} | |
void HSFn_push_id(HSFnContext* context, uint64_t arg) | |
{ | |
HSFn_push_bytes(context, (HSByte*)&arg, sizeof(uint64_t)); | |
} | |
void HSFn_push_pobj(HSFnContext* context, void* arg) | |
{ | |
HSFn_push_bytes(context, (HSByte*)&arg, sizeof(void*)); | |
} | |
void HSFn_push_exec(HSFnContext* context, uint32_t arg) | |
{ | |
HS_ASSERT_VOID(context->stexe_len < HS_FNCTX_STEXE_DEFAULT_SIZE); | |
HSExecPl payload; | |
payload.index = arg; | |
payload.node = 0; | |
context->stexe[context->stexe_len] = payload; | |
context->stexe_len++; | |
} | |
int HSFn_pop_int(HSFnContext* context) | |
{ | |
HSByte* data; | |
uint32_t size; | |
if (HSFn_pop_bytes(context, &data, &size)) | |
{ | |
if (size == sizeof(int)) | |
{ | |
return *((int*)data); | |
} | |
} | |
return 0; | |
} | |
float HSFn_pop_float(HSFnContext* context) | |
{ | |
HSByte* data; | |
uint32_t size; | |
if (HSFn_pop_bytes(context, &data, &size)) | |
{ | |
if (size == sizeof(float)) | |
{ | |
return *((float*)data); | |
} | |
} | |
return 0.0f; | |
} | |
const char* HSFn_pop_pstr(HSFnContext* context) | |
{ | |
HSByte* data; | |
uint32_t size; | |
if (HSFn_pop_bytes(context, &data, &size)) | |
{ | |
if (size == sizeof(const char*)) | |
{ | |
return (const char*)data; | |
} | |
} | |
return ""; | |
} | |
bool HSFn_pop_bool(HSFnContext* context) | |
{ | |
HSByte* data; | |
uint32_t size; | |
if (HSFn_pop_bytes(context, &data, &size)) | |
{ | |
if (size == sizeof(bool)) | |
{ | |
return *((bool*)data); | |
} | |
} | |
return false; | |
} | |
uint64_t HSFn_pop_id(HSFnContext* context) | |
{ | |
HSByte* data; | |
uint32_t size; | |
if (HSFn_pop_bytes(context, &data, &size)) | |
{ | |
if (size == sizeof(uint64_t)) | |
{ | |
return *((uint64_t*)data); | |
} | |
} | |
return HS_NIL_VALUE; | |
} | |
void* HSFn_pop_pobj(HSFnContext* context) | |
{ | |
HSByte* data; | |
uint32_t size; | |
if (HSFn_pop_bytes(context, &data, &size)) | |
{ | |
if (size == sizeof(uint64_t)) | |
{ | |
return (void*)data; | |
} | |
} | |
return NULL; | |
} | |
bool HSFn_pop_exec(HSFnContext* context, uintptr_t* arg) | |
{ | |
if (context->stexe_len == 0) | |
{ | |
return false; | |
} | |
context->stexe_len--; | |
(*arg) = context->stexe[context->stexe_len].node; | |
return true; | |
} | |
HSExecPl* HSFn_peek_exec(HSFnContext* context, size_t index) | |
{ | |
if (index >= HS_FNCTX_STEXE_DEFAULT_SIZE) | |
{ | |
return false; | |
} | |
return &context->stexe[context->stexe_len - index - 1]; | |
} | |
void HSFn_push_loopb(HSFnContext* context, uint32_t index) | |
{ | |
HS_ASSERT_VOID(context->loopb_len < HS_FNCTX_LOOPB_DEFAULT_SIZE); | |
context->loopb[context->loopb_len].payload = context->node; | |
context->loopb[context->loopb_len].index = index; | |
context->loopb_len++; | |
} | |
bool HSFn_pop_loopb(HSFnContext* context, uintptr_t* loopback_node) | |
{ | |
if (context->loopb_len == 0) | |
{ | |
return false; | |
} | |
context->loopb_len--; | |
(*loopback_node) = context->loopb[context->loopb_len].payload; | |
return true; | |
} | |
bool HSFn_check_loopb(HSFnContext* context, uint32_t* index) | |
{ | |
HSLoopPl* pl = &context->loopb[context->loopb_len]; | |
if (pl->payload == context->node) | |
{ | |
(*index) = context->loopb[context->loopb_len].index; | |
return true; | |
} | |
return false; | |
} | |
void HScript_rawcontext_initialize(HSRawContext* context) | |
{ | |
context->funcs = NULL; | |
context->defns = NULL; | |
context->nodes = NULL; | |
context->links = NULL; | |
context->funcs_size = 0; | |
context->defns_size = 0; | |
context->links_size = 0; | |
context->nodes_size = 0; | |
context->string_pool_size = 0; | |
context->string_pool = NULL; | |
srand(HS_RANDOM_HASH_SEED); | |
} | |
void HScript_rawcontext_reset(HSRawContext* context) | |
{ | |
for (size_t i = 0; i < context->defns_size; i++) | |
{ | |
HSDefn* defn = &context->defns[i]; | |
if (defn->inputs) | |
{ | |
free(defn->inputs); | |
defn->inputs = NULL; | |
defn->i_size = 0; | |
} | |
if (defn->outputs) | |
{ | |
free(defn->outputs); | |
defn->outputs = NULL; | |
defn->o_size = 0; | |
} | |
} | |
for (size_t i = 0; i < context->nodes_size; i++) | |
{ | |
HSNode* node = &context->nodes[i]; | |
if (node->args) | |
{ | |
free(node->args); | |
node->args = NULL; | |
node->args_size = 0; | |
} | |
} | |
context->funcs_size = 0; | |
context->defns_size = 0; | |
context->links_size = 0; | |
context->nodes_size = 0; | |
context->string_pool_size = 0; | |
HS_RELEASE(context->string_pool); | |
HS_RELEASE(context->funcs); | |
HS_RELEASE(context->defns); | |
HS_RELEASE(context->nodes); | |
HS_RELEASE(context->links); | |
} | |
void HScript_func_push(HSRawContext* context, HSFuncReg* func) | |
{ | |
const bool success = HScript_resize(&context->funcs, sizeof(HSFuncReg), context->funcs_size, context->funcs_size + 1); | |
HS_ASSERT(success); | |
context->funcs[context->funcs_size] = *func; | |
context->funcs_size++; | |
} | |
HSDefn* HScript_defn_push(HSRawContext* context, HSDefn* defn) | |
{ | |
const bool success = HScript_resize(&context->defns, sizeof(HSDefn), context->defns_size, context->defns_size + 1); | |
HS_ASSERT_RETURN(success, NULL); | |
HSDefn* new_defn = &context->defns[context->defns_size]; | |
*new_defn = *defn; | |
context->defns_size++; | |
new_defn->inputs = NULL; | |
new_defn->i_size = 0; | |
new_defn->outputs = NULL; | |
new_defn->o_size = 0; | |
if (defn->inputs != NULL && defn->i_size > 0) | |
{ | |
HScript_defn_input_push_many(context, new_defn, defn->inputs, defn->i_size); | |
} | |
if (defn->outputs != NULL && defn->o_size > 0) | |
{ | |
HScript_defn_output_push_many(context, new_defn, defn->outputs, defn->o_size); | |
} | |
return new_defn; | |
} | |
HSNode* HScript_node_push(HSRawContext* context, HSNode* node) | |
{ | |
const bool success = HScript_resize(&context->nodes, sizeof(HSNode), context->nodes_size, context->nodes_size + 1); | |
HS_ASSERT_RETURN(success, NULL); | |
HSNode* new_node = &context->nodes[context->nodes_size]; | |
*new_node = *node; | |
context->nodes_size++; | |
new_node->args = NULL; | |
new_node->args_size = 0; | |
new_node->i_size = 0; | |
if (node->args != NULL && node->args_size > 0) | |
{ | |
HScript_node_arg_push_many(context, node, new_node->args, new_node->args_size); | |
} | |
return new_node; | |
} | |
HSLink* HScript_link_push(HSRawContext* context, HSLink* link) | |
{ | |
const bool success = HScript_resize(&context->links, sizeof(HSLink), context->links_size, context->links_size + 1); | |
HS_ASSERT_RETURN(success, NULL); | |
HSLink* new_link = &context->links[context->links_size]; | |
*new_link = *link; | |
context->links_size++; | |
return new_link; | |
} | |
void HScript_defn_remove(HSRawContext* context, HSDefn* defn) | |
{ | |
if ((uintptr_t)defn >= (uintptr_t) context->defns && | |
(uintptr_t)defn < (uintptr_t)&context->defns[context->nodes_size]) | |
{ | |
size_t idx = (defn - context->defns); | |
memmove(context->defns, context->defns + 1, context->defns_size - idx); | |
context->defns_size--; | |
} | |
else | |
{ | |
HS_ASSERT(false); | |
} | |
} | |
void HScript_node_remove(HSRawContext* context, HSNode* node) | |
{ | |
if ((uintptr_t)node >= (uintptr_t) context->nodes && | |
(uintptr_t)node < (uintptr_t)&context->nodes[context->nodes_size]) | |
{ | |
size_t idx = (node - context->nodes); | |
memmove(context->nodes, context->nodes + 1, context->nodes_size - idx); | |
context->nodes_size--; | |
} | |
else | |
{ | |
HS_ASSERT(false); | |
} | |
} | |
void HScript_link_remove(HSRawContext* context, HSLink* link) | |
{ | |
if ((uintptr_t)link >= (uintptr_t) context->links && | |
(uintptr_t)link < (uintptr_t)&context->links[context->links_size]) | |
{ | |
size_t idx = (link - context->links); | |
memmove(context->links, context->links + 1, context->links_size - idx); | |
context->links_size--; | |
} | |
else | |
{ | |
HS_ASSERT(false); | |
} | |
} | |
void HScript_node_arg_push(HSRawContext* context, HSNode* node, HSNodeArg* arg) | |
{ | |
HS_ASSERT(HScript_node_find_argument(node, arg->name) == NULL); | |
const bool success = HScript_resize(&node->args, sizeof(HSNodeArg), node->args_size, node->args_size + 1); | |
HS_ASSERT(success); | |
arg->cnode = NULL; | |
arg->carg = 0; | |
node->args[node->args_size] = *arg; | |
++node->args_size; | |
} | |
void HScript_defn_input_push(HSRawContext* context, HSDefn* defn, HSDefnArg* arg) | |
{ | |
HS_ASSERT(HScript_defn_find_argument(defn, arg->name) == NULL); | |
const bool success = HScript_resize(&defn->inputs, sizeof(HSDefnArg), defn->i_size, defn->i_size + 1); | |
HS_ASSERT(success); | |
defn->inputs[defn->i_size] = *arg; | |
++defn->i_size; | |
} | |
void HScript_defn_output_push(HSRawContext* context, HSDefn* defn, HSDefnArg* arg) | |
{ | |
HS_ASSERT(HScript_defn_find_argument(defn, arg->name) == NULL); | |
const bool success = HScript_resize(&defn->outputs, sizeof(HSDefnArg), defn->o_size, defn->o_size + 1); | |
HS_ASSERT(success); | |
defn->outputs[defn->o_size] = *arg; | |
++defn->o_size; | |
} | |
void HScript_node_arg_push_many(HSRawContext* context, HSNode* node, HSNodeArg* arg, size_t arg_size) | |
{ | |
const bool success = HScript_resize(&node->args, sizeof(HSNodeArg), node->args_size, node->args_size + arg_size); | |
HS_ASSERT(success); | |
memcpy(&(node->args[node->args_size]), arg, arg_size * sizeof(HSNodeArg)); | |
node->args_size += arg_size; | |
} | |
void HScript_defn_input_push_many(HSRawContext* context, HSDefn* defn, HSDefnArg* arg, size_t arg_size) | |
{ | |
const bool success = HScript_resize(&defn->inputs, sizeof(HSDefnArg), defn->i_size, defn->i_size + arg_size); | |
HS_ASSERT(success); | |
memcpy(&(defn->inputs[defn->i_size]), arg, arg_size * sizeof(HSDefnArg)); | |
defn->i_size += arg_size; | |
} | |
void HScript_defn_output_push_many(HSRawContext* context, HSDefn* defn, HSDefnArg* arg, size_t arg_size) | |
{ | |
const bool success = HScript_resize(&defn->outputs, sizeof(HSDefnArg), defn->o_size, defn->o_size + arg_size); | |
HS_ASSERT(success); | |
memcpy(&(defn->outputs[defn->o_size]), arg, arg_size * sizeof(HSDefnArg)); | |
defn->o_size += arg_size; | |
} | |
void HScript_node_arg_remove(HSRawContext* context, HSNode* node, HSNodeArg* arg) | |
{ | |
if ((uintptr_t)arg >= (uintptr_t) node->args && | |
(uintptr_t)arg < (uintptr_t) (node->args + node->args_size)) | |
{ | |
const size_t tail = (size_t)(node->args + node->args_size - arg - 1); | |
memmove(arg, arg + 1, (size_t)(node->args + node->args_size - arg) * sizeof(HSNodeArg)); | |
const bool success = HScript_resize(&node->args, sizeof(HSNodeArg), node->args_size, node->args_size - 1); | |
if (success) | |
{ | |
node->args_size--; | |
} | |
} | |
else | |
{ | |
HS_ASSERT(false); | |
} | |
} | |
void HScript_defn_input_remove(HSRawContext* context, HSDefn* defn, HSDefnArg* arg) | |
{ | |
if ((uintptr_t)arg >= (uintptr_t) defn->inputs && | |
(uintptr_t)arg < (uintptr_t)(defn->inputs + defn->i_size)) | |
{ | |
const size_t tail = (size_t)(defn->inputs + defn->i_size - arg - 1); | |
memmove(arg, arg + 1, tail * sizeof(HSNodeArg)); | |
const bool success = HScript_resize(&defn->inputs, sizeof(HSNodeArg), defn->i_size, defn->i_size - 1); | |
if (success) | |
{ | |
defn->i_size--; | |
} | |
} | |
else | |
{ | |
HS_ASSERT(false); | |
} | |
} | |
void HScript_defn_output_remove(HSRawContext* context, HSDefn* defn, HSDefnArg* arg) | |
{ | |
if ((uintptr_t)arg >= (uintptr_t) defn->outputs && | |
(uintptr_t)arg < (uintptr_t)(defn->outputs + defn->o_size)) | |
{ | |
const size_t tail = (size_t)(defn->outputs + defn->o_size - arg - 1); | |
memmove(arg, arg + 1, tail * sizeof(HSNodeArg)); | |
const bool success = HScript_resize(&defn->outputs, sizeof(HSNodeArg), defn->o_size, defn->o_size - 1); | |
if (success) | |
{ | |
defn->o_size--; | |
} | |
} | |
else | |
{ | |
HS_ASSERT(false); | |
} | |
} | |
void HScript_strcontext_initialize(HSStrContext* context) | |
{ | |
context->strs = NULL; | |
context->arr_size = 0; | |
} | |
void HScript_strcontext_reset(HSStrContext* context) | |
{ | |
if (context->strs) | |
{ | |
for (size_t i = 0; i < context->arr_size; i++) | |
{ | |
free(context->strs[i]); | |
context->strs[i] = NULL; | |
} | |
free(context->strs); | |
context->strs = NULL; | |
} | |
context->arr_size = 0; | |
} | |
char* HScript_strcontext_push(HSStrContext* context, const char* string, size_t len) | |
{ | |
HS_ASSERT_RETURN(len != 0, NULL); | |
const bool success = HScript_resize((void**)&context->strs, sizeof(char*), context->arr_size, context->arr_size + 1); | |
HS_ASSERT_RETURN(success, NULL); | |
char** out_str = &context->strs[context->arr_size]; | |
(*out_str) = malloc(len + 1); | |
HS_ASSERT_RETURN(*out_str, NULL); | |
memcpy(*out_str, string, len); | |
(*out_str)[len] = 0; | |
context->arr_size++; | |
return *out_str; | |
} | |
void HScript_interpret_call(HSRawContext* context, HSFnContext* fn_context, HSNode* node) | |
{ | |
if (node->func == NULL) | |
{ | |
return; | |
} | |
for (size_t i = 0; i < node->i_size; i++) | |
{ | |
HSNodeArg* node_arg = &node->args[i]; | |
switch (node_arg->type) | |
{ | |
case HS_INT: | |
{ | |
HSFn_push_int(fn_context, node_arg->value.as_int); | |
} | |
break; | |
case HS_FLOAT: | |
{ | |
HSFn_push_float(fn_context, node_arg->value.as_float); | |
} | |
break; | |
case HS_BOOLEAN: | |
{ | |
HSFn_push_bool(fn_context, node_arg->value.as_bool); | |
} | |
break; | |
case HS_ENTITY: | |
{ | |
HSFn_push_pobj(fn_context, node_arg->value.as_object); | |
} | |
break; | |
case HS_OBJECT: | |
{ | |
HSFn_push_pobj(fn_context, node_arg->value.as_object); | |
} | |
break; | |
} | |
} | |
fn_context->node = (uintptr_t)node; | |
node->func(fn_context); | |
//if (fn_context->stexe_len == 0) | |
//{ | |
// HSFn_push_exec(fn_context, 0); | |
//} | |
size_t exec_index = 0; | |
for (size_t i = node->i_size; i < node->args_size; i++) | |
{ | |
HSNodeArg* node_arg = &node->args[i]; | |
switch (node_arg->type) | |
{ | |
case HS_INT: | |
{ | |
node_arg->value.as_int = HSFn_pop_int(fn_context); | |
} | |
break; | |
case HS_FLOAT: | |
{ | |
node_arg->value.as_float = HSFn_pop_float(fn_context); | |
} | |
break; | |
case HS_BOOLEAN: | |
{ | |
node_arg->value.as_bool = HSFn_pop_bool(fn_context); | |
} | |
break; | |
case HS_ENTITY: | |
{ | |
node_arg->value.as_object = HSFn_pop_pobj(fn_context); | |
} | |
break; | |
case HS_OBJECT: | |
{ | |
node_arg->value.as_object = HSFn_pop_pobj(fn_context); | |
} | |
break; | |
} | |
// Check if we have next node in chain | |
HSNode* target_node = node_arg->cnode; | |
if (target_node == NULL) | |
{ | |
continue; | |
} | |
// Apply value | |
HSNodeArg* target_arg = &target_node->args[node_arg->carg]; | |
target_arg->value = node_arg->value; | |
// Do nothing if thats not execution pin | |
if (node_arg->type != HS_EXECUTION) | |
{ | |
continue; | |
} | |
// Push execution to loop | |
size_t j = 0; | |
HSExecPl* exec; | |
while (exec = HSFn_peek_exec(fn_context, j)) | |
{ | |
if (exec->index == exec_index) | |
{ | |
exec_index++; | |
exec->node = (intptr_t)target_node; | |
} | |
j++; | |
} | |
} | |
} | |
bool HScript_interpret(HSRawContext* context, HSFnContext* fn_context) | |
{ | |
HS_ASSERT_RETURN(context != NULL && fn_context != NULL, false); | |
bool loop = true; | |
while (loop) | |
{ | |
uintptr_t node = 0; | |
loop = HSFn_pop_exec(fn_context, &node); | |
if (node) | |
{ | |
HScript_interpret_call(context, fn_context, (HSNode*)node); | |
node = 0; | |
} | |
uintptr_t loopb = 0; | |
if (!loop && HSFn_pop_loopb(fn_context, &loopb)) | |
{ | |
loop = true; | |
HScript_interpret_call(context, fn_context, (HSNode*)loopb); | |
} | |
} | |
return false; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment