浏览代码

Improve logic for x->y() shorthand

gingerBill 5 年之前
父节点
当前提交
939878df50
共有 5 个文件被更改,包括 31 次插入18 次删除
  1. 16 0
      src/check_expr.cpp
  2. 1 2
      src/check_stmt.cpp
  3. 2 1
      src/checker.hpp
  4. 0 3
      src/main.cpp
  5. 12 12
      src/parser.cpp

+ 16 - 0
src/check_expr.cpp

@@ -3437,6 +3437,13 @@ Entity *check_selector(CheckerContext *c, Operand *operand, Ast *node, Type *typ
 	Entity *entity = nullptr;
 	Selection sel = {}; // NOTE(bill): Not used if it's an import name
 
+	if (!c->allow_arrow_right_selector_expr && se->token.kind == Token_ArrowRight) {
+		error(node, "Illegal use of -> selector shorthand outside of a call");
+		operand->mode = Addressing_Invalid;
+		operand->expr = node;
+		return nullptr;
+	}
+
 	operand->expr = node;
 
 	Ast *op_expr  = se->expr;
@@ -9492,8 +9499,13 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
 		//
 		// NOTE(bill, 2020-05-22): I'm going to regret this decision, ain't I?
 
+		bool allow_arrow_right_selector_expr;
+		allow_arrow_right_selector_expr = c->allow_arrow_right_selector_expr;
+		c->allow_arrow_right_selector_expr = true;
 		Operand x = {};
 		ExprKind kind = check_expr_base(c, &x, se->expr, nullptr);
+		c->allow_arrow_right_selector_expr = allow_arrow_right_selector_expr;
+
 		if (x.mode == Addressing_Invalid || x.type == t_invalid) {
 			o->mode = Addressing_Invalid;
 			o->type = t_invalid;
@@ -9594,7 +9606,11 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
 		ce->args = modified_args;
 		se->modified_call = true;
 
+		allow_arrow_right_selector_expr = c->allow_arrow_right_selector_expr;
+		c->allow_arrow_right_selector_expr = true;
 		check_expr_base(c, o, se->call, type_hint);
+		c->allow_arrow_right_selector_expr = allow_arrow_right_selector_expr;
+
 		o->expr = node;
 		return Expr_Expr;
 	case_end;

+ 1 - 2
src/check_stmt.cpp

@@ -858,8 +858,7 @@ void check_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags) {
 		token.pos    = ast_token(ss->body).pos;
 		token.string = str_lit("true");
 
-		x.expr = gb_alloc_item(permanent_allocator(), Ast);
-		x.expr->kind = Ast_Ident;
+		x.expr = alloc_ast_node(nullptr, Ast_Ident);
 		x.expr->Ident.token = token;
 	}
 

+ 2 - 1
src/checker.hpp

@@ -45,7 +45,7 @@ enum StmtFlag {
 
 	Stmt_TypeSwitch = 1<<4,
 
-	Stmt_CheckScopeDecls    = 1<<5,
+	Stmt_CheckScopeDecls = 1<<5,
 };
 
 enum BuiltinProcPkg {
@@ -316,6 +316,7 @@ struct CheckerContext {
 	bool       no_polymorphic_errors;
 	bool       hide_polymorphic_errors;
 	bool       in_polymorphic_specialization;
+	bool       allow_arrow_right_selector_expr;
 	Scope *    polymorphic_scope;
 
 	Ast *assignment_lhs_hint;

+ 0 - 3
src/main.cpp

@@ -1876,9 +1876,6 @@ int main(int arg_count, char const **arg_ptr) {
 			SIZE_T virtual_mem_used_by_me = pmc.PrivateUsage;
 			gb_printf_err("virtual_memory_used:            %tu B\n", virtual_mem_used_by_me);
 
-			gb_printf_err("total_allocated_node_memory:    %lld B\n", total_allocated_node_memory.value);
-			gb_printf_err("total_subtype_node_memory_test: %lld B\n", total_subtype_node_memory_test.value);
-			gb_printf_err("fraction:                       %.6f\n", (f64)total_subtype_node_memory_test.value/(f64)total_allocated_node_memory.value);
 			Parser *p      = checker.parser;
 			isize lines    = p->total_line_count;
 			isize tokens   = p->total_token_count;

+ 12 - 12
src/parser.cpp

@@ -109,9 +109,6 @@ Token ast_token(Ast *node) {
 }
 
 
-gb_global gbAtomic64 total_allocated_node_memory = {0};
-gb_global gbAtomic64 total_subtype_node_memory_test = {0};
-
 isize ast_node_size(AstKind kind) {
 	return align_formula_isize(gb_size_of(AstCommonStuff) + ast_variant_sizes[kind], gb_align_of(void *));
 
@@ -122,10 +119,6 @@ Ast *alloc_ast_node(AstFile *f, AstKind kind) {
 
 	isize size = ast_node_size(kind);
 
-	gb_atomic64_fetch_add(&total_allocated_node_memory, cast(i64)(gb_size_of(Ast)));
-	gb_atomic64_fetch_add(&total_subtype_node_memory_test, cast(i64)(gb_size_of(AstCommonStuff) + ast_variant_sizes[kind]));
-
-	// Ast *node = gb_alloc_item(a, Ast);
 	Ast *node = cast(Ast *)gb_alloc(a, size);
 	node->kind = kind;
 	node->file = f;
@@ -2511,7 +2504,15 @@ Ast *parse_call_expr(AstFile *f, Ast *operand) {
 	f->expr_level--;
 	close_paren = expect_closing(f, Token_CloseParen, str_lit("argument list"));
 
-	return ast_call_expr(f, operand, args, open_paren, close_paren, ellipsis);
+
+	Ast *call = ast_call_expr(f, operand, args, open_paren, close_paren, ellipsis);
+
+	Ast *o = unparen_expr(operand);
+	if (o->kind == Ast_SelectorExpr && o->SelectorExpr.token.kind == Token_ArrowRight) {
+		return ast_selector_call_expr(f, o->SelectorExpr.token, o, call);
+	}
+
+	return call;
 }
 
 Ast *parse_atom_expr(AstFile *f, Ast *operand, bool lhs) {
@@ -2563,11 +2564,10 @@ Ast *parse_atom_expr(AstFile *f, Ast *operand, bool lhs) {
 
 		case Token_ArrowRight: {
 			Token token = advance_token(f);
-			// syntax_error(token, "Selector expressions use '.' rather than '->'");
 
-			Ast *sel = ast_selector_expr(f, token, operand, parse_ident(f));
-			Ast *call = parse_call_expr(f, sel);
-			operand = ast_selector_call_expr(f, token, sel, call);
+			operand = ast_selector_expr(f, token, operand, parse_ident(f));
+			// Ast *call = parse_call_expr(f, sel);
+			// operand = ast_selector_call_expr(f, token, sel, call);
 			break;
 		}