aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--api/bool.c6
-rw-r--r--api/bool.h5
-rw-r--r--api/int.c11
-rw-r--r--api/int.h4
-rw-r--r--api/nil.c8
-rw-r--r--api/nil.h3
-rw-r--r--api/ref.c17
-rw-r--r--api/ref.h4
-rw-r--r--api/str.c8
-rw-r--r--api/str.h5
-rw-r--r--api/util.c15
-rw-r--r--api/util.h8
-rw-r--r--api/vm.c74
-rw-r--r--api/vm.h14
-rw-r--r--doc/std.md32
-rw-r--r--src/vm.c6
-rw-r--r--std/bool.c13
-rw-r--r--std/int.c16
-rw-r--r--std/nil.c6
-rw-r--r--std/ref.c21
-rw-r--r--std/str.c6
22 files changed, 170 insertions, 114 deletions
diff --git a/Makefile b/Makefile
index 8dbf5d8..17c6922 100644
--- a/Makefile
+++ b/Makefile
@@ -5,7 +5,7 @@ uwu: src/*.c src/*.h
.PHONY: std api
-std: std/bool.so std/int.so std/str.so std/nil.so
+std: std/bool.so std/int.so std/str.so std/nil.so std/ref.so
api: api/api.so
std/%.so: std/%.c
diff --git a/api/bool.c b/api/bool.c
index 4cbc3f3..768ae2f 100644
--- a/api/bool.c
+++ b/api/bool.c
@@ -25,7 +25,7 @@ bool uwubool_get(UwUVMValue vm_value)
return true;
}
-static void *uwubool_copy(void *data)
+static void *uwubool_clone(void *data)
{
bool *copy = malloc(sizeof(*copy));
*copy = *(bool *) data;
@@ -38,7 +38,7 @@ static char *uwubool_print(void *data)
}
UwUVMType uwubool_type = {
- .copy = &uwubool_copy,
- .delete = &free,
+ .clone = &uwubool_clone,
+ .delet = &free,
.print = &uwubool_print,
};
diff --git a/api/bool.h b/api/bool.h
index 70dfd60..2e43f78 100644
--- a/api/bool.h
+++ b/api/bool.h
@@ -5,8 +5,7 @@
#include "vm.h"
extern UwUVMType uwubool_type;
-
-UwUVMValue uwubool_create(bool value);
-bool uwubool_get(UwUVMValue vm_value);
+UwUVMValue uwubool_create(bool value);
+bool uwubool_get(UwUVMValue vm_value);
#endif
diff --git a/api/int.c b/api/int.c
index 0b9329d..8446d1d 100644
--- a/api/int.c
+++ b/api/int.c
@@ -13,7 +13,12 @@ UwUVMValue uwuint_create(int value)
return vm_value;
}
-void *uwuint_copy(void *data)
+int uwuint_get(UwUVMValue vm_value)
+{
+ return *(int *) vm_value.data;
+}
+
+void *uwuint_clone(void *data)
{
int *copy = malloc(sizeof(*copy));
*copy = *(int *) data;
@@ -26,7 +31,7 @@ char *uwuint_print(void *data)
}
UwUVMType uwuint_type = {
- .copy = &uwuint_copy,
- .delete = &free,
+ .clone = &uwuint_clone,
+ .delet = &free,
.print = &uwuint_print,
};
diff --git a/api/int.h b/api/int.h
index e9c5798..6b5361d 100644
--- a/api/int.h
+++ b/api/int.h
@@ -4,7 +4,7 @@
#include "vm.h"
extern UwUVMType uwuint_type;
-
-UwUVMValue uwuint_create(int value);
+UwUVMValue uwuint_create(int value);
+int uwuint_get(UwUVMValue vm_value);
#endif
diff --git a/api/nil.c b/api/nil.c
index b6304e0..2c47cb6 100644
--- a/api/nil.c
+++ b/api/nil.c
@@ -9,12 +9,12 @@ UwUVMValue uwunil_create()
};
}
-static void *uwunil_copy(void *data)
+static void *uwunil_clone(void *data)
{
return data;
}
-static void uwunil_delete(void *data)
+static void uwunil_delet(void *data)
{
(void) data;
}
@@ -26,7 +26,7 @@ static char *uwunil_print(void *data)
}
UwUVMType uwunil_type = {
- .copy = &uwunil_copy,
- .delete = &uwunil_delete,
+ .clone = &uwunil_clone,
+ .delet = &uwunil_delet,
.print = &uwunil_print,
};
diff --git a/api/nil.h b/api/nil.h
index 014be45..7b2a5cf 100644
--- a/api/nil.h
+++ b/api/nil.h
@@ -4,7 +4,6 @@
#include "vm.h"
extern UwUVMType uwunil_type;
-
-UwUVMValue uwunil_create();
+UwUVMValue uwunil_create();
#endif
diff --git a/api/ref.c b/api/ref.c
index f66ae19..43eb68e 100644
--- a/api/ref.c
+++ b/api/ref.c
@@ -1,20 +1,25 @@
#include "../src/util.h"
#include "ref.h"
-UwUVMValue uwuref_create(UwUVMFunction *function)
+UwUVMValue uwuref_create(UwUVMFunction *value)
{
return (UwUVMValue) {
.type = &uwuref_type,
- .data = function,
+ .data = value,
};
}
-static void *uwuref_copy(void *data)
+UwUVMFunction *uwuref_get(UwUVMValue value)
+{
+ return value.data;
+}
+
+static void *uwuref_clone(void *data)
{
return data;
}
-static void uwuref_delete(void *data)
+static void uwuref_delet(void *data)
{
(void) data;
}
@@ -25,7 +30,7 @@ static char *uwuref_print(void *data)
}
UwUVMType uwuref_type = {
- .copy = &uwuref_copy,
- .delete = &uwuref_delete,
+ .clone = &uwuref_clone,
+ .delet = &uwuref_delet,
.print = &uwuref_print,
};
diff --git a/api/ref.h b/api/ref.h
index 6a2fead..4bbe017 100644
--- a/api/ref.h
+++ b/api/ref.h
@@ -4,7 +4,7 @@
#include "vm.h"
extern UwUVMType uwuref_type;
-
-UwUVMValue uwuref_create(UwUVMFunction *function);
+UwUVMValue uwuref_create(UwUVMFunction *value);
+UwUVMFunction *uwuref_get(UwUVMValue vm_value);
#endif
diff --git a/api/str.c b/api/str.c
index 84d2b10..eefd0d7 100644
--- a/api/str.c
+++ b/api/str.c
@@ -12,10 +12,10 @@ UwUVMValue uwustr_create(const char *value)
char *uwustr_get(UwUVMValue vm_value)
{
- vm_value.type->print(vm_value.data);
+ return uwuvm_print_value(vm_value);
}
-static void *uwustr_copy(void *data)
+static void *uwustr_clone(void *data)
{
return strdup(data);
}
@@ -26,7 +26,7 @@ static char *uwustr_print(void *data)
}
UwUVMType uwustr_type = {
- .copy = &uwustr_copy,
- .delete = &free,
+ .clone = &uwustr_clone,
+ .delet = &free,
.print = &uwustr_print,
};
diff --git a/api/str.h b/api/str.h
index 609328e..d7596fc 100644
--- a/api/str.h
+++ b/api/str.h
@@ -4,8 +4,7 @@
#include "vm.h"
extern UwUVMType uwustr_type;
-
-UwUVMValue uwustr_create(const char *value);
-char *uwustr_get(UwUVMValue vm_value);
+UwUVMValue uwustr_create(const char *value);
+char *uwustr_get(UwUVMValue vm_value);
#endif
diff --git a/api/util.c b/api/util.c
new file mode 100644
index 0000000..c3e8a38
--- /dev/null
+++ b/api/util.c
@@ -0,0 +1,15 @@
+#include "../src/err.h"
+#include "util.h"
+#include "bool.h"
+
+UwUVMValue uwuutil_is_type(const char *fnname, UwUVMArgs *args, UwUVMType *type)
+{
+ if (args->num < 1)
+ error("error: %s requires at least one argument\n", fnname);
+
+ for (size_t i = 0; i < args->num; i++)
+ if (uwuvm_get_arg(args, i).type != type)
+ return uwubool_create(false);
+
+ return uwubool_create(true);
+}
diff --git a/api/util.h b/api/util.h
new file mode 100644
index 0000000..259f53a
--- /dev/null
+++ b/api/util.h
@@ -0,0 +1,8 @@
+#ifndef _API_UTIL_H_
+#define _API_UTIL_H_
+
+#include "vm.h"
+
+UwUVMValue uwuutil_is_type(const char *fnname, UwUVMArgs *args, UwUVMType *type);
+
+#endif
diff --git a/api/vm.c b/api/vm.c
index 73ec87e..5cab6c0 100644
--- a/api/vm.c
+++ b/api/vm.c
@@ -6,33 +6,22 @@
#include "ref.h"
#include "int.h"
-void uwuvm_free_value(UwUVMValue value)
+UwUVMValue uwuvm_clone_value(UwUVMValue value)
{
- value.type->delete(value.data);
+ return (UwUVMValue) {
+ .type = value.type,
+ .data = value.type->clone(value.data),
+ };
}
-void uwuvm_free_args(UwUVMArgs *args)
+void uwuvm_delet_value(UwUVMValue value)
{
- 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);
- }
+ value.type->delet(value.data);
}
-UwUVMValue uwuvm_copy_value(UwUVMValue value)
+char *uwuvm_print_value(UwUVMValue value)
{
- return (UwUVMValue) {
- .type = value.type,
- .data = value.type->copy(value.data),
- };
+ return value.type->print(value.data);
}
UwUVMValue uwuvm_get_arg(UwUVMArgs *args, size_t i)
@@ -58,30 +47,53 @@ UwUVMValue uwuvm_evaluate_expression(UwUVMExpression *expression, UwUVMArgs *arg
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));
+ return uwuvm_clone_value(uwuvm_get_arg(args, expression->value.int_value));
case EX_FNNAME:
return uwuref_create(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,
- });
+ return uwuvm_call_function(
+ expression->value.cll_value.function,
+ expression->value.cll_value.num_args,
+ expression->value.cll_value.args,
+ args
+ );
default:
return (UwUVMValue) {};
}
}
-UwUVMValue uwuvm_run_function(UwUVMFunction *function, UwUVMArgs args)
+UwUVMValue uwuvm_call_function(UwUVMFunction *function, size_t num_args, UwUVMExpression *unevaluated_args, UwUVMArgs *super_args)
{
- UwUVMValue value = function->type == MODULE_PLAIN
+ UwUVMValue *evaluated_args[num_args];
+
+ for (size_t i = 0; i < num_args; i++)
+ evaluated_args[i] = NULL;
+
+ UwUVMArgs args = {
+ .num = num_args,
+ .evaluated = evaluated_args,
+ .unevaluated = unevaluated_args,
+ .super = super_args,
+ };
+
+ UwUVMValue return_value = function->type == MODULE_PLAIN
? uwuvm_evaluate_expression(function->value.plain, &args)
: function->value.native(&args);
- uwuvm_free_args(&args);
- return value;
+ if (num_args > 0) {
+ for (size_t i = 0; i < num_args; i++) {
+ UwUVMValue *value = evaluated_args[i];
+
+ if (value) {
+ uwuvm_delet_value(*value);
+ free(value);
+ }
+ }
+
+ }
+
+ return return_value;
}
diff --git a/api/vm.h b/api/vm.h
index 7286f63..81465f8 100644
--- a/api/vm.h
+++ b/api/vm.h
@@ -13,9 +13,9 @@ typedef enum
typedef struct
{
- void *(*copy )(void *data);
- void (*delete)(void *data);
- char *(*print )(void *data);
+ void *(*clone)(void *data);
+ void (*delet)(void *data);
+ char *(*print)(void *data);
} UwUVMType;
typedef struct
@@ -71,11 +71,11 @@ typedef struct
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_clone_value(UwUVMValue value);
+void uwuvm_delet_value(UwUVMValue value);
+char *uwuvm_print_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);
+UwUVMValue uwuvm_call_function(UwUVMFunction *function, size_t num_args, UwUVMExpression *unevaluated_args, UwUVMArgs *super_args);
#endif
diff --git a/doc/std.md b/doc/std.md
index debf460..2e7720b 100644
--- a/doc/std.md
+++ b/doc/std.md
@@ -1,50 +1,42 @@
# Standard library
-## The `:nil` module
-
-- `:nil:nil`: The nil constant
-
## The `:bool` module
-- `:bool:if`: Requires exactly 3 arguments of arbitrary type. If $0 is a truthy value, evaluate and return $1. If $0 is a falsy value, evaluate and return $2. Values considered as falsy are: `:bool:false` and `:nil:nil`. Everything else is considered truey.
-
+- `:bool:if`: Requires exactly 3 arguments of arbitrary type. If $0 is a truthy value, evaluate and return $1. If $0 is a falsy value, evaluate and return $2. Values considered as falsy are: `:bool:false` and `:nil:nil`. Everything else is considered truthy.
- `:bool:and`: Accepts an arbitrary number of arguments of arbitrary type, but at least one. Returns `:bool:true` if all of the arguments are considered truthy.
-
- `:bool:or`: Accepts an arbitrary number of arguments of arbitrary type, but at least one. Returns `:bool:true` if at least one of the arguments is considered truthy.
-
- `:bool:equal`: Accepts an arbitrary number of arguments of arbitrary type, but at least 2. Returns `bool:true` if either all of the arguments are considered truthy or all of the arguments are considered falsy.
-
- `:bool:not`: Accepts exactly one argument of arbitrary type. Returns `:bool:true` if the $0 is considered falsy, returns `:bool:false` if $0 is considered truthy.
-
- `:bool:true`: The true constant
-
- `:bool:false`: The false constant
-
- `:bool:is`: Accepts an arbitrary number of arguments of arbitrary type, but at least one. Returns `:bool:true` if all arguments are booleans (`:nil:nil` is NOT considered a boolean).
## The `:int` module
- `:int:add`: Accepts an arbitrary number of integer arguments (or none at all) and returns the sum of all arguments, or `0` if none were given.
-
- `:int:sub`: Accepts exactly 2 integer arguments and returns their difference.
-
- `:int:mul`: Accepts an arbitrary number of integer arguments (or none at all) and returns the product of all arguments, or `1` if none were given.
-
- `:int:div`: Accepts exactly 2 integer arguments and returns their quotient (rounded towards 0).
-
- `:int:mod`: Accepts exactly 2 integer arguments and returns the reminder of their division.
-
- `:int:smaller`: Accepts exactly 2 integer arguments and returns `:bool:true` if $0 is smaller than $1, `:boool:false` else.
-
- `:int:greater`: Accepts exactly 2 integer arguments and returns `:bool:true` if $0 is greater than $1, `:bool:false` else.
-
- `:int:equal`: Accepts an arbitrary number of integer arguments, but at least 2. Returns `bool:true` if all the arguments are equal.
-
- `:int:is`: Accepts an arbitrary number of arguments of arbitrary type, but at least one. Returns `:bool:true` if all arguments are integers.
+## The `:nil` module
+
+- `:nil:nil`: The nil constant
+- `:nil:is`: Accepts an arbitrary number of arguments of arbitrary type, but at least one. Returns `:bool:true` if all arguments are strings.
+
+## The `:ref` module
+
+- `:ref:call`: Accepts a function reference as $0 and after that and arbitrary number of arguments of arbitrary type. Calls the function $0 with the arguments that follow and returns it's return value.
+- `:ref:is`: Accepts an arbitrary number of arguments of arbitrary type, but at least one. Returns `:bool:true` if all arguments are function references.
+
## The `:str` module
- `:str:cat`: Accepts an arbitrary number of arguments of arbitrary type and returns the concatenation of their string representations.
+- `:str:is`: Accepts an arbitrary number of arguments of arbitrary type, but at least one. Returns `:bool:true` if all arguments are strings.
### String representations
diff --git a/src/vm.c b/src/vm.c
index 335eb48..8b1b13a 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -20,14 +20,14 @@ static void free_expression(UwUVMExpression *expr)
void vm_run_file(const char *progname, const char *modname)
{
UwUVMProgram program = create_program(progname, modname);
- UwUVMValue result = ((UwUVMValue (*)(UwUVMFunction *, UwUVMArgs args)) dlsym(program.api_library, "uwuvm_run_function"))(program.main_function, (UwUVMArgs) {.num = 0, .evaluated = NULL, .unevaluated = NULL, .super = NULL});
+ UwUVMValue result = ((UwUVMValue (*)(UwUVMFunction *, size_t, UwUVMExpression *, UwUVMArgs *)) dlsym(program.api_library, "uwuvm_call_function"))(program.main_function, 0, NULL, NULL);
- char *str = ((char *(*)(UwUVMValue)) dlsym(program.api_library, "uwustr_get"))(result);
+ char *str = ((char *(*)(UwUVMValue)) dlsym(program.api_library, "uwuvm_print_value"))(result);
printf("%s\n", str);
free(str);
- ((void (*)(UwUVMValue)) dlsym(program.api_library, "uwuvm_free_value"))(result);
+ ((void (*)(UwUVMValue)) dlsym(program.api_library, "uwuvm_delet_value"))(result);
for (size_t i = 0; i < program.num_functions; i++) {
UwUVMFunction *function = program.functions[i];
diff --git a/std/bool.c b/std/bool.c
index 02aa887..4386dc3 100644
--- a/std/bool.c
+++ b/std/bool.c
@@ -2,8 +2,10 @@
#include <stdlib.h>
#include "../src/err.h"
#include "../api/vm.h"
+#include "../api/util.h"
#include "../api/bool.h"
+
static inline bool get_bool_arg(UwUVMArgs *args, size_t i)
{
return uwubool_get(uwuvm_get_arg(args, i));
@@ -14,7 +16,7 @@ UwUVMValue uwu_if(UwUVMArgs *args)
if (args->num != 3)
error("error: :bool:if requires exactly 3 arguments\n");
- return uwuvm_copy_value(get_bool_arg(args, 0)
+ return uwuvm_clone_value(get_bool_arg(args, 0)
? uwuvm_get_arg(args, 1)
: uwuvm_get_arg(args, 2)
);
@@ -84,12 +86,5 @@ UwUVMValue uwu_false(UwUVMArgs *args)
UwUVMValue uwu_is(UwUVMArgs *args)
{
- if (args->num < 1)
- error("error: :bool:is requires at least 1 argument\n");
-
- for (size_t i = 0; i < args->num; i++)
- if (uwuvm_get_arg(args, i).type != &uwubool_type)
- return uwubool_create(false);
-
- return uwubool_create(true);
+ return uwuutil_is_type(":bool:is", args, &uwubool_type);
}
diff --git a/std/int.c b/std/int.c
index c6c8ab7..6857f26 100644
--- a/std/int.c
+++ b/std/int.c
@@ -4,6 +4,7 @@
#include "../api/vm.h"
#include "../api/int.h"
#include "../api/bool.h"
+#include "../api/util.h"
typedef enum
{
@@ -30,8 +31,8 @@ static int binary(const char *fnname, UwUVMArgs *args, BinaryOP op)
if (value1.type != &uwuint_type)
error("error: %s requires an integer as $1\n", fnname);
- int a = *(int *) value0.data;
- int b = *(int *) value1.data;
+ int a = uwuint_get(value0);
+ int b = uwuint_get(value1);
switch (op) {
case BOP_SUB: return a - b;
@@ -60,7 +61,7 @@ static int reduce(const char *fnname, UwUVMArgs *args, ReduceOP op, int result)
if (value.type != &uwuint_type)
error("error: %s only accepts integers as arguments (invalid argument: $%lu)\n", fnname, i);
- int this = *(int *) value.data;
+ int this = uwuint_get(value);
switch (op) {
case ROP_ADD: result += this; break;
@@ -123,12 +124,5 @@ UwUVMValue uwu_equal(UwUVMArgs *args)
UwUVMValue uwu_is(UwUVMArgs *args)
{
- if (args->num < 1)
- error("error: :int:is requires at least 1 argument\n");
-
- for (size_t i = 0; i < args->num; i++)
- if (uwuvm_get_arg(args, i).type != &uwuint_type)
- return uwubool_create(false);
-
- return uwubool_create(true);
+ return uwuutil_is_type(":int:is", args, &uwuint_type);
}
diff --git a/std/nil.c b/std/nil.c
index 33230fb..599e3d4 100644
--- a/std/nil.c
+++ b/std/nil.c
@@ -1,5 +1,6 @@
#include "../src/err.h"
#include "../api/nil.h"
+#include "../api/util.h"
UwUVMValue uwu_nil(UwUVMArgs *args)
{
@@ -8,3 +9,8 @@ UwUVMValue uwu_nil(UwUVMArgs *args)
return uwunil_create();
}
+
+UwUVMValue uwu_is(UwUVMArgs *args)
+{
+ return uwuutil_is_type(":nil:is", args, &uwunil_type);
+}
diff --git a/std/ref.c b/std/ref.c
new file mode 100644
index 0000000..f82bb50
--- /dev/null
+++ b/std/ref.c
@@ -0,0 +1,21 @@
+#include "../src/err.h"
+#include "../api/ref.h"
+#include "../api/util.h"
+
+UwUVMValue uwu_call(UwUVMArgs *args)
+{
+ if (args->num < 1)
+ error(":ref:call requires at least one argument\n");
+
+ UwUVMValue value = uwuvm_get_arg(args, 0);
+
+ if (value.type != &uwuref_type)
+ error(":ref:call requires a function reference as $0\n");
+
+ return uwuvm_call_function(value.data, args->num - 1, &args->unevaluated[1], args->super);
+}
+
+UwUVMValue uwu_is(UwUVMArgs *args)
+{
+ return uwuutil_is_type(":ref:is", args, &uwuref_type);
+}
diff --git a/std/str.c b/std/str.c
index 16f756b..953e8c0 100644
--- a/std/str.c
+++ b/std/str.c
@@ -2,6 +2,7 @@
#include <stdlib.h>
#include "../api/vm.h"
#include "../api/str.h"
+#include "../api/util.h"
UwUVMValue uwu_cat(UwUVMArgs *args)
{
@@ -28,3 +29,8 @@ UwUVMValue uwu_cat(UwUVMArgs *args)
return uwustr_create(result);
}
+
+UwUVMValue uwu_is(UwUVMArgs *args)
+{
+ return uwuutil_is_type(":str:is", args, &uwustr_type);
+}