Skip to content

Commit

Permalink
transformer: handle enum_variant = some_const + 10 (fix vlang#21777) (
Browse files Browse the repository at this point in the history
  • Loading branch information
spytheman authored and raw-bin committed Jul 2, 2024
1 parent 1274bb0 commit 58c139c
Show file tree
Hide file tree
Showing 7 changed files with 44 additions and 9 deletions.
14 changes: 14 additions & 0 deletions vlib/v/ast/ast.v
Original file line number Diff line number Diff line change
Expand Up @@ -1012,13 +1012,27 @@ pub mut:
obj ScopeObject
mod string
name string
full_name string
kind IdentKind
info IdentInfo
is_mut bool // if mut *token* is before name. Use `is_mut()` to lookup mut variable
or_expr OrExpr
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 {
return match i.obj {
Var { i.obj.is_auto_heap }
Expand Down
5 changes: 1 addition & 4 deletions vlib/v/checker/match.v
Original file line number Diff line number Diff line change
Expand Up @@ -291,10 +291,7 @@ fn (mut c Checker) get_comptime_number_value(mut expr ast.Expr) ?i64 {
}
}
if mut expr is ast.Ident {
has_expr_mod_in_name := expr.name.contains('.')
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 mut obj := c.table.global_scope.find_const(expr.full_name()) {
if obj.typ == 0 {
obj.typ = c.expr(mut obj.expr)
}
Expand Down
3 changes: 2 additions & 1 deletion vlib/v/gen/c/match.v
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
} 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 obj.expr.val == '0' {
should_check_low_bound = false
Expand Down
2 changes: 1 addition & 1 deletion vlib/v/gen/c/testdata/global_export_nix.c.must_have
Original file line number Diff line number Diff line change
@@ -1 +1 @@
string VV_EXPORTED_SYMBOL global_exported; // global4
string VV_EXPORTED_SYMBOL global_exported = _SLIT("barqux");
2 changes: 1 addition & 1 deletion vlib/v/parser/parse_type.v
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ fn (mut p Parser) parse_array_type(expecting token.Kind, is_option bool) ast.Typ
}
}
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 {
fixed_size = const_field.expr.val.int()
size_unresolved = false
Expand Down
17 changes: 17 additions & 0 deletions vlib/v/tests/enum_test.v
Original file line number Diff line number Diff line change
Expand Up @@ -172,3 +172,20 @@ fn test_enum_variant_and_method_name_clash() {
x := Bar.baz
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
}
10 changes: 8 additions & 2 deletions vlib/v/transformer/transformer.v
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,13 @@ pub fn (mut t Transformer) stmt(mut node ast.Stmt) ast.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 {
// TODO: check if this can be handled in `t.expr`
node.expr = match mut node.expr {
Expand Down Expand Up @@ -719,7 +725,7 @@ fn (mut t Transformer) trans_const_value_to_literal(mut expr ast.Expr) {
if _ := expr_.scope.find_var(expr_.name) {
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 {
expr = obj.expr
} else if mut obj.expr is ast.IntegerLiteral {
Expand Down

0 comments on commit 58c139c

Please sign in to comment.