aboutsummaryrefslogtreecommitdiff
path: root/src/vm/runner/runner.c
blob: de1a478c1642b0f631a32479cff04b27fbb37d79 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#include "runner.h"

#include <compiler/code_generator/code_generator.h>
#include <stdio.h>
#include <stdlib.h>
#include <utils/memory/memory.h>
#include <utils/types.h>

const BuiltinFunction BUILTIN_FUNCTIONS[] = {
    print,
};
const char *BUILTIN_FUNCTION_NAMES[] = {
    "print",
};
const size_t BUILTIN_FUNCTIONS_SIZE =
    sizeof(BUILTIN_FUNCTIONS) / sizeof(BuiltinFunction);

bool runner(Instructions instructions) {
  size_t stack_size = 0;
  void **stack = a404m_malloc(stack_size * sizeof(void *));
  size_t stack_inserted = 0;

  for (size_t i = 0; i < instructions.size; ++i) {
    if (!runInstruction(instructions.instructions[i], &stack, &stack_size,
                        &stack_inserted)) {
      goto RETURN_ERROR;
    }
  }

  free(stack);
  return true;

RETURN_ERROR:
  free(stack);
  return false;
}

BuiltinFunction getBuiltinFunction(SizedString string) {
  for (size_t i = 0; i < BUILTIN_FUNCTIONS_SIZE; ++i) {
    const char *search = BUILTIN_FUNCTION_NAMES[i];
    // faster than strlen+strncpy
    for (size_t j = 0;; ++j) {
      const char searchChar = search[j];
      if (j == string.size) {
        if (searchChar == '\0') {
          return BUILTIN_FUNCTIONS[i];
        } else {
          break;
        }
      } else if (searchChar == '\0') {
        break;
      } else if (searchChar != string.str[j]) {
        break;
      }
    }
  }
  return NULL;
}

bool runInstruction(Instruction instruction, void ***restrict stack,
                    size_t *restrict stack_size,
                    size_t *restrict stack_inserted) {
  switch (instruction.command) {
    case COMMAND_PUSH_STRING: {
      SizedString *string = instruction.operand;
      if (*stack_inserted == *stack_size) {
        *stack_size += *stack_size / 2 + 1;
        *stack = a404m_realloc(*stack, *stack_size * sizeof(void *));
      }
      (*stack)[*stack_inserted] = string;
      ++*stack_inserted;
      return true;
    }
    case COMMAND_CALL_FUNCTION: {
      SizedString *functionName = instruction.operand;
      BuiltinFunction function = getBuiltinFunction(*functionName);
      if (function == NULL) {
        fprintf(stderr, "function '%.*s' not found\n", (int)functionName->size,
                functionName->str);
        return false;
      }
      function(stack, stack_inserted);
      return true;
    }
    case COMMAND_NONE:
  }
  fprintf(stderr, "unknown command '%d'\n", instruction.command);
  return false;
}

void print(void ***restrict stack, size_t *restrict stack_inserted) {
  const SizedString *string = (*stack)[--*stack_inserted];
  printf("%.*s", (int)string->size, string->str);
}