mirror of
https://github.com/vlang/v.git
synced 2025-08-03 09:47:15 -04:00
markused,builtin,strconv,vlib: reduce generated C sizes for compilers != tcc, for short programs, by simplifying the generation of backtraces, and reducing string interpolations in panics (#23380)
This commit is contained in:
parent
738f847f89
commit
e983d75b64
@ -194,7 +194,8 @@ fn (mut a array) ensure_cap(required int) {
|
||||
return
|
||||
}
|
||||
if a.flags.has(.nogrow) {
|
||||
panic('array.ensure_cap: array with the flag `.nogrow` cannot grow in size, array required new size: ${required}')
|
||||
panic_n('array.ensure_cap: array with the flag `.nogrow` cannot grow in size, array required new size:',
|
||||
required)
|
||||
}
|
||||
mut cap := if a.cap > 0 { i64(a.cap) } else { i64(2) }
|
||||
for required > cap {
|
||||
@ -205,7 +206,8 @@ fn (mut a array) ensure_cap(required int) {
|
||||
// limit the capacity, since bigger values, will overflow the 32bit integer used to store it
|
||||
cap = max_int
|
||||
} else {
|
||||
panic('array.ensure_cap: array needs to grow to cap = ${cap}, which is > 2^31')
|
||||
panic_n('array.ensure_cap: array needs to grow to cap (which is > 2^31):',
|
||||
cap)
|
||||
}
|
||||
}
|
||||
new_size := u64(cap) * u64(a.element_size)
|
||||
@ -240,7 +242,7 @@ pub fn (a array) repeat(count int) array {
|
||||
@[direct_array_access; unsafe]
|
||||
pub fn (a array) repeat_to_depth(count int, depth int) array {
|
||||
if count < 0 {
|
||||
panic('array.repeat: count is negative: ${count}')
|
||||
panic_n('array.repeat: count is negative:', count)
|
||||
}
|
||||
mut size := u64(count) * u64(a.len) * u64(a.element_size)
|
||||
if size == 0 {
|
||||
@ -293,7 +295,7 @@ pub fn (a array) repeat_to_depth(count int, depth int) array {
|
||||
// ```
|
||||
pub fn (mut a array) insert(i int, val voidptr) {
|
||||
if i < 0 || i > a.len {
|
||||
panic('array.insert: index out of range (i == ${i}, a.len == ${a.len})')
|
||||
panic_n2('array.insert: index out of range (i,a.len):', i, a.len)
|
||||
}
|
||||
if a.len == max_int {
|
||||
panic('array.insert: a.len reached max_int')
|
||||
@ -313,11 +315,11 @@ pub fn (mut a array) insert(i int, val voidptr) {
|
||||
@[unsafe]
|
||||
fn (mut a array) insert_many(i int, val voidptr, size int) {
|
||||
if i < 0 || i > a.len {
|
||||
panic('array.insert_many: index out of range (i == ${i}, a.len == ${a.len})')
|
||||
panic_n2('array.insert_many: index out of range (i,a.len):', i, a.len)
|
||||
}
|
||||
new_len := i64(a.len) + i64(size)
|
||||
if new_len > max_int {
|
||||
panic('array.insert_many: a.len = ${new_len} will exceed max_int')
|
||||
panic_n('array.insert_many: max_int will be exceeded by a.len:', new_len)
|
||||
}
|
||||
a.ensure_cap(int(new_len))
|
||||
elem_size := a.element_size
|
||||
@ -374,8 +376,12 @@ pub fn (mut a array) delete(i int) {
|
||||
// ```
|
||||
pub fn (mut a array) delete_many(i int, size int) {
|
||||
if i < 0 || i64(i) + i64(size) > i64(a.len) {
|
||||
endidx := if size > 1 { '..${i + size}' } else { '' }
|
||||
panic('array.delete: index out of range (i == ${i}${endidx}, a.len == ${a.len})')
|
||||
if size > 1 {
|
||||
panic_n3('array.delete: index out of range (i,i+size,a.len):', i, i + size,
|
||||
a.len)
|
||||
} else {
|
||||
panic_n2('array.delete: index out of range (i,a.len):', i, a.len)
|
||||
}
|
||||
}
|
||||
if a.flags.all(.noshrink | .noslices) {
|
||||
unsafe {
|
||||
@ -465,7 +471,7 @@ fn (a array) get_unsafe(i int) voidptr {
|
||||
fn (a array) get(i int) voidptr {
|
||||
$if !no_bounds_checking {
|
||||
if i < 0 || i >= a.len {
|
||||
panic('array.get: index out of range (i == ${i}, a.len == ${a.len})')
|
||||
panic_n2('array.get: index out of range (i,a.len):', i, a.len)
|
||||
}
|
||||
}
|
||||
unsafe {
|
||||
@ -557,13 +563,15 @@ fn (a array) slice(start int, _end int) array {
|
||||
end := if _end == max_int { a.len } else { _end } // max_int
|
||||
$if !no_bounds_checking {
|
||||
if start > end {
|
||||
panic('array.slice: invalid slice index (${start} > ${end})')
|
||||
panic('array.slice: invalid slice index (start>end):' + i64(start).str() + ', ' +
|
||||
i64(end).str())
|
||||
}
|
||||
if end > a.len {
|
||||
panic('array.slice: slice bounds out of range (${end} >= ${a.len})')
|
||||
panic('array.slice: slice bounds out of range (' + i64(end).str() + ' >= ' +
|
||||
i64(a.len).str() + ')')
|
||||
}
|
||||
if start < 0 {
|
||||
panic('array.slice: slice bounds out of range (${start} < 0)')
|
||||
panic('array.slice: slice bounds out of range (start<0):' + start.str())
|
||||
}
|
||||
}
|
||||
// TODO: integrate reference counting
|
||||
@ -683,7 +691,7 @@ fn (mut a array) set_unsafe(i int, val voidptr) {
|
||||
fn (mut a array) set(i int, val voidptr) {
|
||||
$if !no_bounds_checking {
|
||||
if i < 0 || i >= a.len {
|
||||
panic('array.set: index out of range (i == ${i}, a.len == ${a.len})')
|
||||
panic_n2('array.set: index out of range (i,a.len):', i, a.len)
|
||||
}
|
||||
}
|
||||
unsafe { vmemcpy(&u8(a.data) + u64(a.element_size) * u64(i), val, a.element_size) }
|
||||
@ -1000,7 +1008,7 @@ pub fn copy(mut dst []u8, src []u8) int {
|
||||
pub fn (mut a array) grow_cap(amount int) {
|
||||
new_cap := i64(amount) + i64(a.cap)
|
||||
if new_cap > max_int {
|
||||
panic('array.grow_cap: new capacity ${new_cap} will exceed max_int')
|
||||
panic_n('array.grow_cap: max_int will be exceeded by new cap:', new_cap)
|
||||
}
|
||||
a.ensure_cap(int(new_cap))
|
||||
}
|
||||
@ -1013,7 +1021,7 @@ pub fn (mut a array) grow_cap(amount int) {
|
||||
pub fn (mut a array) grow_len(amount int) {
|
||||
new_len := i64(amount) + i64(a.len)
|
||||
if new_len > max_int {
|
||||
panic('array.grow_len: new len ${new_len} will exceed max_int')
|
||||
panic_n('array.grow_len: max_int will be exceeded by new len:', new_len)
|
||||
}
|
||||
a.ensure_cap(int(new_len))
|
||||
a.len = int(new_len)
|
||||
@ -1053,13 +1061,13 @@ pub fn (data &u8) vbytes(len int) []u8 {
|
||||
@[if !no_bounds_checking ?; inline]
|
||||
fn panic_on_negative_len(len int) {
|
||||
if len < 0 {
|
||||
panic('negative .len')
|
||||
panic_n('negative .len:', len)
|
||||
}
|
||||
}
|
||||
|
||||
@[if !no_bounds_checking ?; inline]
|
||||
fn panic_on_negative_cap(cap int) {
|
||||
if cap < 0 {
|
||||
panic('negative .cap')
|
||||
panic_n('negative .cap:', cap)
|
||||
}
|
||||
}
|
||||
|
@ -103,7 +103,8 @@ fn (mut a array) ensure_cap_noscan(required int) {
|
||||
return
|
||||
}
|
||||
if a.flags.has(.nogrow) {
|
||||
panic('array.ensure_cap_noscan: array with the flag `.nogrow` cannot grow in size, array required new size: ${required}')
|
||||
panic_n('array.ensure_cap_noscan: array with the flag `.nogrow` cannot grow in size, array required new size:',
|
||||
required)
|
||||
}
|
||||
mut cap := if a.cap > 0 { i64(a.cap) } else { i64(2) }
|
||||
for required > cap {
|
||||
@ -114,7 +115,8 @@ fn (mut a array) ensure_cap_noscan(required int) {
|
||||
// limit the capacity, since bigger values, will overflow the 32bit integer used to store it
|
||||
cap = max_int
|
||||
} else {
|
||||
panic('array.ensure_cap_noscan: array needs to grow to cap = ${cap}, which is > 2^31')
|
||||
panic_n('array.ensure_cap_noscan: array needs to grow to cap (which is > 2^31):',
|
||||
cap)
|
||||
}
|
||||
}
|
||||
new_size := u64(cap) * u64(a.element_size)
|
||||
@ -136,7 +138,7 @@ fn (mut a array) ensure_cap_noscan(required int) {
|
||||
@[unsafe]
|
||||
fn (a array) repeat_to_depth_noscan(count int, depth int) array {
|
||||
if count < 0 {
|
||||
panic('array.repeat: count is negative: ${count}')
|
||||
panic_n('array.repeat: count is negative:', count)
|
||||
}
|
||||
mut size := u64(count) * u64(a.len) * u64(a.element_size)
|
||||
if size == 0 {
|
||||
@ -170,7 +172,7 @@ fn (a array) repeat_to_depth_noscan(count int, depth int) array {
|
||||
// insert inserts a value in the array at index `i`
|
||||
fn (mut a array) insert_noscan(i int, val voidptr) {
|
||||
if i < 0 || i > a.len {
|
||||
panic('array.insert_noscan: index out of range (i == ${i}, a.len == ${a.len})')
|
||||
panic_n2('array.insert_noscan: index out of range (i,a.len):', i, a.len)
|
||||
}
|
||||
if a.len == max_int {
|
||||
panic('array.insert_noscan: a.len reached max_int')
|
||||
@ -187,11 +189,11 @@ fn (mut a array) insert_noscan(i int, val voidptr) {
|
||||
@[unsafe]
|
||||
fn (mut a array) insert_many_noscan(i int, val voidptr, size int) {
|
||||
if i < 0 || i > a.len {
|
||||
panic('array.insert_many: index out of range (i == ${i}, a.len == ${a.len})')
|
||||
panic_n2('array.insert_many: index out of range (i, a.len):', i, a.len)
|
||||
}
|
||||
new_len := i64(a.len) + i64(size)
|
||||
if new_len > max_int {
|
||||
panic('array.insert_many_noscan: a.len = ${new_len} will exceed max_int')
|
||||
panic_n('array.insert_many_noscan: max_int will be exceeded by a.len:', new_len)
|
||||
}
|
||||
a.ensure_cap_noscan(a.len + size)
|
||||
elem_size := a.element_size
|
||||
@ -328,7 +330,7 @@ fn (a array) reverse_noscan() array {
|
||||
fn (mut a array) grow_cap_noscan(amount int) {
|
||||
new_cap := i64(amount) + i64(a.cap)
|
||||
if new_cap > max_int {
|
||||
panic('array.grow_cap: new capacity ${new_cap} will exceed max_int')
|
||||
panic_n('array.grow_cap: max_int will be exceeded by new cap:', new_cap)
|
||||
}
|
||||
a.ensure_cap_noscan(int(new_cap))
|
||||
}
|
||||
@ -338,7 +340,7 @@ fn (mut a array) grow_cap_noscan(amount int) {
|
||||
fn (mut a array) grow_len_noscan(amount int) {
|
||||
new_len := i64(amount) + i64(a.len)
|
||||
if new_len > max_int {
|
||||
panic('array.grow_len: new len ${new_len} will exceed max_int')
|
||||
panic_n('array.grow_len: max_int will be exceeded by new len:', new_len)
|
||||
}
|
||||
a.ensure_cap_noscan(int(new_len))
|
||||
a.len = int(new_len)
|
||||
|
@ -10,19 +10,24 @@ pub fn print_backtrace() {
|
||||
$if !no_backtrace ? {
|
||||
$if freestanding {
|
||||
println(bare_backtrace())
|
||||
} $else $if native {
|
||||
// TODO: native backtrace solution
|
||||
} $else $if tinyc {
|
||||
C.tcc_backtrace(c'Backtrace')
|
||||
} $else $if use_libbacktrace ? {
|
||||
// NOTE: TCC doesn't have the unwind library
|
||||
print_libbacktrace(1)
|
||||
} $else {
|
||||
$if native {
|
||||
// TODO: native backtrace solution
|
||||
} $else $if tinyc {
|
||||
C.tcc_backtrace(c'Backtrace')
|
||||
} $else {
|
||||
// NOTE: TCC doesn't have the unwind library
|
||||
$if use_libbacktrace ? {
|
||||
print_libbacktrace(1)
|
||||
} $else {
|
||||
print_backtrace_skipping_top_frames(2)
|
||||
}
|
||||
}
|
||||
print_backtrace_skipping_top_frames(2)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn eprint_space_padding(output string, max_len int) {
|
||||
padding_len := max_len - output.len
|
||||
if padding_len > 0 {
|
||||
for _ in 0 .. padding_len {
|
||||
eprint(' ')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -67,17 +67,14 @@ fn print_backtrace_skipping_top_frames_linux(skipframes int) bool {
|
||||
return false
|
||||
}
|
||||
nr_actual_frames := nr_ptrs - skipframes
|
||||
mut sframes := []string{}
|
||||
//////csymbols := backtrace_symbols(*voidptr(&buffer[skipframes]), nr_actual_frames)
|
||||
csymbols := C.backtrace_symbols(voidptr(&buffer[skipframes]), nr_actual_frames)
|
||||
for i in 0 .. nr_actual_frames {
|
||||
sframes << unsafe { tos2(&u8(csymbols[i])) }
|
||||
}
|
||||
for sframe in sframes {
|
||||
sframe := unsafe { tos2(&u8(csymbols[i])) }
|
||||
executable := sframe.all_before('(')
|
||||
addr := sframe.all_after('[').all_before(']')
|
||||
beforeaddr := sframe.all_before('[')
|
||||
cmd := 'addr2line -e ${executable} ${addr}'
|
||||
cmd := 'addr2line -e ' + executable + ' ' + addr
|
||||
// taken from os, to avoid depending on the os module inside builtin.v
|
||||
f := C.popen(&char(cmd.str), c'r')
|
||||
if f == unsafe { nil } {
|
||||
@ -92,7 +89,7 @@ fn print_backtrace_skipping_top_frames_linux(skipframes int) bool {
|
||||
output += tos(bp, vstrlen(bp))
|
||||
}
|
||||
}
|
||||
output = output.trim_space() + ':'
|
||||
output = output.trim_chars(' \t\n', .trim_both) + ':'
|
||||
if C.pclose(f) != 0 {
|
||||
eprintln(sframe)
|
||||
continue
|
||||
@ -104,9 +101,14 @@ fn print_backtrace_skipping_top_frames_linux(skipframes int) bool {
|
||||
// Note: it is shortened here to just d. , just so that it fits, and so
|
||||
// that the common error file:lineno: line format is enforced.
|
||||
output = output.replace(' (discriminator', ': (d.')
|
||||
eprintln('${output:-55s} | ${addr:14s} | ${beforeaddr}')
|
||||
eprint(output)
|
||||
eprint_space_padding(output, 55)
|
||||
eprint(' | ')
|
||||
eprint(addr)
|
||||
eprint(' | ')
|
||||
eprintln(beforeaddr)
|
||||
}
|
||||
if sframes.len > 0 {
|
||||
if nr_actual_frames > 0 {
|
||||
unsafe { C.free(csymbols) }
|
||||
}
|
||||
}
|
||||
|
@ -76,6 +76,7 @@ pub fn print_backtrace_skipping_top_frames(skipframes int) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
@[direct_array_access]
|
||||
fn print_backtrace_skipping_top_frames_msvc(skipframes int) bool {
|
||||
$if msvc {
|
||||
mut offset := u64(0)
|
||||
@ -116,23 +117,31 @@ fn print_backtrace_skipping_top_frames_msvc(skipframes int) bool {
|
||||
if C.SymGetLineFromAddr64(handle, frame_addr, &offset, &sline64) == 1 {
|
||||
file_name := unsafe { tos3(sline64.f_file_name) }
|
||||
lnumber := sline64.f_line_number
|
||||
lineinfo = '${file_name}:${lnumber}'
|
||||
lineinfo = file_name + i64(lnumber).str()
|
||||
} else {
|
||||
// addr:
|
||||
lineinfo = '?? : address = 0x${(&frame_addr):x}'
|
||||
lineinfo = '?? : address = 0x' + ptr_str(frame_addr)
|
||||
}
|
||||
sfunc := unsafe { tos3(fname) }
|
||||
eprintln('${nframe:-2d}: ${sfunc:-25s} ${lineinfo}')
|
||||
snframe := i64(nframe).str()
|
||||
eprint_space_padding(snframe, 2)
|
||||
eprint(': ')
|
||||
eprint(sfunc)
|
||||
eprint_space_padding(sfunc, 25)
|
||||
eprint(' ')
|
||||
eprint(lineinfo)
|
||||
} else {
|
||||
// https://docs.microsoft.com/en-us/windows/win32/debug/system-error-codes
|
||||
cerr := int(C.GetLastError())
|
||||
eprint('SymFromAddr failure: ')
|
||||
eprint(i64(cerr).str())
|
||||
if cerr == 87 {
|
||||
eprintln('SymFromAddr failure: ${cerr} = The parameter is incorrect)')
|
||||
eprintln(' = The parameter is incorrect)')
|
||||
} else if cerr == 487 {
|
||||
// probably caused because the .pdb isn't in the executable folder
|
||||
eprintln('SymFromAddr failure: ${cerr} = Attempt to access invalid address (Verify that you have the .pdb file in the right folder.)')
|
||||
eprintln(' = Attempt to access invalid address (Verify that you have the .pdb file in the right folder.)')
|
||||
} else {
|
||||
eprintln('SymFromAddr failure: ${cerr} (see https://docs.microsoft.com/en-us/windows/win32/debug/system-error-codes)')
|
||||
eprintln(' (see https://docs.microsoft.com/en-us/windows/win32/debug/system-error-codes)')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -106,14 +106,14 @@ fn panic_debug(line_no int, file string, mod string, fn_name string, s string) {
|
||||
// It ends the program with a panic.
|
||||
@[noreturn]
|
||||
pub fn panic_option_not_set(s string) {
|
||||
panic('option not set (${s})')
|
||||
panic('option not set (' + s + ')')
|
||||
}
|
||||
|
||||
// panic_result_not_set is called by V, when you use result error propagation in your main function
|
||||
// It ends the program with a panic.
|
||||
@[noreturn]
|
||||
pub fn panic_result_not_set(s string) {
|
||||
panic('result not set (${s})')
|
||||
panic('result not set (' + s + ')')
|
||||
}
|
||||
|
||||
// panic prints a nice error message, then exits the process with exit code of 1.
|
||||
@ -175,6 +175,24 @@ pub fn c_error_number_str(errnum int) string {
|
||||
return err_msg
|
||||
}
|
||||
|
||||
// panic_n prints an error message, followed by the given number, then exits the process with exit code of 1.
|
||||
@[noreturn]
|
||||
pub fn panic_n(s string, number1 i64) {
|
||||
panic(s + number1.str())
|
||||
}
|
||||
|
||||
// panic_n2 prints an error message, followed by the given numbers, then exits the process with exit code of 1.
|
||||
@[noreturn]
|
||||
pub fn panic_n2(s string, number1 i64, number2 i64) {
|
||||
panic(s + number1.str() + ', ' + number2.str())
|
||||
}
|
||||
|
||||
// panic_n3 prints an error message, followed by the given numbers, then exits the process with exit code of 1.
|
||||
@[noreturn]
|
||||
fn panic_n3(s string, number1 i64, number2 i64, number3 i64) {
|
||||
panic(s + number1.str() + ', ' + number2.str() + ', ' + number2.str())
|
||||
}
|
||||
|
||||
// panic with a C-API error message matching `errnum`
|
||||
@[noreturn]
|
||||
pub fn panic_error_number(basestr string, errnum int) {
|
||||
@ -751,8 +769,8 @@ pub fn gc_memory_use() usize {
|
||||
fn v_fixed_index(i int, len int) int {
|
||||
$if !no_bounds_checking {
|
||||
if i < 0 || i >= len {
|
||||
s := 'fixed array index out of range (index: ${i}, len: ${len})'
|
||||
panic(s)
|
||||
panic('fixed array index out of range (index: ' + i64(i).str() + ', len: ' +
|
||||
i64(len).str() + ')')
|
||||
}
|
||||
}
|
||||
return i
|
||||
|
@ -10,12 +10,6 @@ pub fn isnil(v voidptr) bool {
|
||||
return v == 0
|
||||
}
|
||||
|
||||
/*
|
||||
fn on_panic(f fn(int)int) {
|
||||
// TODO
|
||||
}
|
||||
*/
|
||||
|
||||
struct VCastTypeIndexName {
|
||||
tindex int
|
||||
tname string
|
||||
@ -37,7 +31,7 @@ fn __as_cast(obj voidptr, obj_type int, expected_type int) voidptr {
|
||||
expected_name = x.tname.clone()
|
||||
}
|
||||
}
|
||||
panic('as cast: cannot cast `${obj_name}` to `${expected_name}`')
|
||||
panic('as cast: cannot cast `' + obj_name + '` to `' + expected_name + '`')
|
||||
}
|
||||
return obj
|
||||
}
|
||||
|
@ -67,6 +67,9 @@ fn builtin_init() {
|
||||
$if !no_backtrace ? {
|
||||
add_unhandled_exception_handler()
|
||||
}
|
||||
// On windows, the default buffering is block based (~4096bytes), which interferes badly with non cmd shells
|
||||
// It is much better to have it off by default instead.
|
||||
unbuffer_stdout()
|
||||
}
|
||||
|
||||
// TODO: copypaste from os
|
||||
@ -109,7 +112,7 @@ fn unhandled_exception_handler(e &ExceptionPointers) int {
|
||||
return 0
|
||||
}
|
||||
else {
|
||||
println('Unhandled Exception 0x${e.exception_record.code:X}')
|
||||
println('Unhandled Exception 0x' + ptr_str(e.exception_record.code))
|
||||
print_backtrace_skipping_top_frames(5)
|
||||
}
|
||||
}
|
||||
|
@ -3,29 +3,18 @@
|
||||
// that can be found in the LICENSE file.
|
||||
module builtin
|
||||
|
||||
//
|
||||
// ----- value to string functions -----
|
||||
//
|
||||
|
||||
pub struct VContext {
|
||||
allocator int
|
||||
}
|
||||
|
||||
// type u8 = byte
|
||||
type byte = u8
|
||||
|
||||
// type i32 = int
|
||||
|
||||
// ptr_str returns the address of `ptr` as a `string`.
|
||||
pub fn ptr_str(ptr voidptr) string {
|
||||
buf1 := u64(ptr).hex()
|
||||
return buf1
|
||||
}
|
||||
|
||||
// pub fn nil_str(x voidptr) string {
|
||||
// return 'nil'
|
||||
//}
|
||||
|
||||
// str returns string equivalent of x
|
||||
pub fn (x isize) str() string {
|
||||
return i64(x).str()
|
||||
@ -118,18 +107,7 @@ fn (nn int) str_l(max int) string {
|
||||
}
|
||||
diff := max - index
|
||||
vmemmove(buf, voidptr(buf + index), diff + 1)
|
||||
/*
|
||||
// === manual memory move for bare metal ===
|
||||
mut c:= 0
|
||||
for c < diff {
|
||||
buf[c] = buf[c+index]
|
||||
c++
|
||||
}
|
||||
buf[c] = 0
|
||||
*/
|
||||
return tos(buf, diff)
|
||||
|
||||
// return tos(memdup(&buf[0] + index, (max - index)), (max - index))
|
||||
}
|
||||
}
|
||||
|
||||
@ -165,10 +143,6 @@ pub fn (n int) str() string {
|
||||
return n.str_l(12)
|
||||
}
|
||||
|
||||
// pub fn int_str(n int) string {
|
||||
// return i64(n).str()
|
||||
//}
|
||||
|
||||
// str returns the value of the `u32` as a `string`.
|
||||
// Example: assert u32(20000).str() == '20000'
|
||||
@[direct_array_access; inline]
|
||||
@ -202,8 +176,6 @@ pub fn (nn u32) str() string {
|
||||
diff := max - index
|
||||
vmemmove(buf, voidptr(buf + index), diff + 1)
|
||||
return tos(buf, diff)
|
||||
|
||||
// return tos(memdup(&buf[0] + index, (max - index)), (max - index))
|
||||
}
|
||||
}
|
||||
|
||||
@ -258,7 +230,6 @@ pub fn (nn i64) str() string {
|
||||
diff := max - index
|
||||
vmemmove(buf, voidptr(buf + index), diff + 1)
|
||||
return tos(buf, diff)
|
||||
// return tos(memdup(&buf[0] + index, (max - index)), (max - index))
|
||||
}
|
||||
}
|
||||
|
||||
@ -295,7 +266,6 @@ pub fn (nn u64) str() string {
|
||||
diff := max - index
|
||||
vmemmove(buf, voidptr(buf + index), diff + 1)
|
||||
return tos(buf, diff)
|
||||
// return tos(memdup(&buf[0] + index, (max - index)), (max - index))
|
||||
}
|
||||
}
|
||||
|
||||
@ -308,10 +278,6 @@ pub fn (b bool) str() string {
|
||||
return 'false'
|
||||
}
|
||||
|
||||
//
|
||||
// ----- value to hex string functions -----
|
||||
//
|
||||
|
||||
// u64_to_hex converts the number `nn` to a (zero padded if necessary) hexadecimal `string`.
|
||||
@[direct_array_access; inline]
|
||||
fn u64_to_hex(nn u64, len u8) string {
|
||||
|
@ -6,9 +6,19 @@ module builtin
|
||||
|
||||
fn (a any) toString()
|
||||
|
||||
// panic prints an error message, then exits the process with exit code of 1.
|
||||
@[noreturn]
|
||||
pub fn panic(s string) {
|
||||
eprintln('V panic: ${s}\n${js_stacktrace()}')
|
||||
eprintln('V panic: ' + s)
|
||||
eprintln(js_stacktrace())
|
||||
exit(1)
|
||||
}
|
||||
|
||||
// panic_n prints an error message, followed by the given number, then exits the process with exit code of 1.
|
||||
@[noreturn]
|
||||
pub fn panic_n(s string, n i64) {
|
||||
eprintln('V panic: ' + s)
|
||||
eprintln(js_stacktrace())
|
||||
exit(1)
|
||||
}
|
||||
|
||||
|
@ -158,6 +158,7 @@ fn (mut n mapnode) split_child(child_index int, mut y mapnode) {
|
||||
n.len++
|
||||
}
|
||||
|
||||
@[direct_array_access]
|
||||
fn (m SortedMap) get(key string, out voidptr) bool {
|
||||
mut node := m.root
|
||||
for {
|
||||
|
@ -1115,7 +1115,8 @@ pub fn (s string) substr(start int, _end int) string {
|
||||
end := if _end == max_int { s.len } else { _end } // max_int
|
||||
$if !no_bounds_checking {
|
||||
if start > end || start > s.len || end > s.len || start < 0 || end < 0 {
|
||||
panic('substr(${start}, ${end}) out of bounds (len=${s.len}) s="${s}"')
|
||||
panic('substr(' + start.str() + ', ' + end.str() + ') out of bounds (len=' +
|
||||
s.len.str() + ') s=' + s)
|
||||
}
|
||||
}
|
||||
len := end - start
|
||||
@ -1153,7 +1154,8 @@ pub fn (s string) substr_unsafe(start int, _end int) string {
|
||||
pub fn (s string) substr_with_check(start int, _end int) !string {
|
||||
end := if _end == max_int { s.len } else { _end } // max_int
|
||||
if start > end || start > s.len || end > s.len || start < 0 || end < 0 {
|
||||
return error('substr(${start}, ${end}) out of bounds (len=${s.len})')
|
||||
return error('substr(' + start.str() + ', ' + end.str() + ') out of bounds (len=' +
|
||||
s.len.str() + ')')
|
||||
}
|
||||
len := end - start
|
||||
if len == s.len {
|
||||
@ -1962,7 +1964,7 @@ pub fn (s string) str() string {
|
||||
fn (s string) at(idx int) u8 {
|
||||
$if !no_bounds_checking {
|
||||
if idx < 0 || idx >= s.len {
|
||||
panic('string index out of range: ${idx} / ${s.len}')
|
||||
panic_n2('string index out of range(idx,s.len):', idx, s.len)
|
||||
}
|
||||
}
|
||||
return unsafe { s.str[idx] }
|
||||
|
@ -78,14 +78,15 @@ pub fn utf32_decode_to_buffer(code u32, mut buf &u8) int {
|
||||
// it is used in vlib/builtin/string.v,
|
||||
// and also in vlib/v/gen/c/cgen.v
|
||||
pub fn (_rune string) utf32_code() int {
|
||||
return int(_rune.bytes().utf8_to_utf32() or {
|
||||
// error('more than one utf-8 rune found in this string')
|
||||
rune(0)
|
||||
})
|
||||
if res := _rune.bytes().utf8_to_utf32() {
|
||||
return int(res)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// convert array of utf8 bytes to single utf32 value
|
||||
// will error if more than 4 bytes are submitted
|
||||
@[direct_array_access]
|
||||
pub fn (_bytes []u8) utf8_to_utf32() !rune {
|
||||
if _bytes.len == 0 {
|
||||
return 0
|
||||
|
@ -113,6 +113,6 @@ fn init() {
|
||||
}
|
||||
|
||||
if ret < 0 {
|
||||
panic('failed to initialize coroutines via photon (ret=${ret})')
|
||||
panic_n('failed to initialize coroutines via photon ret:', ret)
|
||||
}
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ pub fn (mut l Log) set_output_path(output_file_path string) {
|
||||
l.output_target = .file
|
||||
l.output_file_name = os.join_path(os.real_path(output_file_path), l.output_label)
|
||||
ofile := os.open_append(l.output_file_name) or {
|
||||
panic('error while opening log file ${l.output_file_name} for appending')
|
||||
panic('error while opening log file ' + l.output_file_name + ' for appending')
|
||||
}
|
||||
l.ofile = ofile
|
||||
}
|
||||
@ -160,7 +160,7 @@ pub fn (mut l Log) fatal(s string) {
|
||||
l.send_output(s, .fatal)
|
||||
l.ofile.close()
|
||||
}
|
||||
panic('${l.output_label}: ${s}')
|
||||
panic(l.output_label + ': ' + s)
|
||||
}
|
||||
|
||||
// error logs line `s` via `send_output` if `Log.level` is greater than or equal to the `Level.error` category.
|
||||
|
@ -36,7 +36,7 @@ pub fn maxof[T]() T {
|
||||
}
|
||||
return int(max_i32)
|
||||
} $else {
|
||||
panic('A maximum value of the type `${typeof[T]().name}` is not defined.')
|
||||
panic('A maximum value of the type `' + typeof[T]().name + '` is not defined.')
|
||||
}
|
||||
}
|
||||
|
||||
@ -73,6 +73,6 @@ pub fn minof[T]() T {
|
||||
}
|
||||
return int(min_i32)
|
||||
} $else {
|
||||
panic('A minimum value of the type `${typeof[T]().name}` is not defined.')
|
||||
panic('A minimum value of the type `' + typeof[T]().name + '` is not defined.')
|
||||
}
|
||||
}
|
||||
|
@ -70,7 +70,7 @@ pub fn digits(num i64, params DigitParams) []int {
|
||||
// set base to 10 initially and change only if base is explicitly set.
|
||||
mut b := params.base
|
||||
if b < 2 {
|
||||
panic('digits: Cannot find digits of n with base ${b}')
|
||||
panic_n('digits: Cannot find digits of n with base:', b)
|
||||
}
|
||||
mut n := num
|
||||
mut sign := 1
|
||||
|
@ -254,7 +254,7 @@ pub fn resolve_ipaddrs(addr string, family AddrFamily, typ SocketType) ![]Addr {
|
||||
addresses << new_addr
|
||||
}
|
||||
else {
|
||||
panic('Unexpected address family ${result.ai_family}')
|
||||
panic('Unexpected address family ' + result.ai_family.str())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -743,7 +743,7 @@ pub fn (h Header) join(other Header) Header {
|
||||
for v in other.custom_values(k, exact: true) {
|
||||
combined.add_custom(k, v) or {
|
||||
// panic because this should never fail
|
||||
panic('unexpected error: ${err}')
|
||||
panic('unexpected error: ' + err.str())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -93,7 +93,7 @@ fn swap_bytes[T](input T) T {
|
||||
} $else $if T is i64 {
|
||||
return i64(swap_bytes_u64(u64(input)))
|
||||
} $else {
|
||||
panic('type is not supported: ${typeof[T]()}')
|
||||
panic('type is not supported: ' + typeof[T]().str())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -606,7 +606,7 @@ pub fn read_file_array[T](path string) []T {
|
||||
// On some systems C.ftell can return values in the 64-bit range
|
||||
// that, when cast to `int`, can result in values below 0.
|
||||
if i64(allocate) < fsize {
|
||||
panic('${fsize} cast to int results in ${int(fsize)})')
|
||||
panic_n2('cast to int results in (fsize, int(fsize)):', i64(fsize), i64(int(fsize)))
|
||||
}
|
||||
buf := unsafe {
|
||||
malloc_noscan(allocate)
|
||||
|
@ -40,7 +40,7 @@ fn test_open_file() {
|
||||
file.write_string(hello) or { panic(err) }
|
||||
file.close()
|
||||
assert u64(hello.len) == os.file_size(filename)
|
||||
read_hello := os.read_file(filename) or { panic('error reading file ${filename}') }
|
||||
read_hello := os.read_file(filename) or { panic('error reading file ' + filename) }
|
||||
assert hello == read_hello
|
||||
os.rm(filename) or { panic(err) }
|
||||
}
|
||||
@ -80,7 +80,7 @@ fn test_open_file_binary() {
|
||||
unsafe { file.write_ptr(bytes.data, bytes.len) }
|
||||
file.close()
|
||||
assert u64(hello.len) == os.file_size(filename)
|
||||
read_hello := os.read_bytes(filename) or { panic('error reading file ${filename}') }
|
||||
read_hello := os.read_bytes(filename) or { panic('error reading file ' + filename) }
|
||||
assert bytes == read_hello
|
||||
os.rm(filename) or { panic(err) }
|
||||
}
|
||||
@ -160,7 +160,7 @@ fn test_write_and_read_string_to_file() {
|
||||
hello := 'hello world!'
|
||||
os.write_file(filename, hello) or { panic(err) }
|
||||
assert u64(hello.len) == os.file_size(filename)
|
||||
read_hello := os.read_file(filename) or { panic('error reading file ${filename}') }
|
||||
read_hello := os.read_file(filename) or { panic('error reading file ' + filename) }
|
||||
assert hello == read_hello
|
||||
os.rm(filename) or { panic(err) }
|
||||
}
|
||||
@ -322,7 +322,7 @@ fn test_cp() {
|
||||
old_file_name := 'cp_example.txt'
|
||||
new_file_name := 'cp_new_example.txt'
|
||||
os.write_file(old_file_name, 'Test data 1 2 3, V is awesome #$%^[]!~⭐') or { panic(err) }
|
||||
os.cp(old_file_name, new_file_name) or { panic('${err}') }
|
||||
os.cp(old_file_name, new_file_name) or { panic(err) }
|
||||
old_file := os.read_file(old_file_name) or { panic(err) }
|
||||
new_file := os.read_file(new_file_name) or { panic(err) }
|
||||
assert old_file == new_file
|
||||
|
@ -258,10 +258,10 @@ fn (mut p Process) _is_pending(pkind ChildProcessPipeKind) bool {
|
||||
// _check_redirection_call - should be called just by stdxxx methods
|
||||
fn (mut p Process) _check_redirection_call(fn_name string) {
|
||||
if !p.use_stdio_ctl {
|
||||
panic('Call p.set_redirect_stdio() before calling p.${fn_name}')
|
||||
panic('Call p.set_redirect_stdio() before calling p.' + fn_name)
|
||||
}
|
||||
if p.status == .not_started {
|
||||
panic('Call p.${fn_name}() after you have called p.run()')
|
||||
panic('Call p.' + fn_name + '() after you have called p.run()')
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -198,7 +198,7 @@ fn (mut p Process) win_is_alive() bool {
|
||||
///////////////
|
||||
|
||||
fn (mut p Process) win_write_string(idx int, _s string) {
|
||||
panic('Process.write_string ${idx} is not implemented yet')
|
||||
panic_n('Process.write_string is not implemented yet, idx:', idx)
|
||||
}
|
||||
|
||||
fn (mut p Process) win_read_string(idx int, _maxbytes int) (string, int) {
|
||||
|
@ -8,7 +8,7 @@ const base_digits = '0123456789abcdefghijklmnopqrstuvwxyz'
|
||||
pub fn format_int(n i64, radix int) string {
|
||||
unsafe {
|
||||
if radix < 2 || radix > 36 {
|
||||
panic('invalid radix: ${radix} . It should be => 2 and <= 36')
|
||||
panic_n('invalid radix, it should be => 2 and <= 36, actual:', radix)
|
||||
}
|
||||
if n == 0 {
|
||||
return '0'
|
||||
@ -45,7 +45,7 @@ pub fn format_int(n i64, radix int) string {
|
||||
pub fn format_uint(n u64, radix int) string {
|
||||
unsafe {
|
||||
if radix < 2 || radix > 36 {
|
||||
panic('invalid radix: ${radix} . It should be => 2 and <= 36')
|
||||
panic_n('invalid radix, it should be => 2 and <= 36, actual:', radix)
|
||||
}
|
||||
if n == 0 {
|
||||
return '0'
|
||||
|
@ -551,7 +551,8 @@ pub fn v_sprintf(str string, pt ...voidptr) string {
|
||||
}
|
||||
|
||||
if p_index != pt.len {
|
||||
panic('${p_index} % conversion specifiers, but given ${pt.len} args')
|
||||
panic_n2('% conversion specifiers number mismatch (expected %, given args)', p_index,
|
||||
pt.len)
|
||||
}
|
||||
|
||||
return res.str()
|
||||
@ -560,7 +561,8 @@ pub fn v_sprintf(str string, pt ...voidptr) string {
|
||||
@[inline]
|
||||
fn v_sprintf_panic(idx int, len int) {
|
||||
if idx >= len {
|
||||
panic('${idx + 1} % conversion specifiers, but given only ${len} args')
|
||||
panic_n2('% conversion specifiers number mismatch (expected %, given args)', idx + 1,
|
||||
len)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -13,21 +13,48 @@ pub fn mark_used(mut table ast.Table, mut pref_ pref.Preferences, ast_files []&a
|
||||
defer {
|
||||
util.timing_measure('MARKUSED')
|
||||
}
|
||||
|
||||
trace_skip_unused := pref_.compile_values['trace_skip_unused'] == 'true'
|
||||
trace_skip_unused_all_fns := pref_.compile_values['trace_skip_unused_all_fns'] == 'true'
|
||||
trace_skip_unused_fn_names := pref_.compile_values['trace_skip_unused_fn_names'] == 'true'
|
||||
trace_skip_unused_interface_methods := pref_.compile_values['trace_skip_unused_interface_methods'] == 'true'
|
||||
used_fns := pref_.compile_values['used_fns']
|
||||
|
||||
byteptr_idx_str := ast.byteptr_type_idx.str()
|
||||
charptr_idx_str := ast.charptr_type_idx.str()
|
||||
string_idx_str := ast.string_type_idx.str()
|
||||
array_idx_str := ast.array_type_idx.str()
|
||||
map_idx_str := ast.map_type_idx.str()
|
||||
ref_map_idx_str := int(ast.map_type.ref()).str()
|
||||
ref_densearray_idx_str := int(table.find_type('DenseArray').ref()).str()
|
||||
ref_array_idx_str := int(ast.array_type.ref()).str()
|
||||
|
||||
// Functions that must be generated and can't be skipped
|
||||
mut all_fn_root_names := []string{}
|
||||
if used_fns != '' {
|
||||
aused_fns := used_fns.split(',')
|
||||
all_fns_keys := all_fns.keys()
|
||||
mut matching := []string{}
|
||||
for ufn in aused_fns {
|
||||
if ufn.contains('*') {
|
||||
matching_fns := all_fns_keys.filter(it.match_glob(ufn))
|
||||
if matching_fns.len > 0 {
|
||||
matching << matching_fns
|
||||
}
|
||||
} else {
|
||||
matching << ufn
|
||||
}
|
||||
}
|
||||
all_fn_root_names << matching
|
||||
for m in matching {
|
||||
println('> used_fn, found matching symbol: ${m}')
|
||||
}
|
||||
}
|
||||
|
||||
if pref_.backend == .native {
|
||||
// Note: this is temporary, until the native backend supports more features!
|
||||
all_fn_root_names << 'main.main'
|
||||
} else {
|
||||
byteptr_idx_str := '${ast.byteptr_type_idx}'
|
||||
charptr_idx_str := '${ast.charptr_type_idx}'
|
||||
string_idx_str := '${ast.string_type_idx}'
|
||||
array_idx_str := '${ast.array_type_idx}'
|
||||
map_idx_str := '${ast.map_type_idx}'
|
||||
ref_map_idx_str := '${int(ast.map_type.ref())}'
|
||||
ref_densearray_idx_str := '${int(table.find_type('DenseArray').ref())}'
|
||||
ref_array_idx_str := '${int(ast.array_type.ref())}'
|
||||
|
||||
mut include_panic_deps := false
|
||||
mut core_fns := [
|
||||
'main.main',
|
||||
@ -41,23 +68,13 @@ pub fn mark_used(mut table ast.Table, mut pref_ pref.Preferences, ast_files []&a
|
||||
'println',
|
||||
'ptr_str',
|
||||
]
|
||||
|
||||
$if debug_used_features ? {
|
||||
dump(table.used_features)
|
||||
}
|
||||
if ast.float_literal_type.idx() in table.used_features.print_types
|
||||
|| ast.f64_type_idx in table.used_features.print_types
|
||||
|| ast.f32_type_idx in table.used_features.print_types {
|
||||
include_panic_deps = true
|
||||
}
|
||||
$if windows {
|
||||
if 'no_backtrace' !in pref_.compile_defines {
|
||||
include_panic_deps = true
|
||||
}
|
||||
} $else {
|
||||
if 'use_libbacktrace' in pref_.compile_defines {
|
||||
core_fns << 'print_libbacktrace'
|
||||
}
|
||||
if 'use_libbacktrace' in pref_.compile_defines {
|
||||
core_fns << 'print_libbacktrace'
|
||||
}
|
||||
if 'callstack' in pref_.compile_defines {
|
||||
core_fns << ref_array_idx_str + '.push'
|
||||
@ -69,7 +86,7 @@ pub fn mark_used(mut table ast.Table, mut pref_ pref.Preferences, ast_files []&a
|
||||
if pref_.autofree {
|
||||
core_fns << string_idx_str + '.clone_static'
|
||||
}
|
||||
if table.used_features.as_cast || table.used_features.auto_str || pref_.is_shared {
|
||||
if table.used_features.auto_str || pref_.is_shared {
|
||||
include_panic_deps = true
|
||||
core_fns << 'isnil'
|
||||
core_fns << '__new_array'
|
||||
@ -133,26 +150,19 @@ pub fn mark_used(mut table ast.Table, mut pref_ pref.Preferences, ast_files []&a
|
||||
if table.used_features.arr_last {
|
||||
core_fns << array_idx_str + '.last'
|
||||
}
|
||||
if table.used_features.arr_delete {
|
||||
include_panic_deps = true
|
||||
}
|
||||
if table.used_features.arr_insert {
|
||||
core_fns << ref_array_idx_str + '.insert_many'
|
||||
}
|
||||
if pref_.ccompiler_type != .tinyc && 'no_backtrace' !in pref_.compile_defines {
|
||||
// with backtrace on gcc/clang more code needs be generated
|
||||
include_panic_deps = true
|
||||
}
|
||||
if table.used_features.interpolation {
|
||||
include_panic_deps = true
|
||||
}
|
||||
if table.used_features.dump {
|
||||
include_panic_deps = true
|
||||
builderptr_idx := int(table.find_type('strings.Builder').ref())
|
||||
builderptr_idx := int(table.find_type('strings.Builder').ref()).str()
|
||||
core_fns << [
|
||||
'${builderptr_idx}.str',
|
||||
'${builderptr_idx}.free',
|
||||
'${builderptr_idx}.write_rune',
|
||||
builderptr_idx + '.str',
|
||||
builderptr_idx + '.free',
|
||||
builderptr_idx + '.write_rune',
|
||||
]
|
||||
}
|
||||
if table.used_features.arr_init || table.used_features.comptime_for {
|
||||
@ -205,14 +215,13 @@ pub fn mark_used(mut table ast.Table, mut pref_ pref.Preferences, ast_files []&a
|
||||
core_fns << 'v.trace_calls.on_call'
|
||||
}
|
||||
if 'C.cJSON_Parse' in all_fns {
|
||||
all_fn_root_names << 'tos5'
|
||||
all_fn_root_names << 'time.unix' // used by json
|
||||
core_fns << 'tos5'
|
||||
core_fns << 'time.unix' // used by json
|
||||
table.used_features.used_maps++ // json needs new_map etc
|
||||
include_panic_deps = true
|
||||
}
|
||||
all_fn_root_names << core_fns
|
||||
if include_panic_deps {
|
||||
all_fn_root_names << [
|
||||
core_fns << [
|
||||
'__new_array_with_default',
|
||||
'__new_array_with_default_noscan',
|
||||
'str_intp',
|
||||
@ -225,6 +234,7 @@ pub fn mark_used(mut table ast.Table, mut pref_ pref.Preferences, ast_files []&a
|
||||
charptr_idx_str + '.vstring_literal',
|
||||
]
|
||||
}
|
||||
all_fn_root_names << core_fns
|
||||
}
|
||||
if pref_.is_bare {
|
||||
all_fn_root_names << [
|
||||
@ -238,10 +248,11 @@ pub fn mark_used(mut table ast.Table, mut pref_ pref.Preferences, ast_files []&a
|
||||
}
|
||||
|
||||
is_noscan_whitelisted := pref_.gc_mode in [.boehm_full_opt, .boehm_incr_opt]
|
||||
|
||||
has_noscan := all_fn_root_names.any(it.contains('noscan')
|
||||
&& it !in ['vcalloc_noscan', 'malloc_noscan'])
|
||||
for k, mut mfn in all_fns {
|
||||
$if trace_skip_unused_all_fns ? {
|
||||
if trace_skip_unused_all_fns {
|
||||
println('k: ${k} | mfn: ${mfn.name}')
|
||||
}
|
||||
if pref_.translated && mfn.attrs.any(it.name == 'c') {
|
||||
@ -328,7 +339,6 @@ pub fn mark_used(mut table ast.Table, mut pref_ pref.Preferences, ast_files []&a
|
||||
continue
|
||||
}
|
||||
if k.starts_with('testsuite_') || k.contains('.testsuite_') {
|
||||
// eprintln('>>> test suite: $k')
|
||||
all_fn_root_names << k
|
||||
continue
|
||||
}
|
||||
@ -363,10 +373,10 @@ pub fn mark_used(mut table ast.Table, mut pref_ pref.Preferences, ast_files []&a
|
||||
all_fn_root_names << 'main.cb_assertion_ok'
|
||||
all_fn_root_names << 'main.cb_assertion_failed'
|
||||
if benched_tests_sym := table.find_sym('main.BenchedTests') {
|
||||
bts_type := benched_tests_sym.methods[0].params[0].typ
|
||||
all_fn_root_names << '${bts_type}.testing_step_start'
|
||||
all_fn_root_names << '${bts_type}.testing_step_end'
|
||||
all_fn_root_names << '${bts_type}.end_testing'
|
||||
bts_type := benched_tests_sym.methods[0].params[0].typ.str()
|
||||
all_fn_root_names << bts_type + '.testing_step_start'
|
||||
all_fn_root_names << bts_type + '.testing_step_end'
|
||||
all_fn_root_names << bts_type + '.end_testing'
|
||||
all_fn_root_names << 'main.start_testing'
|
||||
}
|
||||
}
|
||||
@ -390,16 +400,18 @@ pub fn mark_used(mut table ast.Table, mut pref_ pref.Preferences, ast_files []&a
|
||||
interface_types := [ptype, ntype]
|
||||
for method in interface_info.methods {
|
||||
for typ in interface_types {
|
||||
interface_implementation_method_name := '${int(typ.clear_flags())}.${method.name}'
|
||||
$if trace_skip_unused_interface_methods ? {
|
||||
interface_implementation_method_name := int(typ.clear_flags()).str() + '.' +
|
||||
method.name
|
||||
if trace_skip_unused_interface_methods {
|
||||
eprintln('>> isym.name: ${isym.name} | interface_implementation_method_name: ${interface_implementation_method_name}')
|
||||
}
|
||||
all_fn_root_names << interface_implementation_method_name
|
||||
}
|
||||
}
|
||||
for embed_method in table.get_embed_methods(table.sym(itype)) {
|
||||
interface_implementation_method_name := '${int(embed_method.params[0].typ.clear_flags())}.${embed_method.name}'
|
||||
$if trace_skip_unused_interface_methods ? {
|
||||
interface_implementation_method_name :=
|
||||
int(embed_method.params[0].typ.clear_flags()).str() + '.' + embed_method.name
|
||||
if trace_skip_unused_interface_methods {
|
||||
eprintln('>> isym.name: ${isym.name} | interface_implementation_method_name: ${interface_implementation_method_name} (embeded)')
|
||||
}
|
||||
all_fn_root_names << interface_implementation_method_name
|
||||
@ -420,17 +432,21 @@ pub fn mark_used(mut table ast.Table, mut pref_ pref.Preferences, ast_files []&a
|
||||
}
|
||||
}
|
||||
for orm_type in orm_connection_implementations {
|
||||
typ := int(orm_type)
|
||||
all_fn_root_names << '${typ}.select'
|
||||
all_fn_root_names << '${typ}.insert'
|
||||
all_fn_root_names << '${typ}.update'
|
||||
all_fn_root_names << '${typ}.delete'
|
||||
all_fn_root_names << '${typ}.create'
|
||||
all_fn_root_names << '${typ}.drop'
|
||||
all_fn_root_names << '${typ}.last_id'
|
||||
typ := int(orm_type).str()
|
||||
all_fn_root_names << typ + '.select'
|
||||
all_fn_root_names << typ + '.insert'
|
||||
all_fn_root_names << typ + '.update'
|
||||
all_fn_root_names << typ + '.delete'
|
||||
all_fn_root_names << typ + '.create'
|
||||
all_fn_root_names << typ + '.drop'
|
||||
all_fn_root_names << typ + '.last_id'
|
||||
}
|
||||
}
|
||||
|
||||
if 'debug_used_features' in pref_.compile_defines {
|
||||
dump(table.used_features)
|
||||
}
|
||||
|
||||
mut walker := Walker.new(
|
||||
table: table
|
||||
files: ast_files
|
||||
@ -483,7 +499,7 @@ pub fn mark_used(mut table ast.Table, mut pref_ pref.Preferences, ast_files []&a
|
||||
}
|
||||
}
|
||||
|
||||
$if trace_skip_unused_fn_names ? {
|
||||
if trace_skip_unused_fn_names {
|
||||
for key, _ in walker.used_fns {
|
||||
println('> used fn key: ${key}')
|
||||
}
|
||||
@ -504,11 +520,18 @@ pub fn mark_used(mut table ast.Table, mut pref_ pref.Preferences, ast_files []&a
|
||||
}
|
||||
}
|
||||
|
||||
if table.used_features.range_index {
|
||||
walker.fn_by_name(string_idx_str + '.substr')
|
||||
}
|
||||
if walker.as_cast_type_names.len > 0 {
|
||||
walker.fn_by_name('new_array_from_c_array')
|
||||
}
|
||||
|
||||
table.used_features.used_fns = walker.used_fns.move()
|
||||
table.used_features.used_consts = walker.used_consts.move()
|
||||
table.used_features.used_globals = walker.used_globals.move()
|
||||
|
||||
$if trace_skip_unused ? {
|
||||
if trace_skip_unused {
|
||||
eprintln('>> t.used_fns: ${table.used_features.used_fns.keys()}')
|
||||
eprintln('>> t.used_consts: ${table.used_features.used_consts.keys()}')
|
||||
eprintln('>> t.used_globals: ${table.used_features.used_globals.keys()}')
|
||||
@ -554,9 +577,9 @@ fn all_fn_const_and_global(ast_files []&ast.File) (map[string]ast.FnDecl, map[st
|
||||
|
||||
fn mark_all_methods_used(mut table ast.Table, mut all_fn_root_names []string, typ ast.Type) {
|
||||
sym := table.sym(typ)
|
||||
styp := '${int(typ)}'
|
||||
styp := int(typ).str()
|
||||
for method in sym.methods {
|
||||
all_fn_root_names << '${styp}.${method.name}'
|
||||
all_fn_root_names << styp + '.' + method.name
|
||||
}
|
||||
}
|
||||
|
||||
@ -572,7 +595,7 @@ fn handle_vweb(mut table ast.Table, mut all_fn_root_names []string, result_name
|
||||
mark_all_methods_used(mut table, mut all_fn_root_names, typ_vweb_context)
|
||||
for vgt in table.used_features.used_veb_types {
|
||||
sym_app := table.sym(vgt)
|
||||
pvgt := '${int(vgt.set_nr_muls(1))}'
|
||||
pvgt := int(vgt.set_nr_muls(1)).str()
|
||||
for m in sym_app.methods {
|
||||
mut skip := true
|
||||
if m.name == 'before_request' {
|
||||
@ -586,7 +609,7 @@ fn handle_vweb(mut table ast.Table, mut all_fn_root_names []string, result_name
|
||||
continue
|
||||
}
|
||||
// eprintln('vgt: $vgt | pvgt: $pvgt | sym_app.name: $sym_app.name | m.name: $m.name')
|
||||
all_fn_root_names << '${pvgt}.${m.name}'
|
||||
all_fn_root_names << pvgt + '.' + m.name
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -22,6 +22,8 @@ mut:
|
||||
all_fns map[string]ast.FnDecl
|
||||
all_consts map[string]ast.ConstField
|
||||
all_globals map[string]ast.GlobalField
|
||||
//
|
||||
as_cast_type_names map[string]string
|
||||
}
|
||||
|
||||
pub fn Walker.new(params Walker) &Walker {
|
||||
@ -367,6 +369,10 @@ fn (mut w Walker) expr(node_ ast.Expr) {
|
||||
w.features.used_maps++
|
||||
} else if sym.kind == .array {
|
||||
w.features.used_arrays++
|
||||
} else if sym.kind == .string {
|
||||
if node.index is ast.RangeExpr {
|
||||
w.features.range_index = true
|
||||
}
|
||||
}
|
||||
}
|
||||
ast.InfixExpr {
|
||||
@ -507,6 +513,7 @@ fn (mut w Walker) expr(node_ ast.Expr) {
|
||||
///
|
||||
ast.AsCast {
|
||||
w.expr(node.expr)
|
||||
w.as_cast(node)
|
||||
}
|
||||
ast.AtExpr {}
|
||||
ast.BoolLiteral {}
|
||||
@ -726,3 +733,37 @@ pub fn (mut w Walker) or_block(node ast.OrExpr) {
|
||||
w.stmts(node.stmts)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (mut w Walker) as_cast(node ast.AsCast) {
|
||||
if node.typ == 0 {
|
||||
return
|
||||
}
|
||||
if node.typ.has_flag(.generic) {
|
||||
w.as_cast_type_names['some_generic_type'] = 'some_generic_name'
|
||||
return
|
||||
}
|
||||
if node.expr_type == 0 {
|
||||
return
|
||||
}
|
||||
if node.expr_type.has_flag(.generic) {
|
||||
w.as_cast_type_names['some_generic_type'] = 'some_generic_name'
|
||||
return
|
||||
}
|
||||
mut expr_type_sym := w.table.sym(node.expr_type)
|
||||
if mut expr_type_sym.info is ast.SumType {
|
||||
w.fill_as_cast_type_names(expr_type_sym.info.variants)
|
||||
} else if mut expr_type_sym.info is ast.Interface && node.expr_type != node.typ {
|
||||
w.fill_as_cast_type_names(expr_type_sym.info.types)
|
||||
}
|
||||
}
|
||||
|
||||
fn (mut w Walker) fill_as_cast_type_names(types []ast.Type) {
|
||||
for variant in types {
|
||||
idx := u32(variant).str()
|
||||
if idx in w.as_cast_type_names {
|
||||
continue
|
||||
}
|
||||
variant_sym := w.table.sym(variant)
|
||||
w.as_cast_type_names[idx] = variant_sym.name
|
||||
}
|
||||
}
|
||||
|
@ -188,7 +188,7 @@ pub fn (mut am AssetManager) add(asset_type string, file string) bool {
|
||||
} else if asset_type == 'js' {
|
||||
am.js << asset
|
||||
} else {
|
||||
panic('${unknown_asset_type_error} (${asset_type}).')
|
||||
panic(unknown_asset_type_error + ' ' + asset_type + ' .')
|
||||
}
|
||||
return true
|
||||
}
|
||||
@ -205,7 +205,7 @@ fn (am AssetManager) exists(asset_type string, file string) bool {
|
||||
|
||||
fn (am AssetManager) get_assets(asset_type string) []Asset {
|
||||
if asset_type != 'css' && asset_type != 'js' {
|
||||
panic('${unknown_asset_type_error} (${asset_type}).')
|
||||
panic(unknown_asset_type_error + ' ' + asset_type + ' .')
|
||||
}
|
||||
assets := if asset_type == 'css' { am.css } else { am.js }
|
||||
return assets
|
||||
|
@ -1124,6 +1124,6 @@ pub fn string_buffer_to_generic_number[T](result &T, data []u8) {
|
||||
}
|
||||
*result = T(enumeration)
|
||||
} $else {
|
||||
panic('unsupported type ${typeof[T]().name}')
|
||||
panic('unsupported type ' + typeof[T]().name)
|
||||
}
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ pub fn strict_check[T](json_data string) StructCheckResult {
|
||||
field_name := field.name
|
||||
last_key := arrays.find_last(key_struct, fn [field_name] (k KeyStruct) bool {
|
||||
return k.key == field_name
|
||||
}) or { panic('${field.name} not found') }
|
||||
}) or { panic('field not found: ' + field.name) }
|
||||
|
||||
// TODO: get path here from `last_key.key`
|
||||
if last_key.value_type == .map {
|
||||
|
Loading…
x
Reference in New Issue
Block a user