Browse Source

Correct selector call expression chaining behaviour (a bit of a hack)

gingerBill 4 years ago
parent
commit
574ceb37a9
2 changed files with 35 additions and 10 deletions
  1. 28 9
      src/llvm_backend.cpp
  2. 7 1
      src/parser.hpp

+ 28 - 9
src/llvm_backend.cpp

@@ -10534,7 +10534,26 @@ lbValue lb_handle_param_value(lbProcedure *p, Type *parameter_type, ParameterVal
 }
 
 
+lbValue lb_build_call_expr_internal(lbProcedure *p, Ast *expr);
+
 lbValue lb_build_call_expr(lbProcedure *p, Ast *expr) {
+	expr = unparen_expr(expr);
+	ast_node(ce, CallExpr, expr);
+
+	if (ce->sce_temp_data) {
+		return *(lbValue *)ce->sce_temp_data;
+	}
+
+	lbValue res = lb_build_call_expr_internal(p, expr);
+
+	if (ce->optional_ok_one) { // TODO(bill): Minor hack for #optional_ok procedures
+		GB_ASSERT(is_type_tuple(res.type));
+		GB_ASSERT(res.type->Tuple.variables.count == 2);
+		return lb_emit_struct_ev(p, res, 0);
+	}
+	return res;
+}
+lbValue lb_build_call_expr_internal(lbProcedure *p, Ast *expr) {
 	lbModule *m = p->module;
 
 	TypeAndValue tv = type_and_value_of_expr(expr);
@@ -12482,7 +12501,12 @@ lbValue lb_build_expr(lbProcedure *p, Ast *expr) {
 		GB_ASSERT(se->modified_call);
 		TypeAndValue tav = type_and_value_of_expr(expr);
 		GB_ASSERT(tav.mode != Addressing_Invalid);
-		return lb_build_expr(p, se->call);
+		lbValue res = lb_build_call_expr(p, se->call);
+
+		ast_node(ce, CallExpr, se->call);
+		ce->sce_temp_data = gb_alloc_copy(permanent_allocator(), &res, gb_size_of(res));
+
+		return res;
 	case_end;
 
 	case_ast_node(te, TernaryIfExpr, expr);
@@ -12596,13 +12620,7 @@ lbValue lb_build_expr(lbProcedure *p, Ast *expr) {
 	case_end;
 
 	case_ast_node(ce, CallExpr, expr);
-		lbValue res = lb_build_call_expr(p, expr);
-		if (ce->optional_ok_one) { // TODO(bill): Minor hack for #optional_ok procedures
-			GB_ASSERT(is_type_tuple(res.type));
-			GB_ASSERT(res.type->Tuple.variables.count == 2);
-			return lb_emit_struct_ev(p, res, 0);
-		}
-		return res;
+		return lb_build_call_expr(p, expr);
 	case_end;
 
 	case_ast_node(se, SliceExpr, expr);
@@ -12992,7 +13010,8 @@ lbAddr lb_build_addr(lbProcedure *p, Ast *expr) {
 		GB_ASSERT(se->modified_call);
 		TypeAndValue tav = type_and_value_of_expr(expr);
 		GB_ASSERT(tav.mode != Addressing_Invalid);
-		return lb_build_addr(p, se->call);
+		lbValue e = lb_build_expr(p, expr);
+		return lb_addr(lb_address_from_load_or_generate_local(p, e));
 	case_end;
 
 	case_ast_node(ta, TypeAssertion, expr);

+ 7 - 1
src/parser.hpp

@@ -334,7 +334,11 @@ AST_KIND(_ExprBegin,  "",  bool) \
 		u8 swizzle_indices; /*2 bits per component*/ \
 	}) \
 	AST_KIND(ImplicitSelectorExpr, "implicit selector expression",    struct { Token token; Ast *selector; }) \
-	AST_KIND(SelectorCallExpr, "selector call expression",    struct { Token token; Ast *expr, *call; bool modified_call; }) \
+	AST_KIND(SelectorCallExpr, "selector call expression", struct { \
+		Token token; \
+		Ast *expr, *call;  \
+		bool modified_call; \
+	}) \
 	AST_KIND(IndexExpr,    "index expression",       struct { Ast *expr, *index; Token open, close; }) \
 	AST_KIND(DerefExpr,    "dereference expression", struct { Ast *expr; Token op; }) \
 	AST_KIND(SliceExpr,    "slice expression", struct { \
@@ -352,6 +356,7 @@ AST_KIND(_ExprBegin,  "",  bool) \
 		ProcInlining inlining; \
 		bool         optional_ok_one; \
 		i32          builtin_id; \
+		void *sce_temp_data; \
 	}) \
 	AST_KIND(FieldValue,      "field value",              struct { Token eq; Ast *field, *value; }) \
 	AST_KIND(TernaryIfExpr,   "ternary if expression",    struct { Ast *x, *cond, *y; }) \
@@ -716,3 +721,4 @@ gbAllocator ast_allocator(AstFile *f) {
 
 Ast *alloc_ast_node(AstFile *f, AstKind kind);
 
+gbString expr_to_string(Ast *expression);