Browse Source

`any` type

Ginger Bill 9 years ago
parent
commit
2c4193a242
8 changed files with 261 additions and 107 deletions
  1. 39 4
      examples/demo.odin
  2. 2 10
      examples/runtime.odin
  3. 29 17
      src/checker/checker.cpp
  4. 49 64
      src/checker/expr.cpp
  5. 62 1
      src/checker/type.cpp
  6. 7 0
      src/codegen/print_llvm.cpp
  7. 71 8
      src/codegen/ssa.cpp
  8. 2 3
      src/parser.cpp

+ 39 - 4
examples/demo.odin

@@ -4,7 +4,7 @@
 
 print_type_info_kind :: proc(info: ^Type_Info) {
 	using Type_Info
-	match type i : info {
+	match type info -> i {
 	case Named:     print_string("Named\n")
 	case Integer:   print_string("Integer\n")
 	case Float:     print_string("Float\n")
@@ -23,6 +23,37 @@ print_type_info_kind :: proc(info: ^Type_Info) {
 	}
 }
 
+println :: proc(args: ..any) {
+	for i := 0; i < len(args); i++ {
+		arg := args[i]
+
+		if i > 0 {
+			print_string(" ")
+		}
+
+		using Type_Info
+		match type arg.type_info -> i {
+		case Named:     print_string("Named")
+		case Integer:   print_string("Integer")
+		case Float:     print_string("Float")
+		case String:    print_string("String")
+		case Boolean:   print_string("Boolean")
+		case Pointer:   print_string("Pointer")
+		case Procedure: print_string("Procedure")
+		case Array:     print_string("Array")
+		case Slice:     print_string("Slice")
+		case Vector:    print_string("Vector")
+		case Struct:    print_string("Struct")
+		case Union:     print_string("Union")
+		case Raw_Union: print_string("RawUnion")
+		case Enum:      print_string("Enum")
+		default:        print_string("void")
+		}
+	}
+
+	print_nl()
+}
+
 main :: proc() {
 	i: int
 	s: struct {
@@ -30,7 +61,11 @@ main :: proc() {
 	}
 	p := ^s
 
-	print_type_info_kind(type_info(i))
-	print_type_info_kind(type_info(s))
-	print_type_info_kind(type_info(p))
+	a: any = i
+
+	println(137, "Hello", 1.23)
+
+	// print_type_info_kind(a.type_info)
+	// print_type_info_kind(type_info(s))
+	// print_type_info_kind(type_info(p))
 }

+ 2 - 10
examples/runtime.odin

@@ -18,11 +18,11 @@ Type_Info :: union {
 		base: ^Type_Info
 	}
 	Integer: struct {
-		bits: int
+		size: int // in bytes
 		signed: bool
 	}
 	Float: struct {
-		bits: int
+		size: int // in bytes
 	}
 	String:  struct {}
 	Boolean: struct {}
@@ -49,14 +49,6 @@ Type_Info :: union {
 	}
 }
 
-Any :: struct {
-	type_info: ^Type_Info
-	// pointer to the data stored
-	data: rawptr
-}
-
-
-
 
 assume :: proc(cond: bool) #foreign "llvm.assume"
 

+ 29 - 17
src/checker/checker.cpp

@@ -389,23 +389,7 @@ void add_global_constant(gbAllocator a, String name, Type *type, ExactValue valu
 }
 
 
-Type *t_type_info           = NULL;
-Type *t_type_info_ptr       = NULL;
-
-Type *t_type_info_named     = NULL;
-Type *t_type_info_integer   = NULL;
-Type *t_type_info_float     = NULL;
-Type *t_type_info_string    = NULL;
-Type *t_type_info_boolean   = NULL;
-Type *t_type_info_pointer   = NULL;
-Type *t_type_info_procedure = NULL;
-Type *t_type_info_array     = NULL;
-Type *t_type_info_slice     = NULL;
-Type *t_type_info_vector    = NULL;
-Type *t_type_info_struct    = NULL;
-Type *t_type_info_union     = NULL;
-Type *t_type_info_raw_union = NULL;
-Type *t_type_info_enum      = NULL;
+
 
 
 void init_universal_scope(void) {
@@ -857,6 +841,7 @@ void check_parsed_files(Checker *c) {
 		}
 	}
 
+
 	auto check_global_entity = [](Checker *c, EntityKind kind) {
 		gb_for_array(i, c->info.entities.entries) {
 			auto *entry = &c->info.entities.entries[i];
@@ -869,6 +854,33 @@ void check_parsed_files(Checker *c) {
 	};
 
 	check_global_entity(c, Entity_TypeName);
+
+	if (t_type_info == NULL) {
+		String type_info_str = make_string("Type_Info");
+		Entity **found = map_get(&c->global_scope->elements, hash_string(type_info_str));
+		GB_ASSERT_MSG(found != NULL, "Internal Compiler Error: Could not find type declaration for `Type_Info`");
+		Entity *e = *found;
+		t_type_info = e->type;
+		t_type_info_ptr = make_type_pointer(c->allocator, t_type_info);
+
+		auto *record = &get_base_type(e->type)->Record;
+		GB_ASSERT(record->field_count == 15);
+		t_type_info_named     = record->fields[ 1]->type;
+		t_type_info_integer   = record->fields[ 2]->type;
+		t_type_info_float     = record->fields[ 3]->type;
+		t_type_info_string    = record->fields[ 4]->type;
+		t_type_info_boolean   = record->fields[ 5]->type;
+		t_type_info_pointer   = record->fields[ 6]->type;
+		t_type_info_procedure = record->fields[ 7]->type;
+		t_type_info_array     = record->fields[ 8]->type;
+		t_type_info_slice     = record->fields[ 9]->type;
+		t_type_info_vector    = record->fields[10]->type;
+		t_type_info_struct    = record->fields[11]->type;
+		t_type_info_union     = record->fields[12]->type;
+		t_type_info_raw_union = record->fields[13]->type;
+		t_type_info_enum      = record->fields[14]->type;
+	}
+
 	check_global_entity(c, Entity_Constant);
 	check_global_entity(c, Entity_Procedure);
 	check_global_entity(c, Entity_Variable);

+ 49 - 64
src/checker/expr.cpp

@@ -45,6 +45,44 @@ b32 check_is_assignable_to_using_subtype(Type *dst, Type *src) {
 	return false;
 }
 
+
+void add_type_info_type(Checker *c, Type *t) {
+	if (t == NULL) {
+		return;
+	}
+	t = default_type(t);
+	if (map_get(&c->info.type_info_types, hash_pointer(t)) != NULL) {
+		// Types have already been added
+		return;
+	}
+
+	map_set(&c->info.type_info_types, hash_pointer(t), t);
+	Type *bt = get_base_type(t);
+	switch (bt->kind) {
+	case Type_Named:   add_type_info_type(c, bt->Named.base);   break;
+	case Type_Array:   add_type_info_type(c, bt->Array.elem);   break;
+	case Type_Slice:   add_type_info_type(c, bt->Slice.elem);   break;
+	case Type_Vector:  add_type_info_type(c, bt->Vector.elem);  break;
+	case Type_Pointer: add_type_info_type(c, bt->Pointer.elem); break;
+	case Type_Record: {
+		switch (bt->Record.kind) {
+		case TypeRecord_Enum:
+			add_type_info_type(c, bt->Record.enum_base);
+			break;
+		default:
+			for (isize i = 0; i < bt->Record.field_count; i++) {
+				Entity *f = bt->Record.fields[i];
+				add_type_info_type(c, f->type);
+			}
+			break;
+		}
+	} break;
+	}
+	// TODO(bill): Type info for procedures and tuples
+	// TODO(bill): Remove duplicate identical types efficiently
+}
+
+
 b32 check_is_assignable_to(Checker *c, Operand *operand, Type *type, b32 is_argument = false) {
 	if (operand->mode == Addressing_Invalid ||
 	    type == t_invalid) {
@@ -110,6 +148,13 @@ b32 check_is_assignable_to(Checker *c, Operand *operand, Type *type, b32 is_argu
 		}
 	}
 
+
+	if (dst == t_any) {
+		// NOTE(bill): Anything can cast to `Any`
+		add_type_info_type(c, s);
+		return true;
+	}
+
 	if (is_argument) {
 		// NOTE(bill): Polymorphism for subtyping
 		if (check_is_assignable_to_using_subtype(type, src)) {
@@ -133,11 +178,13 @@ void check_assignment(Checker *c, Operand *operand, Type *type, String context_n
 	if (is_type_untyped(operand->type)) {
 		Type *target_type = type;
 
-		if (type == NULL)
+		if (type == NULL || is_type_any(type)) {
 			target_type = default_type(operand->type);
+		}
 		convert_to_typed(c, operand, target_type);
-		if (operand->mode == Addressing_Invalid)
+		if (operand->mode == Addressing_Invalid) {
 			return;
+		}
 	}
 
 
@@ -1900,42 +1947,6 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node) {
 	return NULL;
 }
 
-void add_type_info_type(Checker *c, Type *t) {
-	if (t == NULL) {
-		return;
-	}
-	t = default_type(t);
-	if (map_get(&c->info.type_info_types, hash_pointer(t)) != NULL) {
-		// Types have already been added
-		return;
-	}
-
-	map_set(&c->info.type_info_types, hash_pointer(t), t);
-	Type *bt = get_base_type(t);
-	switch (bt->kind) {
-	case Type_Named:   add_type_info_type(c, bt->Named.base);   break;
-	case Type_Array:   add_type_info_type(c, bt->Array.elem);   break;
-	case Type_Slice:   add_type_info_type(c, bt->Slice.elem);   break;
-	case Type_Vector:  add_type_info_type(c, bt->Vector.elem);  break;
-	case Type_Pointer: add_type_info_type(c, bt->Pointer.elem); break;
-	case Type_Record: {
-		switch (bt->Record.kind) {
-		case TypeRecord_Enum:
-			add_type_info_type(c, bt->Record.enum_base);
-			break;
-		default:
-			for (isize i = 0; i < bt->Record.field_count; i++) {
-				Entity *f = bt->Record.fields[i];
-				add_type_info_type(c, f->type);
-			}
-			break;
-		}
-	} break;
-	}
-	// TODO(bill): Type info for procedures and tuples
-	// TODO(bill): Remove duplicate identical types efficiently
-}
-
 b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) {
 	GB_ASSERT(call->kind == AstNode_CallExpr);
 	ast_node(ce, CallExpr, call);
@@ -2690,32 +2701,6 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
 
 
 	case BuiltinProc_type_info: {
-		if (t_type_info == NULL) {
-			String type_info_str = make_string("Type_Info");
-			Entity **found = map_get(&c->global_scope->elements, hash_string(type_info_str));
-			GB_ASSERT_MSG(found != NULL, "Internal Compiler Error: Could not find type declaration for `Type_Info`");
-			Entity *e = *found;
-			t_type_info = e->type;
-			t_type_info_ptr = make_type_pointer(c->allocator, t_type_info);
-
-			auto *record = &get_base_type(e->type)->Record;
-			GB_ASSERT(record->field_count == 15);
-			t_type_info_named     = record->fields[ 1]->type;
-			t_type_info_integer   = record->fields[ 2]->type;
-			t_type_info_float     = record->fields[ 3]->type;
-			t_type_info_string    = record->fields[ 4]->type;
-			t_type_info_boolean   = record->fields[ 5]->type;
-			t_type_info_pointer   = record->fields[ 6]->type;
-			t_type_info_procedure = record->fields[ 7]->type;
-			t_type_info_array     = record->fields[ 8]->type;
-			t_type_info_slice     = record->fields[ 9]->type;
-			t_type_info_vector    = record->fields[10]->type;
-			t_type_info_struct    = record->fields[11]->type;
-			t_type_info_union     = record->fields[12]->type;
-			t_type_info_raw_union = record->fields[13]->type;
-			t_type_info_enum      = record->fields[14]->type;
-		}
-
 		add_type_info_type(c, operand->type);
 		operand->mode = Addressing_Value;
 		operand->type = t_type_info_ptr;

+ 62 - 1
src/checker/type.cpp

@@ -19,6 +19,9 @@ enum BasicKind {
 	Basic_uint,
 	Basic_rawptr,
 	Basic_string,
+
+	Basic_any,
+
 	Basic_UntypedBool,
 	Basic_UntypedInteger,
 	Basic_UntypedFloat,
@@ -26,6 +29,7 @@ enum BasicKind {
 	Basic_UntypedString,
 	Basic_UntypedRune,
 
+
 	Basic_Count,
 
 	Basic_byte = Basic_u8,
@@ -306,6 +310,7 @@ gb_global Type basic_types[] = {
 	{0, Type_Basic, {Basic_uint,           BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("uint")}},
 	{0, Type_Basic, {Basic_rawptr,         BasicFlag_Pointer,                      STR_LIT("rawptr")}},
 	{0, Type_Basic, {Basic_string,         BasicFlag_String,                       STR_LIT("string")}},
+	{0, Type_Basic, {Basic_any,            0,                                      STR_LIT("any")}},
 	{0, Type_Basic, {Basic_UntypedBool,    BasicFlag_Boolean | BasicFlag_Untyped,  STR_LIT("untyped bool")}},
 	{0, Type_Basic, {Basic_UntypedInteger, BasicFlag_Integer | BasicFlag_Untyped,  STR_LIT("untyped integer")}},
 	{0, Type_Basic, {Basic_UntypedFloat,   BasicFlag_Float   | BasicFlag_Untyped,  STR_LIT("untyped float")}},
@@ -337,6 +342,7 @@ gb_global Type *t_int             = &basic_types[Basic_int];
 gb_global Type *t_uint            = &basic_types[Basic_uint];
 gb_global Type *t_rawptr          = &basic_types[Basic_rawptr];
 gb_global Type *t_string          = &basic_types[Basic_string];
+gb_global Type *t_any             = &basic_types[Basic_any];
 gb_global Type *t_untyped_bool    = &basic_types[Basic_UntypedBool];
 gb_global Type *t_untyped_integer = &basic_types[Basic_UntypedInteger];
 gb_global Type *t_untyped_float   = &basic_types[Basic_UntypedFloat];
@@ -346,6 +352,25 @@ gb_global Type *t_untyped_rune    = &basic_types[Basic_UntypedRune];
 gb_global Type *t_byte            = &basic_type_aliases[Basic_byte];
 gb_global Type *t_rune            = &basic_type_aliases[Basic_rune];
 
+gb_global Type *t_type_info           = NULL;
+gb_global Type *t_type_info_ptr       = NULL;
+
+gb_global Type *t_type_info_named     = NULL;
+gb_global Type *t_type_info_integer   = NULL;
+gb_global Type *t_type_info_float     = NULL;
+gb_global Type *t_type_info_string    = NULL;
+gb_global Type *t_type_info_boolean   = NULL;
+gb_global Type *t_type_info_pointer   = NULL;
+gb_global Type *t_type_info_procedure = NULL;
+gb_global Type *t_type_info_array     = NULL;
+gb_global Type *t_type_info_slice     = NULL;
+gb_global Type *t_type_info_vector    = NULL;
+gb_global Type *t_type_info_struct    = NULL;
+gb_global Type *t_type_info_union     = NULL;
+gb_global Type *t_type_info_raw_union = NULL;
+gb_global Type *t_type_info_enum      = NULL;
+
+
 
 b32 is_type_named(Type *t) {
 	if (t->kind == Type_Basic)
@@ -488,6 +513,11 @@ Type *get_enum_base_type(Type *t) {
 	return t;
 }
 
+b32 is_type_any(Type *t) {
+	t = get_base_type(t);
+	return (t->kind == Type_Basic && t->Basic.kind == Basic_any);
+}
+
 
 
 b32 is_type_comparable(Type *t) {
@@ -675,6 +705,9 @@ void selection_add_index(Selection *s, isize index) {
 	gb_array_append(s->index, index);
 }
 
+gb_global Entity *entity_any_type_info = NULL;
+gb_global Entity *entity_any_data      = NULL;
+
 Selection lookup_field(Type *type_, String field_name, b32 is_type, Selection sel = empty_selection) {
 	GB_ASSERT(type_ != NULL);
 
@@ -686,11 +719,39 @@ Selection lookup_field(Type *type_, String field_name, b32 is_type, Selection se
 	b32 is_ptr = type != type_;
 	type = get_base_type(type);
 
+	if (type->kind == Type_Basic) {
+		if (type->Basic.kind == Basic_any) {
+			String type_info_str = make_string("type_info");
+			String data_str = make_string("data_str");
+			if (entity_any_type_info == NULL) {
+				Token token = {Token_Identifier};
+				token.string = type_info_str;
+				entity_any_type_info = make_entity_field(gb_heap_allocator(), NULL, token, t_type_info_ptr, false);
+			}
+			if (entity_any_data == NULL) {
+				Token token = {Token_Identifier};
+				token.string = data_str;
+				entity_any_data = make_entity_field(gb_heap_allocator(), NULL, token, t_type_info_ptr, false);
+			}
+
+			if (are_strings_equal(field_name, type_info_str)) {
+				selection_add_index(&sel, 0);
+				sel.entity = entity_any_type_info;
+				return sel;
+			} else if (are_strings_equal(field_name, data_str)) {
+				selection_add_index(&sel, 1);
+				sel.entity = entity_any_data;
+				return sel;
+			}
+		}
+
+		return sel;
+	}
+
 	if (type->kind != Type_Record) {
 		return sel;
 	}
 	if (is_type) {
-
 		if (is_type_union(type)) {
 			for (isize i = 0; i < type->Record.field_count; i++) {
 				Entity *f = type->Record.fields[i];

+ 7 - 0
src/codegen/print_llvm.cpp

@@ -153,6 +153,13 @@ void ssa_print_type(ssaFileBuffer *f, BaseTypeSizes s, Type *t) {
 		case Basic_string: ssa_fprintf(f, "%%..string");              break;
 		case Basic_uint:   ssa_fprintf(f, "i%lld", word_bits);        break;
 		case Basic_int:    ssa_fprintf(f, "i%lld", word_bits);        break;
+		case Basic_any:
+			ssa_fprintf(f, "{");
+			ssa_print_type(f, s, t_type_info_ptr);
+			ssa_fprintf(f, ", ");
+			ssa_print_type(f, s, t_rawptr);
+			ssa_fprintf(f, "}");
+			break;
 		}
 		break;
 	case Type_Array:

+ 71 - 8
src/codegen/ssa.cpp

@@ -1053,9 +1053,26 @@ ssaValue *ssa_emit_deep_field_gep(ssaProcedure *proc, Type *type, ssaValue *e, S
 		if (is_type_raw_union(type)) {
 			type = type->Record.fields[index]->type;
 			e = ssa_emit_conv(proc, e, make_type_pointer(proc->module->allocator, type));
-		} else {
+		} else if (type->kind == Type_Record) {
 			type = type->Record.fields[index]->type;
 			e = ssa_emit_struct_gep(proc, e, index, make_type_pointer(proc->module->allocator, type));
+		} else if (type->kind == Type_Basic) {
+			switch (type->Basic.kind) {
+			case Basic_any: {
+				if (index == 0) {
+					type = t_type_info_ptr;
+				} else if (index == 1) {
+					type = t_rawptr;
+				}
+				e = ssa_emit_struct_gep(proc, e, index, make_type_pointer(proc->module->allocator, type));
+			} break;
+
+			default:
+				GB_PANIC("un-gep-able type");
+				break;
+			}
+		} else {
+			GB_PANIC("un-gep-able type");
 		}
 	}
 
@@ -1079,9 +1096,26 @@ ssaValue *ssa_emit_deep_field_ev(ssaProcedure *proc, Type *type, ssaValue *e, Se
 		if (is_type_raw_union(type)) {
 			type = type->Record.fields[index]->type;
 			e = ssa_emit_conv(proc, e, make_type_pointer(proc->module->allocator, type));
-		} else {
+		} else if (type->kind == Type_Record) {
 			type = type->Record.fields[index]->type;
 			e = ssa_emit_struct_ev(proc, e, index, type);
+		} else if (type->kind == Type_Basic) {
+			switch (type->Basic.kind) {
+			case Basic_any: {
+				if (index == 0) {
+					type = t_type_info_ptr;
+				} else if (index == 1) {
+					type = t_rawptr;
+				}
+				e = ssa_emit_struct_ev(proc, e, index, type);
+			} break;
+
+			default:
+				GB_PANIC("un-ev-able type");
+				break;
+			}
+		} else {
+			GB_PANIC("un-ev-able type");
 		}
 	}
 
@@ -1303,12 +1337,17 @@ ssaValue *ssa_emit_conv(ssaProcedure *proc, ssaValue *value, Type *t, b32 is_arg
 	}
 
 	if (value->kind == ssaValue_Constant) {
-		if (dst->kind == Type_Basic) {
+		if (is_type_any(dst)) {
+			Type *dt = default_type(src);
+			ssaValue *default_value = ssa_add_local_generated(proc, dt);
+			ssa_emit_store(proc, default_value, value);
+			return ssa_emit_conv(proc, ssa_emit_load(proc, default_value), t_any, is_argument);
+		} else if (dst->kind == Type_Basic) {
 			ExactValue ev = value->Constant.value;
 			if (is_type_float(dst)) {
 				ev = exact_value_to_float(ev);
 			} else if (is_type_string(dst)) {
-				//
+				// Handled elsewhere
 			} else if (is_type_integer(dst)) {
 				ev = exact_value_to_integer(ev);
 			} else if (is_type_pointer(dst)) {
@@ -1487,6 +1526,33 @@ ssaValue *ssa_emit_conv(ssaProcedure *proc, ssaValue *value, Type *t, b32 is_arg
 		return v;
 	}
 
+	if (is_type_any(dst)) {
+		ssaValue **found = map_get(&proc->module->members, hash_string(make_string("__type_info_data")));
+		GB_ASSERT(found != NULL);
+		ssaValue *type_info_data = *found;
+		CheckerInfo *info = proc->module->info;
+
+
+		ssaValue *result = ssa_add_local_generated(proc, t_any);
+
+		// NOTE(bill): Make copy on stack so I can reference it later
+		ssaValue *data = ssa_add_local_generated(proc, src_type);
+		ssa_emit_store(proc, data, value);
+		data = ssa_emit_conv(proc, data, t_rawptr);
+
+
+		MapFindResult fr = map__find(&info->type_info_types, hash_pointer(src_type));
+		GB_ASSERT(fr.entry_index >= 0);
+		ssaValue *ti = ssa_emit_struct_gep(proc, type_info_data, fr.entry_index, t_type_info_ptr);
+
+		ssaValue *gep0 = ssa_emit_struct_gep(proc, result, v_zero32, make_type_pointer(proc->module->allocator, t_type_info_ptr));
+		ssaValue *gep1 = ssa_emit_struct_gep(proc, result, v_one32,  make_type_pointer(proc->module->allocator, t_rawptr));
+		ssa_emit_store(proc, gep0, ti);
+		ssa_emit_store(proc, gep1, data);
+
+		return ssa_emit_load(proc, result);
+	}
+
 
 	gb_printf_err("Not Identical %s != %s\n", type_to_string(src_type), type_to_string(t));
 	gb_printf_err("Not Identical %s != %s\n", type_to_string(src), type_to_string(dst));
@@ -3194,10 +3260,7 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
 		ssaBlock *default_block = NULL;
 
 		isize case_count = body->list_count;
-		isize i = 0;
-		for (AstNode *clause = body->list;
-		     clause != NULL;
-		     clause = clause->next, i++) {
+		for (AstNode *clause = body->list; clause != NULL; clause = clause->next) {
 			ast_node(cc, CaseClause, clause);
 
 			if (cc->list == NULL) {

+ 2 - 3
src/parser.cpp

@@ -2297,9 +2297,9 @@ AstNode *parse_match_stmt(AstFile *f) {
 	Token open, close;
 
 	if (allow_token(f, Token_type)) {
+		tag = parse_expr(f, true);
+		expect_token(f, Token_ArrowRight);
 		AstNode *var = parse_identifier(f);
-		expect_token(f, Token_Colon);
-		tag = parse_simple_stmt(f);
 
 		open = expect_token(f, Token_OpenBrace);
 		AstNode *list = NULL;
@@ -2315,7 +2315,6 @@ AstNode *parse_match_stmt(AstFile *f) {
 		close = expect_token(f, Token_CloseBrace);
 		body = make_block_stmt(f, list, list_count, open, close);
 
-		tag = convert_stmt_to_expr(f, tag, make_string("type match expression"));
 		return make_type_match_stmt(f, token, tag, var, body);
 	} else {
 		if (f->cursor[0].kind != Token_OpenBrace) {