checker: allow infix expressions in enum declarations
parent
c4363bc78b
commit
eca78a2906
|
@ -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
|
||||
|
|
|
@ -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 {}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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`
|
||||
|
|
Loading…
Reference in New Issue