aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorA404M <ahmadmahmoudiprogrammer@gmail.com>2024-09-19 15:53:13 +0330
committerA404M <ahmadmahmoudiprogrammer@gmail.com>2024-09-19 15:53:13 +0330
commitd2ab53c625d386a4fbc6a9d5a5eb29faab1b3f0c (patch)
tree3e81b2dce883abb8b5b5ea2edd0300af24079539 /src
parent3df524bacbd6ca55177f481f8c98b118131b6527 (diff)
removing print command and keyword
added function call support cleaned up keyword and operator checking and speed it up a little bit cleaning includes added builtin functions
Diffstat (limited to 'src')
-rw-r--r--src/compiler/code_generator/code_generator.c69
-rw-r--r--src/compiler/code_generator/code_generator.h5
-rw-r--r--src/compiler/lexer/lexer.c56
-rw-r--r--src/compiler/lexer/lexer.h4
-rw-r--r--src/compiler/parser/parser.c148
-rw-r--r--src/compiler/parser/parser.h9
-rw-r--r--src/main.c10
-rw-r--r--src/vm/runner/runner.c64
-rw-r--r--src/vm/runner/runner.h9
9 files changed, 210 insertions, 164 deletions
diff --git a/src/compiler/code_generator/code_generator.c b/src/compiler/code_generator/code_generator.c
index 0cd2722..8560129 100644
--- a/src/compiler/code_generator/code_generator.c
+++ b/src/compiler/code_generator/code_generator.c
@@ -3,13 +3,13 @@
#include <compiler/parser/parser.h>
#include <stdio.h>
#include <stdlib.h>
-
-#include "utils/memory/memory.h"
-#include "utils/types.h"
+#include <string.h>
+#include <utils/memory/memory.h>
+#include <utils/types.h>
const char *COMMAND_STRINGS[] = {
"COMMAND_NONE",
- "COMMAND_PRINT",
+ "COMMAND_CALL_FUNCTION",
"COMMAND_PUSH_STRING",
};
@@ -17,16 +17,15 @@ void printInstruction(Instruction instruction) {
printf("%s", COMMAND_STRINGS[instruction.command]);
switch (instruction.command) {
case COMMAND_NONE:
- case COMMAND_PRINT:
- break;
+ printf("\n");
+ return;
+ case COMMAND_CALL_FUNCTION:
case COMMAND_PUSH_STRING:
SizedString *sizedString = instruction.operand;
- printf(" '%.*s'", (int)sizedString->size, sizedString->str);
- break;
- default:
- fprintf(stderr, "bad instruction %d\n", instruction.command);
+ printf(" '%.*s'\n", (int)sizedString->size, sizedString->str);
+ return;
}
- printf("\n");
+ fprintf(stderr, "bad instruction %d\n", instruction.command);
}
void printInstructions(Instructions instructions) {
@@ -38,16 +37,15 @@ void printInstructions(Instructions instructions) {
void deleteInstruction(Instruction instruction) {
switch (instruction.command) {
case COMMAND_NONE:
- case COMMAND_PRINT:
- break;
+ return;
case COMMAND_PUSH_STRING:
+ case COMMAND_CALL_FUNCTION:
SizedString *sizedString = instruction.operand;
free(sizedString->str);
free(sizedString);
- break;
- default:
- fprintf(stderr, "bad instruction %d\n", instruction.command);
+ return;
}
+ fprintf(stderr, "bad instruction %d\n", instruction.command);
}
void deleteInstructions(Instructions instructions) {
@@ -92,7 +90,31 @@ bool nodeToInstruction(ParsedNode *node, Instruction **instructions,
size_t *instructions_size,
size_t *instructions_inserted) {
switch (node->token) {
- // TODO: this is wrong when you want functions
+ case PARSED_TOKEN_FUNCTION_CALL: {
+ FunctionCallMetadata *metadata = node->metadata;
+ const ScopeMetadata *scope = metadata->scope;
+ for (size_t i = 0; i < scope->operands_size; ++i) {
+ if (!nodeToInstruction(scope->operands[i], instructions,
+ instructions_size, instructions_inserted)) {
+ return false;
+ }
+ }
+
+ SizedString *string = a404m_malloc(sizeof(*string));
+ string->size = metadata->functionNameEnd - metadata->functionNameBegin;
+ string->str = a404m_malloc(string->size);
+ strncpy(string->str, metadata->functionNameBegin, string->size);
+ if (string == NULL) {
+ return false;
+ }
+ const Instruction instruction = {
+ .command = COMMAND_CALL_FUNCTION,
+ .operand = string,
+ };
+ insertInstruction(instruction, instructions, instructions_size,
+ instructions_inserted);
+ return true;
+ }
case PARSED_TOKEN_PARENTHESIS: {
const ScopeMetadata *metadata = node->metadata;
for (size_t i = 0; i < metadata->operands_size; ++i) {
@@ -106,19 +128,6 @@ bool nodeToInstruction(ParsedNode *node, Instruction **instructions,
case PARSED_TOKEN_EOL:
return nodeToInstruction(node->metadata, instructions, instructions_size,
instructions_inserted);
- case PARSED_TOKEN_PRINT:
- if (nodeToInstruction(node->metadata, instructions, instructions_size,
- instructions_inserted)) {
- const Instruction instruction = {
- .command = COMMAND_PRINT,
- .operand = NULL,
- };
- insertInstruction(instruction, instructions, instructions_size,
- instructions_inserted);
- return true;
- } else {
- return false;
- }
case PARSED_TOKEN_VALUE_STRING: {
SizedString *string = nodeToString(node);
if (string == NULL) {
diff --git a/src/compiler/code_generator/code_generator.h b/src/compiler/code_generator/code_generator.h
index 1a9b4ff..da5b686 100644
--- a/src/compiler/code_generator/code_generator.h
+++ b/src/compiler/code_generator/code_generator.h
@@ -1,11 +1,10 @@
#pragma once
-#include <stdio.h>
+#include <compiler/parser/parser.h>
-#include "compiler/parser/parser.h"
typedef enum Command {
COMMAND_NONE = 0,
- COMMAND_PRINT,
+ COMMAND_CALL_FUNCTION,
COMMAND_PUSH_STRING,
} Command;
diff --git a/src/compiler/lexer/lexer.c b/src/compiler/lexer/lexer.c
index eee5ec3..b48be3c 100644
--- a/src/compiler/lexer/lexer.c
+++ b/src/compiler/lexer/lexer.c
@@ -3,13 +3,11 @@
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
-#include <string.h>
#include <utils/memory/memory.h>
const char *TOKEN_STRINGS[] = {
"TOKEN_NONE",
"TOKEN_IDENTIFIER",
- "TOKEN_KEYWORD_PRINT",
"TOKEN_NUMBER",
"TOKEN_STRING",
"TOKEN_OPERATOR",
@@ -25,12 +23,8 @@ const char *TOKEN_STRINGS[] = {
"TOKEN_PARSED",
};
-static const char *KEYWORDS_STRINGS[] = {
- "print",
-};
-static const Token KEYWORDS_TOKENS[] = {
- TOKEN_KEYWORD_PRINT,
-};
+static const char *KEYWORDS_STRINGS[] = {};
+static const Token KEYWORDS_TOKENS[] = {};
static const size_t KEYWORDS_SIZE = sizeof(KEYWORDS_STRINGS) / sizeof(char *);
static const char *OPERATORS_STRINGS[] = {
@@ -46,7 +40,7 @@ static const Token OPERATORS_TOKENS[] = {
TOKEN_OPERATOR_COLON,
TOKEN_OPERATOR_EOL,
};
-static const size_t OPERATOR_SIZE = sizeof(OPERATORS_STRINGS) / sizeof(char *);
+static const size_t OPERATORS_SIZE = sizeof(OPERATORS_STRINGS) / sizeof(char *);
void printNodes(Nodes nodes) {
for (size_t i = 0; i < nodes.size; ++i) {
@@ -174,7 +168,7 @@ Nodes lexer(char const *restrict str) {
const char current = str[i];
if (current == c) {
break;
- }else if(current == '\\'){
+ } else if (current == '\\') {
++i;
} else if (current == '\0') {
fprintf(stderr, "expected %c to end\n", c);
@@ -311,27 +305,37 @@ bool isOperator(char c) {
bool isSymbol(char c) { return c == '#'; }
-Token getKeyword(char const *strBegin, char const *strEnd) {
+Token getTokenInStrings(char const *strBegin, char const *strEnd,
+ const char *strings[], const Token tokens[],
+ size_t size) {
const size_t strSize = strEnd - strBegin;
- for (size_t i = 0; i < KEYWORDS_SIZE; ++i) {
- const char *search = KEYWORDS_STRINGS[i];
- if (strlen(search) == strSize && strncmp(search, strBegin, strSize) == 0) {
- return KEYWORDS_TOKENS[i];
+ for (size_t i = 0; i < size; ++i) {
+ const char *search = strings[i];
+ // faster than strlen+strncpy
+ for (size_t j = 0;; ++j) {
+ const char searchChar = search[j];
+ if (j == strSize) {
+ if (searchChar == '\0') {
+ return tokens[i];
+ } else {
+ break;
+ }
+ } else if (searchChar == '\0') {
+ break;
+ } else if (searchChar != strBegin[j]) {
+ break;
+ }
}
}
-
return TOKEN_NONE;
}
-Token getOperator(char const *strBegin, char const *strEnd) {
- const size_t strSize = strEnd - strBegin;
-
- for (size_t i = 0; i < OPERATOR_SIZE; ++i) {
- const char *search = OPERATORS_STRINGS[i];
- if (strlen(search) == strSize && strncmp(search, strBegin, strSize) == 0) {
- return OPERATORS_TOKENS[i];
- }
- }
- return TOKEN_NONE;
+Token getKeyword(char const *strBegin, char const *strEnd) {
+ return getTokenInStrings(strBegin, strEnd, KEYWORDS_STRINGS, KEYWORDS_TOKENS,
+ KEYWORDS_SIZE);
+}
+Token getOperator(char const *strBegin, char const *strEnd) {
+ return getTokenInStrings(strBegin, strEnd, OPERATORS_STRINGS,
+ OPERATORS_TOKENS, OPERATORS_SIZE);
}
diff --git a/src/compiler/lexer/lexer.h b/src/compiler/lexer/lexer.h
index d6eef17..802b50c 100644
--- a/src/compiler/lexer/lexer.h
+++ b/src/compiler/lexer/lexer.h
@@ -7,7 +7,6 @@
typedef enum Token {
TOKEN_NONE = 0,
TOKEN_IDENTIFIER,
- TOKEN_KEYWORD_PRINT,
TOKEN_NUMBER,
TOKEN_STRING,
TOKEN_OPERATOR,
@@ -61,5 +60,8 @@ extern bool isString(char c);
extern bool isOperator(char c);
extern bool isSymbol(char c);
+extern Token getTokenInStrings(char const *strBegin, char const *strEnd,
+ const char *strings[], const Token tokens[],
+ const size_t size);
extern Token getKeyword(char const *strBegin, char const *strEnd);
extern Token getOperator(char const *strBegin, char const *strEnd);
diff --git a/src/compiler/parser/parser.c b/src/compiler/parser/parser.c
index 2f5b89b..36b2574 100644
--- a/src/compiler/parser/parser.c
+++ b/src/compiler/parser/parser.c
@@ -7,7 +7,7 @@
const char *PARSED_TOKEN_STRINGS[] = {
"PARSED_TOKEN_NONE", "PARSED_TOKEN_ROOT",
- "PARSED_TOKEN_PRINT", "PARSED_TOKEN_PARENTHESIS",
+ "PARSED_TOKEN_PARENTHESIS", "PARSED_TOKEN_FUNCTION_CALL",
"PARSED_TOKEN_VALUE_STRING", "PARSED_TOKEN_EOL",
};
@@ -36,14 +36,6 @@ static const ParseOrder PARSE_ORDER[] = {
.size = 1,
.tokens =
{
- TOKEN_KEYWORD_PRINT,
- },
- },
- {
- .ltr = true,
- .size = 1,
- .tokens =
- {
TOKEN_STRING,
},
},
@@ -88,11 +80,6 @@ void _printParsedNode(const ParsedNode *parsedNode, int indent) {
printf("]\n");
--indent;
} break;
- case PARSED_TOKEN_PRINT: {
- const PrintMetadata *metadata = parsedNode->metadata;
- printf(",operand=\n");
- _printParsedNode(metadata, indent + 1);
- } break;
case PARSED_TOKEN_VALUE_STRING:
printf("\n");
break;
@@ -124,7 +111,8 @@ ParsedNode *getUntilCommonFather(ParsedNode *parsedNode, ParsedNode *parent) {
void deleteParsedNode(ParsedNode *parsedNode) {
switch (parsedNode->token) {
case PARSED_TOKEN_NONE:
- break;
+ case PARSED_TOKEN_VALUE_STRING:
+ goto FREE;
case PARSED_TOKEN_PARENTHESIS:
case PARSED_TOKEN_ROOT: {
ScopeMetadata *metadata = parsedNode->metadata;
@@ -133,23 +121,29 @@ void deleteParsedNode(ParsedNode *parsedNode) {
}
free(metadata->operands);
free(metadata);
- } break;
- case PARSED_TOKEN_PRINT: {
- PrintMetadata *metadata = parsedNode->metadata;
- deleteParsedNode(metadata);
- } break;
- case PARSED_TOKEN_VALUE_STRING:
- break;
+ goto FREE;
+ }
case PARSED_TOKEN_EOL: {
EOLMetadata *metadata = parsedNode->metadata;
deleteParsedNode(metadata);
- break;
+ goto FREE;
+ }
+ case PARSED_TOKEN_FUNCTION_CALL: {
+ FunctionCallMetadata *metadata = parsedNode->metadata;
+ ScopeMetadata *scope = metadata->scope;
+ for (size_t i = 0; i < scope->operands_size; ++i) {
+ deleteParsedNode(scope->operands[i]);
+ }
+ free(scope->operands);
+ free(scope);
+ free(metadata);
+ goto FREE;
}
- default:
- fprintf(stderr, "bad parsed token %d at compiler line %d\n",
- parsedNode->token, __LINE__);
- exit(1);
}
+ fprintf(stderr, "bad parsed token %d at compiler line %d\n",
+ parsedNode->token, __LINE__);
+ exit(1);
+FREE:
free(parsedNode);
}
@@ -168,22 +162,18 @@ ParsedNode *parser(Nodes lexedNodes) {
ScopeMetadata *parserScope(Node *nodesBegin, Node *nodesEnd, ParsedNode *parent,
bool (*isAllowed)(ParsedToken)) {
- if (nodesBegin >= nodesEnd) {
- return NULL;
- }
-
size_t nodes_size = 0;
ParsedNode **nodes = a404m_malloc(nodes_size * sizeof(ParsedNode *));
size_t nodes_inserted = 0;
for (size_t order_index = 0; order_index < PARSE_ORDER_SIZE; ++order_index) {
- const ParseOrder order = PARSE_ORDER[order_index];
+ const ParseOrder *order = &PARSE_ORDER[order_index];
- for (Node *node = order.ltr ? nodesBegin : (nodesEnd - 1);
- nodesBegin <= node && node < nodesEnd; order.ltr ? ++node : --node) {
- for (size_t order_tokens_index = 0; order_tokens_index < order.size;
+ for (Node *node = order->ltr ? nodesBegin : (nodesEnd - 1);
+ nodesBegin <= node && node < nodesEnd; order->ltr ? ++node : --node) {
+ for (size_t order_tokens_index = 0; order_tokens_index < order->size;
++order_tokens_index) {
- if (node->token == order.tokens[order_tokens_index]) {
+ if (node->token == order->tokens[order_tokens_index]) {
ParsedNode *parsedNode =
parseNode(nodesBegin, nodesEnd, node, parent);
if (parsedNode == NULL) {
@@ -246,9 +236,9 @@ static bool isAllowedCodeScope(ParsedToken token) {
switch (token) {
case PARSED_TOKEN_NONE:
case PARSED_TOKEN_ROOT:
- case PARSED_TOKEN_PRINT:
case PARSED_TOKEN_PARENTHESIS:
case PARSED_TOKEN_VALUE_STRING:
+ case PARSED_TOKEN_FUNCTION_CALL:
return false;
case PARSED_TOKEN_EOL:
return true;
@@ -261,10 +251,10 @@ static bool isAllowedParenthesisScope(ParsedToken token) {
switch (token) {
case PARSED_TOKEN_PARENTHESIS:
case PARSED_TOKEN_VALUE_STRING:
+ case PARSED_TOKEN_FUNCTION_CALL:
return true;
case PARSED_TOKEN_NONE:
case PARSED_TOKEN_ROOT:
- case PARSED_TOKEN_PRINT:
case PARSED_TOKEN_EOL:
return false;
}
@@ -285,8 +275,6 @@ ScopeMetadata *parserScopeParenthesis(Node *nodesBegin, Node *nodesEnd,
ParsedNode *parseNode(Node *nodesBegin, Node *nodesEnd, Node *node,
ParsedNode *parent) {
switch (node->token) {
- case TOKEN_KEYWORD_PRINT:
- return parserPrint(nodesBegin, nodesEnd, node, parent);
case TOKEN_OPERATOR_PARENTHESES_CLOSE:
return parseParenthesis(nodesBegin, nodesEnd, node, parent);
case TOKEN_STRING:
@@ -300,37 +288,9 @@ ParsedNode *parseNode(Node *nodesBegin, Node *nodesEnd, Node *node,
}
}
-ParsedNode *parserPrint(Node *, Node *nodesEnd, Node *node,
- ParsedNode *parent) {
- Node *follow = node + 1;
-
- if (follow < nodesEnd && follow->token == TOKEN_PARSED) {
- ParsedNode *root = a404m_malloc(sizeof(ParsedNode));
- root->strBegin = node->strBegin;
- root->strEnd = node->strEnd;
- root->token = PARSED_TOKEN_PRINT;
- root->parent = parent;
-
- ParsedNode *operand = root->metadata =
- getUntilCommonFather(follow->parsedNode, parent);
- if (operand == NULL || operand->token != PARSED_TOKEN_PARENTHESIS) {
- fprintf(stderr, "error in parsing token '%s' at compiler line %d\n",
- TOKEN_STRINGS[node->token], __LINE__);
- free(root);
- return NULL;
- }
- operand->parent = root;
-
- node->parsedNode = root;
- node->token = TOKEN_PARSED;
- return root;
- }
- return NULL;
-}
-
ParsedNode *parseParenthesis(Node *nodesBegin, Node *, Node *node,
ParsedNode *parent) {
- ParsedNode *parsedNode = a404m_malloc(sizeof(*parsedNode));
+ ParsedNode *root = a404m_malloc(sizeof(*root));
Node *opening = NULL;
Node *closing = node;
for (Node *iter = closing - 1; iter >= nodesBegin; --iter) {
@@ -345,26 +305,48 @@ ParsedNode *parseParenthesis(Node *nodesBegin, Node *, Node *node,
goto RETURN_ERROR;
}
- parsedNode->strBegin = opening->strBegin;
- parsedNode->strEnd = closing->strEnd;
- parsedNode->token = PARSED_TOKEN_PARENTHESIS;
- parsedNode->parent = parent;
+ Node *functionName = opening - 1;
+ if (functionName >= nodesBegin && functionName->token == TOKEN_IDENTIFIER) {
+ functionName->token = TOKEN_PARSED;
+ functionName->parsedNode = root;
- const ScopeMetadata *metadata = parsedNode->metadata =
- parserScopeParenthesis(opening + 1, closing, parsedNode);
+ root->token = PARSED_TOKEN_FUNCTION_CALL;
+ root->strBegin = (opening - 1)->strBegin;
+ root->strEnd = closing->strEnd;
+ root->parent = parent;
- if (metadata == NULL) {
- fprintf(stderr, "error in parsing token '%s' at compiler line %d\n",
- TOKEN_STRINGS[node->token], __LINE__);
- goto RETURN_ERROR;
+ FunctionCallMetadata *metadata = root->metadata =
+ a404m_malloc(sizeof(*metadata));
+ metadata->functionNameBegin = functionName->strBegin;
+ metadata->functionNameEnd = functionName->strEnd;
+
+ if ((metadata->scope =
+ parserScopeParenthesis(opening + 1, closing, root)) == NULL) {
+ fprintf(stderr, "error in parsing token '%s' at compiler line %d\n",
+ TOKEN_STRINGS[node->token], __LINE__);
+ free(metadata);
+ goto RETURN_ERROR;
+ }
+ } else {
+ root->token = PARSED_TOKEN_PARENTHESIS;
+ root->strBegin = opening->strBegin;
+ root->strEnd = closing->strEnd;
+ root->parent = parent;
+
+ if ((root->metadata = parserScopeParenthesis(opening + 1, closing, root)) ==
+ NULL) {
+ fprintf(stderr, "error in parsing token '%s' at compiler line %d\n",
+ TOKEN_STRINGS[node->token], __LINE__);
+ goto RETURN_ERROR;
+ }
}
- closing->parsedNode = opening->parsedNode = parsedNode;
+ closing->parsedNode = opening->parsedNode = root;
opening->token = closing->token = TOKEN_PARSED;
- return parsedNode;
+ return root;
RETURN_ERROR:
- free(parsedNode);
+ free(root);
return NULL;
}
@@ -377,7 +359,7 @@ ParsedNode *parseString(Node *node, ParsedNode *parent) {
ParsedNode *parseEOL(Node *nodesBegin, Node *, Node *node, ParsedNode *parent) {
Node *before = node - 1;
- if (before < nodesBegin && before->token != TOKEN_PARSED) {
+ if (before < nodesBegin || before->token != TOKEN_PARSED) {
return NULL;
}
diff --git a/src/compiler/parser/parser.h b/src/compiler/parser/parser.h
index 4a39e17..520c5d1 100644
--- a/src/compiler/parser/parser.h
+++ b/src/compiler/parser/parser.h
@@ -5,8 +5,8 @@
typedef enum ParsedToken {
PARSED_TOKEN_NONE = 0,
PARSED_TOKEN_ROOT,
- PARSED_TOKEN_PRINT,
PARSED_TOKEN_PARENTHESIS,
+ PARSED_TOKEN_FUNCTION_CALL,
PARSED_TOKEN_VALUE_STRING,
PARSED_TOKEN_EOL,
} ParsedToken;
@@ -31,6 +31,11 @@ typedef struct ScopeMetadata {
struct ParsedNode **operands;
size_t operands_size;
} ScopeMetadata;
+typedef struct FunctionCallMetadata {
+ char const *functionNameBegin;
+ char const *functionNameEnd;
+ ScopeMetadata *scope;
+} FunctionCallMetadata ;
typedef ParsedNode PrintMetadata;
typedef ParsedNode EOLMetadata;
@@ -56,8 +61,6 @@ extern ScopeMetadata *parserScopeParenthesis(Node *nodesBegin, Node *nodesEnd,
extern ParsedNode *parseNode(Node *nodesBegin, Node *nodesEnd, Node *node,
ParsedNode *parent);
-extern ParsedNode *parserPrint(Node *nodesBegin, Node *nodesEnd, Node *node,
- ParsedNode *parent);
extern ParsedNode *parseParenthesis(Node *nodesBegin, Node *nodesEnd,
Node *node, ParsedNode *parent);
extern ParsedNode *parseString(Node *node, ParsedNode *parent);
diff --git a/src/main.c b/src/main.c
index c40bfec..c23696e 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1,13 +1,7 @@
-#include <compiler/lexer/lexer.h>
-#include <stdio.h>
#include <stdlib.h>
#include <utils/file.h>
-
-#include "compiler/code_generator/code_generator.h"
-#include "compiler/parser/parser.h"
-#include "utils/time.h"
-#include "utils/types.h"
-#include "vm/runner/runner.h"
+#include <utils/time.h>
+#include <vm/runner/runner.h>
static const char *codes[] = {
"print(\"\");",
diff --git a/src/vm/runner/runner.c b/src/vm/runner/runner.c
index 5e63395..de1a478 100644
--- a/src/vm/runner/runner.c
+++ b/src/vm/runner/runner.c
@@ -1,14 +1,25 @@
#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)) {
@@ -24,15 +35,32 @@ RETURN_ERROR:
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_PRINT: {
- const SizedString *string = (*stack)[*stack_inserted - 1];
- --*stack_inserted;
- printf("%.*s", (int)string->size, string->str);
- } break;
case COMMAND_PUSH_STRING: {
SizedString *string = instruction.operand;
if (*stack_inserted == *stack_size) {
@@ -41,10 +69,26 @@ bool runInstruction(Instruction instruction, void ***restrict stack,
}
(*stack)[*stack_inserted] = string;
++*stack_inserted;
- } break;
- default:
- fprintf(stderr, "unknown command '%d'\n", instruction.command);
- return false;
+ 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:
}
- return true;
+ 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);
}
diff --git a/src/vm/runner/runner.h b/src/vm/runner/runner.h
index e59b447..e81aed7 100644
--- a/src/vm/runner/runner.h
+++ b/src/vm/runner/runner.h
@@ -2,8 +2,17 @@
#include <compiler/code_generator/code_generator.h>
+typedef void (*BuiltinFunction)(void ***restrict stack,
+ size_t *restrict stack_inserted);
+
+extern const BuiltinFunction BUILTIN_FUNCTIONS[];
+extern const char *BUILTIN_FUNCTION_NAMES[];
+extern const size_t BUILTIN_FUNCTIONS_SIZE;
+
extern bool runner(Instructions instructions);
extern bool runInstruction(Instruction instruction, void ***restrict stack,
size_t *restrict stack_size,
size_t *restrict stack_inserted);
+
+extern void print(void ***restrict stack, size_t *restrict stack_inserted);