Skip to content

Commit

Permalink
v,ast,fmt,parser: support @[tag] for hash statements, like `#define…
Browse files Browse the repository at this point in the history
…` and `#flag` (#23210)
  • Loading branch information
spytheman authored Dec 20, 2024
1 parent 30ececc commit 9ae0a9d
Show file tree
Hide file tree
Showing 10 changed files with 45 additions and 9 deletions.
8 changes: 5 additions & 3 deletions cmd/tools/vast/vast.v
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down Expand Up @@ -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
}
Expand All @@ -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
}

Expand Down
2 changes: 2 additions & 0 deletions vlib/fontstash/fontstash.c.v
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
module fontstash

#flag -I @VEXEROOT/thirdparty/fontstash

@[use_once]
#define FONTSTASH_IMPLEMENTATION
$if gcboehm ? {
#define FONTSTASH_MALLOC GC_MALLOC
Expand Down
2 changes: 2 additions & 0 deletions vlib/sokol/audio/audio.c.v
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 6 additions & 0 deletions vlib/sokol/c/declaration.c.v
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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"
1 change: 1 addition & 0 deletions vlib/sokol/f/f.v
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@ import sokol.c as _

//#include "ft2build.h"

@[use_once]
#define SOKOL_FONTSTASH_IMPL
#include "util/sokol_fontstash.h"
2 changes: 2 additions & 0 deletions vlib/v/ast/ast.v
Original file line number Diff line number Diff line change
Expand Up @@ -1365,13 +1365,15 @@ pub:
mod string
pos token.Pos
source_file string
is_use_once bool // true for @[use_once]
pub mut:
val string // example: 'include <openssl/rand.h> # please install openssl // comment'
kind string // : 'include'
main string // : '<openssl/rand.h>'
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
Expand Down
1 change: 1 addition & 0 deletions vlib/v/fmt/fmt.v
Original file line number Diff line number Diff line change
Expand Up @@ -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}')
}

Expand Down
6 changes: 6 additions & 0 deletions vlib/v/fmt/tests/hashstmt_keep.vv
Original file line number Diff line number Diff line change
Expand Up @@ -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
12 changes: 12 additions & 0 deletions vlib/v/parser/comptime.v
Original file line number Diff line number Diff line change
Expand Up @@ -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 := ''
Expand All @@ -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
Expand All @@ -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
}
}

Expand Down
14 changes: 8 additions & 6 deletions vlib/v/parser/fn.v
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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()
Expand All @@ -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
Expand Down Expand Up @@ -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
//
Expand Down Expand Up @@ -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
//
Expand Down Expand Up @@ -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
//
Expand Down

0 comments on commit 9ae0a9d

Please sign in to comment.