diff options
Diffstat (limited to 'api')
-rwxr-xr-x | api/api.so | bin | 0 -> 31832 bytes | |||
-rw-r--r-- | api/bool.c | 51 | ||||
-rw-r--r-- | api/bool.h | 12 | ||||
-rw-r--r-- | api/int.c | 11 | ||||
-rw-r--r-- | api/int.h | 8 | ||||
-rw-r--r-- | api/nil.c | 37 | ||||
-rw-r--r-- | api/nil.h | 10 | ||||
-rw-r--r-- | api/str.c | 32 | ||||
-rw-r--r-- | api/str.h | 9 | ||||
-rw-r--r-- | api/vm.c | 104 | ||||
-rw-r--r-- | api/vm.h | 99 |
11 files changed, 373 insertions, 0 deletions
diff --git a/api/api.so b/api/api.so Binary files differnew file mode 100755 index 0000000..d6eb8e5 --- /dev/null +++ b/api/api.so diff --git a/api/bool.c b/api/bool.c new file mode 100644 index 0000000..2857f0b --- /dev/null +++ b/api/bool.c @@ -0,0 +1,51 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "bool.h" +#include "nil.h" + +UwUVMValue uwubool_create(bool value) +{ + UwUVMValue vm_value = { + .type = VT_NAT, + .value = { + .nat_value = { + .type = &uwubool_type, + .data = malloc(sizeof(bool)) + }, + }, + }; + + *(bool *) vm_value.value.nat_value.data = value; + return vm_value; +} + +bool uwubool_get(UwUVMValue vm_value) +{ + if (vm_value.type != VT_NAT) + return true; + else if (vm_value.value.nat_value.type == &uwunil_type) + return false; + else if (vm_value.value.nat_value.type == &uwubool_type) + return *(bool *) vm_value.value.nat_value.data; + else + return true; +} + +static void *uwubool_copy(void *data) +{ + bool *copy = malloc(sizeof(*copy)); + *copy = *(bool *) data; + return copy; +} + +static char *uwubool_print(void *data) +{ + return strdup(((bool *) data) ? "true" : "false"); +} + +UwUVMNativeType uwubool_type = { + .copy = &uwubool_copy, + .delete = &free, + .print = &uwubool_print, +}; diff --git a/api/bool.h b/api/bool.h new file mode 100644 index 0000000..2299177 --- /dev/null +++ b/api/bool.h @@ -0,0 +1,12 @@ +#ifndef _API_BOOL_H_ +#define _API_BOOL_H_ + +#include <stdbool.h> +#include "vm.h" + +extern UwUVMNativeType uwubool_type; + +UwUVMValue uwubool_create(bool value); +bool uwubool_get(UwUVMValue vm_value); + +#endif diff --git a/api/int.c b/api/int.c new file mode 100644 index 0000000..aea8e26 --- /dev/null +++ b/api/int.c @@ -0,0 +1,11 @@ +#include "int.h" + +UwUVMValue uwuint_create(int value) +{ + return (UwUVMValue) { + .type = VT_INT, + .value = { + .int_value = value, + }, + }; +} diff --git a/api/int.h b/api/int.h new file mode 100644 index 0000000..fd284c7 --- /dev/null +++ b/api/int.h @@ -0,0 +1,8 @@ +#ifndef _API_INT_H_ +#define _API_INT_H_ + +#include "vm.h" + +UwUVMValue uwuint_create(int value); + +#endif diff --git a/api/nil.c b/api/nil.c new file mode 100644 index 0000000..a9c54cc --- /dev/null +++ b/api/nil.c @@ -0,0 +1,37 @@ +#include <string.h> +#include "nil.h" + +UwUVMValue uwunil_create() +{ + return (UwUVMValue) { + .type = VT_NAT, + .value = { + .nat_value = { + .type = &uwunil_type, + .data = NULL, + } + } + }; +} + +static void *uwunil_copy(void *data) +{ + return data; +} + +static void uwunil_delete(void *data) +{ + (void) data; +} + +static char *uwunil_print(void *data) +{ + (void) data; + return strdup(""); +} + +UwUVMNativeType uwunil_type = { + .copy = &uwunil_copy, + .delete = &uwunil_delete, + .print = &uwunil_print, +}; diff --git a/api/nil.h b/api/nil.h new file mode 100644 index 0000000..22df640 --- /dev/null +++ b/api/nil.h @@ -0,0 +1,10 @@ +#ifndef _API_NIL_H +#define _API_NIL_H + +#include "vm.h" + +extern UwUVMNativeType uwunil_type; + +UwUVMValue uwunil_create(); + +#endif diff --git a/api/str.c b/api/str.c new file mode 100644 index 0000000..c634fc2 --- /dev/null +++ b/api/str.c @@ -0,0 +1,32 @@ +#include <string.h> +#include "../src/util.h" +#include "str.h" + +UwUVMValue uwustr_create(const char *value) +{ + return (UwUVMValue) { + .type = VT_STR, + .value = { + .str_value = strdup(value), + }, + }; +} + +char *uwustr_get(UwUVMValue vm_value) +{ + switch (vm_value.type) { + case VT_INT: + return asprintf_wrapper("%d", vm_value.value.int_value); + + case VT_STR: + return strdup(vm_value.value.str_value); + + case VT_REF: + return asprintf_wrapper("[Function reference: %p]", vm_value.value.ref_value); + + case VT_NAT: + return vm_value.value.nat_value.type->print + ? vm_value.value.nat_value.type->print(vm_value.value.nat_value.data) + : asprintf_wrapper("[Native value: %p: %p]", vm_value.value.nat_value.data, vm_value.value.nat_value.type); + } +} diff --git a/api/str.h b/api/str.h new file mode 100644 index 0000000..b035f2a --- /dev/null +++ b/api/str.h @@ -0,0 +1,9 @@ +#ifndef _API_STR_H_ +#define _API_STR_H_ + +#include "vm.h" + +UwUVMValue uwustr_create(const char *value); +char *uwustr_get(UwUVMValue vm_value); + +#endif diff --git a/api/vm.c b/api/vm.c new file mode 100644 index 0000000..547805c --- /dev/null +++ b/api/vm.c @@ -0,0 +1,104 @@ +#include <stdio.h> +#include <stdlib.h> +#include "../src/err.h" +#include "vm.h" +#include "str.h" +#include "int.h" + +void uwuvm_free_value(UwUVMValue value) +{ + if (value.type == VT_STR) + free(value.value.str_value); + else if (value.type == VT_NAT) + value.value.nat_value.type->delete(value.value.nat_value.data); +} + +void uwuvm_free_args(UwUVMArgs *args) +{ + if (args->evaluated) { + for (size_t i = 0; i < args->num; i++) { + UwUVMValue *value = args->evaluated[i]; + + if (value) { + uwuvm_free_value(*value); + free(value); + } + } + + free(args->evaluated); + } +} + +UwUVMValue uwuvm_copy_value(UwUVMValue value) +{ + if (value.type == VT_STR) + return uwustr_create(value.value.str_value); + else if (value.type == VT_NAT) + return (UwUVMValue) { + .type = value.type, + .value = { + .nat_value = { + .type = value.value.nat_value.type, + .data = value.value.nat_value.type->copy(value.value.nat_value.data), + } + } + }; + else + return value; +} + +UwUVMValue uwuvm_get_arg(UwUVMArgs *args, size_t i) +{ + if (! args->evaluated[i]) { + args->evaluated[i] = malloc(sizeof(UwUVMValue)); + *(args->evaluated[i]) = uwuvm_evaluate_expression(&args->unevaluated[i], args->super); + } + + return *(args->evaluated[i]); +} + +UwUVMValue uwuvm_evaluate_expression(UwUVMExpression *expression, UwUVMArgs *args) +{ + switch (expression->type) { + case EX_INTLIT: + return uwuint_create(expression->value.int_value); + + case EX_STRLIT: + return uwustr_create(expression->value.str_value); + + case EX_ARGNUM: + if ((size_t) expression->value.int_value >= args->num) + error("error: not enough arguments (accessed argument $%d, but only %lu arguments were passed)\n", expression->value.int_value, args->num); + + return uwuvm_copy_value(uwuvm_get_arg(args, expression->value.int_value)); + + case EX_FNNAME: + return (UwUVMValue) { + .type = VT_REF, + .value = { + .ref_value = expression->value.ref_value, + }, + }; + + case EX_FNCALL: + return uwuvm_run_function(expression->value.cll_value.function, (UwUVMArgs) { + .num = expression->value.cll_value.num_args, + .evaluated = expression->value.cll_value.num_args == 0 ? NULL : calloc(expression->value.cll_value.num_args, sizeof(UwUVMValue *)), + .unevaluated = expression->value.cll_value.args, + .super = args, + }); + + default: + return (UwUVMValue) {}; + } +} + +UwUVMValue uwuvm_run_function(UwUVMFunction *function, UwUVMArgs args) +{ + UwUVMValue value = function->type == MODULE_PLAIN + ? uwuvm_evaluate_expression(function->value.plain, &args) + : function->value.native(&args); + + uwuvm_free_args(&args); + return value; +} diff --git a/api/vm.h b/api/vm.h new file mode 100644 index 0000000..94103d5 --- /dev/null +++ b/api/vm.h @@ -0,0 +1,99 @@ +#ifndef _API_VM_H_ +#define _API_VM_H_ + +#include <stddef.h> +#include <stdbool.h> +#include "../src/expression.h" + +typedef enum +{ + MODULE_PLAIN, + MODULE_NATIVE, +} UwUVMModuleType; + +typedef struct +{ + void *(*copy )(void *data); + void (*delete)(void *data); + char *(*print )(void *data); +} UwUVMNativeType; + +typedef struct +{ + void *data; + UwUVMNativeType *type; +} UwUVMNativeValue; + +typedef struct UwUVMArgs +{ + size_t num; + struct UwUVMValue **evaluated; + struct UwUVMExpression *unevaluated; + struct UwUVMArgs *super; +} UwUVMArgs; + +typedef struct UwUVMValue (*UwUVMNativeFunction)(UwUVMArgs *args); + +typedef struct +{ + UwUVMModuleType type; + union + { + struct UwUVMExpression *plain; + UwUVMNativeFunction native; + } value; +} UwUVMFunction; + +typedef struct UwUVMValue +{ + enum + { + VT_INT, + VT_STR, + VT_REF, + VT_NAT, + } type; + union + { + int int_value; + char *str_value; + UwUVMFunction *ref_value; + UwUVMNativeValue nat_value; + } value; +} UwUVMValue; + +typedef struct UwUVMExpression +{ + ExpressionType type; + union + { + struct + { + UwUVMFunction *function; + struct UwUVMExpression *args; + size_t num_args; + } cll_value; + int int_value; + char *str_value; + UwUVMFunction *ref_value; + } value; +} UwUVMExpression; + +typedef struct +{ + void *api_library; + UwUVMFunction *main_function; + UwUVMFunction **functions; + size_t num_functions; + void **libraries; + size_t num_libraries; +} UwUVMProgram; + +void uwuvm_free_value(UwUVMValue value); +void uwuvm_free_args(UwUVMArgs *args); +UwUVMValue uwuvm_copy_value(UwUVMValue value); +UwUVMValue uwuvm_get_arg(UwUVMArgs *args, size_t i); +UwUVMValue uwuvm_evaluate_expression(UwUVMExpression *expression, UwUVMArgs *args); +UwUVMValue uwuvm_run_function(UwUVMFunction *function, UwUVMArgs args); + +#endif |