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