Code cleanup for numeric literals
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Mon, 10 Aug 2020 02:45:14 +0000 (21:45 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Mon, 10 Aug 2020 02:45:14 +0000 (21:45 -0500)
include/onyxastnodes.h
include/onyxlex.h
onyx
src/onyxchecker.c
src/onyxlex.c
src/onyxparser.c
src/onyxutils.c

index 7844ecff6e838aa016fd5c59462ecbbc9fe615b9..ab6f1c96c08e9528bad6e6101793e9ad8aa5ab14 100644 (file)
@@ -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) {
index d7c4f468a70ad653a5c783d9819061a5798e3ea7..e1c23c111f286480937d10c1875dd30a4687c815 100644 (file)
@@ -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 ec5938bda814e7c885cc0be7a5d61d3c3786c68c..d9a0568bce2ba3eede60ebdac58bdc563d52ea72 100755 (executable)
Binary files a/onyx and b/onyx differ
index 73c262605473ec655b5cdeb1335274c71d384f29..6307ed75f438b34e224e9f241efe060920dc857e 100644 (file)
@@ -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,
index f5462d56a4aadfcf880a5448f4fa8b3c3cefcc19..3f7fbe78122ac6f278e7315cdfcfdd67c39b9c3b 100644 (file)
@@ -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);
index 5b0c3ffcddb027359bf952ca52ba22fb37153e5c..67749e1d6283b87814b3b6234caa6cc9ce85f84a 100644 (file)
@@ -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;
 }
 
 // ( <expr> )
@@ -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, ';');
index a8a4ec361b41bbd5c43a6af1692372a0f6c25d36..4a1c20feb9deee517dfd3c2bb92894b22caad6c3 100644 (file)
@@ -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