Skip to content

Commit b1d15e3

Browse files
authored
Release 0.1.7
Release 0.1.7
2 parents a7e923f + 7bbbe4c commit b1d15e3

70 files changed

Lines changed: 2895 additions & 874 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CHANGELOG

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,44 @@
1+
Release v0.1.7
2+
--------------
3+
October 25th, 2023
4+
5+
Additions:
6+
- Support for WASIX, a new, extended standard to WASI, popularized by Wasmer.
7+
- Define `WASIX` in `runtime.vars` to enable it. (`-DWASIX` on the CLI)
8+
- Adds support for networking, futexes, and TTY control in WASI.
9+
- `switch` expressions.
10+
- `switch` can appear at the expression level, and uses `case X => value` to
11+
specify cases.
12+
- `cbindgen` now supports passing functions as arguments.
13+
- Internally uses dyncallback
14+
- Only for OVM-wasm and Linux, for now.
15+
- Scoped values in interfaces. `X :: ...` is allowed in an interface now.
16+
- `#inject` works on interfaces.
17+
- Polling to the `io.Stream` functionality.
18+
- Used to query when data is read/write-able from a stream, for supported streams.
19+
- `io.stream_poll`
20+
- `misc.any_unwrap` to unwrap an `any` containing an optional.
21+
- `json.decode_with_result`
22+
- `json.decode_into`
23+
- `slice.group_by`
24+
25+
Removals:
26+
27+
Changes:
28+
- Complete overhaul of networking in the core library.
29+
- Backwards compatiblity was not strictly maintained, but common functions did
30+
not change, like `socket_send` and `socket_recv`.
31+
- When debugging, `/ 0` or `% 0` will trigger an exception to debug the error.
32+
33+
Bugfixes:
34+
- `alloc.atomic` package was broken when `sync` package was missing.
35+
- `X.foo` would not work if `X` was a pointer to a union.
36+
- Captures by pointer would break if the value was a primitive whose address wasn't
37+
taken anywhere else.
38+
- Symbol name reported by documentation generation was incorrect for some methods.
39+
40+
41+
142
Release v0.1.6
243
-----------
344
24th September 2023

compiler/build.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ fi
3030

3131
FLAGS="$FLAGS -DENABLE_RUN_WITH_WASMER"
3232

33-
if [ "$USE_DYNCALL" = "1" ]; then
33+
if [ "$USE_DYNCALL" = "1" ] && [ "$RUNTIME_LIBRARY" = "ovmwasm" ]; then
3434
LIBS="$LIBS ../shared/lib/linux_$ARCH/lib/libdyncall_s.a ../shared/lib/linux_$ARCH/lib/libdyncallback_s.a"
3535
FLAGS="$FLAGS -DUSE_DYNCALL"
3636
fi

