// Copyright (c) 2019 Alexander Medvednikov. All rights reserved. // Use of this source code is governed by an MIT license // that can be found in the LICENSE file. module compiler fn (p mut Parser) enum_decl(_enum_name string) { mut enum_name := _enum_name is_pub := p.tok == .key_pub if is_pub { p.next() p.check(.key_enum) enum_name = p.check_name() } // Specify full type name if !p.builtin_mod && p.mod != 'main' { enum_name = p.prepend_mod(enum_name) } // Skip empty enums if enum_name != 'int' && !p.first_pass() { p.cgen.typedefs << 'typedef int $enum_name;' } p.check(.lcbr) mut val := 0 mut fields := []string for p.tok == .name { field := p.check_name() if contains_capital(field) { p.warn('enum values cannot contain uppercase letters, use snake_case instead') } fields << field p.fgenln('') name := '${mod_gen_name(p.mod)}__${enum_name}_$field' if p.tok == .assign { mut enum_assign_tidx := p.cur_tok_index() if p.peek() == .number { p.next() val = p.lit.int() p.next() }else{ p.next() enum_assign_tidx = p.cur_tok_index() p.error_with_token_index('only numbers are allowed in enum initializations', enum_assign_tidx) } } if p.pass == .main { p.cgen.consts << '#define $name $val' } if p.tok == .comma { p.next() } val++ } p.table.register_type2(Type { name: enum_name mod: p.mod parent: 'int' cat: TypeCategory.enum_ enum_vals: fields.clone() is_public: is_pub }) p.check(.rcbr) p.fgenln('\n') } fn (p mut Parser) check_enum_member_access() { T := p.find_type(p.expected_type) if T.cat == .enum_ { p.check(.dot) val := p.check_name() // Make sure this enum value exists if !T.has_enum_val(val) { p.error('enum `$T.name` does not have value `$val`') } p.gen(mod_gen_name(T.mod) + '__' + p.expected_type + '_' + val) } else { p.error('`$T.name` is not an enum') } }