1
0
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:
lemon 2022-09-27 19:31:54 +09:00 committed by GitHub
parent 51a92d170f
commit f1216090f7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 140 additions and 12 deletions

View File

@ -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

View File

@ -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()')
}

View 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() {
}

View File

View 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()
}

View File

@ -5,3 +5,4 @@ a == 0
0
three
6-9
b