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" ---
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,
Binary_Op_Pipe = 33,
Binary_Op_Range = 34,
+ Binary_Op_Method_Call = 35,
Binary_Op_Count
} BinaryOp;
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);
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) {
"SLICE",
"FIELD_ACCESS",
"PIPE",
+ "METHOD_CALL",
"RANGE",
"SIZE OF",
"ALIGN OF",
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;
}
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;
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;
}
}
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;
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);
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 == ':') {
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 '#': {
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;
*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);
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;