transformer: handle enum_variant = some_const + 10 (fix #21777) (#21779)

This commit is contained in:
Delyan Angelov 2024-07-01 19:22:40 +03:00 committed by GitHub
parent 39f419139e
commit b82d6859b5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 44 additions and 9 deletions

View File

@ -1012,6 +1012,7 @@ pub mut:
obj ScopeObject obj ScopeObject
mod string mod string
name string name string
full_name string
kind IdentKind kind IdentKind
info IdentInfo info IdentInfo
is_mut bool // if mut *token* is before name. Use `is_mut()` to lookup mut variable is_mut bool // if mut *token* is before name. Use `is_mut()` to lookup mut variable
@ -1019,6 +1020,19 @@ pub mut:
concrete_types []Type concrete_types []Type
} }
// full_name returns the name of the ident, prefixed with the module name
pub fn (mut i Ident) full_name() string {
if i.full_name != '' {
return i.full_name
}
if i.name.contains('.') {
i.full_name = i.name
} else {
i.full_name = i.mod + '.' + i.name
}
return i.full_name
}
pub fn (i &Ident) is_auto_heap() bool { pub fn (i &Ident) is_auto_heap() bool {
return match i.obj { return match i.obj {
Var { i.obj.is_auto_heap } Var { i.obj.is_auto_heap }

View File

@ -291,10 +291,7 @@ fn (mut c Checker) get_comptime_number_value(mut expr ast.Expr) ?i64 {
} }
} }
if mut expr is ast.Ident { if mut expr is ast.Ident {
has_expr_mod_in_name := expr.name.contains('.') if mut obj := c.table.global_scope.find_const(expr.full_name()) {
expr_name := if has_expr_mod_in_name { expr.name } else { '${expr.mod}.${expr.name}' }
if mut obj := c.table.global_scope.find_const(expr_name) {
if obj.typ == 0 { if obj.typ == 0 {
obj.typ = c.expr(mut obj.expr) obj.typ = c.expr(mut obj.expr)
} }

View File

@ -403,7 +403,8 @@ fn (mut g Gen) should_check_low_bound_in_range_expr(expr ast.RangeExpr, node_con
should_check_low_bound = false should_check_low_bound = false
} }
} else if expr.low is ast.Ident { } else if expr.low is ast.Ident {
if mut obj := g.table.global_scope.find_const(expr.low.name) { mut elow := unsafe { expr.low }
if mut obj := g.table.global_scope.find_const(elow.full_name()) {
if mut obj.expr is ast.IntegerLiteral { if mut obj.expr is ast.IntegerLiteral {
if obj.expr.val == '0' { if obj.expr.val == '0' {
should_check_low_bound = false should_check_low_bound = false

View File

@ -1 +1 @@
string VV_EXPORTED_SYMBOL global_exported; // global4 string VV_EXPORTED_SYMBOL global_exported = _SLIT("barqux");

View File

@ -42,7 +42,7 @@ fn (mut p Parser) parse_array_type(expecting token.Kind, is_option bool) ast.Typ
} }
} }
ast.Ident { ast.Ident {
if mut const_field := p.table.global_scope.find_const('${p.mod}.${size_expr.name}') { if mut const_field := p.table.global_scope.find_const(size_expr.full_name()) {
if mut const_field.expr is ast.IntegerLiteral { if mut const_field.expr is ast.IntegerLiteral {
fixed_size = const_field.expr.val.int() fixed_size = const_field.expr.val.int()
size_unresolved = false size_unresolved = false

View File

@ -172,3 +172,20 @@ fn test_enum_variant_and_method_name_clash() {
x := Bar.baz x := Bar.baz
println(x) println(x)
} }
const base = 600000
enum EnumWithExpressions {
aa
bb = base
cc
dd = base + 10
ee = base * 99 - 4
}
fn test_enum_variant_with_value_based_on_const_expression() {
assert int(EnumWithExpressions.bb) == base
assert int(EnumWithExpressions.cc) == base + 1
assert int(EnumWithExpressions.dd) == 600010
assert int(EnumWithExpressions.ee) == 59399996
}

View File

@ -220,7 +220,13 @@ pub fn (mut t Transformer) stmt(mut node ast.Stmt) ast.Stmt {
stmt = t.stmt(mut stmt) stmt = t.stmt(mut stmt)
} }
} }
ast.EnumDecl {} ast.EnumDecl {
for mut field in node.fields {
if field.has_expr {
field.expr = t.expr(mut field.expr)
}
}
}
ast.ExprStmt { ast.ExprStmt {
// TODO: check if this can be handled in `t.expr` // TODO: check if this can be handled in `t.expr`
node.expr = match mut node.expr { node.expr = match mut node.expr {
@ -719,7 +725,7 @@ fn (mut t Transformer) trans_const_value_to_literal(mut expr ast.Expr) {
if _ := expr_.scope.find_var(expr_.name) { if _ := expr_.scope.find_var(expr_.name) {
return return
} }
if mut obj := t.table.global_scope.find_const(expr_.mod + '.' + expr_.name) { if mut obj := t.table.global_scope.find_const(expr_.full_name()) {
if mut obj.expr is ast.BoolLiteral { if mut obj.expr is ast.BoolLiteral {
expr = obj.expr expr = obj.expr
} else if mut obj.expr is ast.IntegerLiteral { } else if mut obj.expr is ast.IntegerLiteral {