checker: allow infix expressions in enum declarations
parent
c4363bc78b
commit
eca78a2906
|
@ -1039,8 +1039,9 @@ pub:
|
||||||
pos token.Position
|
pos token.Position
|
||||||
comments []Comment // comment after Enumfield in the same line
|
comments []Comment // comment after Enumfield in the same line
|
||||||
next_comments []Comment // comments between current EnumField and next EnumField
|
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
|
has_expr bool // true, when .expr has a value
|
||||||
|
pub mut:
|
||||||
|
expr Expr // the value of current EnumField; 123 in `ename = 123`
|
||||||
}
|
}
|
||||||
|
|
||||||
// enum declaration
|
// enum declaration
|
||||||
|
|
|
@ -485,6 +485,8 @@ pub fn (t &Table) find_field(s &TypeSymbol, name string) ?StructField {
|
||||||
if field := ts.info.find_field(name) {
|
if field := ts.info.find_field(name) {
|
||||||
return field
|
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')
|
return error('field `$name` does not exist or have the same type in all sumtype variants')
|
||||||
}
|
}
|
||||||
else {}
|
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)
|
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 {
|
if node.fields.len == 0 {
|
||||||
c.error('enum cannot be empty', node.pos)
|
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)
|
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) {
|
if !c.pref.experimental && util.contains_capital(field.name) {
|
||||||
// TODO C2V uses hundreds of enums with capitals, remove -experimental check once it's handled
|
// 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',
|
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 {
|
if field.has_expr {
|
||||||
match field.expr {
|
match mut field.expr {
|
||||||
ast.IntegerLiteral {
|
ast.IntegerLiteral {
|
||||||
val := field.expr.val.i64()
|
val := field.expr.val.i64()
|
||||||
if val < checker.int_min || val > checker.int_max {
|
if val < checker.int_min || val > checker.int_max {
|
||||||
c.error('enum value `$val` overflows int', field.expr.pos)
|
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)
|
c.error('enum value `$val` already exists', field.expr.pos)
|
||||||
}
|
}
|
||||||
seen << i64(val)
|
seen << i64(val)
|
||||||
}
|
}
|
||||||
ast.PrefixExpr {}
|
ast.PrefixExpr {}
|
||||||
|
ast.InfixExpr {
|
||||||
|
// Handle `enum Foo { x = 1 + 2 }`
|
||||||
|
c.infix_expr(mut field.expr)
|
||||||
|
}
|
||||||
|
// ast.ParExpr {} // TODO allow `.x = (1+2)`
|
||||||
else {
|
else {
|
||||||
if field.expr is ast.Ident {
|
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
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3763,7 +3771,7 @@ pub fn (mut c Checker) enum_decl(node ast.EnumDecl) {
|
||||||
last := seen[seen.len - 1]
|
last := seen[seen.len - 1]
|
||||||
if last == checker.int_max {
|
if last == checker.int_max {
|
||||||
c.error('enum value overflows', field.pos)
|
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)
|
c.error('enum value `${last + 1}` already exists', field.pos)
|
||||||
}
|
}
|
||||||
seen << last + 1
|
seen << last + 1
|
||||||
|
@ -4657,7 +4665,7 @@ fn (mut c Checker) stmt(node ast.Stmt) {
|
||||||
c.inside_defer = false
|
c.inside_defer = false
|
||||||
}
|
}
|
||||||
ast.EnumDecl {
|
ast.EnumDecl {
|
||||||
c.enum_decl(node)
|
c.enum_decl(mut node)
|
||||||
}
|
}
|
||||||
ast.ExprStmt {
|
ast.ExprStmt {
|
||||||
node.typ = c.expr(node.expr)
|
node.typ = c.expr(node.expr)
|
||||||
|
|
|
@ -542,6 +542,7 @@ typedef struct sync__Channel* chan;
|
||||||
|
|
||||||
#ifndef __cplusplus
|
#ifndef __cplusplus
|
||||||
#ifndef bool
|
#ifndef bool
|
||||||
|
//typedef int bool;
|
||||||
typedef byte bool;
|
typedef byte bool;
|
||||||
#define true 1
|
#define true 1
|
||||||
#define false 0
|
#define false 0
|
||||||
|
|
|
@ -32,6 +32,20 @@ fn test_enum() {
|
||||||
assert color == .green
|
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() {
|
fn test_in() {
|
||||||
color := Color.red
|
color := Color.red
|
||||||
num := 3 // used to be an expr bug before `in`
|
num := 3 // used to be an expr bug before `in`
|
||||||
|
|
Loading…
Reference in New Issue