diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/compiler/code_generator/code_generator.c | 69 | ||||
-rw-r--r-- | src/compiler/code_generator/code_generator.h | 5 | ||||
-rw-r--r-- | src/compiler/lexer/lexer.c | 56 | ||||
-rw-r--r-- | src/compiler/lexer/lexer.h | 4 | ||||
-rw-r--r-- | src/compiler/parser/parser.c | 148 | ||||
-rw-r--r-- | src/compiler/parser/parser.h | 9 | ||||
-rw-r--r-- | src/main.c | 10 | ||||
-rw-r--r-- | src/vm/runner/runner.c | 64 | ||||
-rw-r--r-- | src/vm/runner/runner.h | 9 |
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); @@ -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); |