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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
|
#include "runner.h"
#include <compiler/code_generator/code_generator.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.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(SourceCode *sourceCode) {
Instructions instructions = codeGenerator(sourceCode);
if (instructions.size != ERROR_SIZE) {
bool ranSuccess = _runner(instructions);
deleteInstructions(instructions);
return ranSuccess;
}
return false;
}
bool _runner(Instructions instructions) {
size_t stack_size = 0;
void **stack = a404m_malloc(stack_size * sizeof(void *));
size_t stack_inserted = 0;
size_t variables_size = 0;
RunnerVariable **variables =
a404m_malloc(variables_size * sizeof(RunnerVariable *));
size_t variables_inserted = 0;
for (size_t i = 0; i < instructions.size; ++i) {
if (!runInstruction(instructions.instructions[i], &stack, &stack_size,
&stack_inserted, &variables, &variables_size,
&variables_inserted)) {
goto RETURN_ERROR;
}
}
for (size_t i = 0; i < variables_inserted; ++i) {
free(variables[i]);
}
free(variables);
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+strncmp
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,
RunnerVariable ***restrict variables,
size_t *restrict variables_size,
size_t *restrict variables_inserted) {
switch (instruction.command) {
case COMMAND_PUSH_IDENTIFIER: {
const CommandPushIdentifierOperand *operand = instruction.operand;
pushToStack(
getRunnerVariable(operand, variables, variables_inserted)->value,
stack, stack_size, stack_inserted);
return true;
}
case COMMAND_PUSH_STRING: {
CommandPushStringOperand *operand = instruction.operand;
pushToStack(operand, stack, stack_size, stack_inserted);
return true;
}
case COMMAND_CALL_FUNCTION: {
SizedString *functionName = instruction.operand;
const 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_POP_IDENTIFIER: {
const CommandPopIdentifierOperand *operand = instruction.operand;
setRunnerVariable(popFromStack(stack, stack_inserted), operand, variables,
variables_size, variables_inserted);
return true;
}
case COMMAND_NONE:
}
fprintf(stderr, "bad command '%d'\n", instruction.command);
return false;
}
RunnerVariable *getRunnerVariable(const SizedString *varName,
RunnerVariable ***restrict variables,
size_t *restrict variables_inserted) {
for (size_t i = *variables_inserted - 1; i != (typeof(i))-1; --i) {
RunnerVariable *variable = (*variables)[i];
if (variable->name->size == varName->size &&
strncmp(varName->str, variable->name->str, varName->size) == 0) {
return variable;
}
}
return NULL;
}
void setRunnerVariable(void *value, const SizedString *varName,
RunnerVariable ***restrict variables,
size_t *restrict variables_size,
size_t *restrict variables_inserted) {
RunnerVariable *variable =
getRunnerVariable(varName, variables, variables_inserted);
if (variable != NULL) {
variable->value = value;
return;
}
variable = a404m_malloc(sizeof(*variable));
variable->name = varName;
variable->value = value;
if (*variables_inserted == *variables_size) {
*variables_size += *variables_size / 2 + 1;
*variables =
a404m_realloc(*variables, *variables_size * sizeof(RunnerVariable *));
}
(*variables)[*variables_inserted] = variable;
*variables_inserted += 1;
}
void *popFromStack(void ***restrict stack, size_t *restrict stack_inserted) {
if (*stack_inserted == 0) {
fprintf(stderr, "stack underflow\n");
exit(1);
}
return (*stack)[--*stack_inserted];
}
void pushToStack(void *value, void ***restrict stack,
size_t *restrict stack_size, size_t *restrict stack_inserted) {
if (*stack_inserted == *stack_size) {
*stack_size += *stack_size / 2 + 1;
*stack = a404m_realloc(*stack, *stack_size * sizeof(void *));
}
(*stack)[*stack_inserted] = value;
++*stack_inserted;
}
void print(void ***restrict stack, size_t *restrict stack_inserted) {
const SizedString *string = popFromStack(stack, stack_inserted);
printf("%.*s", (int)string->size, string->str);
}
|