mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
fmt: smarter if condition wrapping (#8201)
This commit is contained in:
parent
9812230847
commit
8b61891348
@ -266,9 +266,8 @@ fn (vd VDoc) gen_html(d doc.Doc) string {
|
||||
names := dc.head.name.split('.')
|
||||
submod_prefix = if names.len > 1 { names[0] } else { dc.head.name }
|
||||
mut href_name := './${dc.head.name}.html'
|
||||
if (cfg.is_vlib && dc.head.name == 'builtin' && !cfg.include_readme) ||
|
||||
dc.head.name == 'README'
|
||||
{
|
||||
if (cfg.is_vlib && dc.head.name == 'builtin' && !cfg.include_readme)
|
||||
|| dc.head.name == 'README' {
|
||||
href_name = './index.html'
|
||||
} else if submod_prefix !in vd.docs.map(it.head.name) {
|
||||
href_name = '#'
|
||||
@ -303,19 +302,19 @@ fn (vd VDoc) gen_html(d doc.Doc) string {
|
||||
header_name).replace('{{ version }}', version).replace('{{ light_icon }}', vd.assets['light_icon']).replace('{{ dark_icon }}',
|
||||
vd.assets['dark_icon']).replace('{{ menu_icon }}', vd.assets['menu_icon']).replace('{{ head_assets }}',
|
||||
if cfg.inline_assets {
|
||||
'\n${tabs[0]}<style>' + vd.assets['doc_css'] + '</style>\n${tabs[0]}<style>' + vd.assets['normalize_css'] +
|
||||
'</style>\n${tabs[0]}<script>' + vd.assets['dark_mode_js'] + '</script>'
|
||||
'\n${tabs[0]}<style>' + vd.assets['doc_css'] + '</style>\n${tabs[0]}<style>' +
|
||||
vd.assets['normalize_css'] + '</style>\n${tabs[0]}<script>' +
|
||||
vd.assets['dark_mode_js'] + '</script>'
|
||||
} else {
|
||||
'\n${tabs[0]}<link rel="stylesheet" href="' + vd.assets['doc_css'] + '" />\n${tabs[0]}<link rel="stylesheet" href="' +
|
||||
vd.assets['normalize_css'] + '" />\n${tabs[0]}<script src="' + vd.assets['dark_mode_js'] +
|
||||
'"></script>'
|
||||
'\n${tabs[0]}<link rel="stylesheet" href="' + vd.assets['doc_css'] +
|
||||
'" />\n${tabs[0]}<link rel="stylesheet" href="' + vd.assets['normalize_css'] +
|
||||
'" />\n${tabs[0]}<script src="' + vd.assets['dark_mode_js'] + '"></script>'
|
||||
}).replace('{{ toc_links }}', if cfg.is_multi || vd.docs.len > 1 {
|
||||
modules_toc_str
|
||||
} else {
|
||||
symbols_toc_str
|
||||
}).replace('{{ contents }}', contents.str()).replace('{{ right_content }}', if cfg.is_multi &&
|
||||
vd.docs.len > 1 && d.head.name != 'README'
|
||||
{
|
||||
}).replace('{{ contents }}', contents.str()).replace('{{ right_content }}', if cfg.is_multi
|
||||
&& vd.docs.len > 1&& d.head.name != 'README' {
|
||||
'<div class="doc-toc"><ul>' + symbols_toc_str + '</ul></div>'
|
||||
} else {
|
||||
''
|
||||
@ -405,9 +404,8 @@ fn html_highlight(code string, tb &table.Table) string {
|
||||
else {
|
||||
if token.is_key(tok.lit) || token.is_decl(tok.kind) {
|
||||
tok_typ = .keyword
|
||||
} else if tok.kind == .decl_assign || tok.kind.is_assign() || tok.is_unary() ||
|
||||
tok.kind.is_relational() || tok.kind.is_infix()
|
||||
{
|
||||
} else if tok.kind == .decl_assign || tok.kind.is_assign() || tok.is_unary()
|
||||
|| tok.kind.is_relational()|| tok.kind.is_infix() {
|
||||
tok_typ = .operator
|
||||
}
|
||||
}
|
||||
|
@ -467,8 +467,8 @@ fn parse_arguments(args []string) Config {
|
||||
} $else {
|
||||
cfg.input_path = cfg.input_path.replace('\\', os.path_separator)
|
||||
}
|
||||
is_path := cfg.input_path.ends_with('.v') || cfg.input_path.split(os.path_separator).len >
|
||||
1 || cfg.input_path == '.'
|
||||
is_path := cfg.input_path.ends_with('.v') || cfg.input_path.split(os.path_separator).len > 1
|
||||
|| cfg.input_path == '.'
|
||||
if cfg.input_path.trim_right('/') == 'vlib' {
|
||||
cfg.is_vlib = true
|
||||
cfg.is_multi = true
|
||||
|
@ -159,9 +159,8 @@ fn (mut vt Vet) vet_file(path string, is_regression_test bool) {
|
||||
// vet_line vets the contents of `line` from `vet.file`.
|
||||
fn (mut vet Vet) vet_line(lines []string, line string, lnumber int) {
|
||||
// Vet public functions
|
||||
if line.starts_with('pub fn') ||
|
||||
(line.starts_with('fn ') && !(line.starts_with('fn C.') || line.starts_with('fn main')))
|
||||
{
|
||||
if line.starts_with('pub fn') || (line.starts_with('fn ') && !(line.starts_with('fn C.')
|
||||
|| line.starts_with('fn main'))) {
|
||||
// Scan function declarations for missing documentation
|
||||
is_pub_fn := line.starts_with('pub fn')
|
||||
if lnumber > 0 {
|
||||
|
@ -2097,9 +2097,7 @@ fn (r Repo) find_user_by_id(id int) ?User {
|
||||
|
||||
fn main() {
|
||||
repo := Repo{
|
||||
users: [User{1, 'Andrew'}, User{2, 'Bob'},
|
||||
User{10, 'Charles'},
|
||||
]
|
||||
users: [User{1, 'Andrew'}, User{2, 'Bob'}, User{10, 'Charles'}]
|
||||
}
|
||||
user := repo.find_user_by_id(10) or { // Option types must be handled by `or` blocks
|
||||
return
|
||||
|
@ -199,8 +199,7 @@ pub fn (b &Benchmark) total_message(msg string) string {
|
||||
if b.nskip > 0 {
|
||||
tmsg += term.colorize(term.bold, term.colorize(term.yellow, '$b.nskip skipped')) + ', '
|
||||
}
|
||||
tmsg += '$b.ntotal total. ${term.colorize(term.bold, 'Runtime:')} ${b.bench_timer.elapsed().microseconds() /
|
||||
1000} ms.\n'
|
||||
tmsg += '$b.ntotal total. ${term.colorize(term.bold, 'Runtime:')} ${b.bench_timer.elapsed().microseconds() / 1000} ms.\n'
|
||||
tmsg += term.colorize(term.gray, msg)
|
||||
return tmsg
|
||||
}
|
||||
|
@ -353,8 +353,8 @@ pub fn (input BitField) slice(_start int, _end int) BitField {
|
||||
if start_offset != 0 {
|
||||
for i in 0 .. output_slots - 1 {
|
||||
output.field[i] = u32(input.field[start_slot + i] >> u32(start_offset))
|
||||
output.field[i] = output.field[i] | u32(input.field[start_slot + i + 1] << u32(slot_size -
|
||||
start_offset))
|
||||
output.field[i] = output.field[i] | u32(input.field[start_slot + i +
|
||||
1] << u32(slot_size - start_offset))
|
||||
}
|
||||
} else {
|
||||
for i in 0 .. output_slots - 1 {
|
||||
@ -458,8 +458,7 @@ fn (mut instance BitField) clear_tail() {
|
||||
// create a mask for the tail
|
||||
mask := u32((1 << tail) - 1)
|
||||
// clear the extra bits
|
||||
instance.field[zbitnslots(instance.size) - 1] = instance.field[zbitnslots(instance.size) -
|
||||
1] & mask
|
||||
instance.field[zbitnslots(instance.size) - 1] = instance.field[zbitnslots(instance.size) - 1] & mask
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -447,8 +447,8 @@ pub fn (mut a array) reverse_in_place() {
|
||||
mut tmp_value := malloc(a.element_size)
|
||||
for i in 0 .. a.len / 2 {
|
||||
C.memcpy(tmp_value, byteptr(a.data) + i * a.element_size, a.element_size)
|
||||
C.memcpy(byteptr(a.data) + i * a.element_size, byteptr(a.data) + (a.len - 1 - i) *
|
||||
a.element_size, a.element_size)
|
||||
C.memcpy(byteptr(a.data) + i * a.element_size, byteptr(a.data) +
|
||||
(a.len - 1 - i) * a.element_size, a.element_size)
|
||||
C.memcpy(byteptr(a.data) + (a.len - 1 - i) * a.element_size, tmp_value, a.element_size)
|
||||
}
|
||||
free(tmp_value)
|
||||
|
@ -383,25 +383,20 @@ fn test_mutli_array_clone() {
|
||||
assert b2_1 == [['1', '0', '3'], ['4', '5', '6']]
|
||||
assert b2_2 == [['1', '2', '3'], ['0', '5', '6']]
|
||||
// 3d array_int
|
||||
mut a3_1 := [[[1, 1], [2, 2], [3, 3]],
|
||||
[[4, 4], [5, 5], [6, 6]],
|
||||
]
|
||||
mut a3_1 := [[[1, 1], [2, 2], [3, 3]], [[4, 4], [5, 5], [6, 6]]]
|
||||
mut a3_2 := a3_1.clone()
|
||||
a3_1[0][0][1] = 0
|
||||
a3_2[0][1][0] = 0
|
||||
assert a3_1 == [[[1, 0], [2, 2], [3, 3]], [[4, 4], [5, 5], [6, 6]]]
|
||||
assert a3_2 == [[[1, 1], [0, 2], [3, 3]], [[4, 4], [5, 5], [6, 6]]]
|
||||
// 3d array_string
|
||||
mut b3_1 := [[['1', '1'], ['2', '2'],
|
||||
['3', '3'],
|
||||
], [['4', '4'], ['5', '5'], ['6', '6']]]
|
||||
mut b3_1 := [[['1', '1'], ['2', '2'], ['3', '3']], [['4', '4'],
|
||||
['5', '5'], ['6', '6']]]
|
||||
mut b3_2 := b3_1.clone()
|
||||
b3_1[0][0][1] = '0'
|
||||
b3_2[0][1][0] = '0'
|
||||
assert b3_1 ==
|
||||
[[['1', '0'], ['2', '2'], ['3', '3']], [['4', '4'], ['5', '5'], ['6', '6']]]
|
||||
assert b3_2 ==
|
||||
[[['1', '1'], ['0', '2'], ['3', '3']], [['4', '4'], ['5', '5'], ['6', '6']]]
|
||||
assert b3_1 == [[['1', '0'], ['2', '2'], ['3', '3']], [['4', '4'], ['5', '5'], ['6', '6']]]
|
||||
assert b3_2 == [[['1', '1'], ['0', '2'], ['3', '3']], [['4', '4'], ['5', '5'], ['6', '6']]]
|
||||
}
|
||||
|
||||
fn test_doubling() {
|
||||
@ -718,8 +713,7 @@ fn test_sort() {
|
||||
assert nums[3] == 67
|
||||
assert nums[4] == 108
|
||||
//
|
||||
mut users := [User{22, 'Peter'},
|
||||
User{20, 'Bob'}, User{25, 'Alice'}]
|
||||
mut users := [User{22, 'Peter'}, User{20, 'Bob'}, User{25, 'Alice'}]
|
||||
users.sort(a.age < b.age)
|
||||
assert (users[0].age == 20)
|
||||
assert (users[1].age == 22)
|
||||
|
@ -221,13 +221,13 @@ fn (mut flag Flag) parse(args []string, with_abbrev bool) ?[]string {
|
||||
// matches returns `true` if first arg in `args` matches this flag.
|
||||
fn (mut flag Flag) matches(args []string, with_abbrev bool) bool {
|
||||
if with_abbrev {
|
||||
return (flag.name != '' && args[0] == '--$flag.name') ||
|
||||
(flag.name != '' && args[0].starts_with('--$flag.name=')) ||
|
||||
(flag.abbrev != '' && args[0] == '-$flag.abbrev') ||
|
||||
(flag.abbrev != '' && args[0].starts_with('-$flag.abbrev='))
|
||||
return (flag.name != '' && args[0] == '--$flag.name')
|
||||
|| (flag.name != '' && args[0].starts_with('--$flag.name='))
|
||||
|| (flag.abbrev != '' && args[0] == '-$flag.abbrev')
|
||||
|| (flag.abbrev != '' && args[0].starts_with('-$flag.abbrev='))
|
||||
} else {
|
||||
return (flag.name != '' && args[0] == '-$flag.name') ||
|
||||
(flag.name != '' && args[0].starts_with('-$flag.name='))
|
||||
return (flag.name != '' && args[0] == '-$flag.name')
|
||||
|| (flag.name != '' && args[0].starts_with('-$flag.name='))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -111,8 +111,8 @@ fn (cmd Command) help_message() string {
|
||||
}
|
||||
base_indent := ' '.repeat(base_indent_len)
|
||||
description_indent := ' '.repeat(name_len - flag_name.len)
|
||||
help += '$base_indent$flag_name$description_indent' + pretty_description(flag.description +
|
||||
required, base_indent_len + name_len) + '\n'
|
||||
help += '$base_indent$flag_name$description_indent' +
|
||||
pretty_description(flag.description + required, base_indent_len + name_len) + '\n'
|
||||
}
|
||||
}
|
||||
if cmd.commands.len > 0 {
|
||||
@ -120,8 +120,8 @@ fn (cmd Command) help_message() string {
|
||||
for command in cmd.commands {
|
||||
base_indent := ' '.repeat(base_indent_len)
|
||||
description_indent := ' '.repeat(name_len - command.name.len)
|
||||
help += '$base_indent$command.name$description_indent' + pretty_description(command.description, name_len) +
|
||||
'\n'
|
||||
help += '$base_indent$command.name$description_indent' +
|
||||
pretty_description(command.description, name_len) + '\n'
|
||||
}
|
||||
}
|
||||
return help
|
||||
|
@ -184,8 +184,8 @@ pub fn (ctx &Context) text_width(s string) int {
|
||||
mut buf := [4]f32{}
|
||||
C.fonsTextBounds(ctx.ft.fons, 0, 0, s.str, 0, buf)
|
||||
if s.ends_with(' ') {
|
||||
return int((buf[2] - buf[0]) /
|
||||
ctx.scale) + ctx.text_width('i') // TODO fix this in fontstash?
|
||||
return int((buf[2] - buf[0]) / ctx.scale) +
|
||||
ctx.text_width('i') // TODO fix this in fontstash?
|
||||
}
|
||||
return int((buf[2] - buf[0]) / ctx.scale)
|
||||
}
|
||||
|
@ -117,14 +117,12 @@ fn test_str() {
|
||||
assert big.from_u64(4398046511104).str() == '4398046511104'
|
||||
assert big.from_int(4294967295).str() == '18446744073709551615'
|
||||
assert big.from_int(-1).str() == '18446744073709551615'
|
||||
assert big.from_hex_string('e'.repeat(80)).str() ==
|
||||
'1993587900192849410235353592424915306962524220866209251950572167300738410728597846688097947807470'
|
||||
assert big.from_hex_string('e'.repeat(80)).str() == '1993587900192849410235353592424915306962524220866209251950572167300738410728597846688097947807470'
|
||||
}
|
||||
|
||||
fn test_factorial() {
|
||||
f5 := big.factorial(big.from_u64(5))
|
||||
assert f5.hexstr() == '78'
|
||||
f100 := big.factorial(big.from_u64(100))
|
||||
assert f100.hexstr() ==
|
||||
'1b30964ec395dc24069528d54bbda40d16e966ef9a70eb21b5b2943a321cdf10391745570cca9420c6ecb3b72ed2ee8b02ea2735c61a000000000000000000000000'
|
||||
assert f100.hexstr() == '1b30964ec395dc24069528d54bbda40d16e966ef9a70eb21b5b2943a321cdf10391745570cca9420c6ecb3b72ed2ee8b02ea2735c61a000000000000000000000000'
|
||||
}
|
||||
|
@ -107,8 +107,8 @@ pub fn ones_count_16(x u16) int {
|
||||
|
||||
// ones_count_32 returns the number of one bits ("population count") in x.
|
||||
pub fn ones_count_32(x u32) int {
|
||||
return int(pop_8_tab[x >> 24] + pop_8_tab[x >> 16 & 0xff] + pop_8_tab[x >> 8 & 0xff] + pop_8_tab[x &
|
||||
u32(0xff)])
|
||||
return int(pop_8_tab[x >> 24] + pop_8_tab[x >> 16 & 0xff] + pop_8_tab[x >> 8 & 0xff] +
|
||||
pop_8_tab[x & u32(0xff)])
|
||||
}
|
||||
|
||||
// ones_count_64 returns the number of one bits ("population count") in x.
|
||||
|
@ -396,7 +396,7 @@ pub fn is_file(path string) bool {
|
||||
// is_abs_path returns `true` if `path` is absolute.
|
||||
pub fn is_abs_path(path string) bool {
|
||||
$if windows {
|
||||
return path[0] == `/` || // incase we're in MingGW bash
|
||||
return path[0] == `/` || // incase we're in MingGW bash
|
||||
(path[0].is_letter() && path[1] == `:`)
|
||||
}
|
||||
return path[0] == `/`
|
||||
|
@ -771,9 +771,8 @@ fn normalize_drive_letter(path string) string {
|
||||
$if !windows {
|
||||
return path
|
||||
}
|
||||
if path.len > 2 &&
|
||||
path[0] >= `a` && path[0] <= `z` && path[1] == `:` && path[2] == path_separator[0]
|
||||
{
|
||||
if path.len > 2 && path[0] >= `a` && path[0] <= `z` && path[1] == `:`
|
||||
&& path[2] == path_separator[0] {
|
||||
unsafe {
|
||||
x := &path.str[0]
|
||||
(*x) = *x - 32
|
||||
|
@ -92,10 +92,8 @@ pub fn ls(path string) ?[]string {
|
||||
}
|
||||
bptr := byteptr(ent.d_name)
|
||||
unsafe {
|
||||
if bptr[0] == 0 ||
|
||||
(bptr[0] == `.` && bptr[1] == 0) ||
|
||||
(bptr[0] == `.` && bptr[1] == `.` && bptr[2] == 0)
|
||||
{
|
||||
if bptr[0] == 0 || (bptr[0] == `.` && bptr[1] == 0)
|
||||
|| (bptr[0] == `.` && bptr[1] == `.` && bptr[2] == 0) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
@ -135,7 +135,8 @@ pub fn mkdir(path string) ?bool {
|
||||
}
|
||||
apath := real_path(path)
|
||||
if !C.CreateDirectory(apath.to_wide(), 0) {
|
||||
return error('mkdir failed for "$apath", because CreateDirectory returned ' + get_error_msg(int(C.GetLastError())))
|
||||
return error('mkdir failed for "$apath", because CreateDirectory returned ' +
|
||||
get_error_msg(int(C.GetLastError())))
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
@ -8,8 +8,8 @@ fn version_satisfies(ver Version, input string) bool {
|
||||
}
|
||||
|
||||
fn compare_eq(v1 Version, v2 Version) bool {
|
||||
return v1.major == v2.major &&
|
||||
v1.minor == v2.minor && v1.patch == v2.patch && v1.prerelease == v2.prerelease
|
||||
return v1.major == v2.major && v1.minor == v2.minor && v1.patch == v2.patch
|
||||
&& v1.prerelease == v2.prerelease
|
||||
}
|
||||
|
||||
fn compare_gt(v1 Version, v2 Version) bool {
|
||||
|
@ -43,8 +43,9 @@ fn (ver RawVersion) is_valid() bool {
|
||||
if ver.raw_ints.len != 3 {
|
||||
return false
|
||||
}
|
||||
return is_valid_number(ver.raw_ints[ver_major]) && is_valid_number(ver.raw_ints[ver_minor]) &&
|
||||
is_valid_number(ver.raw_ints[ver_patch]) && is_valid_string(ver.prerelease) && is_valid_string(ver.metadata)
|
||||
return is_valid_number(ver.raw_ints[ver_major]) && is_valid_number(ver.raw_ints[ver_minor])
|
||||
&& is_valid_number(ver.raw_ints[ver_patch]) && is_valid_string(ver.prerelease)
|
||||
&& is_valid_string(ver.metadata)
|
||||
}
|
||||
|
||||
fn (ver RawVersion) is_missing(typ int) bool {
|
||||
|
@ -139,8 +139,8 @@ fn parse_xrange(input string) ?Version {
|
||||
}
|
||||
|
||||
fn can_expand(input string) bool {
|
||||
return input[0] == `~` ||
|
||||
input[0] == `^` || input.contains(hyphen_range_sep) || input.index_any(x_range_symbols) > -1
|
||||
return input[0] == `~` || input[0] == `^` || input.contains(hyphen_range_sep)
|
||||
|| input.index_any(x_range_symbols) > -1
|
||||
}
|
||||
|
||||
fn expand_comparator_set(input string) ?ComparatorSet {
|
||||
|
@ -71,8 +71,11 @@ pub fn colorize(cfn fn (string) string, s string) string {
|
||||
// If an empty string is passed in, print enough spaces to make a new line
|
||||
pub fn h_divider(divider string) string {
|
||||
cols, _ := get_terminal_size()
|
||||
result := if divider.len > 0 { divider.repeat(1 + (cols / divider.len)) } else { ' '.repeat(1 +
|
||||
cols) }
|
||||
result := if divider.len > 0 {
|
||||
divider.repeat(1 + (cols / divider.len))
|
||||
} else {
|
||||
' '.repeat(1 + cols)
|
||||
}
|
||||
return result[0..cols]
|
||||
}
|
||||
|
||||
@ -85,12 +88,18 @@ pub fn header(text string, divider string) string {
|
||||
}
|
||||
xcols, _ := get_terminal_size()
|
||||
cols := imax(1, xcols)
|
||||
tlimit := imax(1, if cols > text.len + 2 + 2 * divider.len { text.len } else { cols - 3 -
|
||||
2 * divider.len })
|
||||
tlimit := imax(1, if cols > text.len + 2 + 2 * divider.len {
|
||||
text.len
|
||||
} else {
|
||||
cols - 3 - 2 * divider.len
|
||||
})
|
||||
tlimit_alligned := if (tlimit % 2) != (cols % 2) { tlimit + 1 } else { tlimit }
|
||||
tstart := imax(0, (cols - tlimit_alligned) / 2)
|
||||
ln := if divider.len > 0 { divider.repeat(1 + cols / divider.len)[0..cols] } else { ' '.repeat(1 +
|
||||
cols) }
|
||||
ln := if divider.len > 0 {
|
||||
divider.repeat(1 + cols / divider.len)[0..cols]
|
||||
} else {
|
||||
' '.repeat(1 + cols)
|
||||
}
|
||||
if ln.len == 1 {
|
||||
return ln + ' ' + text[0..tlimit] + ' ' + ln
|
||||
}
|
||||
|
@ -6,8 +6,8 @@ fn test_parse() {
|
||||
assert false
|
||||
return
|
||||
}
|
||||
assert t.year == 2018 &&
|
||||
t.month == 1 && t.day == 27 && t.hour == 12 && t.minute == 48 && t.second == 34
|
||||
assert t.year == 2018 && t.month == 1 && t.day == 27 && t.hour == 12 && t.minute == 48
|
||||
&& t.second == 34
|
||||
assert t.unix == 1517057314
|
||||
}
|
||||
|
||||
@ -26,16 +26,16 @@ fn test_parse_rfc2822() {
|
||||
assert false
|
||||
return
|
||||
}
|
||||
assert t1.year == 2019 &&
|
||||
t1.month == 12 && t1.day == 12 && t1.hour == 6 && t1.minute == 7 && t1.second == 45
|
||||
assert t1.year == 2019 && t1.month == 12 && t1.day == 12 && t1.hour == 6 && t1.minute == 7
|
||||
&& t1.second == 45
|
||||
assert t1.unix == 1576130865
|
||||
s2 := 'Thu 12 Dec 2019 06:07:45 +0800'
|
||||
t2 := time.parse_rfc2822(s2) or {
|
||||
assert false
|
||||
return
|
||||
}
|
||||
assert t2.year == 2019 &&
|
||||
t2.month == 12 && t2.day == 12 && t2.hour == 6 && t2.minute == 7 && t2.second == 45
|
||||
assert t2.year == 2019 && t2.month == 12 && t2.day == 12 && t2.hour == 6 && t2.minute == 7
|
||||
&& t2.second == 45
|
||||
assert t2.unix == 1576130865
|
||||
}
|
||||
|
||||
|
@ -87,14 +87,12 @@ fn test_format_ss() {
|
||||
}
|
||||
|
||||
fn test_format_ss_milli() {
|
||||
assert '11.07.1980 21:23:42.123' ==
|
||||
time_to_test.get_fmt_str(.dot, .hhmmss24_milli, .ddmmyyyy)
|
||||
assert '11.07.1980 21:23:42.123' == time_to_test.get_fmt_str(.dot, .hhmmss24_milli, .ddmmyyyy)
|
||||
assert '1980-07-11 21:23:42.123' == time_to_test.format_ss_milli()
|
||||
}
|
||||
|
||||
fn test_format_ss_micro() {
|
||||
assert '11.07.1980 21:23:42.123456' ==
|
||||
time_to_test.get_fmt_str(.dot, .hhmmss24_micro, .ddmmyyyy)
|
||||
assert '11.07.1980 21:23:42.123456' == time_to_test.get_fmt_str(.dot, .hhmmss24_micro, .ddmmyyyy)
|
||||
assert '1980-07-11 21:23:42.123456' == time_to_test.format_ss_micro()
|
||||
}
|
||||
|
||||
|
@ -133,8 +133,9 @@ pub fn (node &FnDecl) stringify(t &table.Table, cur_mod string, m2a map[string]s
|
||||
// must be enclosed in braces.
|
||||
pub fn (lit &StringInterLiteral) get_fspec_braces(i int) (string, bool) {
|
||||
mut res := []string{}
|
||||
needs_fspec := lit.need_fmts[i] || lit.pluss[i] ||
|
||||
(lit.fills[i] && lit.fwidths[i] >= 0) || lit.fwidths[i] != 0 || lit.precisions[i] != 987698
|
||||
needs_fspec := lit.need_fmts[i] || lit.pluss[i]
|
||||
|| (lit.fills[i] && lit.fwidths[i] >= 0) || lit.fwidths[i] != 0
|
||||
|| lit.precisions[i] != 987698
|
||||
mut needs_braces := needs_fspec
|
||||
if !needs_braces {
|
||||
if i + 1 < lit.vals.len && lit.vals[i + 1].len > 0 {
|
||||
|
@ -239,9 +239,8 @@ pub fn (b &Builder) find_module_path(mod string, fpath string) ?string {
|
||||
vmod_file_location := mcache.get_by_file(fpath)
|
||||
mod_path := module_path(mod)
|
||||
mut module_lookup_paths := []string{}
|
||||
if vmod_file_location.vmod_file.len != 0 &&
|
||||
vmod_file_location.vmod_folder !in b.module_search_paths
|
||||
{
|
||||
if vmod_file_location.vmod_file.len != 0
|
||||
&& vmod_file_location.vmod_folder !in b.module_search_paths {
|
||||
module_lookup_paths << vmod_file_location.vmod_folder
|
||||
}
|
||||
module_lookup_paths << b.module_search_paths
|
||||
|
@ -211,9 +211,8 @@ fn (mut v Builder) setup_ccompiler_options(ccompiler string) {
|
||||
// deliberately guessing only for -prod builds for performance reasons
|
||||
if ccversion := os.exec('cc --version') {
|
||||
if ccversion.exit_code == 0 {
|
||||
if ccversion.output.contains('This is free software;') &&
|
||||
ccversion.output.contains('Free Software Foundation, Inc.')
|
||||
{
|
||||
if ccversion.output.contains('This is free software;')
|
||||
&& ccversion.output.contains('Free Software Foundation, Inc.') {
|
||||
ccoptions.guessed_compiler = 'gcc'
|
||||
}
|
||||
if ccversion.output.contains('clang version ') {
|
||||
@ -353,9 +352,8 @@ fn (mut v Builder) setup_ccompiler_options(ccompiler string) {
|
||||
}
|
||||
// Without these libs compilation will fail on Linux
|
||||
// || os.user_os() == 'linux'
|
||||
if !v.pref.is_bare && v.pref.build_mode != .build_module && v.pref.os in
|
||||
[.linux, .freebsd, .openbsd, .netbsd, .dragonfly, .solaris, .haiku]
|
||||
{
|
||||
if !v.pref.is_bare && v.pref.build_mode != .build_module
|
||||
&& v.pref.os in [.linux, .freebsd, .openbsd, .netbsd, .dragonfly, .solaris, .haiku] {
|
||||
ccoptions.linker_flags << '-lm'
|
||||
ccoptions.linker_flags << '-lpthread'
|
||||
// -ldl is a Linux only thing. BSDs have it in libc.
|
||||
@ -402,9 +400,8 @@ fn (ccoptions CcompilerOptions) thirdparty_object_args(middle []string) []string
|
||||
}
|
||||
|
||||
fn (mut v Builder) setup_output_name() {
|
||||
if !v.pref.is_shared && v.pref.build_mode != .build_module && os.user_os() == 'windows' &&
|
||||
!v.pref.out_name.ends_with('.exe')
|
||||
{
|
||||
if !v.pref.is_shared && v.pref.build_mode != .build_module && os.user_os() == 'windows'
|
||||
&& !v.pref.out_name.ends_with('.exe') {
|
||||
v.pref.out_name += '.exe'
|
||||
}
|
||||
// Output executable name
|
||||
@ -658,8 +655,10 @@ fn (mut v Builder) cc() {
|
||||
if res.exit_code == 127 {
|
||||
verror('C compiler error, while attempting to run: \n' +
|
||||
'-----------------------------------------------------------\n' + '$cmd\n' +
|
||||
'-----------------------------------------------------------\n' + 'Probably your C compiler is missing. \n' +
|
||||
'Please reinstall it, or make it available in your PATH.\n\n' + missing_compiler_info())
|
||||
'-----------------------------------------------------------\n' +
|
||||
'Probably your C compiler is missing. \n' +
|
||||
'Please reinstall it, or make it available in your PATH.\n\n' +
|
||||
missing_compiler_info())
|
||||
}
|
||||
}
|
||||
if !v.pref.show_c_output {
|
||||
@ -716,8 +715,7 @@ fn (mut v Builder) cc() {
|
||||
println('install upx with `brew install upx`')
|
||||
}
|
||||
$if linux {
|
||||
println('install upx\n' +
|
||||
'for example, on Debian/Ubuntu run `sudo apt install upx`')
|
||||
println('install upx\n' + 'for example, on Debian/Ubuntu run `sudo apt install upx`')
|
||||
}
|
||||
$if windows {
|
||||
// :)
|
||||
|
@ -14,15 +14,13 @@ fn (mut v Builder) get_os_cflags() []cflag.CFlag {
|
||||
if flag.value.ends_with('.o') {
|
||||
flag.cached = v.pref.cache_manager.postfix_with_key2cpath('.o', os.real_path(flag.value))
|
||||
}
|
||||
if flag.os == '' ||
|
||||
(flag.os == 'linux' && v.pref.os == .linux) ||
|
||||
(flag.os == 'macos' && v.pref.os == .macos) ||
|
||||
(flag.os == 'darwin' && v.pref.os == .macos) ||
|
||||
(flag.os == 'freebsd' && v.pref.os == .freebsd) ||
|
||||
(flag.os == 'windows' && v.pref.os == .windows) ||
|
||||
(flag.os == 'mingw' && v.pref.os == .windows && v.pref.ccompiler != 'msvc') ||
|
||||
(flag.os == 'solaris' && v.pref.os == .solaris)
|
||||
{
|
||||
if flag.os == '' || (flag.os == 'linux' && v.pref.os == .linux)
|
||||
|| (flag.os == 'macos' && v.pref.os == .macos)
|
||||
|| (flag.os == 'darwin' && v.pref.os == .macos)
|
||||
|| (flag.os == 'freebsd' && v.pref.os == .freebsd)
|
||||
|| (flag.os == 'windows' && v.pref.os == .windows)
|
||||
|| (flag.os == 'mingw' && v.pref.os == .windows && v.pref.ccompiler != 'msvc')
|
||||
|| (flag.os == 'solaris' && v.pref.os == .solaris) {
|
||||
flags << flag
|
||||
}
|
||||
if flag.os in ctimedefines {
|
||||
|
@ -15,7 +15,8 @@ fn (mut b Builder) get_vtmp_filename(base_file_name string, postfix string) stri
|
||||
if !b.pref.reuse_tmpc {
|
||||
uniq = '.$rand.u64()'
|
||||
}
|
||||
return os.real_path(os.join_path(vtmp, os.file_name(os.real_path(base_file_name)) + '$uniq$postfix'))
|
||||
return os.real_path(os.join_path(vtmp, os.file_name(os.real_path(base_file_name)) +
|
||||
'$uniq$postfix'))
|
||||
}
|
||||
|
||||
pub fn compile(command string, pref &pref.Preferences) {
|
||||
|
@ -81,8 +81,8 @@ fn find_windows_kit_root(host_arch string) ?WindowsKit {
|
||||
$if windows {
|
||||
root_key := RegKey(0)
|
||||
path := 'SOFTWARE\\Microsoft\\Windows Kits\\Installed Roots'
|
||||
rc := C.RegOpenKeyEx(hkey_local_machine, path.to_wide(), 0, key_query_value | key_wow64_32key |
|
||||
key_enumerate_sub_keys, &root_key)
|
||||
rc := C.RegOpenKeyEx(hkey_local_machine, path.to_wide(), 0, key_query_value | key_wow64_32key | key_enumerate_sub_keys,
|
||||
&root_key)
|
||||
// TODO: Fix defer inside ifs
|
||||
// defer {
|
||||
// C.RegCloseKey(root_key)
|
||||
|
@ -8,7 +8,8 @@ import v.gen.x64
|
||||
pub fn (mut b Builder) build_x64(v_files []string, out_file string) {
|
||||
$if !linux {
|
||||
println('v -x64 can only generate Linux binaries for now')
|
||||
println('You are not on a Linux system, so you will not ' + 'be able to run the resulting executable')
|
||||
println('You are not on a Linux system, so you will not ' +
|
||||
'be able to run the resulting executable')
|
||||
}
|
||||
b.timing_start('PARSE')
|
||||
b.parsed_files = parser.parse_files(v_files, b.table, b.pref, b.global_scope)
|
||||
|
@ -56,26 +56,20 @@ pub fn (mut c Checker) check_basic(got table.Type, expected table.Type) bool {
|
||||
return true
|
||||
}
|
||||
// TODO i64 as int etc
|
||||
if (exp_idx in table.pointer_type_idxs ||
|
||||
exp_idx in table.number_type_idxs) &&
|
||||
(got_idx in table.pointer_type_idxs || got_idx in table.number_type_idxs)
|
||||
{
|
||||
if (exp_idx in table.pointer_type_idxs || exp_idx in table.number_type_idxs)
|
||||
&& (got_idx in table.pointer_type_idxs || got_idx in table.number_type_idxs) {
|
||||
return true
|
||||
}
|
||||
// if exp_idx in pointer_type_idxs && got_idx in pointer_type_idxs {
|
||||
// return true
|
||||
// }
|
||||
// see hack in checker IndexExpr line #691
|
||||
if (got_idx == table.byte_type_idx &&
|
||||
exp_idx == table.byteptr_type_idx) ||
|
||||
(exp_idx == table.byte_type_idx && got_idx == table.byteptr_type_idx)
|
||||
{
|
||||
if (got_idx == table.byte_type_idx && exp_idx == table.byteptr_type_idx)
|
||||
|| (exp_idx == table.byte_type_idx && got_idx == table.byteptr_type_idx) {
|
||||
return true
|
||||
}
|
||||
if (got_idx == table.char_type_idx &&
|
||||
exp_idx == table.charptr_type_idx) ||
|
||||
(exp_idx == table.char_type_idx && got_idx == table.charptr_type_idx)
|
||||
{
|
||||
if (got_idx == table.char_type_idx && exp_idx == table.charptr_type_idx)
|
||||
|| (exp_idx == table.char_type_idx && got_idx == table.charptr_type_idx) {
|
||||
return true
|
||||
}
|
||||
// TODO: this should no longer be needed
|
||||
@ -110,16 +104,13 @@ pub fn (mut c Checker) check_basic(got table.Type, expected table.Type) bool {
|
||||
}
|
||||
// TODO
|
||||
// accept [] when an expected type is an array
|
||||
if got_type_sym.kind == .array &&
|
||||
exp_type_sym.kind == .array && got_type_sym.name == 'array_void'
|
||||
{
|
||||
if got_type_sym.kind == .array && exp_type_sym.kind == .array
|
||||
&& got_type_sym.name == 'array_void' {
|
||||
return true
|
||||
}
|
||||
// type alias
|
||||
if (got_type_sym.kind == .alias &&
|
||||
got_type_sym.parent_idx == exp_idx) ||
|
||||
(exp_type_sym.kind == .alias && exp_type_sym.parent_idx == got_idx)
|
||||
{
|
||||
if (got_type_sym.kind == .alias && got_type_sym.parent_idx == exp_idx)
|
||||
|| (exp_type_sym.kind == .alias && exp_type_sym.parent_idx == got_idx) {
|
||||
return true
|
||||
}
|
||||
// sum type
|
||||
@ -242,9 +233,8 @@ fn (c &Checker) promote_num(left_type table.Type, right_type table.Type) table.T
|
||||
}
|
||||
} else if idx_lo >= table.byte_type_idx { // both operands are unsigned
|
||||
return type_hi
|
||||
} else if idx_lo >= table.i8_type_idx &&
|
||||
(idx_hi <= table.i64_type_idx || idx_hi == table.rune_type_idx)
|
||||
{ // both signed
|
||||
} else if idx_lo >= table.i8_type_idx
|
||||
&& (idx_hi <= table.i64_type_idx || idx_hi == table.rune_type_idx) { // both signed
|
||||
return if idx_lo == table.i64_type_idx {
|
||||
type_lo
|
||||
} else {
|
||||
@ -363,11 +353,9 @@ pub fn (c &Checker) get_default_fmt(ftyp table.Type, typ table.Type) byte {
|
||||
if sym.kind == .function {
|
||||
return `s`
|
||||
}
|
||||
if ftyp in [table.string_type, table.bool_type] ||
|
||||
sym.kind in
|
||||
[.enum_, .array, .array_fixed, .struct_, .map, .multi_return, .sum_type, .none_] ||
|
||||
ftyp.has_flag(.optional) || sym.has_method('str')
|
||||
{
|
||||
if ftyp in [table.string_type, table.bool_type]
|
||||
|| sym.kind in [.enum_, .array, .array_fixed, .struct_, .map, .multi_return, .sum_type, .none_]
|
||||
|| ftyp.has_flag(.optional)|| sym.has_method('str') {
|
||||
return `s`
|
||||
} else {
|
||||
return `_`
|
||||
@ -382,9 +370,7 @@ pub fn (mut c Checker) string_inter_lit(mut node ast.StringInterLiteral) table.T
|
||||
typ := c.table.unalias_num_type(ftyp)
|
||||
mut fmt := node.fmts[i]
|
||||
// analyze and validate format specifier
|
||||
if fmt !in
|
||||
[`E`, `F`, `G`, `e`, `f`, `g`, `d`, `u`, `x`, `X`, `o`, `c`, `s`, `p`, `_`]
|
||||
{
|
||||
if fmt !in [`E`, `F`, `G`, `e`, `f`, `g`, `d`, `u`, `x`, `X`, `o`, `c`, `s`, `p`, `_`] {
|
||||
c.error('unknown format specifier `${fmt:c}`', node.fmt_poss[i])
|
||||
}
|
||||
if fmt == `_` { // set default representation for type if none has been given
|
||||
@ -405,14 +391,13 @@ pub fn (mut c Checker) string_inter_lit(mut node ast.StringInterLiteral) table.T
|
||||
if node.pluss[i] && !typ.is_number() {
|
||||
c.error('plus prefix only allowed for numbers', node.fmt_poss[i])
|
||||
}
|
||||
if (typ.is_unsigned() && fmt !in [`u`, `x`, `X`, `o`, `c`]) ||
|
||||
(typ.is_signed() && fmt !in [`d`, `x`, `X`, `o`, `c`]) ||
|
||||
(typ.is_int_literal() && fmt !in [`d`, `c`, `x`, `X`, `o`, `u`, `x`, `X`, `o`]) ||
|
||||
(typ.is_float() && fmt !in [`E`, `F`, `G`, `e`, `f`, `g`]) ||
|
||||
(typ.is_pointer() && fmt !in [`p`, `x`, `X`]) ||
|
||||
(typ.is_string() && fmt != `s`) ||
|
||||
(typ.idx() in [table.i64_type_idx, table.f64_type_idx] && fmt == `c`)
|
||||
{
|
||||
if (typ.is_unsigned() && fmt !in [`u`, `x`, `X`, `o`, `c`])
|
||||
|| (typ.is_signed() && fmt !in [`d`, `x`, `X`, `o`, `c`])
|
||||
|| (typ.is_int_literal() && fmt !in [`d`, `c`, `x`, `X`, `o`, `u`, `x`, `X`, `o`])
|
||||
|| (typ.is_float() && fmt !in [`E`, `F`, `G`, `e`, `f`, `g`])
|
||||
|| (typ.is_pointer() && fmt !in [`p`, `x`, `X`])
|
||||
|| (typ.is_string() && fmt != `s`)
|
||||
|| (typ.idx() in [table.i64_type_idx, table.f64_type_idx] && fmt == `c`) {
|
||||
c.error('illegal format specifier `${fmt:c}` for type `${c.table.get_type_name(ftyp)}`',
|
||||
node.fmt_poss[i])
|
||||
}
|
||||
@ -456,10 +441,8 @@ pub fn (mut c Checker) infer_fn_types(f table.Fn, mut call_expr ast.CallExpr) {
|
||||
mut arg_elem_sym := c.table.get_type_symbol(arg_elem_info.elem_type)
|
||||
mut param_elem_sym := c.table.get_type_symbol(param_elem_info.elem_type)
|
||||
for {
|
||||
if arg_elem_sym.kind == .array &&
|
||||
param_elem_sym.kind == .array && c.cur_fn.generic_params.filter(it.name ==
|
||||
param_elem_sym.name).len == 0
|
||||
{
|
||||
if arg_elem_sym.kind == .array && param_elem_sym.kind == .array
|
||||
&& c.cur_fn.generic_params.filter(it.name == param_elem_sym.name).len == 0 {
|
||||
arg_elem_info = arg_elem_sym.info as table.Array
|
||||
arg_elem_sym = c.table.get_type_symbol(arg_elem_info.elem_type)
|
||||
param_elem_info = param_elem_sym.info as table.Array
|
||||
|
@ -562,16 +562,15 @@ pub fn (mut c Checker) struct_init(mut struct_init ast.StructInit) table.Type {
|
||||
return table.void_type
|
||||
}
|
||||
}
|
||||
if !type_sym.is_public && type_sym.kind != .placeholder && type_sym.mod != c.mod &&
|
||||
type_sym.language != .c
|
||||
{
|
||||
if !type_sym.is_public && type_sym.kind != .placeholder && type_sym.mod != c.mod
|
||||
&& type_sym.language != .c {
|
||||
c.error('type `$type_sym.name` is private', struct_init.pos)
|
||||
}
|
||||
if type_sym.kind == .struct_ {
|
||||
info := type_sym.info as table.Struct
|
||||
if info.attrs.len > 0 && info.attrs[0].name == 'noinit' && type_sym.mod != c.mod {
|
||||
c.error('struct `$type_sym.name` is declared with a `[noinit]` attribute, so ' + 'it cannot be initialized with `$type_sym.name{}`',
|
||||
struct_init.pos)
|
||||
c.error('struct `$type_sym.name` is declared with a `[noinit]` attribute, so ' +
|
||||
'it cannot be initialized with `$type_sym.name{}`', struct_init.pos)
|
||||
}
|
||||
}
|
||||
if type_sym.name.len == 1 && c.cur_fn.generic_params.len == 0 {
|
||||
@ -681,9 +680,8 @@ pub fn (mut c Checker) struct_init(mut struct_init ast.StructInit) table.Type {
|
||||
field.pos)
|
||||
}
|
||||
}
|
||||
if info_field.typ.is_ptr() && !expr_type.is_ptr() && !expr_type.is_pointer() &&
|
||||
!expr_type.is_number()
|
||||
{
|
||||
if info_field.typ.is_ptr() && !expr_type.is_ptr() && !expr_type.is_pointer()
|
||||
&& !expr_type.is_number() {
|
||||
c.error('ref', field.pos)
|
||||
}
|
||||
struct_init.fields[i].typ = expr_type
|
||||
@ -833,14 +831,12 @@ pub fn (mut c Checker) infix_expr(mut infix_expr ast.InfixExpr) table.Type {
|
||||
return table.bool_type
|
||||
}
|
||||
.plus, .minus, .mul, .div, .mod, .xor, .amp, .pipe { // binary operators that expect matching types
|
||||
if right.info is table.Alias &&
|
||||
(right.info as table.Alias).language != .c && c.mod == c.table.type_to_str(right_type).split('.')[0]
|
||||
{
|
||||
if right.info is table.Alias
|
||||
&& (right.info as table.Alias).language != .c && c.mod == c.table.type_to_str(right_type).split('.')[0] {
|
||||
right = c.table.get_type_symbol((right.info as table.Alias).parent_type)
|
||||
}
|
||||
if left.info is table.Alias &&
|
||||
(left.info as table.Alias).language != .c && c.mod == c.table.type_to_str(left_type).split('.')[0]
|
||||
{
|
||||
if left.info is table.Alias
|
||||
&& (left.info as table.Alias).language != .c && c.mod == c.table.type_to_str(left_type).split('.')[0] {
|
||||
left = c.table.get_type_symbol((left.info as table.Alias).parent_type)
|
||||
}
|
||||
if left.kind in [.array, .array_fixed, .map, .struct_] {
|
||||
@ -944,9 +940,8 @@ pub fn (mut c Checker) infix_expr(mut infix_expr ast.InfixExpr) table.Type {
|
||||
// []T << T
|
||||
return table.void_type
|
||||
}
|
||||
if right.kind == .array &&
|
||||
c.check_types(left_value_type, c.table.value_type(right_type))
|
||||
{
|
||||
if right.kind == .array
|
||||
&& c.check_types(left_value_type, c.table.value_type(right_type)) {
|
||||
// []T << []T
|
||||
return table.void_type
|
||||
}
|
||||
@ -1017,9 +1012,8 @@ pub fn (mut c Checker) infix_expr(mut infix_expr ast.InfixExpr) table.Type {
|
||||
if left_type == table.bool_type && infix_expr.op !in [.eq, .ne, .logical_or, .and] {
|
||||
c.error('bool types only have the following operators defined: `==`, `!=`, `||`, and `&&`',
|
||||
infix_expr.pos)
|
||||
} else if left_type == table.string_type &&
|
||||
infix_expr.op !in [.plus, .eq, .ne, .lt, .gt, .le, .ge]
|
||||
{
|
||||
} else if left_type == table.string_type
|
||||
&& infix_expr.op !in [.plus, .eq, .ne, .lt, .gt, .le, .ge] {
|
||||
// TODO broken !in
|
||||
c.error('string types only have the following operators defined: `==`, `!=`, `<`, `>`, `<=`, `>=`, and `+`',
|
||||
infix_expr.pos)
|
||||
@ -1221,15 +1215,15 @@ pub fn (mut c Checker) call_expr(mut call_expr ast.CallExpr) table.Type {
|
||||
// Now call `call_method` or `call_fn` for specific checks.
|
||||
typ := if call_expr.is_method { c.call_method(mut call_expr) } else { c.call_fn(mut call_expr) }
|
||||
// autofree: mark args that have to be freed (after saving them in tmp exprs)
|
||||
free_tmp_arg_vars := c.pref.autofree && !c.is_builtin_mod && call_expr.args.len > 0 && !call_expr.args[0].typ.has_flag(.optional)
|
||||
free_tmp_arg_vars := c.pref.autofree && !c.is_builtin_mod && call_expr.args.len > 0
|
||||
&& !call_expr.args[0].typ.has_flag(.optional)
|
||||
if free_tmp_arg_vars && !c.inside_const {
|
||||
for i, arg in call_expr.args {
|
||||
if arg.typ != table.string_type {
|
||||
continue
|
||||
}
|
||||
if arg.expr is ast.Ident ||
|
||||
arg.expr is ast.StringLiteral || arg.expr is ast.SelectorExpr
|
||||
{
|
||||
if arg.expr is ast.Ident || arg.expr is ast.StringLiteral
|
||||
|| arg.expr is ast.SelectorExpr {
|
||||
// Simple expressions like variables, string literals, selector expressions
|
||||
// (`x.field`) can't result in allocations and don't need to be assigned to
|
||||
// temporary vars.
|
||||
@ -1239,9 +1233,9 @@ pub fn (mut c Checker) call_expr(mut call_expr ast.CallExpr) table.Type {
|
||||
call_expr.args[i].is_tmp_autofree = true
|
||||
}
|
||||
// TODO copy pasta from above
|
||||
if call_expr.receiver_type == table.string_type && !(call_expr.left is ast.Ident ||
|
||||
call_expr.left is ast.StringLiteral || call_expr.left is ast.SelectorExpr)
|
||||
{
|
||||
if call_expr.receiver_type == table.string_type && !(call_expr.left is ast.Ident
|
||||
|| call_expr.left is ast.StringLiteral
|
||||
|| call_expr.left is ast.SelectorExpr) {
|
||||
call_expr.free_receiver = true
|
||||
}
|
||||
}
|
||||
@ -1263,13 +1257,11 @@ fn (mut c Checker) check_map_and_filter(is_map bool, elem_typ table.Type, call_e
|
||||
ast.AnonFn {
|
||||
if arg_expr.decl.params.len > 1 {
|
||||
c.error('function needs exactly 1 argument', arg_expr.decl.pos)
|
||||
} else if is_map &&
|
||||
(arg_expr.decl.return_type == table.void_type || arg_expr.decl.params[0].typ != elem_typ)
|
||||
{
|
||||
} else if is_map
|
||||
&& (arg_expr.decl.return_type == table.void_type || arg_expr.decl.params[0].typ != elem_typ) {
|
||||
c.error('type mismatch, should use `fn(a $elem_sym.name) T {...}`', arg_expr.decl.pos)
|
||||
} else if !is_map &&
|
||||
(arg_expr.decl.return_type != table.bool_type || arg_expr.decl.params[0].typ != elem_typ)
|
||||
{
|
||||
} else if !is_map
|
||||
&& (arg_expr.decl.return_type != table.bool_type || arg_expr.decl.params[0].typ != elem_typ) {
|
||||
c.error('type mismatch, should use `fn(a $elem_sym.name) bool {...}`',
|
||||
arg_expr.decl.pos)
|
||||
}
|
||||
@ -1282,14 +1274,12 @@ fn (mut c Checker) check_map_and_filter(is_map bool, elem_typ table.Type, call_e
|
||||
}
|
||||
if func.params.len > 1 {
|
||||
c.error('function needs exactly 1 argument', call_expr.pos)
|
||||
} else if is_map &&
|
||||
(func.return_type == table.void_type || func.params[0].typ != elem_typ)
|
||||
{
|
||||
} else if is_map
|
||||
&& (func.return_type == table.void_type || func.params[0].typ != elem_typ) {
|
||||
c.error('type mismatch, should use `fn(a $elem_sym.name) T {...}`',
|
||||
arg_expr.pos)
|
||||
} else if !is_map &&
|
||||
(func.return_type != table.bool_type || func.params[0].typ != elem_typ)
|
||||
{
|
||||
} else if !is_map
|
||||
&& (func.return_type != table.bool_type || func.params[0].typ != elem_typ) {
|
||||
c.error('type mismatch, should use `fn(a $elem_sym.name) bool {...}`',
|
||||
arg_expr.pos)
|
||||
}
|
||||
@ -1357,7 +1347,8 @@ pub fn (mut c Checker) call_method(mut call_expr ast.CallExpr) table.Type {
|
||||
// Verify `.sort(a < b)`
|
||||
if call_expr.args.len > 0 {
|
||||
if call_expr.args[0].expr !is ast.InfixExpr {
|
||||
c.error('`.sort()` requires a `<` or `>` comparison as the first and only argument' +
|
||||
c.error(
|
||||
'`.sort()` requires a `<` or `>` comparison as the first and only argument' +
|
||||
'\ne.g. `users.sort(a.id < b.id)`', call_expr.pos)
|
||||
}
|
||||
}
|
||||
@ -1473,9 +1464,8 @@ pub fn (mut c Checker) call_method(mut call_expr ast.CallExpr) table.Type {
|
||||
}
|
||||
}
|
||||
if has_method {
|
||||
if !method.is_pub && !c.is_builtin_mod && !c.pref.is_test && left_type_sym.mod != c.mod &&
|
||||
left_type_sym.mod != ''
|
||||
{ // method.mod != c.mod {
|
||||
if !method.is_pub && !c.is_builtin_mod && !c.pref.is_test && left_type_sym.mod != c.mod
|
||||
&& left_type_sym.mod != '' { // method.mod != c.mod {
|
||||
// If a private method is called outside of the module
|
||||
// its receiver type is defined in, show an error.
|
||||
// println('warn $method_name lef.mod=$left_type_sym.mod c.mod=$c.mod')
|
||||
@ -1485,14 +1475,16 @@ pub fn (mut c Checker) call_method(mut call_expr ast.CallExpr) table.Type {
|
||||
c.fail_if_immutable(call_expr.left)
|
||||
// call_expr.is_mut = true
|
||||
}
|
||||
if method.return_type == table.void_type &&
|
||||
method.ctdefine.len > 0 && method.ctdefine !in c.pref.compile_defines
|
||||
{
|
||||
if method.return_type == table.void_type && method.ctdefine.len > 0
|
||||
&& method.ctdefine !in c.pref.compile_defines {
|
||||
call_expr.should_be_skipped = true
|
||||
}
|
||||
nr_args := if method.params.len == 0 { 0 } else { method.params.len - 1 }
|
||||
min_required_args := method.params.len - if method.is_variadic && method.params.len >
|
||||
1 { 2 } else { 1 }
|
||||
min_required_args := method.params.len - if method.is_variadic && method.params.len > 1 {
|
||||
2
|
||||
} else {
|
||||
1
|
||||
}
|
||||
if call_expr.args.len < min_required_args {
|
||||
c.error('expected $min_required_args arguments, but got $call_expr.args.len',
|
||||
call_expr.pos)
|
||||
@ -1508,8 +1500,11 @@ pub fn (mut c Checker) call_method(mut call_expr ast.CallExpr) table.Type {
|
||||
// call_expr.args << method.args[0].typ
|
||||
// call_expr.exp_arg_types << method.args[0].typ
|
||||
for i, arg in call_expr.args {
|
||||
exp_arg_typ := if method.is_variadic && i >= method.params.len - 1 { method.params[method.params.len -
|
||||
1].typ } else { method.params[i + 1].typ }
|
||||
exp_arg_typ := if method.is_variadic && i >= method.params.len - 1 {
|
||||
method.params[method.params.len - 1].typ
|
||||
} else {
|
||||
method.params[i + 1].typ
|
||||
}
|
||||
exp_arg_sym := c.table.get_type_symbol(exp_arg_typ)
|
||||
c.expected_type = exp_arg_typ
|
||||
got_arg_typ := c.expr(arg.expr)
|
||||
@ -1537,8 +1532,11 @@ pub fn (mut c Checker) call_method(mut call_expr ast.CallExpr) table.Type {
|
||||
call_expr.pos)
|
||||
}
|
||||
}
|
||||
param := if method.is_variadic && i >= method.params.len - 1 { method.params[method.params.len -
|
||||
1] } else { method.params[i + 1] }
|
||||
param := if method.is_variadic && i >= method.params.len - 1 {
|
||||
method.params[method.params.len - 1]
|
||||
} else {
|
||||
method.params[i + 1]
|
||||
}
|
||||
if arg.is_mut {
|
||||
c.fail_if_immutable(arg.expr)
|
||||
if !param.is_mut {
|
||||
@ -1551,8 +1549,8 @@ pub fn (mut c Checker) call_method(mut call_expr ast.CallExpr) table.Type {
|
||||
} else {
|
||||
if param.is_mut && (!arg.is_mut || param.typ.share() != arg.share) {
|
||||
tok := arg.share.str()
|
||||
c.warn('`$call_expr.name` parameter `$param.name` is `$tok`, you need to provide `$tok` e.g. `$tok arg${i +
|
||||
1}`', arg.expr.position())
|
||||
c.warn('`$call_expr.name` parameter `$param.name` is `$tok`, you need to provide `$tok` e.g. `$tok arg${
|
||||
i + 1}`', arg.expr.position())
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1605,8 +1603,7 @@ pub fn (mut c Checker) call_method(mut call_expr ast.CallExpr) table.Type {
|
||||
elem_info := return_sym.info as table.Chan
|
||||
elem_sym := c.table.get_type_symbol(elem_info.elem_type)
|
||||
if elem_sym.name in method.generic_names {
|
||||
idx := c.table.find_or_register_chan(elem_info.elem_type, elem_info.elem_type.nr_muls() >
|
||||
0)
|
||||
idx := c.table.find_or_register_chan(elem_info.elem_type, elem_info.elem_type.nr_muls() > 0)
|
||||
return table.new_type(idx)
|
||||
}
|
||||
}
|
||||
@ -1789,9 +1786,8 @@ pub fn (mut c Checker) call_fn(mut call_expr ast.CallExpr) table.Type {
|
||||
if f.is_deprecated {
|
||||
c.warn('function `$f.name` has been deprecated', call_expr.pos)
|
||||
}
|
||||
if f.is_unsafe && !c.inside_unsafe && f.language == .c && f.name[2] in [`m`, `s`] &&
|
||||
f.mod == 'builtin'
|
||||
{
|
||||
if f.is_unsafe && !c.inside_unsafe && f.language == .c && f.name[2] in [`m`, `s`]
|
||||
&& f.mod == 'builtin' {
|
||||
// builtin C.m*, C.s* only - temp
|
||||
c.warn('function `$f.name` must be called from an `unsafe` block', call_expr.pos)
|
||||
}
|
||||
@ -1817,9 +1813,8 @@ pub fn (mut c Checker) call_fn(mut call_expr ast.CallExpr) table.Type {
|
||||
} else {
|
||||
call_expr.return_type = f.return_type
|
||||
}
|
||||
if f.return_type == table.void_type &&
|
||||
f.ctdefine.len > 0 && f.ctdefine !in c.pref.compile_defines
|
||||
{
|
||||
if f.return_type == table.void_type && f.ctdefine.len > 0
|
||||
&& f.ctdefine !in c.pref.compile_defines {
|
||||
call_expr.should_be_skipped = true
|
||||
}
|
||||
if f.language != .v || call_expr.language != .v {
|
||||
@ -1891,8 +1886,8 @@ pub fn (mut c Checker) call_fn(mut call_expr ast.CallExpr) table.Type {
|
||||
} else {
|
||||
if arg.is_mut && (!call_arg.is_mut || arg.typ.share() != call_arg.share) {
|
||||
tok := call_arg.share.str()
|
||||
c.warn('`$call_expr.name` parameter `$arg.name` is `$tok`, you need to provide `$tok` e.g. `$tok arg${i +
|
||||
1}`', call_arg.expr.position())
|
||||
c.warn('`$call_expr.name` parameter `$arg.name` is `$tok`, you need to provide `$tok` e.g. `$tok arg${
|
||||
i + 1}`', call_arg.expr.position())
|
||||
}
|
||||
}
|
||||
// Handle expected interface
|
||||
@ -2036,8 +2031,8 @@ pub fn (mut c Checker) check_or_expr(or_expr ast.OrExpr, ret_type table.Type, ex
|
||||
c.expected_or_type = ret_type.clear_flag(.optional)
|
||||
last_stmt_typ := c.expr(last_stmt.expr)
|
||||
c.expected_or_type = table.void_type
|
||||
type_fits := c.check_types(last_stmt_typ, ret_type) && last_stmt_typ.nr_muls() ==
|
||||
ret_type.nr_muls()
|
||||
type_fits := c.check_types(last_stmt_typ, ret_type)
|
||||
&& last_stmt_typ.nr_muls() == ret_type.nr_muls()
|
||||
is_panic_or_exit := is_expr_panic_or_exit(last_stmt.expr)
|
||||
if type_fits || is_panic_or_exit {
|
||||
return
|
||||
@ -2233,9 +2228,8 @@ pub fn (mut c Checker) return_stmt(mut return_stmt ast.Return) {
|
||||
c.error('too many arguments to return, current function does not return anything',
|
||||
return_stmt.pos)
|
||||
return
|
||||
} else if return_stmt.exprs.len == 0 && !(c.expected_type == table.void_type ||
|
||||
expected_type_sym.kind == .void)
|
||||
{
|
||||
} else if return_stmt.exprs.len == 0 && !(c.expected_type == table.void_type
|
||||
|| expected_type_sym.kind == .void) {
|
||||
c.error('too few arguments to return', return_stmt.pos)
|
||||
return
|
||||
}
|
||||
@ -2274,9 +2268,8 @@ pub fn (mut c Checker) return_stmt(mut return_stmt ast.Return) {
|
||||
}
|
||||
for i, exp_type in expected_types {
|
||||
got_typ := c.unwrap_generic(got_types[i])
|
||||
if got_typ.has_flag(.optional) &&
|
||||
(!exp_type.has_flag(.optional) || c.table.type_to_str(got_typ) != c.table.type_to_str(exp_type))
|
||||
{
|
||||
if got_typ.has_flag(.optional)
|
||||
&& (!exp_type.has_flag(.optional) || c.table.type_to_str(got_typ) != c.table.type_to_str(exp_type)) {
|
||||
pos := return_stmt.exprs[i].position()
|
||||
c.error('cannot use `${c.table.type_to_str(got_typ)}` as type `${c.table.type_to_str(exp_type)}` in return argument',
|
||||
pos)
|
||||
@ -2292,16 +2285,14 @@ pub fn (mut c Checker) return_stmt(mut return_stmt ast.Return) {
|
||||
c.error('cannot use `$got_typ_sym.name` as type `$exp_typ_sym.name` in return argument',
|
||||
pos)
|
||||
}
|
||||
if (got_typ.is_ptr() || got_typ.is_pointer()) &&
|
||||
(!exp_type.is_ptr() && !exp_type.is_pointer())
|
||||
{
|
||||
if (got_typ.is_ptr() || got_typ.is_pointer())
|
||||
&& (!exp_type.is_ptr() && !exp_type.is_pointer()) {
|
||||
pos := return_stmt.exprs[i].position()
|
||||
c.error('fn `$c.cur_fn.name` expects you to return a non reference type `${c.table.type_to_str(exp_type)}`, but you are returning `${c.table.type_to_str(got_typ)}` instead',
|
||||
pos)
|
||||
}
|
||||
if (exp_type.is_ptr() || exp_type.is_pointer()) &&
|
||||
(!got_typ.is_ptr() && !got_typ.is_pointer()) && got_typ != table.int_literal_type
|
||||
{
|
||||
if (exp_type.is_ptr() || exp_type.is_pointer())
|
||||
&& (!got_typ.is_ptr() && !got_typ.is_pointer())&& got_typ != table.int_literal_type {
|
||||
pos := return_stmt.exprs[i].position()
|
||||
c.error('fn `$c.cur_fn.name` expects you to return a reference type `${c.table.type_to_str(exp_type)}`, but you are returning `${c.table.type_to_str(got_typ)}` instead',
|
||||
pos)
|
||||
@ -2580,10 +2571,9 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) {
|
||||
// TODO replace all c.pref.translated checks with `$if !translated` for performance
|
||||
continue
|
||||
}
|
||||
if left_sym.kind == .array && !c.inside_unsafe && assign_stmt.op in [.assign, .decl_assign] &&
|
||||
right_sym.kind == .array &&
|
||||
(left is ast.Ident && !left.is_blank_ident()) && right is ast.Ident
|
||||
{
|
||||
if left_sym.kind == .array && !c.inside_unsafe && assign_stmt.op in [.assign, .decl_assign]
|
||||
&& right_sym.kind == .array && (left is ast.Ident && !left.is_blank_ident())
|
||||
&& right is ast.Ident {
|
||||
// Do not allow `a = b`, only `a = b.clone()`
|
||||
c.error('use `array2 = array1.clone()` instead of `array2 = array1` (or use `unsafe`)',
|
||||
assign_stmt.pos)
|
||||
@ -2622,10 +2612,12 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) {
|
||||
c.error('invalid right operand: $left_sym.name $assign_stmt.op $right_sym.name',
|
||||
right.position())
|
||||
}
|
||||
} else if !left_sym.is_number() && left_sym.kind !in [.byteptr, .charptr, .struct_, .alias] {
|
||||
} else if !left_sym.is_number()
|
||||
&& left_sym.kind !in [.byteptr, .charptr, .struct_, .alias] {
|
||||
c.error('operator `$assign_stmt.op` not defined on left operand type `$left_sym.name`',
|
||||
left.position())
|
||||
} else if !right_sym.is_number() && left_sym.kind !in [.byteptr, .charptr, .struct_, .alias] {
|
||||
} else if !right_sym.is_number()
|
||||
&& left_sym.kind !in [.byteptr, .charptr, .struct_, .alias] {
|
||||
c.error('invalid right operand: $left_sym.name $assign_stmt.op $right_sym.name',
|
||||
right.position())
|
||||
} else if right is ast.IntegerLiteral {
|
||||
@ -2640,40 +2632,35 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) {
|
||||
}
|
||||
}
|
||||
.mult_assign, .div_assign {
|
||||
if !left_sym.is_number() &&
|
||||
!c.table.get_final_type_symbol(left_type_unwrapped).is_int() && left_sym.kind !in
|
||||
[.struct_, .alias]
|
||||
{
|
||||
if !left_sym.is_number()
|
||||
&& !c.table.get_final_type_symbol(left_type_unwrapped).is_int()
|
||||
&& left_sym.kind !in [.struct_, .alias] {
|
||||
c.error('operator $assign_stmt.op.str() not defined on left operand type `$left_sym.name`',
|
||||
left.position())
|
||||
} else if !right_sym.is_number() &&
|
||||
!c.table.get_final_type_symbol(left_type_unwrapped).is_int() && left_sym.kind !in
|
||||
[.struct_, .alias]
|
||||
{
|
||||
} else if !right_sym.is_number()
|
||||
&& !c.table.get_final_type_symbol(left_type_unwrapped).is_int()
|
||||
&& left_sym.kind !in [.struct_, .alias] {
|
||||
c.error('operator $assign_stmt.op.str() not defined on right operand type `$right_sym.name`',
|
||||
right.position())
|
||||
}
|
||||
}
|
||||
.and_assign, .or_assign, .xor_assign, .mod_assign, .left_shift_assign, .right_shift_assign
|
||||
{
|
||||
if !left_sym.is_int() &&
|
||||
!c.table.get_final_type_symbol(left_type_unwrapped).is_int()
|
||||
{
|
||||
if !left_sym.is_int()
|
||||
&& !c.table.get_final_type_symbol(left_type_unwrapped).is_int() {
|
||||
c.error('operator $assign_stmt.op.str() not defined on left operand type `$left_sym.name`',
|
||||
left.position())
|
||||
} else if !right_sym.is_int() &&
|
||||
!c.table.get_final_type_symbol(right_type_unwrapped).is_int()
|
||||
{
|
||||
} else if !right_sym.is_int()
|
||||
&& !c.table.get_final_type_symbol(right_type_unwrapped).is_int() {
|
||||
c.error('operator $assign_stmt.op.str() not defined on right operand type `$right_sym.name`',
|
||||
right.position())
|
||||
}
|
||||
}
|
||||
else {}
|
||||
}
|
||||
if assign_stmt.op in
|
||||
[.plus_assign, .minus_assign, .mod_assign, .mult_assign, .div_assign] &&
|
||||
((left_sym.kind == .struct_ && right_sym.kind == .struct_) || left_sym.kind == .alias)
|
||||
{
|
||||
if assign_stmt.op in [.plus_assign, .minus_assign, .mod_assign, .mult_assign, .div_assign]
|
||||
&& ((left_sym.kind == .struct_ && right_sym.kind == .struct_)
|
||||
|| left_sym.kind == .alias) {
|
||||
left_name := c.table.type_to_str(left_type)
|
||||
right_name := c.table.type_to_str(right_type)
|
||||
parent_sym := c.table.get_final_type_symbol(left_type)
|
||||
@ -2884,7 +2871,8 @@ pub fn (mut c Checker) array_init(mut array_init ast.ArrayInit) table.Type {
|
||||
array_init.typ = table.new_type(idx)
|
||||
}
|
||||
array_init.elem_type = elem_type
|
||||
} else if array_init.is_fixed && array_init.exprs.len == 1 && array_init.elem_type != table.void_type {
|
||||
} else if array_init.is_fixed && array_init.exprs.len == 1
|
||||
&& array_init.elem_type != table.void_type {
|
||||
// [50]byte
|
||||
mut fixed_size := 0
|
||||
init_expr := array_init.exprs[0]
|
||||
@ -3070,7 +3058,8 @@ fn (mut c Checker) stmt(node ast.Stmt) {
|
||||
node.scope.update_var_type(node.val_var, val_type)
|
||||
} else {
|
||||
if sym.kind == .map && !(node.key_var.len > 0 && node.val_var.len > 0) {
|
||||
c.error('declare a key and a value variable when ranging a map: `for key, val in map {`\n' +
|
||||
c.error(
|
||||
'declare a key and a value variable when ranging a map: `for key, val in map {`\n' +
|
||||
'use `_` if you do not need the variable', node.pos)
|
||||
}
|
||||
if node.key_var.len > 0 {
|
||||
@ -3129,7 +3118,8 @@ fn (mut c Checker) stmt(node ast.Stmt) {
|
||||
arg.expr.position())
|
||||
}
|
||||
}
|
||||
if node.call_expr.is_method && node.call_expr.receiver_type.is_ptr() && !node.call_expr.left_type.is_ptr() {
|
||||
if node.call_expr.is_method && node.call_expr.receiver_type.is_ptr()
|
||||
&& !node.call_expr.left_type.is_ptr() {
|
||||
c.error('method in `go` statement cannot have non-reference mutable receiver',
|
||||
node.call_expr.left.position())
|
||||
}
|
||||
@ -3195,9 +3185,8 @@ fn (mut c Checker) hash_stmt(mut node ast.HashStmt) {
|
||||
node.main = vroot
|
||||
}
|
||||
flag_no_comment := flag.all_before('//').trim_space()
|
||||
if !((flag_no_comment.starts_with('"') && flag_no_comment.ends_with('"')) ||
|
||||
(flag_no_comment.starts_with('<') && flag_no_comment.ends_with('>')))
|
||||
{
|
||||
if !((flag_no_comment.starts_with('"') && flag_no_comment.ends_with('"'))
|
||||
|| (flag_no_comment.starts_with('<') && flag_no_comment.ends_with('>'))) {
|
||||
c.error('including C files should use either `"header_file.h"` or `<header_file.h>` quoting',
|
||||
node.pos)
|
||||
}
|
||||
@ -3578,10 +3567,8 @@ pub fn (mut c Checker) cast_expr(mut node ast.CastExpr) table.Type {
|
||||
c.error('cannot convert type `$from_type_sym.name` to `$to_type_sym.name` (alias to `$parent_type_sym.name`)',
|
||||
node.pos)
|
||||
}
|
||||
} else if node.typ == table.string_type &&
|
||||
(from_type_sym.kind in [.int_literal, .int, .byte, .byteptr, .bool] ||
|
||||
(from_type_sym.kind == .array && from_type_sym.name == 'array_byte'))
|
||||
{
|
||||
} else if node.typ == table.string_type
|
||||
&& (from_type_sym.kind in [.int_literal, .int, .byte, .byteptr, .bool] || (from_type_sym.kind == .array && from_type_sym.name == 'array_byte')) {
|
||||
type_name := c.table.type_to_str(node.expr_type)
|
||||
c.error('cannot cast type `$type_name` to string, use `x.str()` instead', node.pos)
|
||||
} else if node.expr_type == table.string_type {
|
||||
@ -3594,13 +3581,13 @@ pub fn (mut c Checker) cast_expr(mut node ast.CastExpr) table.Type {
|
||||
}
|
||||
c.error(error_msg, node.pos)
|
||||
}
|
||||
} else if to_type_sym.kind == .byte &&
|
||||
node.expr_type != table.voidptr_type && from_type_sym.kind != .enum_ && !node.expr_type.is_int() &&
|
||||
!node.expr_type.is_float() && !node.expr_type.is_ptr()
|
||||
{
|
||||
} else if to_type_sym.kind == .byte && node.expr_type != table.voidptr_type
|
||||
&& from_type_sym.kind != .enum_ && !node.expr_type.is_int() && !node.expr_type.is_float()
|
||||
&& !node.expr_type.is_ptr() {
|
||||
type_name := c.table.type_to_str(node.expr_type)
|
||||
c.error('cannot cast type `$type_name` to `byte`', node.pos)
|
||||
} else if to_type_sym.kind == .struct_ && !node.typ.is_ptr() && !(to_type_sym.info as table.Struct).is_typedef {
|
||||
} else if to_type_sym.kind == .struct_ && !node.typ.is_ptr()
|
||||
&& !(to_type_sym.info as table.Struct).is_typedef {
|
||||
// For now we ignore C typedef because of `C.Window(C.None)` in vlib/clipboard
|
||||
if from_type_sym.kind == .struct_ && !node.expr_type.is_ptr() {
|
||||
from_type_info := from_type_sym.info as table.Struct
|
||||
@ -3790,7 +3777,8 @@ pub fn (mut c Checker) ident(mut ident ast.Ident) table.Type {
|
||||
c.error('undefined variable `$ident.name` (used before declaration)',
|
||||
ident.pos)
|
||||
}
|
||||
is_sum_type_cast := obj.sum_type_casts.len != 0 && !c.prevent_sum_type_unwrapping_once
|
||||
is_sum_type_cast := obj.sum_type_casts.len != 0
|
||||
&& !c.prevent_sum_type_unwrapping_once
|
||||
c.prevent_sum_type_unwrapping_once = false
|
||||
mut typ := if is_sum_type_cast { obj.sum_type_casts.last() } else { obj.typ }
|
||||
if typ == 0 {
|
||||
@ -4293,9 +4281,9 @@ pub fn (mut c Checker) select_expr(mut node ast.SelectExpr) table.Type {
|
||||
}
|
||||
} else {
|
||||
if branch.stmt.expr is ast.InfixExpr {
|
||||
if branch.stmt.expr.left !is ast.Ident &&
|
||||
branch.stmt.expr.left !is ast.SelectorExpr && branch.stmt.expr.left !is ast.IndexExpr
|
||||
{
|
||||
if branch.stmt.expr.left !is ast.Ident
|
||||
&& branch.stmt.expr.left !is ast.SelectorExpr
|
||||
&& branch.stmt.expr.left !is ast.IndexExpr {
|
||||
c.error('channel in `select` key must be predefined', branch.stmt.expr.left.position())
|
||||
}
|
||||
} else {
|
||||
@ -4307,9 +4295,8 @@ pub fn (mut c Checker) select_expr(mut node ast.SelectExpr) table.Type {
|
||||
expr := branch.stmt.right[0]
|
||||
match expr {
|
||||
ast.PrefixExpr {
|
||||
if expr.right !is ast.Ident &&
|
||||
expr.right !is ast.SelectorExpr && expr.right !is ast.IndexExpr
|
||||
{
|
||||
if expr.right !is ast.Ident && expr.right !is ast.SelectorExpr
|
||||
&& expr.right !is ast.IndexExpr {
|
||||
c.error('channel in `select` key must be predefined', expr.right.position())
|
||||
}
|
||||
if expr.or_block.kind != .absent {
|
||||
@ -4388,10 +4375,8 @@ fn (mut c Checker) for_stmt(mut node ast.ForStmt) {
|
||||
if node.cond is ast.InfixExpr {
|
||||
infix := node.cond
|
||||
if infix.op == .key_is {
|
||||
if (infix.left is ast.Ident ||
|
||||
infix.left is ast.SelectorExpr) &&
|
||||
infix.right is ast.Type
|
||||
{
|
||||
if (infix.left is ast.Ident || infix.left is ast.SelectorExpr)
|
||||
&& infix.right is ast.Type {
|
||||
right_expr := infix.right as ast.Type
|
||||
is_variable := if mut infix.left is ast.Ident {
|
||||
infix.left.kind == .variable
|
||||
@ -4440,7 +4425,8 @@ pub fn (mut c Checker) if_expr(mut node ast.IfExpr) table.Type {
|
||||
// check condition type is boolean
|
||||
c.expected_type = table.bool_type
|
||||
cond_typ := c.expr(branch.cond)
|
||||
if cond_typ.idx() !in [table.bool_type_idx, table.void_type_idx] && !c.pref.translated {
|
||||
if cond_typ.idx() !in [table.bool_type_idx, table.void_type_idx]
|
||||
&& !c.pref.translated {
|
||||
// void types are skipped, because they mean the var was initialized incorrectly
|
||||
// (via missing function etc)
|
||||
typ_sym := c.table.get_type_symbol(cond_typ)
|
||||
@ -4462,10 +4448,8 @@ pub fn (mut c Checker) if_expr(mut node ast.IfExpr) table.Type {
|
||||
expr_str := c.table.type_to_str(expr_type)
|
||||
c.error('cannot use type `$expect_str` as type `$expr_str`', branch.pos)
|
||||
}
|
||||
if (infix.left is ast.Ident ||
|
||||
infix.left is ast.SelectorExpr) &&
|
||||
infix.right is ast.Type
|
||||
{
|
||||
if (infix.left is ast.Ident || infix.left is ast.SelectorExpr)
|
||||
&& infix.right is ast.Type {
|
||||
is_variable := if mut infix.left is ast.Ident {
|
||||
infix.left.kind == .variable
|
||||
} else {
|
||||
@ -4660,10 +4644,8 @@ fn (mut c Checker) comp_if_branch(cond ast.Expr, pos token.Position) bool {
|
||||
return l && r // skip (return true) only if both should be skipped
|
||||
}
|
||||
.key_is, .not_is {
|
||||
if (cond.left is ast.SelectorExpr ||
|
||||
cond.left is ast.Type) &&
|
||||
cond.right is ast.Type
|
||||
{
|
||||
if (cond.left is ast.SelectorExpr || cond.left is ast.Type)
|
||||
&& cond.right is ast.Type {
|
||||
// $if method.@type is string
|
||||
} else {
|
||||
c.error('invalid `\$if` condition: $cond.left', cond.pos)
|
||||
@ -4725,9 +4707,8 @@ fn (mut c Checker) comp_if_branch(cond ast.Expr, pos token.Position) bool {
|
||||
} else if cond.name !in c.pref.compile_defines_all {
|
||||
// `$if some_var {}`
|
||||
typ := c.expr(cond)
|
||||
if cond.obj !is ast.Var &&
|
||||
cond.obj !is ast.ConstField && cond.obj !is ast.GlobalField
|
||||
{
|
||||
if cond.obj !is ast.Var && cond.obj !is ast.ConstField
|
||||
&& cond.obj !is ast.GlobalField {
|
||||
c.error('unknown var: `$cond.name`', pos)
|
||||
return false
|
||||
}
|
||||
@ -4924,9 +4905,8 @@ pub fn (mut c Checker) index_expr(mut node ast.IndexExpr) table.Type {
|
||||
mut typ := c.expr(node.left)
|
||||
node.left_type = typ
|
||||
typ_sym := c.table.get_final_type_symbol(typ)
|
||||
if typ_sym.kind !in [.array, .array_fixed, .string, .map] && !typ.is_ptr() && typ !in [table.byteptr_type, table.charptr_type] &&
|
||||
!typ.has_flag(.variadic)
|
||||
{
|
||||
if typ_sym.kind !in [.array, .array_fixed, .string, .map] && !typ.is_ptr()
|
||||
&& typ !in [table.byteptr_type, table.charptr_type]&& !typ.has_flag(.variadic) {
|
||||
c.error('type `$typ_sym.name` does not support indexing', node.pos)
|
||||
}
|
||||
if typ_sym.kind == .string && !typ.is_ptr() && node.is_setter {
|
||||
@ -5275,8 +5255,8 @@ fn (mut c Checker) sql_stmt(mut node ast.SqlStmt) table.Type {
|
||||
}
|
||||
|
||||
fn (mut c Checker) fetch_and_verify_orm_fields(info table.Struct, pos token.Position, table_name string) []table.Field {
|
||||
fields := info.fields.filter(it.typ in
|
||||
[table.string_type, table.int_type, table.bool_type] && !it.attrs.contains('skip'))
|
||||
fields := info.fields.filter(it.typ in [table.string_type, table.int_type, table.bool_type]
|
||||
&& !it.attrs.contains('skip'))
|
||||
if fields.len == 0 {
|
||||
c.error('V orm: select: empty fields in `$table_name`', pos)
|
||||
return []table.Field{}
|
||||
@ -5344,17 +5324,15 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) {
|
||||
// Make sure all types are valid
|
||||
for arg in node.params {
|
||||
sym := c.table.get_type_symbol(arg.typ)
|
||||
if sym.kind == .placeholder ||
|
||||
(sym.kind in [table.Kind.int_literal, .float_literal] && !c.is_builtin_mod)
|
||||
{
|
||||
if sym.kind == .placeholder
|
||||
|| (sym.kind in [table.Kind.int_literal, .float_literal] && !c.is_builtin_mod) {
|
||||
c.error('unknown type `$sym.name`', node.pos)
|
||||
}
|
||||
}
|
||||
}
|
||||
return_sym := c.table.get_type_symbol(node.return_type)
|
||||
if node.language == .v &&
|
||||
return_sym.kind in [.placeholder, .int_literal, .float_literal] && return_sym.language == .v
|
||||
{
|
||||
if node.language == .v && return_sym.kind in [.placeholder, .int_literal, .float_literal]
|
||||
&& return_sym.language == .v {
|
||||
c.error('unknown type `$return_sym.name`', node.pos)
|
||||
}
|
||||
if node.language == .v && node.is_method && node.name == 'str' {
|
||||
@ -5365,9 +5343,8 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) {
|
||||
c.error('.str() methods should have 0 arguments', node.pos)
|
||||
}
|
||||
}
|
||||
if node.language == .v && node.is_method && node.name in
|
||||
['+', '-', '*', '%', '/', '<', '>', '==', '!=', '>=', '<=']
|
||||
{
|
||||
if node.language == .v && node.is_method
|
||||
&& node.name in ['+', '-', '*', '%', '/', '<', '>', '==', '!=', '>=', '<='] {
|
||||
if node.params.len != 2 {
|
||||
c.error('operator methods should have exactly 1 argument', node.pos)
|
||||
} else {
|
||||
@ -5385,9 +5362,8 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) {
|
||||
} else if node.receiver.typ != node.params[1].typ {
|
||||
c.error('expected `$receiver_sym.name` not `$param_sym.name` - both operands must be the same type for operator overloading',
|
||||
node.params[1].type_pos)
|
||||
} else if node.name in ['<', '>', '==', '!=', '>=', '<='] &&
|
||||
node.return_type != table.bool_type
|
||||
{
|
||||
} else if node.name in ['<', '>', '==', '!=', '>=', '<=']
|
||||
&& node.return_type != table.bool_type {
|
||||
c.error('operator comparison methods should return `bool`', node.pos)
|
||||
} else if parent_sym.is_primitive() {
|
||||
c.error('cannot define operator methods on type alias for `$parent_sym.name`',
|
||||
@ -5397,7 +5373,8 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) {
|
||||
}
|
||||
}
|
||||
// TODO c.pref.is_vet
|
||||
if node.language == .v && !node.is_method && node.params.len == 0 && node.name.after('.').starts_with('test_') {
|
||||
if node.language == .v && !node.is_method && node.params.len == 0
|
||||
&& node.name.after('.').starts_with('test_') {
|
||||
if !c.file.path.ends_with('_test.v') {
|
||||
// simple heuristic
|
||||
for st in node.stmts {
|
||||
@ -5416,9 +5393,8 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) {
|
||||
c.expected_type = table.void_type
|
||||
c.cur_fn = node
|
||||
// Add return if `fn(...) ? {...}` have no return at end
|
||||
if node.return_type != table.void_type && node.return_type.has_flag(.optional) &&
|
||||
(node.stmts.len == 0 || node.stmts[node.stmts.len - 1] !is ast.Return)
|
||||
{
|
||||
if node.return_type != table.void_type && node.return_type.has_flag(.optional)
|
||||
&& (node.stmts.len == 0 || node.stmts[node.stmts.len - 1] !is ast.Return) {
|
||||
sym := c.table.get_type_symbol(node.return_type)
|
||||
if sym.kind == .void {
|
||||
node.stmts << ast.Return{
|
||||
@ -5429,9 +5405,8 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) {
|
||||
c.fn_scope = node.scope
|
||||
c.stmts(node.stmts)
|
||||
returns := c.returns || has_top_return(node.stmts)
|
||||
if node.language == .v && !node.no_body && node.return_type != table.void_type && !returns &&
|
||||
node.name !in ['panic', 'exit']
|
||||
{
|
||||
if node.language == .v && !node.no_body && node.return_type != table.void_type && !returns
|
||||
&& node.name !in ['panic', 'exit'] {
|
||||
c.error('missing return at end of function `$node.name`', node.pos)
|
||||
}
|
||||
c.returns = false
|
||||
@ -5487,9 +5462,8 @@ fn (mut c Checker) verify_all_vweb_routes() {
|
||||
if isnil(f) {
|
||||
continue
|
||||
}
|
||||
if f.return_type == typ_vweb_result &&
|
||||
f.receiver.typ == m.params[0].typ && f.name == m.name
|
||||
{
|
||||
if f.return_type == typ_vweb_result && f.receiver.typ == m.params[0].typ
|
||||
&& f.name == m.name {
|
||||
c.file = f.source_file // setup of file path for the warning
|
||||
c.warn('mismatched parameters count between vweb method `${sym_app.name}.$m.name` ($nargs) and route attribute $m.attrs ($nroute_attributes)',
|
||||
f.pos)
|
||||
|
@ -372,8 +372,7 @@ pub fn (mut d Doc) generate() ? {
|
||||
}
|
||||
filename := os.base(file_path)
|
||||
d.sources[filename] = util.read_file(file_path) or { '' }
|
||||
file_asts <<
|
||||
parser.parse_file(file_path, d.table, comments_mode, d.prefs, global_scope)
|
||||
file_asts << parser.parse_file(file_path, d.table, comments_mode, d.prefs, global_scope)
|
||||
}
|
||||
return d.file_asts(file_asts)
|
||||
}
|
||||
|
259
vlib/v/fmt/fmt.v
259
vlib/v/fmt/fmt.v
@ -5,7 +5,6 @@ module fmt
|
||||
|
||||
import v.ast
|
||||
import v.table
|
||||
import v.token
|
||||
import strings
|
||||
import v.util
|
||||
|
||||
@ -15,7 +14,7 @@ const (
|
||||
'\t\t\t\t\t\t\t\t',
|
||||
]
|
||||
// when to break a line dependant on penalty
|
||||
max_len = [0, 35, 85, 93, 100]
|
||||
max_len = [0, 35, 60, 85, 93, 100]
|
||||
)
|
||||
|
||||
pub struct Fmt {
|
||||
@ -27,13 +26,10 @@ pub mut:
|
||||
indent int
|
||||
empty_line bool
|
||||
line_len int
|
||||
buffering bool // expressions will be analyzed later by adjust_complete_line() before finally written
|
||||
expr_bufs []string // and stored here in the meantime (expr_bufs.len-1 = penalties.len = precedences.len)
|
||||
penalties []int // how hard should it be to break line after each expression
|
||||
precedences []int // operator/parenthese precedences for operator at end of each expression
|
||||
par_level int // how many parentheses are put around the current expression
|
||||
array_init_break []bool // line breaks after elements in hierarchy level of multi dimensional array
|
||||
array_init_depth int // current level of hierarchie in array init
|
||||
buffering bool // disables line wrapping for exprs that will be analyzed later
|
||||
par_level int // how many parentheses are put around the current expression
|
||||
array_init_break []bool // line breaks after elements in hierarchy level of multi dimensional array
|
||||
array_init_depth int // current level of hierarchie in array init
|
||||
single_line_if bool
|
||||
cur_mod string
|
||||
file ast.File
|
||||
@ -92,43 +88,19 @@ pub fn (mut f Fmt) process_file_imports(file &ast.File) {
|
||||
}
|
||||
|
||||
pub fn (mut f Fmt) write(s string) {
|
||||
if !f.buffering {
|
||||
if f.indent > 0 && f.empty_line {
|
||||
f.write_indent()
|
||||
}
|
||||
f.out.write(s)
|
||||
f.line_len += s.len
|
||||
f.empty_line = false
|
||||
} else {
|
||||
f.out.write(s)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (mut f Fmt) writeln(s string) {
|
||||
empty_fifo := f.buffering
|
||||
if empty_fifo {
|
||||
f.write(s)
|
||||
f.expr_bufs << f.out.str()
|
||||
f.out = f.out_save
|
||||
f.adjust_complete_line()
|
||||
f.buffering = false
|
||||
for i, p in f.penalties {
|
||||
f.write(f.expr_bufs[i])
|
||||
f.wrap_long_line(p, true)
|
||||
}
|
||||
f.write(f.expr_bufs[f.expr_bufs.len - 1])
|
||||
f.expr_bufs = []string{}
|
||||
f.penalties = []int{}
|
||||
f.precedences = []int{}
|
||||
}
|
||||
if f.indent > 0 && f.empty_line {
|
||||
f.write_indent()
|
||||
}
|
||||
f.out.writeln(if empty_fifo {
|
||||
''
|
||||
} else {
|
||||
s
|
||||
})
|
||||
f.out.write(s)
|
||||
f.line_len += s.len
|
||||
f.empty_line = false
|
||||
}
|
||||
|
||||
pub fn (mut f Fmt) writeln(s string) {
|
||||
if f.indent > 0 && f.empty_line {
|
||||
f.write_indent()
|
||||
}
|
||||
f.out.writeln(s)
|
||||
f.empty_line = true
|
||||
f.line_len = 0
|
||||
}
|
||||
@ -145,52 +117,10 @@ fn (mut f Fmt) write_indent() {
|
||||
f.line_len += f.indent * 4
|
||||
}
|
||||
|
||||
// adjustments that can only be done after full line is processed. For now
|
||||
// only prevents line breaks if everything fits in max_len[last] by increasing
|
||||
// penalties to maximum
|
||||
fn (mut f Fmt) adjust_complete_line() {
|
||||
for i, buf in f.expr_bufs {
|
||||
// search for low penalties
|
||||
if i == 0 || f.penalties[i - 1] <= 1 {
|
||||
precedence := if i == 0 { -1 } else { f.precedences[i - 1] }
|
||||
mut len_sub_expr := if i == 0 { buf.len + f.line_len } else { buf.len }
|
||||
mut sub_expr_end_idx := f.penalties.len
|
||||
// search for next position with low penalty and same precedence to form subexpression
|
||||
for j in i .. f.penalties.len {
|
||||
if f.penalties[j] <= 1 &&
|
||||
f.precedences[j] == precedence && len_sub_expr >= max_len[1]
|
||||
{
|
||||
sub_expr_end_idx = j
|
||||
break
|
||||
} else if f.precedences[j] < precedence {
|
||||
// we cannot form a sensible subexpression
|
||||
len_sub_expr = C.INT32_MAX
|
||||
break
|
||||
} else {
|
||||
len_sub_expr += f.expr_bufs[j + 1].len
|
||||
}
|
||||
}
|
||||
// if subexpression would fit in single line adjust penalties to actually do so
|
||||
if len_sub_expr <= max_len[max_len.len - 1] {
|
||||
for j in i .. sub_expr_end_idx {
|
||||
f.penalties[j] = max_len.len - 1
|
||||
}
|
||||
if i > 0 {
|
||||
f.penalties[i - 1] = 0
|
||||
}
|
||||
if sub_expr_end_idx < f.penalties.len {
|
||||
f.penalties[sub_expr_end_idx] = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
// emergency fallback: decrease penalty in front of long unbreakable parts
|
||||
if i > 0 && buf.len > 55 && f.penalties[i - 1] > 0 {
|
||||
f.penalties[i - 1] = if buf.len >= 72 { 0 } else { 1 }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (mut f Fmt) wrap_long_line(penalty_idx int, add_indent bool) bool {
|
||||
if f.buffering {
|
||||
return false
|
||||
}
|
||||
if f.line_len <= max_len[penalty_idx] {
|
||||
return false
|
||||
}
|
||||
@ -493,8 +423,9 @@ pub fn (mut f Fmt) type_decl(node ast.TypeDecl) {
|
||||
}
|
||||
}
|
||||
is_last_arg := i == fn_info.params.len - 1
|
||||
should_add_type := true || is_last_arg || fn_info.params[i + 1].typ != arg.typ ||
|
||||
(fn_info.is_variadic && i == fn_info.params.len - 2)
|
||||
should_add_type := true || is_last_arg
|
||||
|| fn_info.params[i + 1].typ != arg.typ
|
||||
|| (fn_info.is_variadic && i == fn_info.params.len - 2)
|
||||
if should_add_type {
|
||||
ns := if arg.name == '' { '' } else { ' ' }
|
||||
if fn_info.is_variadic && is_last_arg {
|
||||
@ -532,7 +463,7 @@ pub fn (mut f Fmt) type_decl(node ast.TypeDecl) {
|
||||
f.write(' | ')
|
||||
}
|
||||
if i < sum_type_names.len - 1 {
|
||||
f.wrap_long_line(2, true)
|
||||
f.wrap_long_line(3, true)
|
||||
}
|
||||
}
|
||||
// f.write(sum_type_names.join(' | '))
|
||||
@ -762,7 +693,8 @@ pub fn (mut f Fmt) struct_decl(node ast.StructDecl) {
|
||||
comment_align_i++
|
||||
align = comment_aligns[comment_align_i]
|
||||
}
|
||||
pad_len := align.max_attrs_len - attrs_len + align.max_type_len - field_types[i].len
|
||||
pad_len := align.max_attrs_len - attrs_len +
|
||||
align.max_type_len - field_types[i].len
|
||||
f.write(strings.repeat(` `, pad_len))
|
||||
}
|
||||
f.write(' ')
|
||||
@ -1496,74 +1428,97 @@ pub fn (mut f Fmt) lock_expr(lex ast.LockExpr) {
|
||||
pub fn (mut f Fmt) infix_expr(node ast.InfixExpr) {
|
||||
buffering_save := f.buffering
|
||||
if !f.buffering {
|
||||
f.out_save = f.out
|
||||
f.out = strings.new_builder(60)
|
||||
f.buffering = true
|
||||
}
|
||||
infix_start := f.out.len
|
||||
start_len := f.line_len
|
||||
f.expr(node.left)
|
||||
is_one_val_array_init := node.op in [.key_in, .not_in] &&
|
||||
node.right is ast.ArrayInit && (node.right as ast.ArrayInit).exprs.len == 1
|
||||
is_one_val_array_init := node.op in [.key_in, .not_in] && node.right is ast.ArrayInit
|
||||
&& (node.right as ast.ArrayInit).exprs.len == 1
|
||||
if is_one_val_array_init {
|
||||
// `var in [val]` => `var == val`
|
||||
f.write(if node.op == .key_in {
|
||||
' == '
|
||||
} else {
|
||||
' != '
|
||||
})
|
||||
op := if node.op == .key_in { ' == ' } else { ' != ' }
|
||||
f.write(op)
|
||||
} else {
|
||||
f.write(' $node.op.str() ')
|
||||
}
|
||||
f.expr_bufs << f.out.str()
|
||||
mut penalty := 3
|
||||
match mut node.left {
|
||||
ast.InfixExpr {
|
||||
if int(token.precedences[node.left.op]) > int(token.precedences[node.op]) {
|
||||
penalty--
|
||||
}
|
||||
}
|
||||
ast.ParExpr {
|
||||
penalty = 1
|
||||
}
|
||||
else {}
|
||||
}
|
||||
match node.right {
|
||||
ast.InfixExpr { penalty-- }
|
||||
ast.ParExpr { penalty = 1 }
|
||||
else {}
|
||||
}
|
||||
f.penalties << penalty
|
||||
// combine parentheses level with operator precedence to form effective precedence
|
||||
f.precedences << int(token.precedences[node.op]) | (f.par_level << 16)
|
||||
f.out = strings.new_builder(60)
|
||||
f.buffering = true
|
||||
if is_one_val_array_init {
|
||||
// `var in [val]` => `var == val`
|
||||
f.expr((node.right as ast.ArrayInit).exprs[0])
|
||||
} else {
|
||||
f.expr(node.right)
|
||||
}
|
||||
if !buffering_save && f.buffering { // now decide if and where to break
|
||||
f.expr_bufs << f.out.str()
|
||||
f.out = f.out_save
|
||||
if !buffering_save && f.buffering {
|
||||
f.buffering = false
|
||||
f.adjust_complete_line()
|
||||
for i, p in f.penalties {
|
||||
f.write(f.expr_bufs[i])
|
||||
f.wrap_long_line(p, true)
|
||||
if !f.single_line_if && f.line_len > max_len.last() {
|
||||
f.wrap_infix(infix_start, start_len)
|
||||
}
|
||||
f.write(f.expr_bufs[f.expr_bufs.len - 1])
|
||||
f.expr_bufs = []string{}
|
||||
f.penalties = []int{}
|
||||
f.precedences = []int{}
|
||||
}
|
||||
f.or_expr(node.or_block)
|
||||
}
|
||||
|
||||
pub fn (mut f Fmt) wrap_infix(start_pos int, start_len int) {
|
||||
cut_span := f.out.len - start_pos
|
||||
condstr := f.out.cut_last(cut_span)
|
||||
is_cond_infix := condstr.contains_any_substr(['&&', '||'])
|
||||
if !is_cond_infix && !condstr.contains('+') {
|
||||
f.write(condstr)
|
||||
return
|
||||
}
|
||||
f.line_len = start_len
|
||||
if start_len == 0 {
|
||||
f.empty_line = true
|
||||
}
|
||||
or_pen := if condstr.contains('&&') { 3 } else { 5 }
|
||||
cond_parts := condstr.split(' ')
|
||||
mut grouped_cond := false
|
||||
mut conditions := ['']
|
||||
mut penalties := [5]
|
||||
mut index := 0
|
||||
for cp in cond_parts {
|
||||
if is_cond_infix && cp in ['&&', '||'] {
|
||||
if grouped_cond {
|
||||
conditions[index] += '$cp '
|
||||
} else {
|
||||
p := if cp == '||' { or_pen } else { 5 }
|
||||
penalties << p
|
||||
conditions << '$cp '
|
||||
index++
|
||||
}
|
||||
} else if !is_cond_infix && cp == '+' {
|
||||
penalties << 5
|
||||
conditions[index] += '$cp '
|
||||
conditions << ''
|
||||
index++
|
||||
} else {
|
||||
conditions[index] += '$cp '
|
||||
if cp.starts_with('(') {
|
||||
grouped_cond = true
|
||||
} else if cp.ends_with(')') {
|
||||
grouped_cond = false
|
||||
}
|
||||
}
|
||||
}
|
||||
for i, c in conditions {
|
||||
cnd := c.trim_space()
|
||||
if f.line_len + cnd.len < max_len[penalties[i]] {
|
||||
if i > 0 && (!is_cond_infix || i < conditions.len - 1) {
|
||||
f.write(' ')
|
||||
}
|
||||
f.write(cnd)
|
||||
} else {
|
||||
f.writeln('')
|
||||
f.indent++
|
||||
f.write(cnd)
|
||||
f.indent--
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (mut f Fmt) if_expr(it ast.IfExpr) {
|
||||
dollar := if it.is_comptime { '$' } else { '' }
|
||||
mut single_line := it.branches.len == 2 && it.has_else && branch_is_single_line(it.branches[0]) &&
|
||||
branch_is_single_line(it.branches[1]) &&
|
||||
(it.is_expr || f.is_assign)
|
||||
mut single_line := it.branches.len == 2 && it.has_else && branch_is_single_line(it.branches[0])
|
||||
&& branch_is_single_line(it.branches[1])&& (it.is_expr || f.is_assign)
|
||||
f.single_line_if = single_line
|
||||
if_start := f.line_len
|
||||
for {
|
||||
@ -1583,15 +1538,8 @@ pub fn (mut f Fmt) if_expr(it ast.IfExpr) {
|
||||
}
|
||||
if i < it.branches.len - 1 || !it.has_else {
|
||||
f.write('${dollar}if ')
|
||||
cur_pos := f.out.len
|
||||
f.expr(branch.cond)
|
||||
cond_len := f.out.len - cur_pos
|
||||
is_cond_wrapped := if cond_len > 0 { '\n' in f.out.last_n(cond_len) } else { false }
|
||||
if is_cond_wrapped {
|
||||
f.writeln('')
|
||||
} else {
|
||||
f.write(' ')
|
||||
}
|
||||
f.write(' ')
|
||||
}
|
||||
f.write('{')
|
||||
if single_line {
|
||||
@ -1654,7 +1602,7 @@ pub fn (mut f Fmt) call_args(args []ast.CallArg) {
|
||||
f.write(arg.share.str() + ' ')
|
||||
}
|
||||
if i > 0 {
|
||||
f.wrap_long_line(2, true)
|
||||
f.wrap_long_line(3, true)
|
||||
}
|
||||
f.expr(arg.expr)
|
||||
if i < args.len - 1 {
|
||||
@ -1790,7 +1738,7 @@ pub fn (mut f Fmt) match_expr(it ast.MatchExpr) {
|
||||
if j < branch.exprs.len - 1 {
|
||||
f.write(', ')
|
||||
}
|
||||
f.wrap_long_line(3, false)
|
||||
f.wrap_long_line(4, false)
|
||||
}
|
||||
f.is_mbranch_expr = false
|
||||
} else {
|
||||
@ -1900,10 +1848,10 @@ pub fn (mut f Fmt) array_init(it ast.ArrayInit) {
|
||||
f.array_init_break << (last_line_nr < line_nr)
|
||||
}
|
||||
}
|
||||
is_same_line_comment := i > 0 &&
|
||||
(expr is ast.Comment && line_nr == it.exprs[i - 1].position().line_nr)
|
||||
is_same_line_comment := i > 0
|
||||
&& (expr is ast.Comment && line_nr == it.exprs[i - 1].position().line_nr)
|
||||
line_break := f.array_init_break[f.array_init_depth - 1]
|
||||
mut penalty := if line_break && !is_same_line_comment { 0 } else { 3 }
|
||||
mut penalty := if line_break && !is_same_line_comment { 0 } else { 4 }
|
||||
if penalty > 0 {
|
||||
if i == 0 || should_decrease_arr_penalty(it.exprs[i - 1]) {
|
||||
penalty--
|
||||
@ -2066,10 +2014,9 @@ pub fn (mut f Fmt) struct_init(it ast.StructInit) {
|
||||
f.writeln('')
|
||||
}
|
||||
f.comments(field.next_comments, inline: false, has_nl: true, level: .keep)
|
||||
if single_line_fields &&
|
||||
(field.comments.len > 0 ||
|
||||
field.next_comments.len > 0 || !expr_is_single_line(field.expr) || f.line_len > max_len.last())
|
||||
{
|
||||
if single_line_fields
|
||||
&& (field.comments.len > 0 || field.next_comments.len > 0 || !expr_is_single_line(field.expr)
|
||||
|| f.line_len > max_len.last()) {
|
||||
single_line_fields = false
|
||||
f.out.go_back_to(fields_start)
|
||||
f.line_len = fields_start
|
||||
@ -2389,7 +2336,7 @@ pub fn (mut f Fmt) sql_stmt(node ast.SqlStmt) {
|
||||
} else {
|
||||
f.write(' ')
|
||||
}
|
||||
f.wrap_long_line(2, true)
|
||||
f.wrap_long_line(3, true)
|
||||
}
|
||||
f.write('where ')
|
||||
f.expr(node.where_expr)
|
||||
|
@ -1,6 +1,17 @@
|
||||
fn concatenation_of_strings() {
|
||||
_ := 'Simple' + 'Concat'
|
||||
_ := 'Hello' + ' ' + 'World' + '!'
|
||||
_ := 'There' + ' ' + 'so' + ' ' + 'many' + ' ' + 'words' + ' ' + 'they' + ' ' + "don't" +
|
||||
' ' + 'fit' + ' ' + 'in' + ' ' + 'one' + ' ' + 'line'
|
||||
_ := 'There' + ' ' + 'so' + ' ' + 'many' + ' ' + 'words' + ' ' + 'they' + ' ' + "don't" + ' ' +
|
||||
'fit' + ' ' + 'in' + ' ' + 'one' + ' ' + 'line'
|
||||
}
|
||||
|
||||
fn concat_inside_ternary() {
|
||||
{ // This block is needed to force line wrapping
|
||||
cline := if iline == pos.line_nr {
|
||||
sline[..start_column] + color(kind, sline[start_column..end_column]) +
|
||||
sline[end_column..]
|
||||
} else {
|
||||
sline
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,3 +5,13 @@ _ := 'Simple' + 'Concat'
|
||||
'World' + '!'
|
||||
_ := 'There' + ' ' + 'so' + ' ' + 'many' + ' ' + 'words' + ' ' + 'they' + ' ' + "don't" + ' ' + 'fit' + ' ' + 'in' + ' ' + 'one' + ' ' + 'line'
|
||||
}
|
||||
|
||||
fn concat_inside_ternary() {
|
||||
{ // This block is needed to force line wrapping
|
||||
cline := if iline == pos.line_nr {
|
||||
sline[..start_column] + color(kind, sline[start_column..end_column]) + sline[end_column..]
|
||||
} else {
|
||||
sline
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,9 +11,7 @@ fn string_inter_lit(mut c checker.Checker, mut node ast.StringInterLiteral) tabl
|
||||
typ := c.table.unalias_num_type(ftyp)
|
||||
mut fmt := node.fmts[i]
|
||||
// analyze and validate format specifier
|
||||
if fmt !in
|
||||
[`E`, `F`, `G`, `e`, `f`, `g`, `d`, `u`, `x`, `X`, `o`, `c`, `s`, `p`, `_`]
|
||||
{
|
||||
if fmt !in [`E`, `F`, `G`, `e`, `f`, `g`, `d`, `u`, `x`, `X`, `o`, `c`, `s`, `p`, `_`] {
|
||||
c.error('unknown format specifier `${fmt:c}`', node.fmt_poss[i])
|
||||
}
|
||||
if node.precisions[i] != 987698 && !typ.is_float() {
|
||||
@ -22,14 +20,13 @@ fn string_inter_lit(mut c checker.Checker, mut node ast.StringInterLiteral) tabl
|
||||
if node.pluss[i] && !typ.is_number() {
|
||||
c.error('plus prefix only allowd for numbers', node.fmt_poss[i])
|
||||
}
|
||||
if (typ.is_unsigned() && fmt !in [`u`, `x`, `X`, `o`, `c`]) ||
|
||||
(typ.is_signed() && fmt !in [`d`, `x`, `X`, `o`, `c`]) ||
|
||||
(typ.is_int_literal() && fmt !in [`d`, `c`, `x`, `X`, `o`, `u`, `x`, `X`, `o`]) ||
|
||||
(typ.is_float() && fmt !in [`E`, `F`, `G`, `e`, `f`, `g`]) ||
|
||||
(typ.is_pointer() && fmt !in [`p`, `x`, `X`]) ||
|
||||
(typ.is_string() && fmt != `s`) ||
|
||||
(typ.idx() in [table.i64_type_idx, table.f64_type_idx] && fmt == `c`)
|
||||
{
|
||||
if (typ.is_unsigned() && fmt !in [`u`, `x`, `X`, `o`, `c`])
|
||||
|| (typ.is_signed() && fmt !in [`d`, `x`, `X`, `o`, `c`])
|
||||
|| (typ.is_int_literal() && fmt !in [`d`, `c`, `x`, `X`, `o`, `u`, `x`, `X`, `o`])
|
||||
|| (typ.is_float() && fmt !in [`E`, `F`, `G`, `e`, `f`, `g`])
|
||||
|| (typ.is_pointer() && fmt !in [`p`, `x`, `X`])
|
||||
|| (typ.is_string() && fmt != `s`)
|
||||
|| (typ.idx() in [table.i64_type_idx, table.f64_type_idx] && fmt == `c`) {
|
||||
c.error('illegal format specifier `${fmt:c}` for type `${c.table.get_type_name(ftyp)}`',
|
||||
node.fmt_poss[i])
|
||||
}
|
||||
@ -40,8 +37,8 @@ fn string_inter_lit(mut c checker.Checker, mut node ast.StringInterLiteral) tabl
|
||||
}
|
||||
|
||||
fn get_some_val(a_test f64, b_test f64, c_test f64, d_test f64, e_test f64, f_test f64) f64 {
|
||||
return a_test * b_test * c_test * d_test +
|
||||
e_test * f_test * a_test * d_test + a_test * b_test * c_test
|
||||
return a_test * b_test * c_test * d_test + e_test * f_test * a_test * d_test +
|
||||
a_test * b_test * c_test
|
||||
}
|
||||
|
||||
fn main() {
|
||||
@ -55,10 +52,8 @@ fn main() {
|
||||
println(s)
|
||||
println('this is quite a long string' +
|
||||
' that is followd by an even longer part that should go to another line')
|
||||
if (a == b && b > r) ||
|
||||
(d > r) || (a < b) || (b < d && a + b > r) ||
|
||||
(a + b + d >= 0 && r < 0) || (a > b && d - r < b)
|
||||
{
|
||||
if (a == b && b > r) || (d > r) || (a < b) || (b < d && a + b > r)
|
||||
|| (a + b + d >= 0 && r < 0)|| (a > b && d - r < b) {
|
||||
println('ok')
|
||||
}
|
||||
}
|
||||
@ -76,9 +71,8 @@ struct Parser {
|
||||
}
|
||||
|
||||
fn (mut p Parser) name_expr() {
|
||||
if p.peek_tok.kind == .lpar ||
|
||||
(p.peek_tok.kind == .lt && p.peek_tok2.kind == .name && p.peek_tok3.kind == .gt)
|
||||
{
|
||||
if p.peek_tok.kind == .lpar
|
||||
|| (p.peek_tok.kind == .lt && p.peek_tok2.kind == .name && p.peek_tok3.kind == .gt) {
|
||||
println(p.peek_tok.lit)
|
||||
}
|
||||
}
|
||||
|
@ -108,8 +108,7 @@ fn test_select_blocks() {
|
||||
else {
|
||||
h = 2
|
||||
}
|
||||
}
|
||||
{
|
||||
} {
|
||||
panic('channel is still open')
|
||||
} else {
|
||||
is_open = false
|
||||
|
@ -40,9 +40,7 @@ fn (g &Gen) type_to_fmt(typ table.Type) string {
|
||||
sym := g.table.get_type_symbol(typ)
|
||||
if typ.is_ptr() && (typ.is_int() || typ.is_float()) {
|
||||
return '%.*s\\000'
|
||||
} else if sym.kind in
|
||||
[.struct_, .array, .array_fixed, .map, .bool, .enum_, .interface_, .sum_type, .function]
|
||||
{
|
||||
} else if sym.kind in [.struct_, .array, .array_fixed, .map, .bool, .enum_, .interface_, .sum_type, .function] {
|
||||
return '%.*s\\000'
|
||||
} else if sym.kind == .string {
|
||||
return "'%.*s\\000'"
|
||||
@ -184,8 +182,11 @@ fn (mut g Gen) gen_str_for_array(info table.Array, styp string, str_fn_name stri
|
||||
sym_has_str_method, str_method_expects_ptr, _ := sym.str_method_info()
|
||||
mut elem_str_fn_name := ''
|
||||
if sym_has_str_method {
|
||||
elem_str_fn_name = if is_elem_ptr { field_styp.replace('*', '') + '_str' } else { field_styp +
|
||||
'_str' }
|
||||
elem_str_fn_name = if is_elem_ptr {
|
||||
field_styp.replace('*', '') + '_str'
|
||||
} else {
|
||||
field_styp + '_str'
|
||||
}
|
||||
if sym.kind == .byte {
|
||||
elem_str_fn_name = elem_str_fn_name + '_escaped'
|
||||
}
|
||||
@ -263,8 +264,11 @@ fn (mut g Gen) gen_str_for_array_fixed(info table.ArrayFixed, styp string, str_f
|
||||
sym_has_str_method, str_method_expects_ptr, _ := sym.str_method_info()
|
||||
mut elem_str_fn_name := ''
|
||||
if sym_has_str_method {
|
||||
elem_str_fn_name = if is_elem_ptr { field_styp.replace('*', '') + '_str' } else { field_styp +
|
||||
'_str' }
|
||||
elem_str_fn_name = if is_elem_ptr {
|
||||
field_styp.replace('*', '') + '_str'
|
||||
} else {
|
||||
field_styp + '_str'
|
||||
}
|
||||
} else {
|
||||
elem_str_fn_name = styp_to_str_fn_name(field_styp)
|
||||
}
|
||||
@ -382,8 +386,11 @@ fn (mut g Gen) gen_str_for_multi_return(info table.MultiReturn, styp string, str
|
||||
sym_has_str_method, str_method_expects_ptr, _ := sym.str_method_info()
|
||||
mut arg_str_fn_name := ''
|
||||
if sym_has_str_method {
|
||||
arg_str_fn_name = if is_arg_ptr { field_styp.replace('*', '') + '_str' } else { field_styp +
|
||||
'_str' }
|
||||
arg_str_fn_name = if is_arg_ptr {
|
||||
field_styp.replace('*', '') + '_str'
|
||||
} else {
|
||||
field_styp + '_str'
|
||||
}
|
||||
} else {
|
||||
arg_str_fn_name = styp_to_str_fn_name(field_styp)
|
||||
}
|
||||
@ -440,8 +447,8 @@ fn (mut g Gen) gen_str_for_struct(info table.Struct, styp string, str_fn_name st
|
||||
if clean_struct_v_type_name.contains('_T_') {
|
||||
// TODO: this is a bit hacky. styp shouldn't be even parsed with _T_
|
||||
// use something different than g.typ for styp
|
||||
clean_struct_v_type_name = clean_struct_v_type_name.replace('_T_', '<').replace('_', ', ') +
|
||||
'>'
|
||||
clean_struct_v_type_name =
|
||||
clean_struct_v_type_name.replace('_T_', '<').replace('_', ', ') + '>'
|
||||
}
|
||||
clean_struct_v_type_name = util.strip_main_name(clean_struct_v_type_name)
|
||||
// generate ident / indent length = 4 spaces
|
||||
|
@ -155,10 +155,8 @@ pub fn cgen(files []ast.File, table &table.Table, pref &pref.Preferences) string
|
||||
mut module_built := ''
|
||||
if pref.build_mode == .build_module {
|
||||
for file in files {
|
||||
if pref.path in file.path &&
|
||||
file.mod.short_name ==
|
||||
pref.path.all_after_last(os.path_separator).trim_right(os.path_separator)
|
||||
{
|
||||
if pref.path in file.path
|
||||
&& file.mod.short_name == pref.path.all_after_last(os.path_separator).trim_right(os.path_separator) {
|
||||
module_built = file.mod.name
|
||||
break
|
||||
}
|
||||
@ -408,8 +406,10 @@ pub fn (mut g Gen) init() {
|
||||
}
|
||||
if g.pref.compile_defines_all.len > 0 {
|
||||
g.comptime_defines.writeln('// V compile time defines by -d or -define flags:')
|
||||
g.comptime_defines.writeln('// All custom defines : ' + g.pref.compile_defines_all.join(','))
|
||||
g.comptime_defines.writeln('// Turned ON custom defines: ' + g.pref.compile_defines.join(','))
|
||||
g.comptime_defines.writeln('// All custom defines : ' +
|
||||
g.pref.compile_defines_all.join(','))
|
||||
g.comptime_defines.writeln('// Turned ON custom defines: ' +
|
||||
g.pref.compile_defines.join(','))
|
||||
for cdefine in g.pref.compile_defines {
|
||||
g.comptime_defines.writeln('#define CUSTOM_DEFINE_$cdefine')
|
||||
}
|
||||
@ -1012,10 +1012,8 @@ fn (mut g Gen) stmt(node ast.Stmt) {
|
||||
// TODO true for not just "builtin"
|
||||
// TODO: clean this up
|
||||
mod := if g.is_builtin_mod { 'builtin' } else { node.name.all_before_last('.') }
|
||||
if (mod != g.module_built &&
|
||||
node.mod != g.module_built.after('/')) ||
|
||||
should_bundle_module
|
||||
{
|
||||
if (mod != g.module_built && node.mod != g.module_built.after('/'))
|
||||
|| should_bundle_module {
|
||||
// Skip functions that don't have to be generated for this module.
|
||||
// println('skip bm $node.name mod=$node.mod module_built=$g.module_built')
|
||||
skip = true
|
||||
@ -1030,10 +1028,8 @@ fn (mut g Gen) stmt(node ast.Stmt) {
|
||||
if g.pref.use_cache {
|
||||
// We are using prebuilt modules, we do not need to generate
|
||||
// their functions in main.c.
|
||||
if node.mod != 'main' &&
|
||||
node.mod != 'help' && !should_bundle_module && !g.file.path.ends_with('_test.v') &&
|
||||
node.generic_params.len == 0
|
||||
{
|
||||
if node.mod != 'main' && node.mod != 'help' && !should_bundle_module
|
||||
&& !g.file.path.ends_with('_test.v')&& node.generic_params.len == 0 {
|
||||
skip = true
|
||||
}
|
||||
}
|
||||
@ -1042,15 +1038,13 @@ fn (mut g Gen) stmt(node ast.Stmt) {
|
||||
if node.name == 'main.main' {
|
||||
g.has_main = true
|
||||
}
|
||||
if node.name == 'backtrace' ||
|
||||
node.name == 'backtrace_symbols' || node.name == 'backtrace_symbols_fd'
|
||||
{
|
||||
if node.name == 'backtrace' || node.name == 'backtrace_symbols'
|
||||
|| node.name == 'backtrace_symbols_fd' {
|
||||
g.write('\n#ifndef __cplusplus\n')
|
||||
}
|
||||
g.gen_fn_decl(node, skip)
|
||||
if node.name == 'backtrace' ||
|
||||
node.name == 'backtrace_symbols' || node.name == 'backtrace_symbols_fd'
|
||||
{
|
||||
if node.name == 'backtrace' || node.name == 'backtrace_symbols'
|
||||
|| node.name == 'backtrace_symbols_fd' {
|
||||
g.write('\n#endif\n')
|
||||
}
|
||||
g.fn_decl = keep_fn_decl
|
||||
@ -1504,7 +1498,8 @@ fn (mut g Gen) expr_with_cast(expr ast.Expr, got_type_raw table.Type, expected_t
|
||||
got_is_ptr := got_type.is_ptr()
|
||||
expected_is_ptr := expected_type.is_ptr()
|
||||
neither_void := table.voidptr_type !in [got_type, expected_type]
|
||||
if got_is_ptr && !expected_is_ptr && neither_void && expected_sym.kind !in [.interface_, .placeholder] {
|
||||
if got_is_ptr && !expected_is_ptr && neither_void
|
||||
&& expected_sym.kind !in [.interface_, .placeholder] {
|
||||
got_deref_type := got_type.deref()
|
||||
deref_sym := g.table.get_type_symbol(got_deref_type)
|
||||
deref_will_match := expected_type in [got_type, got_deref_type, deref_sym.parent_idx]
|
||||
@ -1671,9 +1666,9 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
|
||||
}
|
||||
// Free the old value assigned to this string var (only if it's `str = [new value]`
|
||||
// or `x.str = [new value]` )
|
||||
mut af := g.is_autofree && !g.is_builtin_mod && assign_stmt.op == .assign && assign_stmt.left_types.len ==
|
||||
1 &&
|
||||
(assign_stmt.left[0] is ast.Ident || assign_stmt.left[0] is ast.SelectorExpr)
|
||||
mut af := g.is_autofree && !g.is_builtin_mod && assign_stmt.op == .assign
|
||||
&& assign_stmt.left_types.len == 1
|
||||
&& (assign_stmt.left[0] is ast.Ident || assign_stmt.left[0] is ast.SelectorExpr)
|
||||
// assign_stmt.left_types[0] in [table.string_type, table.array_type] &&
|
||||
mut sref_name := ''
|
||||
mut type_to_free := ''
|
||||
@ -1728,9 +1723,8 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
|
||||
// }
|
||||
// int pos = *(int*)_t190.data;
|
||||
mut tmp_opt := ''
|
||||
is_optional := g.is_autofree &&
|
||||
(assign_stmt.op in [.decl_assign, .assign]) && assign_stmt.left_types.len == 1 &&
|
||||
assign_stmt.right[0] is ast.CallExpr
|
||||
is_optional := g.is_autofree && (assign_stmt.op in [.decl_assign, .assign])
|
||||
&& assign_stmt.left_types.len == 1&& assign_stmt.right[0] is ast.CallExpr
|
||||
if is_optional {
|
||||
// g.write('/* optional assignment */')
|
||||
call_expr := assign_stmt.right[0] as ast.CallExpr
|
||||
@ -2035,12 +2029,9 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
|
||||
str_add = true
|
||||
}
|
||||
// Assignment Operator Overloading
|
||||
if ((left_sym.kind == .struct_ &&
|
||||
right_sym.kind == .struct_) ||
|
||||
(left_sym.kind == .alias &&
|
||||
right_sym.kind == .alias)) &&
|
||||
assign_stmt.op in [.plus_assign, .minus_assign, .div_assign, .mult_assign, .mod_assign]
|
||||
{
|
||||
if ((left_sym.kind == .struct_ && right_sym.kind == .struct_)
|
||||
|| (left_sym.kind == .alias && right_sym.kind == .alias))
|
||||
&& assign_stmt.op in [.plus_assign, .minus_assign, .div_assign, .mult_assign, .mod_assign] {
|
||||
extracted_op := match assign_stmt.op {
|
||||
.plus_assign { '+' }
|
||||
.minus_assign { '-' }
|
||||
@ -2075,7 +2066,8 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
|
||||
g.prevent_sum_type_unwrapping_once = true
|
||||
}
|
||||
if !is_fixed_array_copy || is_decl {
|
||||
if !is_decl && left is ast.Ident && g.for_in_mul_val_name == (left as ast.Ident).name {
|
||||
if !is_decl && left is ast.Ident
|
||||
&& g.for_in_mul_val_name == (left as ast.Ident).name {
|
||||
g.write('*')
|
||||
}
|
||||
g.expr(left)
|
||||
@ -2375,9 +2367,8 @@ fn (mut g Gen) autofree_scope_vars2(scope &ast.Scope, start_pos int, end_pos int
|
||||
// }
|
||||
// ```
|
||||
// if !isnil(scope.parent) && line_nr > 0 {
|
||||
if free_parent_scopes && !isnil(scope.parent) &&
|
||||
(stop_pos == -1 || scope.parent.start_pos >= stop_pos)
|
||||
{
|
||||
if free_parent_scopes && !isnil(scope.parent)
|
||||
&& (stop_pos == -1 || scope.parent.start_pos >= stop_pos) {
|
||||
g.writeln('// af parent scope:')
|
||||
g.autofree_scope_vars2(scope.parent, start_pos, end_pos, line_nr, true, stop_pos)
|
||||
}
|
||||
@ -2535,9 +2526,8 @@ fn (mut g Gen) expr(node ast.Expr) {
|
||||
// if g.fileis('1.strings') {
|
||||
// println('before:' + node.autofree_pregen)
|
||||
// }
|
||||
if g.is_autofree && !g.is_builtin_mod && !g.is_js_call && g.strs_to_free0.len == 0 &&
|
||||
!g.inside_lambda
|
||||
{ // && g.inside_ternary ==
|
||||
if g.is_autofree && !g.is_builtin_mod && !g.is_js_call && g.strs_to_free0.len == 0
|
||||
&& !g.inside_lambda { // && g.inside_ternary ==
|
||||
// if len != 0, that means we are handling call expr inside call expr (arg)
|
||||
// and it'll get messed up here, since it's handled recursively in autofree_call_pregen()
|
||||
// so just skip it
|
||||
@ -2594,7 +2584,8 @@ fn (mut g Gen) expr(node ast.Expr) {
|
||||
g.write(')')
|
||||
} else if sym.kind == .sum_type {
|
||||
g.expr_with_cast(node.expr, node.expr_type, node.typ)
|
||||
} else if sym.kind == .struct_ && !node.typ.is_ptr() && !(sym.info as table.Struct).is_typedef {
|
||||
} else if sym.kind == .struct_ && !node.typ.is_ptr()
|
||||
&& !(sym.info as table.Struct).is_typedef {
|
||||
styp := g.typ(node.typ)
|
||||
g.write('*(($styp *)(&')
|
||||
g.expr(node.expr)
|
||||
@ -2603,16 +2594,14 @@ fn (mut g Gen) expr(node ast.Expr) {
|
||||
styp := g.typ(node.typ)
|
||||
mut cast_label := ''
|
||||
// `table.string_type` is done for MSVC's bug
|
||||
if sym.kind != .alias ||
|
||||
(sym.info as table.Alias).parent_type !in [node.expr_type, table.string_type]
|
||||
{
|
||||
if sym.kind != .alias
|
||||
|| (sym.info as table.Alias).parent_type !in [node.expr_type, table.string_type] {
|
||||
cast_label = '($styp)'
|
||||
}
|
||||
g.write('(${cast_label}(')
|
||||
g.expr(node.expr)
|
||||
if node.expr is ast.IntegerLiteral &&
|
||||
node.typ in [table.u64_type, table.u32_type, table.u16_type]
|
||||
{
|
||||
if node.expr is ast.IntegerLiteral
|
||||
&& node.typ in [table.u64_type, table.u32_type, table.u16_type] {
|
||||
g.write('U')
|
||||
}
|
||||
g.write('))')
|
||||
@ -3086,9 +3075,8 @@ fn (mut g Gen) infix_expr(node ast.InfixExpr) {
|
||||
g.write(')')
|
||||
} else if unaliased_left == table.string_type_idx && node.op !in [.key_in, .not_in] {
|
||||
// `str == ''` -> `str.len == 0` optimization
|
||||
if node.op in [.eq, .ne] &&
|
||||
node.right is ast.StringLiteral && (node.right as ast.StringLiteral).val == ''
|
||||
{
|
||||
if node.op in [.eq, .ne] && node.right is ast.StringLiteral
|
||||
&& (node.right as ast.StringLiteral).val == '' {
|
||||
arrow := if left_type.is_ptr() { '->' } else { '.' }
|
||||
g.write('(')
|
||||
g.expr(node.left)
|
||||
@ -3144,9 +3132,8 @@ fn (mut g Gen) infix_expr(node ast.InfixExpr) {
|
||||
}
|
||||
g.expr(node.right)
|
||||
g.write(')')
|
||||
} else if node.op in [.eq, .ne] &&
|
||||
left_sym.kind == .array_fixed && right_sym.kind == .array_fixed
|
||||
{
|
||||
} else if node.op in [.eq, .ne] && left_sym.kind == .array_fixed
|
||||
&& right_sym.kind == .array_fixed {
|
||||
ptr_typ := g.gen_fixed_array_equality_fn(left_type)
|
||||
if node.op == .ne {
|
||||
g.write('!')
|
||||
@ -3184,9 +3171,8 @@ fn (mut g Gen) infix_expr(node ast.InfixExpr) {
|
||||
}
|
||||
g.expr(node.right)
|
||||
g.write(')')
|
||||
} else if node.op in [.eq, .ne] &&
|
||||
left_sym.kind == .struct_ && right_sym.kind == .struct_ && has_eq_overloaded && has_ne_overloaded
|
||||
{
|
||||
} else if node.op in [.eq, .ne] && left_sym.kind == .struct_ && right_sym.kind == .struct_
|
||||
&& has_eq_overloaded&& has_ne_overloaded {
|
||||
ptr_typ := g.gen_struct_equality_fn(left_type)
|
||||
if node.op == .eq {
|
||||
g.write('${ptr_typ}_struct_eq(')
|
||||
@ -3327,41 +3313,45 @@ fn (mut g Gen) infix_expr(node ast.InfixExpr) {
|
||||
if gen_or {
|
||||
g.or_block(tmp_opt, node.or_block, table.void_type)
|
||||
}
|
||||
} else if unaliased_left.idx() in [table.u32_type_idx, table.u64_type_idx] && unaliased_right.is_signed() &&
|
||||
node.op in [.eq, .ne, .gt, .lt, .ge, .le]
|
||||
{
|
||||
bitsize := if unaliased_left.idx() == table.u32_type_idx &&
|
||||
unaliased_right.idx() != table.i64_type_idx
|
||||
{ 32 } else { 64 }
|
||||
} else if unaliased_left.idx() in [table.u32_type_idx, table.u64_type_idx]
|
||||
&& unaliased_right.is_signed()&& node.op in [.eq, .ne, .gt, .lt, .ge, .le] {
|
||||
bitsize := if unaliased_left.idx() == table.u32_type_idx
|
||||
&& unaliased_right.idx() != table.i64_type_idx {
|
||||
32
|
||||
} else {
|
||||
64
|
||||
}
|
||||
g.write('_us${bitsize}_${cmp_str[int(node.op) - int(token.Kind.eq)]}(')
|
||||
g.expr(node.left)
|
||||
g.write(',')
|
||||
g.expr(node.right)
|
||||
g.write(')')
|
||||
} else if unaliased_right.idx() in [table.u32_type_idx, table.u64_type_idx] && unaliased_left.is_signed() &&
|
||||
node.op in [.eq, .ne, .gt, .lt, .ge, .le]
|
||||
{
|
||||
bitsize := if unaliased_right.idx() == table.u32_type_idx &&
|
||||
unaliased_left.idx() != table.i64_type_idx
|
||||
{ 32 } else { 64 }
|
||||
} else if unaliased_right.idx() in [table.u32_type_idx, table.u64_type_idx]
|
||||
&& unaliased_left.is_signed()&& node.op in [.eq, .ne, .gt, .lt, .ge, .le] {
|
||||
bitsize := if unaliased_right.idx() == table.u32_type_idx
|
||||
&& unaliased_left.idx() != table.i64_type_idx {
|
||||
32
|
||||
} else {
|
||||
64
|
||||
}
|
||||
g.write('_us${bitsize}_${cmp_rev[int(node.op) - int(token.Kind.eq)]}(')
|
||||
g.expr(node.right)
|
||||
g.write(',')
|
||||
g.expr(node.left)
|
||||
g.write(')')
|
||||
} else {
|
||||
a := (left_sym.name[0].is_capital() || left_sym.name.contains('.')) &&
|
||||
left_sym.kind !in [.enum_, .function, .interface_, .sum_type] && left_sym.language != .c
|
||||
a := (left_sym.name[0].is_capital() || left_sym.name.contains('.'))
|
||||
&& left_sym.kind !in [.enum_, .function, .interface_, .sum_type]
|
||||
&& left_sym.language != .c
|
||||
b := left_sym.kind != .alias
|
||||
c := left_sym.kind == .alias && (left_sym.info as table.Alias).language == .c
|
||||
// Check if aliased type is a struct
|
||||
d := !b &&
|
||||
g.typ((left_sym.info as table.Alias).parent_type).split('__').last()[0].is_capital()
|
||||
d := !b
|
||||
&& g.typ((left_sym.info as table.Alias).parent_type).split('__').last()[0].is_capital()
|
||||
// Do not generate operator overloading with these `right_sym.kind`.
|
||||
e := right_sym.kind !in [.voidptr, .int_literal, .int]
|
||||
if node.op in [.plus, .minus, .mul, .div, .mod, .lt, .gt, .eq, .ne, .le, .ge] &&
|
||||
((a && b && e) || c || d)
|
||||
{
|
||||
if node.op in [.plus, .minus, .mul, .div, .mod, .lt, .gt, .eq, .ne, .le, .ge]
|
||||
&& ((a && b && e) || c|| d) {
|
||||
// Overloaded operators
|
||||
g.write(g.typ(if !d {
|
||||
left_type
|
||||
@ -3565,9 +3555,8 @@ fn (mut g Gen) match_expr_classic(node ast.MatchExpr, is_expr bool, cond_var str
|
||||
// if type is unsigned and low is 0, check is unneeded
|
||||
mut skip_low := false
|
||||
if expr.low is ast.IntegerLiteral {
|
||||
if node.cond_type in [table.u16_type, table.u32_type, table.u64_type] &&
|
||||
expr.low.val == '0'
|
||||
{
|
||||
if node.cond_type in [table.u16_type, table.u32_type, table.u64_type]
|
||||
&& expr.low.val == '0' {
|
||||
skip_low = true
|
||||
}
|
||||
}
|
||||
@ -3633,10 +3622,8 @@ fn (mut g Gen) select_expr(node ast.SelectExpr) {
|
||||
// send expression
|
||||
expr := branch.stmt.expr as ast.InfixExpr
|
||||
channels << expr.left
|
||||
if expr.right is ast.Ident ||
|
||||
expr.right is ast.IndexExpr || expr.right is ast.SelectorExpr || expr.right is
|
||||
ast.StructInit
|
||||
{
|
||||
if expr.right is ast.Ident || expr.right is ast.IndexExpr
|
||||
|| expr.right is ast.SelectorExpr|| expr.right is ast.StructInit {
|
||||
// addressable objects in the `C` output
|
||||
objs << expr.right
|
||||
tmp_objs << ''
|
||||
@ -3656,9 +3643,8 @@ fn (mut g Gen) select_expr(node ast.SelectExpr) {
|
||||
channels << rec_expr.right
|
||||
is_push << false
|
||||
// create tmp unless the object with *exactly* the type we need exists already
|
||||
if branch.stmt.op == .decl_assign ||
|
||||
branch.stmt.right_types[0] != branch.stmt.left_types[0]
|
||||
{
|
||||
if branch.stmt.op == .decl_assign
|
||||
|| branch.stmt.right_types[0] != branch.stmt.left_types[0] {
|
||||
tmp_obj := g.new_tmp_var()
|
||||
tmp_objs << tmp_obj
|
||||
el_stype := g.typ(branch.stmt.right_types[0])
|
||||
@ -3850,11 +3836,8 @@ fn (mut g Gen) if_expr(node ast.IfExpr) {
|
||||
// (as it used to be done).
|
||||
// Always use this in -autofree, since ?: can have tmp expressions that have to be freed.
|
||||
first_branch := node.branches[0]
|
||||
needs_tmp_var := node.is_expr &&
|
||||
(g.is_autofree || (g.pref.experimental &&
|
||||
(first_branch.stmts.len > 1 ||
|
||||
(first_branch.stmts[0] is ast.ExprStmt &&
|
||||
(first_branch.stmts[0] as ast.ExprStmt).expr is ast.IfExpr))))
|
||||
needs_tmp_var := node.is_expr
|
||||
&& (g.is_autofree || (g.pref.experimental && (first_branch.stmts.len > 1 || (first_branch.stmts[0] is ast.ExprStmt && (first_branch.stmts[0] as ast.ExprStmt).expr is ast.IfExpr))))
|
||||
/*
|
||||
needs_tmp_var := node.is_expr &&
|
||||
(g.autofree || g.pref.experimental) &&
|
||||
@ -4108,8 +4091,8 @@ fn (mut g Gen) index_expr(node ast.IndexExpr) {
|
||||
.function { 'voidptr*' }
|
||||
else { '$elem_type_str*' }
|
||||
}
|
||||
needs_clone := info.elem_type == table.string_type_idx && g.is_autofree &&
|
||||
!g.is_assign_lhs
|
||||
needs_clone := info.elem_type == table.string_type_idx && g.is_autofree
|
||||
&& !g.is_assign_lhs
|
||||
is_gen_or_and_assign_rhs := gen_or && g.is_assign_rhs
|
||||
cur_line := if is_gen_or_and_assign_rhs {
|
||||
line := g.go_before_stmt(0)
|
||||
@ -4228,9 +4211,9 @@ fn (mut g Gen) index_expr(node ast.IndexExpr) {
|
||||
zero := g.type_default(info.value_type)
|
||||
g.write('$zero })))')
|
||||
}
|
||||
} else if g.inside_map_postfix || g.inside_map_infix || g.inside_map_index ||
|
||||
(g.is_assign_lhs && !g.is_array_set && get_and_set_types)
|
||||
{
|
||||
} else if g.inside_map_postfix || g.inside_map_infix
|
||||
|| g.inside_map_index
|
||||
|| (g.is_assign_lhs && !g.is_array_set && get_and_set_types) {
|
||||
zero := g.type_default(info.value_type)
|
||||
g.write('(*($elem_type_str*)map_get_and_set_1(')
|
||||
if !left_is_ptr {
|
||||
@ -4733,9 +4716,8 @@ fn (mut g Gen) struct_init(struct_init ast.StructInit) {
|
||||
}
|
||||
}
|
||||
if !cloned {
|
||||
if field.expected_type.is_ptr() && !(field.typ.is_ptr() || field.typ.is_pointer()) &&
|
||||
!field.typ.is_number()
|
||||
{
|
||||
if field.expected_type.is_ptr() && !(field.typ.is_ptr()
|
||||
|| field.typ.is_pointer())&& !field.typ.is_number() {
|
||||
g.write('/* autoref */&')
|
||||
}
|
||||
g.expr_with_cast(field.expr, field.typ, field.expected_type)
|
||||
@ -4794,8 +4776,8 @@ fn (mut g Gen) struct_init(struct_init ast.StructInit) {
|
||||
expected_field_type_sym := g.table.get_type_symbol(sfield.expected_type)
|
||||
field_type_sym := g.table.get_type_symbol(sfield.typ)
|
||||
mut cloned := false
|
||||
is_interface := expected_field_type_sym.kind == .interface_ &&
|
||||
field_type_sym.kind != .interface_
|
||||
is_interface := expected_field_type_sym.kind == .interface_
|
||||
&& field_type_sym.kind != .interface_
|
||||
if g.is_autofree && !sfield.typ.is_ptr() && field_type_sym.kind in [.array, .string] {
|
||||
g.write('/*clone1*/')
|
||||
if g.gen_clone_assignment(sfield.expr, field_type_sym, false) {
|
||||
@ -4806,9 +4788,8 @@ fn (mut g Gen) struct_init(struct_init ast.StructInit) {
|
||||
if is_interface {
|
||||
g.interface_call(sfield.typ, sfield.expected_type)
|
||||
}
|
||||
if sfield.expected_type.is_ptr() && !(sfield.typ.is_ptr() || sfield.typ.is_pointer()) &&
|
||||
!sfield.typ.is_number()
|
||||
{
|
||||
if sfield.expected_type.is_ptr() && !(sfield.typ.is_ptr()
|
||||
|| sfield.typ.is_pointer())&& !sfield.typ.is_number() {
|
||||
g.write('/* autoref */&')
|
||||
}
|
||||
g.expr_with_cast(sfield.expr, sfield.typ, sfield.expected_type)
|
||||
@ -5187,7 +5168,8 @@ fn (g &Gen) sort_structs(typesa []table.TypeSymbol) []table.TypeSymbol {
|
||||
if !dep_graph_sorted.acyclic {
|
||||
// this should no longer be called since it's catched in the parser
|
||||
// TODO: should it be removed?
|
||||
verror('cgen.sort_structs(): the following structs form a dependency cycle:\n' + dep_graph_sorted.display_cycles() +
|
||||
verror('cgen.sort_structs(): the following structs form a dependency cycle:\n' +
|
||||
dep_graph_sorted.display_cycles() +
|
||||
'\nyou can solve this by making one or both of the dependant struct fields references, eg: field &MyStruct' +
|
||||
'\nif you feel this is an error, please create a new issue here: https://github.com/vlang/v/issues and tag @joe-conigliaro')
|
||||
}
|
||||
@ -5258,16 +5240,16 @@ fn (mut g Gen) or_block(var_name string, or_block ast.OrExpr, return_type table.
|
||||
g.inside_or_block = false
|
||||
}
|
||||
stmts := or_block.stmts
|
||||
if stmts.len > 0 && stmts[or_block.stmts.len - 1] is ast.ExprStmt && (stmts[stmts.len -
|
||||
1] as ast.ExprStmt).typ != table.void_type
|
||||
{
|
||||
if stmts.len > 0 && stmts[or_block.stmts.len - 1] is ast.ExprStmt
|
||||
&& (stmts[stmts.len - 1] as ast.ExprStmt).typ != table.void_type {
|
||||
g.indent++
|
||||
for i, stmt in stmts {
|
||||
if i == stmts.len - 1 {
|
||||
expr_stmt := stmt as ast.ExprStmt
|
||||
g.stmt_path_pos << g.out.len
|
||||
g.write('*($mr_styp*) ${cvar_name}.data = ')
|
||||
is_opt_call := expr_stmt.expr is ast.CallExpr && expr_stmt.typ.has_flag(.optional)
|
||||
is_opt_call := expr_stmt.expr is ast.CallExpr
|
||||
&& expr_stmt.typ.has_flag(.optional)
|
||||
if is_opt_call {
|
||||
g.write('*($mr_styp*) ')
|
||||
}
|
||||
@ -5472,9 +5454,8 @@ fn (mut g Gen) comp_if_to_ifdef(name string, is_comptime_optional bool) ?string
|
||||
return 'TARGET_ORDER_IS_BIG'
|
||||
}
|
||||
else {
|
||||
if is_comptime_optional ||
|
||||
(g.pref.compile_defines_all.len > 0 && name in g.pref.compile_defines_all)
|
||||
{
|
||||
if is_comptime_optional
|
||||
|| (g.pref.compile_defines_all.len > 0 && name in g.pref.compile_defines_all) {
|
||||
return 'CUSTOM_DEFINE_$name'
|
||||
}
|
||||
return error('bad os ifdef name "$name"') // should never happen, caught in the checker
|
||||
@ -5928,7 +5909,8 @@ fn (mut g Gen) interface_table() string {
|
||||
// i.e. cctype is always just Cat, not Cat_ptr:
|
||||
cctype := g.cc_type(st)
|
||||
$if debug_interface_table ? {
|
||||
eprintln('>> interface name: $ityp.name | concrete type: $st.debug() | st symname: ' +
|
||||
eprintln(
|
||||
'>> interface name: $ityp.name | concrete type: $st.debug() | st symname: ' +
|
||||
g.table.get_type_symbol(st).name)
|
||||
}
|
||||
// Speaker_Cat_index = 0
|
||||
|
@ -17,9 +17,8 @@ fn (mut g Gen) comptime_selector(node ast.ComptimeSelector) {
|
||||
// check for field.name
|
||||
if node.field_expr is ast.SelectorExpr {
|
||||
if node.field_expr.expr is ast.Ident {
|
||||
if node.field_expr.expr.name == g.comp_for_field_var &&
|
||||
node.field_expr.field_name == 'name'
|
||||
{
|
||||
if node.field_expr.expr.name == g.comp_for_field_var
|
||||
&& node.field_expr.field_name == 'name' {
|
||||
g.write(g.comp_for_field_value.name)
|
||||
return
|
||||
}
|
||||
@ -316,7 +315,8 @@ fn (mut g Gen) comp_for(node ast.CompFor) {
|
||||
g.writeln('\t${node.val_var}.attrs = __new_array_with_default(0, 0, sizeof(string), 0);')
|
||||
} else {
|
||||
attrs := cgen_attrs(method.attrs)
|
||||
g.writeln('\t${node.val_var}.attrs = new_array_from_c_array($attrs.len, $attrs.len, sizeof(string), _MOV((string[$attrs.len]){' +
|
||||
g.writeln(
|
||||
'\t${node.val_var}.attrs = new_array_from_c_array($attrs.len, $attrs.len, sizeof(string), _MOV((string[$attrs.len]){' +
|
||||
attrs.join(', ') + '}));')
|
||||
}
|
||||
if method.params.len < 2 {
|
||||
@ -385,7 +385,8 @@ fn (mut g Gen) comp_for(node ast.CompFor) {
|
||||
g.writeln('\t${node.val_var}.attrs = __new_array_with_default(0, 0, sizeof(string), 0);')
|
||||
} else {
|
||||
attrs := cgen_attrs(field.attrs)
|
||||
g.writeln('\t${node.val_var}.attrs = new_array_from_c_array($attrs.len, $attrs.len, sizeof(string), _MOV((string[$attrs.len]){' +
|
||||
g.writeln(
|
||||
'\t${node.val_var}.attrs = new_array_from_c_array($attrs.len, $attrs.len, sizeof(string), _MOV((string[$attrs.len]){' +
|
||||
attrs.join(', ') + '}));')
|
||||
}
|
||||
// field_sym := g.table.get_type_symbol(field.typ)
|
||||
|
@ -129,10 +129,8 @@ fn (mut g Gen) gen_fn_decl(it ast.FnDecl, skip bool) {
|
||||
arg_start_pos := g.out.len
|
||||
fargs, fargtypes := g.fn_args(it.params, it.is_variadic)
|
||||
arg_str := g.out.after(arg_start_pos)
|
||||
if it.no_body ||
|
||||
((g.pref.use_cache && g.pref.build_mode != .build_module) && it.is_builtin && !g.is_test) ||
|
||||
skip
|
||||
{
|
||||
if it.no_body || ((g.pref.use_cache && g.pref.build_mode != .build_module) && it.is_builtin
|
||||
&& !g.is_test)|| skip {
|
||||
// Just a function header. Builtin function bodies are defined in builtin.o
|
||||
g.definitions.writeln(');') // // NO BODY')
|
||||
g.writeln(');')
|
||||
@ -295,9 +293,9 @@ fn (mut g Gen) call_expr(node ast.CallExpr) {
|
||||
g.write('$styp $tmp_opt = ')
|
||||
}
|
||||
if node.is_method && !node.is_field {
|
||||
if node.name == 'writeln' && g.pref.experimental && node.args.len > 0 && node.args[0].expr is
|
||||
ast.StringInterLiteral && g.table.get_type_symbol(node.receiver_type).name == 'strings.Builder'
|
||||
{
|
||||
if node.name == 'writeln' && g.pref.experimental && node.args.len > 0
|
||||
&& node.args[0].expr is ast.StringInterLiteral
|
||||
&& g.table.get_type_symbol(node.receiver_type).name == 'strings.Builder' {
|
||||
g.string_inter_literal_sb_optimized(node)
|
||||
} else {
|
||||
g.method_call(node)
|
||||
@ -413,9 +411,8 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
|
||||
receiver_type_name = 'map'
|
||||
}
|
||||
// TODO performance, detect `array` method differently
|
||||
if left_sym.kind == .array && node.name in
|
||||
['repeat', 'sort_with_compare', 'free', 'push_many', 'trim', 'first', 'last', 'pop', 'clone', 'reverse', 'slice']
|
||||
{
|
||||
if left_sym.kind == .array
|
||||
&& node.name in ['repeat', 'sort_with_compare', 'free', 'push_many', 'trim', 'first', 'last', 'pop', 'clone', 'reverse', 'slice'] {
|
||||
// && rec_sym.name == 'array' {
|
||||
// && rec_sym.name == 'array' && receiver_name.starts_with('array') {
|
||||
// `array_byte_clone` => `array_clone`
|
||||
@ -480,9 +477,8 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
|
||||
if !is_range_slice {
|
||||
g.write('&')
|
||||
}
|
||||
} else if !node.receiver_type.is_ptr() && node.left_type.is_ptr() && node.name != 'str' &&
|
||||
node.from_embed_type == 0
|
||||
{
|
||||
} else if !node.receiver_type.is_ptr() && node.left_type.is_ptr() && node.name != 'str'
|
||||
&& node.from_embed_type == 0 {
|
||||
g.write('/*rec*/*')
|
||||
}
|
||||
if g.is_autofree && node.free_receiver && !g.inside_lambda && !g.is_builtin_mod {
|
||||
@ -505,8 +501,8 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
|
||||
if has_cast {
|
||||
g.write(')')
|
||||
}
|
||||
is_variadic := node.expected_arg_types.len > 0 && node.expected_arg_types[node.expected_arg_types.len -
|
||||
1].has_flag(.variadic)
|
||||
is_variadic := node.expected_arg_types.len > 0
|
||||
&& node.expected_arg_types[node.expected_arg_types.len - 1].has_flag(.variadic)
|
||||
if node.args.len > 0 || is_variadic {
|
||||
g.write(', ')
|
||||
}
|
||||
@ -672,8 +668,8 @@ fn (mut g Gen) autofree_call_pregen(node ast.CallExpr) {
|
||||
// g.writeln('// autofree_call_pregen()')
|
||||
// Create a temporary var before fn call for each argument in order to free it (only if it's a complex expression,
|
||||
// like `foo(get_string())` or `foo(a + b)`
|
||||
mut free_tmp_arg_vars := g.is_autofree && !g.is_builtin_mod && node.args.len > 0 &&
|
||||
!node.args[0].typ.has_flag(.optional) // TODO copy pasta checker.v
|
||||
mut free_tmp_arg_vars := g.is_autofree && !g.is_builtin_mod && node.args.len > 0
|
||||
&& !node.args[0].typ.has_flag(.optional) // TODO copy pasta checker.v
|
||||
if !free_tmp_arg_vars {
|
||||
return
|
||||
}
|
||||
@ -803,13 +799,14 @@ fn (mut g Gen) autofree_call_postgen(node_pos int) {
|
||||
fn (mut g Gen) call_args(node ast.CallExpr) {
|
||||
args := if g.is_js_call { node.args[1..] } else { node.args }
|
||||
expected_types := node.expected_arg_types
|
||||
is_variadic := expected_types.len > 0 && expected_types[expected_types.len - 1].has_flag(.variadic)
|
||||
is_variadic := expected_types.len > 0
|
||||
&& expected_types[expected_types.len - 1].has_flag(.variadic)
|
||||
for i, arg in args {
|
||||
if is_variadic && i == expected_types.len - 1 {
|
||||
break
|
||||
}
|
||||
use_tmp_var_autofree := g.is_autofree && arg.typ == table.string_type && arg.is_tmp_autofree &&
|
||||
!g.inside_const && !g.is_builtin_mod
|
||||
use_tmp_var_autofree := g.is_autofree && arg.typ == table.string_type && arg.is_tmp_autofree
|
||||
&& !g.inside_const&& !g.is_builtin_mod
|
||||
// g.write('/* af=$arg.is_tmp_autofree */')
|
||||
mut is_interface := false
|
||||
// some c fn definitions dont have args (cfns.v) or are not updated in checker
|
||||
|
@ -128,7 +128,8 @@ fn (mut g Gen) gen_struct_enc_dec(type_info table.TypeInfo, styp string, mut enc
|
||||
field_sym := g.table.get_type_symbol(field.typ)
|
||||
// First generate decoding
|
||||
if field.attrs.contains('raw') {
|
||||
dec.writeln('\tres.${c_name(field.name)} = tos4(cJSON_PrintUnformatted(' + 'js_get(root, "$name")));')
|
||||
dec.writeln('\tres.${c_name(field.name)} = tos4(cJSON_PrintUnformatted(' +
|
||||
'js_get(root, "$name")));')
|
||||
} else {
|
||||
// Now generate decoders for all field types in this struct
|
||||
// need to do it here so that these functions are generated first
|
||||
@ -201,8 +202,7 @@ fn js_dec_name(typ string) string {
|
||||
}
|
||||
|
||||
fn is_js_prim(typ string) bool {
|
||||
return typ in
|
||||
['int', 'string', 'bool', 'f32', 'f64', 'i8', 'i16', 'i64', 'u16', 'u32', 'u64', 'byte']
|
||||
return typ in ['int', 'string', 'bool', 'f32', 'f64', 'i8', 'i16', 'i64', 'u16', 'u32', 'u64', 'byte']
|
||||
}
|
||||
|
||||
fn (mut g Gen) decode_array(value_type table.Type) string {
|
||||
|
@ -45,8 +45,7 @@ fn (mut g Gen) generate_hotcode_reloader_code() {
|
||||
phd = posix_hotcode_definitions_1
|
||||
} else {
|
||||
for so_fn in g.hotcode_fn_names {
|
||||
load_code <<
|
||||
'impl_live_$so_fn = (void *)GetProcAddress(live_lib, "impl_live_$so_fn"); '
|
||||
load_code << 'impl_live_$so_fn = (void *)GetProcAddress(live_lib, "impl_live_$so_fn"); '
|
||||
}
|
||||
phd = windows_hotcode_definitions_1
|
||||
}
|
||||
|
@ -340,9 +340,8 @@ fn (mut g Gen) gen_expr_to_string(expr ast.Expr, etype table.Type) {
|
||||
g.enum_expr(expr)
|
||||
g.write('")')
|
||||
}
|
||||
} else if sym_has_str_method || sym.kind in
|
||||
[.array, .array_fixed, .map, .struct_, .multi_return, .sum_type, .interface_]
|
||||
{
|
||||
} else if sym_has_str_method
|
||||
|| sym.kind in [.array, .array_fixed, .map, .struct_, .multi_return, .sum_type, .interface_] {
|
||||
is_ptr := typ.is_ptr()
|
||||
str_fn_name := g.gen_str_for_type(typ)
|
||||
if is_ptr {
|
||||
|
@ -65,7 +65,8 @@ fn (mut p Parser) check_cross_variables(exprs []ast.Expr, val ast.Expr) bool {
|
||||
}
|
||||
}
|
||||
ast.InfixExpr {
|
||||
return p.check_cross_variables(exprs, val_.left) || p.check_cross_variables(exprs, val_.right)
|
||||
return p.check_cross_variables(exprs, val_.left)
|
||||
|| p.check_cross_variables(exprs, val_.right)
|
||||
}
|
||||
ast.PrefixExpr {
|
||||
return p.check_cross_variables(exprs, val_.right)
|
||||
|
@ -275,9 +275,8 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
|
||||
}
|
||||
}
|
||||
}
|
||||
if p.tok.kind in [.plus, .minus, .mul, .div, .mod, .gt, .lt, .eq, .ne, .le, .ge] &&
|
||||
p.peek_tok.kind == .lpar
|
||||
{
|
||||
if p.tok.kind in [.plus, .minus, .mul, .div, .mod, .gt, .lt, .eq, .ne, .le, .ge]
|
||||
&& p.peek_tok.kind == .lpar {
|
||||
name = p.tok.kind.str() // op_to_fn_name()
|
||||
if rec_type == table.void_type {
|
||||
p.error_with_pos('cannot use operator overloading with normal functions',
|
||||
@ -311,9 +310,8 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
|
||||
mut end_pos := p.prev_tok.position()
|
||||
// Return type
|
||||
mut return_type := table.void_type
|
||||
if p.tok.kind.is_start_of_type() ||
|
||||
(p.tok.kind == .key_fn && p.tok.line_nr == p.prev_tok.line_nr)
|
||||
{
|
||||
if p.tok.kind.is_start_of_type()
|
||||
|| (p.tok.kind == .key_fn && p.tok.line_nr == p.prev_tok.line_nr) {
|
||||
return_type = p.parse_type()
|
||||
}
|
||||
mut type_sym_method_idx := 0
|
||||
@ -327,8 +325,8 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
|
||||
// check maps & arrays, must be defined in same module as the elem type
|
||||
if !is_non_local && type_sym.kind in [.array, .map] {
|
||||
elem_type_sym := p.table.get_type_symbol(p.table.value_type(rec_type))
|
||||
is_non_local = elem_type_sym.mod.len > 0 &&
|
||||
elem_type_sym.mod != p.mod && elem_type_sym.language == .v
|
||||
is_non_local = elem_type_sym.mod.len > 0 && elem_type_sym.mod != p.mod
|
||||
&& elem_type_sym.language == .v
|
||||
}
|
||||
if is_non_local {
|
||||
p.error_with_pos('cannot define new methods on non-local type $type_sym.name',
|
||||
@ -570,9 +568,9 @@ fn (mut p Parser) fn_args() ([]table.Param, bool, bool) {
|
||||
} else {
|
||||
p.tok.lit
|
||||
}
|
||||
types_only := p.tok.kind in [.amp, .ellipsis, .key_fn] ||
|
||||
(p.peek_tok.kind == .comma && p.table.known_type(argname)) || p.peek_tok.kind == .dot ||
|
||||
p.peek_tok.kind == .rpar
|
||||
types_only := p.tok.kind in [.amp, .ellipsis, .key_fn]
|
||||
|| (p.peek_tok.kind == .comma && p.table.known_type(argname))
|
||||
|| p.peek_tok.kind == .dot|| p.peek_tok.kind == .rpar
|
||||
// TODO copy pasta, merge 2 branches
|
||||
if types_only {
|
||||
// p.warn('types only')
|
||||
@ -668,7 +666,8 @@ fn (mut p Parser) fn_args() ([]table.Param, bool, bool) {
|
||||
// `a, b, c int`
|
||||
for p.tok.kind == .comma {
|
||||
if !p.pref.is_fmt {
|
||||
p.warn('`fn f(x, y Type)` syntax has been deprecated and will soon be removed. ' +
|
||||
p.warn(
|
||||
'`fn f(x, y Type)` syntax has been deprecated and will soon be removed. ' +
|
||||
'Use `fn f(x Type, y Type)` instead. You can run `v fmt -w "$p.scanner.file_path"` to automatically fix your code.')
|
||||
}
|
||||
p.next()
|
||||
@ -746,11 +745,10 @@ fn (mut p Parser) fn_args() ([]table.Param, bool, bool) {
|
||||
|
||||
fn (mut p Parser) check_fn_mutable_arguments(typ table.Type, pos token.Position) {
|
||||
sym := p.table.get_type_symbol(typ)
|
||||
if sym.kind !in
|
||||
[.array, .array_fixed, .interface_, .map, .placeholder, .struct_, .sum_type] &&
|
||||
!typ.is_ptr() && !typ.is_pointer()
|
||||
{
|
||||
p.error_with_pos('mutable arguments are only allowed for arrays, interfaces, maps, pointers and structs\n' +
|
||||
if sym.kind !in [.array, .array_fixed, .interface_, .map, .placeholder, .struct_, .sum_type]
|
||||
&& !typ.is_ptr()&& !typ.is_pointer() {
|
||||
p.error_with_pos(
|
||||
'mutable arguments are only allowed for arrays, interfaces, maps, pointers and structs\n' +
|
||||
'return values instead: `fn foo(mut n $sym.name) {` => `fn foo(n $sym.name) $sym.name {`',
|
||||
pos)
|
||||
}
|
||||
|
@ -78,9 +78,8 @@ fn (mut p Parser) for_stmt() ast.Stmt {
|
||||
}
|
||||
p.close_scope()
|
||||
return for_c_stmt
|
||||
} else if p.peek_tok.kind in [.key_in, .comma] ||
|
||||
(p.tok.kind == .key_mut && p.peek_tok2.kind in [.key_in, .comma])
|
||||
{
|
||||
} else if p.peek_tok.kind in [.key_in, .comma]
|
||||
|| (p.tok.kind == .key_mut && p.peek_tok2.kind in [.key_in, .comma]) {
|
||||
// `for i in vals`, `for i in start .. end`, `for mut user in users`, `for i, mut user in users`
|
||||
mut val_is_mut := p.tok.kind == .key_mut
|
||||
mut_pos := p.tok.position()
|
||||
|
@ -179,13 +179,10 @@ fn (mut p Parser) match_expr() ast.MatchExpr {
|
||||
if p.tok.kind == .key_else {
|
||||
is_else = true
|
||||
p.next()
|
||||
} else if (p.tok.kind == .name && !(p.tok.lit == 'C' &&
|
||||
p.peek_tok.kind == .dot) &&
|
||||
(p.tok.lit in table.builtin_type_names || p.tok.lit[0].is_capital() ||
|
||||
(p.peek_tok.kind == .dot &&
|
||||
p.peek_tok2.lit.len > 0 && p.peek_tok2.lit[0].is_capital()))) ||
|
||||
p.tok.kind == .lsbr
|
||||
{
|
||||
} else if (p.tok.kind == .name && !(p.tok.lit == 'C' && p.peek_tok.kind == .dot)
|
||||
&& (p.tok.lit in table.builtin_type_names || p.tok.lit[0].is_capital()
|
||||
|| (p.peek_tok.kind == .dot && p.peek_tok2.lit.len > 0 && p.peek_tok2.lit[0].is_capital())))
|
||||
|| p.tok.kind == .lsbr {
|
||||
mut types := []table.Type{}
|
||||
for {
|
||||
// Sum type match
|
||||
|
@ -77,9 +77,8 @@ pub fn (mut p Parser) parse_map_type() table.Type {
|
||||
// error is reported in parse_type
|
||||
return 0
|
||||
}
|
||||
if !(key_type in [table.string_type_idx, table.voidptr_type_idx] ||
|
||||
(key_type.is_int() && !key_type.is_ptr()))
|
||||
{
|
||||
if !(key_type in [table.string_type_idx, table.voidptr_type_idx]
|
||||
|| (key_type.is_int() && !key_type.is_ptr())) {
|
||||
s := p.table.type_to_str(key_type)
|
||||
p.error_with_pos('maps only support string, integer, rune or voidptr keys for now (not `$s`)',
|
||||
p.tok.position())
|
||||
|
@ -125,11 +125,11 @@ pub fn (mut p Parser) set_path(path string) {
|
||||
p.file_name = path
|
||||
p.file_base = os.base(path)
|
||||
p.file_name_dir = os.dir(path)
|
||||
if path.ends_with('_c.v') || path.ends_with('.c.v') || path.ends_with('.c.vv') || path.ends_with('.c.vsh') {
|
||||
if path.ends_with('_c.v') || path.ends_with('.c.v') || path.ends_with('.c.vv')
|
||||
|| path.ends_with('.c.vsh') {
|
||||
p.file_backend_mode = .c
|
||||
} else if path.ends_with('_js.v') || path.ends_with('.js.v') || path.ends_with('.js.vv') ||
|
||||
path.ends_with('.js.vsh')
|
||||
{
|
||||
} else if path.ends_with('_js.v') || path.ends_with('.js.v') || path.ends_with('.js.vv')
|
||||
|| path.ends_with('.js.vsh') {
|
||||
p.file_backend_mode = .js
|
||||
} else {
|
||||
p.file_backend_mode = .v
|
||||
@ -677,9 +677,8 @@ pub fn (mut p Parser) stmt(is_top_level bool) ast.Stmt {
|
||||
} else if p.peek_tok.kind == .name {
|
||||
p.error_with_pos('unexpected name `$p.peek_tok.lit`', p.peek_tok.position())
|
||||
return ast.Stmt{}
|
||||
} else if !p.inside_if_expr && !p.inside_match_body && !p.inside_or_expr &&
|
||||
p.peek_tok.kind in [.rcbr, .eof] && !p.mark_var_as_used(p.tok.lit)
|
||||
{
|
||||
} else if !p.inside_if_expr && !p.inside_match_body && !p.inside_or_expr
|
||||
&& p.peek_tok.kind in [.rcbr, .eof]&& !p.mark_var_as_used(p.tok.lit) {
|
||||
p.error_with_pos('`$p.tok.lit` evaluated but not used', p.tok.position())
|
||||
return ast.Stmt{}
|
||||
}
|
||||
@ -1004,12 +1003,11 @@ fn (mut p Parser) parse_multi_expr(is_top_level bool) ast.Stmt {
|
||||
}
|
||||
if p.tok.kind in [.assign, .decl_assign] || p.tok.kind.is_assign() {
|
||||
return p.partial_assign_stmt(left, left_comments)
|
||||
} else if tok.kind !in [.key_if, .key_match, .key_lock, .key_rlock, .key_select] &&
|
||||
left0 !is ast.CallExpr && (is_top_level || p.tok.kind != .rcbr) && left0 !is ast.PostfixExpr &&
|
||||
!(left0 is ast.InfixExpr &&
|
||||
(left0 as ast.InfixExpr).op in [.left_shift, .arrow]) && left0 !is ast.ComptimeCall &&
|
||||
left0 !is ast.SelectorExpr
|
||||
{
|
||||
} else if tok.kind !in [.key_if, .key_match, .key_lock, .key_rlock, .key_select]
|
||||
&& left0 !is ast.CallExpr && (is_top_level || p.tok.kind != .rcbr)
|
||||
&& left0 !is ast.PostfixExpr && !(left0 is ast.InfixExpr
|
||||
&& (left0 as ast.InfixExpr).op in [.left_shift, .arrow]) && left0 !is ast.ComptimeCall
|
||||
&& left0 !is ast.SelectorExpr {
|
||||
p.error_with_pos('expression evaluated but not used', left0.position())
|
||||
return ast.Stmt{}
|
||||
}
|
||||
@ -1100,9 +1098,7 @@ fn (p &Parser) is_generic_call() bool {
|
||||
return !lit0_is_capital && p.peek_tok.kind == .lt && (match p.peek_tok2.kind {
|
||||
.name {
|
||||
// maybe `f<int>`, `f<map[`, f<string,
|
||||
(p.peek_tok2.kind == .name &&
|
||||
p.peek_tok3.kind in [.gt, .comma]) ||
|
||||
(p.peek_tok2.lit == 'map' && p.peek_tok3.kind == .lsbr)
|
||||
(p.peek_tok2.kind == .name && p.peek_tok3.kind in [.gt, .comma]) || (p.peek_tok2.lit == 'map' && p.peek_tok3.kind == .lsbr)
|
||||
}
|
||||
.lsbr {
|
||||
// maybe `f<[]T>`, assume `var < []` is invalid
|
||||
@ -1206,9 +1202,8 @@ pub fn (mut p Parser) name_expr() ast.Expr {
|
||||
}
|
||||
known_var := p.mark_var_as_used(p.tok.lit)
|
||||
mut is_mod_cast := false
|
||||
if p.peek_tok.kind == .dot && !known_var &&
|
||||
(language != .v || p.known_import(p.tok.lit) || p.mod.all_after_last('.') == p.tok.lit)
|
||||
{
|
||||
if p.peek_tok.kind == .dot && !known_var && (language != .v || p.known_import(p.tok.lit)
|
||||
|| p.mod.all_after_last('.') == p.tok.lit) {
|
||||
// p.tok.lit has been recognized as a module
|
||||
if language == .c {
|
||||
mod = 'C'
|
||||
@ -1218,13 +1213,11 @@ pub fn (mut p Parser) name_expr() ast.Expr {
|
||||
if p.tok.lit in p.imports {
|
||||
// mark the imported module as used
|
||||
p.register_used_import(p.tok.lit)
|
||||
if p.peek_tok.kind == .dot &&
|
||||
p.peek_tok2.kind != .eof && p.peek_tok2.lit.len > 0 && p.peek_tok2.lit[0].is_capital()
|
||||
{
|
||||
if p.peek_tok.kind == .dot && p.peek_tok2.kind != .eof && p.peek_tok2.lit.len > 0
|
||||
&& p.peek_tok2.lit[0].is_capital() {
|
||||
is_mod_cast = true
|
||||
} else if p.peek_tok.kind == .dot &&
|
||||
p.peek_tok2.kind != .eof && p.peek_tok2.lit.len == 0
|
||||
{
|
||||
} else if p.peek_tok.kind == .dot && p.peek_tok2.kind != .eof
|
||||
&& p.peek_tok2.lit.len == 0 {
|
||||
// incomplete module selector must be handled by dot_expr instead
|
||||
node = p.parse_ident(language)
|
||||
return node
|
||||
@ -1256,10 +1249,9 @@ pub fn (mut p Parser) name_expr() ast.Expr {
|
||||
name_w_mod := p.prepend_mod(name)
|
||||
// type cast. TODO: finish
|
||||
// if name in table.builtin_type_names {
|
||||
if (!known_var && (name in p.table.type_idxs ||
|
||||
name_w_mod in p.table.type_idxs) && name !in ['C.stat', 'C.sigaction']) ||
|
||||
is_mod_cast || (language == .v && name[0].is_capital())
|
||||
{
|
||||
if (!known_var && (name in p.table.type_idxs || name_w_mod in p.table.type_idxs)
|
||||
&& name !in ['C.stat', 'C.sigaction']) || is_mod_cast
|
||||
|| (language == .v && name[0].is_capital()) {
|
||||
// MainLetter(x) is *always* a cast, as long as it is not `C.`
|
||||
// TODO handle C.stat()
|
||||
start_pos := p.tok.position()
|
||||
@ -1299,13 +1291,10 @@ pub fn (mut p Parser) name_expr() ast.Expr {
|
||||
// println('calling $p.tok.lit')
|
||||
node = p.call_expr(language, mod)
|
||||
}
|
||||
} else if (p.peek_tok.kind == .lcbr ||
|
||||
(p.peek_tok.kind == .lt && lit0_is_capital)) &&
|
||||
(!p.inside_match || (p.inside_select && prev_tok_kind == .arrow && lit0_is_capital)) &&
|
||||
!p.inside_match_case &&
|
||||
(!p.inside_if || p.inside_select) &&
|
||||
(!p.inside_for || p.inside_select)
|
||||
{ // && (p.tok.lit[0].is_capital() || p.builtin_mod) {
|
||||
} else if (p.peek_tok.kind == .lcbr || (p.peek_tok.kind == .lt && lit0_is_capital))
|
||||
&& (!p.inside_match || (p.inside_select && prev_tok_kind == .arrow && lit0_is_capital))
|
||||
&& !p.inside_match_case && (!p.inside_if || p.inside_select)
|
||||
&& (!p.inside_for || p.inside_select) { // && (p.tok.lit[0].is_capital() || p.builtin_mod) {
|
||||
return p.struct_init(false) // short_syntax: false
|
||||
} else if p.peek_tok.kind == .dot && (lit0_is_capital && !known_var && language == .v) {
|
||||
// T.name
|
||||
@ -2044,10 +2033,9 @@ const (
|
||||
|
||||
// left hand side of `=` or `:=` in `a,b,c := 1,2,3`
|
||||
fn (mut p Parser) global_decl() ast.GlobalDecl {
|
||||
if !p.pref.translated && !p.pref.is_livemain && !p.builtin_mod && !p.pref.building_v &&
|
||||
p.mod != 'ui' && p.mod != 'gg2' && p.mod != 'uiold' && !p.pref.enable_globals && !p.pref.is_fmt &&
|
||||
p.mod !in global_enabled_mods
|
||||
{
|
||||
if !p.pref.translated && !p.pref.is_livemain && !p.builtin_mod && !p.pref.building_v
|
||||
&& p.mod != 'ui' && p.mod != 'gg2' && p.mod != 'uiold' && !p.pref.enable_globals
|
||||
&& !p.pref.is_fmt&& p.mod !in global_enabled_mods {
|
||||
p.error('use `v --enable-globals ...` to enable globals')
|
||||
return ast.GlobalDecl{}
|
||||
}
|
||||
|
@ -385,9 +385,8 @@ fn (mut p Parser) infix_expr(left ast.Expr) ast.Expr {
|
||||
}
|
||||
right = p.expr(precedence)
|
||||
p.expecting_type = prev_expecting_type
|
||||
if p.pref.is_vet && op in [.key_in, .not_in] && right is ast.ArrayInit && (right as ast.ArrayInit).exprs.len ==
|
||||
1
|
||||
{
|
||||
if p.pref.is_vet && op in [.key_in, .not_in] && right is ast.ArrayInit
|
||||
&& (right as ast.ArrayInit).exprs.len == 1 {
|
||||
p.vet_error('Use `var == value` instead of `var in [value]`', pos.line_nr, vet.FixKind.vfmt)
|
||||
}
|
||||
mut or_stmts := []ast.Stmt{}
|
||||
|
@ -65,7 +65,8 @@ fn (mut p Parser) struct_decl() ast.StructDecl {
|
||||
p.error('`$p.tok.lit` lacks body')
|
||||
return ast.StructDecl{}
|
||||
}
|
||||
if language == .v && !p.builtin_mod && name.len > 0 && !name[0].is_capital() && !p.pref.translated {
|
||||
if language == .v && !p.builtin_mod && name.len > 0 && !name[0].is_capital()
|
||||
&& !p.pref.translated {
|
||||
p.error_with_pos('struct name `$name` must begin with capital letter', name_pos)
|
||||
return ast.StructDecl{}
|
||||
}
|
||||
@ -176,9 +177,8 @@ fn (mut p Parser) struct_decl() ast.StructDecl {
|
||||
}
|
||||
}
|
||||
field_start_pos := p.tok.position()
|
||||
is_embed := ((p.tok.lit.len > 1 && p.tok.lit[0].is_capital()) ||
|
||||
p.peek_tok.kind == .dot) &&
|
||||
language == .v
|
||||
is_embed := ((p.tok.lit.len > 1 && p.tok.lit[0].is_capital())
|
||||
|| p.peek_tok.kind == .dot)&& language == .v
|
||||
is_on_top := ast_fields.len == 0 && !(is_field_mut || is_field_mut || is_field_global)
|
||||
mut field_name := ''
|
||||
mut typ := table.Type(0)
|
||||
@ -385,8 +385,11 @@ fn (mut p Parser) struct_init(short_syntax bool) ast.StructInit {
|
||||
expr = p.expr(0)
|
||||
comments = p.eat_line_end_comments()
|
||||
last_field_pos := expr.position()
|
||||
field_len := if last_field_pos.len > 0 { last_field_pos.pos - first_field_pos.pos +
|
||||
last_field_pos.len } else { first_field_pos.len + 1 }
|
||||
field_len := if last_field_pos.len > 0 {
|
||||
last_field_pos.pos - first_field_pos.pos + last_field_pos.len
|
||||
} else {
|
||||
first_field_pos.len + 1
|
||||
}
|
||||
field_pos = token.Position{
|
||||
line_nr: first_field_pos.line_nr
|
||||
pos: first_field_pos.pos
|
||||
|
@ -481,9 +481,8 @@ pub fn parse_args(args []string) (&Preferences, string) {
|
||||
exit(tmp_result)
|
||||
}
|
||||
must_exist(res.path)
|
||||
if !res.path.ends_with('.v') && os.is_executable(res.path) && os.is_file(res.path) &&
|
||||
os.is_file(res.path + '.v')
|
||||
{
|
||||
if !res.path.ends_with('.v') && os.is_executable(res.path) && os.is_file(res.path)
|
||||
&& os.is_file(res.path + '.v') {
|
||||
eprintln('It looks like you wanted to run "${res.path}.v", so we went ahead and did that since "$res.path" is an executable.')
|
||||
res.path += '.v'
|
||||
}
|
||||
@ -569,7 +568,8 @@ fn parse_define(mut prefs Preferences, define string) {
|
||||
prefs.compile_defines << define_parts[0]
|
||||
}
|
||||
else {
|
||||
println('V error: Unknown define argument value `${define_parts[1]}` for ${define_parts[0]}.' +
|
||||
println(
|
||||
'V error: Unknown define argument value `${define_parts[1]}` for ${define_parts[0]}.' +
|
||||
' Expected `0` or `1`.')
|
||||
exit(1)
|
||||
}
|
||||
|
@ -132,8 +132,8 @@ pub fn new_vet_scanner(text string, comments_mode CommentsMode, pref &pref.Prefe
|
||||
|
||||
[inline]
|
||||
fn (s &Scanner) should_parse_comment() bool {
|
||||
return (s.comments_mode == .parse_comments) ||
|
||||
(s.comments_mode == .toplevel_comments && !s.is_inside_toplvl_statement)
|
||||
return (s.comments_mode == .parse_comments)
|
||||
|| (s.comments_mode == .toplevel_comments && !s.is_inside_toplvl_statement)
|
||||
}
|
||||
|
||||
// NB: this is called by v's parser
|
||||
@ -473,7 +473,8 @@ fn (mut s Scanner) end_of_file() token.Token {
|
||||
s.eofs++
|
||||
if s.eofs > 50 {
|
||||
s.line_nr--
|
||||
panic('the end of file `$s.file_path` has been reached 50 times already, the v parser is probably stuck.\n' +
|
||||
panic(
|
||||
'the end of file `$s.file_path` has been reached 50 times already, the v parser is probably stuck.\n' +
|
||||
'This should not happen. Please report the bug here, and include the last 2-3 lines of your source code:\n' +
|
||||
'https://github.com/vlang/v/issues/new?labels=Bug&template=bug_report.md')
|
||||
}
|
||||
@ -603,7 +604,8 @@ fn (mut s Scanner) text_scan() token.Token {
|
||||
}
|
||||
// end of `$expr`
|
||||
// allow `'$a.b'` and `'$a.c()'`
|
||||
if s.is_inter_start && next_char == `\\` && s.look_ahead(2) !in [`x`, `n`, `r`, `\\`, `t`, `e`] {
|
||||
if s.is_inter_start && next_char == `\\`
|
||||
&& s.look_ahead(2) !in [`x`, `n`, `r`, `\\`, `t`, `e`] {
|
||||
s.warn('unknown escape sequence \\${s.look_ahead(2)}')
|
||||
}
|
||||
if s.is_inter_start && next_char == `(` {
|
||||
@ -901,14 +903,12 @@ fn (mut s Scanner) text_scan() token.Token {
|
||||
if nextc == `=` {
|
||||
s.pos++
|
||||
return s.new_token(.ne, '', 2)
|
||||
} else if s.text.len > s.pos + 3 &&
|
||||
nextc == `i` && s.text[s.pos + 2] == `n` && s.text[s.pos + 3].is_space()
|
||||
{
|
||||
} else if s.text.len > s.pos + 3 && nextc == `i` && s.text[s.pos + 2] == `n`
|
||||
&& s.text[s.pos + 3].is_space() {
|
||||
s.pos += 2
|
||||
return s.new_token(.not_in, '', 3)
|
||||
} else if s.text.len > s.pos + 3 &&
|
||||
nextc == `i` && s.text[s.pos + 2] == `s` && s.text[s.pos + 3].is_space()
|
||||
{
|
||||
} else if s.text.len > s.pos + 3 && nextc == `i` && s.text[s.pos + 2] == `s`
|
||||
&& s.text[s.pos + 3].is_space() {
|
||||
s.pos += 2
|
||||
return s.new_token(.not_is, '', 3)
|
||||
} else {
|
||||
@ -1037,9 +1037,8 @@ fn (mut s Scanner) ident_string() string {
|
||||
// }
|
||||
mut n_cr_chars := 0
|
||||
mut start := s.pos
|
||||
if s.text[start] == s.quote ||
|
||||
(s.text[start] == s.inter_quote && (s.is_inter_start || s.is_enclosed_inter))
|
||||
{
|
||||
if s.text[start] == s.quote
|
||||
|| (s.text[start] == s.inter_quote && (s.is_inter_start || s.is_enclosed_inter)) {
|
||||
start++
|
||||
}
|
||||
s.is_inside_string = false
|
||||
@ -1068,9 +1067,8 @@ fn (mut s Scanner) ident_string() string {
|
||||
}
|
||||
// Don't allow \0
|
||||
if c == `0` && s.pos > 2 && prevc == slash {
|
||||
if (s.pos < s.text.len - 1 && s.text[s.pos + 1].is_digit()) ||
|
||||
s.count_symbol_before(s.pos - 1, slash) % 2 == 0
|
||||
{
|
||||
if (s.pos < s.text.len - 1 && s.text[s.pos + 1].is_digit())
|
||||
|| s.count_symbol_before(s.pos - 1, slash) % 2 == 0 {
|
||||
} else if !is_cstr && !is_raw {
|
||||
s.error(r'cannot use `\0` (NULL character) in the string literal')
|
||||
}
|
||||
@ -1089,11 +1087,11 @@ fn (mut s Scanner) ident_string() string {
|
||||
s.error(r'`\x` used with no following hex digits')
|
||||
}
|
||||
// Escape `\u`
|
||||
if c == `u` && (s.text[s.pos + 1] == s.quote ||
|
||||
s.text[s.pos + 2] == s.quote || s.text[s.pos + 3] == s.quote || s.text[s.pos +
|
||||
4] == s.quote || !s.text[s.pos + 1].is_hex_digit() || !s.text[s.pos + 2].is_hex_digit() ||
|
||||
!s.text[s.pos + 3].is_hex_digit() || !s.text[s.pos + 4].is_hex_digit())
|
||||
{
|
||||
if c == `u`
|
||||
&& (s.text[s.pos + 1] == s.quote || s.text[s.pos + 2] == s.quote || s.text[s.pos + 3] == s.quote || s.text[s.pos + 4] == s.quote || !s.text[s.pos + 1].is_hex_digit()
|
||||
|| !s.text[s.pos + 2].is_hex_digit()
|
||||
|| !s.text[s.pos + 3].is_hex_digit()
|
||||
|| !s.text[s.pos + 4].is_hex_digit()) {
|
||||
s.error(r'`\u` incomplete unicode character value')
|
||||
}
|
||||
}
|
||||
@ -1106,9 +1104,8 @@ fn (mut s Scanner) ident_string() string {
|
||||
break
|
||||
}
|
||||
// $var
|
||||
if prevc == `$` && util.is_name_char(c) && !is_raw && s.count_symbol_before(s.pos - 2, slash) %
|
||||
2 == 0
|
||||
{
|
||||
if prevc == `$` && util.is_name_char(c) && !is_raw
|
||||
&& s.count_symbol_before(s.pos - 2, slash) % 2 == 0 {
|
||||
s.is_inside_string = true
|
||||
s.is_inter_start = true
|
||||
s.pos -= 2
|
||||
@ -1175,7 +1172,8 @@ fn (mut s Scanner) ident_char() string {
|
||||
if len != 1 {
|
||||
u := c.ustring()
|
||||
if u.len != 1 {
|
||||
s.error('invalid character literal (more than one character)\n' + 'use quotes for strings, backticks for characters')
|
||||
s.error('invalid character literal (more than one character)\n' +
|
||||
'use quotes for strings, backticks for characters')
|
||||
}
|
||||
}
|
||||
// Escapes a `'` character
|
||||
|
@ -41,9 +41,10 @@ pub mut:
|
||||
}
|
||||
|
||||
fn (f &Fn) method_equals(o &Fn) bool {
|
||||
return f.params[1..].equals(o.params[1..]) && f.return_type == o.return_type && f.is_variadic ==
|
||||
o.is_variadic && f.language == o.language && f.generic_names == o.generic_names &&
|
||||
f.is_pub == o.is_pub && f.mod == o.mod && f.name == o.name
|
||||
return f.params[1..].equals(o.params[1..]) && f.return_type == o.return_type
|
||||
&& f.is_variadic == o.is_variadic && f.language == o.language
|
||||
&& f.generic_names == o.generic_names && f.is_pub == o.is_pub && f.mod == o.mod
|
||||
&& f.name == o.name
|
||||
}
|
||||
|
||||
pub struct Param {
|
||||
|
@ -409,14 +409,13 @@ pub fn (tok Token) is_scalar() bool {
|
||||
|
||||
// is_unary returns true if the token can be in a unary expression
|
||||
pub fn (tok Token) is_unary() bool {
|
||||
return tok.kind in
|
||||
[
|
||||
/* `+` | `-` | `!` | `~` | `*` | `&` */.plus, .minus, .not, .bit_not, .mul, .amp, .arrow]
|
||||
// `+` | `-` | `!` | `~` | `*` | `&` | `<-`
|
||||
return tok.kind in [ .plus, .minus, .not, .bit_not, .mul, .amp, .arrow]
|
||||
}
|
||||
|
||||
pub fn (tok Kind) is_relational() bool {
|
||||
return tok in [
|
||||
/* `<` | `<=` | `>` | `>=` */.lt, .le, .gt, .ge, .eq, .ne]
|
||||
// `<` | `<=` | `>` | `>=` | `==` | `!=`
|
||||
return tok in [.lt, .le, .gt, .ge, .eq, .ne]
|
||||
}
|
||||
|
||||
pub fn (k Kind) is_start_of_type() bool {
|
||||
@ -429,7 +428,7 @@ pub fn (kind Kind) is_prefix() bool {
|
||||
|
||||
pub fn (kind Kind) is_infix() bool {
|
||||
return kind in
|
||||
[.plus, .minus, .mod, .mul, .div, .eq, .ne, .gt, .lt, .key_in, /* */.key_as, .ge, .le, .logical_or, .xor, .not_in, .key_is, .not_is, /* */.and, .dot, .pipe, .amp, .left_shift, .right_shift, .arrow]
|
||||
[.plus, .minus, .mod, .mul, .div, .eq, .ne, .gt, .lt, .key_in, .key_as, .ge, .le, .logical_or, .xor, .not_in, .key_is, .not_is, .and, .dot, .pipe, .amp, .left_shift, .right_shift, .arrow]
|
||||
}
|
||||
|
||||
// Pass table.builtin_type_names
|
||||
|
@ -12,8 +12,7 @@ pub fn find_working_diff_command() ?string {
|
||||
if env_difftool.len > 0 {
|
||||
known_diff_tools << env_difftool
|
||||
}
|
||||
known_diff_tools <<
|
||||
['colordiff', 'gdiff', 'diff', 'colordiff.exe', 'diff.exe', 'opendiff', 'code', 'code.cmd']
|
||||
known_diff_tools << ['colordiff', 'gdiff', 'diff', 'colordiff.exe', 'diff.exe', 'opendiff', 'code', 'code.cmd']
|
||||
// NOTE: code.cmd is the Windows variant of the `code` cli tool
|
||||
for diffcmd in known_diff_tools {
|
||||
if diffcmd == 'opendiff' { // opendiff has no `--version` option
|
||||
|
@ -119,8 +119,12 @@ pub fn source_context(kind string, source string, column int, pos token.Position
|
||||
sline := source_lines[iline]
|
||||
start_column := imax(0, imin(column, sline.len))
|
||||
end_column := imax(0, imin(column + imax(0, pos.len), sline.len))
|
||||
cline := if iline == pos.line_nr { sline[..start_column] + color(kind, sline[start_column..end_column]) +
|
||||
sline[end_column..] } else { sline }
|
||||
cline := if iline == pos.line_nr {
|
||||
sline[..start_column] + color(kind, sline[start_column..end_column]) +
|
||||
sline[end_column..]
|
||||
} else {
|
||||
sline
|
||||
}
|
||||
clines << '${iline + 1:5d} | ' + cline.replace('\t', tab_spaces)
|
||||
//
|
||||
if iline == pos.line_nr {
|
||||
|
@ -90,9 +90,8 @@ pub fn mod_path_to_full_name(mod string, path string) ?string {
|
||||
if ls := os.ls(parent) {
|
||||
// currently CI clones some modules into the v repo to test, the condition
|
||||
// after `'v.mod' in ls` can be removed once a proper solution is added
|
||||
if 'v.mod' in ls &&
|
||||
(try_path_parts.len > i && try_path_parts[i] != 'v' && 'vlib' !in ls)
|
||||
{
|
||||
if 'v.mod' in ls
|
||||
&& (try_path_parts.len > i && try_path_parts[i] != 'v' && 'vlib' !in ls) {
|
||||
last_v_mod = j
|
||||
}
|
||||
continue
|
||||
|
@ -157,8 +157,8 @@ pub fn launch_tool(is_verbose bool, tool_name string, args []string) {
|
||||
}
|
||||
disabling_file := recompilation.disabling_file(vroot)
|
||||
is_recompilation_disabled := os.exists(disabling_file)
|
||||
should_compile := !is_recompilation_disabled &&
|
||||
should_recompile_tool(vexe, tool_source, tool_name, tool_exe)
|
||||
should_compile := !is_recompilation_disabled
|
||||
&& should_recompile_tool(vexe, tool_source, tool_name, tool_exe)
|
||||
if is_verbose {
|
||||
println('launch_tool should_compile: $should_compile')
|
||||
}
|
||||
|
@ -491,11 +491,9 @@ fn handle_conn<T>(mut conn net.TcpConn, mut app T) {
|
||||
// since such methods have a priority.
|
||||
// For example URL `/register` matches route `/:user`, but `fn register()`
|
||||
// should be called first.
|
||||
if (req_method_str == '' &&
|
||||
url_words[0] == method.name && url_words.len == 1) ||
|
||||
(req_method_str == req.method.str() && url_words[0] == method.name && url_words.len ==
|
||||
1)
|
||||
{
|
||||
if (req_method_str == '' && url_words[0] == method.name && url_words.len == 1)
|
||||
|| (req_method_str == req.method.str() && url_words[0] == method.name
|
||||
&& url_words.len == 1) {
|
||||
$if debug {
|
||||
println('easy match method=$method.name')
|
||||
}
|
||||
@ -521,9 +519,8 @@ fn handle_conn<T>(mut conn net.TcpConn, mut app T) {
|
||||
if route_words.len == 1 && route_words[0] in methods_without_first {
|
||||
req_method << route_words[0]
|
||||
}
|
||||
if url_words.len == route_words.len ||
|
||||
(url_words.len >= route_words.len - 1 && route_words.len > 0 && route_words.last().ends_with('...'))
|
||||
{
|
||||
if url_words.len == route_words.len
|
||||
|| (url_words.len >= route_words.len - 1 && route_words.len > 0 && route_words.last().ends_with('...')) {
|
||||
if req_method.len > 0 {
|
||||
if req_method_str.to_lower()[1..] !in req_method {
|
||||
continue
|
||||
|
@ -118,9 +118,9 @@ fn (mut ws Client) read_handshake_str() ?string {
|
||||
}
|
||||
msg[total_bytes_read] = buffer[0]
|
||||
total_bytes_read++
|
||||
if total_bytes_read > 5 && msg[total_bytes_read - 1] == `\n` && msg[total_bytes_read -
|
||||
2] == `\r` && msg[total_bytes_read - 3] == `\n` && msg[total_bytes_read - 4] == `\r`
|
||||
{
|
||||
if total_bytes_read > 5 && msg[total_bytes_read - 1] == `\n`
|
||||
&& msg[total_bytes_read - 2] == `\r` && msg[total_bytes_read - 3] == `\n`
|
||||
&& msg[total_bytes_read - 4] == `\r` {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
@ -42,9 +42,8 @@ pub fn (mut ws Client) validate_frame(frame &Frame) ? {
|
||||
ws.close(1002, 'rsv cannot be other than 0, not negotiated')
|
||||
return error('rsv cannot be other than 0, not negotiated')
|
||||
}
|
||||
if (int(frame.opcode) >= 3 && int(frame.opcode) <= 7) ||
|
||||
(int(frame.opcode) >= 11 && int(frame.opcode) <= 15)
|
||||
{
|
||||
if (int(frame.opcode) >= 3 && int(frame.opcode) <= 7)
|
||||
|| (int(frame.opcode) >= 11 && int(frame.opcode) <= 15) {
|
||||
ws.close(1002, 'use of reserved opcode') ?
|
||||
return error('use of reserved opcode')
|
||||
}
|
||||
|
@ -232,7 +232,11 @@ pub fn (mut ws Client) write_ptr(bytes byteptr, payload_len int, code OPCode) ?
|
||||
// todo: send error here later
|
||||
return error('trying to write on a closed socket!')
|
||||
}
|
||||
mut header_len := 2 + if payload_len > 125 { 2 } else { 0 } + if payload_len > 0xffff { 6 } else { 0 }
|
||||
mut header_len := 2 + if payload_len > 125 { 2 } else { 0 } + if payload_len > 0xffff {
|
||||
6
|
||||
} else {
|
||||
0
|
||||
}
|
||||
if !ws.is_server {
|
||||
header_len += 4
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user