Skip to content

Commit

Permalink
all: new string interpolation "hello {name}!"
Browse files Browse the repository at this point in the history
  • Loading branch information
medvednikov committed Oct 27, 2022
1 parent e6fad82 commit 18c7da9
Show file tree
Hide file tree
Showing 26 changed files with 124 additions and 88 deletions.
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Expand Up @@ -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: |
Expand Down
2 changes: 1 addition & 1 deletion ROADMAP.md
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions cmd/tools/gen_vc.v
Expand Up @@ -169,10 +169,10 @@ pub fn (mut ws WebhookServer) genhook() {
ws.gen_vc.generate()
// error in generate
if ws.gen_vc.gen_error {
ws.json('{status: "failed"}')
ws.json('{ status: "failed" }')
return
}
ws.json('{status: "ok"}')
ws.json('{ status: "ok" }')
}

pub fn (ws &WebhookServer) reset() {
Expand Down
6 changes: 3 additions & 3 deletions cmd/tools/modules/vgit/vgit.v
Expand Up @@ -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)
Expand Down Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion cmd/tools/vdoctor.v
Expand Up @@ -72,7 +72,7 @@ fn (mut a App) collect_info() {
os_details += ' (WSL)'
}
// From https://unix.stackexchange.com/a/14346
awk_cmd := '[ "$(awk \'\$5=="/" {print \$1}\' </proc/1/mountinfo)" != "$(awk \'\$5=="/" {print \$1}\' </proc/$$/mountinfo)" ] ; echo \$?'
awk_cmd := '[ "$(awk \'\$5=="/" { print \$1 }\' </proc/1/mountinfo)" != "$(awk \'\$5=="/" { print \$1 }\' </proc/$$/mountinfo)" ] ; echo \$?'
if a.cmd(command: awk_cmd) == '0' {
os_details += ' (chroot)'
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/tools/vpm.v
Expand Up @@ -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 = {
Expand Down
12 changes: 6 additions & 6 deletions vlib/builtin/string_interpolation.v
Expand Up @@ -687,22 +687,22 @@ pub const (

[inline]
pub fn str_intp_sq(in_str string) string {
return 'str_intp(2, _MOV((StrIntpData[]){{_SLIT("\'"), $si_s_code, {.d_s = $in_str}},{_SLIT("\'"), 0, {.d_c = 0 }}}))'
return 'str_intp(2, _MOV((StrIntpData[]){{ _SLIT("\'"), $si_s_code, {.d_s = $in_str}},{ _SLIT("\'"), 0, {.d_c = 0 }}}))'
}

[inline]
pub fn str_intp_rune(in_str string) string {
return 'str_intp(2, _MOV((StrIntpData[]){{_SLIT("\`"), $si_s_code, {.d_s = $in_str}},{_SLIT("\`"), 0, {.d_c = 0 }}}))'
return 'str_intp(2, _MOV((StrIntpData[]){{ _SLIT("\`"), $si_s_code, {.d_s = $in_str}},{ _SLIT("\`"), 0, {.d_c = 0 }}}))'
}

[inline]
pub fn str_intp_g32(in_str string) string {
return 'str_intp(1, _MOV((StrIntpData[]){{_SLIT0, $si_g32_code, {.d_f32 = $in_str }}}))'
return 'str_intp(1, _MOV((StrIntpData[]){{ _SLIT0, $si_g32_code, {.d_f32 = $in_str }}}))'
}

[inline]
pub fn str_intp_g64(in_str string) string {
return 'str_intp(1, _MOV((StrIntpData[]){{_SLIT0, $si_g64_code, {.d_f64 = $in_str }}}))'
return 'str_intp(1, _MOV((StrIntpData[]){{ _SLIT0, $si_g64_code, {.d_f64 = $in_str }}}))'
}

// replace %% with the in_str
Expand All @@ -718,12 +718,12 @@ pub fn str_intp_sub(base_str string, in_str string) string {
st_str := base_str[..index]
if index + 2 < base_str.len {
en_str := base_str[index + 2..]
res_str := 'str_intp(2, _MOV((StrIntpData[]){{_SLIT("$st_str"), $si_s_code, {.d_s = $in_str }},{_SLIT("$en_str"), 0, {.d_c = 0}}}))'
res_str := 'str_intp(2, _MOV((StrIntpData[]){{ _SLIT("$st_str"), $si_s_code, {.d_s = $in_str }},{ _SLIT("$en_str"), 0, {.d_c = 0}}}))'
st_str.free()
en_str.free()
return res_str
}
res2_str := 'str_intp(1, _MOV((StrIntpData[]){{_SLIT("$st_str"), $si_s_code, {.d_s = $in_str }}}))'
res2_str := 'str_intp(1, _MOV((StrIntpData[]){{ _SLIT("$st_str"), $si_s_code, { .d_s = $in_str }}}))'
st_str.free()
return res2_str
}
Expand Down
5 changes: 5 additions & 0 deletions vlib/builtin/string_test.v
Expand Up @@ -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
Expand Down
30 changes: 15 additions & 15 deletions vlib/v/eval/gen/infix_gen.v
Expand Up @@ -10,10 +10,10 @@ module eval
import v.token
import v.ast
fn(e Eval)infix_expr(left Object,right Object,op token.Kind,expecting ast.Type)Object{match op{'
footer = "else{e.error('unknown infix expression: \$op')}}return empty // should e.error before this anyway
footer = "else{ e.error('unknown infix expression: \$op')}}return empty // should e.error before this anyway
}
"
uk_expect_footer = "else{e.error('unknown infix expectation: \${e.table.sym(expecting).str()}')}}"
uk_expect_footer = "else{ e.error('unknown infix expectation: \${e.table.sym(expecting).str()}')}}"
comparison = {
'gt': '>'
'lt': '<'
Expand Down Expand Up @@ -46,7 +46,7 @@ fn main() {
for lt2 in literal_types {
b.write_string('$lt2{return left.val${op}right}')
}
b.write_string("else{e.error('invalid operands to $op: $ct and \$right.type_name()')}}}")
b.write_string("else{ e.error('invalid operands to $op: $ct and \$right.type_name()')}}}")
}
for lt in literal_types {
b.write_string('$lt {match right{')
Expand All @@ -61,9 +61,9 @@ fn main() {
b.write_string(" literal and \$right.type_name()')}}}")
}
if op in ['==', '!='] {
b.write_string('string{match right{string{return left${op}right}else{e.error(\'invalid operands to $op: string and \$right.type_name()\')}}}')
b.write_string('string{ match right{ string{ return left${op}right}else{ e.error(\'invalid operands to $op: string and \$right.type_name()\')}}}')
}
b.write_string("else {e.error('invalid operands to $op: \$left.type_name() and \$right.type_name()')}}}")
b.write_string("else { e.error('invalid operands to $op: \$left.type_name() and \$right.type_name()')}}}")
}
for math, op in math_ops {
b.write_string('.$math{match left{')
Expand All @@ -77,9 +77,9 @@ fn main() {
continue
}
unsafe_start, unsafe_end := if op in ['<<', '>>'] { 'unsafe{', '}' } else { '', '' }
b.write_string('$ct2{if expecting in ast.signed_integer_type_idxs{return Int{i64(left.val)${op}i64(right.val),i8(e.type_to_size(expecting))}}else if expecting in ast.unsigned_integer_type_idxs{return Uint{u64(left.val)${op}u64(right.val),i8(e.type_to_size(expecting))}}else if expecting==ast.int_literal_type_idx{${unsafe_start}return i64(i64(left.val)${op}i64(right.val))$unsafe_end}')
b.write_string('$ct2{ if expecting in ast.signed_integer_type_idxs{ return Int{ i64(left.val)${op}i64(right.val),i8(e.type_to_size(expecting))}}else if expecting in ast.unsigned_integer_type_idxs{ return Uint{ u64(left.val)${op}u64(right.val),i8(e.type_to_size(expecting))}}else if expecting==ast.int_literal_type_idx{${unsafe_start}return i64(i64(left.val)${op}i64(right.val))$unsafe_end}')
if op !in ['<<', '>>'] {
b.write_string('else if expecting in ast.float_type_idxs{return Float{f64(left.val)${op}f64(right.val), i8(e.type_to_size(expecting))}}else if expecting==ast.float_literal_type_idx{return f64(f64(left.val)${op}f64(right.val))}')
b.write_string('else if expecting in ast.float_type_idxs{ return Float{ f64(left.val)${op}f64(right.val),i8(e.type_to_size(expecting))}}else if expecting==ast.float_literal_type_idx{ return f64(f64(left.val)${op}f64(right.val))}')
}
b.write_string(uk_expect_footer)
}
Expand All @@ -88,13 +88,13 @@ fn main() {
continue
}
unsafe_start, unsafe_end := if op in ['<<', '>>'] { 'unsafe{', '}' } else { '', '' }
b.write_string('$lt2{if expecting in ast.signed_integer_type_idxs{return Int{i64(left.val)${op}i64(right),i8(e.type_to_size(expecting))}}else if expecting in ast.unsigned_integer_type_idxs{return Uint{u64(left.val)${op}u64(right),i8(e.type_to_size(expecting))}}else if expecting==ast.int_literal_type_idx{${unsafe_start}return i64(i64(left.val)${op}i64(right))$unsafe_end}')
b.write_string('$lt2{ if expecting in ast.signed_integer_type_idxs{ return Int{ i64(left.val)${op}i64(right),i8(e.type_to_size(expecting))}}else if expecting in ast.unsigned_integer_type_idxs{ return Uint{ u64(left.val)${op}u64(right),i8(e.type_to_size(expecting))}}else if expecting==ast.int_literal_type_idx{${unsafe_start}return i64(i64(left.val)${op}i64(right))$unsafe_end}')
if op !in ['<<', '>>'] {
b.write_string('else if expecting in ast.float_type_idxs{return Float{f64(left.val)${op}f64(right), i8(e.type_to_size(expecting))}}else if expecting==ast.float_literal_type_idx{return f64(f64(left.val)${op}f64(right))}')
b.write_string('else if expecting in ast.float_type_idxs{ return Float{ f64(left.val)${op}f64(right), i8(e.type_to_size(expecting))}}else if expecting==ast.float_literal_type_idx{ return f64(f64(left.val)${op}f64(right))}')
}
b.write_string(uk_expect_footer)
}
b.write_string("else {e.error('invalid operands to $op: $ct and \$right.type_name()')}}}")
b.write_string("else { e.error('invalid operands to $op: $ct and \$right.type_name()')}}}")
}
for lt in literal_types {
if op in ['<<', '>>'] && lt == 'f64' {
Expand All @@ -106,9 +106,9 @@ fn main() {
continue
}
unsafe_start, unsafe_end := if op in ['<<', '>>'] { 'unsafe{', '}' } else { '', '' }
b.write_string('$ct2{if expecting in ast.signed_integer_type_idxs{return Int{i64(left)${op}i64(right.val),i8(e.type_to_size(expecting))}}else if expecting in ast.unsigned_integer_type_idxs{return Uint{u64(left)${op}u64(right.val),i8(e.type_to_size(expecting))}}else if expecting==ast.int_literal_type_idx{${unsafe_start}return i64(i64(left)${op}i64(right.val))$unsafe_end}')
b.write_string('$ct2{ if expecting in ast.signed_integer_type_idxs{ return Int{ i64(left)${op}i64(right.val),i8(e.type_to_size(expecting))}}else if expecting in ast.unsigned_integer_type_idxs{ return Uint{ u64(left)${op}u64(right.val),i8(e.type_to_size(expecting))}}else if expecting==ast.int_literal_type_idx{${unsafe_start}return i64(i64(left)${op}i64(right.val))$unsafe_end}')
if op !in ['<<', '>>'] {
b.write_string('else if expecting in ast.float_type_idxs{return Float{f64(left)${op}f64(right.val), i8(e.type_to_size(expecting))}}else if expecting==ast.float_literal_type_idx{return f64(f64(left)${op}f64(right.val))}')
b.write_string('else if expecting in ast.float_type_idxs{ return Float{ f64(left)${op}f64(right.val), i8(e.type_to_size(expecting))}}else if expecting==ast.float_literal_type_idx{ return f64(f64(left)${op}f64(right.val))}')
}
b.write_string(uk_expect_footer)
}
Expand All @@ -117,17 +117,17 @@ fn main() {
continue
}
unsafe_start, unsafe_end := if op in ['<<', '>>'] { 'unsafe{', '}' } else { '', '' }
b.write_string('$lt2{if expecting in ast.signed_integer_type_idxs{return Int{i64(left)${op}i64(right),i8(e.type_to_size(expecting))}}else if expecting in ast.unsigned_integer_type_idxs{return Uint{u64(left)${op}u64(right),i8(e.type_to_size(expecting))}}else if expecting==ast.int_literal_type_idx{${unsafe_start}return i64(i64(left)${op}i64(right))$unsafe_end}')
b.write_string('$lt2{if expecting in ast.signed_integer_type_idxs{ return Int{ i64(left)${op}i64(right),i8(e.type_to_size(expecting))}}else if expecting in ast.unsigned_integer_type_idxs{ return Uint{ u64(left)${op}u64(right),i8(e.type_to_size(expecting))}}else if expecting==ast.int_literal_type_idx{${unsafe_start}return i64(i64(left)${op}i64(right))$unsafe_end}')
if op !in ['<<', '>>'] {
b.write_string('else if expecting in ast.float_type_idxs{return Float{f64(left)${op}f64(right), i8(e.type_to_size(expecting))}}else if expecting==ast.float_literal_type_idx{return f64(f64(left)${op}f64(right))}')
b.write_string('else if expecting in ast.float_type_idxs{ return Float{ f64(left)${op}f64(right), i8(e.type_to_size(expecting))}}else if expecting==ast.float_literal_type_idx{ return f64(f64(left)${op}f64(right))}')
}
b.write_string(uk_expect_footer)
}
b.write_string("else {e.error('invalid operands to $op: ")
b.write_string(if lt == 'i64' { 'int' } else { 'float' })
b.write_string(" literal and \$right.type_name()')}}}")
}
b.write_string("else {e.error('invalid operands to $op: \$left.type_name() and \$right.type_name()')}}}")
b.write_string("else { e.error('invalid operands to $op: \$left.type_name() and \$right.type_name()')}}}")
}

b.write_string(footer)
Expand Down
2 changes: 1 addition & 1 deletion vlib/v/fmt/fmt.v
Expand Up @@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion vlib/v/gen/c/assign.v
Expand Up @@ -209,7 +209,7 @@ fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) {
g.expr(val)
} else {
if left_sym.kind == .function {
g.write('{void* _ = ')
g.write('{ void* _ = ')
} else {
g.write('{$styp _ = ')
}
Expand Down
2 changes: 1 addition & 1 deletion vlib/v/gen/c/auto_eq_methods.v
Expand Up @@ -352,7 +352,7 @@ fn (mut g Gen) gen_map_equality_fn(left_type ast.Type) string {
}
match kind {
.string {
fn_builder.writeln('\t\tif (!fast_string_eq(*(string*)map_get(&b, k, &(string[]){_SLIT("")}), v)) {')
fn_builder.writeln('\t\tif (!fast_string_eq(*(string*)map_get(&b, k, &(string[]){ _SLIT("")}), v)) {')
}
.sum_type {
eq_fn := g.gen_sumtype_equality_fn(value.typ)
Expand Down

0 comments on commit 18c7da9

Please sign in to comment.