mirror of
https://github.com/odin-lang/Odin.git
synced 2026-04-19 13:00:28 +00:00
Implicit Selector Expressions: .A
This commit is contained in:
@@ -144,6 +144,10 @@ Selector_Expr :: struct {
|
||||
field: ^Ident,
|
||||
}
|
||||
|
||||
Implicit_Selector_Expr :: struct {
|
||||
using node: Expr,
|
||||
field: ^Ident,
|
||||
}
|
||||
|
||||
Index_Expr :: struct {
|
||||
using node: Expr,
|
||||
|
||||
@@ -2581,6 +2581,13 @@ parse_unary_expr :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr {
|
||||
ue.expr = expr;
|
||||
return ue;
|
||||
|
||||
case token.Period:
|
||||
op := advance_token(p);
|
||||
field := parse_ident(p);
|
||||
ise := ast.new(ast.Implicit_Selector_Expr, op.pos, field.end);
|
||||
ise.field = field;
|
||||
return ise;
|
||||
|
||||
}
|
||||
return parse_atom_expr(p, parse_operand(p, lhs), lhs);
|
||||
}
|
||||
|
||||
@@ -991,7 +991,6 @@ Entity *check_ident(CheckerContext *c, Operand *o, Ast *n, Type *named_type, Typ
|
||||
o->expr = n;
|
||||
String name = n->Ident.token.string;
|
||||
|
||||
|
||||
Entity *e = scope_lookup(c->scope, name);
|
||||
if (e == nullptr) {
|
||||
if (is_blank_ident(name)) {
|
||||
@@ -6177,7 +6176,7 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
|
||||
continue;
|
||||
}
|
||||
|
||||
check_expr(c, o, elem);
|
||||
check_expr_with_type_hint(c, o, elem, et);
|
||||
|
||||
if (is_constant) {
|
||||
is_constant = o->mode == Addressing_Constant;
|
||||
@@ -6408,6 +6407,47 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
|
||||
case_end;
|
||||
|
||||
|
||||
case_ast_node(ise, ImplicitSelectorExpr, node);
|
||||
o->type = t_invalid;
|
||||
o->expr = node;
|
||||
o->mode = Addressing_Invalid;
|
||||
|
||||
if (type_hint == nullptr) {
|
||||
gbString str = expr_to_string(node);
|
||||
error(node, "Cannot determine type for implicit selector expression '%s'", str);
|
||||
gb_string_free(str);
|
||||
return Expr_Expr;
|
||||
}
|
||||
o->type = type_hint;
|
||||
if (!is_type_enum(type_hint)) {
|
||||
gbString typ = type_to_string(type_hint);
|
||||
gbString str = expr_to_string(node);
|
||||
error(node, "Invalid type '%s' for implicit selector expression '%s'", typ, str);
|
||||
gb_string_free(str);
|
||||
gb_string_free(typ);
|
||||
return Expr_Expr;
|
||||
}
|
||||
GB_ASSERT(ise->selector->kind == Ast_Ident);
|
||||
String name = ise->selector->Ident.token.string;
|
||||
|
||||
Type *enum_type = base_type(type_hint);
|
||||
GB_ASSERT(enum_type->kind == Type_Enum);
|
||||
Entity *e = scope_lookup_current(enum_type->Enum.scope, name);
|
||||
if (e == nullptr) {
|
||||
gbString typ = type_to_string(type_hint);
|
||||
error(node, "Undeclared name %.*s for type '%s'", LIT(name), typ);
|
||||
gb_string_free(typ);
|
||||
return Expr_Expr;
|
||||
}
|
||||
GB_ASSERT(are_types_identical(base_type(e->type), base_type(type_hint)));
|
||||
GB_ASSERT(e->kind == Entity_Constant);
|
||||
o->value = e->Constant.value;
|
||||
o->mode = Addressing_Constant;
|
||||
o->type = e->type;
|
||||
|
||||
return Expr_Expr;
|
||||
case_end;
|
||||
|
||||
case_ast_node(ie, IndexExpr, node);
|
||||
check_expr(c, o, ie->expr);
|
||||
if (o->mode == Addressing_Invalid) {
|
||||
@@ -6832,6 +6872,11 @@ gbString write_expr_to_string(gbString str, Ast *node) {
|
||||
str = write_expr_to_string(str, se->selector);
|
||||
case_end;
|
||||
|
||||
case_ast_node(se, ImplicitSelectorExpr, node);
|
||||
str = gb_string_append_rune(str, '.');
|
||||
str = write_expr_to_string(str, se->selector);
|
||||
case_end;
|
||||
|
||||
case_ast_node(ta, TypeAssertion, node);
|
||||
str = write_expr_to_string(str, ta->expr);
|
||||
str = gb_string_appendc(str, ".(");
|
||||
|
||||
@@ -6268,6 +6268,13 @@ irValue *ir_build_expr_internal(irProcedure *proc, Ast *expr) {
|
||||
return ir_addr_load(proc, ir_build_addr(proc, expr));
|
||||
case_end;
|
||||
|
||||
case_ast_node(ise, ImplicitSelectorExpr, expr);
|
||||
TypeAndValue tav = type_and_value_of_expr(expr);
|
||||
GB_ASSERT(tav.mode == Addressing_Constant);
|
||||
|
||||
return ir_add_module_constant(proc->module, tv.type, tv.value);
|
||||
case_end;
|
||||
|
||||
case_ast_node(te, TernaryExpr, expr);
|
||||
ir_emit_comment(proc, str_lit("TernaryExpr"));
|
||||
|
||||
|
||||
@@ -25,6 +25,11 @@ Token ast_token(Ast *node) {
|
||||
return ast_token(node->SelectorExpr.selector);
|
||||
}
|
||||
return node->SelectorExpr.token;
|
||||
case Ast_ImplicitSelectorExpr:
|
||||
if (node->ImplicitSelectorExpr.selector != nullptr) {
|
||||
return ast_token(node->ImplicitSelectorExpr.selector);
|
||||
}
|
||||
return node->ImplicitSelectorExpr.token;
|
||||
case Ast_IndexExpr: return node->IndexExpr.open;
|
||||
case Ast_SliceExpr: return node->SliceExpr.open;
|
||||
case Ast_Ellipsis: return node->Ellipsis.token;
|
||||
@@ -165,6 +170,9 @@ Ast *clone_ast(Ast *node) {
|
||||
n->SelectorExpr.expr = clone_ast(n->SelectorExpr.expr);
|
||||
n->SelectorExpr.selector = clone_ast(n->SelectorExpr.selector);
|
||||
break;
|
||||
case Ast_ImplicitSelectorExpr:
|
||||
n->ImplicitSelectorExpr.selector = clone_ast(n->ImplicitSelectorExpr.selector);
|
||||
break;
|
||||
case Ast_IndexExpr:
|
||||
n->IndexExpr.expr = clone_ast(n->IndexExpr.expr);
|
||||
n->IndexExpr.index = clone_ast(n->IndexExpr.index);
|
||||
@@ -504,11 +512,20 @@ Ast *ast_call_expr(AstFile *f, Ast *proc, Array<Ast *> args, Token open, Token c
|
||||
|
||||
Ast *ast_selector_expr(AstFile *f, Token token, Ast *expr, Ast *selector) {
|
||||
Ast *result = alloc_ast_node(f, Ast_SelectorExpr);
|
||||
result->SelectorExpr.token = token;
|
||||
result->SelectorExpr.expr = expr;
|
||||
result->SelectorExpr.selector = selector;
|
||||
return result;
|
||||
}
|
||||
|
||||
Ast *ast_implicit_selector_expr(AstFile *f, Token token, Ast *selector) {
|
||||
Ast *result = alloc_ast_node(f, Ast_ImplicitSelectorExpr);
|
||||
result->ImplicitSelectorExpr.token = token;
|
||||
result->ImplicitSelectorExpr.selector = selector;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
Ast *ast_index_expr(AstFile *f, Ast *expr, Ast *index, Token open, Token close) {
|
||||
Ast *result = alloc_ast_node(f, Ast_IndexExpr);
|
||||
result->IndexExpr.expr = expr;
|
||||
@@ -1612,7 +1629,6 @@ Ast *parse_operand(AstFile *f, bool lhs) {
|
||||
case Token_offset_of:
|
||||
return parse_call_expr(f, ast_implicit(f, advance_token(f)));
|
||||
|
||||
|
||||
case Token_String:
|
||||
return ast_basic_lit(f, advance_token(f));
|
||||
|
||||
@@ -2277,6 +2293,12 @@ Ast *parse_unary_expr(AstFile *f, bool lhs) {
|
||||
Ast *expr = parse_unary_expr(f, lhs);
|
||||
return ast_unary_expr(f, token, expr);
|
||||
}
|
||||
|
||||
case Token_Period: {
|
||||
Token token = expect_token(f, Token_Period);
|
||||
Ast *ident = parse_ident(f);
|
||||
return ast_implicit_selector_expr(f, token, ident);
|
||||
}
|
||||
}
|
||||
|
||||
return parse_atom_expr(f, parse_operand(f, lhs), lhs);
|
||||
|
||||
@@ -245,6 +245,7 @@ AST_KIND(_ExprBegin, "", bool) \
|
||||
AST_KIND(BinaryExpr, "binary expression", struct { Token op; Ast *left, *right; } ) \
|
||||
AST_KIND(ParenExpr, "parentheses expression", struct { Ast *expr; Token open, close; }) \
|
||||
AST_KIND(SelectorExpr, "selector expression", struct { Token token; Ast *expr, *selector; }) \
|
||||
AST_KIND(ImplicitSelectorExpr, "implicit selector expression", struct { Token token; Ast *selector; }) \
|
||||
AST_KIND(IndexExpr, "index expression", struct { Ast *expr, *index; Token open, close; }) \
|
||||
AST_KIND(DerefExpr, "dereference expression", struct { Token op; Ast *expr; }) \
|
||||
AST_KIND(SliceExpr, "slice expression", struct { \
|
||||
|
||||
Reference in New Issue
Block a user