From 40450a81f7c5990d9e0367c618cab5213670614b Mon Sep 17 00:00:00 2001 From: Brendan Hansen Date: Sat, 19 Feb 2022 10:37:19 -0600 Subject: [PATCH] added syntax for avoid redeclaration error --- core/container/map.onyx | 4 +-- core/net/tcp.onyx | 18 ++++++----- examples/50_misc.onyx | 70 +++++++++++++++++++++++++++++++++++++++++ src/parser.c | 28 ++++++++++------- 4 files changed, 98 insertions(+), 22 deletions(-) create mode 100644 examples/50_misc.onyx diff --git a/core/container/map.onyx b/core/container/map.onyx index e72a46cd..4e2a4c27 100644 --- a/core/container/map.onyx +++ b/core/container/map.onyx @@ -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; } diff --git a/core/net/tcp.onyx b/core/net/tcp.onyx index 23428c92..92741bf7 100644 --- a/core/net/tcp.onyx +++ b/core/net/tcp.onyx @@ -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 index 00000000..feb89ef5 --- /dev/null +++ b/examples/50_misc.onyx @@ -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 diff --git a/src/parser.c b/src/parser.c index b4c9de03..11f6ae53 100644 --- a/src/parser.c +++ b/src/parser.c @@ -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; } -- 2.25.1