mirror of
https://github.com/vlang/v.git
synced 2025-09-08 06:41:58 -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
|
return
|
||||||
}
|
}
|
||||||
if a.flags.has(.nogrow) {
|
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) }
|
mut cap := if a.cap > 0 { i64(a.cap) } else { i64(2) }
|
||||||
for required > cap {
|
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
|
// limit the capacity, since bigger values, will overflow the 32bit integer used to store it
|
||||||
cap = max_int
|
cap = max_int
|
||||||
} else {
|
} 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)
|
new_size := u64(cap) * u64(a.element_size)
|
||||||
@ -240,7 +242,7 @@ pub fn (a array) repeat(count int) array {
|
|||||||
@[direct_array_access; unsafe]
|
@[direct_array_access; unsafe]
|
||||||
pub fn (a array) repeat_to_depth(count int, depth int) array {
|
pub fn (a array) repeat_to_depth(count int, depth int) array {
|
||||||
if count < 0 {
|
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)
|
mut size := u64(count) * u64(a.len) * u64(a.element_size)
|
||||||
if size == 0 {
|
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) {
|
pub fn (mut a array) insert(i int, val voidptr) {
|
||||||
if i < 0 || i > a.len {
|
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 {
|
if a.len == max_int {
|
||||||
panic('array.insert: a.len reached 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]
|
@[unsafe]
|
||||||
fn (mut a array) insert_many(i int, val voidptr, size int) {
|
fn (mut a array) insert_many(i int, val voidptr, size int) {
|
||||||
if i < 0 || i > a.len {
|
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)
|
new_len := i64(a.len) + i64(size)
|
||||||
if new_len > max_int {
|
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))
|
a.ensure_cap(int(new_len))
|
||||||
elem_size := a.element_size
|
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) {
|
pub fn (mut a array) delete_many(i int, size int) {
|
||||||
if i < 0 || i64(i) + i64(size) > i64(a.len) {
|
if i < 0 || i64(i) + i64(size) > i64(a.len) {
|
||||||
endidx := if size > 1 { '..${i + size}' } else { '' }
|
if size > 1 {
|
||||||
panic('array.delete: index out of range (i == ${i}${endidx}, a.len == ${a.len})')
|
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) {
|
if a.flags.all(.noshrink | .noslices) {
|
||||||
unsafe {
|
unsafe {
|
||||||
@ -465,7 +471,7 @@ fn (a array) get_unsafe(i int) voidptr {
|
|||||||
fn (a array) get(i int) voidptr {
|
fn (a array) get(i int) voidptr {
|
||||||
$if !no_bounds_checking {
|
$if !no_bounds_checking {
|
||||||
if i < 0 || i >= a.len {
|
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 {
|
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
|
end := if _end == max_int { a.len } else { _end } // max_int
|
||||||
$if !no_bounds_checking {
|
$if !no_bounds_checking {
|
||||||
if start > end {
|
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 {
|
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 {
|
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
|
// 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) {
|
fn (mut a array) set(i int, val voidptr) {
|
||||||
$if !no_bounds_checking {
|
$if !no_bounds_checking {
|
||||||
if i < 0 || i >= a.len {
|
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) }
|
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) {
|
pub fn (mut a array) grow_cap(amount int) {
|
||||||
new_cap := i64(amount) + i64(a.cap)
|
new_cap := i64(amount) + i64(a.cap)
|
||||||
if new_cap > max_int {
|
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))
|
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) {
|
pub fn (mut a array) grow_len(amount int) {
|
||||||
new_len := i64(amount) + i64(a.len)
|
new_len := i64(amount) + i64(a.len)
|
||||||
if new_len > max_int {
|
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.ensure_cap(int(new_len))
|
||||||
a.len = 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]
|
@[if !no_bounds_checking ?; inline]
|
||||||
fn panic_on_negative_len(len int) {
|
fn panic_on_negative_len(len int) {
|
||||||
if len < 0 {
|
if len < 0 {
|
||||||
panic('negative .len')
|
panic_n('negative .len:', len)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@[if !no_bounds_checking ?; inline]
|
@[if !no_bounds_checking ?; inline]
|
||||||
fn panic_on_negative_cap(cap int) {
|
fn panic_on_negative_cap(cap int) {
|
||||||
if cap < 0 {
|
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
|
return
|
||||||
}
|
}
|
||||||
if a.flags.has(.nogrow) {
|
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) }
|
mut cap := if a.cap > 0 { i64(a.cap) } else { i64(2) }
|
||||||
for required > cap {
|
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
|
// limit the capacity, since bigger values, will overflow the 32bit integer used to store it
|
||||||
cap = max_int
|
cap = max_int
|
||||||
} else {
|
} 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)
|
new_size := u64(cap) * u64(a.element_size)
|
||||||
@ -136,7 +138,7 @@ fn (mut a array) ensure_cap_noscan(required int) {
|
|||||||
@[unsafe]
|
@[unsafe]
|
||||||
fn (a array) repeat_to_depth_noscan(count int, depth int) array {
|
fn (a array) repeat_to_depth_noscan(count int, depth int) array {
|
||||||
if count < 0 {
|
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)
|
mut size := u64(count) * u64(a.len) * u64(a.element_size)
|
||||||
if size == 0 {
|
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`
|
// insert inserts a value in the array at index `i`
|
||||||
fn (mut a array) insert_noscan(i int, val voidptr) {
|
fn (mut a array) insert_noscan(i int, val voidptr) {
|
||||||
if i < 0 || i > a.len {
|
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 {
|
if a.len == max_int {
|
||||||
panic('array.insert_noscan: a.len reached 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]
|
@[unsafe]
|
||||||
fn (mut a array) insert_many_noscan(i int, val voidptr, size int) {
|
fn (mut a array) insert_many_noscan(i int, val voidptr, size int) {
|
||||||
if i < 0 || i > a.len {
|
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)
|
new_len := i64(a.len) + i64(size)
|
||||||
if new_len > max_int {
|
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)
|
a.ensure_cap_noscan(a.len + size)
|
||||||
elem_size := a.element_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) {
|
fn (mut a array) grow_cap_noscan(amount int) {
|
||||||
new_cap := i64(amount) + i64(a.cap)
|
new_cap := i64(amount) + i64(a.cap)
|
||||||
if new_cap > max_int {
|
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))
|
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) {
|
fn (mut a array) grow_len_noscan(amount int) {
|
||||||
new_len := i64(amount) + i64(a.len)
|
new_len := i64(amount) + i64(a.len)
|
||||||
if new_len > max_int {
|
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.ensure_cap_noscan(int(new_len))
|
||||||
a.len = int(new_len)
|
a.len = int(new_len)
|
||||||
|
@ -10,19 +10,24 @@ pub fn print_backtrace() {
|
|||||||
$if !no_backtrace ? {
|
$if !no_backtrace ? {
|
||||||
$if freestanding {
|
$if freestanding {
|
||||||
println(bare_backtrace())
|
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 {
|
} $else {
|
||||||
$if native {
|
print_backtrace_skipping_top_frames(2)
|
||||||
// TODO: native backtrace solution
|
}
|
||||||
} $else $if tinyc {
|
}
|
||||||
C.tcc_backtrace(c'Backtrace')
|
}
|
||||||
} $else {
|
|
||||||
// NOTE: TCC doesn't have the unwind library
|
fn eprint_space_padding(output string, max_len int) {
|
||||||
$if use_libbacktrace ? {
|
padding_len := max_len - output.len
|
||||||
print_libbacktrace(1)
|
if padding_len > 0 {
|
||||||
} $else {
|
for _ in 0 .. padding_len {
|
||||||
print_backtrace_skipping_top_frames(2)
|
eprint(' ')
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -67,17 +67,14 @@ fn print_backtrace_skipping_top_frames_linux(skipframes int) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
nr_actual_frames := nr_ptrs - skipframes
|
nr_actual_frames := nr_ptrs - skipframes
|
||||||
mut sframes := []string{}
|
|
||||||
//////csymbols := backtrace_symbols(*voidptr(&buffer[skipframes]), nr_actual_frames)
|
//////csymbols := backtrace_symbols(*voidptr(&buffer[skipframes]), nr_actual_frames)
|
||||||
csymbols := C.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 {
|
for i in 0 .. nr_actual_frames {
|
||||||
sframes << unsafe { tos2(&u8(csymbols[i])) }
|
sframe := unsafe { tos2(&u8(csymbols[i])) }
|
||||||
}
|
|
||||||
for sframe in sframes {
|
|
||||||
executable := sframe.all_before('(')
|
executable := sframe.all_before('(')
|
||||||
addr := sframe.all_after('[').all_before(']')
|
addr := sframe.all_after('[').all_before(']')
|
||||||
beforeaddr := sframe.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
|
// taken from os, to avoid depending on the os module inside builtin.v
|
||||||
f := C.popen(&char(cmd.str), c'r')
|
f := C.popen(&char(cmd.str), c'r')
|
||||||
if f == unsafe { nil } {
|
if f == unsafe { nil } {
|
||||||
@ -92,7 +89,7 @@ fn print_backtrace_skipping_top_frames_linux(skipframes int) bool {
|
|||||||
output += tos(bp, vstrlen(bp))
|
output += tos(bp, vstrlen(bp))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
output = output.trim_space() + ':'
|
output = output.trim_chars(' \t\n', .trim_both) + ':'
|
||||||
if C.pclose(f) != 0 {
|
if C.pclose(f) != 0 {
|
||||||
eprintln(sframe)
|
eprintln(sframe)
|
||||||
continue
|
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
|
// 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.
|
// that the common error file:lineno: line format is enforced.
|
||||||
output = output.replace(' (discriminator', ': (d.')
|
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) }
|
unsafe { C.free(csymbols) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -76,6 +76,7 @@ pub fn print_backtrace_skipping_top_frames(skipframes int) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@[direct_array_access]
|
||||||
fn print_backtrace_skipping_top_frames_msvc(skipframes int) bool {
|
fn print_backtrace_skipping_top_frames_msvc(skipframes int) bool {
|
||||||
$if msvc {
|
$if msvc {
|
||||||
mut offset := u64(0)
|
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 {
|
if C.SymGetLineFromAddr64(handle, frame_addr, &offset, &sline64) == 1 {
|
||||||
file_name := unsafe { tos3(sline64.f_file_name) }
|
file_name := unsafe { tos3(sline64.f_file_name) }
|
||||||
lnumber := sline64.f_line_number
|
lnumber := sline64.f_line_number
|
||||||
lineinfo = '${file_name}:${lnumber}'
|
lineinfo = file_name + i64(lnumber).str()
|
||||||
} else {
|
} else {
|
||||||
// addr:
|
// addr:
|
||||||
lineinfo = '?? : address = 0x${(&frame_addr):x}'
|
lineinfo = '?? : address = 0x' + ptr_str(frame_addr)
|
||||||
}
|
}
|
||||||
sfunc := unsafe { tos3(fname) }
|
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 {
|
} else {
|
||||||
// https://docs.microsoft.com/en-us/windows/win32/debug/system-error-codes
|
// https://docs.microsoft.com/en-us/windows/win32/debug/system-error-codes
|
||||||
cerr := int(C.GetLastError())
|
cerr := int(C.GetLastError())
|
||||||
|
eprint('SymFromAddr failure: ')
|
||||||
|
eprint(i64(cerr).str())
|
||||||
if cerr == 87 {
|
if cerr == 87 {
|
||||||
eprintln('SymFromAddr failure: ${cerr} = The parameter is incorrect)')
|
eprintln(' = The parameter is incorrect)')
|
||||||
} else if cerr == 487 {
|
} else if cerr == 487 {
|
||||||
// probably caused because the .pdb isn't in the executable folder
|
// 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 {
|
} 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.
|
// It ends the program with a panic.
|
||||||
@[noreturn]
|
@[noreturn]
|
||||||
pub fn panic_option_not_set(s string) {
|
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
|
// 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.
|
// It ends the program with a panic.
|
||||||
@[noreturn]
|
@[noreturn]
|
||||||
pub fn panic_result_not_set(s string) {
|
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.
|
// 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
|
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`
|
// panic with a C-API error message matching `errnum`
|
||||||
@[noreturn]
|
@[noreturn]
|
||||||
pub fn panic_error_number(basestr string, errnum int) {
|
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 {
|
fn v_fixed_index(i int, len int) int {
|
||||||
$if !no_bounds_checking {
|
$if !no_bounds_checking {
|
||||||
if i < 0 || i >= len {
|
if i < 0 || i >= len {
|
||||||
s := 'fixed array index out of range (index: ${i}, len: ${len})'
|
panic('fixed array index out of range (index: ' + i64(i).str() + ', len: ' +
|
||||||
panic(s)
|
i64(len).str() + ')')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return i
|
return i
|
||||||
|
@ -10,12 +10,6 @@ pub fn isnil(v voidptr) bool {
|
|||||||
return v == 0
|
return v == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
fn on_panic(f fn(int)int) {
|
|
||||||
// TODO
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
struct VCastTypeIndexName {
|
struct VCastTypeIndexName {
|
||||||
tindex int
|
tindex int
|
||||||
tname string
|
tname string
|
||||||
@ -37,7 +31,7 @@ fn __as_cast(obj voidptr, obj_type int, expected_type int) voidptr {
|
|||||||
expected_name = x.tname.clone()
|
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
|
return obj
|
||||||
}
|
}
|
||||||
|
@ -67,6 +67,9 @@ fn builtin_init() {
|
|||||||
$if !no_backtrace ? {
|
$if !no_backtrace ? {
|
||||||
add_unhandled_exception_handler()
|
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
|
// TODO: copypaste from os
|
||||||
@ -109,7 +112,7 @@ fn unhandled_exception_handler(e &ExceptionPointers) int {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
else {
|
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)
|
print_backtrace_skipping_top_frames(5)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,29 +3,18 @@
|
|||||||
// that can be found in the LICENSE file.
|
// that can be found in the LICENSE file.
|
||||||
module builtin
|
module builtin
|
||||||
|
|
||||||
//
|
|
||||||
// ----- value to string functions -----
|
|
||||||
//
|
|
||||||
|
|
||||||
pub struct VContext {
|
pub struct VContext {
|
||||||
allocator int
|
allocator int
|
||||||
}
|
}
|
||||||
|
|
||||||
// type u8 = byte
|
|
||||||
type byte = u8
|
type byte = u8
|
||||||
|
|
||||||
// type i32 = int
|
|
||||||
|
|
||||||
// ptr_str returns the address of `ptr` as a `string`.
|
// ptr_str returns the address of `ptr` as a `string`.
|
||||||
pub fn ptr_str(ptr voidptr) string {
|
pub fn ptr_str(ptr voidptr) string {
|
||||||
buf1 := u64(ptr).hex()
|
buf1 := u64(ptr).hex()
|
||||||
return buf1
|
return buf1
|
||||||
}
|
}
|
||||||
|
|
||||||
// pub fn nil_str(x voidptr) string {
|
|
||||||
// return 'nil'
|
|
||||||
//}
|
|
||||||
|
|
||||||
// str returns string equivalent of x
|
// str returns string equivalent of x
|
||||||
pub fn (x isize) str() string {
|
pub fn (x isize) str() string {
|
||||||
return i64(x).str()
|
return i64(x).str()
|
||||||
@ -118,18 +107,7 @@ fn (nn int) str_l(max int) string {
|
|||||||
}
|
}
|
||||||
diff := max - index
|
diff := max - index
|
||||||
vmemmove(buf, voidptr(buf + index), diff + 1)
|
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(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)
|
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`.
|
// str returns the value of the `u32` as a `string`.
|
||||||
// Example: assert u32(20000).str() == '20000'
|
// Example: assert u32(20000).str() == '20000'
|
||||||
@[direct_array_access; inline]
|
@[direct_array_access; inline]
|
||||||
@ -202,8 +176,6 @@ pub fn (nn u32) str() string {
|
|||||||
diff := max - index
|
diff := max - index
|
||||||
vmemmove(buf, voidptr(buf + index), diff + 1)
|
vmemmove(buf, voidptr(buf + index), diff + 1)
|
||||||
return tos(buf, diff)
|
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
|
diff := max - index
|
||||||
vmemmove(buf, voidptr(buf + index), diff + 1)
|
vmemmove(buf, voidptr(buf + index), diff + 1)
|
||||||
return tos(buf, diff)
|
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
|
diff := max - index
|
||||||
vmemmove(buf, voidptr(buf + index), diff + 1)
|
vmemmove(buf, voidptr(buf + index), diff + 1)
|
||||||
return tos(buf, diff)
|
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'
|
return 'false'
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// ----- value to hex string functions -----
|
|
||||||
//
|
|
||||||
|
|
||||||
// u64_to_hex converts the number `nn` to a (zero padded if necessary) hexadecimal `string`.
|
// u64_to_hex converts the number `nn` to a (zero padded if necessary) hexadecimal `string`.
|
||||||
@[direct_array_access; inline]
|
@[direct_array_access; inline]
|
||||||
fn u64_to_hex(nn u64, len u8) string {
|
fn u64_to_hex(nn u64, len u8) string {
|
||||||
|
@ -6,9 +6,19 @@ module builtin
|
|||||||
|
|
||||||
fn (a any) toString()
|
fn (a any) toString()
|
||||||
|
|
||||||
|
// panic prints an error message, then exits the process with exit code of 1.
|
||||||
@[noreturn]
|
@[noreturn]
|
||||||
pub fn panic(s string) {
|
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)
|
exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,6 +158,7 @@ fn (mut n mapnode) split_child(child_index int, mut y mapnode) {
|
|||||||
n.len++
|
n.len++
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@[direct_array_access]
|
||||||
fn (m SortedMap) get(key string, out voidptr) bool {
|
fn (m SortedMap) get(key string, out voidptr) bool {
|
||||||
mut node := m.root
|
mut node := m.root
|
||||||
for {
|
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
|
end := if _end == max_int { s.len } else { _end } // max_int
|
||||||
$if !no_bounds_checking {
|
$if !no_bounds_checking {
|
||||||
if start > end || start > s.len || end > s.len || start < 0 || end < 0 {
|
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
|
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 {
|
pub fn (s string) substr_with_check(start int, _end int) !string {
|
||||||
end := if _end == max_int { s.len } else { _end } // max_int
|
end := if _end == max_int { s.len } else { _end } // max_int
|
||||||
if start > end || start > s.len || end > s.len || start < 0 || end < 0 {
|
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
|
len := end - start
|
||||||
if len == s.len {
|
if len == s.len {
|
||||||
@ -1962,7 +1964,7 @@ pub fn (s string) str() string {
|
|||||||
fn (s string) at(idx int) u8 {
|
fn (s string) at(idx int) u8 {
|
||||||
$if !no_bounds_checking {
|
$if !no_bounds_checking {
|
||||||
if idx < 0 || idx >= s.len {
|
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] }
|
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,
|
// it is used in vlib/builtin/string.v,
|
||||||
// and also in vlib/v/gen/c/cgen.v
|
// and also in vlib/v/gen/c/cgen.v
|
||||||
pub fn (_rune string) utf32_code() int {
|
pub fn (_rune string) utf32_code() int {
|
||||||
return int(_rune.bytes().utf8_to_utf32() or {
|
if res := _rune.bytes().utf8_to_utf32() {
|
||||||
// error('more than one utf-8 rune found in this string')
|
return int(res)
|
||||||
rune(0)
|
}
|
||||||
})
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// convert array of utf8 bytes to single utf32 value
|
// convert array of utf8 bytes to single utf32 value
|
||||||
// will error if more than 4 bytes are submitted
|
// will error if more than 4 bytes are submitted
|
||||||
|
@[direct_array_access]
|
||||||
pub fn (_bytes []u8) utf8_to_utf32() !rune {
|
pub fn (_bytes []u8) utf8_to_utf32() !rune {
|
||||||
if _bytes.len == 0 {
|
if _bytes.len == 0 {
|
||||||
return 0
|
return 0
|
||||||
|
@ -113,6 +113,6 @@ fn init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ret < 0 {
|
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_target = .file
|
||||||
l.output_file_name = os.join_path(os.real_path(output_file_path), l.output_label)
|
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 {
|
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
|
l.ofile = ofile
|
||||||
}
|
}
|
||||||
@ -160,7 +160,7 @@ pub fn (mut l Log) fatal(s string) {
|
|||||||
l.send_output(s, .fatal)
|
l.send_output(s, .fatal)
|
||||||
l.ofile.close()
|
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.
|
// 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)
|
return int(max_i32)
|
||||||
} $else {
|
} $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)
|
return int(min_i32)
|
||||||
} $else {
|
} $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.
|
// set base to 10 initially and change only if base is explicitly set.
|
||||||
mut b := params.base
|
mut b := params.base
|
||||||
if b < 2 {
|
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 n := num
|
||||||
mut sign := 1
|
mut sign := 1
|
||||||
|
@ -254,7 +254,7 @@ pub fn resolve_ipaddrs(addr string, family AddrFamily, typ SocketType) ![]Addr {
|
|||||||
addresses << new_addr
|
addresses << new_addr
|
||||||
}
|
}
|
||||||
else {
|
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) {
|
for v in other.custom_values(k, exact: true) {
|
||||||
combined.add_custom(k, v) or {
|
combined.add_custom(k, v) or {
|
||||||
// panic because this should never fail
|
// 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 {
|
} $else $if T is i64 {
|
||||||
return i64(swap_bytes_u64(u64(input)))
|
return i64(swap_bytes_u64(u64(input)))
|
||||||
} $else {
|
} $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
|
// On some systems C.ftell can return values in the 64-bit range
|
||||||
// that, when cast to `int`, can result in values below 0.
|
// that, when cast to `int`, can result in values below 0.
|
||||||
if i64(allocate) < fsize {
|
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 {
|
buf := unsafe {
|
||||||
malloc_noscan(allocate)
|
malloc_noscan(allocate)
|
||||||
|
@ -40,7 +40,7 @@ fn test_open_file() {
|
|||||||
file.write_string(hello) or { panic(err) }
|
file.write_string(hello) or { panic(err) }
|
||||||
file.close()
|
file.close()
|
||||||
assert u64(hello.len) == os.file_size(filename)
|
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
|
assert hello == read_hello
|
||||||
os.rm(filename) or { panic(err) }
|
os.rm(filename) or { panic(err) }
|
||||||
}
|
}
|
||||||
@ -80,7 +80,7 @@ fn test_open_file_binary() {
|
|||||||
unsafe { file.write_ptr(bytes.data, bytes.len) }
|
unsafe { file.write_ptr(bytes.data, bytes.len) }
|
||||||
file.close()
|
file.close()
|
||||||
assert u64(hello.len) == os.file_size(filename)
|
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
|
assert bytes == read_hello
|
||||||
os.rm(filename) or { panic(err) }
|
os.rm(filename) or { panic(err) }
|
||||||
}
|
}
|
||||||
@ -160,7 +160,7 @@ fn test_write_and_read_string_to_file() {
|
|||||||
hello := 'hello world!'
|
hello := 'hello world!'
|
||||||
os.write_file(filename, hello) or { panic(err) }
|
os.write_file(filename, hello) or { panic(err) }
|
||||||
assert u64(hello.len) == os.file_size(filename)
|
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
|
assert hello == read_hello
|
||||||
os.rm(filename) or { panic(err) }
|
os.rm(filename) or { panic(err) }
|
||||||
}
|
}
|
||||||
@ -322,7 +322,7 @@ fn test_cp() {
|
|||||||
old_file_name := 'cp_example.txt'
|
old_file_name := 'cp_example.txt'
|
||||||
new_file_name := 'cp_new_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.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) }
|
old_file := os.read_file(old_file_name) or { panic(err) }
|
||||||
new_file := os.read_file(new_file_name) or { panic(err) }
|
new_file := os.read_file(new_file_name) or { panic(err) }
|
||||||
assert old_file == new_file
|
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
|
// _check_redirection_call - should be called just by stdxxx methods
|
||||||
fn (mut p Process) _check_redirection_call(fn_name string) {
|
fn (mut p Process) _check_redirection_call(fn_name string) {
|
||||||
if !p.use_stdio_ctl {
|
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 {
|
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) {
|
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) {
|
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 {
|
pub fn format_int(n i64, radix int) string {
|
||||||
unsafe {
|
unsafe {
|
||||||
if radix < 2 || radix > 36 {
|
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 {
|
if n == 0 {
|
||||||
return '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 {
|
pub fn format_uint(n u64, radix int) string {
|
||||||
unsafe {
|
unsafe {
|
||||||
if radix < 2 || radix > 36 {
|
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 {
|
if n == 0 {
|
||||||
return '0'
|
return '0'
|
||||||
|
@ -551,7 +551,8 @@ pub fn v_sprintf(str string, pt ...voidptr) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if p_index != pt.len {
|
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()
|
return res.str()
|
||||||
@ -560,7 +561,8 @@ pub fn v_sprintf(str string, pt ...voidptr) string {
|
|||||||
@[inline]
|
@[inline]
|
||||||
fn v_sprintf_panic(idx int, len int) {
|
fn v_sprintf_panic(idx int, len int) {
|
||||||
if idx >= len {
|
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 {
|
defer {
|
||||||
util.timing_measure('MARKUSED')
|
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
|
// Functions that must be generated and can't be skipped
|
||||||
mut all_fn_root_names := []string{}
|
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 {
|
if pref_.backend == .native {
|
||||||
// Note: this is temporary, until the native backend supports more features!
|
// Note: this is temporary, until the native backend supports more features!
|
||||||
all_fn_root_names << 'main.main'
|
all_fn_root_names << 'main.main'
|
||||||
} else {
|
} 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 include_panic_deps := false
|
||||||
mut core_fns := [
|
mut core_fns := [
|
||||||
'main.main',
|
'main.main',
|
||||||
@ -41,23 +68,13 @@ pub fn mark_used(mut table ast.Table, mut pref_ pref.Preferences, ast_files []&a
|
|||||||
'println',
|
'println',
|
||||||
'ptr_str',
|
'ptr_str',
|
||||||
]
|
]
|
||||||
|
|
||||||
$if debug_used_features ? {
|
|
||||||
dump(table.used_features)
|
|
||||||
}
|
|
||||||
if ast.float_literal_type.idx() in table.used_features.print_types
|
if ast.float_literal_type.idx() in table.used_features.print_types
|
||||||
|| ast.f64_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 {
|
|| ast.f32_type_idx in table.used_features.print_types {
|
||||||
include_panic_deps = true
|
include_panic_deps = true
|
||||||
}
|
}
|
||||||
$if windows {
|
if 'use_libbacktrace' in pref_.compile_defines {
|
||||||
if 'no_backtrace' !in pref_.compile_defines {
|
core_fns << 'print_libbacktrace'
|
||||||
include_panic_deps = true
|
|
||||||
}
|
|
||||||
} $else {
|
|
||||||
if 'use_libbacktrace' in pref_.compile_defines {
|
|
||||||
core_fns << 'print_libbacktrace'
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if 'callstack' in pref_.compile_defines {
|
if 'callstack' in pref_.compile_defines {
|
||||||
core_fns << ref_array_idx_str + '.push'
|
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 {
|
if pref_.autofree {
|
||||||
core_fns << string_idx_str + '.clone_static'
|
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
|
include_panic_deps = true
|
||||||
core_fns << 'isnil'
|
core_fns << 'isnil'
|
||||||
core_fns << '__new_array'
|
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 {
|
if table.used_features.arr_last {
|
||||||
core_fns << array_idx_str + '.last'
|
core_fns << array_idx_str + '.last'
|
||||||
}
|
}
|
||||||
if table.used_features.arr_delete {
|
|
||||||
include_panic_deps = true
|
|
||||||
}
|
|
||||||
if table.used_features.arr_insert {
|
if table.used_features.arr_insert {
|
||||||
core_fns << ref_array_idx_str + '.insert_many'
|
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 {
|
if table.used_features.interpolation {
|
||||||
include_panic_deps = true
|
include_panic_deps = true
|
||||||
}
|
}
|
||||||
if table.used_features.dump {
|
if table.used_features.dump {
|
||||||
include_panic_deps = true
|
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 << [
|
core_fns << [
|
||||||
'${builderptr_idx}.str',
|
builderptr_idx + '.str',
|
||||||
'${builderptr_idx}.free',
|
builderptr_idx + '.free',
|
||||||
'${builderptr_idx}.write_rune',
|
builderptr_idx + '.write_rune',
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
if table.used_features.arr_init || table.used_features.comptime_for {
|
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'
|
core_fns << 'v.trace_calls.on_call'
|
||||||
}
|
}
|
||||||
if 'C.cJSON_Parse' in all_fns {
|
if 'C.cJSON_Parse' in all_fns {
|
||||||
all_fn_root_names << 'tos5'
|
core_fns << 'tos5'
|
||||||
all_fn_root_names << 'time.unix' // used by json
|
core_fns << 'time.unix' // used by json
|
||||||
table.used_features.used_maps++ // json needs new_map etc
|
table.used_features.used_maps++ // json needs new_map etc
|
||||||
include_panic_deps = true
|
include_panic_deps = true
|
||||||
}
|
}
|
||||||
all_fn_root_names << core_fns
|
|
||||||
if include_panic_deps {
|
if include_panic_deps {
|
||||||
all_fn_root_names << [
|
core_fns << [
|
||||||
'__new_array_with_default',
|
'__new_array_with_default',
|
||||||
'__new_array_with_default_noscan',
|
'__new_array_with_default_noscan',
|
||||||
'str_intp',
|
'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',
|
charptr_idx_str + '.vstring_literal',
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
all_fn_root_names << core_fns
|
||||||
}
|
}
|
||||||
if pref_.is_bare {
|
if pref_.is_bare {
|
||||||
all_fn_root_names << [
|
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]
|
is_noscan_whitelisted := pref_.gc_mode in [.boehm_full_opt, .boehm_incr_opt]
|
||||||
|
|
||||||
has_noscan := all_fn_root_names.any(it.contains('noscan')
|
has_noscan := all_fn_root_names.any(it.contains('noscan')
|
||||||
&& it !in ['vcalloc_noscan', 'malloc_noscan'])
|
&& it !in ['vcalloc_noscan', 'malloc_noscan'])
|
||||||
for k, mut mfn in all_fns {
|
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}')
|
println('k: ${k} | mfn: ${mfn.name}')
|
||||||
}
|
}
|
||||||
if pref_.translated && mfn.attrs.any(it.name == 'c') {
|
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
|
continue
|
||||||
}
|
}
|
||||||
if k.starts_with('testsuite_') || k.contains('.testsuite_') {
|
if k.starts_with('testsuite_') || k.contains('.testsuite_') {
|
||||||
// eprintln('>>> test suite: $k')
|
|
||||||
all_fn_root_names << k
|
all_fn_root_names << k
|
||||||
continue
|
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_ok'
|
||||||
all_fn_root_names << 'main.cb_assertion_failed'
|
all_fn_root_names << 'main.cb_assertion_failed'
|
||||||
if benched_tests_sym := table.find_sym('main.BenchedTests') {
|
if benched_tests_sym := table.find_sym('main.BenchedTests') {
|
||||||
bts_type := benched_tests_sym.methods[0].params[0].typ
|
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_start'
|
||||||
all_fn_root_names << '${bts_type}.testing_step_end'
|
all_fn_root_names << bts_type + '.testing_step_end'
|
||||||
all_fn_root_names << '${bts_type}.end_testing'
|
all_fn_root_names << bts_type + '.end_testing'
|
||||||
all_fn_root_names << 'main.start_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]
|
interface_types := [ptype, ntype]
|
||||||
for method in interface_info.methods {
|
for method in interface_info.methods {
|
||||||
for typ in interface_types {
|
for typ in interface_types {
|
||||||
interface_implementation_method_name := '${int(typ.clear_flags())}.${method.name}'
|
interface_implementation_method_name := int(typ.clear_flags()).str() + '.' +
|
||||||
$if trace_skip_unused_interface_methods ? {
|
method.name
|
||||||
|
if trace_skip_unused_interface_methods {
|
||||||
eprintln('>> isym.name: ${isym.name} | interface_implementation_method_name: ${interface_implementation_method_name}')
|
eprintln('>> isym.name: ${isym.name} | interface_implementation_method_name: ${interface_implementation_method_name}')
|
||||||
}
|
}
|
||||||
all_fn_root_names << interface_implementation_method_name
|
all_fn_root_names << interface_implementation_method_name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for embed_method in table.get_embed_methods(table.sym(itype)) {
|
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}'
|
interface_implementation_method_name :=
|
||||||
$if trace_skip_unused_interface_methods ? {
|
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)')
|
eprintln('>> isym.name: ${isym.name} | interface_implementation_method_name: ${interface_implementation_method_name} (embeded)')
|
||||||
}
|
}
|
||||||
all_fn_root_names << interface_implementation_method_name
|
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 {
|
for orm_type in orm_connection_implementations {
|
||||||
typ := int(orm_type)
|
typ := int(orm_type).str()
|
||||||
all_fn_root_names << '${typ}.select'
|
all_fn_root_names << typ + '.select'
|
||||||
all_fn_root_names << '${typ}.insert'
|
all_fn_root_names << typ + '.insert'
|
||||||
all_fn_root_names << '${typ}.update'
|
all_fn_root_names << typ + '.update'
|
||||||
all_fn_root_names << '${typ}.delete'
|
all_fn_root_names << typ + '.delete'
|
||||||
all_fn_root_names << '${typ}.create'
|
all_fn_root_names << typ + '.create'
|
||||||
all_fn_root_names << '${typ}.drop'
|
all_fn_root_names << typ + '.drop'
|
||||||
all_fn_root_names << '${typ}.last_id'
|
all_fn_root_names << typ + '.last_id'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if 'debug_used_features' in pref_.compile_defines {
|
||||||
|
dump(table.used_features)
|
||||||
|
}
|
||||||
|
|
||||||
mut walker := Walker.new(
|
mut walker := Walker.new(
|
||||||
table: table
|
table: table
|
||||||
files: ast_files
|
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 {
|
for key, _ in walker.used_fns {
|
||||||
println('> used fn key: ${key}')
|
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_fns = walker.used_fns.move()
|
||||||
table.used_features.used_consts = walker.used_consts.move()
|
table.used_features.used_consts = walker.used_consts.move()
|
||||||
table.used_features.used_globals = walker.used_globals.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_fns: ${table.used_features.used_fns.keys()}')
|
||||||
eprintln('>> t.used_consts: ${table.used_features.used_consts.keys()}')
|
eprintln('>> t.used_consts: ${table.used_features.used_consts.keys()}')
|
||||||
eprintln('>> t.used_globals: ${table.used_features.used_globals.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) {
|
fn mark_all_methods_used(mut table ast.Table, mut all_fn_root_names []string, typ ast.Type) {
|
||||||
sym := table.sym(typ)
|
sym := table.sym(typ)
|
||||||
styp := '${int(typ)}'
|
styp := int(typ).str()
|
||||||
for method in sym.methods {
|
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)
|
mark_all_methods_used(mut table, mut all_fn_root_names, typ_vweb_context)
|
||||||
for vgt in table.used_features.used_veb_types {
|
for vgt in table.used_features.used_veb_types {
|
||||||
sym_app := table.sym(vgt)
|
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 {
|
for m in sym_app.methods {
|
||||||
mut skip := true
|
mut skip := true
|
||||||
if m.name == 'before_request' {
|
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
|
continue
|
||||||
}
|
}
|
||||||
// eprintln('vgt: $vgt | pvgt: $pvgt | sym_app.name: $sym_app.name | m.name: $m.name')
|
// 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_fns map[string]ast.FnDecl
|
||||||
all_consts map[string]ast.ConstField
|
all_consts map[string]ast.ConstField
|
||||||
all_globals map[string]ast.GlobalField
|
all_globals map[string]ast.GlobalField
|
||||||
|
//
|
||||||
|
as_cast_type_names map[string]string
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn Walker.new(params Walker) &Walker {
|
pub fn Walker.new(params Walker) &Walker {
|
||||||
@ -367,6 +369,10 @@ fn (mut w Walker) expr(node_ ast.Expr) {
|
|||||||
w.features.used_maps++
|
w.features.used_maps++
|
||||||
} else if sym.kind == .array {
|
} else if sym.kind == .array {
|
||||||
w.features.used_arrays++
|
w.features.used_arrays++
|
||||||
|
} else if sym.kind == .string {
|
||||||
|
if node.index is ast.RangeExpr {
|
||||||
|
w.features.range_index = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast.InfixExpr {
|
ast.InfixExpr {
|
||||||
@ -507,6 +513,7 @@ fn (mut w Walker) expr(node_ ast.Expr) {
|
|||||||
///
|
///
|
||||||
ast.AsCast {
|
ast.AsCast {
|
||||||
w.expr(node.expr)
|
w.expr(node.expr)
|
||||||
|
w.as_cast(node)
|
||||||
}
|
}
|
||||||
ast.AtExpr {}
|
ast.AtExpr {}
|
||||||
ast.BoolLiteral {}
|
ast.BoolLiteral {}
|
||||||
@ -726,3 +733,37 @@ pub fn (mut w Walker) or_block(node ast.OrExpr) {
|
|||||||
w.stmts(node.stmts)
|
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' {
|
} else if asset_type == 'js' {
|
||||||
am.js << asset
|
am.js << asset
|
||||||
} else {
|
} else {
|
||||||
panic('${unknown_asset_type_error} (${asset_type}).')
|
panic(unknown_asset_type_error + ' ' + asset_type + ' .')
|
||||||
}
|
}
|
||||||
return true
|
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 {
|
fn (am AssetManager) get_assets(asset_type string) []Asset {
|
||||||
if asset_type != 'css' && asset_type != 'js' {
|
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 }
|
assets := if asset_type == 'css' { am.css } else { am.js }
|
||||||
return assets
|
return assets
|
||||||
|
@ -1124,6 +1124,6 @@ pub fn string_buffer_to_generic_number[T](result &T, data []u8) {
|
|||||||
}
|
}
|
||||||
*result = T(enumeration)
|
*result = T(enumeration)
|
||||||
} $else {
|
} $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
|
field_name := field.name
|
||||||
last_key := arrays.find_last(key_struct, fn [field_name] (k KeyStruct) bool {
|
last_key := arrays.find_last(key_struct, fn [field_name] (k KeyStruct) bool {
|
||||||
return k.key == field_name
|
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`
|
// TODO: get path here from `last_key.key`
|
||||||
if last_key.value_type == .map {
|
if last_key.value_type == .map {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user