parsing done + vm

This commit is contained in:
SimonFJ20 2024-04-05 04:14:35 +02:00
parent 216dbf2fce
commit afb271be68
7 changed files with 610 additions and 30 deletions

View File

@ -5,6 +5,9 @@ CFLAGS = -std=c17 -Wall -Wextra -Wpedantic -Wconversion -pedantic -pedantic-erro
CFILES = \ CFILES = \
main.c \ main.c \
parser.c \
checker.c \
vm.c \
OBJECT_FILES = $(patsubst %.c,%.o,$(CFILES)) OBJECT_FILES = $(patsubst %.c,%.o,$(CFILES))

1
checker.c Normal file
View File

@ -0,0 +1 @@
#include "parser.h"

24
main.c
View File

@ -1,3 +1,25 @@
#include "parser.h"
#include <stddef.h>
#include <stdio.h> #include <stdio.h>
#include <string.h>
int main(void) { printf("hello world\n"); } bool lexer_debug = false;
void print_error(const char* message, Pos pos)
{
fprintf(
stderr, "\x1b[31merror\x1b[0m: %s, on line %d\n", message, pos.line);
}
int main(void)
{
char test_program[] = " if a == true { (1) += 2; } ";
Parser parser;
parser_construct(&parser, test_program, strlen(test_program));
ASTNode* ast = parser_parse_statements(&parser);
printf("ast = %d\n", ast->node_type);
}

481
parser.c
View File

