syntax: new global variable declaration syntax (#6540)
parent
8ac0bd44bd
commit
c9574ae7d7
|
@ -21,7 +21,7 @@ pub type Stmt = AssertStmt | AssignStmt | Block | BranchStmt | CompFor | ConstDe
|
||||||
GotoLabel | GotoStmt | HashStmt | Import | InterfaceDecl | Module | Return | SqlStmt |
|
GotoLabel | GotoStmt | HashStmt | Import | InterfaceDecl | Module | Return | SqlStmt |
|
||||||
StructDecl | TypeDecl
|
StructDecl | TypeDecl
|
||||||
|
|
||||||
pub type ScopeObject = ConstField | GlobalDecl | Var
|
pub type ScopeObject = ConstField | GlobalField | Var
|
||||||
|
|
||||||
pub struct Type {
|
pub struct Type {
|
||||||
pub:
|
pub:
|
||||||
|
@ -346,7 +346,7 @@ pub mut:
|
||||||
is_changed bool // to detect mutable vars that are never changed
|
is_changed bool // to detect mutable vars that are never changed
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct GlobalDecl {
|
pub struct GlobalField {
|
||||||
pub:
|
pub:
|
||||||
name string
|
name string
|
||||||
expr Expr
|
expr Expr
|
||||||
|
@ -354,6 +354,15 @@ pub:
|
||||||
pos token.Position
|
pos token.Position
|
||||||
pub mut:
|
pub mut:
|
||||||
typ table.Type
|
typ table.Type
|
||||||
|
comments []Comment
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct GlobalDecl {
|
||||||
|
pub:
|
||||||
|
pos token.Position
|
||||||
|
pub mut:
|
||||||
|
fields []GlobalField
|
||||||
|
end_comments []Comment
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct File {
|
pub struct File {
|
||||||
|
|
|
@ -38,6 +38,7 @@ pub mut:
|
||||||
const_decl string
|
const_decl string
|
||||||
const_deps []string
|
const_deps []string
|
||||||
const_names []string
|
const_names []string
|
||||||
|
global_names []string
|
||||||
locked_names []string // vars that are currently locked
|
locked_names []string // vars that are currently locked
|
||||||
rlocked_names []string // vars that are currently read-locked
|
rlocked_names []string // vars that are currently read-locked
|
||||||
pref &pref.Preferences // Preferences shared from V struct
|
pref &pref.Preferences // Preferences shared from V struct
|
||||||
|
@ -1954,7 +1955,7 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) {
|
||||||
if left_type != 0 {
|
if left_type != 0 {
|
||||||
match mut left.obj as v {
|
match mut left.obj as v {
|
||||||
ast.Var { v.typ = left_type }
|
ast.Var { v.typ = left_type }
|
||||||
ast.GlobalDecl { v.typ = left_type }
|
ast.GlobalField { v.typ = left_type }
|
||||||
else {}
|
else {}
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
@ -2372,7 +2373,13 @@ fn (mut c Checker) stmt(node ast.Stmt) {
|
||||||
c.in_for_count--
|
c.in_for_count--
|
||||||
}
|
}
|
||||||
ast.GlobalDecl {
|
ast.GlobalDecl {
|
||||||
c.check_valid_snake_case(node.name, 'global name', node.pos)
|
for field in node.fields {
|
||||||
|
c.check_valid_snake_case(field.name, 'global name', field.pos)
|
||||||
|
if field.name in c.global_names {
|
||||||
|
c.error('duplicate global `$field.name`', field.pos)
|
||||||
|
}
|
||||||
|
c.global_names << field.name
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ast.GoStmt {
|
ast.GoStmt {
|
||||||
if node.call_expr !is ast.CallExpr {
|
if node.call_expr !is ast.CallExpr {
|
||||||
|
@ -2865,7 +2872,7 @@ pub fn (mut c Checker) ident(mut ident ast.Ident) table.Type {
|
||||||
start_scope := c.file.scope.innermost(ident.pos.pos)
|
start_scope := c.file.scope.innermost(ident.pos.pos)
|
||||||
if obj1 := start_scope.find(ident.name) {
|
if obj1 := start_scope.find(ident.name) {
|
||||||
match mut obj1 as obj {
|
match mut obj1 as obj {
|
||||||
ast.GlobalDecl {
|
ast.GlobalField {
|
||||||
ident.kind = .global
|
ident.kind = .global
|
||||||
ident.info = ast.IdentVar{
|
ident.info = ast.IdentVar{
|
||||||
typ: obj.typ
|
typ: obj.typ
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
vlib/v/checker/tests/globals/assign_no_type.vv:1:21: error: global assign must have a type and value, use `__global ( name = type(value) )` or `__global ( name type )`
|
||||||
|
1 | __global ( test = 0 )
|
||||||
|
| ^
|
|
@ -0,0 +1 @@
|
||||||
|
__global ( test = 0 )
|
|
@ -0,0 +1,3 @@
|
||||||
|
vlib/v/checker/tests/globals/assign_no_value.vv:1:23: error: global assign must have a type and value, use `__global ( name = type(value) )` or `__global ( name type )`
|
||||||
|
1 | __global ( test = int )
|
||||||
|
| ^
|
|
@ -0,0 +1 @@
|
||||||
|
__global ( test = int )
|
|
@ -1,3 +1,3 @@
|
||||||
vlib/v/checker/tests/globals/incorrect_name_global.vv:1:1: error: global name `A` cannot contain uppercase letters, use snake_case instead
|
vlib/v/checker/tests/globals/incorrect_name_global.vv:1:12: error: global name `A` cannot contain uppercase letters, use snake_case instead
|
||||||
1 | __global A int = 1
|
1 | __global ( A = int(1) )
|
||||||
| ~~~~~~~~~~
|
| ^
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
__global A int = 1
|
__global ( A = int(1) )
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
vlib/v/checker/tests/globals/no_type.vv:1:17: error: bad type syntax
|
||||||
|
1 | __global ( test )
|
||||||
|
| ^
|
|
@ -0,0 +1 @@
|
||||||
|
__global ( test )
|
|
@ -1,6 +1,6 @@
|
||||||
vlib/v/checker/tests/globals_error.vv:2:1: error: use `v --enable-globals ...` to enable globals
|
vlib/v/checker/tests/globals_error.vv:2:1: error: use `v --enable-globals ...` to enable globals
|
||||||
1 |
|
1 |
|
||||||
2 | __global rfcnt int
|
2 | __global ( rfcnt int )
|
||||||
| ~~~~~~~~
|
| ~~~~~~~~
|
||||||
3 |
|
3 |
|
||||||
4 | fn abc(){
|
4 | fn abc(){
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
|
|
||||||
__global rfcnt int
|
__global ( rfcnt int )
|
||||||
|
|
||||||
fn abc(){
|
fn abc(){
|
||||||
rfcnt = 2
|
rfcnt = 2
|
||||||
|
|
|
@ -399,13 +399,7 @@ pub fn (mut f Fmt) stmt(node ast.Stmt) {
|
||||||
f.writeln('}')
|
f.writeln('}')
|
||||||
}
|
}
|
||||||
ast.GlobalDecl {
|
ast.GlobalDecl {
|
||||||
f.write('__global $it.name ')
|
f.global_decl(it)
|
||||||
f.write(f.type_to_str(it.typ))
|
|
||||||
if it.has_expr {
|
|
||||||
f.write(' = ')
|
|
||||||
f.expr(it.expr)
|
|
||||||
}
|
|
||||||
f.writeln('')
|
|
||||||
}
|
}
|
||||||
ast.GoStmt {
|
ast.GoStmt {
|
||||||
f.write('go ')
|
f.write('go ')
|
||||||
|
@ -1885,6 +1879,58 @@ pub fn (mut f Fmt) const_decl(it ast.ConstDecl) {
|
||||||
f.writeln(')\n')
|
f.writeln(')\n')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn (mut f Fmt) global_decl(it ast.GlobalDecl) {
|
||||||
|
single := it.fields.len == 1
|
||||||
|
if single {
|
||||||
|
f.write('__global ( ')
|
||||||
|
} else {
|
||||||
|
f.write('__global (')
|
||||||
|
f.writeln('')
|
||||||
|
f.indent++
|
||||||
|
}
|
||||||
|
mut max := 0
|
||||||
|
mut has_assign := false
|
||||||
|
for field in it.fields {
|
||||||
|
if field.name.len > max {
|
||||||
|
max = field.name.len
|
||||||
|
}
|
||||||
|
if field.has_expr {
|
||||||
|
has_assign = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for field in it.fields {
|
||||||
|
comments := field.comments
|
||||||
|
for comment in comments {
|
||||||
|
f.comment(comment, {
|
||||||
|
inline: true
|
||||||
|
})
|
||||||
|
f.writeln('')
|
||||||
|
}
|
||||||
|
f.write('$field.name ')
|
||||||
|
f.write(strings.repeat(` `, max - field.name.len))
|
||||||
|
if field.has_expr {
|
||||||
|
f.write('= ')
|
||||||
|
f.write(f.type_to_str(field.typ))
|
||||||
|
f.write('(')
|
||||||
|
f.expr(field.expr)
|
||||||
|
f.write(')')
|
||||||
|
} else {
|
||||||
|
if !single && has_assign {
|
||||||
|
f.write(' ')
|
||||||
|
}
|
||||||
|
f.write('${f.type_to_str(field.typ)} ')
|
||||||
|
}
|
||||||
|
if !single {
|
||||||
|
f.writeln('')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !single {
|
||||||
|
f.indent--
|
||||||
|
}
|
||||||
|
f.comments_after_last_field(it.end_comments)
|
||||||
|
f.writeln(')\n')
|
||||||
|
}
|
||||||
|
|
||||||
fn (mut f Fmt) is_external_name(name string) bool {
|
fn (mut f Fmt) is_external_name(name string) bool {
|
||||||
if name.len > 2 && name[0] == `C` && name[1] == `.` {
|
if name.len > 2 && name[0] == `C` && name[1] == `.` {
|
||||||
return true
|
return true
|
||||||
|
|
|
@ -937,8 +937,7 @@ fn (mut g Gen) stmt(node ast.Stmt) {
|
||||||
g.writeln('}')
|
g.writeln('}')
|
||||||
}
|
}
|
||||||
ast.GlobalDecl {
|
ast.GlobalDecl {
|
||||||
styp := g.typ(node.typ)
|
g.global_decl(node)
|
||||||
g.definitions.writeln('$styp $node.name; // global')
|
|
||||||
}
|
}
|
||||||
ast.GoStmt {
|
ast.GoStmt {
|
||||||
g.go_stmt(node)
|
g.go_stmt(node)
|
||||||
|
@ -3662,6 +3661,17 @@ fn (mut g Gen) const_decl_init_later(mod, name, val string, typ table.Type) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn (mut g Gen) global_decl(node ast.GlobalDecl) {
|
||||||
|
for field in node.fields {
|
||||||
|
styp := g.typ(field.typ)
|
||||||
|
if field.has_expr {
|
||||||
|
g.definitions.writeln('$styp $field.name = $field.expr; // global')
|
||||||
|
} else {
|
||||||
|
g.definitions.writeln('$styp $field.name; // global')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn (mut g Gen) go_back_out(n int) {
|
fn (mut g Gen) go_back_out(n int) {
|
||||||
g.out.go_back(n)
|
g.out.go_back(n)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1676,41 +1676,79 @@ fn (mut p Parser) global_decl() ast.GlobalDecl {
|
||||||
p.error('use `v --enable-globals ...` to enable globals')
|
p.error('use `v --enable-globals ...` to enable globals')
|
||||||
}
|
}
|
||||||
start_pos := p.tok.position()
|
start_pos := p.tok.position()
|
||||||
p.next()
|
end_pos := p.tok.position()
|
||||||
pos := start_pos.extend(p.tok.position())
|
p.check(.key_global)
|
||||||
name := p.check_name()
|
if p.tok.kind != .lpar {
|
||||||
// println(name)
|
// Need to work for intermediate V Compiler for PRs process
|
||||||
typ := p.parse_type()
|
// p.error('globals must be grouped, e.g. `__global ( a = int(1) )`')
|
||||||
mut expr := ast.Expr{}
|
pos := p.tok.position()
|
||||||
has_expr := p.tok.kind == .assign
|
name := p.check_name()
|
||||||
if has_expr {
|
typ := p.parse_type()
|
||||||
p.next()
|
mut expr := ast.Expr{}
|
||||||
expr = p.expr(0)
|
has_expr := p.tok.kind == .assign
|
||||||
|
if has_expr {
|
||||||
|
p.next()
|
||||||
|
expr = p.expr(0)
|
||||||
|
}
|
||||||
|
mut fields := []ast.GlobalField{}
|
||||||
|
field := ast.GlobalField{
|
||||||
|
name: name
|
||||||
|
has_expr: has_expr
|
||||||
|
expr: expr
|
||||||
|
pos: pos
|
||||||
|
typ: typ
|
||||||
|
comments: []ast.Comment{}
|
||||||
|
}
|
||||||
|
fields << field
|
||||||
|
p.global_scope.register(field.name, field)
|
||||||
|
return ast.GlobalDecl{
|
||||||
|
fields: fields
|
||||||
|
pos: start_pos.extend(end_pos)
|
||||||
|
end_comments: []ast.Comment{}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// p.genln(p.table.cgen_name_type_pair(name, typ))
|
p.next() // (
|
||||||
/*
|
mut fields := []ast.GlobalField{}
|
||||||
mut g := p.table.cgen_name_type_pair(name, typ)
|
mut comments := []ast.Comment{}
|
||||||
if p.tok == .assign {
|
for {
|
||||||
p.next()
|
comments = p.eat_comments()
|
||||||
g += ' = '
|
if p.tok.kind == .rpar {
|
||||||
_,expr := p.tmp_expr()
|
break
|
||||||
g += expr
|
}
|
||||||
|
pos := p.tok.position()
|
||||||
|
name := p.check_name()
|
||||||
|
has_expr := p.tok.kind == .assign
|
||||||
|
if has_expr {
|
||||||
|
p.next() // =
|
||||||
|
}
|
||||||
|
typ := p.parse_type()
|
||||||
|
mut expr := ast.Expr{}
|
||||||
|
if has_expr {
|
||||||
|
if p.tok.kind != .lpar {
|
||||||
|
p.error('global assign must have a type and value, use `__global ( name = type(value) )` or `__global ( name type )`')
|
||||||
|
}
|
||||||
|
p.next() // (
|
||||||
|
expr = p.expr(0)
|
||||||
|
p.check(.rpar)
|
||||||
|
}
|
||||||
|
field := ast.GlobalField{
|
||||||
|
name: name
|
||||||
|
has_expr: has_expr
|
||||||
|
expr: expr
|
||||||
|
pos: pos
|
||||||
|
typ: typ
|
||||||
|
comments: comments
|
||||||
|
}
|
||||||
|
fields << field
|
||||||
|
p.global_scope.register(field.name, field)
|
||||||
|
comments = []
|
||||||
}
|
}
|
||||||
// p.genln('; // global')
|
p.check(.rpar)
|
||||||
g += '; // global'
|
return ast.GlobalDecl{
|
||||||
if !p.cgen.nogen {
|
pos: start_pos.extend(end_pos)
|
||||||
p.cgen.consts << g
|
fields: fields
|
||||||
|
end_comments: comments
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
glob := ast.GlobalDecl{
|
|
||||||
name: name
|
|
||||||
typ: typ
|
|
||||||
pos: pos
|
|
||||||
has_expr: has_expr
|
|
||||||
expr: expr
|
|
||||||
}
|
|
||||||
p.global_scope.register(name, glob)
|
|
||||||
return glob
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut p Parser) enum_decl() ast.EnumDecl {
|
fn (mut p Parser) enum_decl() ast.EnumDecl {
|
||||||
|
|
Loading…
Reference in New Issue