From: Brendan Hansen Date: Tue, 2 Feb 2021 20:28:03 +0000 (-0600) Subject: added experimental 'method call' syntax X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=a4322042876f15179b991666e1f6489574a71064;p=onyx.git added experimental 'method call' syntax --- diff --git a/bin/onyx b/bin/onyx index c9f7b5c2..705f3739 100755 Binary files a/bin/onyx and b/bin/onyx differ diff --git a/core/js/webgl.onyx b/core/js/webgl.onyx index 2167761c..02a22b62 100644 --- a/core/js/webgl.onyx +++ b/core/js/webgl.onyx @@ -738,7 +738,7 @@ blendFuncSeparate :: (srcRGB: GLenum, dstRGB: GLenum, srcAlpha: GLe blitFramebuffer :: (sx0: GLint, sy0: GLint, sx1: GLint, sy1: GLint, dx0: GLint, dy0: GLint, dx1: GLint, dy1: GLint, mask: GLbitfield, filter: GLenum) -> void #foreign "gl" "blitFramebuffer" --- bufferDataWithData :: (target: GLenum, buffer: [] void, usage: GLenum) -> void #foreign "gl" "bufferDataWithData" --- bufferDataNoData :: (target: GLenum, size: GLsizeiptr, usage: GLenum) -> void #foreign "gl" "bufferDataNoData" --- -bufferData :: { bufferDataWithData, bufferDataNoData } +bufferData :: proc { bufferDataWithData, bufferDataNoData } bufferSubData :: (target: GLenum, offset: GLsizei, data: [] void) -> void #foreign "gl" "bufferSubData" --- canvasSize :: (width: GLsizei, height: GLsizei) -> void #foreign "gl" "canvasSize" --- checkFrameBufferStatus :: (target: GLenum) -> GLenum #foreign "gl" "checkFrameBufferStatus" --- diff --git a/include/onyxastnodes.h b/include/onyxastnodes.h index 0617aa7b..5d477b6c 100644 --- a/include/onyxastnodes.h +++ b/include/onyxastnodes.h @@ -146,6 +146,7 @@ typedef enum AstKind { Ast_Kind_Slice, Ast_Kind_Field_Access, Ast_Kind_Pipe, + Ast_Kind_Method_Call, Ast_Kind_Range_Literal, Ast_Kind_Size_Of, Ast_Kind_Align_Of, @@ -263,6 +264,7 @@ typedef enum BinaryOp { Binary_Op_Pipe = 33, Binary_Op_Range = 34, + Binary_Op_Method_Call = 35, Binary_Op_Count } BinaryOp; @@ -1067,6 +1069,7 @@ AstRangeLiteral* make_range_literal(bh_allocator a, AstTyped* low, AstTyped* hig AstBinaryOp* make_binary_op(bh_allocator a, BinaryOp operation, AstTyped* left, AstTyped* right); AstArgument* make_argument(bh_allocator a, AstTyped* value); AstFieldAccess* make_field_access(bh_allocator a, AstTyped* node, char* field); +AstAddressOf* make_address_of(bh_allocator a, AstTyped* node); AstLocal* make_local(bh_allocator a, OnyxToken* token, AstType* type_node); AstNode* make_symbol(bh_allocator a, OnyxToken* sym); diff --git a/onyx.exe b/onyx.exe index eee67d05..e0845ccf 100644 Binary files a/onyx.exe and b/onyx.exe differ diff --git a/src/onyx.c b/src/onyx.c index 0be1e45a..a01a38ae 100644 --- a/src/onyx.c +++ b/src/onyx.c @@ -327,7 +327,7 @@ static i32 onyx_compile() { entity_heap_remove_top(&context.entities); #if defined(_BH_LINUX) - if (context.options->fun_output) { + if (context.options->fun_output) { output_dummy_progress_bar(); if (ent.expr->token) { diff --git a/src/onyxastnodes.c b/src/onyxastnodes.c index 1ea640df..9d39772f 100644 --- a/src/onyxastnodes.c +++ b/src/onyxastnodes.c @@ -64,6 +64,7 @@ static const char* ast_node_names[] = { "SLICE", "FIELD_ACCESS", "PIPE", + "METHOD_CALL", "RANGE", "SIZE OF", "ALIGN OF", @@ -688,6 +689,14 @@ AstFieldAccess* make_field_access(bh_allocator a, AstTyped* node, char* field) { return fa; } +AstAddressOf* make_address_of(bh_allocator a, AstTyped* node) { + AstAddressOf* ao = onyx_ast_node_new(a, sizeof(AstAddressOf), Ast_Kind_Address_Of); + if (node->token) ao->token = node->token; + ao->expr = node; + + return ao; +} + AstLocal* make_local(bh_allocator a, OnyxToken* token, AstType* type_node) { AstLocal* local = onyx_ast_node_new(a, sizeof(AstLocal), Ast_Kind_Local); local->token = token; diff --git a/src/onyxparser.c b/src/onyxparser.c index 9251f6c7..d6fc334a 100644 --- a/src/onyxparser.c +++ b/src/onyxparser.c @@ -196,8 +196,7 @@ static b32 parse_possible_directive(OnyxParser* parser, const char* dir) { } static b32 parse_possible_struct_literal(OnyxParser* parser, AstTyped* left, AstTyped** ret) { - if (parser->curr->type != '.' - || peek_token(1)->type != '{') return 0; + if (parser->curr->type != '.' || peek_token(1)->type != '{') return 0; AstStructLiteral* sl = make_node(AstStructLiteral, Ast_Kind_Struct_Literal); sl->token = parser->curr; @@ -596,6 +595,16 @@ static AstTyped* parse_factor(OnyxParser* parser) { break; } + case Token_Type_Right_Arrow: { + AstBinaryOp* method_call = make_node(AstBinaryOp, Ast_Kind_Method_Call); + method_call->token = expect_token(parser, Token_Type_Right_Arrow); + method_call->left = retval; + method_call->right = parse_factor(parser); + + retval = (AstTyped *) method_call; + break; + } + default: goto factor_parsed; } } @@ -2073,7 +2082,8 @@ static AstBinding* parse_top_level_binding(OnyxParser* parser, OnyxToken* symbol AstTyped* node = parse_top_level_expression(parser); if (parser->hit_unexpected_token || node == NULL) return NULL; - + + // CLEANUP if (node->kind == Ast_Kind_Function) { AstFunction* func = (AstFunction *) node; @@ -2132,7 +2142,8 @@ static AstNode* parse_top_level_statement(OnyxParser* parser) { else if (parse_possible_directive(parser, "private_file")) { private_kind = Ast_Flag_Private_File; } - + + // CLEANUP switch ((u16) parser->curr->type) { case Token_Type_Keyword_Use: { AstNode* use_node = parse_use_stmt(parser); @@ -2145,9 +2156,7 @@ static AstNode* parse_top_level_statement(OnyxParser* parser) { return NULL; case Token_Type_Symbol: { - OnyxToken* symbol = parser->curr; - consume_token(parser); - + OnyxToken* symbol = expect_token(parser, Token_Type_Symbol); expect_token(parser, ':'); if (parser->curr->type == ':') { @@ -2156,27 +2165,26 @@ static AstNode* parse_top_level_statement(OnyxParser* parser) { if (binding != NULL) binding->node->flags |= private_kind; return (AstNode *) binding; + } + + AstMemRes* memres = make_node(AstMemRes, Ast_Kind_Memres); + memres->token = symbol; - } else { - AstMemRes* memres = make_node(AstMemRes, Ast_Kind_Memres); - memres->token = symbol; - - if (parser->curr->type != '=') - memres->type_node = parse_type(parser); - - if (consume_token_if_next(parser, '=')) - memres->initial_value = parse_expression(parser, 1); - - memres->flags |= private_kind; - - ENTITY_SUBMIT(memres); - - AstBinding* binding = make_node(AstBinding, Ast_Kind_Binding); - binding->token = symbol; - binding->node = (AstNode *) memres; + if (parser->curr->type != '=') + memres->type_node = parse_type(parser); + + if (consume_token_if_next(parser, '=')) + memres->initial_value = parse_expression(parser, 1); + + memres->flags |= private_kind; + + ENTITY_SUBMIT(memres); + + AstBinding* binding = make_node(AstBinding, Ast_Kind_Binding); + binding->token = symbol; + binding->node = (AstNode *) memres; - return (AstNode *) binding; - } + return (AstNode *) binding; } case '#': { @@ -2238,7 +2246,8 @@ static AstPackage* parse_package_name(OnyxParser* parser) { package_node->package = package; return package_node; } - + + // CLEANUP char package_name[1024]; // CLEANUP: This could overflow, if someone decides to be dumb // with their package names - brendanfh 2020/12/06 package_name[0] = 0; diff --git a/src/onyxsymres.c b/src/onyxsymres.c index 2a88efe6..0e663545 100644 --- a/src/onyxsymres.c +++ b/src/onyxsymres.c @@ -352,6 +352,43 @@ static void symres_pipe(AstBinaryOp** pipe) { *pipe = (AstBinaryOp *) call_node; } +// nocheckin +// CLEANUP: This is an experimental feature and might be removed in the future. +// I noticed a common pattern when writing in Onyx is something that looks like this: +// +// foo.member_function(^foo, ...) +// +// I decided it would be worth adding a bit of syntactic sugar for such as call. I +// decided to use the '->' operator for this purpose. The snippet below is the exact +// same as the snippet above (after the nodes have been processed by the function below) +// +// foo->member_function(...) +static void symres_method_call(AstBinaryOp** mcall) { + AstCall* call_node = (AstCall *) (*mcall)->right; + if (call_node->kind != Ast_Kind_Call) { + onyx_report_error((*mcall)->token->pos, "'->' expected procedure call on right side."); + return; + } + + symres_expression(&(*mcall)->left); + if ((*mcall)->left == NULL) return; + + bh_arr_insertn(call_node->args.values, 0, 1); + + AstTyped* implicit_pointer = (AstTyped *) make_address_of(context.ast_alloc, (*mcall)->left); + call_node->args.values[0] = (AstTyped *) make_argument(context.ast_alloc, implicit_pointer); + + AstFieldAccess* implicit_field_access = make_field_access(context.ast_alloc, (*mcall)->left, NULL); + implicit_field_access->token = call_node->callee->token; + call_node->callee = (AstTyped *) implicit_field_access; + symres_expression((AstTyped **) &call_node); + + call_node->next = (*mcall)->next; + + // NOTE: Not a BinaryOp node + *mcall = (AstBinaryOp *) call_node; +} + static void symres_unaryop(AstUnaryOp** unaryop) { if ((*unaryop)->operation == Unary_Op_Cast) { (*unaryop)->type_node = symres_type((*unaryop)->type_node); @@ -415,6 +452,7 @@ static void symres_expression(AstTyped** expr) { case Ast_Kind_Dereference: symres_expression(&((AstDereference *)(*expr))->expr); break; case Ast_Kind_Field_Access: symres_field_access((AstFieldAccess **) expr); break; case Ast_Kind_Pipe: symres_pipe((AstBinaryOp **) expr); break; + case Ast_Kind_Method_Call: symres_method_call((AstBinaryOp **) expr); break; case Ast_Kind_Size_Of: symres_size_of((AstSizeOf *)*expr); break; case Ast_Kind_Align_Of: symres_align_of((AstAlignOf *)*expr); break;