Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into cleanup_resolve_com…
Browse files Browse the repository at this point in the history
…ptime_args
  • Loading branch information
felipensp committed Jan 2, 2025
2 parents dfd1cf4 + 7cf77fb commit 8551ba1
Show file tree
Hide file tree
Showing 10 changed files with 171 additions and 59 deletions.
132 changes: 80 additions & 52 deletions cmd/tools/vbug.v
Original file line number Diff line number Diff line change
@@ -1,72 +1,88 @@
import net.urllib
import os
import term
import readline
import net.urllib

const vroot = @VMODROOT
fn elog(msg string) {
eprintln(term.ecolorize(term.gray, msg))
}

fn olog(msg string) {
println(term.colorize(term.green, msg))
}

// get output from `v doctor`
fn get_vdoctor_output(is_verbose bool) string {
vexe := os.getenv('VEXE')
verbose_flag := if is_verbose { '-v' } else { '' }
result := os.execute('${os.quoted_path(vexe)} ${verbose_flag} doctor')
if result.exit_code != 0 {
eprintln('unable to get `v doctor` output: ${result.output}')
elog('> unable to get `v doctor` output: ${result.output}')
return ''
}
return result.output
}

// get output from `./v -g -o vdbg cmd/v && ./vdbg file.v`
fn get_v_build_output(is_verbose bool, is_yes bool, file_path string) string {
fn runv(label string, user_cmd string) os.Result {
mut result := os.Result{}
elog('> ${label} using: ${term.ecolorize(term.magenta, user_cmd)}')
result = os.execute(user_cmd)
print(result.output)
return result
}

// get output from `./v -g -o vdbg cmd/v && ./vdbg -user_args run file.v`
fn get_v_build_output(is_verbose bool, is_yes bool, file_path string, user_args string, generated_file string) string {
mut result := os.Result{}
mut vexe := os.getenv('VEXE')

// prepare a V compiler with -g to have better backtraces if possible
wd := os.getwd()
vroot := @VMODROOT
os.chdir(vroot) or {}
verbose_flag := if is_verbose { '-v' } else { '' }
vdbg_path := $if windows { '${vroot}/vdbg.exe' } $else { '${vroot}/vdbg' }
vdbg_compilation_cmd := '${os.quoted_path(vexe)} ${verbose_flag} -g -o ${os.quoted_path(vdbg_path)} cmd/v'
vdbg_result := os.execute(vdbg_compilation_cmd)
result = runv('Prepare vdbg', vdbg_compilation_cmd)
os.chdir(wd) or {}
if vdbg_result.exit_code == 0 {

if result.exit_code == 0 {
vexe = vdbg_path
} else {
eprintln('unable to compile V in debug mode: ${vdbg_result.output}\ncommand: ${vdbg_compilation_cmd}\n')
elog('> unable to compile V in debug mode: ${result.output}\ncommand: ${vdbg_compilation_cmd}\n')
}

mut result := os.execute('${os.quoted_path(vexe)} ${verbose_flag} ${os.quoted_path(file_path)}')
result = runv('Compile', '${os.quoted_path(vexe)} ${verbose_flag} ${user_args} ${os.quoted_path(file_path)}')
defer {
os.rm(vdbg_path) or {
if is_verbose {
eprintln('unable to delete `vdbg`: ${err}')
elog('> unable to delete `vdbg`: ${err}')
}
}
}
if result.exit_code == 0 {
defer {
mut generated_file := file_path.all_before_last('.')
$if windows {
generated_file += '.exe'
}
os.rm(generated_file) or {
if is_verbose {
eprintln('unable to delete generated file: ${err}')
elog('> unable to delete generated file: ${err}')
}
}
}
run := is_yes
|| ask('It looks like the compilation went well, do you want to run the file?')
if run {
result = os.execute('${os.quoted_path(vexe)} ${verbose_flag} run ${os.quoted_path(file_path)}')
result = runv('Run', generated_file)
if result.exit_code == 0 && !is_yes {
confirm_or_exit('It looks like the file ran correctly as well, are you sure you want to continue?')
elog('> The file ran correctly as well.')
confirm_or_exit('Are you sure you want to continue?')
}
}
}
return result.output
}

fn ask(msg string) bool {
prompt := os.input_opt('${msg} [Y/n] ') or { 'y' }
prompt := os.input_opt(term.colorize(term.bright_white, '${msg} [Y/n] ')) or { 'y' }
return prompt == '' || prompt[0].ascii_str().to_lower() != 'n'
}

Expand All @@ -77,59 +93,68 @@ fn confirm_or_exit(msg string) {
}

fn main() {
unbuffer_stdout()
mut compiler_args := []string{}
mut file_path := ''
mut is_verbose := false
mut is_yes := false
for arg in os.args[2..] {
match arg {
'-v' {
is_verbose = true
}
'-y' {
is_yes = true
is_verbose := '-v' in os.args
is_yes := '-y' in os.args

for arg in os.args[1..] {
if arg == 'bug' {
continue
}
if arg.ends_with('.v') || arg.ends_with('.vsh') || arg.ends_with('.vv') {
if file_path != '' {
elog('> v bug: only one V file can be submitted')
exit(1)
}
else {
if !arg.ends_with('.v') && !arg.ends_with('.vsh') && !arg.ends_with('.vv') {
eprintln('unknown argument: `${arg}`')
exit(1)
}
if file_path != '' {
eprintln('only one V file can be submitted')
exit(1)
}
file_path = arg
file_path = arg
} else {
if arg !in ['-y', '-v'] {
compiler_args << arg
}
}
}

if file_path == '' {
eprintln('v bug: no v file listed to report')
elog('> v bug: no v file listed to report')
exit(1)
}

os.unsetenv('VCOLORS')
// collect error information
// output from `v doctor`
vdoctor_output := get_vdoctor_output(is_verbose)
// file content
file_content := os.read_file(file_path) or {
eprintln('unable to get file "${file_path}" content: ${err}')
elog('> unable to get file "${file_path}" content: ${err}')
''
}
// output from `./v -g -o vdbg cmd/v && ./vdbg file.v`
build_output := get_v_build_output(is_verbose, is_yes, file_path)

user_args := compiler_args.join(' ')
mut generated_file := file_path.all_before_last('.')
if os.user_os() == 'windows' {
generated_file += '.exe'
}
build_output := get_v_build_output(is_verbose, is_yes, file_path, user_args, generated_file)

// ask the user if he wants to submit even after an error
if !is_yes && (vdoctor_output == '' || file_content == '' || build_output == '') {
confirm_or_exit('An error occurred retrieving the information, do you want to continue?')
elog('> Error while retrieving the information.')
confirm_or_exit('Do you want to continue?')
}

expected_result := readline.read_line('What did you expect to see? ') or {
// Ctrl-C was pressed
eprintln('\nCanceled')
elog('\nCanceled')
exit(1)
}
// open prefilled issue creation page, or print link as a fallback

if !is_yes && vdoctor_output.contains('behind V master') {
confirm_or_exit('It looks like your installation of V is outdated, we advise you to run `v up` before submitting an issue. Are you sure you want to continue?')
olog('> It looks like your installation of V is outdated.')
olog('> We advise you to run `v up` before submitting an issue.')
confirm_or_exit('Are you sure you want to continue?')
}

// When updating this template, make sure to update `.github/ISSUE_TEMPLATE/bug_report.md` too
Expand All @@ -140,30 +165,33 @@ ${vdoctor_output}
```
**What did you do?**
`./v -g -o vdbg cmd/v && ./vdbg ${file_path}`
`./v -g -o vdbg cmd/v && ./vdbg ${user_args} ${file_path} && ${generated_file}`
{file_content}
**What did you see instead?**
```
${build_output}```
**What did you expect to see?**
${expected_result}
**What did you see instead?**
```
${build_output}```'
'
mut encoded_body := urllib.query_escape(raw_body.replace_once('{file_content}', '```v\n${file_content}\n```'))
mut generated_uri := 'https://github.com/vlang/v/issues/new?labels=Bug&body=${encoded_body}'
if generated_uri.len > 8192 {
// GitHub doesn't support URLs longer than 8192 characters
encoded_body = urllib.query_escape(raw_body.replace_once('{file_content}', 'See attached file `${file_path}`'))
generated_uri = 'https://github.com/vlang/v/issues/new?labels=Bug&body=${encoded_body}'
println('Your file is too big to be submitted. Head over to the following URL and attach your file.')
println(generated_uri)
elog('> Your file is too big to be submitted.')
elog('> Go to the following URL, and attach your file:')
olog(generated_uri)
} else {
os.open_uri(generated_uri) or {
if is_verbose {
eprintln(err)
elog(err.str())
}
println(generated_uri)
olog(generated_uri)
}
}
}
8 changes: 5 additions & 3 deletions vlib/v/gen/c/array.v
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ fn (mut g Gen) array_init(node ast.ArrayInit, var_name string) {
}
for i, expr in node.exprs {
if node.expr_types[i] == ast.string_type
&& expr !in [ast.StringLiteral, ast.StringInterLiteral] {
&& expr !in [ast.IndexExpr, ast.CallExpr, ast.StringLiteral, ast.StringInterLiteral, ast.InfixExpr] {
g.write('string_clone(')
g.expr(expr)
g.write(')')
Expand Down Expand Up @@ -1035,12 +1035,14 @@ fn (mut g Gen) gen_array_insert(node ast.CallExpr) {
g.expr(node.args[1].expr)
g.write('.len)')
} else {
needs_clone := left_info.elem_type == ast.string_type
&& node.args[1].expr !in [ast.IndexExpr, ast.CallExpr, ast.StringLiteral, ast.StringInterLiteral, ast.InfixExpr]
g.write(', &(${elem_type_str}[]){')
if left_info.elem_type == ast.string_type {
if needs_clone {
g.write('string_clone(')
}
g.expr_with_cast(node.args[1].expr, node.args[1].typ, left_info.elem_type)
if left_info.elem_type == ast.string_type {
if needs_clone {
g.write(')')
}
g.write('})')
Expand Down
3 changes: 2 additions & 1 deletion vlib/v/gen/c/assert.v
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,8 @@ fn (mut g Gen) gen_assert_single_expr(expr ast.Expr, typ ast.Type) {
}
else {
mut should_clone := true
if typ == ast.string_type && expr is ast.StringLiteral {
if typ == ast.string_type
&& expr in [ast.IndexExpr, ast.CallExpr, ast.StringLiteral, ast.StringInterLiteral] {
should_clone = false
}
if expr is ast.CTempVar {
Expand Down
2 changes: 1 addition & 1 deletion vlib/v/gen/c/cgen.v
Original file line number Diff line number Diff line change
Expand Up @@ -7043,7 +7043,7 @@ fn (mut g Gen) type_default_impl(typ_ ast.Type, decode_sumtype bool) string {
}
} else {
default_str := g.expr_string_opt(field.typ, field.default_expr)
if default_str.count('\n') > 1 {
if default_str.count(';\n') > 1 {
g.type_default_vars.writeln(default_str.all_before_last('\n'))
expr_str = default_str.all_after_last('\n')
} else {
Expand Down
1 change: 1 addition & 0 deletions vlib/v/gen/c/infix.v
Original file line number Diff line number Diff line change
Expand Up @@ -1054,6 +1054,7 @@ fn (mut g Gen) infix_expr_left_shift_op(node ast.InfixExpr) {
needs_clone := !g.is_builtin_mod
&& array_info.elem_type.idx() == ast.string_type_idx
&& array_info.elem_type.nr_muls() == 0
&& node.right !in [ast.StringLiteral, ast.StringInterLiteral, ast.CallExpr, ast.IndexExpr, ast.InfixExpr]
if needs_clone {
g.write('string_clone(')
}
Expand Down
15 changes: 15 additions & 0 deletions vlib/v/tests/structs/default_expr_array_init_test.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
struct Foo {
pub mut:
integer_range_for_discrete []int = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
}

fn foo(a string) Foo {
return match a {
'a' { Foo{} }
else { panic('foo') }
}
}

fn test_main() {
assert foo('a') == Foo{}
}
8 changes: 8 additions & 0 deletions vlib/v/type_resolver/generic_resolver.v
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,14 @@ pub fn (mut t TypeResolver) resolve_args(cur_fn &ast.FnDecl, func &ast.Fn, mut n
comptime_args[k] = cparam_type_sym.info.key_type
comptime_args[k + 1] = cparam_type_sym.info.value_type
}
} else if call_arg.expr is ast.IndexExpr && t.info.is_comptime(call_arg.expr) {
mut ctyp := t.get_type(call_arg.expr)
param_typ_sym := t.table.sym(param_typ)
cparam_type_sym := t.table.sym(t.resolver.unwrap_generic(ctyp))
if param_typ_sym.kind == .array && cparam_type_sym.info is ast.Array {
ctyp = cparam_type_sym.info.elem_type
}
comptime_args[k] = ctyp
}
}
return comptime_args
Expand Down
4 changes: 2 additions & 2 deletions vlib/x/json2/decoder.v
Original file line number Diff line number Diff line change
Expand Up @@ -291,8 +291,8 @@ fn decode_array_item[T](mut field T, arr []Any) {
$else $if T is [][]?u64 { field << arr.map(it.as_map().values().map(?u64(it.u64()))) }
$else $if T is [][]bool { field << arr.map(it.as_map().values().map(it.bool())) }
$else $if T is [][]?bool { field << arr.map(it.as_map().values().map(?bool(it.bool()))) }
$else $if T is [][]string { field << arr.map(it.as_map().values().map(it.string())) }
$else $if T is [][]?string { field << arr.map(it.as_map().values().map(?string(it.string()))) }
$else $if T is [][]string { field << arr.map(it.as_map().values().map(it.str())) }
$else $if T is [][]?string { field << arr.map(it.as_map().values().map(?string(it.str()))) }
}
}
// vfmt on
Expand Down
18 changes: 18 additions & 0 deletions vlib/x/json2/json2.v
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,24 @@ pub fn (f Any) i64() i64 {
}
}

// u8 uses `Any` as a 8-bit unsigned integer.
pub fn (f Any) u8() u8 {
match f {
u8 {
return f
}
u16, u32, i8, i16, i32, int, i64, f32, f64, bool {
return u8(u16(f))
}
string {
return f.u8()
}
else {
return 0
}
}
}

// u64 uses `Any` as a 64-bit unsigned integer.
pub fn (f Any) u64() u64 {
match f {
Expand Down
Loading

0 comments on commit 8551ba1

Please sign in to comment.