mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
native: support enum (#15895)
This commit is contained in:
parent
51a92d170f
commit
f1216090f7
@ -584,7 +584,16 @@ fn (mut g Gen) mov_reg_to_var(var Var, reg Register, config VarConfig) {
|
||||
size_str = 'BYTE'
|
||||
}
|
||||
else {
|
||||
g.n_error('unsupported type for mov_reg_to_var')
|
||||
ts := g.table.sym(typ.idx())
|
||||
if ts.info is ast.Enum {
|
||||
if is_extended_register {
|
||||
g.write8(0x44)
|
||||
}
|
||||
g.write8(0x89)
|
||||
size_str = 'DWORD'
|
||||
} else {
|
||||
g.n_error('unsupported type for mov_reg_to_var')
|
||||
}
|
||||
}
|
||||
}
|
||||
far_var_offset := if is_far_var { 0x40 } else { 0 }
|
||||
@ -2265,7 +2274,8 @@ fn (mut g Gen) infix_expr(node ast.InfixExpr) {
|
||||
})
|
||||
}
|
||||
}
|
||||
if node.left_type !in ast.integer_type_idxs && node.left_type != ast.bool_type_idx {
|
||||
if node.left_type !in ast.integer_type_idxs && node.left_type != ast.bool_type_idx
|
||||
&& g.table.sym(node.left_type).info !is ast.Enum {
|
||||
g.n_error('unsupported type for `$node.op`: $node.left_type')
|
||||
}
|
||||
// left: rax, right: rdx
|
||||
@ -2467,17 +2477,9 @@ fn (mut g Gen) gen_asm_stmt_amd64(asm_node ast.AsmStmt) {
|
||||
|
||||
fn (mut g Gen) gen_assert(assert_node ast.AssertStmt) {
|
||||
mut cjmp_addr := 0
|
||||
mut ine := ast.InfixExpr{}
|
||||
ane := assert_node.expr
|
||||
if ane is ast.ParExpr { // assert(1==1)
|
||||
ine = ane.expr as ast.InfixExpr
|
||||
} else if ane is ast.InfixExpr { // assert 1==1
|
||||
ine = ane
|
||||
} else {
|
||||
g.n_error('Unsupported expression in assert')
|
||||
}
|
||||
label := g.labels.new_label()
|
||||
cjmp_addr = g.condition(ine, true)
|
||||
cjmp_addr = g.condition(ane, true)
|
||||
g.labels.patches << LabelPatch{
|
||||
id: label
|
||||
pos: cjmp_addr
|
||||
|
@ -11,6 +11,7 @@ import v.mathutil as mu
|
||||
import v.token
|
||||
import v.errors
|
||||
import v.pref
|
||||
import v.eval
|
||||
import term
|
||||
import strconv
|
||||
|
||||
@ -53,6 +54,8 @@ mut:
|
||||
defer_stmts []ast.DeferStmt
|
||||
builtins map[string]BuiltinFn
|
||||
structs []Struct
|
||||
eval eval.Eval
|
||||
enum_vals map[string]Enum
|
||||
// macho specific
|
||||
macho_ncmds int
|
||||
macho_cmdsize int
|
||||
@ -107,6 +110,11 @@ mut:
|
||||
offsets []int
|
||||
}
|
||||
|
||||
struct Enum {
|
||||
mut:
|
||||
fields map[string]int
|
||||
}
|
||||
|
||||
enum Size {
|
||||
_8
|
||||
_16
|
||||
@ -217,11 +225,13 @@ pub fn gen(files []&ast.File, table &ast.Table, out_name string, pref &pref.Pref
|
||||
}
|
||||
labels: 0
|
||||
structs: []Struct{len: table.type_symbols.len}
|
||||
eval: eval.new_eval(table, pref)
|
||||
}
|
||||
g.code_gen.g = g
|
||||
g.generate_header()
|
||||
g.init_builtins()
|
||||
g.calculate_all_size_align()
|
||||
g.calculate_enum_fields()
|
||||
for file in files {
|
||||
/*
|
||||
if file.warnings.len > 0 {
|
||||
@ -330,6 +340,25 @@ pub fn (mut g Gen) calculate_all_size_align() {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (mut g Gen) calculate_enum_fields() {
|
||||
for name, decl in g.table.enum_decls {
|
||||
mut enum_vals := Enum{}
|
||||
mut value := if decl.is_flag { 1 } else { 0 }
|
||||
for field in decl.fields {
|
||||
if field.has_expr {
|
||||
value = int(g.eval.expr(field.expr, ast.int_type_idx).int_val())
|
||||
}
|
||||
enum_vals.fields[field.name] = value
|
||||
if decl.is_flag {
|
||||
value <<= 1
|
||||
} else {
|
||||
value++
|
||||
}
|
||||
}
|
||||
g.enum_vals[name] = enum_vals
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (mut g Gen) stmts(stmts []ast.Stmt) {
|
||||
for stmt in stmts {
|
||||
g.stmt(stmt)
|
||||
@ -496,13 +525,17 @@ fn (mut g Gen) get_type_size(typ ast.Type) int {
|
||||
}
|
||||
}
|
||||
size = (size + align - 1) / align * align
|
||||
g.structs[typ.idx()] = strc
|
||||
}
|
||||
ast.Enum {
|
||||
size = 4
|
||||
align = 4
|
||||
}
|
||||
else {}
|
||||
}
|
||||
mut ts_ := g.table.sym(typ)
|
||||
ts_.size = size
|
||||
ts_.align = align
|
||||
g.structs[typ.idx()] = strc
|
||||
// g.n_error('unknown type size')
|
||||
return size
|
||||
}
|
||||
@ -1138,6 +1171,7 @@ fn (mut g Gen) stmt(node ast.Stmt) {
|
||||
}
|
||||
ast.Import {} // do nothing here
|
||||
ast.StructDecl {}
|
||||
ast.EnumDecl {}
|
||||
else {
|
||||
eprintln('native.stmt(): bad node: ' + node.type_name())
|
||||
}
|
||||
@ -1235,6 +1269,9 @@ fn (mut g Gen) expr(node ast.Expr) {
|
||||
ast.Struct {
|
||||
g.lea_var_to_reg(.rax, g.get_var_offset(node.name))
|
||||
}
|
||||
ast.Enum {
|
||||
g.mov_var_to_reg(.rax, node as ast.Ident, typ: ast.int_type_idx)
|
||||
}
|
||||
else {
|
||||
g.n_error('Unsupported variable type')
|
||||
}
|
||||
@ -1289,6 +1326,10 @@ fn (mut g Gen) expr(node ast.Expr) {
|
||||
g.add(.rax, offset)
|
||||
g.mov_deref(.rax, .rax, node.typ)
|
||||
}
|
||||
ast.EnumVal {
|
||||
type_name := g.table.get_type_name(node.typ)
|
||||
g.mov(.rax, g.enum_vals[type_name].fields[node.val])
|
||||
}
|
||||
else {
|
||||
g.n_error('expr: unhandled node type: $node.type_name()')
|
||||
}
|
||||
|
51
vlib/v/gen/native/tests/enum.vv
Normal file
51
vlib/v/gen/native/tests/enum.vv
Normal file
@ -0,0 +1,51 @@
|
||||
enum Color {
|
||||
red
|
||||
blue
|
||||
green
|
||||
}
|
||||
|
||||
fn enum_test() {
|
||||
assert Color.red == .red
|
||||
assert Color.blue == .blue
|
||||
assert Color.green == .green
|
||||
assert Color.red != .blue
|
||||
assert Color.red != .green
|
||||
assert Color.blue != .green
|
||||
mut color := Color.red
|
||||
assert color == .red
|
||||
color = .green
|
||||
assert color == .green
|
||||
}
|
||||
|
||||
fn match_test() {
|
||||
color := Color.green
|
||||
num := 3
|
||||
match color {
|
||||
.red {
|
||||
assert false
|
||||
}
|
||||
.green {
|
||||
assert true
|
||||
}
|
||||
else {
|
||||
assert false
|
||||
}
|
||||
}
|
||||
// println(color)
|
||||
assert num == 3
|
||||
}
|
||||
|
||||
enum Bar {
|
||||
baz
|
||||
}
|
||||
|
||||
fn (_ Bar) baz() {}
|
||||
|
||||
fn test_enum_variant_and_method_name_clash() {
|
||||
x := Bar.baz
|
||||
// println(x)
|
||||
x.baz()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
}
|
0
vlib/v/gen/native/tests/enum.vv.out
Normal file
0
vlib/v/gen/native/tests/enum.vv.out
Normal file
@ -117,9 +117,42 @@ fn multiple_test() { // from match_test.v
|
||||
}
|
||||
}
|
||||
|
||||
enum Foo {
|
||||
a
|
||||
b
|
||||
c = 4 + 8
|
||||
}
|
||||
|
||||
fn get() Foo {
|
||||
return .a
|
||||
}
|
||||
|
||||
fn foo(f Foo) {
|
||||
match f {
|
||||
.a {
|
||||
println('a')
|
||||
}
|
||||
.b {
|
||||
println('b')
|
||||
}
|
||||
.c {
|
||||
println('c')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn enum_test() {
|
||||
foo(match get() {
|
||||
.a { .b }
|
||||
.b { .c }
|
||||
.c { .a }
|
||||
})
|
||||
}
|
||||
|
||||
fn main() {
|
||||
match_for_test()
|
||||
ifexpr_match_test()
|
||||
integer_match_test()
|
||||
multiple_test()
|
||||
enum_test()
|
||||
}
|
||||
|
@ -5,3 +5,4 @@ a == 0
|
||||
0
|
||||
three
|
||||
6-9
|
||||
b
|
||||
|
Loading…
Reference in New Issue
Block a user