@ -1,5 +1,6 @@
#include "parser.h" #include "parser.h"
#include <stddef.h> #include <stddef.h>
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -65,7 +66,8 @@ static inline TokenType match_id_to_token_type(
const char* source, size_t length, struct MatchIdToTokenTypeCase cases[]) const char* source, size_t length, struct MatchIdToTokenTypeCase cases[])
{ {
for (size_t i = 0; cases[i].keyword != NULL; ++i) { for (size_t i = 0; cases[i].keyword != NULL; ++i) {
if (strncmp(source, cases[i].keyword, length) == 0) { if (strlen(cases[i].keyword) <= length
&& strncmp(source, cases[i].keyword, length) == 0) {
return cases[i].token_type; return cases[i].token_type;
} }
} }
@ -87,7 +89,9 @@ static inline Token lex_id_or_keyword(Lexer* lexer)
{ "and", TokenType_And }, { "and", TokenType_And },
{ "or", TokenType_Or }, { "or", TokenType_Or },
{ "if", TokenType_If }, { "if", TokenType_If },
{ "else", TokenType_Else },
{ "loop", TokenType_Loop }, { "loop", TokenType_Loop },
{ "let", TokenType_Let },
{ "fn", TokenType_Fn }, { "fn", TokenType_Fn },
{ "return", TokenType_Return }, { "return", TokenType_Return },
{ "break", TokenType_Break }, { "break", TokenType_Break },
@ -134,11 +138,23 @@ Token lexer_next(Lexer* lexer)
} }
if (c >= '1' && c <= '9') { if (c >= '1' && c <= '9') {
lexer_step(lexer); lexer_step(lexer);
while (!lexer_done(lexer) && c >= '1' && c <= '9') { while (!lexer_done(lexer) && lexer_current(lexer) >= '0'
&& lexer_current(lexer) <= '9') {
lexer_step(lexer); lexer_step(lexer);
} }
return lexer_token(lexer, TokenType_Int, pos); return lexer_token(lexer, TokenType_Int, pos);
} }
if (c == '-') {
lexer_step(lexer);
if (lexer_current(lexer) == '=') {
lexer_step(lexer);
return lexer_token(lexer, TokenType_MinusEqual, pos);
} else if (lexer_current(lexer) == '>') {
lexer_step(lexer);
return lexer_token(lexer, TokenType_MinusGT, pos);
}
return lexer_token(lexer, TokenType_Minus, pos);
}
switch (c) { switch (c) {
case '0': case '0':
return lex_single_char(lexer, TokenType_Int); return lex_single_char(lexer, TokenType_Int);
@ -161,9 +177,6 @@ Token lexer_next(Lexer* lexer)
case '+': case '+':
return lex_single_or_double_char( return lex_single_or_double_char(
lexer, TokenType_Plus, '=', TokenType_PlusEqual); lexer, TokenType_Plus, '=', TokenType_PlusEqual);
case '-':
return lex_single_or_double_char(
lexer, TokenType_Minus, '=', TokenType_MinusEqual);
case '*': case '*':
return lex_single_or_double_char( return lex_single_or_double_char(
lexer, TokenType_Asterisk, '=', TokenType_AsteriskEqual); lexer, TokenType_Asterisk, '=', TokenType_AsteriskEqual);
@ -292,6 +305,10 @@ void ast_node_free(ASTNode* node)
break; break;
case ASTNodeType_Int: case ASTNodeType_Int:
break; break;
case ASTNodeType_Group:
ast_node_free(node->group_value);
break;
case ASTNodeType_Statements:
case ASTNodeType_Block: case ASTNodeType_Block:
for (size_t i = 0; i < node->statements.length; ++i) { for (size_t i = 0; i < node->statements.length; ++i) {
ast_node_free(node->statements.data[i]); ast_node_free(node->statements.data[i]);
@ -329,23 +346,24 @@ void ast_node_free(ASTNode* node)
ast_node_free(node->assign_node.value); ast_node_free(node->assign_node.value);
break; break;
case ASTNodeType_Let: case ASTNodeType_Let:
if (node->let_node.id != NULL) { ast_node_free(node->let_node.id);
free(node->let_node.id);
}
ast_node_free(node->let_node.value); ast_node_free(node->let_node.value);
break; break;
case ASTNodeType_Break: case ASTNodeType_Break:
break; break;
case ASTNodeType_Fn: case ASTNodeType_Fn:
if (node->fn_node.id != NULL) { ast_node_free(node->fn_node.id);
free(node->fn_node.id);
}
for (size_t i = 0; i < node->fn_node.params.length; ++i) { for (size_t i = 0; i < node->fn_node.params.length; ++i) {
ast_node_free(node->fn_node.params.data[i]); ast_node_free(node->fn_node.params.data[i]);
} }
ast_node_vec_destroy(&node->fn_node.params); ast_node_vec_destroy(&node->fn_node.params);
ast_node_free(node->fn_node.body); ast_node_free(node->fn_node.body);
break; break;
case ASTNodeType_Return:
if (node->return_node.value != NULL) {
ast_node_free(node->return_node.value);
}
break;
} }
free(node); free(node);
} }
@ -360,7 +378,7 @@ void parser_construct(Parser* parser, const char* text, size_t text_length)
.failed = false, .failed = false,
}; };
lexer_construct(&parser->lexer, text, text_length); lexer_construct(&parser->lexer, text, text_length);
parser->current = lexer_next(&parser->lexer); parser_step(parser);
} }
bool parser_failed(const Parser* parser) { return parser->failed; } bool parser_failed(const Parser* parser) { return parser->failed; }
@ -375,11 +393,379 @@ bool parser_done(const Parser* parser)
return parser->current.token_type == TokenType_EOF; return parser->current.token_type == TokenType_EOF;
} }
ASTNode* parser_parse(Parser* parser) { return parser_parse_expr(parser); } ASTNode* parser_parse_statements(Parser* parser)
ASTNode* parser_parse_expr(Parser* parser)
{ {
return parser_parse_operand(parser); Pos pos = parser->current.pos;
ASTNodeVec statements;
ast_node_vec_construct(&statements);
while (!parser_done(parser)) {
ASTNode* statement = parser_parse_statement(parser);
ast_node_vec_push(&statements, statement);
}
return ast_node_new(
ASTNodeType_Statements, pos, (ASTNode) { .statements = statements });
}
ASTNode* parser_parse_statement(Parser* parser)
{
if (parser->current.token_type == TokenType_Fn) {
return parser_parse_fn(parser);
} else if (parser->current.token_type == TokenType_If) {
return parser_parse_if(parser);
} else if (parser->current.token_type == TokenType_Loop) {
return parser_parse_loop(parser);
} else {
ASTNode* statement = parser_parse_single_line_statement(parser);
if (parser->current.token_type != TokenType_Semicolon) {
parser->failed = true;
print_error("parser: expected ';'", parser->current.pos);
}
parser_step(parser);
return statement;
}
}
ASTNode* parser_parse_fn(Parser* parser)
{
Pos pos = parser->current.pos;
parser_step(parser);
if (parser->current.token_type != TokenType_Id) {
parser->failed = true;
print_error("parser: expected 'id'", parser->current.pos);
return ast_node_new(ASTNodeType_Error, pos, (ASTNode) { 0 });
}
ASTNode* id = parser_parse_id(parser);
if (parser->current.token_type != TokenType_LParen) {
parser->failed = true;
print_error("parser: expected '('", parser->current.pos);
return ast_node_new(ASTNodeType_Error, pos, (ASTNode) { 0 });
}
parser_step(parser);
ASTNodeVec params;
ast_node_vec_construct(&params);
if (!parser_done(parser)
&& parser->current.token_type != TokenType_RParen) {
if (parser->current.token_type != TokenType_Id) {
parser->failed = true;
print_error("parser: expected 'id'", parser->current.pos);
return ast_node_new(ASTNodeType_Error, pos, (ASTNode) { 0 });
}
ast_node_vec_push(&params, parser_parse_id(parser));
while (parser->current.token_type == TokenType_Comma) {
parser_step(parser);
if (parser->current.token_type == TokenType_RParen) {
break;
}
if (parser->current.token_type != TokenType_Id) {
parser->failed = true;
print_error("parser: expected 'id'", parser->current.pos);
return ast_node_new(ASTNodeType_Error, pos, (ASTNode) { 0 });
}
ast_node_vec_push(&params, parser_parse_id(parser));
}
}
if (parser->current.token_type != TokenType_RParen) {
parser->failed = true;
print_error("parser: expected ')'", parser->current.pos);
return ast_node_new(ASTNodeType_Error, pos, (ASTNode) { 0 });
}
parser_step(parser);
if (parser->current.token_type != TokenType_LBrace) {
parser->failed = true;
print_error("parser: expected '{'", parser->current.pos);
return ast_node_new(ASTNodeType_Error, pos, (ASTNode) { 0 });
}
ASTNode* body = parser_parse_block(parser);
return ast_node_new(ASTNodeType_Fn, pos, (ASTNode) {
.fn_node = (ASTFnNode) {
.id = id,
.params = params,
.body = body,
},
});
}
ASTNode* parser_parse_single_line_statement(Parser* parser)
{
if (parser->current.token_type == TokenType_Let) {
return parser_parse_let(parser);
} else if (parser->current.token_type == TokenType_Return) {
return parser_parse_return(parser);
} else if (parser->current.token_type == TokenType_Break) {
return parser_parse_break(parser);
} else {
return parser_parse_assign(parser);
}
}
ASTNode* parser_parse_let(Parser* parser)
{
Pos pos = parser->current.pos;
parser_step(parser);
if (parser->current.token_type != TokenType_Id) {
parser->failed = true;
print_error("parser: expected 'id'", parser->current.pos);
return ast_node_new(ASTNodeType_Error, pos, (ASTNode) { 0 });
}
ASTNode* id = parser_parse_id(parser);
if (parser->current.token_type != TokenType_Equal) {
parser->failed = true;
print_error("parser: expected '='", parser->current.pos);
return ast_node_new(ASTNodeType_Error, pos, (ASTNode) { 0 });
}
parser_step(parser);
ASTNode* value = parser_parse_expr(parser);
return ast_node_new(ASTNodeType_Let, pos, (ASTNode) {
.let_node = (ASTLetNode) {
.id = id,
.value = value,
},
});
}
ASTNode* parser_parse_return(Parser* parser)
{
Pos pos = parser->current.pos;
parser_step(parser);
ASTNode* value = NULL;
if (parser->current.token_type != TokenType_Semicolon) {
value = parser_parse_expr(parser);
}
return ast_node_new(ASTNodeType_Return, pos, (ASTNode) {
.return_node = (ASTReturnNode) {
.value = value,
},
});
}
ASTNode* parser_parse_break(Parser* parser)
{
Pos pos = parser->current.pos;
parser_step(parser);
return ast_node_new(ASTNodeType_Return, pos, (ASTNode) { 0 });
}
ASTNode* parser_parse_assign(Parser* parser)
{
Pos pos = parser->current.pos;
ASTNode* subject = parser_parse_expr(parser);
int assign_type = -1;
if (parser->current.token_type == TokenType_Equal) {
assign_type = AssignType_Assign;
} else if (parser->current.token_type == TokenType_PlusEqual) {
assign_type = AssignType_Add;
} else if (parser->current.token_type == TokenType_MinusEqual) {
assign_type = AssignType_Subtract;
} else if (parser->current.token_type == TokenType_AsteriskEqual) {
assign_type = AssignType_Multiply;
}
if (assign_type == -1) {
return subject;
}
parser_step(parser);
return ast_node_new(ASTNodeType_Assign, pos, (ASTNode) {
.assign_node = (ASTAssignNode) {
.assign_type = (AssignType)assign_type,
.subject = subject,
.value = parser_parse_expr(parser),
},
});
}
ASTNode* parser_parse_expr(Parser* parser) { return parser_parse_or(parser); }
static inline ASTNode* binary_node(
Pos pos, BinaryType binary_type, ASTNode* left, ASTNode* right)
{
return ast_node_new(ASTNodeType_Binary, pos, (ASTNode) {
.binary_node = (ASTBinaryNode) {
.binary_type = binary_type,
.left = left,
.right = right,
},
});
}
ASTNode* parser_parse_or(Parser* parser)
{
Pos pos = parser->current.pos;
ASTNode* left = parser_parse_and(parser);
while (parser->current.token_type == TokenType_Or) {
parser_step(parser);
left = binary_node(pos, BinaryType_Or, left, parser_parse_and(parser));
}
return left;
}
ASTNode* parser_parse_and(Parser* parser)
{
Pos pos = parser->current.pos;
ASTNode* left = parser_parse_equality(parser);
while (parser->current.token_type == TokenType_And) {
parser_step(parser);
left = binary_node(
pos, BinaryType_And, left, parser_parse_equality(parser));
}
return left;
}
ASTNode* parser_parse_equality(Parser* parser)
{
Pos pos = parser->current.pos;
ASTNode* left = parser_parse_comparison(parser);
if (parser->current.token_type == TokenType_EqualEqual) {
parser_step(parser);
return binary_node(
pos, BinaryType_EE, left, parser_parse_comparison(parser));
} else if (parser->current.token_type == TokenType_ExclamationEqual) {
parser_step(parser);
return binary_node(
pos, BinaryType_NE, left, parser_parse_comparison(parser));
} else {
return left;
}
}
ASTNode* parser_parse_comparison(Parser* parser)
{
Pos pos = parser->current.pos;
ASTNode* left = parser_parse_term(parser);
while (!parser_done(parser)) {
if (parser->current.token_type == TokenType_LT) {
parser_step(parser);
return binary_node(
pos, BinaryType_LT, left, parser_parse_term(parser));
} else if (parser->current.token_type == TokenType_LTEqual) {
parser_step(parser);
return binary_node(
pos, BinaryType_LTE, left, parser_parse_term(parser));
} else if (parser->current.token_type == TokenType_GT) {
parser_step(parser);
return binary_node(
pos, BinaryType_GT, left, parser_parse_term(parser));
} else if (parser->current.token_type == TokenType_GTEqual) {
parser_step(parser);
return binary_node(
pos, BinaryType_GTE, left, parser_parse_term(parser));
} else {
break;
}
}
return left;
}
ASTNode* parser_parse_term(Parser* parser)
{
Pos pos = parser->current.pos;
ASTNode* left = parser_parse_factor(parser);
while (!parser_done(parser)) {
if (parser->current.token_type == TokenType_Plus) {
parser_step(parser);
return binary_node(
pos, BinaryType_Add, left, parser_parse_factor(parser));
} else if (parser->current.token_type == TokenType_Minus) {
parser_step(parser);
return binary_node(
pos, BinaryType_Subtract, left, parser_parse_factor(parser));
} else {
break;
}
}
return left;
}
ASTNode* parser_parse_factor(Parser* parser)
{
Pos pos = parser->current.pos;
ASTNode* left = parser_parse_unary(parser);
while (!parser_done(parser)) {
if (parser->current.token_type == TokenType_Asterisk) {
parser_step(parser);
return binary_node(
pos, BinaryType_Multiply, left, parser_parse_unary(parser));
} else {
break;
}
}
return left;
}
ASTNode* parser_parse_unary(Parser* parser)
{
Pos pos = parser->current.pos;
if (parser->current.token_type == TokenType_Not) {
parser_step(parser);
return ast_node_new(ASTNodeType_Unary, pos, (ASTNode) {
.unary_node = (ASTUnaryNode) {
.unary_type = UnaryType_Not,
.subject = parser_parse_unary(parser),
},
});
} else if (parser->current.token_type == TokenType_Minus) {
parser_step(parser);
return ast_node_new(ASTNodeType_Unary, pos, (ASTNode) {
.unary_node = (ASTUnaryNode) {
.unary_type = UnaryType_Negate,
.subject = parser_parse_unary(parser),
},
});
} else {
return parser_parse_index_call(parser);
}
}
ASTNode* parser_parse_index_call(Parser* parser)
{
Pos pos = parser->current.pos;
ASTNode* subject = parser_parse_operand(parser);
while (!parser_done(parser)) {
if (parser->current.token_type == TokenType_LParen) {
parser_step(parser);
ASTNodeVec args;
ast_node_vec_construct(&args);
if (!parser_done(parser)
&& parser->current.token_type != TokenType_RParen) {
ast_node_vec_push(&args, parser_parse_expr(parser));
while (parser->current.token_type == TokenType_Comma) {
parser_step(parser);
if (parser->current.token_type == TokenType_RParen) {
break;
}
ast_node_vec_push(&args, parser_parse_expr(parser));
}
}
if (parser->current.token_type != TokenType_RParen) {
parser->failed = true;
print_error("parser: expected ')'", parser->current.pos);
return ast_node_new(ASTNodeType_Error, pos, (ASTNode) { 0 });
}
parser_step(parser);
subject = ast_node_new(ASTNodeType_Call, pos, (ASTNode) {
.call_node = (ASTCallNode) {
.subject = subject,
.args = args,
},
});
} else if (parser->current.token_type == TokenType_LBracket) {
parser_step(parser);
ASTNode* value = parser_parse_expr(parser);
if (parser->current.token_type != TokenType_RBracket) {
parser->failed = true;
print_error("parser: expected ']'", parser->current.pos);
return ast_node_new(ASTNodeType_Error, pos, (ASTNode) { 0 });
}
parser_step(parser);
subject = ast_node_new(ASTNodeType_Index, pos, (ASTNode) {
.index_node = (ASTIndexNode) {
.subject = subject,
.value = value,
},
});
} else {
break;
}
}
return subject;
} }
ASTNode* parser_parse_operand(Parser* parser) ASTNode* parser_parse_operand(Parser* parser)
@ -393,14 +779,17 @@ ASTNode* parser_parse_operand(Parser* parser)
case TokenType_Int: case TokenType_Int:
return parser_parse_int(parser); return parser_parse_int(parser);
case TokenType_LParen: case TokenType_LParen:
return parser_parse_group(parser);
case TokenType_LBrace: case TokenType_LBrace:
return parser_parse_block(parser);
case TokenType_If: case TokenType_If:
return parser_parse_if(parser);
case TokenType_Loop: case TokenType_Loop:
return parser_parse_loop(parser);
default: default:
parser->failed = true; parser->failed = true;
print_error("expected operand", pos); print_error("parser: expected operand", pos);
return ast_node_new(ASTNodeType_Error, pos, (ASTNode) { 0 }); return ast_node_new(ASTNodeType_Error, pos, (ASTNode) { 0 });
break;
} }
} }
@ -430,11 +819,14 @@ ASTNode* parser_parse_group(Parser* parser)
ASTNode* expr = parser_parse_expr(parser); ASTNode* expr = parser_parse_expr(parser);
if (parser->current.token_type != TokenType_RParen) { if (parser->current.token_type != TokenType_RParen) {
parser->failed = true; parser->failed = true;
print_error("parser: expected ')'", pos); print_error("parser: expected ')'", parser->current.pos);
return ast_node_new(ASTNodeType_Error, pos, (ASTNode) { 0 }); return ast_node_new(ASTNodeType_Error, pos, (ASTNode) { 0 });
} }
parser_step(parser); parser_step(parser);
return expr; return ast_node_new(ASTNodeType_Group, pos,
(ASTNode) {
.group_value = expr,
});
} }
ASTNode* parser_parse_block(Parser* parser) ASTNode* parser_parse_block(Parser* parser)
@ -450,7 +842,7 @@ ASTNode* parser_parse_block(Parser* parser)
} }
if (parser->current.token_type != TokenType_RBrace) { if (parser->current.token_type != TokenType_RBrace) {
parser->failed = true; parser->failed = true;
print_error("parser: expected '}'", pos); print_error("parser: expected '}'", parser->current.pos);
return ast_node_new(ASTNodeType_Error, pos, (ASTNode) { 0 }); return ast_node_new(ASTNodeType_Error, pos, (ASTNode) { 0 });
} }
parser_step(parser); parser_step(parser);
@ -458,6 +850,49 @@ ASTNode* parser_parse_block(Parser* parser)
ASTNodeType_Block, pos, (ASTNode) { .statements = statements }); ASTNodeType_Block, pos, (ASTNode) { .statements = statements });
} }
ASTNode* parser_parse_if(Parser* parser); ASTNode* parser_parse_if(Parser* parser)
{
Pos pos = parser->current.pos;
parser_step(parser);
ASTNode* condition = parser_parse_expr(parser);
if (parser->current.token_type != TokenType_LBrace) {
parser->failed = true;
print_error("parser: expected '{'", parser->current.pos);
return ast_node_new(ASTNodeType_Error, pos, (ASTNode) { 0 });
}
ASTNode* truthy = parser_parse_block(parser);
ASTNode* falsy = NULL;
if (parser->current.token_type == TokenType_Else) {
parser_step(parser);
if (parser->current.token_type != TokenType_LBrace) {
parser->failed = true;
print_error("parser: expected '{'", parser->current.pos);
return ast_node_new(ASTNodeType_Error, pos, (ASTNode) { 0 });
}
falsy = parser_parse_block(parser);
}
return ast_node_new(ASTNodeType_If, pos, (ASTNode) {
.if_node = (ASTIfNode) {
.condition = condition,
.truthy = truthy,
.falsy = falsy,
},
});
}
ASTNode* parser_parse_loop(Parser* parser); ASTNode* parser_parse_loop(Parser* parser)
{
Pos pos = parser->current.pos;
parser_step(parser);
if (parser->current.token_type != TokenType_RBrace) {
parser->failed = true;
print_error("parser: expected '}'", parser->current.pos);
return ast_node_new(ASTNodeType_Error, pos, (ASTNode) { 0 });
}
ASTNode* body = parser_parse_block(parser);
return ast_node_new(ASTNodeType_Loop, pos, (ASTNode) {
.loop_node = (ASTLoopNode) {
.body = body,
},
});
}

