mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
all: new string interpolation "hello {name}!"
This commit is contained in:
parent
e6fad82b87
commit
18c7da9a5e
1
.github/workflows/ci.yml
vendored
1
.github/workflows/ci.yml
vendored
@ -222,6 +222,7 @@ jobs:
|
||||
git clone --depth 1 https://github.com/vlang/ved
|
||||
cd ved && ../v -o ved .
|
||||
../v -autofree .
|
||||
../v -prod .
|
||||
cd ..
|
||||
# - name: Test c2v
|
||||
# run: |
|
||||
|
@ -9,7 +9,7 @@
|
||||
- [ ] Recursive structs via optionals: `struct Node { next ?Node }`
|
||||
- [ ] Optional function struct fields
|
||||
- [ ] Handle function pointers safely, remove `if function == 0 {`
|
||||
- [ ] Bundle OpenSSL like GC
|
||||
- [x] Bundle OpenSSL like GC
|
||||
- [x] Anonymous structs
|
||||
- [ ] -usecache on by default
|
||||
- [ ] -skip-unused on by default
|
||||
|
@ -112,10 +112,10 @@ pub fn (mut vgit_context VGitContext) compile_oldv_if_needed() {
|
||||
mut command_for_selfbuilding := ''
|
||||
if 'windows' == os.user_os() {
|
||||
command_for_building_v_from_c_source = '$vgit_context.cc -std=c99 -I ./thirdparty/stdatomic/win -municode -w -o cv.exe "$vgit_context.path_vc/v_win.c" '
|
||||
command_for_selfbuilding = './cv.exe -o $vgit_context.vexename {SOURCE}'
|
||||
command_for_selfbuilding = './cv.exe -o $vgit_context.vexename \{SOURCE}'
|
||||
} else {
|
||||
command_for_building_v_from_c_source = '$vgit_context.cc -std=gnu11 -I ./thirdparty/stdatomic/nix -w -o cv "$vgit_context.path_vc/v.c" -lm -lpthread'
|
||||
command_for_selfbuilding = './cv -o $vgit_context.vexename {SOURCE}'
|
||||
command_for_selfbuilding = './cv -o $vgit_context.vexename \{SOURCE}'
|
||||
}
|
||||
scripting.chdir(vgit_context.workdir)
|
||||
clone_or_pull(vgit_context.v_repo_url, vgit_context.path_v)
|
||||
@ -146,7 +146,7 @@ pub fn (mut vgit_context VGitContext) compile_oldv_if_needed() {
|
||||
scripting.run('make fresh_tcc')
|
||||
}
|
||||
scripting.run(command_for_building_v_from_c_source)
|
||||
build_cmd := command_for_selfbuilding.replace('{SOURCE}', vgit_context.vvlocation)
|
||||
build_cmd := command_for_selfbuilding.replace('\{SOURCE}', vgit_context.vvlocation)
|
||||
scripting.run(build_cmd)
|
||||
// At this point, there exists a file vgit_context.vexepath
|
||||
// which should be a valid working V executable.
|
||||
|
@ -29,7 +29,7 @@ const (
|
||||
'hg': 'hg clone'
|
||||
}
|
||||
supported_vcs_outdated_steps = {
|
||||
'git': ['git fetch', 'git rev-parse @', 'git rev-parse @{u}']
|
||||
'git': ['git fetch', 'git rev-parse @', 'git rev-parse @\{u}']
|
||||
'hg': ['hg incoming']
|
||||
}
|
||||
supported_vcs_version_cmds = {
|
||||
|
@ -849,6 +849,11 @@ fn test_raw_inter() {
|
||||
assert s.contains('$')
|
||||
}
|
||||
|
||||
fn test_new_inter() {
|
||||
// world := 'world'
|
||||
// assert 'hello {world}' == 'hello world'
|
||||
}
|
||||
|
||||
fn test_c_r() {
|
||||
// This used to break because of r'' and c''
|
||||
c := 42
|
||||
|
@ -1663,7 +1663,7 @@ pub fn (mut f Fmt) array_init(node ast.ArrayInit) {
|
||||
}
|
||||
f.write(f.table.type_to_str_using_aliases(node.elem_type, f.mod2alias))
|
||||
if node.has_default {
|
||||
f.write('{init: ')
|
||||
f.write('\{init: ')
|
||||
f.expr(node.default_expr)
|
||||
f.write('}')
|
||||
} else {
|
||||
|
@ -1272,8 +1272,7 @@ fn (mut g Gen) write_chan_push_optional_fns() {
|
||||
g.channel_definitions.writeln('
|
||||
static inline ${c.option_name}_void __Option_${styp}_pushval($styp ch, $el_type e) {
|
||||
if (sync__Channel_try_push_priv(ch, &e, false)) {
|
||||
return (${c.option_name}_void){ .state = 2, .err = _v_error(_SLIT("channel closed")), .data = {EMPTY_STRUCT_INITIALIZATION} };
|
||||
}
|
||||
return (${c.option_name}_void){ .state = 2, .err = _v_error(_SLIT("channel closed")), .data = { EMPTY_STRUCT_INITIALIZATION} }; }
|
||||
return (${c.option_name}_void){0};
|
||||
}')
|
||||
}
|
||||
|
@ -802,9 +802,13 @@ fn (mut s Scanner) text_scan() token.Token {
|
||||
return s.new_token(.rsbr, '', 1)
|
||||
}
|
||||
`{` {
|
||||
// Skip { in `${` in strings
|
||||
if s.is_inside_string {
|
||||
// Handle new `hello {name}` string interpolation
|
||||
if !s.text[s.pos + 1].is_space() && s.text[s.pos - 1] != `$` {
|
||||
return s.new_token(.str_dollar, '', 1)
|
||||
}
|
||||
if s.text[s.pos - 1] == `$` {
|
||||
// Skip { in `${` in strings
|
||||
continue
|
||||
} else {
|
||||
s.inter_cbr_count++
|
||||
@ -1225,6 +1229,33 @@ fn (mut s Scanner) ident_string() string {
|
||||
s.pos -= 2
|
||||
break
|
||||
}
|
||||
// {var} (ignore in vfmt mode) (skip \{)
|
||||
if c == `{` && util.is_name_char(s.text[s.pos + 1]) && prevc != `$` && !is_raw
|
||||
&& s.count_symbol_before(s.pos - 1, scanner.backslash) % 2 == 0 {
|
||||
// Detect certain strings with "{" that are not interpolation:
|
||||
// e.g. "{init: " (no "}" at the end)
|
||||
mut is_valid_inter := true
|
||||
for i := s.pos + 1; i < s.text.len; i++ {
|
||||
if s.text[i] == `}` {
|
||||
// No } in this string, so it's not a valid `{x}` interpolation
|
||||
break
|
||||
}
|
||||
if s.text[i] in [`=`, `\n`, s.inter_quote] {
|
||||
// We reached the end of the line or string without reaching "}".
|
||||
// Also if there's "=", there's no way it's a valid interpolation expression:
|
||||
// e.g. `println("{a.b = 42}")`
|
||||
is_valid_inter = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if is_valid_inter {
|
||||
s.is_inside_string = true
|
||||
s.is_enclosed_inter = true
|
||||
// so that s.pos points to $ at the next step
|
||||
s.pos -= 1
|
||||
break
|
||||
}
|
||||
}
|
||||
if c != scanner.backslash {
|
||||
backslash_count = 0
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ pub fn (mut p Pos) free() {
|
||||
}
|
||||
|
||||
pub fn (p Pos) line_str() string {
|
||||
return '{l: ${p.line_nr + 1:5}, c: ${p.col:3}, p: ${p.pos:5}, ll: ${p.last_line + 1:5}}'
|
||||
return '\{l: ${p.line_nr + 1:5}, c: ${p.col:3}, p: ${p.pos:5}, ll: ${p.last_line + 1:5}}'
|
||||
}
|
||||
|
||||
pub fn (pos Pos) extend(end Pos) Pos {
|
||||
|
Loading…
Reference in New Issue
Block a user