From: Brendan Hansen Date: Mon, 10 Aug 2020 02:45:14 +0000 (-0500) Subject: Code cleanup for numeric literals X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=5e99afecd8673bb7b7d75161fd6a001300a32b58;p=onyx.git Code cleanup for numeric literals --- diff --git a/include/onyxastnodes.h b/include/onyxastnodes.h index 7844ecff..ab6f1c96 100644 --- a/include/onyxastnodes.h +++ b/include/onyxastnodes.h @@ -492,6 +492,8 @@ typedef struct BuiltinSymbol { 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) { diff --git a/include/onyxlex.h b/include/onyxlex.h index d7c4f468..e1c23c11 100644 --- a/include/onyxlex.h +++ b/include/onyxlex.h @@ -58,7 +58,8 @@ typedef enum TokenType { 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, diff --git a/onyx b/onyx index ec5938bd..d9a0568b 100755 Binary files a/onyx and b/onyx differ diff --git a/src/onyxchecker.c b/src/onyxchecker.c index 73c26260..6307ed75 100644 --- a/src/onyxchecker.c +++ b/src/onyxchecker.c @@ -113,6 +113,13 @@ CHECK(for, AstFor* fornode) { 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, diff --git a/src/onyxlex.c b/src/onyxlex.c index f5462d56..3f7fbe78 100644 --- a/src/onyxlex.c +++ b/src/onyxlex.c @@ -56,7 +56,8 @@ static const char* token_type_names[] = { "TOKEN_TYPE_SYMBOL", "TOKEN_TYPE_LITERAL_STRING", - "TOKEN_TYPE_LITERAL_NUMERIC", + "TOKEN_TYPE_LITERAL_INTEGER", + "TOKEN_TYPE_LITERAL_FLOAT", "true", "false", @@ -243,7 +244,7 @@ OnyxToken* onyx_get_token(OnyxTokenizer* tokenizer) { INCREMENT_CURR_TOKEN(tokenizer); } - tk.type = Token_Type_Literal_Numeric; + tk.type = Token_Type_Literal_Integer; tk.length = len; INCREMENT_CURR_TOKEN(tokenizer); @@ -251,19 +252,36 @@ OnyxToken* onyx_get_token(OnyxTokenizer* 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); diff --git a/src/onyxparser.c b/src/onyxparser.c index 5b0c3ffc..67749e1d 100644 --- a/src/onyxparser.c +++ b/src/onyxparser.c @@ -14,7 +14,8 @@ static void unconsume_token(OnyxParser* parser); 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); @@ -95,40 +96,49 @@ static void add_node_to_process(OnyxParser* parser, AstNode* node) { -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; } // ( ) @@ -241,8 +251,12 @@ static AstTyped* parse_factor(OnyxParser* parser) { 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: { @@ -731,7 +745,8 @@ static AstNode* parse_statement(OnyxParser* parser) { 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; @@ -1252,7 +1267,7 @@ static AstEnumType* parse_enum_declaration(OnyxParser* parser) { consume_token(parser); expect_token(parser, ':'); - evalue->value = parse_numeric_literal(parser); + evalue->value = parse_int_literal(parser); } expect_token(parser, ';'); diff --git a/src/onyxutils.c b/src/onyxutils.c index a8a4ec36..4a1c20fe 100644 --- a/src/onyxutils.c +++ b/src/onyxutils.c @@ -134,7 +134,6 @@ b32 symbol_introduce(Scope* scope, OnyxToken* tkn, AstNode* symbol) { } 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; @@ -181,191 +180,19 @@ AstNode* symbol_resolve(Scope* start_scope, OnyxToken* tkn) { } -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