diff options
Diffstat (limited to 'std')
-rw-r--r-- | std/bool.c | 97 | ||||
-rwxr-xr-x | std/bool.so | bin | 0 -> 22392 bytes | |||
-rw-r--r-- | std/int.c | 134 | ||||
-rwxr-xr-x | std/int.so | bin | 0 -> 22736 bytes | |||
-rw-r--r-- | std/str.c | 30 | ||||
-rwxr-xr-x | std/str.so | bin | 0 -> 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 Binary files differnew file mode 100755 index 0000000..5007f5f --- /dev/null +++ b/std/bool.so 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 Binary files differnew file mode 100755 index 0000000..e7ab065 --- /dev/null +++ b/std/int.so 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 Binary files differnew file mode 100755 index 0000000..a7c6497 --- /dev/null +++ b/std/str.so |