mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
scanner: add support for @STRUCT
compile time substitution
This commit is contained in:
parent
285e04393e
commit
31ba64b409
@ -31,6 +31,7 @@ pub mut:
|
||||
is_started bool
|
||||
fn_name string // needed for @FN
|
||||
mod_name string // needed for @MOD
|
||||
struct_name string // needed for @STRUCT
|
||||
is_print_line_on_error bool
|
||||
is_print_colored_error bool
|
||||
is_print_rel_paths_on_error bool
|
||||
@ -174,6 +175,67 @@ fn (mut s Scanner) ident_mod_name() string {
|
||||
return mod_name
|
||||
}
|
||||
|
||||
// ident_struct_name look ahead and return name of last encountered struct if possible, otherwise empty string
|
||||
fn (mut s Scanner) ident_struct_name() string {
|
||||
start := s.pos
|
||||
mut pos := s.pos
|
||||
|
||||
// Return last known stuct_name encountered to avoid using high order/anonymous function definitions
|
||||
if s.current_column() - 2 != 0 {
|
||||
return s.struct_name
|
||||
}
|
||||
|
||||
pos++
|
||||
|
||||
// Eat whitespaces
|
||||
for pos < s.text.len && s.text[pos].is_space() {
|
||||
pos++
|
||||
}
|
||||
if pos >= s.text.len {
|
||||
return ''
|
||||
}
|
||||
|
||||
// Return if `(` is not the first character after "fn ..."
|
||||
if s.text[pos] != `(` {
|
||||
return ''
|
||||
}
|
||||
|
||||
// Search for closing paranthesis
|
||||
for pos < s.text.len && s.text[pos] != `)` {
|
||||
pos++
|
||||
}
|
||||
if pos >= s.text.len {
|
||||
return ''
|
||||
}
|
||||
|
||||
pos--
|
||||
// Search backwards for end position of struct name
|
||||
// Eat whitespaces
|
||||
for pos > start && s.text[pos].is_space() {
|
||||
pos--
|
||||
}
|
||||
if pos < start {
|
||||
return ''
|
||||
}
|
||||
end_pos := pos + 1
|
||||
|
||||
// Go back while we have a name character or digit
|
||||
for pos > start && (util.is_name_char(s.text[pos]) || s.text[pos].is_digit()) {
|
||||
pos--
|
||||
}
|
||||
if pos < start {
|
||||
return ''
|
||||
}
|
||||
|
||||
start_pos := pos + 1
|
||||
|
||||
if s.text[start_pos].is_digit() || end_pos > s.text.len || end_pos <= start_pos || end_pos <= start || start_pos <= start {
|
||||
return ''
|
||||
}
|
||||
struct_name := s.text[start_pos..end_pos]
|
||||
return struct_name
|
||||
}
|
||||
|
||||
fn filter_num_sep(txt byteptr, start int, end int) string {
|
||||
unsafe{
|
||||
mut b := malloc(end - start + 1) // add a byte for the endstring 0
|
||||
@ -491,6 +553,7 @@ pub fn (mut s Scanner) scan() token.Token {
|
||||
kind := token.key_to_token(name)
|
||||
if kind == .key_fn {
|
||||
s.fn_name = s.ident_fn_name()
|
||||
s.struct_name = s.ident_struct_name()
|
||||
} else if kind == .key_module {
|
||||
s.mod_name = s.ident_mod_name()
|
||||
}
|
||||
@ -676,6 +739,7 @@ pub fn (mut s Scanner) scan() token.Token {
|
||||
name := s.ident_name()
|
||||
// @FN => will be substituted with the name of the current V function
|
||||
// @MOD => will be substituted with the name of the current V module
|
||||
// @STRUCT => will be substituted with the name of the current V struct
|
||||
// @VEXE => will be substituted with the path to the V compiler
|
||||
// @FILE => will be substituted with the path of the V source file
|
||||
// @LINE => will be substituted with the V line number where it appears (as a string).
|
||||
@ -690,6 +754,9 @@ pub fn (mut s Scanner) scan() token.Token {
|
||||
if name == 'MOD' {
|
||||
return s.new_token(.string, s.mod_name, 4)
|
||||
}
|
||||
if name == 'STRUCT' {
|
||||
return s.new_token(.string, s.struct_name, 7)
|
||||
}
|
||||
if name == 'VEXE' {
|
||||
vexe := pref.vexe_path()
|
||||
return s.new_token(.string, util.cescaped_path(vexe), 5)
|
||||
|
@ -5,6 +5,26 @@ module scanner
|
||||
|
||||
import v.token
|
||||
|
||||
|
||||
struct TestStruct {
|
||||
test string
|
||||
}
|
||||
|
||||
fn (mut t TestStruct) test_struct() {
|
||||
assert @STRUCT == 'TestStruct'
|
||||
}
|
||||
|
||||
fn (mut t TestStruct) test_struct_w_return() string {
|
||||
assert @STRUCT == 'TestStruct'
|
||||
return t.test
|
||||
}
|
||||
|
||||
fn (mut t TestStruct) test_struct_w_high_order(cb fn(int)string) string {
|
||||
assert @STRUCT == 'TestStruct'
|
||||
return 'test'+cb(2)
|
||||
}
|
||||
|
||||
|
||||
fn test_scan() {
|
||||
text := 'println(2 + 3)'
|
||||
mut scanner := new_scanner(text, .skip_comments)
|
||||
@ -41,9 +61,24 @@ fn test_scan() {
|
||||
assert 1.23e+10 == 1.23e0010
|
||||
assert (-1.23e+10) == (1.23e0010 * -1.0)
|
||||
|
||||
// test @MOD
|
||||
// Test @FN
|
||||
assert @FN == 'test_scan'
|
||||
|
||||
// Test @MOD
|
||||
assert @MOD == 'scanner'
|
||||
|
||||
// test @FN
|
||||
assert @FN == 'test_scan'
|
||||
// Test @STRUCT
|
||||
assert @STRUCT == ''
|
||||
|
||||
ts := TestStruct { test: "test" }
|
||||
ts.test_struct()
|
||||
r1 := ts.test_struct_w_return()
|
||||
r2 := ts.test_struct_w_high_order(fn(i int)string{
|
||||
assert @STRUCT == ''
|
||||
return i.str()
|
||||
})
|
||||
assert r1 == 'test'
|
||||
assert r2 == 'test2'
|
||||
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user