added ranges; will replace for loop and slice syntax soon
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Fri, 4 Sep 2020 03:18:40 +0000 (22:18 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Fri, 4 Sep 2020 03:18:40 +0000 (22:18 -0500)
13 files changed:
core/builtin.onyx
docs/plan
include/onyxastnodes.h
include/onyxlex.h
onyx
progs/poly_test.onyx
src/onyxbuiltins.c
src/onyxchecker.c
src/onyxclone.c
src/onyxlex.c
src/onyxparser.c
src/onyxsymres.c
src/onyxutils.c

index f8b1d2dc2bf5ce6b14dff40079fb3790b735092d..b07fe7d6f7592ed7b838cebdc713a35f8d7cc662 100644 (file)
@@ -5,6 +5,12 @@ cstring :: #type ^u8;
 
 Buffer :: #type []void;
 
+range :: struct {
+    low  : i32;
+    high : i32;
+    step : i32 = 1;
+}
+
 null :: cast(rawptr) 0;
 
 // ---------------------------------
index ba6b114e0dca38813fd8660da0c4fdd7a04ba166..610ee4a6172828312ef6a2a71f54a5c9eae005b3 100644 (file)
--- a/docs/plan
+++ b/docs/plan
@@ -237,6 +237,9 @@ HOW:
             - Removes the argument from the list and replaces the function with the
                 baked function
 
+        [ ] Add SIMD intrinsics
+            - This also requires adding the v128 SIMD type
+
         [ ] Put type info in data section so it is runtime accessible
             - type name
             - size
index 34537780b9ba47f827efe402200f1c1ac6e570ba..74747d8450d2e5304f1f539224a4fa7581bf08a4 100644 (file)
@@ -125,7 +125,8 @@ typedef enum AstKind {
     Ast_Kind_Array_Access,
     Ast_Kind_Slice,
     Ast_Kind_Field_Access,
-    Ast_Kind_Ufc,
+    Ast_Kind_Pipe,
+    Ast_Kind_Range,
     Ast_Kind_Size_Of,
     Ast_Kind_Align_Of,
     Ast_Kind_File_Contents,
@@ -225,6 +226,7 @@ typedef enum BinaryOp {
     Binary_Op_Assign_End      = 32,
 
     Binary_Op_Pipe            = 33,
+    Binary_Op_Range           = 34,
 } BinaryOp;
 
 typedef enum OnyxIntrinsic {
@@ -581,6 +583,7 @@ extern AstNode   builtin_package_node;
 extern AstNumLit builtin_heap_start;
 extern AstGlobal builtin_stack_top;
 extern AstType  *builtin_string_type;
+extern AstType  *builtin_range_type;
 
 typedef struct BuiltinSymbol {
     char*    package;
index 21d4b3a0b680fb4d6adf7bed2f47684f58afc3a5..58cd343efa41b099669fd603d4e06223f5405111 100644 (file)
@@ -60,6 +60,8 @@ typedef enum TokenType {
     Token_Type_Shr_Equal,
     Token_Type_Sar_Equal,
 
+    Token_Type_Dot_Dot,
+
     Token_Type_Symbol,
     Token_Type_Literal_String,
     Token_Type_Literal_Integer,
diff --git a/onyx b/onyx
index bfe7d9cd83347f794ed6ceb65a69c35f3a4e880d..4d064dbdef8ae331e5dc198c57a8e2dd5a01d0a1 100755 (executable)
Binary files a/onyx and b/onyx differ
index b4a68d62ef84bd6565caef43001c058f7bb5cd33..80de2d0d42ab90efdd9654228169ba0a49e15160 100644 (file)
@@ -61,14 +61,31 @@ soa_deinit :: proc (s: ^SOA) {
     array_free(^s.b);
 }
 
+get_range :: proc (arr: ^[..] $T) -> range {
+    return 0 .. arr.count;
+}
+
+print_range :: proc (r: range) #add_overload print {
+    print(r.low);
+    print(" to ");
+    print(r.high);
+    print(" by ");
+    print(r.step);
+    print("\n");
+}
+
 main :: proc (args: [] cstring) {
     res := compose(5, proc (x: i32) -> i32 do return x * 3;,
                       proc (x: i32) -> i32 do return x + 5;);
     print(res);
+    print("\n");
 
     s : SOA;
     soa_init(^s);
-    defer soa_deinit(^s);
+    defer {
+        print("Clearing SOA...\n");
+        soa_deinit(^s);
+    }
 
     print_arr_details(^s.a);
     print_arr_details(^s.b);
@@ -78,6 +95,9 @@ main :: proc (args: [] cstring) {
         array_push(^s.b, 3l * cast(i64) i);
     }
 
+    r := ^s.a |> get_range();
+    print(r);
+
     array_sort(^s.a, cmp_dec);
     array_sort(^s.b, cmp_asc);
 
index b1f4e487def45bf5a8f5a95e15d83d2a66e724c3..4085e062a5a7c84be89b91a230d24ba30f449ea7 100644 (file)
@@ -24,7 +24,9 @@ static OnyxToken builtin_heap_start_token = { Token_Type_Symbol, 12, "__heap_sta
 static OnyxToken builtin_stack_top_token  = { Token_Type_Symbol, 11, "__stack_top ",  { 0 } };
 AstNumLit builtin_heap_start  = { Ast_Kind_NumLit, Ast_Flag_Const, &builtin_heap_start_token, NULL, (AstType *) &basic_type_rawptr, NULL, 0 };
 AstGlobal builtin_stack_top   = { Ast_Kind_Global, Ast_Flag_Const | Ast_Flag_Global_Stack_Top,  &builtin_stack_top_token,  NULL, (AstType *) &basic_type_rawptr, NULL };
+
 AstType  *builtin_string_type;
+AstType  *builtin_range_type;
 
 const BuiltinSymbol builtin_symbols[] = {
     { NULL, "void",       (AstNode *) &basic_type_void },
@@ -69,9 +71,16 @@ void initialize_builtins(bh_allocator a, ProgramInfo* prog) {
     }
 
     Package* p = program_info_package_lookup_or_create(prog, "builtin", prog->global_scope, a);
+
     builtin_string_type = (AstType *) symbol_raw_resolve(p->scope, "string");
     if (builtin_string_type == NULL) {
         onyx_report_error((OnyxFilePos) { 0 }, "'string' struct not found in builtin package.");
         return;
     }
-}
\ No newline at end of file
+
+    builtin_range_type = (AstType *) symbol_raw_resolve(p->scope, "range");
+    if (builtin_range_type == NULL) {
+        onyx_report_error((OnyxFilePos) { 0 }, "'range' struct not found in builtin package.");
+        return;
+    }
+}
index 0d0dfe16a4cf68f09c9fcc87199e4d78b191b7bc..8204f0d6fea7f6a888d9d8fc8d2ccf9604f11875 100644 (file)
@@ -23,6 +23,7 @@ CHECK(dereference, AstDereference* deref);
 CHECK(array_access, AstArrayAccess* expr);
 CHECK(slice, AstSlice* sl);
 CHECK(field_access, AstFieldAccess** pfield);
+CHECK(range_literal, AstBinaryOp** range);
 CHECK(size_of, AstSizeOf* so);
 CHECK(align_of, AstAlignOf* ao);
 CHECK(global, AstGlobal* global);
@@ -331,7 +332,7 @@ b32 check_call(AstCall* call) {
                 actual->type = actual->value->type;
                 actual->value->flags |= Ast_Flag_Function_Used;
             }
-                    
+
             actual = (AstArgument *) actual->next;
             arg_idx++;
         }
@@ -587,7 +588,7 @@ b32 check_binaryop_compare(AstBinaryOp** pbinop) {
         // NOTE: Not a binary op
         *pbinop = (AstBinaryOp *) ast_reduce(semstate.node_allocator, (AstTyped *) binop);
     }
-    
+
     return 0;
 }
 
@@ -946,6 +947,52 @@ b32 check_field_access(AstFieldAccess** pfield) {
     return 0;
 }
 
+b32 check_range_literal(AstBinaryOp** prange) {
+    AstBinaryOp* range = *prange;
+    if (check_expression(&range->left))  return 1;
+    if (check_expression(&range->right)) return 1;
+
+    Type* expected_range_type = type_build_from_ast(semstate.node_allocator, builtin_range_type);
+    StructMember smem;
+
+    type_lookup_member(expected_range_type, "low", &smem);
+    if (!types_are_compatible(range->left->type, smem.type)) {
+        onyx_report_error(range->token->pos, "Expected left side of range to be a 32-bit integer.");
+        return 1;
+    }
+
+    type_lookup_member(expected_range_type, "high", &smem);
+    if (!types_are_compatible(range->right->type, smem.type)) {
+        onyx_report_error(range->token->pos, "Expected right side of range to be a 32-bit integer.");
+        return 1;
+    }
+
+    // NOTE: Implicitly converting this to a struct literal because that makes the
+    // WASM generation easier and more robust for return a range from a procedure
+    // and the like. This could be improved as struct literals are made more throughout
+    // the code base.
+    //                                                          - brendanfh, 2020/09/03
+    AstStructLiteral* rsl = onyx_ast_node_new(semstate.node_allocator, sizeof(AstStructLiteral), Ast_Kind_Struct_Literal);
+    bh_arr_new(global_heap_allocator, rsl->values, 3);
+
+    bh_arr_push(rsl->values, range->left);
+    bh_arr_push(rsl->values, range->right);
+
+    // HACK: This relies on the third member of the 'range' struct to exist, be the step,
+    // and have an intial_value.
+    AstStructMember* step_member = ((AstStructType *) builtin_range_type)->members[2];
+    if (check_expression(&step_member->initial_value)) return 1;
+    bh_arr_push(rsl->values, step_member->initial_value);
+
+    rsl->token = range->token;
+    rsl->type = expected_range_type;
+
+    // NOTE: Not a binary op
+    *prange = (AstBinaryOp *) rsl;
+
+    return 0;
+}
+
 b32 check_size_of(AstSizeOf* so) {
     so->size = type_size_of(type_build_from_ast(semstate.allocator, so->so_type));
 
@@ -998,6 +1045,7 @@ b32 check_expression(AstTyped** pexpr) {
         case Ast_Kind_Field_Access: retval = check_field_access((AstFieldAccess **) pexpr); break;
         case Ast_Kind_Size_Of:      retval = check_size_of((AstSizeOf *) expr); break;
         case Ast_Kind_Align_Of:     retval = check_align_of((AstAlignOf *) expr); break;
+        case Ast_Kind_Range:        retval = check_range_literal((AstBinaryOp **) pexpr); break;
 
         case Ast_Kind_Global:
             if (expr->type == NULL) {
@@ -1252,7 +1300,7 @@ b32 check_memres(AstMemRes* memres) {
             return 1;
         }
     }
-    
+
     return 0;
 }
 
index 1f5049afc5f9b6169af6b3a4101c03d94119dff9..c0c32c93ecd6387880a799f201840a43374d128e 100644 (file)
@@ -71,7 +71,8 @@ static inline i32 ast_kind_to_size(AstNode* node) {
         case Ast_Kind_Array_Access: return sizeof(AstArrayAccess);
         case Ast_Kind_Slice: return sizeof(AstSlice);
         case Ast_Kind_Field_Access: return sizeof(AstFieldAccess);
-        case Ast_Kind_Ufc: return sizeof(AstBinaryOp);
+        case Ast_Kind_Pipe: return sizeof(AstBinaryOp);
+        case Ast_Kind_Range: return sizeof(AstBinaryOp);
         case Ast_Kind_Size_Of: return sizeof(AstSizeOf);
         case Ast_Kind_Align_Of: return sizeof(AstAlignOf);
         case Ast_Kind_File_Contents: return sizeof(AstFileContents);
@@ -223,7 +224,7 @@ AstNode* ast_clone(bh_allocator a, void* n) {
                        if (((AstIfWhile *) nn)->assignment)
                                ((AstIfWhile *) nn)->assignment->left = (AstTyped *) ((AstIfWhile *) nn)->local;
 
-                       ((AstIfWhile *) nn)->cond = (AstTyped *) ast_clone(a, ((AstIfWhile *) node)->cond);                     
+                       ((AstIfWhile *) nn)->cond = (AstTyped *) ast_clone(a, ((AstIfWhile *) node)->cond);
                        ((AstIfWhile *) nn)->true_stmt = (AstBlock *) ast_clone(a, ((AstIfWhile *) node)->true_stmt);
                        ((AstIfWhile *) nn)->false_stmt = (AstBlock *) ast_clone(a, ((AstIfWhile *) node)->false_stmt);
                        break;
@@ -239,7 +240,7 @@ AstNode* ast_clone(bh_allocator a, void* n) {
                        dw->expr = (AstTyped *) ast_clone(a, sw->expr);
 
                        dw->default_case = (AstBlock *) ast_clone(a, sw->default_case);
-                       
+
                        dw->cases = NULL;
                        bh_arr_new(global_heap_allocator, dw->cases, bh_arr_length(sw->cases));
 
@@ -314,4 +315,4 @@ AstNode* ast_clone(bh_allocator a, void* n) {
        }
 
        return nn;
-}
\ No newline at end of file
+}
index 4f6945db5de36d9c87a788537f41f9a4a017aa01..d5a0a0fe3c978db274a6494d29ebbb9e61124f58 100644 (file)
@@ -57,6 +57,7 @@ static const char* token_type_names[] = {
     "<<=",
     ">>=",
     ">>>=",
+    "..",
 
     "TOKEN_TYPE_SYMBOL",
     "TOKEN_TYPE_LITERAL_STRING",
@@ -366,13 +367,14 @@ whitespace_skipped:
         break;
 
     default:
-        LITERAL_TOKEN("^=",          0, Token_Type_Xor_Equal);
         LITERAL_TOKEN("==",          0, Token_Type_Equal_Equal);
         LITERAL_TOKEN("!=",          0, Token_Type_Not_Equal);
         LITERAL_TOKEN("+=",          0, Token_Type_Plus_Equal);
         LITERAL_TOKEN("*=",          0, Token_Type_Star_Equal);
+        LITERAL_TOKEN("^=",          0, Token_Type_Xor_Equal);
         LITERAL_TOKEN("/=",          0, Token_Type_Fslash_Equal);
         LITERAL_TOKEN("%=",          0, Token_Type_Percent_Equal);
+        LITERAL_TOKEN("..",          0, Token_Type_Dot_Dot);
         break;
     }
 
index 3c511d705c28ae4b790a43060d37eea0842b7a35..70603f3e5c4264b0d8c99b363a62366fc4eaf760 100644 (file)
@@ -612,6 +612,7 @@ static inline i32 get_precedence(BinaryOp kind) {
         case Binary_Op_Assign_Sar:      return 1;
 
         case Binary_Op_Pipe:            return 2;
+        case Binary_Op_Range:           return 2;
 
         case Binary_Op_Bool_And:        return 3;
         case Binary_Op_Bool_Or:         return 3;
@@ -716,6 +717,7 @@ static AstTyped* parse_expression(OnyxParser* parser) {
             case Token_Type_Sar_Equal:         bin_op_kind = Binary_Op_Assign_Sar; break;
 
             case Token_Type_Pipe:              bin_op_kind = Binary_Op_Pipe; break;
+            case Token_Type_Dot_Dot:           bin_op_kind = Binary_Op_Range; break;
             default: goto expression_done;
         }
 
@@ -724,16 +726,19 @@ static AstTyped* parse_expression(OnyxParser* parser) {
             consume_token(parser);
 
             AstBinaryOp* bin_op;
-            if (bin_op_kind != Binary_Op_Pipe) {
-                bin_op = make_node(AstBinaryOp, Ast_Kind_Binary_Op);
-                bin_op->operation = bin_op_kind;
-                bin_op->token = bin_op_tok;
+            if (bin_op_kind == Binary_Op_Pipe) {
+                bin_op = make_node(AstBinaryOp, Ast_Kind_Pipe);
+
+            } else if (bin_op_kind == Binary_Op_Range) {
+                bin_op = make_node(AstBinaryOp, Ast_Kind_Range);
 
             } else {
-                bin_op = make_node(AstBinaryOp, Ast_Kind_Ufc);
-                bin_op->token = bin_op_tok;
+                bin_op = make_node(AstBinaryOp, Ast_Kind_Binary_Op);
             }
 
+            bin_op->token = bin_op_tok;
+            bin_op->operation = bin_op_kind;
+
             while ( !bh_arr_is_empty(tree_stack) &&
                     get_precedence(bh_arr_last(tree_stack)->operation) >= get_precedence(bin_op_kind))
                 bh_arr_pop(tree_stack);
@@ -1209,12 +1214,11 @@ static AstType* parse_type(OnyxParser* parser) {
             if (parser->curr->type == ']') {
                 new = make_node(AstSliceType, Ast_Kind_Slice_Type);
                 new->token = open_bracket;
-                
-            } else if (parser->curr->type == '.') {
+
+            } else if (parser->curr->type == Token_Type_Dot_Dot) {
                 new = make_node(AstDynArrType, Ast_Kind_DynArr_Type);
                 new->token = open_bracket;
                 consume_token(parser);
-                expect_token(parser, '.');
 
             } else {
                 new = make_node(AstArrayType, Ast_Kind_Array_Type);
@@ -1531,7 +1535,7 @@ static AstFunction* parse_function_definition(OnyxParser* parser) {
             if (func_def->overloaded_function != NULL) {
                 onyx_report_error(parser->curr->pos, "cannot have multiple #add_overload directives on a single procedure.");
                 expect_token(parser, Token_Type_Symbol);
-                
+
             } else {
                 AstNode* sym_node = make_node(AstNode, Ast_Kind_Symbol);
                 sym_node->token = expect_token(parser, Token_Type_Symbol);
index ece7115fc82e38492e81b8292ab0a64ddda964ef..4871c6d39979b94d71590706c901c8f26c8ab48e 100644 (file)
@@ -182,31 +182,31 @@ static void symres_field_access(AstFieldAccess** fa) {
     }
 }
 
-static void symres_ufc(AstBinaryOp** ufc) {
-    AstCall* call_node = (AstCall *) (*ufc)->right;
+static void symres_pipe(AstBinaryOp** pipe) {
+    AstCall* call_node = (AstCall *) (*pipe)->right;
     symres_expression((AstTyped **) &call_node);
-    symres_expression(&(*ufc)->left);
+    symres_expression(&(*pipe)->left);
 
     if (call_node->kind != Ast_Kind_Call) {
-        onyx_report_error((*ufc)->token->pos, "universal function call expected call on right side");
+        onyx_report_error((*pipe)->token->pos, "universal function call expected call on right side");
         return;
     }
 
-    if ((*ufc)->left == NULL) return;
+    if ((*pipe)->left == NULL) return;
 
     AstArgument* implicit_arg = onyx_ast_node_new(semstate.node_allocator,
             sizeof(AstArgument),
             Ast_Kind_Argument);
-    implicit_arg->token = (*ufc)->left->token;
-    implicit_arg->value = (*ufc)->left;
+    implicit_arg->token = (*pipe)->left->token;
+    implicit_arg->value = (*pipe)->left;
     implicit_arg->next = (AstNode *) call_node->arguments;
 
     call_node->arguments = implicit_arg;
     call_node->arg_count++;
-    call_node->next = (*ufc)->next;
+    call_node->next = (*pipe)->next;
 
     // NOTE: Not a BinaryOp node
-    *ufc = (AstBinaryOp *) call_node;
+    *pipe = (AstBinaryOp *) call_node;
 }
 
 static void symres_unaryop(AstUnaryOp** unaryop) {
@@ -297,15 +297,22 @@ static void symres_expression(AstTyped** expr) {
         case Ast_Kind_Address_Of:   symres_expression(&((AstAddressOf *)(*expr))->expr); break;
         case Ast_Kind_Dereference:  symres_expression(&((AstDereference *)(*expr))->expr); break;
         case Ast_Kind_Field_Access: symres_field_access((AstFieldAccess **) expr); break;
-        case Ast_Kind_Ufc:          symres_ufc((AstBinaryOp **) expr); break;
+        case Ast_Kind_Pipe:         symres_pipe((AstBinaryOp **) expr); break;
         case Ast_Kind_Size_Of:      symres_size_of((AstSizeOf *)*expr); break;
         case Ast_Kind_Align_Of:     symres_align_of((AstAlignOf *)*expr); break;
 
+        case Ast_Kind_Range:
+            symres_expression(&((AstBinaryOp *)(*expr))->left);
+            symres_expression(&((AstBinaryOp *)(*expr))->right);
+
+            (*expr)->type_node = symres_type(builtin_range_type);
+            break;
+
         case Ast_Kind_Function:
         case Ast_Kind_NumLit:
             (*expr)->type_node = symres_type((*expr)->type_node);
             break;
-            
+
         case Ast_Kind_StrLit:
             (*expr)->type_node = symres_type(builtin_string_type);
             break;
@@ -462,7 +469,7 @@ void symres_function(AstFunction* func) {
         if (param->default_value != NULL) {
             symres_expression(&param->default_value);
             if (onyx_has_errors()) return;
-            
+
             if (check_expression(&param->default_value)) return;
         }
     }
index 9c057fd25f72322de4d9ea924be8bcba01677751..1b330fcbde8603a1921b1b5aece1008a753d3b7e 100644 (file)
@@ -69,7 +69,8 @@ static const char* ast_node_names[] = {
     "ARRAY_ACCESS",
     "SLICE",
     "FIELD_ACCESS",
-    "UFC",
+    "PIPE",
+    "RANGE",
     "SIZE OF",
     "ALIGN OF",
     "FILE CONTENTS",
@@ -326,7 +327,7 @@ AstTyped* ast_reduce(bh_allocator a, AstTyped* node) {
         case Ast_Kind_Binary_Op: return (AstTyped *) ast_reduce_binop(a, (AstBinaryOp *) node);
         case Ast_Kind_Unary_Op:  return (AstTyped *) ast_reduce_unaryop(a, (AstUnaryOp *) node);
         case Ast_Kind_NumLit:    return node;
-        default:                 return NULL; 
+        default:                 return NULL;
     }
 }