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'
|
size_str = 'BYTE'
|
||||||
}
|
}
|
||||||
else {
|
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 }
|
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')
|
g.n_error('unsupported type for `$node.op`: $node.left_type')
|
||||||
}
|
}
|
||||||
// left: rax, right: rdx
|
// 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) {
|
fn (mut g Gen) gen_assert(assert_node ast.AssertStmt) {
|
||||||
mut cjmp_addr := 0
|
mut cjmp_addr := 0
|
||||||
mut ine := ast.InfixExpr{}
|
|
||||||
ane := assert_node.expr
|
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()
|
label := g.labels.new_label()
|
||||||
cjmp_addr = g.condition(ine, true)
|
cjmp_addr = g.condition(ane, true)
|
||||||
g.labels.patches << LabelPatch{
|
g.labels.patches << LabelPatch{
|
||||||
id: label
|
id: label
|
||||||
pos: cjmp_addr
|
pos: cjmp_addr
|
||||||
|
@ -11,6 +11,7 @@ import v.mathutil as mu
|
|||||||
import v.token
|
import v.token
|
||||||
import v.errors
|
import v.errors
|
||||||
import v.pref
|
import v.pref
|
||||||
|
import v.eval
|
||||||
import term
|
import term
|
||||||
import strconv
|
import strconv
|
||||||
|
|
||||||
@ -53,6 +54,8 @@ mut:
|
|||||||
defer_stmts []ast.DeferStmt
|
defer_stmts []ast.DeferStmt
|
||||||
builtins map[string]BuiltinFn
|
builtins map[string]BuiltinFn
|
||||||
structs []Struct
|
structs []Struct
|
||||||
|
eval eval.Eval
|
||||||
|
enum_vals map[string]Enum
|
||||||
// macho specific
|
// macho specific
|
||||||
macho_ncmds int
|
macho_ncmds int
|
||||||
macho_cmdsize int
|
macho_cmdsize int
|
||||||
@ -107,6 +110,11 @@ mut:
|
|||||||
offsets []int
|
offsets []int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Enum {
|
||||||
|
mut:
|
||||||
|
fields map[string]int
|
||||||
|
}
|
||||||
|
|
||||||
enum Size {
|
enum Size {
|
||||||
_8
|
_8
|
||||||
_16
|
_16
|
||||||
@ -217,11 +225,13 @@ pub fn gen(files []&ast.File, table &ast.Table, out_name string, pref &pref.Pref
|
|||||||
}
|
}
|
||||||
labels: 0
|
labels: 0
|
||||||
structs: []Struct{len: table.type_symbols.len}
|
structs: []Struct{len: table.type_symbols.len}
|
||||||
|
eval: eval.new_eval(table, pref)
|
||||||
}
|
}
|
||||||
g.code_gen.g = g
|
g.code_gen.g = g
|
||||||
g.generate_header()
|
g.generate_header()
|
||||||
g.init_builtins()
|
g.init_builtins()
|
||||||
g.calculate_all_size_align()
|
g.calculate_all_size_align()
|
||||||
|
g.calculate_enum_fields()
|
||||||
for file in files {
|
for file in files {
|
||||||
/*
|
/*
|
||||||
if file.warnings.len > 0 {
|
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) {
|
pub fn (mut g Gen) stmts(stmts []ast.Stmt) {
|
||||||
for stmt in stmts {
|
for stmt in stmts {
|
||||||
g.stmt(stmt)
|
g.stmt(stmt)
|
||||||
@ -496,13 +525,17 @@ fn (mut g Gen) get_type_size(typ ast.Type) int {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
size = (size + align - 1) / align * align
|
size = (size + align - 1) / align * align
|
||||||
|
g.structs[typ.idx()] = strc
|
||||||
|
}
|
||||||
|
ast.Enum {
|
||||||
|
size = 4
|
||||||
|
align = 4
|
||||||
}
|
}
|
||||||
else {}
|
else {}
|
||||||
}
|
}
|
||||||
mut ts_ := g.table.sym(typ)
|
mut ts_ := g.table.sym(typ)
|
||||||
ts_.size = size
|
ts_.size = size
|
||||||
ts_.align = align
|
ts_.align = align
|
||||||
g.structs[typ.idx()] = strc
|
|
||||||
// g.n_error('unknown type size')
|
// g.n_error('unknown type size')
|
||||||
return size
|
return size
|
||||||
}
|
}
|
||||||
@ -1138,6 +1171,7 @@ fn (mut g Gen) stmt(node ast.Stmt) {
|
|||||||
}
|
}
|
||||||
ast.Import {} // do nothing here
|
ast.Import {} // do nothing here
|
||||||
ast.StructDecl {}
|
ast.StructDecl {}
|
||||||
|
ast.EnumDecl {}
|
||||||
else {
|
else {
|
||||||
eprintln('native.stmt(): bad node: ' + node.type_name())
|
eprintln('native.stmt(): bad node: ' + node.type_name())
|
||||||
}
|
}
|
||||||
@ -1235,6 +1269,9 @@ fn (mut g Gen) expr(node ast.Expr) {
|
|||||||
ast.Struct {
|
ast.Struct {
|
||||||
g.lea_var_to_reg(.rax, g.get_var_offset(node.name))
|
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 {
|
else {
|
||||||
g.n_error('Unsupported variable type')
|
g.n_error('Unsupported variable type')
|
||||||
}
|
}
|
||||||
@ -1289,6 +1326,10 @@ fn (mut g Gen) expr(node ast.Expr) {
|
|||||||
g.add(.rax, offset)
|
g.add(.rax, offset)
|
||||||
g.mov_deref(.rax, .rax, node.typ)
|
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 {
|
else {
|
||||||
g.n_error('expr: unhandled node type: $node.type_name()')
|
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() {
|
fn main() {
|
||||||
match_for_test()
|
match_for_test()
|
||||||
ifexpr_match_test()
|
ifexpr_match_test()
|
||||||
integer_match_test()
|
integer_match_test()
|
||||||
multiple_test()
|
multiple_test()
|
||||||
|
enum_test()
|
||||||
}
|
}
|
||||||
|
@ -5,3 +5,4 @@ a == 0
|
|||||||
0
|
0
|
||||||
three
|
three
|
||||||
6-9
|
6-9
|
||||||
|
b
|
||||||
|
Loading…
Reference in New Issue
Block a user