]> git.lizzy.rs Git - uwu-lang.git/blob - api/vm.c
Initial commit
[uwu-lang.git] / api / vm.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include "../src/err.h"
4 #include "vm.h"
5 #include "str.h"
6 #include "int.h"
7
8 void uwuvm_free_value(UwUVMValue value)
9 {
10         if (value.type == VT_STR)
11                 free(value.value.str_value);
12         else if (value.type == VT_NAT)
13                 value.value.nat_value.type->delete(value.value.nat_value.data);
14 }
15
16 void uwuvm_free_args(UwUVMArgs *args)
17 {
18         if (args->evaluated) {
19                 for (size_t i = 0; i < args->num; i++) {
20                         UwUVMValue *value = args->evaluated[i];
21
22                         if (value) {
23                                 uwuvm_free_value(*value);
24                                 free(value);
25                         }
26                 }
27
28                 free(args->evaluated);
29         }
30 }
31
32 UwUVMValue uwuvm_copy_value(UwUVMValue value)
33 {
34         if (value.type == VT_STR)
35                 return uwustr_create(value.value.str_value);
36         else if (value.type == VT_NAT)
37                 return (UwUVMValue) {
38                         .type = value.type,
39                         .value = {
40                                 .nat_value = {
41                                         .type = value.value.nat_value.type,
42                                         .data = value.value.nat_value.type->copy(value.value.nat_value.data),
43                                 }
44                         }
45                 };
46         else
47                 return value;
48 }
49
50 UwUVMValue uwuvm_get_arg(UwUVMArgs *args, size_t i)
51 {
52         if (! args->evaluated[i]) {
53                 args->evaluated[i] = malloc(sizeof(UwUVMValue));
54                 *(args->evaluated[i]) = uwuvm_evaluate_expression(&args->unevaluated[i], args->super);
55         }
56
57         return *(args->evaluated[i]);
58 }
59
60 UwUVMValue uwuvm_evaluate_expression(UwUVMExpression *expression, UwUVMArgs *args)
61 {
62         switch (expression->type) {
63                 case EX_INTLIT:
64                         return uwuint_create(expression->value.int_value);
65
66                 case EX_STRLIT:
67                         return uwustr_create(expression->value.str_value);
68
69                 case EX_ARGNUM:
70                         if ((size_t) expression->value.int_value >= args->num) 
71                                 error("error: not enough arguments (accessed argument $%d, but only %lu arguments were passed)\n", expression->value.int_value, args->num);
72
73                         return uwuvm_copy_value(uwuvm_get_arg(args, expression->value.int_value));
74
75                 case EX_FNNAME:
76                         return (UwUVMValue) {
77                                 .type = VT_REF,
78                                 .value = {
79                                         .ref_value = expression->value.ref_value,
80                                 },
81                         };
82
83                 case EX_FNCALL:
84                         return uwuvm_run_function(expression->value.cll_value.function, (UwUVMArgs) {
85                                 .num = expression->value.cll_value.num_args,
86                                 .evaluated = expression->value.cll_value.num_args == 0 ? NULL : calloc(expression->value.cll_value.num_args, sizeof(UwUVMValue *)),
87                                 .unevaluated = expression->value.cll_value.args,
88                                 .super = args,
89                         });
90
91                 default:
92                         return (UwUVMValue) {};
93         }
94 }
95
96 UwUVMValue uwuvm_run_function(UwUVMFunction *function, UwUVMArgs args)
97 {
98         UwUVMValue value = function->type == MODULE_PLAIN
99                 ? uwuvm_evaluate_expression(function->value.plain, &args)
100                 : function->value.native(&args);
101
102         uwuvm_free_args(&args);
103         return value;
104 }