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;
}
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;
}
alive := true;
pulse_time_ms := 500;
-
+
get_events :: tcp_get_events
listen :: tcp_server_listen
pulse :: tcp_server_pulse
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?
}
}
}
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;
}
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
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 {
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;
});
--- /dev/null
+//
+// 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
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;
}
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, ',');
}
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);
}
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);
} else {
bh_arr_free(polymorphic_vars);
}
-
+
bh_arr_pop(parser->current_function_stack);
return func_def;
}