extern const BuiltinSymbol builtin_symbols[];
+// NOTE: Useful not inlined functions
+void promote_numlit_to_larger(AstNumLit* num);
// NOTE: Useful inlined functions
static inline b32 is_lval(AstNode* node) {
Token_Type_Symbol,
Token_Type_Literal_String,
- Token_Type_Literal_Numeric,
+ Token_Type_Literal_Integer,
+ Token_Type_Literal_Float,
Token_Type_Literal_True,
Token_Type_Literal_False,
return 1;
}
+ // NOTE: Auto promote implicit step to the type of start
+ if (fornode->step->kind == Ast_Kind_NumLit) {
+ fornode->step->type_node = fornode->start->type_node;
+ fornode->step->type = fornode->start->type;
+ promote_numlit_to_larger((AstNumLit *) fornode->step);
+ }
+
if (!types_are_compatible(fornode->end->type, fornode->start->type)) {
onyx_message_add(Msg_Type_Literal,
fornode->end->token->pos,
"TOKEN_TYPE_SYMBOL",
"TOKEN_TYPE_LITERAL_STRING",
- "TOKEN_TYPE_LITERAL_NUMERIC",
+ "TOKEN_TYPE_LITERAL_INTEGER",
+ "TOKEN_TYPE_LITERAL_FLOAT",
"true",
"false",
INCREMENT_CURR_TOKEN(tokenizer);
}
- tk.type = Token_Type_Literal_Numeric;
+ tk.type = Token_Type_Literal_Integer;
tk.length = len;
INCREMENT_CURR_TOKEN(tokenizer);
}
// Number literal
- if (char_is_num(*tokenizer->curr)) {
+ if (char_is_num(*tokenizer->curr)
+ || (*(tokenizer->curr) == '.' && char_is_num(*(tokenizer->curr + 1)))) {
+ tk.type = Token_Type_Literal_Integer;
+
+ b32 hit_decimal = 0;
+ if (*tokenizer->curr == '.') hit_decimal = 1;
+
u32 len = 1;
- while (char_is_num(*(tokenizer->curr + 1)) || *(tokenizer->curr + 1) == '.') {
+ while (char_is_num(*(tokenizer->curr + 1)) || (!hit_decimal && *(tokenizer->curr + 1) == '.')) {
len++;
INCREMENT_CURR_TOKEN(tokenizer);
+
+ if (*tokenizer->curr == '.') hit_decimal = 1;
}
- if (*(tokenizer->curr + 1) == 'f') {
+ if (!hit_decimal && *(tokenizer->curr + 1) == 'l') {
+ tk.type = Token_Type_Literal_Integer;
+
len++;
INCREMENT_CURR_TOKEN(tokenizer);
}
+ else if (*(tokenizer->curr + 1) == 'f') {
+ tk.type = Token_Type_Literal_Float;
+
+ len++;
+ INCREMENT_CURR_TOKEN(tokenizer);
+ }
+
+ if (hit_decimal) tk.type = Token_Type_Literal_Float;
- tk.type = Token_Type_Literal_Numeric;
tk.length = len;
INCREMENT_CURR_TOKEN(tokenizer);
static b32 is_terminating_token(TokenType token_type);
static OnyxToken* expect_token(OnyxParser* parser, TokenType token_type);
-static AstNumLit* parse_numeric_literal(OnyxParser* parser);
+static AstNumLit* parse_int_literal(OnyxParser* parser);
+static AstNumLit* parse_float_literal(OnyxParser* parser);
static AstTyped* parse_factor(OnyxParser* parser);
static AstTyped* parse_expression(OnyxParser* parser);
static AstIf* parse_if_stmt(OnyxParser* parser);
-static AstNumLit* parse_numeric_literal(OnyxParser* parser) {
- AstNumLit* lit_node = make_node(AstNumLit, Ast_Kind_NumLit);
- lit_node->token = expect_token(parser, Token_Type_Literal_Numeric);
- lit_node->flags |= Ast_Flag_Comptime;
- lit_node->value.l = 0ll;
+static AstNumLit* parse_int_literal(OnyxParser* parser) {
+ AstNumLit* int_node = make_node(AstNumLit, Ast_Kind_NumLit);
+ int_node->token = expect_token(parser, Token_Type_Literal_Integer);
+ int_node->flags |= Ast_Flag_Comptime;
+ int_node->value.l = 0ll;
- AstType* type;
- token_toggle_end(lit_node->token);
- char* tok = lit_node->token->text;
+ AstType* type = (AstType *) &basic_type_i32;
+ token_toggle_end(int_node->token);
- // NOTE: charset_contains() behaves more like string_contains()
- // so I'm using it in this case
- if (charset_contains(tok, '.')) {
- if (tok[lit_node->token->length - 1] == 'f') {
- type = (AstType *) &basic_type_f32;
- lit_node->value.f = strtof(tok, NULL);
- } else {
- type = (AstType *) &basic_type_f64;
- lit_node->value.d = strtod(tok, NULL);
- }
- } else {
- i64 value = strtoll(tok, NULL, 0);
- if (bh_abs(value) < ((u64) 1 << 32)) {
- type = (AstType *) &basic_type_i32;
- } else {
- type = (AstType *) &basic_type_i64;
- }
+ char* first_invalid = NULL;
+ i64 value = strtoll(int_node->token->text, &first_invalid, 0);
+ if (bh_abs(value) > ((u64) 1 << 32) || *first_invalid == 'l') {
+ type = (AstType *) &basic_type_i64;
+ }
- lit_node->value.l = value;
+ int_node->value.l = value;
+ int_node->type_node = type;
+
+ token_toggle_end(int_node->token);
+ return int_node;
+}
+
+static AstNumLit* parse_float_literal(OnyxParser* parser) {
+ AstNumLit* float_node = make_node(AstNumLit, Ast_Kind_NumLit);
+ float_node->token = expect_token(parser, Token_Type_Literal_Float);
+ float_node->flags |= Ast_Flag_Comptime;
+ float_node->value.d = 0.0;
+
+ AstType* type = (AstType *) &basic_type_f64;
+ token_toggle_end(float_node->token);
+
+ if (float_node->token->text[float_node->token->length - 1] == 'f') {
+ type = (AstType *) &basic_type_f32;
+ float_node->value.f = strtof(float_node->token->text, NULL);
+ } else {
+ type = (AstType *) &basic_type_f64;
+ float_node->value.d = strtod(float_node->token->text, NULL);
}
- lit_node->type_node = type;
- token_toggle_end(lit_node->token);
- return lit_node;
+ float_node->type_node = type;
+
+ token_toggle_end(float_node->token);
+ return float_node;
}
// ( <expr> )
break;
}
- case Token_Type_Literal_Numeric:
- retval = (AstTyped *) parse_numeric_literal(parser);
+ case Token_Type_Literal_Integer:
+ retval = (AstTyped *) parse_int_literal(parser);
+ break;
+
+ case Token_Type_Literal_Float:
+ retval = (AstTyped *) parse_float_literal(parser);
break;
case Token_Type_Literal_String: {
case '-':
case '!':
case '*':
- case Token_Type_Literal_Numeric:
+ case Token_Type_Literal_Integer:
+ case Token_Type_Literal_Float:
case Token_Type_Literal_String:
retval = (AstNode *) parse_expression(parser);
break;
consume_token(parser);
expect_token(parser, ':');
- evalue->value = parse_numeric_literal(parser);
+ evalue->value = parse_int_literal(parser);
}
expect_token(parser, ';');
}
b32 symbol_raw_introduce(Scope* scope, char* name, OnyxFilePos pos, AstNode* symbol) {
-
if (bh_table_has(AstNode *, scope->symbols, name)) {
onyx_message_add(Msg_Type_Redeclare_Symbol, pos, name);
return 0;
}
-void onyx_ast_print(AstNode* node, i32 indent) {
- assert(0);
-}
-#if 0
-
-#define print_indent { if (indent > 0) bh_printf("\n"); for (int i = 0; i < indent; i++) bh_printf(" "); }
-
-void onyx_ast_print(AstNode* node, i32 indent) {
- while (node) {
- print_indent;
- bh_printf("(%d) %s ", node->flags, onyx_ast_node_kind_string(node->kind));
-
- switch (node->kind) {
- case AST_NODE_KIND_USE: {
- AstNodeUse* use_node = (AstNodeUse *) node;
- bh_printf("%b", use_node->filename->token, use_node->filename->length);
-
- break;
- }
-
- case AST_NODE_KIND_FUNCTION: {
- if (node->token)
- bh_printf("(%b) ", node->token->token, node->token->length);
- AstNodeFunction* fd = (AstNodeFunction *) node;
-
- print_indent;
- bh_printf("Params ");
- if (fd->params)
- onyx_ast_print((AstNode *) fd->params, 0);
-
- print_indent;
- bh_printf("Returns %s", fd->base.type->name);
-
- print_indent;
- bh_printf("Body");
- if (fd->body)
- onyx_ast_print((AstNode *) fd->body, indent + 1);
-
- break;
- }
-
- case AST_NODE_KIND_PARAM: {
- AstNodeLocal* param = (AstNodeLocal *) node;
- bh_printf("%b %s", param->base.token->token, param->base.token->length, param->base.type->name);
- if (param->base.next && indent == 0) {
- bh_printf(", ");
- onyx_ast_print((AstNode *) param->base.next, 0);
- }
-
- return;
- }
-
- case AST_NODE_KIND_BLOCK: {
- AstNodeBlock* block = (AstNodeBlock *) node;
- if (block->scope) {
- onyx_ast_print((AstNode *) block->scope, indent + 1);
- }
-
- if (block->body) {
- onyx_ast_print((AstNode *) block->body, indent + 1);
- }
-
- break;
- }
-
- case AST_NODE_KIND_SCOPE: {
- AstNodeScope* scope = (AstNodeScope *) scope;
- if (scope->last_local) {
- onyx_ast_print((AstNode *) scope->last_local, 0);
- }
-
- break;
- }
-
- case AST_NODE_KIND_LOCAL: {
- AstNodeLocal* local = (AstNodeLocal *) node;
- bh_printf("%b %s", local->base.token->token, local->base.token->length, local->base.type->name);
- if (local->prev_local && indent == 0) {
- bh_printf(", ");
- onyx_ast_print((AstNode *) local->prev_local, 0);
- }
- break;
- }
-
- case AST_NODE_KIND_GLOBAL: {
- AstNodeGlobal* global = (AstNodeGlobal *) node;
- bh_printf("%b %s", global->base.token->token, global->base.token->length, global->base.type->name);
- if (global->initial_value) {
- onyx_ast_print((AstNode *) global->initial_value, indent + 1);
- }
-
- if (node->next) {
- onyx_ast_print(node->next, indent);
- }
- break;
- }
-
- case AST_NODE_KIND_SYMBOL: {
- bh_printf("%b", node->token->token, node->token->length);
- if (node->next) {
- onyx_ast_print(node->next, indent);
- }
- break;
- }
-
- case AST_NODE_KIND_RETURN: {
- AstNodeReturn* ret = (AstNodeReturn *) node;
- if (ret->expr) {
- onyx_ast_print((AstNode *) ret->expr, indent + 1);
- }
-
- break;
- }
-
- case AST_NODE_KIND_LITERAL: {
- AstNodeNumLit* lit = (AstNodeNumLit *) node;
- bh_printf("(%s) %b", lit->base.type->name, lit->base.token->token, lit->base.token->length);
-
- break;
- }
- case AST_NODE_KIND_CALL: {
- AstNodeCall* call = (AstNodeCall *) node;
- if (call->callee) {
- if (call->callee->kind == AST_NODE_KIND_FUNCTION) {
- bh_printf("function: %b", call->callee->token->token, call->callee->token->length);
- } else {
- onyx_ast_print(call->callee, indent + 1);
- }
- }
- onyx_ast_print((AstNode *) call->arguments, indent + 1);
-
- break;
- }
- case AST_NODE_KIND_FOREIGN: {
- AstNodeForeign* foreign = (AstNodeForeign *) node;
- bh_printf("%b:%b",
- foreign->mod_token->token, foreign->mod_token->length,
- foreign->name_token->token, foreign->name_token->length);
- if (foreign->import) {
- onyx_ast_print(foreign->import, indent + 1);
- }
+void promote_numlit_to_larger(AstNumLit* num) {
+ assert(num->type != NULL);
- break;
- }
-
- case AST_NODE_KIND_IF: {
- AstNodeIf* if_node = (AstNodeIf *) node;
- if (if_node->cond) {
- print_indent;
- bh_printf("Condition:");
- onyx_ast_print((AstNode *) if_node->cond, indent + 1);
- }
- if (if_node->true_block.as_if) {
- print_indent;
- bh_printf("True block:");
- onyx_ast_print((AstNode *) if_node->true_block.as_if, indent + 1);
- }
- if (if_node->false_block.as_if) {
- print_indent;
- bh_printf("False block:");
- onyx_ast_print((AstNode *) if_node->false_block.as_if, indent + 1);
- }
-
- break;
- }
-
- case AST_NODE_KIND_BIN_OP: {
- AstNodeBinOp* binop = (AstNodeBinOp *) node;
- bh_printf("%b", binop->base.token->token, binop->base.token->length);
-
- onyx_ast_print((AstNode *) binop->left, indent + 1);
- onyx_ast_print((AstNode *) binop->right, indent + 1);
-
- break;
- }
-
- default:
- break;
- }
-
- node = node->next;
+ if (type_is_integer(num->type) && num->type->Basic.size <= 4) {
+ // NOTE: Int32, Int16, Int8
+ i64 val = (i64) num->value.i;
+ num->value.l = val;
+ } else if (num->type->Basic.size <= 4) {
+ // NOTE: Float32
+ f64 val = (f64) num->value.f;
+ num->value.d = val;
}
}
-
-#endif