Browse Source

Make `AstNodeIdent` a struct wrapping its `Token`

Ginger Bill 8 years ago
parent
commit
d167290b28
8 changed files with 60 additions and 58 deletions
  1. 1 1
      src/check_decl.cpp
  2. 29 29
      src/check_expr.cpp
  3. 9 9
      src/check_stmt.cpp
  4. 6 6
      src/checker.cpp
  5. 7 7
      src/ir.cpp
  6. 1 1
      src/ir_print.cpp
  7. 5 3
      src/parser.cpp
  8. 2 2
      src/ssa.cpp

+ 1 - 1
src/check_decl.cpp

@@ -291,7 +291,7 @@ void init_entity_foreign_library(Checker *c, Entity *e) {
 	} else if (ident->kind != AstNode_Ident) {
 		error(ident, "foreign library names must be an identifier");
 	} else {
-		String name = ident->Ident.string;
+		String name = ident->Ident.token.string;
 		Entity *found = scope_lookup_entity(c->context.scope, name);
 		if (found == NULL) {
 			if (name == "_") {

+ 29 - 29
src/check_expr.cpp

@@ -469,7 +469,7 @@ isize check_fields(Checker *c, AstNode *node, Array<AstNode *> decls,
 				continue;
 			}
 
-			Token name_token = name->Ident;
+			Token name_token = name->Ident.token;
 
 			Entity *e = make_entity_field(c->allocator, c->context.scope, name_token, type, is_using, cast(i32)field_index);
 			e->identifier = name;
@@ -501,7 +501,7 @@ isize check_fields(Checker *c, AstNode *node, Array<AstNode *> decls,
 			if (!is_type_struct(t) && !is_type_raw_union(t) && !is_type_bit_field(t) &&
 			    f->names.count >= 1 &&
 			    f->names[0]->kind == AstNode_Ident) {
-				Token name_token = f->names[0]->Ident;
+				Token name_token = f->names[0]->Ident.token;
 				if (is_type_indexable(t)) {
 					bool ok = true;
 					for_array(emi, entity_map.entries) {
@@ -731,7 +731,7 @@ void check_union_type(Checker *c, Type *named_type, Type *union_type, AstNode *n
 			continue;
 		}
 		ast_node(f, UnionField, variant);
-		Token name_token = f->name->Ident;
+		Token name_token = f->name->Ident.token;
 
 		Type *base_type = make_type_struct(c->allocator);
 		{
@@ -883,7 +883,7 @@ void check_enum_type(Checker *c, Type *enum_type, Type *named_type, AstNode *nod
 			error(field, "An enum field's name must be an identifier");
 			continue;
 		}
-		String name = ident->Ident.string;
+		String name = ident->Ident.token.string;
 
 		if (init != NULL) {
 			Operand o = {};
@@ -932,7 +932,7 @@ void check_enum_type(Checker *c, Type *enum_type, Type *named_type, AstNode *nod
 			max_value = iota;
 		}
 
-		Entity *e = make_entity_constant(c->allocator, c->context.scope, ident->Ident, constant_type, iota);
+		Entity *e = make_entity_constant(c->allocator, c->context.scope, ident->Ident.token, constant_type, iota);
 		e->identifier = ident;
 		e->flags |= EntityFlag_Visited;
 
@@ -990,7 +990,7 @@ void check_bit_field_type(Checker *c, Type *bit_field_type, Type *named_type, As
 			error(field, "A bit field value's name must be an identifier");
 			continue;
 		}
-		String name = ident->Ident.string;
+		String name = ident->Ident.token.string;
 
 		Operand o = {};
 		check_expr(c, &o, value);
@@ -1010,7 +1010,7 @@ void check_bit_field_type(Checker *c, Type *bit_field_type, Type *named_type, As
 		}
 
 		Type *value_type = make_type_bit_field_value(c->allocator, bits);
-		Entity *e = make_entity_variable(c->allocator, bit_field_type->BitField.scope, ident->Ident, value_type, false);
+		Entity *e = make_entity_variable(c->allocator, bit_field_type->BitField.scope, ident->Ident.token, value_type, false);
 		e->identifier = ident;
 		e->flags |= EntityFlag_BitFieldValue;
 
@@ -1235,10 +1235,10 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_vari
 			if (ast_node_expect(name, AstNode_Ident)) {
 				Entity *param = NULL;
 				if (is_type_param) {
-					param = make_entity_type_name(c->allocator, scope, name->Ident, type);
+					param = make_entity_type_name(c->allocator, scope, name->Ident.token, type);
 					param->TypeName.is_type_alias = true;
 				} else {
-					param = make_entity_param(c->allocator, scope, name->Ident, type,
+					param = make_entity_param(c->allocator, scope, name->Ident.token, type,
 					                          (p->flags&FieldFlag_using) != 0, false);
 					param->Variable.default_value = value;
 					param->Variable.default_is_nil = default_is_nil;
@@ -1367,7 +1367,7 @@ Type *check_get_results(Checker *c, Scope *scope, AstNode *_results) {
 				if (name->kind != AstNode_Ident) {
 					error(name, "Expected an identifer for as the field name");
 				} else {
-					token = name->Ident;
+					token = name->Ident.token;
 				}
 
 				Entity *param = make_entity_param(c->allocator, scope, token, type, false, false);
@@ -1653,14 +1653,14 @@ Entity *check_ident(Checker *c, Operand *o, AstNode *n, Type *named_type, Type *
 	GB_ASSERT(n->kind == AstNode_Ident);
 	o->mode = Addressing_Invalid;
 	o->expr = n;
-	String name = n->Ident.string;
+	String name = n->Ident.token.string;
 
 	Entity *e = scope_lookup_entity(c->context.scope, name);
 	if (e == NULL) {
 		if (name == "_") {
-			error(n->Ident, "`_` cannot be used as a value type");
+			error(n, "`_` cannot be used as a value type");
 		} else {
-			error(n->Ident, "Undeclared name: %.*s", LIT(name));
+			error(n, "Undeclared name: %.*s", LIT(name));
 		}
 		o->type = t_invalid;
 		o->mode = Addressing_Invalid;
@@ -1672,10 +1672,10 @@ Entity *check_ident(Checker *c, Operand *o, AstNode *n, Type *named_type, Type *
 	if (e->parent_proc_decl != NULL &&
 	    e->parent_proc_decl != c->context.curr_proc_decl) {
 		if (e->kind == Entity_Variable) {
-			error(n->Ident, "Nested procedures do not capture its parent's variables: %.*s", LIT(name));
+			error(n, "Nested procedures do not capture its parent's variables: %.*s", LIT(name));
 			return NULL;
 		} else if (e->kind == Entity_Label) {
-			error(n->Ident, "Nested procedures do not capture its parent's labels: %.*s", LIT(name));
+			error(n, "Nested procedures do not capture its parent's labels: %.*s", LIT(name));
 			return NULL;
 		}
 	}
@@ -3529,7 +3529,7 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h
 	}
 
 	if (op_expr->kind == AstNode_Ident) {
-		String op_name = op_expr->Ident.string;
+		String op_name = op_expr->Ident.token.string;
 		Entity *e = scope_lookup_entity(c->context.scope, op_name);
 
 		add_entity_use(c, op_expr, e);
@@ -3542,7 +3542,7 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h
 			// If you can clean this up, please do but be really careful
 			String import_name = op_name;
 			Scope *import_scope = e->ImportName.scope;
-			String entity_name = selector->Ident.string;
+			String entity_name = selector->Ident.token.string;
 
 			check_op_expr = false;
 			entity = scope_lookup_entity(import_scope, entity_name);
@@ -3641,7 +3641,7 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h
 
 
 	if (entity == NULL && selector->kind == AstNode_Ident) {
-		String field_name = selector->Ident.string;
+		String field_name = selector->Ident.token.string;
 		sel = lookup_field(c->allocator, operand->type, field_name, operand->mode == Addressing_Type);
 
 		if (operand->mode != Addressing_Type && !check_is_field_exported(c, sel.entity)) {
@@ -4236,18 +4236,18 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
 
 
 		ast_node(arg, Ident, field_arg);
-		Selection sel = lookup_field(c->allocator, type, arg->string, operand->mode == Addressing_Type);
+		Selection sel = lookup_field(c->allocator, type, arg->token.string, operand->mode == Addressing_Type);
 		if (sel.entity == NULL) {
 			gbString type_str = type_to_string(bt);
 			error(ce->args[0],
-			      "`%s` has no field named `%.*s`", type_str, LIT(arg->string));
+			      "`%s` has no field named `%.*s`", type_str, LIT(arg->token.string));
 			gb_string_free(type_str);
 			return false;
 		}
 		if (sel.indirect) {
 			gbString type_str = type_to_string(bt);
 			error(ce->args[0],
-			      "Field `%.*s` is embedded via a pointer in `%s`", LIT(arg->string), type_str);
+			      "Field `%.*s` is embedded via a pointer in `%s`", LIT(arg->token.string), type_str);
 			gb_string_free(type_str);
 			return false;
 		}
@@ -5045,7 +5045,7 @@ Entity *find_or_generate_polymorphic_procedure(Checker *c, Entity *base_entity,
 
 	u64 tags = base_entity->Procedure.tags;
 	AstNode *ident = clone_ast_node(a, base_entity->identifier);
-	Token token = ident->Ident;
+	Token token = ident->Ident.token;
 	DeclInfo *d = make_declaration_info(c->allocator, c->context.scope, old_decl->parent);
 	d->gen_proc_type = final_proc_type;
 	d->type_expr = pl->type;
@@ -5136,14 +5136,14 @@ CALL_ARGUMENT_CHECKER(check_call_arguments_internal) {
 		if (show_error) {
 			error(ce->ellipsis,
 			      "Cannot use `..` in call to a non-variadic procedure: `%.*s`",
-			      LIT(ce->proc->Ident.string));
+			      LIT(ce->proc->Ident.token.string));
 		}
 		err = CallArgumentError_NonVariadicExpand;
 	} else if (vari_expand && pt->c_vararg) {
 		if (show_error) {
 			error(ce->ellipsis,
 			      "Cannot use `..` in call to a `#c_vararg` variadic procedure: `%.*s`",
-			      LIT(ce->proc->Ident.string));
+			      LIT(ce->proc->Ident.token.string));
 		}
 		err = CallArgumentError_NonVariadicExpand;
 	} else if (operands.count == 0 && param_count_excluding_defaults == 0) {
@@ -5341,7 +5341,7 @@ CALL_ARGUMENT_CHECKER(check_named_call_arguments) {
 			err = CallArgumentError_InvalidFieldValue;
 			continue;
 		}
-		String name = fv->field->Ident.string;
+		String name = fv->field->Ident.token.string;
 		isize index = lookup_procedure_parameter(pt, name);
 		if (index < 0) {
 			if (show_error) {
@@ -6084,7 +6084,7 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t
 							gb_string_free(expr_str);
 							continue;
 						}
-						String name = fv->field->Ident.string;
+						String name = fv->field->Ident.token.string;
 
 						Selection sel = lookup_field(c->allocator, type, name, o->mode == Addressing_Type);
 						bool is_unknown = sel.entity == NULL;
@@ -6281,7 +6281,7 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t
 							gb_string_free(expr_str);
 							continue;
 						}
-						String name = fv->field->Ident.string;
+						String name = fv->field->Ident.token.string;
 
 						Selection sel = lookup_field(c->allocator, type, name, o->mode == Addressing_Type);
 						if (sel.entity == NULL) {
@@ -6853,7 +6853,7 @@ gbString write_expr_to_string(gbString str, AstNode *node) {
 		break;
 
 	case_ast_node(i, Ident, node);
-		str = string_append_token(str, *i);
+		str = string_append_token(str, i->token);
 	case_end;
 
 	case_ast_node(i, Implicit, node);
@@ -7030,7 +7030,7 @@ gbString write_expr_to_string(gbString str, AstNode *node) {
 			}
 			AstNode *name = field->names[0];
 			ast_node(n, Ident, name);
-			if (n->string != "_") {
+			if (n->token.string != "_") {
 				has_name = true;
 				break;
 			}

+ 9 - 9
src/check_stmt.cpp

@@ -187,7 +187,7 @@ Type *check_assignment_variable(Checker *c, Operand *rhs, AstNode *lhs_node) {
 
 	// NOTE(bill): Ignore assignments to `_`
 	if (node->kind == AstNode_Ident &&
-	    node->Ident.string == "_") {
+	    node->Ident.token.string == "_") {
 		add_entity_definition(&c->info, node, NULL);
 		check_assignment(c, rhs, NULL, str_lit("assignment to `_` identifier"));
 		if (rhs->mode == Addressing_Invalid) {
@@ -238,7 +238,7 @@ Type *check_assignment_variable(Checker *c, Operand *rhs, AstNode *lhs_node) {
 	} else {
 		if (node->kind == AstNode_Ident) {
 			ast_node(i, Ident, node);
-			e = scope_lookup_entity(c->context.scope, i->string);
+			e = scope_lookup_entity(c->context.scope, i->token.string);
 			if (e != NULL && e->kind == Entity_Variable) {
 				used = (e->flags & EntityFlag_Used) != 0; // TODO(bill): Make backup just in case
 			}
@@ -428,7 +428,7 @@ void check_label(Checker *c, AstNode *label) {
 		error(l->name, "A label's name must be an identifier");
 		return;
 	}
-	String name = l->name->Ident.string;
+	String name = l->name->Ident.token.string;
 	if (name == "_") {
 		error(l->name, "A label's name cannot be a blank identifier");
 		return;
@@ -451,7 +451,7 @@ void check_label(Checker *c, AstNode *label) {
 		}
 	}
 
-	Entity *e = make_entity_label(c->allocator, c->context.scope, l->name->Ident, t_invalid, label);
+	Entity *e = make_entity_label(c->allocator, c->context.scope, l->name->Ident.token, t_invalid, label);
 	add_entity(c, c->context.scope, l->name, e);
 	e->parent_proc_decl = c->context.curr_proc_decl;
 
@@ -862,7 +862,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 					gb_string_free(expr_str);
 					continue;
 				}
-				String name = fv->field->Ident.string;
+				String name = fv->field->Ident.token.string;
 				isize index = lookup_procedure_result(pt, name);
 				if (index < 0) {
 					error(arg, "No result named `%.*s` for this procedure type", LIT(name));
@@ -1127,7 +1127,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 
 			Entity *entity = NULL;
 			if (name->kind == AstNode_Ident) {
-				Token token = name->Ident;
+				Token token = name->Ident.token;
 				String str = token.string;
 				Entity *found = NULL;
 
@@ -1523,7 +1523,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 
 			check_open_scope(c, stmt);
 			{
-				Entity *tag_var = make_entity_variable(c->allocator, c->context.scope, lhs->Ident, case_type, false);
+				Entity *tag_var = make_entity_variable(c->allocator, c->context.scope, lhs->Ident.token, case_type, false);
 				tag_var->flags |= EntityFlag_Used;
 				tag_var->flags |= EntityFlag_Value;
 				add_entity(c, c->context.scope, lhs, tag_var);
@@ -1579,7 +1579,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 				return;
 			}
 			AstNode *ident = bs->label;
-			String name = ident->Ident.string;
+			String name = ident->Ident.token.string;
 			Operand o = {};
 			Entity *e = check_ident(c, &o, ident, NULL, NULL, false);
 			if (e == NULL) {
@@ -1678,7 +1678,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 				if (name->kind != AstNode_Ident) {
 					error(name, "A variable declaration must be an identifier");
 				} else {
-					Token token = name->Ident;
+					Token token = name->Ident.token;
 					String str = token.string;
 					Entity *found = NULL;
 					// NOTE(bill): Ignore assignments to `_`

+ 6 - 6
src/checker.cpp

@@ -944,7 +944,7 @@ void add_type_and_value(CheckerInfo *i, AstNode *expression, AddressingMode mode
 void add_entity_definition(CheckerInfo *i, AstNode *identifier, Entity *entity) {
 	GB_ASSERT(identifier != NULL);
 	if (identifier->kind == AstNode_Ident) {
-		if (identifier->Ident.string == "_") {
+		if (identifier->Ident.token.string == "_") {
 			return;
 		}
 		HashKey key = hash_node(identifier);
@@ -1009,7 +1009,7 @@ void add_entity_use(Checker *c, AstNode *identifier, Entity *entity) {
 void add_entity_and_decl_info(Checker *c, AstNode *identifier, Entity *e, DeclInfo *d) {
 	GB_ASSERT(identifier->kind == AstNode_Ident);
 	GB_ASSERT(e != NULL && d != NULL);
-	GB_ASSERT(identifier->Ident.string == e->token.string);
+	GB_ASSERT(identifier->Ident.token.string == e->token.string);
 	if (e->scope != NULL) add_entity(c, e->scope, identifier, e);
 	add_entity_definition(&c->info, identifier, e);
 	map_set(&c->info.entities, hash_entity(e), d);
@@ -1627,7 +1627,7 @@ void check_collect_entities(Checker *c, Array<AstNode *> nodes, bool is_file_sco
 						error(name, "A declaration's name must be an identifier, got %.*s", LIT(ast_node_strings[name->kind]));
 						continue;
 					}
-					Entity *e = make_entity_variable(c->allocator, c->context.scope, name->Ident, NULL, false);
+					Entity *e = make_entity_variable(c->allocator, c->context.scope, name->Ident.token, NULL, false);
 					e->Variable.is_thread_local = (vd->flags & VarDeclFlag_thread_local) != 0;
 					e->identifier = name;
 
@@ -1680,12 +1680,12 @@ void check_collect_entities(Checker *c, Array<AstNode *> nodes, bool is_file_sco
 					Entity *e = NULL;
 
 					if (is_ast_node_type(init)) {
-						e = make_entity_type_name(c->allocator, d->scope, name->Ident, NULL);
+						e = make_entity_type_name(c->allocator, d->scope, name->Ident.token, NULL);
 						d->type_expr = init;
 						d->init_expr = init;
 					} else if (init->kind == AstNode_ProcLit) {
 						ast_node(pl, ProcLit, init);
-						e = make_entity_procedure(c->allocator, d->scope, name->Ident, NULL, pl->tags);
+						e = make_entity_procedure(c->allocator, d->scope, name->Ident.token, NULL, pl->tags);
 						if (fl != NULL) {
 							GB_ASSERT(fl->kind == AstNode_Ident);
 							e->Procedure.foreign_library_ident = fl;
@@ -1694,7 +1694,7 @@ void check_collect_entities(Checker *c, Array<AstNode *> nodes, bool is_file_sco
 						d->proc_lit = init;
 						d->type_expr = pl->type;
 					} else {
-						e = make_entity_constant(c->allocator, d->scope, name->Ident, NULL, empty_exact_value);
+						e = make_entity_constant(c->allocator, d->scope, name->Ident.token, NULL, empty_exact_value);
 						d->type_expr = vd->type;
 						d->init_expr = init;
 					}

+ 7 - 7
src/ir.cpp

@@ -656,7 +656,7 @@ Type *ir_type(irValue *value) {
 bool ir_is_blank_ident(AstNode *node) {
 	if (node->kind == AstNode_Ident) {
 		ast_node(i, Ident, node);
-		return is_blank_ident(i->string);
+		return is_blank_ident(i->token.string);
 	}
 	return false;
 }
@@ -4452,7 +4452,7 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) {
 		} else if (e != NULL && e->kind == Entity_Variable) {
 			return ir_addr_load(proc, ir_build_addr(proc, expr));
 		}
-		GB_PANIC("NULL value for expression from identifier: %.*s @ %p", LIT(i->string), expr);
+		GB_PANIC("NULL value for expression from identifier: %.*s @ %p", LIT(i->token.string), expr);
 		return NULL;
 	case_end;
 
@@ -4672,7 +4672,7 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) {
 				AstNode *arg = ce->args[arg_index];
 				ast_node(fv, FieldValue, arg);
 				GB_ASSERT(fv->field->kind == AstNode_Ident);
-				String name = fv->field->Ident.string;
+				String name = fv->field->Ident.token.string;
 				isize index = lookup_procedure_parameter(type, name);
 				GB_ASSERT(index >= 0);
 				irValue *expr = ir_build_expr(proc, fv->value);
@@ -4928,7 +4928,7 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
 		ir_emit_comment(proc, str_lit("SelectorExpr"));
 		AstNode *sel = unparen_expr(se->selector);
 		if (sel->kind == AstNode_Ident) {
-			String selector = sel->Ident.string;
+			String selector = sel->Ident.token.string;
 			TypeAndValue tav = type_and_value_of_expr(proc->module->info, se->expr);
 
 			if (tav.mode == Addressing_Invalid) {
@@ -5344,7 +5344,7 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
 
 					if (elem->kind == AstNode_FieldValue) {
 						ast_node(fv, FieldValue, elem);
-						String name = fv->field->Ident.string;
+						String name = fv->field->Ident.token.string;
 						Selection sel = lookup_field(proc->module->allocator, bt, name, false);
 						index = sel.index[0];
 						elem = fv->value;
@@ -5499,7 +5499,7 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
 
 					if (elem->kind == AstNode_FieldValue) {
 						ast_node(fv, FieldValue, elem);
-						Selection sel = lookup_field(proc->module->allocator, bt, fv->field->Ident.string, false);
+						Selection sel = lookup_field(proc->module->allocator, bt, fv->field->Ident.token.string, false);
 						index = sel.index[0];
 						elem = fv->value;
 					} else {
@@ -6184,7 +6184,7 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
 				AstNode *arg = rs->results[arg_index];
 				ast_node(fv, FieldValue, arg);
 				GB_ASSERT(fv->field->kind == AstNode_Ident);
-				String name = fv->field->Ident.string;
+				String name = fv->field->Ident.token.string;
 				isize index = lookup_procedure_result(&proc->type->Proc, name);
 				GB_ASSERT(index >= 0);
 				irValue *expr = ir_build_expr(proc, fv->value);

+ 1 - 1
src/ir_print.cpp

@@ -594,7 +594,7 @@ void ir_print_exact_value(irFileBuffer *f, irModule *m, ExactValue value, Type *
 				isize elem_count = cl->elems.count;
 				for (isize i = 0; i < elem_count; i++) {
 					ast_node(fv, FieldValue, cl->elems[i]);
-					String name = fv->field->Ident.string;
+					String name = fv->field->Ident.token.string;
 
 					TypeAndValue tav = type_and_value_of_expr(m->info, fv->value);
 					GB_ASSERT(tav.mode != Addressing_Invalid);

+ 5 - 3
src/parser.cpp

@@ -137,7 +137,9 @@ Array<AstNode *> make_ast_node_array(AstFile *f, isize init_capacity = 8) {
 // for the AstNode. I personally prefer discriminated unions over subtype polymorphism as I can preallocate
 // all the nodes and even memcpy in a different kind of node
 #define AST_NODE_KINDS \
-	AST_NODE_KIND(Ident,          "identifier",      Token) \
+	AST_NODE_KIND(Ident,          "identifier",      struct { \
+		Token token; \
+	}) \
 	AST_NODE_KIND(Implicit,       "implicit",        Token) \
 	AST_NODE_KIND(Undef,          "undef",           Token) \
 	AST_NODE_KIND(BasicLit,       "basic literal",   Token) \
@@ -501,7 +503,7 @@ gb_inline bool is_ast_node_when_stmt(AstNode *node) {
 
 Token ast_node_token(AstNode *node) {
 	switch (node->kind) {
-	case AstNode_Ident:          return node->Ident;
+	case AstNode_Ident:          return node->Ident.token;
 	case AstNode_Implicit:       return node->Implicit;
 	case AstNode_Undef:          return node->Undef;
 	case AstNode_BasicLit:       return node->BasicLit;
@@ -1042,7 +1044,7 @@ AstNode *ast_deref_expr(AstFile *f, AstNode *expr, Token op) {
 
 AstNode *ast_ident(AstFile *f, Token token) {
 	AstNode *result = make_ast_node(f, AstNode_Ident);
-	result->Ident = token;
+	result->Ident.token = token;
 	return result;
 }
 

+ 2 - 2
src/ssa.cpp

@@ -534,7 +534,7 @@ bool ssa_is_op_const(ssaOp op) {
 bool ssa_is_blank_ident(AstNode *node) {
 	if (node->kind == AstNode_Ident) {
 		ast_node(i, Ident, node);
-		return is_blank_ident(i->string);
+		return is_blank_ident(i->token.string);
 	}
 	return false;
 }
@@ -1048,7 +1048,7 @@ ssaAddr ssa_build_addr(ssaProc *p, AstNode *expr) {
 		ssa_emit_comment(p, str_lit("SelectorExpr"));
 		AstNode *sel = unparen_expr(se->selector);
 		if (sel->kind == AstNode_Ident) {
-			String selector = sel->Ident.string;
+			String selector = sel->Ident.token.string;
 			TypeAndValue tav = type_and_value_of_expr(p->module->info, se->expr);
 
 			if (tav.mode == Addressing_Invalid) {