parser: reimplement [flag] enum support. Add p.vcodegen too
parent
5825e467b8
commit
b0cfd3fa67
|
@ -6,7 +6,6 @@ import v.pref
|
||||||
|
|
||||||
const (
|
const (
|
||||||
skip_test_files = [
|
skip_test_files = [
|
||||||
'vlib/v/tests/enum_bitfield_test.v',
|
|
||||||
'vlib/net/http/http_httpbin_test.v',
|
'vlib/net/http/http_httpbin_test.v',
|
||||||
]
|
]
|
||||||
skip_on_musl = [
|
skip_on_musl = [
|
||||||
|
|
|
@ -577,6 +577,7 @@ pub struct EnumDecl {
|
||||||
pub:
|
pub:
|
||||||
name string
|
name string
|
||||||
is_pub bool
|
is_pub bool
|
||||||
|
is_flag bool // true when the enum has [flag] tag
|
||||||
fields []EnumField
|
fields []EnumField
|
||||||
pos token.Position
|
pos token.Position
|
||||||
}
|
}
|
||||||
|
|
|
@ -1401,7 +1401,7 @@ pub fn (mut c Checker) array_init(mut array_init ast.ArrayInit) table.Type {
|
||||||
// scope := c.file.scope.innermost(array_init.pos.pos)
|
// scope := c.file.scope.innermost(array_init.pos.pos)
|
||||||
// eprintln('scope: ${scope.str()}')
|
// eprintln('scope: ${scope.str()}')
|
||||||
// scope.find(it.name) or {
|
// scope.find(it.name) or {
|
||||||
// c.error('undefined: `$it.name`', array_init.pos)
|
// c.error('undefined ident: `$it.name`', array_init.pos)
|
||||||
// }
|
// }
|
||||||
mut full_const_name := if it.mod == 'main' { it.name } else { it.mod + '.' +
|
mut full_const_name := if it.mod == 'main' { it.name } else { it.mod + '.' +
|
||||||
it.name }
|
it.name }
|
||||||
|
@ -1951,7 +1951,7 @@ pub fn (mut c Checker) ident(mut ident ast.Ident) table.Type {
|
||||||
return table.int_type
|
return table.int_type
|
||||||
}
|
}
|
||||||
if ident.name != '_' {
|
if ident.name != '_' {
|
||||||
c.error('undefined: `$ident.name`', ident.pos)
|
c.error('undefined ident: `$ident.name`', ident.pos)
|
||||||
}
|
}
|
||||||
if c.table.known_type(ident.name) {
|
if c.table.known_type(ident.name) {
|
||||||
// e.g. `User` in `json.decode(User, '...')`
|
// e.g. `User` in `json.decode(User, '...')`
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
vlib/v/checker/tests/assign_expr_undefined_err_a.v:2:7: error: undefined: `a`
|
vlib/v/checker/tests/assign_expr_undefined_err_a.v:2:7: error: undefined variable: `a`
|
||||||
1 | fn main() {
|
1 | fn main() {
|
||||||
2 | a := a
|
2 | a := a
|
||||||
| ^
|
| ^
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
vlib/v/checker/tests/assign_expr_undefined_err_b.v:2:10: error: undefined: `a`
|
vlib/v/checker/tests/assign_expr_undefined_err_b.v:2:10: error: undefined variable: `a`
|
||||||
1 | fn main() {
|
1 | fn main() {
|
||||||
2 | a, b := a, b
|
2 | a, b := a, b
|
||||||
| ^
|
| ^
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
vlib/v/checker/tests/assign_expr_undefined_err_c.v:2:10: error: undefined: `a`
|
vlib/v/checker/tests/assign_expr_undefined_err_c.v:2:10: error: undefined variable: `a`
|
||||||
1 | fn main() {
|
1 | fn main() {
|
||||||
2 | a, b := a + 1, b * 3
|
2 | a, b := a + 1, b * 3
|
||||||
| ^
|
| ^
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
vlib/v/checker/tests/assign_expr_undefined_err_d.v:2:9: error: undefined: `s`
|
vlib/v/checker/tests/assign_expr_undefined_err_d.v:2:9: error: undefined variable: `s`
|
||||||
1 | fn main() {
|
1 | fn main() {
|
||||||
2 | s := '$s'
|
2 | s := '$s'
|
||||||
| ^
|
| ^
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
vlib/v/checker/tests/match_undefined_cond.v:4:15: error: undefined: `Asd`
|
vlib/v/checker/tests/match_undefined_cond.v:4:15: error: undefined ident: `Asd`
|
||||||
2 |
|
2 |
|
||||||
3 | fn main() {
|
3 | fn main() {
|
||||||
4 | res := match Asd {
|
4 | res := match Asd {
|
||||||
|
|
|
@ -14,7 +14,7 @@ fn (mut p Parser) check_undefined_variables(idents []ast.Ident, expr ast.Expr) {
|
||||||
ast.Ident {
|
ast.Ident {
|
||||||
for ident in idents {
|
for ident in idents {
|
||||||
if ident.name == it.name {
|
if ident.name == it.name {
|
||||||
p.error_with_pos('undefined: `$it.name`', it.pos)
|
p.error_with_pos('undefined variable: `$it.name`', it.pos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,6 +94,7 @@ pub fn parse_file(path string, b_table &table.Table, comments_mode scanner.Comme
|
||||||
global_scope: global_scope
|
global_scope: global_scope
|
||||||
}
|
}
|
||||||
// comments_mode: comments_mode
|
// comments_mode: comments_mode
|
||||||
|
p.init_parse_fns()
|
||||||
p.read_first_token()
|
p.read_first_token()
|
||||||
for p.tok.kind == .comment {
|
for p.tok.kind == .comment {
|
||||||
stmts << p.comment()
|
stmts << p.comment()
|
||||||
|
@ -126,6 +127,7 @@ pub fn parse_file(path string, b_table &table.Table, comments_mode scanner.Comme
|
||||||
// println('nr stmts = $stmts.len')
|
// println('nr stmts = $stmts.len')
|
||||||
// println(stmts[0])
|
// println(stmts[0])
|
||||||
p.scope.end_pos = p.tok.pos
|
p.scope.end_pos = p.tok.pos
|
||||||
|
//
|
||||||
return ast.File{
|
return ast.File{
|
||||||
path: path
|
path: path
|
||||||
mod: module_decl
|
mod: module_decl
|
||||||
|
@ -210,7 +212,6 @@ pub fn parse_files(paths []string, table &table.Table, pref &pref.Preferences, g
|
||||||
pub fn (p &Parser) init_parse_fns() {
|
pub fn (p &Parser) init_parse_fns() {
|
||||||
// p.prefix_parse_fns = make(100, 100, sizeof(PrefixParseFn))
|
// p.prefix_parse_fns = make(100, 100, sizeof(PrefixParseFn))
|
||||||
// p.prefix_parse_fns[token.Kind.name] = parse_name
|
// p.prefix_parse_fns[token.Kind.name] = parse_name
|
||||||
println('')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut p Parser) read_first_token() {
|
pub fn (mut p Parser) read_first_token() {
|
||||||
|
@ -1371,17 +1372,35 @@ fn (mut p Parser) enum_decl() ast.EnumDecl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
p.check(.rcbr)
|
p.check(.rcbr)
|
||||||
|
attr := p.attr
|
||||||
|
is_flag := attr == 'flag'
|
||||||
|
if is_flag {
|
||||||
|
if fields.len > 32 {
|
||||||
|
p.error('when an enum is used as bit field, it must have a max of 32 fields')
|
||||||
|
}
|
||||||
|
pubfn := if p.mod == 'main' { 'fn' } else { 'pub fn' }
|
||||||
|
p.scanner.codegen('
|
||||||
|
//
|
||||||
|
$pubfn ( e &$name) has(flag $name) bool { return (int(*e) & (1 << int(flag))) != 0 }
|
||||||
|
$pubfn (mut e $name) set(flag $name) { unsafe{ *e = int(*e) | (1 << int(flag)) } }
|
||||||
|
$pubfn (mut e $name) clear(flag $name) { unsafe{ *e = int(*e) & ~(1 << int(flag)) } }
|
||||||
|
$pubfn (mut e $name) toggle(flag $name) { unsafe{ *e = int(*e) ^ (1 << int(flag)) } }
|
||||||
|
//
|
||||||
|
')
|
||||||
|
}
|
||||||
p.table.register_type_symbol(table.TypeSymbol{
|
p.table.register_type_symbol(table.TypeSymbol{
|
||||||
kind: .enum_
|
kind: .enum_
|
||||||
name: name
|
name: name
|
||||||
mod: p.mod
|
mod: p.mod
|
||||||
info: table.Enum{
|
info: table.Enum{
|
||||||
vals: vals
|
vals: vals
|
||||||
|
is_flag: is_flag
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return ast.EnumDecl{
|
return ast.EnumDecl{
|
||||||
name: name
|
name: name
|
||||||
is_pub: is_pub
|
is_pub: is_pub
|
||||||
|
is_flag: is_flag
|
||||||
fields: fields
|
fields: fields
|
||||||
pos: start_pos.extend(end_pos)
|
pos: start_pos.extend(end_pos)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1121,3 +1121,15 @@ pub fn (s &Scanner) error(msg string) {
|
||||||
pub fn verror(s string) {
|
pub fn verror(s string) {
|
||||||
util.verror('scanner error', s)
|
util.verror('scanner error', s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn (mut s Scanner) codegen(newtext string) {
|
||||||
|
// codegen makes sense only during normal compilation
|
||||||
|
// feeding code generated V code to vfmt or vdoc will
|
||||||
|
// cause them to output/document ephemeral stuff.
|
||||||
|
if s.comments_mode == .skip_comments {
|
||||||
|
s.text += newtext
|
||||||
|
$if debug_codegen ? {
|
||||||
|
eprintln('scanner.codegen:\n $newtext')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -611,6 +611,7 @@ pub mut:
|
||||||
pub struct Enum {
|
pub struct Enum {
|
||||||
pub:
|
pub:
|
||||||
vals []string
|
vals []string
|
||||||
|
is_flag bool
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Alias {
|
pub struct Alias {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
println(a)
|
println(a)
|
||||||
===output===
|
===output===
|
||||||
.vrepl.v:2:9: error: undefined: `a`
|
.vrepl.v:2:9: error: undefined ident: `a`
|
||||||
1 |
|
1 |
|
||||||
2 | println(a)
|
2 | println(a)
|
||||||
| ^
|
| ^
|
||||||
|
|
Loading…
Reference in New Issue