From 2f51938ef7397270dda33963a1c5e1fb8f44d0f6 Mon Sep 17 00:00:00 2001 From: Delyan Angelov Date: Thu, 19 Dec 2024 22:28:52 +0200 Subject: [PATCH 1/2] v,ast,fmt,parser: support @[tag] for hash statements like `#define` and `#flag` --- cmd/tools/vast/vast.v | 8 +++++--- vlib/fontstash/fontstash.c.v | 2 ++ vlib/sokol/audio/audio.c.v | 2 ++ vlib/sokol/c/declaration.c.v | 6 ++++++ vlib/sokol/f/f.v | 1 + vlib/v/ast/ast.v | 2 ++ vlib/v/fmt/fmt.v | 1 + vlib/v/fmt/tests/hashstmt_keep.vv | 6 ++++++ vlib/v/parser/comptime.v | 12 ++++++++++++ 9 files changed, 37 insertions(+), 3 deletions(-) diff --git a/cmd/tools/vast/vast.v b/cmd/tools/vast/vast.v index f8e4db9828ee56..9ad057c91ea894 100644 --- a/cmd/tools/vast/vast.v +++ b/cmd/tools/vast/vast.v @@ -592,7 +592,7 @@ fn (t Tree) fn_decl(node ast.FnDecl) &Node { obj.add_terse('return_type', t.type_node(node.return_type)) obj.add('source_file', t.number_node(int(node.source_file))) obj.add('scope', t.number_node(int(node.scope))) - obj.add('attrs', t.array_node_attr(node.attrs)) + obj.add_terse('attrs', t.array_node_attr(node.attrs)) obj.add_terse('params', t.array_node_arg(node.params)) obj.add_terse('generic_names', t.array_node_string(node.generic_names)) obj.add_terse('stmts', t.array_node_stmt(node.stmts)) @@ -756,8 +756,10 @@ fn (t Tree) hash_stmt(node ast.HashStmt) &Node { obj.add_terse('kind', t.string_node(node.kind)) obj.add_terse('main', t.string_node(node.main)) obj.add_terse('msg', t.string_node(node.msg)) + obj.add_terse('is_use_once', t.bool_node(node.is_use_once)) obj.add_terse('ct_conds', t.array_node_expr(node.ct_conds)) obj.add_terse('source_file', t.string_node(node.source_file)) + obj.add_terse('attrs', t.array_node_attr(node.attrs)) obj.add('pos', t.pos(node.pos)) return obj } @@ -778,11 +780,11 @@ fn (t Tree) global_decl(node ast.GlobalDecl) &Node { mut obj := new_object() obj.add_terse('ast_type', t.string_node('GlobalDecl')) obj.add_terse('mod', t.string_node(node.mod)) - obj.add('pos', t.pos(node.pos)) + obj.add_terse('attrs', t.array_node_attr(node.attrs)) obj.add_terse('is_block', t.bool_node(node.is_block)) obj.add_terse('fields', t.array_node_global_field(node.fields)) + obj.add('pos', t.pos(node.pos)) obj.add('end_comments', t.array_node_comment(node.end_comments)) - obj.add('attrs', t.array_node_attr(node.attrs)) return obj } diff --git a/vlib/fontstash/fontstash.c.v b/vlib/fontstash/fontstash.c.v index e30a41812f157d..0b151b1e08edd6 100644 --- a/vlib/fontstash/fontstash.c.v +++ b/vlib/fontstash/fontstash.c.v @@ -1,6 +1,8 @@ module fontstash #flag -I @VEXEROOT/thirdparty/fontstash + +@[use_once] #define FONTSTASH_IMPLEMENTATION $if gcboehm ? { #define FONTSTASH_MALLOC GC_MALLOC diff --git a/vlib/sokol/audio/audio.c.v b/vlib/sokol/audio/audio.c.v index 706b1e654d0414..3fdf3350c79cd5 100644 --- a/vlib/sokol/audio/audio.c.v +++ b/vlib/sokol/audio/audio.c.v @@ -10,6 +10,8 @@ $if linux { #flag -I @VEXEROOT/thirdparty/sokol // FreeBSD requires the audio/alsa-lib to be installed #flag freebsd -I/usr/local/include + +@[use_once] #define SOKOL_IMPL #include "sokol_audio.h" #flag linux -lasound -lpthread diff --git a/vlib/sokol/c/declaration.c.v b/vlib/sokol/c/declaration.c.v index 9160dac2fa5e58..19e1d97808682c 100644 --- a/vlib/sokol/c/declaration.c.v +++ b/vlib/sokol/c/declaration.c.v @@ -56,6 +56,8 @@ $if emscripten ? { //#flag windows -DSOKOL_D3D11 // for simplicity, all header includes are here because import order matters and we dont have any way // to ensure import order with V yet + +@[use_once] #define SOKOL_IMPL // TODO: should not be defined for android graphic (apk/aab using sokol) builds, but we have no ways to undefine //#define SOKOL_NO_ENTRY @@ -75,9 +77,13 @@ $if emscripten ? { $if !no_sokol_app ? { #include "sokol_app.h" } + +@[use_once] #define SOKOL_IMPL #define SOKOL_NO_DEPRECATED #include "sokol_gfx.h" + +@[use_once] #define SOKOL_GL_IMPL #include "util/sokol_gl.h" #include "sokol_v.post.h" diff --git a/vlib/sokol/f/f.v b/vlib/sokol/f/f.v index ce1998bf1dc416..1a096728c3d58a 100644 --- a/vlib/sokol/f/f.v +++ b/vlib/sokol/f/f.v @@ -7,5 +7,6 @@ import sokol.c as _ //#include "ft2build.h" +@[use_once] #define SOKOL_FONTSTASH_IMPL #include "util/sokol_fontstash.h" diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index dcb6c443595145..1f39d9a326f2a3 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -1365,6 +1365,7 @@ pub: mod string pos token.Pos source_file string + is_use_once bool // true for @[use_once] pub mut: val string // example: 'include # please install openssl // comment' kind string // : 'include' @@ -1372,6 +1373,7 @@ pub mut: msg string // : 'please install openssl' ct_conds []Expr // *all* comptime conditions, that must be true, for the hash to be processed // ct_conds is filled by the checker, based on the current nesting of `$if cond1 {}` blocks + attrs []Attr } // variable assign statement diff --git a/vlib/v/fmt/fmt.v b/vlib/v/fmt/fmt.v index b3bfc4145c0095..9e7f1aba2e3a5f 100644 --- a/vlib/v/fmt/fmt.v +++ b/vlib/v/fmt/fmt.v @@ -1361,6 +1361,7 @@ pub fn (mut f Fmt) goto_stmt(node ast.GotoStmt) { } pub fn (mut f Fmt) hash_stmt(node ast.HashStmt) { + f.attrs(node.attrs) f.writeln('#${node.val}') } diff --git a/vlib/v/fmt/tests/hashstmt_keep.vv b/vlib/v/fmt/tests/hashstmt_keep.vv index 4d02369f750433..4a56b83ed489d5 100644 --- a/vlib/v/fmt/tests/hashstmt_keep.vv +++ b/vlib/v/fmt/tests/hashstmt_keep.vv @@ -10,3 +10,9 @@ // comment between without newlines #include "sqlite3.h" // comment directly after the HsahStmt + +@[another; use_once] +#define SOME_SINGLE_HEADER_IMPL 1 + +@[custom_tag; use_once] +#flag -I @VMODROOT/c/something/else diff --git a/vlib/v/parser/comptime.v b/vlib/v/parser/comptime.v index 9f14a749d63b6b..19fe361c415090 100644 --- a/vlib/v/parser/comptime.v +++ b/vlib/v/parser/comptime.v @@ -78,6 +78,7 @@ fn (mut p Parser) hash() ast.HashStmt { pos := p.tok.pos() val := p.tok.lit kind := val.all_before(' ') + attrs := p.attrs p.next() mut main_str := '' mut msg := '' @@ -89,6 +90,15 @@ fn (mut p Parser) hash() ast.HashStmt { main_str = content.trim_space() msg = '' } + + mut is_use_once := false + for fna in attrs { + match fna.name { + 'use_once' { is_use_once = true } + else {} + } + } + return ast.HashStmt{ mod: p.mod source_file: p.file_path @@ -97,6 +107,8 @@ fn (mut p Parser) hash() ast.HashStmt { main: main_str msg: msg pos: pos + attrs: attrs + is_use_once: is_use_once } } From 5f2c233637b5a053909e9611495c2aaf28aede08 Mon Sep 17 00:00:00 2001 From: Delyan Angelov Date: Thu, 19 Dec 2024 22:42:33 +0200 Subject: [PATCH 2/2] fix formatting of fns containing # statements in the .js.v files --- vlib/v/parser/fn.v | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/vlib/v/parser/fn.v b/vlib/v/parser/fn.v index 3464c518675470..e5bb1250387d29 100644 --- a/vlib/v/parser/fn.v +++ b/vlib/v/parser/fn.v @@ -203,7 +203,9 @@ fn (mut p Parser) fn_decl() ast.FnDecl { mut is_markused := false mut is_expand_simple_interpolation := false mut comments := []ast.Comment{} - for fna in p.attrs { + fn_attrs := p.attrs + p.attrs = [] + for fna in fn_attrs { match fna.name { 'noreturn' { is_noreturn = true @@ -271,7 +273,7 @@ fn (mut p Parser) fn_decl() ast.FnDecl { else {} } } - conditional_ctdefine_idx := p.attrs.find_comptime_define() or { -1 } + conditional_ctdefine_idx := fn_attrs.find_comptime_define() or { -1 } is_pub := p.tok.kind == .key_pub if is_pub { p.next() @@ -286,7 +288,7 @@ fn (mut p Parser) fn_decl() ast.FnDecl { mut language := p.parse_language() p.fn_language = language if language != .v { - for fna in p.attrs { + for fna in fn_attrs { if fna.name == 'export' { p.error_with_pos('interop function cannot be exported', fna.pos) break @@ -555,7 +557,7 @@ run them via `v file.v` instead', is_method: true receiver_type: rec.typ // - attrs: p.attrs + attrs: fn_attrs is_conditional: conditional_ctdefine_idx != ast.invalid_type_idx ctdefine_idx: conditional_ctdefine_idx // @@ -611,7 +613,7 @@ run them via `v file.v` instead', receiver_type: if is_static_type_method { rec.typ } else { 0 } // used only if is static type method is_file_translated: p.is_translated // - attrs: p.attrs + attrs: fn_attrs is_conditional: conditional_ctdefine_idx != ast.invalid_type_idx ctdefine_idx: conditional_ctdefine_idx // @@ -686,7 +688,7 @@ run them via `v file.v` instead', is_markused: is_markused is_file_translated: p.is_translated // - attrs: p.attrs + attrs: fn_attrs is_conditional: conditional_ctdefine_idx != ast.invalid_type_idx ctdefine_idx: conditional_ctdefine_idx //