compiler/include/astnodes.h

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -881,7 +881,7 @@ typedef enum SwitchKind {
881881
typedef struct CaseToBlock {
882882
AstTyped *original_value;
883883
AstBinaryOp *comparison;
884-
AstBlock *block;
884+
AstSwitchCase *casestmt;
885885
} CaseToBlock;
886886

887887
struct AstSwitchCase {
@@ -890,16 +890,21 @@ struct AstSwitchCase {
890890
// NOTE: All expressions that end up in this block
891891
bh_arr(AstTyped *) values;
892892

893-
AstBlock *block;
893+
union {
894+
AstBlock *block;
895+
AstTyped *expr;
896+
};
894897

895898
AstLocal *capture;
899+
Scope *scope; // Scope for the capture
896900

897901
b32 is_default: 1; // Could this be inferred by the values array being null?
898902
b32 capture_is_by_pointer: 1;
903+
b32 body_is_expr : 1;
899904
};
900905

901906
struct AstSwitch {
902-
AstNode_base;
907+
AstTyped_base;
903908

904909
Scope *scope;
905910
AstNode* initialization;
@@ -918,6 +923,8 @@ struct AstSwitch {
918923
// been handled.
919924
u8 *union_variants_handled;
920925

926+
b32 is_expr;
927+
921928
union {
922929
struct {
923930
// NOTE: This is a mapping from the compile time known case value
@@ -1213,6 +1220,8 @@ struct AstInterface {
12131220
bh_arr(InterfaceParam) params;
12141221
bh_arr(InterfaceConstraint) exprs;
12151222

1223+
Scope *scope;
1224+
12161225
b32 is_intrinsic: 1;
12171226
};
12181227

compiler/src/astnodes.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -770,6 +770,34 @@ TypeMatch unify_node_and_type_(AstTyped** pnode, Type* type, b32 permanent) {
770770
}
771771
}
772772

773+
if (node->kind == Ast_Kind_Switch) {
774+
AstSwitch *switchnode = (AstSwitch *) node;
775+
if (!switchnode->is_expr) return TYPE_MATCH_FAILED;
776+
777+
if (switchnode->cases == NULL) return TYPE_MATCH_YIELD;
778+
779+
bh_arr_each(AstSwitchCase *, pcasestmt, switchnode->cases) {
780+
AstSwitchCase *casestmt = *pcasestmt;
781+
if (!casestmt->body_is_expr) continue;
782+
783+
switch (unify_node_and_type_(&casestmt->expr, type, permanent)) {
784+
case TYPE_MATCH_SUCCESS: break;
785+
case TYPE_MATCH_FAILED: return TYPE_MATCH_FAILED;
786+
case TYPE_MATCH_YIELD: return TYPE_MATCH_YIELD;
787+
}
788+
}
789+
790+
if (switchnode->default_case) {
791+
switch (unify_node_and_type_((AstTyped **) &switchnode->default_case, type, permanent)) {
792+
case TYPE_MATCH_SUCCESS: break;
793+
case TYPE_MATCH_FAILED: return TYPE_MATCH_FAILED;
794+
case TYPE_MATCH_YIELD: return TYPE_MATCH_YIELD;
795+
}
796+
}
797+
798+
if (permanent) switchnode->type = type;
799+
return TYPE_MATCH_SUCCESS;
800+
}
773801

774802
// If the destination type is an optional, and the node's type is a value of
775803
// the same underlying type, then we can construct an optional with a value

compiler/src/checker.c

Lines changed: 63 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,7 @@ CheckStatus check_for(AstFor* fornode) {
362362
return Check_Success;
363363
}
364364

365-
static b32 add_case_to_switch_statement(AstSwitch* switchnode, u64 case_value, AstBlock* block, OnyxFilePos pos) {
365+
static b32 add_case_to_switch_statement(AstSwitch* switchnode, u64 case_value, AstSwitchCase* casestmt, OnyxFilePos pos) {
366366
assert(switchnode->switch_kind == Switch_Kind_Integer || switchnode->switch_kind == Switch_Kind_Union);
367367

368368
switchnode->min_case = bh_min(switchnode->min_case, case_value);
@@ -373,7 +373,7 @@ static b32 add_case_to_switch_statement(AstSwitch* switchnode, u64 case_value, A
373373
return 1;
374374
}
375375

376-
bh_imap_put(&switchnode->case_map, case_value, (u64) block);
376+
bh_imap_put(&switchnode->case_map, case_value, (u64) casestmt);
377377
return 0;
378378
}
379379

@@ -488,7 +488,7 @@ CheckStatus check_switch(AstSwitch* switchnode) {
488488
AstSwitchCase *sc = switchnode->cases[i];
489489

490490
if (sc->capture && bh_arr_length(sc->values) != 1) {
491-
ERROR(sc->token->pos, "Expected exactly one value in switch-case when using a capture, i.e. `case X => Y { ... }`.");
491+
ERROR(sc->token->pos, "Expected exactly one value in switch-case when using a capture, i.e. `case value: X { ... }`.");
492492
}
493493

494494
if (sc->capture && switchnode->switch_kind != Switch_Kind_Union) {
@@ -519,7 +519,7 @@ CheckStatus check_switch(AstSwitch* switchnode) {
519519

520520
// NOTE: This is inclusive!!!!
521521
fori (case_value, lower, upper + 1) {
522-
if (add_case_to_switch_statement(switchnode, case_value, sc->block, rl->token->pos))
522+
if (add_case_to_switch_statement(switchnode, case_value, sc, rl->token->pos))
523523
return Check_Error;
524524
}
525525

@@ -573,7 +573,7 @@ CheckStatus check_switch(AstSwitch* switchnode) {
573573
if (!is_valid)
574574
ERROR_((*value)->token->pos, "Case statement expected compile time known integer. Got '%s'.", onyx_ast_node_kind_string((*value)->kind));
575575

576-
if (add_case_to_switch_statement(switchnode, integer_value, sc->block, sc->block->token->pos))
576+
if (add_case_to_switch_statement(switchnode, integer_value, sc, sc->block->token->pos))
577577
return Check_Error;
578578

579579
break;
@@ -592,7 +592,7 @@ CheckStatus check_switch(AstSwitch* switchnode) {
592592
if (found) break;
593593

594594
CaseToBlock ctb;
595-
ctb.block = sc->block;
595+
ctb.casestmt = sc;
596596
ctb.original_value = *value;
597597
ctb.comparison = make_binary_op(context.ast_alloc, Binary_Op_Equal, switchnode->expr, *value);
598598
ctb.comparison->token = (*value)->token;
@@ -607,13 +607,52 @@ CheckStatus check_switch(AstSwitch* switchnode) {
607607
sc->flags |= Ast_Flag_Has_Been_Checked;
608608

609609
check_switch_case_block:
610-
CHECK(block, sc->block);
610+
if (switchnode->is_expr) {
611+
if (!sc->body_is_expr) {
612+
onyx_report_error(sc->token->pos, Error_Critical, "Inside a switch expression, all cases must return a value.");
613+
ERROR(sc->token->pos, "Change the case statement to look like 'case X => expr'.");
614+
}
615+
} else {
616+
if (sc->body_is_expr) {
617+
ERROR(sc->token->pos, "This kind of case statement is only allowed in switch expressions, not switch statements.");
618+
}
619+
}
620+
621+
if (sc->body_is_expr) {
622+
CHECK(expression, &sc->expr);
623+
if (switchnode->type == NULL) {
624+
switchnode->type = resolve_expression_type(sc->expr);
625+
} else {
626+
TYPE_CHECK(&sc->expr, switchnode->type) {
627+
ERROR_(sc->token->pos, "Expected case expression to be of type '%s', got '%s'.",
628+
type_get_name(switchnode->type),
629+
type_get_name(sc->expr->type));
630+
}
631+
}
632+
633+
} else {
634+
CHECK(block, sc->block);
635+
}
611636

612637
switchnode->yield_return_index += 1;
613638
}
614639

615640
if (switchnode->default_case) {
616-
CHECK(block, switchnode->default_case);
641+
if (switchnode->is_expr) {
642+
AstTyped **default_case = (AstTyped **) &switchnode->default_case;
643+
CHECK(expression, default_case);
644+
645+
if (switchnode->type) {
646+
TYPE_CHECK(default_case, switchnode->type) {
647+
ERROR_((*default_case)->token->pos, "Expected case expression to be of type '%s', got '%s'.",
648+
type_get_name(switchnode->type),
649+
type_get_name((*default_case)->type));
650+
}
651+
}
652+
653+
} else {
654+
CHECK(block, switchnode->default_case);
655+
}
617656

618657
} else if (switchnode->switch_kind == Switch_Kind_Union) {
619658
// If there is no default case, and this is a union switch,
@@ -2403,6 +2442,10 @@ CheckStatus check_expression(AstTyped** pexpr) {
24032442
ERROR_(cl->token->pos, "Cannot pass '%b' by pointer because it is not an l-value.", cl->token->text, cl->token->length);
24042443
}
24052444

2445+
if (cl->captured_value->kind == Ast_Kind_Local) {
2446+
cl->captured_value->flags |= Ast_Flag_Address_Taken;
2447+
}
2448+
24062449
expr->type = type_make_pointer(context.ast_alloc, cl->captured_value->type);
24072450

24082451
} else {
@@ -2411,14 +2454,22 @@ CheckStatus check_expression(AstTyped** pexpr) {
24112454
break;
24122455
}
24132456

2457+
case Ast_Kind_Switch: {
2458+
AstSwitch* switch_node = (AstSwitch *) expr;
2459+
assert(switch_node->is_expr);
2460+
2461+
CHECK(switch, switch_node);
2462+
break;
2463+
}
2464+
2465+
case Ast_Kind_Switch_Case: break;
24142466
case Ast_Kind_File_Contents: break;
24152467
case Ast_Kind_Overloaded_Function: break;
24162468
case Ast_Kind_Enum_Value: break;
24172469
case Ast_Kind_Polymorphic_Proc: break;
24182470
case Ast_Kind_Package: break;
24192471
case Ast_Kind_Error: break;
24202472
case Ast_Kind_Unary_Field_Access: break;
2421-
case Ast_Kind_Switch_Case: break;
24222473
case Ast_Kind_Foreign_Block: break;
24232474
case Ast_Kind_Zero_Value: break;
24242475
case Ast_Kind_Interface: break;
@@ -3567,8 +3618,10 @@ CheckStatus check_constraint(AstConstraint *constraint) {
35673618
}
35683619

35693620
assert(constraint->interface->entity && constraint->interface->entity->scope);
3621+
assert(constraint->interface->scope);
3622+
assert(constraint->interface->scope->parent == constraint->interface->entity->scope);
35703623

3571-
constraint->scope = scope_create(context.ast_alloc, constraint->interface->entity->scope, constraint->token->pos);
3624+
constraint->scope = scope_create(context.ast_alloc, constraint->interface->scope, constraint->token->pos);
35723625

35733626
if (bh_arr_length(constraint->type_args) != bh_arr_length(constraint->interface->params)) {
35743627
ERROR_(constraint->token->pos, "Wrong number of arguments given to interface. Expected %d, got %d.",

compiler/src/doc.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -501,8 +501,18 @@ static void write_doc_methods(bh_buffer *buffer, Scope *method_scope) {
501501
case Ast_Kind_Overloaded_Function: binding = ((AstOverloadedFunction *) node)->original_binding_to_node; break;
502502
}
503503

504+
OnyxToken tmp_name_token;
505+
tmp_name_token.pos = binding->token->pos;
506+
tmp_name_token.text = method_scope->symbols[i].key;
507+
tmp_name_token.length = strlen(tmp_name_token.text);
508+
509+
OnyxToken *old_token = binding->token;
510+
binding->token = &tmp_name_token;
511+
504512
method_count++;
505513
write_doc_procedure(buffer, binding, (AstNode *) node);
514+
515+
binding->token = old_token;
506516
}
507517

508518
*((u32 *) bh_pointer_add(buffer->data, count_patch)) = method_count;

compiler/src/onyx.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ extern struct bh_allocator global_heap_allocator;
1919
#include "wasm_emit.h"
2020
#include "doc.h"
2121

22-
#define VERSION "v0.1.6"
22+
#define VERSION "v0.1.7"
2323

2424

2525
Context context;
@@ -934,7 +934,7 @@ static i32 onyx_compile() {
934934
if (context.options->verbose_output > 0) {
935935
// TODO: Replace these with bh_printf when padded formatting is added.
936936
printf("\nStatistics:\n");
937-
printf(" Time taken: %lf seconds\n", (double) duration / 1000);
937+
printf(" Time taken: %lf ms\n", (double) duration);
938938
printf(" Processed %ld lines (%f lines/second).\n", context.lexer_lines_processed, ((f32) 1000 * context.lexer_lines_processed) / (duration));
939939
printf(" Processed %ld tokens (%f tokens/second).\n", context.lexer_tokens_processed, ((f32) 1000 * context.lexer_tokens_processed) / (duration));
940940
printf("\n");

0 commit comments

Comments
 (0)