View File

@ -21,7 +21,9 @@ typedef enum {
TokenType_And, TokenType_And,
TokenType_Or, TokenType_Or,
TokenType_If, TokenType_If,
TokenType_Else,
TokenType_Loop, TokenType_Loop,
TokenType_Let,
TokenType_Fn, TokenType_Fn,
TokenType_Return, TokenType_Return,
TokenType_Break, TokenType_Break,
@ -37,6 +39,7 @@ typedef enum {
TokenType_PlusEqual, TokenType_PlusEqual,
TokenType_Minus, TokenType_Minus,
TokenType_MinusEqual, TokenType_MinusEqual,
TokenType_MinusGT,
TokenType_Asterisk, TokenType_Asterisk,
TokenType_AsteriskEqual, TokenType_AsteriskEqual,
TokenType_Equal, TokenType_Equal,
@ -79,6 +82,7 @@ typedef enum {
ASTNodeType_Error, ASTNodeType_Error,
ASTNodeType_Id, ASTNodeType_Id,
ASTNodeType_Int, ASTNodeType_Int,
ASTNodeType_Group,
ASTNodeType_Block, ASTNodeType_Block,
ASTNodeType_If, ASTNodeType_If,
ASTNodeType_Loop, ASTNodeType_Loop,
@ -90,6 +94,8 @@ typedef enum {
ASTNodeType_Let, ASTNodeType_Let,
ASTNodeType_Break, ASTNodeType_Break,
ASTNodeType_Fn, ASTNodeType_Fn,
ASTNodeType_Return,
ASTNodeType_Statements,
} ASTNodeType; } ASTNodeType;
typedef struct ASTNode ASTNode; typedef struct ASTNode ASTNode;
@ -137,15 +143,15 @@ typedef struct {
typedef enum { typedef enum {
BinaryType_And, BinaryType_And,
BinaryType_Or, BinaryType_Or,
BinaryType_Add,
BinaryType_Subtract,
BinaryType_Multiply,
BinaryType_EE, BinaryType_EE,
BinaryType_NE, BinaryType_NE,
BinaryType_LT, BinaryType_LT,
BinaryType_GT, BinaryType_GT,
BinaryType_LTE, BinaryType_LTE,
BinaryType_GTE, BinaryType_GTE,
BinaryType_Add,
BinaryType_Subtract,
BinaryType_Multiply,
} BinaryType; } BinaryType;
typedef struct { typedef struct {
@ -168,22 +174,27 @@ typedef struct {
} ASTAssignNode; } ASTAssignNode;
typedef struct { typedef struct {
char* id; ASTNode* id;
ASTNode* value; ASTNode* value;
} ASTLetNode; } ASTLetNode;
typedef struct { typedef struct {
char* id; ASTNode* id;
ASTNodeVec params; ASTNodeVec params;
ASTNode* body; ASTNode* body;
} ASTFnNode; } ASTFnNode;
typedef struct {
ASTNode* value;
} ASTReturnNode;
struct ASTNode { struct ASTNode {
ASTNodeType node_type; ASTNodeType node_type;
Pos pos; Pos pos;
union { union {
char* id_value; char* id_value;
int int_value; int int_value;
ASTNode* group_value;
ASTNodeVec statements; ASTNodeVec statements;
ASTIfNode if_node; ASTIfNode if_node;
ASTLoopNode loop_node; ASTLoopNode loop_node;
@ -194,6 +205,7 @@ struct ASTNode {
ASTAssignNode assign_node; ASTAssignNode assign_node;
ASTLetNode let_node; ASTLetNode let_node;
ASTFnNode fn_node; ASTFnNode fn_node;
ASTReturnNode return_node;
}; };
}; };
@ -212,9 +224,23 @@ void parser_construct(Parser* parser, const char* text, size_t text_length);
bool parser_failed(const Parser* parser); bool parser_failed(const Parser* parser);
void parser_step(Parser* parser); void parser_step(Parser* parser);
bool parser_done(const Parser* parser); bool parser_done(const Parser* parser);
ASTNode* parser_parse(Parser* parser); ASTNode* parser_parse_statements(Parser* parser);
ASTNode* parser_parse_statement(Parser* parser); ASTNode* parser_parse_statement(Parser* parser);
ASTNode* parser_parse_fn(Parser* parser);
ASTNode* parser_parse_single_line_statement(Parser* parser);
ASTNode* parser_parse_let(Parser* parser);
ASTNode* parser_parse_return(Parser* parser);
ASTNode* parser_parse_break(Parser* parser);
ASTNode* parser_parse_assign(Parser* parser);
ASTNode* parser_parse_expr(Parser* parser); ASTNode* parser_parse_expr(Parser* parser);
ASTNode* parser_parse_or(Parser* parser);
ASTNode* parser_parse_and(Parser* parser);
ASTNode* parser_parse_equality(Parser* parser);
ASTNode* parser_parse_comparison(Parser* parser);
ASTNode* parser_parse_term(Parser* parser);
ASTNode* parser_parse_factor(Parser* parser);
ASTNode* parser_parse_unary(Parser* parser);
ASTNode* parser_parse_index_call(Parser* parser);
ASTNode* parser_parse_operand(Parser* parser); ASTNode* parser_parse_operand(Parser* parser);
ASTNode* parser_parse_id(Parser* parser); ASTNode* parser_parse_id(Parser* parser);
ASTNode* parser_parse_int(Parser* parser); ASTNode* parser_parse_int(Parser* parser);
@ -223,4 +249,11 @@ ASTNode* parser_parse_block(Parser* parser);
ASTNode* parser_parse_if(Parser* parser); ASTNode* parser_parse_if(Parser* parser);
ASTNode* parser_parse_loop(Parser* parser); ASTNode* parser_parse_loop(Parser* parser);
typedef struct {
int _a;
} Checker;
void checker_construct(Checker* checker);
void checker_(Checker* checker);
#endif #endif

16
vm.c Normal file
View File

@ -0,0 +1,16 @@
#include "vm.h"
#include <stdlib.h>
void vm_construct(
VM* vm, const Op* program, size_t program_size, size_t stack_size)
{
*vm = (VM) {
.program = program,
.program_size = program_size,
.pc = 0,
.stack = malloc(sizeof(Value) * stack_size),
.stack_size = stack_size,
.sp = 0,
.bp = 0,
};
}

70
vm.h Normal file
View File

@ -0,0 +1,70 @@
#ifndef VM_H
#define VM_H
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
typedef enum {
OpType_Nop,
OpType_PushNull,
OpType_PushInt,
OpType_PushBool,
OpType_PushPtr,
OpType_Pop,
OpType_LoadLocal,
OpType_StoreLocal,
OpType_Jump,
OpType_JumpIf,
OpType_Load,
OpType_Store,
OpType_Call,
OpType_Return,
OpType_And,
OpType_Or,
OpType_EE,
OpType_NE,
OpType_LT,
OpType_GT,
OpType_LTE,
OpType_GTE,
OpType_Add,
OpType_Subtract,
OpType_Multiply,
OpType_Not,
OpType_Negate,
} OpType;
typedef uint32_t Op;
typedef enum {
ValueType_Null,
ValueType_Int,
ValueType_Bool,
ValueType_Ptr,
} ValueType;
typedef struct Value Value;
struct Value {
ValueType type;
union {
int int_value;
bool bool_value;
void* ptr_value;
};
};
typedef struct {
const Op* program;
size_t program_size;
size_t pc;
Value* stack;
size_t stack_size;
size_t sp;
size_t bp;
} VM;
void vm_construct(
VM* vm, const Op* program, size_t program_size, size_t stack_size);
#endif