aboutsummaryrefslogtreecommitdiff
path: root/std
diff options
context:
space:
mode:
Diffstat (limited to 'std')
-rw-r--r--std/bool.c97
-rwxr-xr-xstd/bool.sobin0 -> 22392 bytes
-rw-r--r--std/int.c134
-rwxr-xr-xstd/int.sobin0 -> 22736 bytes
-rw-r--r--std/str.c30
-rwxr-xr-xstd/str.sobin0 -> 19592 bytes
6 files changed, 261 insertions, 0 deletions
diff --git a/std/bool.c b/std/bool.c
new file mode 100644
index 0000000..cb4082b
--- /dev/null
+++ b/std/bool.c
@@ -0,0 +1,97 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "../src/err.h"
+#include "../api/vm.h"
+#include "../api/bool.h"
+
+static inline bool get_bool_arg(UwUVMArgs *args, size_t i)
+{
+ return uwubool_get(uwuvm_get_arg(args, i));
+}
+
+#include "../api/str.h"
+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)
+ ? uwuvm_get_arg(args, 1)
+ : uwuvm_get_arg(args, 2)
+ );
+}
+
+UwUVMValue uwu_and(UwUVMArgs *args)
+{
+ if (args->num < 1)
+ error("error: :bool:and requires at least one argument\n");
+
+ for (size_t i = 0; i < args->num; i++)
+ if (! get_bool_arg(args, i))
+ return uwubool_create(false);
+
+ return uwubool_create(true);
+}
+
+UwUVMValue uwu_or(UwUVMArgs *args)
+{
+ if (args->num < 1)
+ error("error: :bool:or requires at least one argument\n");
+
+ for (size_t i = 0; i < args->num; i++)
+ if (get_bool_arg(args, i))
+ return uwubool_create(true);
+
+ return uwubool_create(false);
+}
+
+UwUVMValue uwu_equal(UwUVMArgs *args)
+{
+ if (args->num < 2)
+ error("error: :bool:equal requires at least 2 arguments\n");
+
+ bool value = get_bool_arg(args, 0);
+
+ for (size_t i = 1; i < args->num; i++)
+ if (get_bool_arg(args, i) != value)
+ return uwubool_create(false);
+
+ return uwubool_create(true);
+}
+
+UwUVMValue uwu_not(UwUVMArgs *args)
+{
+ if (args->num != 1)
+ error("error: :bool:not requires exactly 1 argument\n");
+
+ return uwubool_create(! get_bool_arg(args, 0));
+}
+
+UwUVMValue uwu_true(UwUVMArgs *args)
+{
+ if (args->num != 0)
+ error("error: :bool:true does not take any arguments\n");
+
+ return uwubool_create(true);
+}
+
+UwUVMValue uwu_false(UwUVMArgs *args)
+{
+ if (args->num != 0)
+ error("error: :bool:false does not take any arguments\n");
+
+ return uwubool_create(false);
+}
+
+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++) {
+ UwUVMValue value = uwuvm_get_arg(args, i);
+ return uwubool_create(value.type != VT_NAT || value.value.nat_value.type != &uwubool_type);
+ }
+
+ return uwubool_create(true);
+}
diff --git a/std/bool.so b/std/bool.so
new file mode 100755
index 0000000..5007f5f
--- /dev/null
+++ b/std/bool.so
Binary files differ
diff --git a/std/int.c b/std/int.c
new file mode 100644
index 0000000..a8d2c6d
--- /dev/null
+++ b/std/int.c
@@ -0,0 +1,134 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "../src/err.h"
+#include "../api/vm.h"
+#include "../api/int.h"
+#include "../api/bool.h"
+
+typedef enum
+{
+ BOP_SUB,
+ BOP_DIV,
+ BOP_MOD,
+ BOP_SML,
+ BOP_GRT,
+ BOP_EQU,
+} BinaryOP;
+
+static int binary(const char *fnname, UwUVMArgs *args, BinaryOP op)
+{
+ if (args->num != 2)
+ error("error: %s requires exactly 2 arguments\n", fnname);
+
+ UwUVMValue value0 = uwuvm_get_arg(args, 0);
+
+ if (value0.type != VT_INT)
+ error("error: %s requires an integer as $0\n", fnname);
+
+ UwUVMValue value1 = uwuvm_get_arg(args, 1);
+
+ if (value1.type != VT_INT)
+ error("error: %s requires an integer as $1\n", fnname);
+
+ int a = value0.value.int_value;
+ int b = value1.value.int_value;
+
+ switch (op) {
+ case BOP_SUB: return a - b;
+ case BOP_DIV: return a / b;
+ case BOP_MOD: return a % b;
+ case BOP_SML: return a < b;
+ case BOP_GRT: return a > b;
+ case BOP_EQU: return a == b;
+ }
+}
+
+typedef enum
+{
+ ROP_ADD,
+ ROP_MUL,
+ ROP_EQU,
+} ReduceOP;
+
+static int reduce(const char *fnname, UwUVMArgs *args, ReduceOP op, int result)
+{
+ int first;
+
+ for (size_t i = 0; i < args->num; i++) {
+ UwUVMValue value = uwuvm_get_arg(args, i);
+
+ if (value.type != VT_INT)
+ error("error: %s only accepts integers as arguments (invalid argument: $%lu)\n", fnname, i);
+
+ int this = value.value.int_value;
+
+ switch (op) {
+ case ROP_ADD: result += this; break;
+ case ROP_MUL: result *= this; break;
+ case ROP_EQU:
+ if (i == 0)
+ first = this;
+ else if (this != first)
+ return 0;
+
+ break;
+ }
+ }
+
+ return result;
+}
+
+UwUVMValue uwu_add(UwUVMArgs *args)
+{
+ return uwuint_create(reduce(":int:mul", args, ROP_ADD, 0));
+}
+
+UwUVMValue uwu_sub(UwUVMArgs *args)
+{
+ return uwuint_create(binary(":int:sub", args, BOP_SUB));
+}
+
+UwUVMValue uwu_mul(UwUVMArgs *args)
+{
+ return uwuint_create(reduce(":int:mul", args, ROP_MUL, 1));
+}
+
+UwUVMValue uwu_div(UwUVMArgs *args)
+{
+ return uwuint_create(binary(":int:div", args, BOP_DIV));
+}
+
+UwUVMValue uwu_mod(UwUVMArgs *args)
+{
+ return uwuint_create(binary(":int:mod", args, BOP_MOD));
+}
+
+UwUVMValue uwu_smaller(UwUVMArgs *args)
+{
+ return uwubool_create(binary(":int:smaller", args, BOP_SML) == 1);
+}
+
+UwUVMValue uwu_greater(UwUVMArgs *args)
+{
+ return uwubool_create(binary(":int:greater", args, BOP_GRT) == 1);
+}
+
+UwUVMValue uwu_equal(UwUVMArgs *args)
+{
+ if (args->num < 2)
+ error("error: :int:equal requires at least 2 arguments\n");
+
+ return uwubool_create(reduce(":int:equal", args, ROP_EQU, 1) == 1);
+}
+
+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 != VT_INT)
+ return uwubool_create(false);
+
+ return uwubool_create(true);
+}
diff --git a/std/int.so b/std/int.so
new file mode 100755
index 0000000..e7ab065
--- /dev/null
+++ b/std/int.so
Binary files differ
diff --git a/std/str.c b/std/str.c
new file mode 100644
index 0000000..16f756b
--- /dev/null
+++ b/std/str.c
@@ -0,0 +1,30 @@
+#include <string.h>
+#include <stdlib.h>
+#include "../api/vm.h"
+#include "../api/str.h"
+
+UwUVMValue uwu_cat(UwUVMArgs *args)
+{
+ size_t total_len = 0;
+ size_t lengths[args->num];
+ char *substrs[args->num];
+
+ for (size_t i = 0; i < args->num; i++) {
+ substrs[i] = uwustr_get(uwuvm_get_arg(args, i));
+ lengths[i] = strlen(substrs[i]);
+ total_len += lengths[i];
+ }
+
+ char result[total_len + 1];
+ char *result_ptr = result;
+
+ for (size_t i = 0; i < args->num; i++) {
+ strcpy(result_ptr, substrs[i]);
+ free(substrs[i]);
+ result_ptr += lengths[i];
+ }
+
+ *result_ptr = 0;
+
+ return uwustr_create(result);
+}
diff --git a/std/str.so b/std/str.so
new file mode 100755
index 0000000..a7c6497
--- /dev/null
+++ b/std/str.so
Binary files differ