added syntax for avoid redeclaration error
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Sat, 19 Feb 2022 16:37:19 +0000 (10:37 -0600)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Sat, 19 Feb 2022 16:37:19 +0000 (10:37 -0600)
core/container/map.onyx
core/net/tcp.onyx
examples/50_misc.onyx [new file with mode: 0644]
src/parser.c

index e72a46cd478b88551cfc9e280893b34b9bae3392..4e2a4c27ff9c021b128051a983e9269c9ac8db1d 100644 (file)
@@ -117,7 +117,7 @@ delete :: (use map: ^Map, key: map.Key_Type) {
     if lr.entry_prev < 0   do hashes[lr.hash_index]       = entries[lr.entry_index].next;
     else                   do entries[lr.entry_prev].next = entries[lr.entry_index].next;
 
-    if lr.entry_index == entries.count - 1{
+    if lr.entry_index == entries.count - 1 {
         array.pop(^entries);
         return;
     }
@@ -204,7 +204,7 @@ format_map :: (output: ^conv.Format_Output, format: ^conv.Format, x: ^Map($K, $V
         for ^entry: entries {
             defer index += 1;
 
-            lr := lookup(map, entry.key); 
+            lr := lookup(map, entry.key);
             entries[index].next = hashes[lr.hash_index];
             hashes[lr.hash_index] = index;
         }
index 23428c92d8a28d2f75f003472c43920dc6dac802..92741bf764a1af105ddcf98f372d19b8bc11e5b2 100644 (file)
@@ -120,7 +120,7 @@ TCP_Server :: struct {
 
     alive         := true;
     pulse_time_ms := 500;
-    
+
     get_events    :: tcp_get_events
     listen        :: tcp_server_listen
     pulse         :: tcp_server_pulse
@@ -160,7 +160,7 @@ tcp_server_make :: (max_clients := 32, allocator := context.allocator) -> ^TCP_S
         conn_event := new(TCP_Event.Connection, allocator=server.event_allocator);
         conn_event.address = ^client.address;
         conn_event.client = client;
-        server.events << .{ .Connection, conn_event };
+        server.events << .{ .Connection, conn_event }; @Threading // This operation should be protected by a mutex?
     }
 }
 
@@ -184,6 +184,8 @@ tcp_server_pulse :: (use server: ^TCP_Server) -> bool {
     }
 
     if client_count == 0 {
+        // This is bad because if the pulse_time_ms is large, the server
+        // will have a unnecessary delay for the first client to connect.
         os.sleep(pulse_time_ms);
         return true;
     }
@@ -197,7 +199,7 @@ tcp_server_pulse :: (use server: ^TCP_Server) -> bool {
         msg_buffer: [1024] u8;
         bytes_read := it.socket->recv_into(msg_buffer);
 
-        // If exactly 0 bytes are read from the buffer, it means that the 
+        // If exactly 0 bytes are read from the buffer, it means that the
         // client has shutdown and future communication should be terminated.
         //
         // If a negative number of bytes are read, then an error has occured
@@ -211,7 +213,7 @@ tcp_server_pulse :: (use server: ^TCP_Server) -> bool {
         data_event.client  = it;
         data_event.address = ^it.address;
         data_event.contents = memory.copy_slice(msg_buffer[0 .. bytes_read], allocator=server.event_allocator);
-        server.events << .{ .Data, data_event };
+        server.events << .{ .Data, data_event }; @Threading // See comment above.
     }
 
     for clients {
@@ -219,16 +221,16 @@ tcp_server_pulse :: (use server: ^TCP_Server) -> bool {
             disconnect_event := new(TCP_Event.Disconnection, allocator=server.event_allocator);
             disconnect_event.client  = it;
             disconnect_event.address = ^it.address;
-            server.events << .{ .Disconnection, disconnect_event };
+            server.events << .{ .Disconnection, disconnect_event }; @Threading // See comment above.
         }
     }
 
     array.sort(clients, (a, b) => {
-        a_val := 1 if a == null else 0; 
-        b_val := 1 if b == null else 0; 
+        a_val := 1 if a == null else 0;
+        b_val := 1 if b == null else 0;
 
         if a_val != b_val do return b_val - a_val;
-        
+
         return cast(i32) a.state - cast(i32) b.state;
     });
 
diff --git a/examples/50_misc.onyx b/examples/50_misc.onyx
new file mode 100644 (file)
index 0000000..feb89ef
--- /dev/null
@@ -0,0 +1,70 @@
+//
+// This file contains abunch of miscellaneous quirks/features of Onyx
+// that make programming it enjoyable.
+//
+
+underscore_is_weird :: () {
+    //
+    // Underscores are allowed in variable names, obviously.
+    // One feature I decided to add early one was to allow for the variable
+    // name '_' to be special, in that it can be declared and reused as
+    // many times as necesssary without causing an error. This means that
+    // it is great if you want to ignore a returned value. Take this
+    // example.
+
+    multiple_returns :: () -> (i32, str) {
+        return 123, "Hello";
+    }
+
+    _, s := multiple_returns();
+    printf("s: {}\n", s);
+
+    i, _ := multiple_returns();
+    printf("i: {}\n\n", i);
+}
+
+multiple_declaration_improvements :: () {
+    //
+    // Sometimes you want to call a function that returns multiple things
+    // and assign each of them to a new variable. This is totally within
+    // the normal semantics of the language and looks like so.
+
+    multiple_returns :: () -> (i32, str) {
+        return 123, "Hello";
+    }
+
+    i, s := multiple_returns();
+    printf("i: {}\ns: {}\n\n", i, s);
+
+    //
+    // However sometimes you want to declare one new variable and reuse
+    // old variable in the compound assignment. This is tricky, because
+    // if you were to write the following, you would get an error saying
+    // that 's' is already declared.
+    //
+    //     k, s := multiple_returns();
+    //
+    // You're trying to declare a new variable k, while using the old variable
+    // s in the same declaration. To get around this issue, there is a special
+    // syntax you can use that tell the compiler that s is a not a new
+    // variable, but the same one as above. You simple place a ' after the
+    // variable that you want to reuse.
+
+    k, s' := multiple_returns();
+    printf("k: {}\ns: {}\n\n", k, s);
+
+    //
+    // Obviously this assumes that s is the same type as before. If the types
+    // were different, you would not be able to do this.
+}
+
+
+//
+// A simple main to run all the examples.
+main :: (args) => {
+    underscore_is_weird();
+    multiple_declaration_improvements();
+}
+
+#load "core/std"
+use package core
index b4c9de03f0428ebe0464fb421553c205718a252b..11f6ae53ee917595a92844baf11b1fea5b589817 100644 (file)
@@ -1203,6 +1203,8 @@ static i32 parse_possible_compound_symbol_declaration(OnyxParser* parser, AstNod
     while (peek_token(token_offset)->type == Token_Type_Symbol) {
         token_offset += 1;
 
+        if (peek_token(token_offset)->type == '\'') token_offset += 1;
+
         if (peek_token(token_offset)->type != ',') break;
         token_offset += 1;
     }
@@ -1220,18 +1222,19 @@ static i32 parse_possible_compound_symbol_declaration(OnyxParser* parser, AstNod
         if (parser->hit_unexpected_token) return 1;
 
         OnyxToken* local_sym = expect_token(parser, Token_Type_Symbol);
-        AstLocal* new_local = make_local(parser->allocator, local_sym, NULL);
-
-        if (prev_local == NULL) {
-            first_local = new_local;
-        } else {
-            prev_local->next = (AstNode *) new_local;
-        }
-        prev_local = new_local;
-
         AstNode* sym_node = make_symbol(parser->allocator, local_sym);
         bh_arr_push(local_compound->exprs, (AstTyped *) sym_node);
 
+        if (!consume_token_if_next(parser, '\'')) {
+            AstLocal* new_local = make_local(parser->allocator, local_sym, NULL);
+            if (prev_local == NULL) {
+                first_local = new_local;
+            } else {
+                prev_local->next = (AstNode *) new_local;
+            }
+            prev_local = new_local;
+        }
+
         consume_token_if_next(parser, ',');
     }
 
@@ -1265,7 +1268,8 @@ static i32 parse_possible_symbol_declaration(OnyxParser* parser, AstNode** ret)
     if (parser->curr->type != Token_Type_Symbol) return 0;
 
     // If the token after the symbol is a comma, assume this is a compound declaration.
-    if (peek_token(1)->type == ',') {
+    if (peek_token(1)->type == ',' ||
+        (peek_token(1)->type == '\'' && peek_token(2)->type == ',')) {
         return parse_possible_compound_symbol_declaration(parser, ret);
     }
 
@@ -2159,7 +2163,7 @@ static void parse_function_params(OnyxParser* parser, AstFunction* func) {
 
     u32 param_idx = 0;
     assert(parser->polymorph_context.poly_params != NULL);
-    
+
     bh_arr(AstParam) param_buffer=NULL;
     bh_arr_new(global_heap_allocator, param_buffer, 2);
 
@@ -2402,7 +2406,7 @@ function_defined:
     } else {
         bh_arr_free(polymorphic_vars);
     }
-    
+
     bh_arr_pop(parser->current_function_stack);
     return func_def;
 }