Better parse tree printer and some type checking
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Tue, 2 Jun 2020 01:05:14 +0000 (20:05 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Tue, 2 Jun 2020 01:05:14 +0000 (20:05 -0500)
13 files changed:
docs/plan
docs/thoughts
onyx
onyx.c
onyxlex.c
onyxlex.h
onyxmsgs.c
onyxmsgs.h
onyxparser.c
onyxparser.h
onyxutils.c
progs/minimal.onyx
progs/mvp.onyx

index 0d11788da66a2f1e20653d262f3b92173f05d1c6..d78b4992e601f3b3dd9da95167beb47403df5398 100644 (file)
--- 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
index 86a7ba5de4de424bd3026763e2a03a800087c09f..24dfa3cc22cbb3004f074c18dba7009f3af43a2b 100644 (file)
@@ -22,3 +22,5 @@ Type checking at parse time:
        foo(5) would have a left node of SYMBOL:foo\r
        This will be resolved in a later stage between the parsing and semantic pass\r
        Type checking and resolving would have to occur afterwards\r
+\r
+Creating an IR:\r
diff --git a/onyx b/onyx
index 0786469358d3d498ecc20b1d390fc2338fbb24ae..37a1774ae70719ac06b4010caf3f5d73c76dd987 100755 (executable)
Binary files a/onyx and b/onyx differ
diff --git a/onyx.c b/onyx.c
index 27eeec059c56a1ba34163c0c6d20e43d837e7dd9..ceb097038cb90b4578ab0ad9fb986c3889557977 100644 (file)
--- 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;
 }
index a922f7c819b8128b30cb3c31e4f428dcbc60cdd0..d76c93f32b3bace691d751c92ca51e3a5582075e 100644 (file)
--- 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);
index a64b0ec699134fab9eacc717cbbebb8426568c2a..b1b5eb064bdd41292f73c0fd596e07746ceecf52 100644 (file)
--- 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,
index 6b92357d4643ce0f25a5c5794641bf49bf23dfc8..a2e555120991a29fdb8cc983cfa09ffcc00b802d 100644 (file)
@@ -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, ...) {
index fc102233a3adb9f160764b43e255274865d66f41..6c6a19e8afef966e7d5398fa1b686aa3d441a51b 100644 (file)
@@ -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;
index 77bc0c47b83b2db099ef7c6ff2a8327b97f11f81..103d8e3c095338eb05c0aeebaf3176a712076e2c 100644 (file)
@@ -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);
index dadf29f973f23f70fd5e31b7416d3f843fffa8d1..b2496f6974f18d244beb43eaba8f7b464937f628 100644 (file)
@@ -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[];
index 2a07f2a9b65a53f4ce4d43648596047ad965d0e8..e40e0cb12a7b6532abb12539f22b7d4880a7ae0f 100644 (file)
@@ -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);
index 19173392705698e4bb56eca34ce31d7df385cc11..23ea5bbe98e71c2b81d8429e4b2d8e9e04c87998 100644 (file)
@@ -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;
 }
index 1cfbedc218c65e281472a72432f051a5fe08bf1e..cb32d79b2b31d78754ffdd560b8de79f6716532a 100644 (file)
@@ -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
+};