Skip to content

Commit

Permalink
added: return #from_proc; fixed: nested ?
Browse files Browse the repository at this point in the history
  • Loading branch information
brendanfh committed May 7, 2024
1 parent bf5b296 commit ff0b89a
Show file tree
Hide file tree
Showing 8 changed files with 41 additions and 56 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,21 @@ Additions:
- `x |> y->z() === y->z(x)`
- Ability to use `_` where `#auto` is used.
- This will be come the default soon and `#auto` will be removed.
- `return #from_proc` to return all the way from the procedure.

Removals:
- `Optional.try` as it is incompatible with new semantics of `?`.

Changes:
- `str.as_str` is now preferred over `string.as_str`
- `str.compare` is now preferred over `string.compare`
- `str.to_cstr_on_stack` is now preferred over `string.to_cstr_on_stack`
- `str.join` is now preferred over `string.join`
- Implementation of `?` for `Optional` and `Result` to return from the enclosing procedure.

Bugfixes:
- Fixed WASI compilation due to syntax issue.
- Fixed WASI platform `__file_open` implementation for wasmtime.

Contributors:

Expand Down
2 changes: 1 addition & 1 deletion compiler/include/astnodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -830,7 +830,7 @@ struct AstDirectiveSolidify {
};

// Intruction Node
struct AstReturn { AstNode_base; AstTyped* expr; u32 count; }; // Note: This count is one less than it should be, because internal codegen with macros would have to know about this and that is error prone.
struct AstReturn { AstNode_base; AstTyped* expr; u32 count; b32 from_proc: 1; }; // Note: This count is one less than it should be, because internal codegen with macros would have to know about this and that is error prone.
struct AstJump { AstNode_base; JumpType jump; u32 count; };

// Structure Nodes
Expand Down
11 changes: 9 additions & 2 deletions compiler/src/checker.c
Original file line number Diff line number Diff line change
Expand Up @@ -146,8 +146,15 @@ CheckStatus check_return(AstReturn* retnode) {
bh_arr_length(context.checker.expected_return_type_stack));
}

expected_return_type = context.checker.expected_return_type_stack[bh_arr_length(context.checker.expected_return_type_stack) - retnode->count - 1];
named_return_values = context.checker.named_return_values_stack[bh_arr_length(context.checker.named_return_values_stack) - retnode->count - 1];
if (retnode->from_proc) {
expected_return_type = context.checker.expected_return_type_stack[0];
named_return_values = context.checker.named_return_values_stack[0];
} else {
i32 idx = bh_arr_length(context.checker.expected_return_type_stack) - retnode->count - 1;
expected_return_type = context.checker.expected_return_type_stack[idx];
named_return_values = context.checker.named_return_values_stack[idx];
}


retry_return_expr_check:

Expand Down
4 changes: 4 additions & 0 deletions compiler/src/parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -1870,6 +1870,10 @@ static AstReturn* parse_return_stmt(OnyxParser* parser) {
return_node->count += 1;
}

if (parse_possible_directive(parser, "from_proc")) {
return_node->from_proc = 1;
}

AstTyped* expr = NULL;

if (parser->curr->type != ';' && parser->curr->type != Token_Type_Inserted_Semicolon) {
Expand Down
16 changes: 16 additions & 0 deletions compiler/src/symres.c
Original file line number Diff line number Diff line change
Expand Up @@ -485,8 +485,24 @@ static SymresStatus symres_if_expression(AstIfExpression* if_expr) {
}

static SymresStatus symres_pipe(AstBinaryOp** pipe) {
if ((*pipe)->right->kind == Ast_Kind_Unary_Op) {
AstUnaryOp *the_try = (AstUnaryOp *) (*pipe)->right;
if (the_try->operation == Unary_Op_Try) {
// Shuffle the tree!
AstBinaryOp *the_pipe = *pipe;

the_pipe->right = the_try->expr;
the_try->expr = (AstTyped *) the_pipe;
*pipe = (AstBinaryOp *) the_try;

SYMRES(expression, (AstTyped **) pipe);
return Symres_Success;
}
}

AstCall* base_call_node = (AstCall *) (*pipe)->right;
AstCall* call_node = base_call_node;

if (call_node->kind == Ast_Kind_Method_Call) {
call_node = (AstCall *) ((AstBinaryOp *) call_node)->right;
}
Expand Down
6 changes: 5 additions & 1 deletion compiler/src/wasm_emit.c
Original file line number Diff line number Diff line change
Expand Up @@ -4175,8 +4175,12 @@ EMIT_FUNC(return, AstReturn* ret) {
AstLocal* result_destination = NULL;
i64 jump_label = get_structured_jump_label(mod, Jump_Type_Return, ret->count + 1);

if (ret->from_proc) {
jump_label = -1;
}

//
// If this is return statement if an inner return of a `do` block,
// If this is return statement of an inner return of a `do` block,
// we have to get the result destination out of the return location stack.
// This can be computed as the -ret->count element.
//
Expand Down
52 changes: 1 addition & 51 deletions core/container/optional.onyx
Original file line number Diff line number Diff line change
Expand Up @@ -180,56 +180,6 @@ Optional.with :: macro (o: ?$T, body: Code) {
}
}

/// Creates a scope that the `?` operator on an Optional type can
/// return to, instead of returning from the enclosing function.
///
/// Useful when chaining a bunch of operations that *could* fail,
/// while having a clean and easy escape hatch.
///
/// Optional.try() {
/// x := operation_1()?;
/// y := operation_2(x)?;
/// z := operation_3(x, y)?;
/// opreation_4(z);
/// }
/// println("Done");
///
/// In this example, if any of the operations fail, the execution
/// will cleanly go to `println` statement.
///
/// To know when something returned `None`, you can either use the second
/// parameter called `catch`, which is simply a block of code to be run.
/// Or you can use the return result from the function as so:
///
/// // Sadly, cannot use the nicer syntax, `try() { ... }`
/// completed := Optional.try(#quote {
/// // ...
/// });
Optional.try :: macro (body: Code, catch: Code = []{}) -> bool {
//
// Using a 'do'-expression block to introduce a new
// 'return' location. This way, when the code in the `body`
// does a `return return`, it will target this do-block.
_ := do -> u32 {
//
// Insert the body of interest.
#unquote body;

//
// If execution makes it here, everything was successfuly
// and no `return return`s were encountered. Return true.
return return true;
};

#unquote catch;

//
// If execution makes it here, there was an unexpected early
// return. Return false to signal the caller of this.
return false;
}


Optional.hash :: (o: ?$T/core.hash.Hashable) => switch o {
case .Some as v => core.hash.hash(v);
case _ => 0;
Expand Down Expand Up @@ -263,7 +213,7 @@ Optional.hash :: (o: ?$T/core.hash.Hashable) => switch o {
#operator ? macro (opt: ?$T) -> T {
switch value := opt; value {
case .Some as v do return v;
case _ do return return .{};
case _ do return #from_proc .{};
}
}

Expand Down
2 changes: 1 addition & 1 deletion core/container/result.onyx
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ __implicit_bool_cast :: macro (r: Result($O, $E)) => cast(Result(O, E).tag_enum,
#operator ? macro (r: Result($T, $E)) -> T {
switch res := r; res {
case .Ok as v do return v;
case .Err as v do return return .{ Err = v };
case .Err as v do return #from_proc .{ Err = v };
}
}

Expand Down

0 comments on commit ff0b89a

Please sign in to comment.