diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index a1846891de..904554535c 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -1039,8 +1039,9 @@ pub: pos token.Position comments []Comment // comment after Enumfield in the same line next_comments []Comment // comments between current EnumField and next EnumField - expr Expr // the value of current EnumField; 123 in `ename = 123` has_expr bool // true, when .expr has a value +pub mut: + expr Expr // the value of current EnumField; 123 in `ename = 123` } // enum declaration diff --git a/vlib/v/ast/table.v b/vlib/v/ast/table.v index dd9eaa3436..c874aac27d 100644 --- a/vlib/v/ast/table.v +++ b/vlib/v/ast/table.v @@ -485,6 +485,8 @@ pub fn (t &Table) find_field(s &TypeSymbol, name string) ?StructField { if field := ts.info.find_field(name) { return field } + // mut info := ts.info as SumType + // TODO a more detailed error so that it's easier to fix? return error('field `$name` does not exist or have the same type in all sumtype variants') } else {} diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 4893f279b7..30d5e90cd3 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -3711,9 +3711,9 @@ pub fn (mut c Checker) const_decl(mut node ast.ConstDecl) { } } -pub fn (mut c Checker) enum_decl(node ast.EnumDecl) { +pub fn (mut c Checker) enum_decl(mut node ast.EnumDecl) { c.check_valid_pascal_case(node.name, 'enum name', node.pos) - mut seen := []i64{} + mut seen := []i64{cap: node.fields.len} if node.fields.len == 0 { c.error('enum cannot be empty', node.pos) } @@ -3722,7 +3722,7 @@ pub fn (mut c Checker) enum_decl(node ast.EnumDecl) { c.error('`builtin` module cannot have enums', node.pos) } */ - for i, field in node.fields { + for i, mut field in node.fields { if !c.pref.experimental && util.contains_capital(field.name) { // TODO C2V uses hundreds of enums with capitals, remove -experimental check once it's handled c.error('field name `$field.name` cannot contain uppercase letters, use snake_case instead', @@ -3734,20 +3734,28 @@ pub fn (mut c Checker) enum_decl(node ast.EnumDecl) { } } if field.has_expr { - match field.expr { + match mut field.expr { ast.IntegerLiteral { val := field.expr.val.i64() if val < checker.int_min || val > checker.int_max { c.error('enum value `$val` overflows int', field.expr.pos) - } else if !node.is_multi_allowed && i64(val) in seen { + } else if !c.pref.translated && !node.is_multi_allowed && i64(val) in seen { c.error('enum value `$val` already exists', field.expr.pos) } seen << i64(val) } ast.PrefixExpr {} + ast.InfixExpr { + // Handle `enum Foo { x = 1 + 2 }` + c.infix_expr(mut field.expr) + } + // ast.ParExpr {} // TODO allow `.x = (1+2)` else { if field.expr is ast.Ident { - if field.expr.language == .c { + x := field.expr as ast.Ident + // TODO sum type bug, remove temp var + // if field.expr.language == .c { + if x.language == .c { continue } } @@ -3763,7 +3771,7 @@ pub fn (mut c Checker) enum_decl(node ast.EnumDecl) { last := seen[seen.len - 1] if last == checker.int_max { c.error('enum value overflows', field.pos) - } else if !node.is_multi_allowed && last + 1 in seen { + } else if !c.pref.translated && !node.is_multi_allowed && last + 1 in seen { c.error('enum value `${last + 1}` already exists', field.pos) } seen << last + 1 @@ -4657,7 +4665,7 @@ fn (mut c Checker) stmt(node ast.Stmt) { c.inside_defer = false } ast.EnumDecl { - c.enum_decl(node) + c.enum_decl(mut node) } ast.ExprStmt { node.typ = c.expr(node.expr) diff --git a/vlib/v/gen/c/cheaders.v b/vlib/v/gen/c/cheaders.v index b723a702a2..cefd8b6511 100644 --- a/vlib/v/gen/c/cheaders.v +++ b/vlib/v/gen/c/cheaders.v @@ -542,6 +542,7 @@ typedef struct sync__Channel* chan; #ifndef __cplusplus #ifndef bool + //typedef int bool; typedef byte bool; #define true 1 #define false 0 diff --git a/vlib/v/tests/enum_test.v b/vlib/v/tests/enum_test.v index e9ef0f0ba5..9eac7654cd 100644 --- a/vlib/v/tests/enum_test.v +++ b/vlib/v/tests/enum_test.v @@ -32,6 +32,20 @@ fn test_enum() { assert color == .green } +enum PowerDuration { + invulntics = 30 * 35 + invistics = 60 * 35 + infratics = 120 * 35 +} + +fn test_custom_values() { + mut p := PowerDuration.invulntics + assert int(p) == 30 * 35 + p = .invistics + assert int(p) == 60 * 35 + assert int(PowerDuration.infratics) == 120 * 35 +} + fn test_in() { color := Color.red num := 3 // used to be an expr bug before `in`