From b873916ea511cab56d84b764bf3796392598b4fb Mon Sep 17 00:00:00 2001 From: Brendan Hansen Date: Mon, 1 Jun 2020 20:05:14 -0500 Subject: [PATCH] Better parse tree printer and some type checking --- docs/plan | 63 +++---- docs/thoughts | 2 + onyx | Bin 92544 -> 97080 bytes onyx.c | 10 +- onyxlex.c | 2 + onyxlex.h | 1 + onyxmsgs.c | 2 + onyxmsgs.h | 2 + onyxparser.c | 445 +++++++++++++++++++++++++-------------------- onyxparser.h | 1 + onyxutils.c | 9 + progs/minimal.onyx | 26 +-- progs/mvp.onyx | 2 +- 13 files changed, 305 insertions(+), 260 deletions(-) diff --git a/docs/plan b/docs/plan index 0d11788d..d78b4992 100644 --- a/docs/plan +++ b/docs/plan @@ -26,36 +26,33 @@ FEATURES: - defer ? polymorphic functions -EXAMPLE CODE: - -// This is a comment -// This is also the only way to do comments - -use "core"; // Looks for "core.onyx" in the current directory - -Foo :: struct { x i32, y i32 }; - -export add :: proc (a i32, b i32) -> i32 { - return a + b; -}; - -foo :: proc (a i32) -> Foo { - return Foo { x = a, y = 0 }; -} - -MVP CODE: - -/* Comments need to be parsed */ - -export add :: proc (a i32, b i32) -> i32 { - return a + b; -} - -export max :: proc (a i32, b i32) -> i32 { - /* Curly braces are required */ - if a > b { - return a; - } else { - return b; - } -} +HOW: + Currently there is a multi-phase development process since implementing everything + at once would be overwhelming and unsatisfying. The current progress of each stage: + + Stage 1 (MVP): + [ ] Can declare procedures + [ ] Procedures have params and returns of the following types: + - i32, u32 + - i64, u64 + - f32, f64 + [ ] Procedures have locals of the same set of types + [ ] Locals are declared in the following way + local : (const) (type) (= initial value); + + if const is specified, the value is unmodifiable + if type is specified, that is assumed to be the correct type + if type is not specified, the type of initial value is used as the type + + [ ] Five basic math operations are legal: + + - * / % + [ ] Math operations are sign aware and only operate on operands of the same type + [ ] All casts are explicit using this syntax: + X as T + + casts X to type T + + [ ] Conditional branching works as expected + [ ] Curly braces are required for all bodies of blocks + [ ] Simple while loop is functioning as expected + [ ] break and continue semantics diff --git a/docs/thoughts b/docs/thoughts index 86a7ba5d..24dfa3cc 100644 --- a/docs/thoughts +++ b/docs/thoughts @@ -22,3 +22,5 @@ Type checking at parse time: foo(5) would have a left node of SYMBOL:foo This will be resolved in a later stage between the parsing and semantic pass Type checking and resolving would have to occur afterwards + +Creating an IR: diff --git a/onyx b/onyx index 0786469358d3d498ecc20b1d390fc2338fbb24ae..37a1774ae70719ac06b4010caf3f5d73c76dd987 100755 GIT binary patch delta 39334 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 P{(M1pb#Tg5*6e=)bb0|A delta 38211 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 diff --git a/onyx.c b/onyx.c index 27eeec05..ceb09703 100644 --- a/onyx.c +++ b/onyx.c @@ -53,17 +53,19 @@ int main(int argc, char *argv[]) { // even if it may have still been generated correctly. if (onyx_message_has_errors(&msgs)) { onyx_message_print(&msgs); + goto main_exit; } else { onyx_ast_print(program, 0); bh_printf("\nNo errors.\n"); } - bh_file_contents_delete(&fc); - onyx_tokenizer_free(&tokenizer); - onyx_parser_free(&parser); + +main_exit: // NOTE: Cleanup, since C doesn't have defer bh_arena_free(&msg_arena); bh_arena_free(&ast_arena); - + onyx_parser_free(&parser); + onyx_tokenizer_free(&tokenizer); + bh_file_contents_delete(&fc); return 0; } diff --git a/onyxlex.c b/onyxlex.c index a922f7c8..d76c93f3 100644 --- a/onyxlex.c +++ b/onyxlex.c @@ -19,6 +19,7 @@ static const char* onyx_token_type_names[] = { "foreign", //"TOKEN_TYPE_KEYWORD_FOREIGN", "proc", //"TOKEN_TYPE_KEYWORD_PROC", "global", //"TOKEN_TYPE_KEYWORD_GLOBAL", + "as", //"TOKEN_TYPE_KEYWORD_CAST", "->", //"TOKEN_TYPE_RIGHT_ARROW", "<-", //"TOKEN_TYPE_LEFT_ARROW", @@ -160,6 +161,7 @@ OnyxToken* onyx_get_token(OnyxTokenizer* tokenizer) { LITERAL_TOKEN("do", TOKEN_TYPE_KEYWORD_DO); LITERAL_TOKEN("proc", TOKEN_TYPE_KEYWORD_PROC); LITERAL_TOKEN("global", TOKEN_TYPE_KEYWORD_GLOBAL); + LITERAL_TOKEN("as", TOKEN_TYPE_KEYWORD_CAST); LITERAL_TOKEN("->", TOKEN_TYPE_RIGHT_ARROW); LITERAL_TOKEN("<-", TOKEN_TYPE_RIGHT_ARROW); LITERAL_TOKEN("(", TOKEN_TYPE_OPEN_PAREN); diff --git a/onyxlex.h b/onyxlex.h index a64b0ec6..b1b5eb06 100644 --- a/onyxlex.h +++ b/onyxlex.h @@ -21,6 +21,7 @@ typedef enum OnyxTokenType { TOKEN_TYPE_KEYWORD_FOREIGN, TOKEN_TYPE_KEYWORD_PROC, TOKEN_TYPE_KEYWORD_GLOBAL, + TOKEN_TYPE_KEYWORD_CAST, TOKEN_TYPE_RIGHT_ARROW, TOKEN_TYPE_LEFT_ARROW, diff --git a/onyxmsgs.c b/onyxmsgs.c index 6b92357d..a2e55512 100644 --- a/onyxmsgs.c +++ b/onyxmsgs.c @@ -9,6 +9,8 @@ static const char* msg_formats[] = { "attempt to assign to constant '%s'", "unknown symbol '%s'", "redefinition of function '%s'", + "mismatched types for binary operator, '%s', '%s'", + "mismatched types on assignment, '%s', '%s'", }; void onyx_message_add(OnyxMessages* msgs, OnyxMessageType type, OnyxFilePos pos, ...) { diff --git a/onyxmsgs.h b/onyxmsgs.h index fc102233..6c6a19e8 100644 --- a/onyxmsgs.h +++ b/onyxmsgs.h @@ -16,6 +16,8 @@ typedef enum OnyxMessageType { ONYX_MESSAGE_TYPE_ASSIGN_CONST, ONYX_MESSAGE_TYPE_UNKNOWN_SYMBOL, ONYX_MESSAGE_TYPE_FUNCTION_REDEFINITION, + ONYX_MESSAGE_TYPE_BINOP_MISMATCH_TYPE, + ONYX_MESSAGE_TYPE_ASSIGNMENT_TYPE_MISMATCH, ONYX_MESSAGE_TYPE_COUNT, } OnyxMessageType; diff --git a/onyxparser.c b/onyxparser.c index 77bc0c47..103d8e3c 100644 --- a/onyxparser.c +++ b/onyxparser.c @@ -1,5 +1,6 @@ #include "onyxlex.h" +#include "onyxmsgs.h" #include "onyxparser.h" static const char* ast_node_names[] = { @@ -42,23 +43,19 @@ static const char* ast_node_names[] = { struct OnyxTypeInfo builtin_types[] = { { ONYX_TYPE_INFO_KIND_UNKNOWN, 0, "unknown" }, - { ONYX_TYPE_INFO_KIND_VOID, 0, "void" }, + { ONYX_TYPE_INFO_KIND_VOID, 0, "void", 0, 0, 0, 0, 1 }, - { ONYX_TYPE_INFO_KIND_BOOL, 1, "bool", 0, 0, 0, 1 }, + { ONYX_TYPE_INFO_KIND_BOOL, 1, "bool", 0, 0, 0, 1, 1 }, - { ONYX_TYPE_INFO_KIND_UINT8, 1, "u8", 1, 1, 0, 0 }, - { ONYX_TYPE_INFO_KIND_UINT16, 2, "u16", 1, 1, 0, 0 }, - { ONYX_TYPE_INFO_KIND_UINT32, 4, "u32", 1, 1, 0, 0 }, - { ONYX_TYPE_INFO_KIND_UINT64, 8, "u64", 1, 1, 0, 0 }, + { ONYX_TYPE_INFO_KIND_UINT32, 4, "u32", 1, 1, 0, 0, 1 }, + { ONYX_TYPE_INFO_KIND_UINT64, 8, "u64", 1, 1, 0, 0, 1 }, - { ONYX_TYPE_INFO_KIND_INT8, 1, "i8", 1, 0, 0, 0 }, - { ONYX_TYPE_INFO_KIND_INT16, 2, "i16", 1, 0, 0, 0 }, - { ONYX_TYPE_INFO_KIND_INT32, 4, "i32", 1, 0, 0, 0 }, - { ONYX_TYPE_INFO_KIND_INT64, 8, "i64", 1, 0, 0, 0 }, + { ONYX_TYPE_INFO_KIND_INT32, 4, "i32", 1, 0, 0, 0, 1 }, + { ONYX_TYPE_INFO_KIND_INT64, 8, "i64", 1, 0, 0, 0, 1 }, - { ONYX_TYPE_INFO_KIND_FLOAT32, 4, "f32", 0, 0, 1, 0 }, - { ONYX_TYPE_INFO_KIND_FLOAT64, 8, "f64", 0, 0, 1, 0 }, - { ONYX_TYPE_INFO_KIND_SOFT_FLOAT, 8, "sf64", 0, 0, 1, 0 }, + { ONYX_TYPE_INFO_KIND_FLOAT32, 4, "f32", 0, 0, 1, 0, 1 }, + { ONYX_TYPE_INFO_KIND_FLOAT64, 8, "f64", 0, 0, 1, 0, 1}, + { ONYX_TYPE_INFO_KIND_SOFT_FLOAT, 8, "sf64", 0, 0, 1, 0, 1 }, { 0xffffffff } // Sentinel }; @@ -197,41 +194,44 @@ static void remove_identifier(OnyxParser* parser, OnyxAstNode* ident) { static OnyxAstNode* parse_factor(OnyxParser* parser) { switch (parser->curr_token->type) { - case TOKEN_TYPE_OPEN_PAREN: { - parser_next_token(parser); - OnyxAstNode* expr = parse_expression(parser); - expect(parser, TOKEN_TYPE_CLOSE_PAREN); - return expr; - } - - case TOKEN_TYPE_SYMBOL: { - OnyxToken* sym_token = expect(parser, TOKEN_TYPE_SYMBOL); - OnyxAstNode* sym_node = lookup_identifier(parser, sym_token); - if (sym_node == NULL) { - onyx_token_null_toggle(*sym_token); - onyx_message_add(parser->msgs, - ONYX_MESSAGE_TYPE_UNKNOWN_SYMBOL, - sym_token->pos, sym_token->token); - onyx_token_null_toggle(*sym_token); - } + case TOKEN_TYPE_OPEN_PAREN: + { + parser_next_token(parser); + OnyxAstNode* expr = parse_expression(parser); + expect(parser, TOKEN_TYPE_CLOSE_PAREN); + return expr; + } - // TODO: Handle calling a function - return sym_node; - } + case TOKEN_TYPE_SYMBOL: + { + OnyxToken* sym_token = expect(parser, TOKEN_TYPE_SYMBOL); + OnyxAstNode* sym_node = lookup_identifier(parser, sym_token); + if (sym_node == NULL) { + onyx_token_null_toggle(*sym_token); + onyx_message_add(parser->msgs, + ONYX_MESSAGE_TYPE_UNKNOWN_SYMBOL, + sym_token->pos, sym_token->token); + onyx_token_null_toggle(*sym_token); + } + + // TODO: Handle calling a function + return sym_node; + } - case TOKEN_TYPE_LITERAL_NUMERIC: { - OnyxAstNode* lit_node = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_LITERAL); - lit_node->type = &builtin_types[ONYX_TYPE_INFO_KIND_INT64]; - lit_node->token = expect(parser, TOKEN_TYPE_LITERAL_NUMERIC); - lit_node->flags |= ONYX_AST_FLAG_COMPTIME; - return lit_node; - } + case TOKEN_TYPE_LITERAL_NUMERIC: + { + OnyxAstNode* lit_node = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_LITERAL); + lit_node->type = &builtin_types[ONYX_TYPE_INFO_KIND_INT64]; + lit_node->token = expect(parser, TOKEN_TYPE_LITERAL_NUMERIC); + lit_node->flags |= ONYX_AST_FLAG_COMPTIME; + return lit_node; + } - default: - onyx_message_add(parser->msgs, - ONYX_MESSAGE_TYPE_UNEXPECTED_TOKEN, - parser->curr_token->pos, - onyx_get_token_type_name(parser->curr_token->type)); + default: + onyx_message_add(parser->msgs, + ONYX_MESSAGE_TYPE_UNEXPECTED_TOKEN, + parser->curr_token->pos, + onyx_get_token_type_name(parser->curr_token->type)); } return NULL; @@ -249,12 +249,25 @@ static OnyxAstNode* parse_bin_op(OnyxParser* parser, OnyxAstNode* left) { } if (kind != -1) { + OnyxToken* bin_op_tok = parser->curr_token; parser_next_token(parser); + OnyxAstNode* right = parse_factor(parser); + // NOTE: Typechecking like this will not be here for long but + // want to start working on it early + if (left->type != right->type) { + onyx_message_add(parser->msgs, + ONYX_MESSAGE_TYPE_BINOP_MISMATCH_TYPE, + bin_op_tok->pos, + left->type->name, right->type->name); + return &error_node; + } + OnyxAstNode* bin_op = onyx_ast_node_new(parser->allocator, kind); bin_op->left = left; bin_op->right = right; + bin_op->type = left->type; return bin_op; } @@ -265,14 +278,31 @@ static OnyxAstNode* parse_expression(OnyxParser* parser) { OnyxAstNode* left = parse_factor(parser); switch (parser->curr_token->type) { - case TOKEN_TYPE_SYM_PLUS: - case TOKEN_TYPE_SYM_MINUS: - case TOKEN_TYPE_SYM_STAR: - case TOKEN_TYPE_SYM_FSLASH: - case TOKEN_TYPE_SYM_PERCENT: { - OnyxAstNode* expr = parse_bin_op(parser, left); - return expr; - } + case TOKEN_TYPE_SYM_PLUS: + case TOKEN_TYPE_SYM_MINUS: + case TOKEN_TYPE_SYM_STAR: + case TOKEN_TYPE_SYM_FSLASH: + case TOKEN_TYPE_SYM_PERCENT: + { + OnyxAstNode* expr = parse_bin_op(parser, left); + return expr; + } + case TOKEN_TYPE_KEYWORD_CAST: + { + parser_next_token(parser); + OnyxTypeInfo* type = parse_type(parser); + + // NOTE: This may be premature in the parser but a cast + // node doesn't need to exist if the source and target + // types are the same + if (type == left->type) return left; + + OnyxAstNode* cast_node = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_CAST); + cast_node->type = type; + cast_node->left = left; + + return cast_node; + } } return left; @@ -289,83 +319,96 @@ static b32 parse_symbol_statement(OnyxParser* parser, OnyxAstNode** ret) { OnyxToken* symbol = expect(parser, TOKEN_TYPE_SYMBOL); switch (parser->curr_token->type) { - // NOTE: Declaration - case TOKEN_TYPE_SYM_COLON: { - parser_next_token(parser); - OnyxTypeInfo* type = &builtin_types[ONYX_TYPE_INFO_KIND_UNKNOWN]; - u32 flags = ONYX_AST_FLAG_LVAL; - - // NOTE: var: const ... - if (parser->curr_token->type == TOKEN_TYPE_KEYWORD_CONST) { - parser_next_token(parser); - flags |= ONYX_AST_FLAG_CONST; - } - - // NOTE: var: type - if (parser->curr_token->type == TOKEN_TYPE_SYMBOL) { - type = parse_type(parser); - } - - OnyxAstNodeLocal* local = (OnyxAstNodeLocal*) onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_LOCAL); - local->token = symbol; - local->type = type; - local->flags |= flags; - - insert_identifier(parser, (OnyxAstNode *) local, 1); - - if (parser->curr_token->type == TOKEN_TYPE_SYM_EQUALS) { - parser_next_token(parser); - - OnyxAstNode* expr = parse_expression(parser); - OnyxAstNode* assignment = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_ASSIGNMENT); - assignment->right = expr; - assignment->left = (OnyxAstNode*) local; - *ret = assignment; - } - return 1; - } + // NOTE: Declaration + case TOKEN_TYPE_SYM_COLON: + { + parser_next_token(parser); + OnyxTypeInfo* type = &builtin_types[ONYX_TYPE_INFO_KIND_UNKNOWN]; + u32 flags = ONYX_AST_FLAG_LVAL; + + // NOTE: var: const ... + if (parser->curr_token->type == TOKEN_TYPE_KEYWORD_CONST) { + parser_next_token(parser); + flags |= ONYX_AST_FLAG_CONST; + } + + // NOTE: var: type + if (parser->curr_token->type == TOKEN_TYPE_SYMBOL) { + type = parse_type(parser); + } + + OnyxAstNodeLocal* local = (OnyxAstNodeLocal*) onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_LOCAL); + local->token = symbol; + local->type = type; + local->flags |= flags; + + insert_identifier(parser, (OnyxAstNode *) local, 1); + + if (parser->curr_token->type == TOKEN_TYPE_SYM_EQUALS) { + OnyxAstNode* assignment = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_ASSIGNMENT); + assignment->token = parser->curr_token; + parser_next_token(parser); + + OnyxAstNode* expr = parse_expression(parser); + assignment->right = expr; + assignment->left = (OnyxAstNode*) local; + + if (local->type->is_known && local->type != expr->type) { + onyx_message_add(parser->msgs, + ONYX_MESSAGE_TYPE_ASSIGNMENT_TYPE_MISMATCH, + assignment->token->pos, + local->type->name, expr->type->name); + return 1; + } else if (!local->type->is_known) { + local->type = expr->type; + } + *ret = assignment; + } + return 1; + } - // NOTE: Assignment - case TOKEN_TYPE_SYM_EQUALS: { - parser_next_token(parser); + // NOTE: Assignment + case TOKEN_TYPE_SYM_EQUALS: + { + parser_next_token(parser); - OnyxAstNode* lval = lookup_identifier(parser, symbol); + OnyxAstNode* lval = lookup_identifier(parser, symbol); - if (lval != NULL && lval->flags & ONYX_AST_FLAG_LVAL && (lval->flags & ONYX_AST_FLAG_CONST) == 0) { - OnyxAstNode* rval = parse_expression(parser); - OnyxAstNode* assignment = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_ASSIGNMENT); - assignment->right = rval; - assignment->left = lval; - *ret = assignment; - return 1; - } - - onyx_token_null_toggle(*symbol); - if (lval == NULL) { - onyx_message_add(parser->msgs, - ONYX_MESSAGE_TYPE_UNKNOWN_SYMBOL, - symbol->pos, symbol->token); - } - - else if ((lval->flags & ONYX_AST_FLAG_LVAL) == 0) { - onyx_message_add(parser->msgs, - ONYX_MESSAGE_TYPE_NOT_LVAL, - symbol->pos, symbol->token); - } + if (lval != NULL && lval->flags & ONYX_AST_FLAG_LVAL && (lval->flags & ONYX_AST_FLAG_CONST) == 0) { + OnyxAstNode* rval = parse_expression(parser); + OnyxAstNode* assignment = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_ASSIGNMENT); + assignment->right = rval; + assignment->left = lval; + *ret = assignment; + return 1; + } - else if (lval->flags & ONYX_AST_FLAG_CONST) { - onyx_message_add(parser->msgs, - ONYX_MESSAGE_TYPE_ASSIGN_CONST, - symbol->pos, symbol->token); - } - onyx_token_null_toggle(*symbol); + onyx_token_null_toggle(*symbol); + if (lval == NULL) { + onyx_message_add(parser->msgs, + ONYX_MESSAGE_TYPE_UNKNOWN_SYMBOL, + symbol->pos, symbol->token); + } + + else if ((lval->flags & ONYX_AST_FLAG_LVAL) == 0) { + onyx_message_add(parser->msgs, + ONYX_MESSAGE_TYPE_NOT_LVAL, + symbol->pos, symbol->token); + } + + else if (lval->flags & ONYX_AST_FLAG_CONST) { + onyx_message_add(parser->msgs, + ONYX_MESSAGE_TYPE_ASSIGN_CONST, + symbol->pos, symbol->token); + } + onyx_token_null_toggle(*symbol); - find_token(parser, TOKEN_TYPE_SYM_SEMICOLON); - return 1; - } + find_token(parser, TOKEN_TYPE_SYM_SEMICOLON); + return 1; + } - default: - parser_prev_token(parser); + default: + parser_prev_token(parser); } return 0; @@ -393,31 +436,32 @@ static OnyxAstNode* parse_return_statement(OnyxParser* parser) { static OnyxAstNode* parse_statement(OnyxParser* parser) { switch (parser->curr_token->type) { - case TOKEN_TYPE_KEYWORD_RETURN: - return parse_return_statement(parser); + case TOKEN_TYPE_KEYWORD_RETURN: + return parse_return_statement(parser); - case TOKEN_TYPE_OPEN_BRACE: - return (OnyxAstNode *) parse_block(parser, 0); + case TOKEN_TYPE_OPEN_BRACE: + return (OnyxAstNode *) parse_block(parser, 0); - case TOKEN_TYPE_SYMBOL: { - OnyxAstNode* ret = NULL; - if (parse_symbol_statement(parser, &ret)) return ret; - // fallthrough - } + case TOKEN_TYPE_SYMBOL: + { + OnyxAstNode* ret = NULL; + if (parse_symbol_statement(parser, &ret)) return ret; + // fallthrough + } - case TOKEN_TYPE_OPEN_PAREN: - case TOKEN_TYPE_SYM_PLUS: - case TOKEN_TYPE_SYM_MINUS: - case TOKEN_TYPE_SYM_BANG: - case TOKEN_TYPE_LITERAL_NUMERIC: - case TOKEN_TYPE_LITERAL_STRING: - return parse_expression(parser); + case TOKEN_TYPE_OPEN_PAREN: + case TOKEN_TYPE_SYM_PLUS: + case TOKEN_TYPE_SYM_MINUS: + case TOKEN_TYPE_SYM_BANG: + case TOKEN_TYPE_LITERAL_NUMERIC: + case TOKEN_TYPE_LITERAL_STRING: + return parse_expression(parser); - case TOKEN_TYPE_KEYWORD_IF: - return parse_if_stmt(parser); + case TOKEN_TYPE_KEYWORD_IF: + return parse_if_stmt(parser); - default: - return NULL; + default: + return NULL; } } @@ -558,65 +602,68 @@ static OnyxAstNodeFuncDef* parse_function_definition(OnyxParser* parser) { static OnyxAstNode* parse_top_level_statement(OnyxParser* parser) { switch (parser->curr_token->type) { - case TOKEN_TYPE_KEYWORD_USE: - assert(0); - break; - - case TOKEN_TYPE_KEYWORD_EXPORT: { - expect(parser, TOKEN_TYPE_KEYWORD_EXPORT); - if (parser->curr_token->type != TOKEN_TYPE_SYMBOL) { - onyx_message_add(parser->msgs, - ONYX_MESSAGE_TYPE_EXPECTED_TOKEN, - parser->curr_token->pos, - onyx_get_token_type_name(TOKEN_TYPE_SYMBOL), - onyx_get_token_type_name(parser->curr_token->type)); + case TOKEN_TYPE_KEYWORD_USE: + assert(0); break; - } - OnyxAstNode* top_level_decl = parse_top_level_statement(parser); - top_level_decl->flags |= ONYX_AST_FLAG_EXPORTED; - return top_level_decl; - } break; - - case TOKEN_TYPE_SYMBOL: { - OnyxToken* symbol = parser->curr_token; - parser_next_token(parser); - - expect(parser, TOKEN_TYPE_SYM_COLON); - expect(parser, TOKEN_TYPE_SYM_COLON); - - if (parser->curr_token->type == TOKEN_TYPE_KEYWORD_PROC) { - OnyxAstNodeFuncDef* func_def = parse_function_definition(parser); - func_def->token = symbol; - - onyx_token_null_toggle(*symbol); - - if (!bh_hash_has(OnyxAstNode *, parser->identifiers, symbol->token)) { - bh_hash_put(OnyxAstNode *, parser->identifiers, symbol->token, (OnyxAstNode *) func_def); - } else { - onyx_message_add(parser->msgs, - ONYX_MESSAGE_TYPE_FUNCTION_REDEFINITION, - symbol->pos, - symbol->token); - - // NOTE: I really wish C had defer... - onyx_token_null_toggle(*symbol); - return NULL; + case TOKEN_TYPE_KEYWORD_EXPORT: + { + expect(parser, TOKEN_TYPE_KEYWORD_EXPORT); + if (parser->curr_token->type != TOKEN_TYPE_SYMBOL) { + onyx_message_add(parser->msgs, + ONYX_MESSAGE_TYPE_EXPECTED_TOKEN, + parser->curr_token->pos, + onyx_get_token_type_name(TOKEN_TYPE_SYMBOL), + onyx_get_token_type_name(parser->curr_token->type)); + break; + } + + OnyxAstNode* top_level_decl = parse_top_level_statement(parser); + top_level_decl->flags |= ONYX_AST_FLAG_EXPORTED; + return top_level_decl; } - onyx_token_null_toggle(*symbol); - return (OnyxAstNode *) func_def; - - } else if (parser->curr_token->type == TOKEN_TYPE_KEYWORD_STRUCT) { - // Handle struct case - assert(0); - } else { - onyx_message_add(parser->msgs, - ONYX_MESSAGE_TYPE_UNEXPECTED_TOKEN, - parser->curr_token->pos, - onyx_get_token_type_name(parser->curr_token->type)); - } - } break; + case TOKEN_TYPE_SYMBOL: + { + OnyxToken* symbol = parser->curr_token; + parser_next_token(parser); + + expect(parser, TOKEN_TYPE_SYM_COLON); + expect(parser, TOKEN_TYPE_SYM_COLON); + + if (parser->curr_token->type == TOKEN_TYPE_KEYWORD_PROC) { + OnyxAstNodeFuncDef* func_def = parse_function_definition(parser); + func_def->token = symbol; + + onyx_token_null_toggle(*symbol); + + if (!bh_hash_has(OnyxAstNode *, parser->identifiers, symbol->token)) { + bh_hash_put(OnyxAstNode *, parser->identifiers, symbol->token, (OnyxAstNode *) func_def); + } else { + onyx_message_add(parser->msgs, + ONYX_MESSAGE_TYPE_FUNCTION_REDEFINITION, + symbol->pos, + symbol->token); + + // NOTE: I really wish C had defer... + onyx_token_null_toggle(*symbol); + return NULL; + } + + onyx_token_null_toggle(*symbol); + return (OnyxAstNode *) func_def; + + } else if (parser->curr_token->type == TOKEN_TYPE_KEYWORD_STRUCT) { + // Handle struct case + assert(0); + } else { + onyx_message_add(parser->msgs, + ONYX_MESSAGE_TYPE_UNEXPECTED_TOKEN, + parser->curr_token->pos, + onyx_get_token_type_name(parser->curr_token->type)); + break; + } + } } parser_next_token(parser); diff --git a/onyxparser.h b/onyxparser.h index dadf29f9..b2496f69 100644 --- a/onyxparser.h +++ b/onyxparser.h @@ -100,6 +100,7 @@ typedef struct OnyxTypeInfo { u32 is_unsigned : 1; u32 is_float : 1; u32 is_bool : 1; + u32 is_known : 1; } OnyxTypeInfo; extern OnyxTypeInfo builtin_types[]; diff --git a/onyxutils.c b/onyxutils.c index 2a07f2a9..e40e0cb1 100644 --- a/onyxutils.c +++ b/onyxutils.c @@ -97,6 +97,15 @@ void onyx_ast_print(OnyxAstNode* node, i32 indent) { break; } + case ONYX_AST_NODE_KIND_CAST: { + bh_printf("to %s ", node->type->name); + onyx_ast_print(node->left, indent + 1); + if (node->next) { + onyx_ast_print(node->next, indent); + } + break; + } + default: { onyx_ast_print(node->left, indent + 1); onyx_ast_print(node->right, indent + 1); diff --git a/progs/minimal.onyx b/progs/minimal.onyx index 19173392..23ea5bbe 100644 --- a/progs/minimal.onyx +++ b/progs/minimal.onyx @@ -1,36 +1,16 @@ -/* This is a comment */ - -/* Currently the "foreign" keyword doesn't do anything */ -foreign "console" log :: proc (a i32, b i32) -> i32 --- export add :: proc (a i32, b i32) -> i32 { - /* More comments */ return a + b; } -export mul :: proc (a i32, b i32) -> i32 { +export mul :: proc (a i32, b i32) -> i64 { /* Typechecked */ - c: const i32 = a - b; + c: const i64 = ((a as i64) - (b as i64)); /* Don't love this syntax, but it's easy to parse so whatever Inferred type, but constant */ /* a and b are both i32, so i32 + i32 is i32 so d is i32 */ d: const = a + b; - return c * d; -} - -very_long_function_name :: proc () -> void { - a:i32; - b:i32; - c:i32; - d:i32; - e:i32; - f:i32; - g:i32; - h:i32; - i:i32 = 0 + 2; - j:i32; - k:i32; - l:i32; + return ((c as i32) * d) as i64; } diff --git a/progs/mvp.onyx b/progs/mvp.onyx index 1cfbedc2..cb32d79b 100644 --- a/progs/mvp.onyx +++ b/progs/mvp.onyx @@ -24,4 +24,4 @@ export max :: proc (a i32, b i32) -> i32 { export main :: proc () -> void { console.log(add(2, 3)); console.log(max(5, 10)); -}; \ No newline at end of file +}; -- 2.25.1