aboutsummaryrefslogtreecommitdiff
path: root/api
diff options
context:
space:
mode:
Diffstat (limited to 'api')
-rwxr-xr-xapi/api.sobin0 -> 31832 bytes
-rw-r--r--api/bool.c51
-rw-r--r--api/bool.h12
-rw-r--r--api/int.c11
-rw-r--r--api/int.h8
-rw-r--r--api/nil.c37
-rw-r--r--api/nil.h10
-rw-r--r--api/str.c32
-rw-r--r--api/str.h9
-rw-r--r--api/vm.c104
-rw-r--r--api/vm.h99
11 files changed, 373 insertions, 0 deletions
diff --git a/api/api.so b/api/api.so
new file mode 100755
index 0000000..d6eb8e5
--- /dev/null
+++ b/api/api.so
Binary files differ
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