diff --git a/vlib/builtin/builtin.v b/vlib/builtin/builtin.v index 2559002380..d43196e8f7 100644 --- a/vlib/builtin/builtin.v +++ b/vlib/builtin/builtin.v @@ -4,8 +4,8 @@ module builtin __global ( - g_m2_buf &byte - g_m2_ptr &byte + g_m2_buf &byte + g_m2_ptr &byte ) // isnil returns true if an object is nil (only for C objects). @@ -48,7 +48,7 @@ __global ( total_m = i64(0) nr_mallocs = int(0) // will be filled in cgen - as_cast_type_indexes []VCastTypeIndexName + as_cast_type_indexes []VCastTypeIndexName ) fn __as_cast(obj voidptr, obj_type int, expected_type int) voidptr { diff --git a/vlib/builtin/builtin_windows.c.v b/vlib/builtin/builtin_windows.c.v index be7bfb8e12..3cd3d6350d 100644 --- a/vlib/builtin/builtin_windows.c.v +++ b/vlib/builtin/builtin_windows.c.v @@ -66,7 +66,9 @@ const ( ) // g_original_codepage - used to restore the original windows console code page when exiting -__global ( g_original_codepage = u32(0)) +__global ( + g_original_codepage = u32(0) +) // utf8 to stdout needs C.SetConsoleOutputCP(C.CP_UTF8) fn C.GetConsoleOutputCP() u32 diff --git a/vlib/builtin/string.v b/vlib/builtin/string.v index 7e3969cb32..412f27dc41 100644 --- a/vlib/builtin/string.v +++ b/vlib/builtin/string.v @@ -1285,7 +1285,9 @@ pub fn (s string) ustring() ustring { // A hack that allows to create ustring without allocations. // It's called from functions like draw_text() where we know that the string is going to be freed // right away. Uses global buffer for storing runes []int array. -__global ( g_ustring_runes []int ) +__global ( + g_ustring_runes []int +) pub fn (s string) ustring_tmp() ustring { if g_ustring_runes.len == 0 { diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index 20d3ea4a7e..5ee9fb5a63 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -526,7 +526,8 @@ pub mut: pub struct GlobalDecl { pub: - pos token.Position + pos token.Position + is_block bool // __global() block pub mut: fields []GlobalField end_comments []Comment diff --git a/vlib/v/checker/tests/globals/assign_no_type.out b/vlib/v/checker/tests/globals/assign_no_type.out index abc2238987..5782878412 100644 --- a/vlib/v/checker/tests/globals/assign_no_type.out +++ b/vlib/v/checker/tests/globals/assign_no_type.out @@ -1,3 +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 )` +vlib/v/checker/tests/globals/assign_no_type.vv:1:21: error: global assign must have a type and value, use `name = type(value)` or `name type` 1 | __global ( test = 0 ) | ^ diff --git a/vlib/v/checker/tests/globals/assign_no_value.out b/vlib/v/checker/tests/globals/assign_no_value.out index 7270daa7fe..00b93ef683 100644 --- a/vlib/v/checker/tests/globals/assign_no_value.out +++ b/vlib/v/checker/tests/globals/assign_no_value.out @@ -1,3 +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 )` +vlib/v/checker/tests/globals/assign_no_value.vv:1:23: error: global assign must have a type and value, use `name = type(value)` or `name type` 1 | __global ( test = int ) | ^ diff --git a/vlib/v/checker/tests/globals/unexpected_eof.out b/vlib/v/checker/tests/globals/unexpected_eof.out new file mode 100644 index 0000000000..f0a6cbcb23 --- /dev/null +++ b/vlib/v/checker/tests/globals/unexpected_eof.out @@ -0,0 +1,3 @@ +vlib/v/checker/tests/globals/unexpected_eof.vv:3:1: error: unexpected eof, expecting ´)´ + 1 | __global ( + 2 | x string diff --git a/vlib/v/checker/tests/globals/unexpected_eof.vv b/vlib/v/checker/tests/globals/unexpected_eof.vv new file mode 100644 index 0000000000..ab9c9c684c --- /dev/null +++ b/vlib/v/checker/tests/globals/unexpected_eof.vv @@ -0,0 +1,2 @@ +__global ( + x string diff --git a/vlib/v/fmt/fmt.v b/vlib/v/fmt/fmt.v index 12f94cd582..5458d1deb3 100644 --- a/vlib/v/fmt/fmt.v +++ b/vlib/v/fmt/fmt.v @@ -1083,21 +1083,23 @@ pub fn (mut f Fmt) for_stmt(node ast.ForStmt) { } pub fn (mut f Fmt) global_decl(node ast.GlobalDecl) { - single := node.fields.len == 1 - if single { - f.write('__global ( ') - } else { - f.writeln('__global (') - f.indent++ + if node.fields.len == 0 && node.pos.line_nr == node.pos.last_line { + f.writeln('__global ()') + return } + f.write('__global ') mut max := 0 mut has_assign := false - for field in node.fields { - if field.name.len > max { - max = field.name.len - } - if field.has_expr { - has_assign = true + if node.is_block { + f.writeln('(') + f.indent++ + for field in node.fields { + if field.name.len > max { + max = field.name.len + } + if field.has_expr { + has_assign = true + } } } for field in node.fields { @@ -1111,20 +1113,19 @@ pub fn (mut f Fmt) global_decl(node ast.GlobalDecl) { f.expr(field.expr) f.write(')') } else { - if !single && has_assign { - f.write(' ') - } - f.write('${f.table.type_to_str_using_aliases(field.typ, f.mod2alias)} ') + f.write('${f.table.type_to_str_using_aliases(field.typ, f.mod2alias)}') } - if !single { + if node.is_block { f.writeln('') } } - if !single { - f.indent-- - } f.comments_after_last_field(node.end_comments) - f.writeln(')\n') + if node.is_block { + f.indent-- + f.writeln(')') + } else { + f.writeln('') + } } pub fn (mut f Fmt) go_expr(node ast.GoExpr) { diff --git a/vlib/v/fmt/tests/global_keep.vv b/vlib/v/fmt/tests/global_keep.vv new file mode 100644 index 0000000000..e809f3d2fe --- /dev/null +++ b/vlib/v/fmt/tests/global_keep.vv @@ -0,0 +1,10 @@ +__global x = bool(true) +__global y f32 +__global () +__global ( + spam string + foo = int(5) +) +__global ( + a int +) diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index dace207f2d..469266c6d4 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -2818,17 +2818,19 @@ fn (mut p Parser) global_decl() ast.GlobalDecl { return ast.GlobalDecl{} } start_pos := p.tok.position() - end_pos := p.tok.position() p.check(.key_global) - if p.tok.kind != .lpar { - p.error('globals must be grouped, e.g. `__global ( a = int(1) )`') - return ast.GlobalDecl{} + is_block := p.tok.kind == .lpar + if is_block { + p.next() // ( } - p.next() // ( mut fields := []ast.GlobalField{} mut comments := []ast.Comment{} for { comments = p.eat_comments({}) + if is_block && p.tok.kind == .eof { + p.error('unexpected eof, expecting ´)´') + return ast.GlobalDecl{} + } if p.tok.kind == .rpar { break } @@ -2840,13 +2842,13 @@ fn (mut p Parser) global_decl() ast.GlobalDecl { } typ := p.parse_type() if p.tok.kind == .assign { - p.error('global assign must have the type around the value, use `__global ( name = type(value) )`') + p.error('global assign must have the type around the value, use `name = type(value)`') return ast.GlobalDecl{} } mut expr := ast.empty_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.error('global assign must have a type and value, use `name = type(value)` or `name type`') return ast.GlobalDecl{} } p.next() // ( @@ -2864,12 +2866,18 @@ fn (mut p Parser) global_decl() ast.GlobalDecl { fields << field p.global_scope.register(field) comments = [] + if !is_block { + break + } + } + if is_block { + p.check(.rpar) } - p.check(.rpar) return ast.GlobalDecl{ - pos: start_pos.extend(end_pos) + pos: start_pos.extend(p.prev_tok.position()) fields: fields end_comments: comments + is_block: is_block } }