#include "onyxlex.h"
+#include "onyxmsgs.h"
#include "onyxparser.h"
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
};
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;
}
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;
}
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;
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;
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;
}
}
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);