fmt: fix if cond break readability (#8132)
parent
2f7a66386e
commit
53941c4a0a
|
@ -265,7 +265,8 @@ fn (vd VDoc) gen_html(d doc.Doc) string {
|
||||||
submod_prefix = if names.len > 1 { names[0] } else { dc.head.name }
|
submod_prefix = if names.len > 1 { names[0] } else { dc.head.name }
|
||||||
mut href_name := './${dc.head.name}.html'
|
mut href_name := './${dc.head.name}.html'
|
||||||
if (cfg.is_vlib && dc.head.name == 'builtin' && !cfg.include_readme) ||
|
if (cfg.is_vlib && dc.head.name == 'builtin' && !cfg.include_readme) ||
|
||||||
dc.head.name == 'README' {
|
dc.head.name == 'README'
|
||||||
|
{
|
||||||
href_name = './index.html'
|
href_name = './index.html'
|
||||||
} else if submod_prefix !in vd.docs.map(it.head.name) {
|
} else if submod_prefix !in vd.docs.map(it.head.name) {
|
||||||
href_name = '#'
|
href_name = '#'
|
||||||
|
@ -310,7 +311,8 @@ fn (vd VDoc) gen_html(d doc.Doc) string {
|
||||||
} else {
|
} else {
|
||||||
symbols_toc_str
|
symbols_toc_str
|
||||||
}).replace('{{ contents }}', contents.str()).replace('{{ right_content }}', if cfg.is_multi &&
|
}).replace('{{ contents }}', contents.str()).replace('{{ right_content }}', if cfg.is_multi &&
|
||||||
vd.docs.len > 1 && d.head.name != 'README' {
|
vd.docs.len > 1 && d.head.name != 'README'
|
||||||
|
{
|
||||||
'<div class="doc-toc"><ul>' + symbols_toc_str + '</ul></div>'
|
'<div class="doc-toc"><ul>' + symbols_toc_str + '</ul></div>'
|
||||||
} else {
|
} else {
|
||||||
''
|
''
|
||||||
|
@ -401,7 +403,8 @@ fn html_highlight(code string, tb &table.Table) string {
|
||||||
if token.is_key(tok.lit) || token.is_decl(tok.kind) {
|
if token.is_key(tok.lit) || token.is_decl(tok.kind) {
|
||||||
tok_typ = .keyword
|
tok_typ = .keyword
|
||||||
} else if tok.kind == .decl_assign || tok.kind.is_assign() || tok.is_unary() ||
|
} else if tok.kind == .decl_assign || tok.kind.is_assign() || tok.is_unary() ||
|
||||||
tok.kind.is_relational() || tok.kind.is_infix() {
|
tok.kind.is_relational() || tok.kind.is_infix()
|
||||||
|
{
|
||||||
tok_typ = .operator
|
tok_typ = .operator
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -160,7 +160,8 @@ fn (mut vt Vet) vet_file(path string, is_regression_test bool) {
|
||||||
fn (mut vet Vet) vet_line(lines []string, line string, lnumber int) {
|
fn (mut vet Vet) vet_line(lines []string, line string, lnumber int) {
|
||||||
// Vet public functions
|
// Vet public functions
|
||||||
if line.starts_with('pub fn') ||
|
if line.starts_with('pub fn') ||
|
||||||
(line.starts_with('fn ') && !(line.starts_with('fn C.') || line.starts_with('fn main'))) {
|
(line.starts_with('fn ') && !(line.starts_with('fn C.') || line.starts_with('fn main')))
|
||||||
|
{
|
||||||
// Scan function declarations for missing documentation
|
// Scan function declarations for missing documentation
|
||||||
is_pub_fn := line.starts_with('pub fn')
|
is_pub_fn := line.starts_with('pub fn')
|
||||||
if lnumber > 0 {
|
if lnumber > 0 {
|
||||||
|
|
|
@ -772,7 +772,8 @@ fn normalize_drive_letter(path string) string {
|
||||||
return path
|
return path
|
||||||
}
|
}
|
||||||
if path.len > 2 &&
|
if path.len > 2 &&
|
||||||
path[0] >= `a` && path[0] <= `z` && path[1] == `:` && path[2] == path_separator[0] {
|
path[0] >= `a` && path[0] <= `z` && path[1] == `:` && path[2] == path_separator[0]
|
||||||
|
{
|
||||||
unsafe {
|
unsafe {
|
||||||
x := &path.str[0]
|
x := &path.str[0]
|
||||||
(*x) = *x - 32
|
(*x) = *x - 32
|
||||||
|
|
|
@ -94,7 +94,8 @@ pub fn ls(path string) ?[]string {
|
||||||
unsafe {
|
unsafe {
|
||||||
if bptr[0] == 0 ||
|
if bptr[0] == 0 ||
|
||||||
(bptr[0] == `.` && bptr[1] == 0) ||
|
(bptr[0] == `.` && bptr[1] == 0) ||
|
||||||
(bptr[0] == `.` && bptr[1] == `.` && bptr[2] == 0) {
|
(bptr[0] == `.` && bptr[1] == `.` && bptr[2] == 0)
|
||||||
|
{
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -237,7 +237,8 @@ pub fn (b &Builder) find_module_path(mod string, fpath string) ?string {
|
||||||
mod_path := module_path(mod)
|
mod_path := module_path(mod)
|
||||||
mut module_lookup_paths := []string{}
|
mut module_lookup_paths := []string{}
|
||||||
if vmod_file_location.vmod_file.len != 0 &&
|
if vmod_file_location.vmod_file.len != 0 &&
|
||||||
vmod_file_location.vmod_folder !in b.module_search_paths {
|
vmod_file_location.vmod_folder !in b.module_search_paths
|
||||||
|
{
|
||||||
module_lookup_paths << vmod_file_location.vmod_folder
|
module_lookup_paths << vmod_file_location.vmod_folder
|
||||||
}
|
}
|
||||||
module_lookup_paths << b.module_search_paths
|
module_lookup_paths << b.module_search_paths
|
||||||
|
|
|
@ -210,7 +210,8 @@ fn (mut v Builder) setup_ccompiler_options(ccompiler string) {
|
||||||
if ccversion := os.exec('cc --version') {
|
if ccversion := os.exec('cc --version') {
|
||||||
if ccversion.exit_code == 0 {
|
if ccversion.exit_code == 0 {
|
||||||
if ccversion.output.contains('This is free software;') &&
|
if ccversion.output.contains('This is free software;') &&
|
||||||
ccversion.output.contains('Free Software Foundation, Inc.') {
|
ccversion.output.contains('Free Software Foundation, Inc.')
|
||||||
|
{
|
||||||
ccoptions.guessed_compiler = 'gcc'
|
ccoptions.guessed_compiler = 'gcc'
|
||||||
}
|
}
|
||||||
if ccversion.output.contains('clang version ') {
|
if ccversion.output.contains('clang version ') {
|
||||||
|
@ -351,7 +352,8 @@ fn (mut v Builder) setup_ccompiler_options(ccompiler string) {
|
||||||
// Without these libs compilation will fail on Linux
|
// Without these libs compilation will fail on Linux
|
||||||
// || os.user_os() == 'linux'
|
// || os.user_os() == 'linux'
|
||||||
if !v.pref.is_bare && v.pref.build_mode != .build_module && v.pref.os in
|
if !v.pref.is_bare && v.pref.build_mode != .build_module && v.pref.os in
|
||||||
[.linux, .freebsd, .openbsd, .netbsd, .dragonfly, .solaris, .haiku] {
|
[.linux, .freebsd, .openbsd, .netbsd, .dragonfly, .solaris, .haiku]
|
||||||
|
{
|
||||||
ccoptions.linker_flags << '-lm'
|
ccoptions.linker_flags << '-lm'
|
||||||
ccoptions.linker_flags << '-lpthread'
|
ccoptions.linker_flags << '-lpthread'
|
||||||
// -ldl is a Linux only thing. BSDs have it in libc.
|
// -ldl is a Linux only thing. BSDs have it in libc.
|
||||||
|
@ -399,7 +401,8 @@ fn (ccoptions CcompilerOptions) thirdparty_object_args(middle []string) []string
|
||||||
|
|
||||||
fn (mut v Builder) setup_output_name() {
|
fn (mut v Builder) setup_output_name() {
|
||||||
if !v.pref.is_shared && v.pref.build_mode != .build_module && os.user_os() == 'windows' &&
|
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.ends_with('.exe')
|
||||||
|
{
|
||||||
v.pref.out_name += '.exe'
|
v.pref.out_name += '.exe'
|
||||||
}
|
}
|
||||||
// Output executable name
|
// Output executable name
|
||||||
|
|
|
@ -21,7 +21,8 @@ fn (mut v Builder) get_os_cflags() []cflag.CFlag {
|
||||||
(flag.os == 'freebsd' && v.pref.os == .freebsd) ||
|
(flag.os == 'freebsd' && v.pref.os == .freebsd) ||
|
||||||
(flag.os == 'windows' && v.pref.os == .windows) ||
|
(flag.os == 'windows' && v.pref.os == .windows) ||
|
||||||
(flag.os == 'mingw' && v.pref.os == .windows && v.pref.ccompiler != 'msvc') ||
|
(flag.os == 'mingw' && v.pref.os == .windows && v.pref.ccompiler != 'msvc') ||
|
||||||
(flag.os == 'solaris' && v.pref.os == .solaris) {
|
(flag.os == 'solaris' && v.pref.os == .solaris)
|
||||||
|
{
|
||||||
flags << flag
|
flags << flag
|
||||||
}
|
}
|
||||||
if flag.os in ctimedefines {
|
if flag.os in ctimedefines {
|
||||||
|
|
|
@ -58,7 +58,8 @@ pub fn (mut c Checker) check_basic(got table.Type, expected table.Type) bool {
|
||||||
// TODO i64 as int etc
|
// TODO i64 as int etc
|
||||||
if (exp_idx in table.pointer_type_idxs ||
|
if (exp_idx in table.pointer_type_idxs ||
|
||||||
exp_idx in table.number_type_idxs) &&
|
exp_idx in table.number_type_idxs) &&
|
||||||
(got_idx in table.pointer_type_idxs || got_idx in table.number_type_idxs) {
|
(got_idx in table.pointer_type_idxs || got_idx in table.number_type_idxs)
|
||||||
|
{
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// if exp_idx in pointer_type_idxs && got_idx in pointer_type_idxs {
|
// if exp_idx in pointer_type_idxs && got_idx in pointer_type_idxs {
|
||||||
|
@ -67,12 +68,14 @@ pub fn (mut c Checker) check_basic(got table.Type, expected table.Type) bool {
|
||||||
// see hack in checker IndexExpr line #691
|
// see hack in checker IndexExpr line #691
|
||||||
if (got_idx == table.byte_type_idx &&
|
if (got_idx == table.byte_type_idx &&
|
||||||
exp_idx == table.byteptr_type_idx) ||
|
exp_idx == table.byteptr_type_idx) ||
|
||||||
(exp_idx == table.byte_type_idx && got_idx == table.byteptr_type_idx) {
|
(exp_idx == table.byte_type_idx && got_idx == table.byteptr_type_idx)
|
||||||
|
{
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if (got_idx == table.char_type_idx &&
|
if (got_idx == table.char_type_idx &&
|
||||||
exp_idx == table.charptr_type_idx) ||
|
exp_idx == table.charptr_type_idx) ||
|
||||||
(exp_idx == table.char_type_idx && got_idx == table.charptr_type_idx) {
|
(exp_idx == table.char_type_idx && got_idx == table.charptr_type_idx)
|
||||||
|
{
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// TODO: this should no longer be needed
|
// TODO: this should no longer be needed
|
||||||
|
@ -108,13 +111,15 @@ pub fn (mut c Checker) check_basic(got table.Type, expected table.Type) bool {
|
||||||
// TODO
|
// TODO
|
||||||
// accept [] when an expected type is an array
|
// accept [] when an expected type is an array
|
||||||
if got_type_sym.kind == .array &&
|
if got_type_sym.kind == .array &&
|
||||||
exp_type_sym.kind == .array && got_type_sym.name == 'array_void' {
|
exp_type_sym.kind == .array && got_type_sym.name == 'array_void'
|
||||||
|
{
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// type alias
|
// type alias
|
||||||
if (got_type_sym.kind == .alias &&
|
if (got_type_sym.kind == .alias &&
|
||||||
got_type_sym.parent_idx == exp_idx) ||
|
got_type_sym.parent_idx == exp_idx) ||
|
||||||
(exp_type_sym.kind == .alias && exp_type_sym.parent_idx == got_idx) {
|
(exp_type_sym.kind == .alias && exp_type_sym.parent_idx == got_idx)
|
||||||
|
{
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// sum type
|
// sum type
|
||||||
|
@ -238,7 +243,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
|
} else if idx_lo >= table.byte_type_idx { // both operands are unsigned
|
||||||
return type_hi
|
return type_hi
|
||||||
} else if idx_lo >= table.i8_type_idx &&
|
} else if idx_lo >= table.i8_type_idx &&
|
||||||
(idx_hi <= table.i64_type_idx || idx_hi == table.rune_type_idx) { // both signed
|
(idx_hi <= table.i64_type_idx || idx_hi == table.rune_type_idx)
|
||||||
|
{ // both signed
|
||||||
return if idx_lo == table.i64_type_idx {
|
return if idx_lo == table.i64_type_idx {
|
||||||
type_lo
|
type_lo
|
||||||
} else {
|
} else {
|
||||||
|
@ -360,7 +366,8 @@ pub fn (c &Checker) get_default_fmt(ftyp table.Type, typ table.Type) byte {
|
||||||
if ftyp in [table.string_type, table.bool_type] ||
|
if ftyp in [table.string_type, table.bool_type] ||
|
||||||
sym.kind in
|
sym.kind in
|
||||||
[.enum_, .array, .array_fixed, .struct_, .map, .multi_return, .sum_type, .none_] || ftyp.has_flag(.optional) ||
|
[.enum_, .array, .array_fixed, .struct_, .map, .multi_return, .sum_type, .none_] || ftyp.has_flag(.optional) ||
|
||||||
sym.has_method('str') {
|
sym.has_method('str')
|
||||||
|
{
|
||||||
return `s`
|
return `s`
|
||||||
} else {
|
} else {
|
||||||
return `_`
|
return `_`
|
||||||
|
@ -376,7 +383,8 @@ pub fn (mut c Checker) string_inter_lit(mut node ast.StringInterLiteral) table.T
|
||||||
mut fmt := node.fmts[i]
|
mut fmt := node.fmts[i]
|
||||||
// analyze and validate format specifier
|
// analyze and validate format specifier
|
||||||
if fmt !in
|
if fmt !in
|
||||||
[`E`, `F`, `G`, `e`, `f`, `g`, `d`, `u`, `x`, `X`, `o`, `c`, `s`, `p`, `_`] {
|
[`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])
|
c.error('unknown format specifier `${fmt:c}`', node.fmt_poss[i])
|
||||||
}
|
}
|
||||||
if fmt == `_` { // set default representation for type if none has been given
|
if fmt == `_` { // set default representation for type if none has been given
|
||||||
|
@ -403,7 +411,8 @@ pub fn (mut c Checker) string_inter_lit(mut node ast.StringInterLiteral) table.T
|
||||||
(typ.is_float() && fmt !in [`E`, `F`, `G`, `e`, `f`, `g`]) ||
|
(typ.is_float() && fmt !in [`E`, `F`, `G`, `e`, `f`, `g`]) ||
|
||||||
(typ.is_pointer() && fmt !in [`p`, `x`, `X`]) ||
|
(typ.is_pointer() && fmt !in [`p`, `x`, `X`]) ||
|
||||||
(typ.is_string() && fmt != `s`) ||
|
(typ.is_string() && fmt != `s`) ||
|
||||||
(typ.idx() in [table.i64_type_idx, table.f64_type_idx] && fmt == `c`) {
|
(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)}`',
|
c.error('illegal format specifier `${fmt:c}` for type `${c.table.get_type_name(ftyp)}`',
|
||||||
node.fmt_poss[i])
|
node.fmt_poss[i])
|
||||||
}
|
}
|
||||||
|
@ -438,7 +447,8 @@ pub fn (mut c Checker) infer_fn_types(f table.Fn, mut call_expr ast.CallExpr) {
|
||||||
mut param_elem_sym := c.table.get_type_symbol(param_elem_info.elem_type)
|
mut param_elem_sym := c.table.get_type_symbol(param_elem_info.elem_type)
|
||||||
for {
|
for {
|
||||||
if arg_elem_sym.kind == .array &&
|
if arg_elem_sym.kind == .array &&
|
||||||
param_elem_sym.kind == .array && param_elem_sym.name != 'T' {
|
param_elem_sym.kind == .array && param_elem_sym.name != 'T'
|
||||||
|
{
|
||||||
arg_elem_info = arg_elem_sym.info as table.Array
|
arg_elem_info = arg_elem_sym.info as table.Array
|
||||||
arg_elem_sym = c.table.get_type_symbol(arg_elem_info.elem_type)
|
arg_elem_sym = c.table.get_type_symbol(arg_elem_info.elem_type)
|
||||||
param_elem_info = param_elem_sym.info as table.Array
|
param_elem_info = param_elem_sym.info as table.Array
|
||||||
|
|
|
@ -501,7 +501,8 @@ pub fn (mut c Checker) struct_init(mut struct_init ast.StructInit) table.Type {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !type_sym.is_public && type_sym.kind != .placeholder && type_sym.mod != c.mod &&
|
if !type_sym.is_public && type_sym.kind != .placeholder && type_sym.mod != c.mod &&
|
||||||
type_sym.language != .c {
|
type_sym.language != .c
|
||||||
|
{
|
||||||
c.error('type `$type_sym.name` is private', struct_init.pos)
|
c.error('type `$type_sym.name` is private', struct_init.pos)
|
||||||
}
|
}
|
||||||
if type_sym.kind == .struct_ {
|
if type_sym.kind == .struct_ {
|
||||||
|
@ -618,7 +619,8 @@ pub fn (mut c Checker) struct_init(mut struct_init ast.StructInit) table.Type {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if info_field.typ.is_ptr() && !expr_type.is_ptr() && !expr_type.is_pointer() &&
|
if info_field.typ.is_ptr() && !expr_type.is_ptr() && !expr_type.is_pointer() &&
|
||||||
!expr_type.is_number() {
|
!expr_type.is_number()
|
||||||
|
{
|
||||||
c.error('ref', field.pos)
|
c.error('ref', field.pos)
|
||||||
}
|
}
|
||||||
struct_init.fields[i].typ = expr_type
|
struct_init.fields[i].typ = expr_type
|
||||||
|
@ -770,11 +772,13 @@ pub fn (mut c Checker) infix_expr(mut infix_expr ast.InfixExpr) table.Type {
|
||||||
}
|
}
|
||||||
.plus, .minus, .mul, .div, .mod, .xor, .amp, .pipe { // binary operators that expect matching types
|
.plus, .minus, .mul, .div, .mod, .xor, .amp, .pipe { // binary operators that expect matching types
|
||||||
if right.info is table.Alias &&
|
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.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)
|
right = c.table.get_type_symbol((right.info as table.Alias).parent_type)
|
||||||
}
|
}
|
||||||
if left.info is table.Alias &&
|
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.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)
|
left = c.table.get_type_symbol((left.info as table.Alias).parent_type)
|
||||||
}
|
}
|
||||||
if left.kind in [.array, .array_fixed, .map, .struct_] {
|
if left.kind in [.array, .array_fixed, .map, .struct_] {
|
||||||
|
@ -879,7 +883,8 @@ pub fn (mut c Checker) infix_expr(mut infix_expr ast.InfixExpr) table.Type {
|
||||||
return table.void_type
|
return table.void_type
|
||||||
}
|
}
|
||||||
if right.kind == .array &&
|
if right.kind == .array &&
|
||||||
c.check_types(left_value_type, c.table.value_type(right_type)) {
|
c.check_types(left_value_type, c.table.value_type(right_type))
|
||||||
|
{
|
||||||
// []T << []T
|
// []T << []T
|
||||||
return table.void_type
|
return table.void_type
|
||||||
}
|
}
|
||||||
|
@ -951,7 +956,8 @@ pub fn (mut c Checker) infix_expr(mut infix_expr ast.InfixExpr) table.Type {
|
||||||
c.error('bool types only have the following operators defined: `==`, `!=`, `||`, and `&&`',
|
c.error('bool types only have the following operators defined: `==`, `!=`, `||`, and `&&`',
|
||||||
infix_expr.pos)
|
infix_expr.pos)
|
||||||
} else if left_type == table.string_type &&
|
} else if left_type == table.string_type &&
|
||||||
infix_expr.op !in [.plus, .eq, .ne, .lt, .gt, .le, .ge] {
|
infix_expr.op !in [.plus, .eq, .ne, .lt, .gt, .le, .ge]
|
||||||
|
{
|
||||||
// TODO broken !in
|
// TODO broken !in
|
||||||
c.error('string types only have the following operators defined: `==`, `!=`, `<`, `>`, `<=`, `>=`, and `+`',
|
c.error('string types only have the following operators defined: `==`, `!=`, `<`, `>`, `<=`, `>=`, and `+`',
|
||||||
infix_expr.pos)
|
infix_expr.pos)
|
||||||
|
@ -1151,7 +1157,8 @@ pub fn (mut c Checker) call_expr(mut call_expr ast.CallExpr) table.Type {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if arg.expr is ast.Ident ||
|
if arg.expr is ast.Ident ||
|
||||||
arg.expr is ast.StringLiteral || arg.expr is ast.SelectorExpr {
|
arg.expr is ast.StringLiteral || arg.expr is ast.SelectorExpr
|
||||||
|
{
|
||||||
// Simple expressions like variables, string literals, selector expressions
|
// Simple expressions like variables, string literals, selector expressions
|
||||||
// (`x.field`) can't result in allocations and don't need to be assigned to
|
// (`x.field`) can't result in allocations and don't need to be assigned to
|
||||||
// temporary vars.
|
// temporary vars.
|
||||||
|
@ -1162,7 +1169,8 @@ pub fn (mut c Checker) call_expr(mut call_expr ast.CallExpr) table.Type {
|
||||||
}
|
}
|
||||||
// TODO copy pasta from above
|
// TODO copy pasta from above
|
||||||
if call_expr.receiver_type == table.string_type && !(call_expr.left is ast.Ident ||
|
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.left is ast.StringLiteral || call_expr.left is ast.SelectorExpr)
|
||||||
|
{
|
||||||
call_expr.free_receiver = true
|
call_expr.free_receiver = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1185,10 +1193,12 @@ fn (mut c Checker) check_map_and_filter(is_map bool, elem_typ table.Type, call_e
|
||||||
if arg_expr.decl.params.len > 1 {
|
if arg_expr.decl.params.len > 1 {
|
||||||
c.error('function needs exactly 1 argument', arg_expr.decl.pos)
|
c.error('function needs exactly 1 argument', arg_expr.decl.pos)
|
||||||
} else if is_map &&
|
} else if is_map &&
|
||||||
(arg_expr.decl.return_type == table.void_type || arg_expr.decl.params[0].typ != elem_typ) {
|
(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)
|
c.error('type mismatch, should use `fn(a $elem_sym.name) T {...}`', arg_expr.decl.pos)
|
||||||
} else if !is_map &&
|
} else if !is_map &&
|
||||||
(arg_expr.decl.return_type != table.bool_type || arg_expr.decl.params[0].typ != elem_typ) {
|
(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 {...}`',
|
c.error('type mismatch, should use `fn(a $elem_sym.name) bool {...}`',
|
||||||
arg_expr.decl.pos)
|
arg_expr.decl.pos)
|
||||||
}
|
}
|
||||||
|
@ -1202,11 +1212,13 @@ fn (mut c Checker) check_map_and_filter(is_map bool, elem_typ table.Type, call_e
|
||||||
if func.params.len > 1 {
|
if func.params.len > 1 {
|
||||||
c.error('function needs exactly 1 argument', call_expr.pos)
|
c.error('function needs exactly 1 argument', call_expr.pos)
|
||||||
} else if is_map &&
|
} else if is_map &&
|
||||||
(func.return_type == table.void_type || func.params[0].typ != elem_typ) {
|
(func.return_type == table.void_type || func.params[0].typ != elem_typ)
|
||||||
|
{
|
||||||
c.error('type mismatch, should use `fn(a $elem_sym.name) T {...}`',
|
c.error('type mismatch, should use `fn(a $elem_sym.name) T {...}`',
|
||||||
arg_expr.pos)
|
arg_expr.pos)
|
||||||
} else if !is_map &&
|
} else if !is_map &&
|
||||||
(func.return_type != table.bool_type || func.params[0].typ != elem_typ) {
|
(func.return_type != table.bool_type || func.params[0].typ != elem_typ)
|
||||||
|
{
|
||||||
c.error('type mismatch, should use `fn(a $elem_sym.name) bool {...}`',
|
c.error('type mismatch, should use `fn(a $elem_sym.name) bool {...}`',
|
||||||
arg_expr.pos)
|
arg_expr.pos)
|
||||||
}
|
}
|
||||||
|
@ -1379,7 +1391,8 @@ pub fn (mut c Checker) call_method(mut call_expr ast.CallExpr) table.Type {
|
||||||
}
|
}
|
||||||
if has_method {
|
if has_method {
|
||||||
if !method.is_pub && !c.is_builtin_mod && !c.pref.is_test && left_type_sym.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 {
|
left_type_sym.mod != ''
|
||||||
|
{ // method.mod != c.mod {
|
||||||
// If a private method is called outside of the module
|
// If a private method is called outside of the module
|
||||||
// its receiver type is defined in, show an error.
|
// its receiver type is defined in, show an error.
|
||||||
// println('warn $method_name lef.mod=$left_type_sym.mod c.mod=$c.mod')
|
// println('warn $method_name lef.mod=$left_type_sym.mod c.mod=$c.mod')
|
||||||
|
@ -1390,7 +1403,8 @@ pub fn (mut c Checker) call_method(mut call_expr ast.CallExpr) table.Type {
|
||||||
// call_expr.is_mut = true
|
// call_expr.is_mut = true
|
||||||
}
|
}
|
||||||
if method.return_type == table.void_type &&
|
if method.return_type == table.void_type &&
|
||||||
method.ctdefine.len > 0 && method.ctdefine !in c.pref.compile_defines {
|
method.ctdefine.len > 0 && method.ctdefine !in c.pref.compile_defines
|
||||||
|
{
|
||||||
call_expr.should_be_skipped = true
|
call_expr.should_be_skipped = true
|
||||||
}
|
}
|
||||||
nr_args := if method.params.len == 0 { 0 } else { method.params.len - 1 }
|
nr_args := if method.params.len == 0 { 0 } else { method.params.len - 1 }
|
||||||
|
@ -1677,7 +1691,8 @@ pub fn (mut c Checker) call_fn(mut call_expr ast.CallExpr) table.Type {
|
||||||
c.warn('function `$f.name` has been deprecated', call_expr.pos)
|
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`] &&
|
if f.is_unsafe && !c.inside_unsafe && f.language == .c && f.name[2] in [`m`, `s`] &&
|
||||||
f.mod == 'builtin' {
|
f.mod == 'builtin'
|
||||||
|
{
|
||||||
// builtin C.m*, C.s* only - temp
|
// builtin C.m*, C.s* only - temp
|
||||||
c.warn('function `$f.name` must be called from an `unsafe` block', call_expr.pos)
|
c.warn('function `$f.name` must be called from an `unsafe` block', call_expr.pos)
|
||||||
}
|
}
|
||||||
|
@ -1709,7 +1724,8 @@ pub fn (mut c Checker) call_fn(mut call_expr ast.CallExpr) table.Type {
|
||||||
call_expr.return_type = f.return_type
|
call_expr.return_type = f.return_type
|
||||||
}
|
}
|
||||||
if f.return_type == table.void_type &&
|
if f.return_type == table.void_type &&
|
||||||
f.ctdefine.len > 0 && f.ctdefine !in c.pref.compile_defines {
|
f.ctdefine.len > 0 && f.ctdefine !in c.pref.compile_defines
|
||||||
|
{
|
||||||
call_expr.should_be_skipped = true
|
call_expr.should_be_skipped = true
|
||||||
}
|
}
|
||||||
if f.language != .v || call_expr.language != .v {
|
if f.language != .v || call_expr.language != .v {
|
||||||
|
@ -2124,7 +2140,8 @@ pub fn (mut c Checker) return_stmt(mut return_stmt ast.Return) {
|
||||||
return_stmt.pos)
|
return_stmt.pos)
|
||||||
return
|
return
|
||||||
} else if return_stmt.exprs.len == 0 && !(c.expected_type == table.void_type ||
|
} else if return_stmt.exprs.len == 0 && !(c.expected_type == table.void_type ||
|
||||||
expected_type_sym.kind == .void) {
|
expected_type_sym.kind == .void)
|
||||||
|
{
|
||||||
c.error('too few arguments to return', return_stmt.pos)
|
c.error('too few arguments to return', return_stmt.pos)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -2162,7 +2179,8 @@ pub fn (mut c Checker) return_stmt(mut return_stmt ast.Return) {
|
||||||
for i, exp_type in expected_types {
|
for i, exp_type in expected_types {
|
||||||
got_typ := c.unwrap_generic(got_types[i])
|
got_typ := c.unwrap_generic(got_types[i])
|
||||||
if got_typ.has_flag(.optional) &&
|
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)) {
|
(!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()
|
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',
|
c.error('cannot use `${c.table.type_to_str(got_typ)}` as type `${c.table.type_to_str(exp_type)}` in return argument',
|
||||||
pos)
|
pos)
|
||||||
|
@ -2179,13 +2197,15 @@ pub fn (mut c Checker) return_stmt(mut return_stmt ast.Return) {
|
||||||
pos)
|
pos)
|
||||||
}
|
}
|
||||||
if (got_typ.is_ptr() || got_typ.is_pointer()) &&
|
if (got_typ.is_ptr() || got_typ.is_pointer()) &&
|
||||||
(!exp_type.is_ptr() && !exp_type.is_pointer()) {
|
(!exp_type.is_ptr() && !exp_type.is_pointer())
|
||||||
|
{
|
||||||
pos := return_stmt.exprs[i].position()
|
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',
|
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)
|
pos)
|
||||||
}
|
}
|
||||||
if (exp_type.is_ptr() || exp_type.is_pointer()) &&
|
if (exp_type.is_ptr() || exp_type.is_pointer()) &&
|
||||||
(!got_typ.is_ptr() && !got_typ.is_pointer()) && got_typ != table.int_literal_type {
|
(!got_typ.is_ptr() && !got_typ.is_pointer()) && got_typ != table.int_literal_type
|
||||||
|
{
|
||||||
pos := return_stmt.exprs[i].position()
|
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',
|
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)
|
pos)
|
||||||
|
@ -2466,7 +2486,8 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) {
|
||||||
}
|
}
|
||||||
if left_sym.kind == .array && !c.inside_unsafe && assign_stmt.op in [.assign, .decl_assign] &&
|
if left_sym.kind == .array && !c.inside_unsafe && assign_stmt.op in [.assign, .decl_assign] &&
|
||||||
right_sym.kind == .array &&
|
right_sym.kind == .array &&
|
||||||
(left is ast.Ident && !left.is_blank_ident()) && right is ast.Ident {
|
(left is ast.Ident && !left.is_blank_ident()) && right is ast.Ident
|
||||||
|
{
|
||||||
// Do not allow `a = b`, only `a = b.clone()`
|
// Do not allow `a = b`, only `a = b.clone()`
|
||||||
c.error('use `array2 = array1.clone()` instead of `array2 = array1` (or use `unsafe`)',
|
c.error('use `array2 = array1.clone()` instead of `array2 = array1` (or use `unsafe`)',
|
||||||
assign_stmt.pos)
|
assign_stmt.pos)
|
||||||
|
@ -2524,22 +2545,26 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) {
|
||||||
}
|
}
|
||||||
.mult_assign, .div_assign {
|
.mult_assign, .div_assign {
|
||||||
if !left_sym.is_number() &&
|
if !left_sym.is_number() &&
|
||||||
!c.table.get_final_type_symbol(left_type_unwrapped).is_int() && left_sym.kind !in [.struct_, .alias] {
|
!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`',
|
c.error('operator $assign_stmt.op.str() not defined on left operand type `$left_sym.name`',
|
||||||
left.position())
|
left.position())
|
||||||
} else if !right_sym.is_number() &&
|
} else if !right_sym.is_number() &&
|
||||||
!c.table.get_final_type_symbol(left_type_unwrapped).is_int() && left_sym.kind !in [.struct_, .alias] {
|
!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`',
|
c.error('operator $assign_stmt.op.str() not defined on right operand type `$right_sym.name`',
|
||||||
right.position())
|
right.position())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.and_assign, .or_assign, .xor_assign, .mod_assign, .left_shift_assign, .right_shift_assign {
|
.and_assign, .or_assign, .xor_assign, .mod_assign, .left_shift_assign, .right_shift_assign {
|
||||||
if !left_sym.is_int() &&
|
if !left_sym.is_int() &&
|
||||||
!c.table.get_final_type_symbol(left_type_unwrapped).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`',
|
c.error('operator $assign_stmt.op.str() not defined on left operand type `$left_sym.name`',
|
||||||
left.position())
|
left.position())
|
||||||
} else if !right_sym.is_int() &&
|
} else if !right_sym.is_int() &&
|
||||||
!c.table.get_final_type_symbol(right_type_unwrapped).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`',
|
c.error('operator $assign_stmt.op.str() not defined on right operand type `$right_sym.name`',
|
||||||
right.position())
|
right.position())
|
||||||
}
|
}
|
||||||
|
@ -2548,7 +2573,8 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) {
|
||||||
}
|
}
|
||||||
if assign_stmt.op in
|
if assign_stmt.op in
|
||||||
[.plus_assign, .minus_assign, .mod_assign, .mult_assign, .div_assign] &&
|
[.plus_assign, .minus_assign, .mod_assign, .mult_assign, .div_assign] &&
|
||||||
((left_sym.kind == .struct_ && right_sym.kind == .struct_) || left_sym.kind == .alias) {
|
((left_sym.kind == .struct_ && right_sym.kind == .struct_) || left_sym.kind == .alias)
|
||||||
|
{
|
||||||
left_name := c.table.type_to_str(left_type)
|
left_name := c.table.type_to_str(left_type)
|
||||||
right_name := c.table.type_to_str(right_type)
|
right_name := c.table.type_to_str(right_type)
|
||||||
parent_sym := c.table.get_final_type_symbol(left_type)
|
parent_sym := c.table.get_final_type_symbol(left_type)
|
||||||
|
@ -3062,7 +3088,8 @@ fn (mut c Checker) hash_stmt(mut node ast.HashStmt) {
|
||||||
}
|
}
|
||||||
flag_no_comment := flag.all_before('//').trim_space()
|
flag_no_comment := flag.all_before('//').trim_space()
|
||||||
if !((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('>'))) {
|
(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',
|
c.error('including C files should use either `"header_file.h"` or `<header_file.h>` quoting',
|
||||||
node.pos)
|
node.pos)
|
||||||
}
|
}
|
||||||
|
@ -3461,7 +3488,8 @@ pub fn (mut c Checker) cast_expr(mut node ast.CastExpr) table.Type {
|
||||||
}
|
}
|
||||||
} else if node.typ == table.string_type &&
|
} else if node.typ == table.string_type &&
|
||||||
(from_type_sym.kind in [.int_literal, .int, .byte, .byteptr, .bool] ||
|
(from_type_sym.kind in [.int_literal, .int, .byte, .byteptr, .bool] ||
|
||||||
(from_type_sym.kind == .array && from_type_sym.name == 'array_byte')) {
|
(from_type_sym.kind == .array && from_type_sym.name == 'array_byte'))
|
||||||
|
{
|
||||||
type_name := c.table.type_to_str(node.expr_type)
|
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)
|
c.error('cannot cast type `$type_name` to string, use `x.str()` instead', node.pos)
|
||||||
} else if node.expr_type == table.string_type {
|
} else if node.expr_type == table.string_type {
|
||||||
|
@ -3476,7 +3504,8 @@ pub fn (mut c Checker) cast_expr(mut node ast.CastExpr) table.Type {
|
||||||
}
|
}
|
||||||
} else if to_type_sym.kind == .byte &&
|
} 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 != table.voidptr_type && from_type_sym.kind != .enum_ && !node.expr_type.is_int() &&
|
||||||
!node.expr_type.is_float() && !node.expr_type.is_ptr() {
|
!node.expr_type.is_float() && !node.expr_type.is_ptr()
|
||||||
|
{
|
||||||
type_name := c.table.type_to_str(node.expr_type)
|
type_name := c.table.type_to_str(node.expr_type)
|
||||||
c.error('cannot cast type `$type_name` to `byte`', node.pos)
|
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 {
|
||||||
|
@ -4123,7 +4152,8 @@ pub fn (mut c Checker) select_expr(mut node ast.SelectExpr) table.Type {
|
||||||
} else {
|
} else {
|
||||||
if branch.stmt.expr is ast.InfixExpr {
|
if branch.stmt.expr is ast.InfixExpr {
|
||||||
if branch.stmt.expr.left !is ast.Ident &&
|
if branch.stmt.expr.left !is ast.Ident &&
|
||||||
branch.stmt.expr.left !is ast.SelectorExpr && branch.stmt.expr.left !is ast.IndexExpr {
|
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())
|
c.error('channel in `select` key must be predefined', branch.stmt.expr.left.position())
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -4136,7 +4166,8 @@ pub fn (mut c Checker) select_expr(mut node ast.SelectExpr) table.Type {
|
||||||
match expr {
|
match expr {
|
||||||
ast.PrefixExpr {
|
ast.PrefixExpr {
|
||||||
if expr.right !is ast.Ident &&
|
if expr.right !is ast.Ident &&
|
||||||
expr.right !is ast.SelectorExpr && expr.right !is ast.IndexExpr {
|
expr.right !is ast.SelectorExpr && expr.right !is ast.IndexExpr
|
||||||
|
{
|
||||||
c.error('channel in `select` key must be predefined', expr.right.position())
|
c.error('channel in `select` key must be predefined', expr.right.position())
|
||||||
}
|
}
|
||||||
if expr.or_block.kind != .absent {
|
if expr.or_block.kind != .absent {
|
||||||
|
@ -4217,7 +4248,8 @@ fn (mut c Checker) for_stmt(mut node ast.ForStmt) {
|
||||||
if infix.op == .key_is {
|
if infix.op == .key_is {
|
||||||
if (infix.left is ast.Ident ||
|
if (infix.left is ast.Ident ||
|
||||||
infix.left is ast.SelectorExpr) &&
|
infix.left is ast.SelectorExpr) &&
|
||||||
infix.right is ast.Type {
|
infix.right is ast.Type
|
||||||
|
{
|
||||||
right_expr := infix.right as ast.Type
|
right_expr := infix.right as ast.Type
|
||||||
is_variable := if mut infix.left is ast.Ident {
|
is_variable := if mut infix.left is ast.Ident {
|
||||||
infix.left.kind == .variable
|
infix.left.kind == .variable
|
||||||
|
@ -4290,7 +4322,8 @@ pub fn (mut c Checker) if_expr(mut node ast.IfExpr) table.Type {
|
||||||
}
|
}
|
||||||
if (infix.left is ast.Ident ||
|
if (infix.left is ast.Ident ||
|
||||||
infix.left is ast.SelectorExpr) &&
|
infix.left is ast.SelectorExpr) &&
|
||||||
infix.right is ast.Type {
|
infix.right is ast.Type
|
||||||
|
{
|
||||||
is_variable := if mut infix.left is ast.Ident {
|
is_variable := if mut infix.left is ast.Ident {
|
||||||
infix.left.kind == .variable
|
infix.left.kind == .variable
|
||||||
} else {
|
} else {
|
||||||
|
@ -4487,7 +4520,8 @@ fn (mut c Checker) comp_if_branch(cond ast.Expr, pos token.Position) bool {
|
||||||
.key_is, .not_is {
|
.key_is, .not_is {
|
||||||
if (cond.left is ast.SelectorExpr ||
|
if (cond.left is ast.SelectorExpr ||
|
||||||
cond.left is ast.Type) &&
|
cond.left is ast.Type) &&
|
||||||
cond.right is ast.Type {
|
cond.right is ast.Type
|
||||||
|
{
|
||||||
// $if method.@type is string
|
// $if method.@type is string
|
||||||
} else {
|
} else {
|
||||||
c.error('invalid `\$if` condition: $cond.left', cond.pos)
|
c.error('invalid `\$if` condition: $cond.left', cond.pos)
|
||||||
|
@ -4549,7 +4583,8 @@ fn (mut c Checker) comp_if_branch(cond ast.Expr, pos token.Position) bool {
|
||||||
// `$if some_var {}`
|
// `$if some_var {}`
|
||||||
typ := c.expr(cond)
|
typ := c.expr(cond)
|
||||||
if cond.obj !is ast.Var &&
|
if cond.obj !is ast.Var &&
|
||||||
cond.obj !is ast.ConstField && cond.obj !is ast.GlobalField {
|
cond.obj !is ast.ConstField && cond.obj !is ast.GlobalField
|
||||||
|
{
|
||||||
c.error('unknown var: `$cond.name`', pos)
|
c.error('unknown var: `$cond.name`', pos)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -4738,7 +4773,8 @@ pub fn (mut c Checker) index_expr(mut node ast.IndexExpr) table.Type {
|
||||||
node.left_type = typ
|
node.left_type = typ
|
||||||
typ_sym := c.table.get_final_type_symbol(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] &&
|
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) {
|
!typ.has_flag(.variadic)
|
||||||
|
{
|
||||||
c.error('type `$typ_sym.name` does not support indexing', node.pos)
|
c.error('type `$typ_sym.name` does not support indexing', node.pos)
|
||||||
}
|
}
|
||||||
if typ_sym.kind == .string && !typ.is_ptr() && node.is_setter {
|
if typ_sym.kind == .string && !typ.is_ptr() && node.is_setter {
|
||||||
|
@ -5153,14 +5189,16 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) {
|
||||||
for arg in node.params {
|
for arg in node.params {
|
||||||
sym := c.table.get_type_symbol(arg.typ)
|
sym := c.table.get_type_symbol(arg.typ)
|
||||||
if sym.kind == .placeholder ||
|
if sym.kind == .placeholder ||
|
||||||
(sym.kind in [table.Kind.int_literal, .float_literal] && !c.is_builtin_mod) {
|
(sym.kind in [table.Kind.int_literal, .float_literal] && !c.is_builtin_mod)
|
||||||
|
{
|
||||||
c.error('unknown type `$sym.name`', node.pos)
|
c.error('unknown type `$sym.name`', node.pos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return_sym := c.table.get_type_symbol(node.return_type)
|
return_sym := c.table.get_type_symbol(node.return_type)
|
||||||
if node.language == .v &&
|
if node.language == .v &&
|
||||||
return_sym.kind in [.placeholder, .int_literal, .float_literal] && return_sym.language == .v {
|
return_sym.kind in [.placeholder, .int_literal, .float_literal] && return_sym.language == .v
|
||||||
|
{
|
||||||
c.error('unknown type `$return_sym.name`', node.pos)
|
c.error('unknown type `$return_sym.name`', node.pos)
|
||||||
}
|
}
|
||||||
if node.language == .v && node.is_method && node.name == 'str' {
|
if node.language == .v && node.is_method && node.name == 'str' {
|
||||||
|
@ -5172,7 +5210,8 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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 {
|
if node.params.len != 2 {
|
||||||
c.error('operator methods should have exactly 1 argument', node.pos)
|
c.error('operator methods should have exactly 1 argument', node.pos)
|
||||||
} else {
|
} else {
|
||||||
|
@ -5190,7 +5229,8 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) {
|
||||||
} else if node.receiver.typ != node.params[1].typ {
|
} else if node.receiver.typ != node.params[1].typ {
|
||||||
c.error('both sides of an operator must be the same type', node.pos)
|
c.error('both sides of an operator must be the same type', node.pos)
|
||||||
} else if node.name in ['<', '>', '==', '!=', '>=', '<='] &&
|
} else if node.name in ['<', '>', '==', '!=', '>=', '<='] &&
|
||||||
node.return_type != table.bool_type {
|
node.return_type != table.bool_type
|
||||||
|
{
|
||||||
c.error('operator comparison methods should return `bool`', node.pos)
|
c.error('operator comparison methods should return `bool`', node.pos)
|
||||||
} else if parent_sym.is_primitive() {
|
} else if parent_sym.is_primitive() {
|
||||||
c.error('cannot define operator methods on type alias for `$parent_sym.name`',
|
c.error('cannot define operator methods on type alias for `$parent_sym.name`',
|
||||||
|
@ -5220,7 +5260,8 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) {
|
||||||
c.cur_fn = node
|
c.cur_fn = node
|
||||||
// Add return if `fn(...) ? {...}` have no return at end
|
// Add return if `fn(...) ? {...}` have no return at end
|
||||||
if node.return_type != table.void_type && node.return_type.has_flag(.optional) &&
|
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) {
|
(node.stmts.len == 0 || node.stmts[node.stmts.len - 1] !is ast.Return)
|
||||||
|
{
|
||||||
sym := c.table.get_type_symbol(node.return_type)
|
sym := c.table.get_type_symbol(node.return_type)
|
||||||
if sym.kind == .void {
|
if sym.kind == .void {
|
||||||
node.stmts << ast.Return{
|
node.stmts << ast.Return{
|
||||||
|
@ -5231,7 +5272,8 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) {
|
||||||
c.stmts(node.stmts)
|
c.stmts(node.stmts)
|
||||||
returns := c.returns || has_top_return(node.stmts)
|
returns := c.returns || has_top_return(node.stmts)
|
||||||
if node.language == .v && !node.no_body && node.return_type != table.void_type && !returns &&
|
if node.language == .v && !node.no_body && node.return_type != table.void_type && !returns &&
|
||||||
node.name !in ['panic', 'exit'] {
|
node.name !in ['panic', 'exit']
|
||||||
|
{
|
||||||
c.error('missing return at end of function `$node.name`', node.pos)
|
c.error('missing return at end of function `$node.name`', node.pos)
|
||||||
}
|
}
|
||||||
c.returns = false
|
c.returns = false
|
||||||
|
@ -5288,7 +5330,8 @@ fn (mut c Checker) verify_all_vweb_routes() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if f.return_type == typ_vweb_result &&
|
if f.return_type == typ_vweb_result &&
|
||||||
f.receiver.typ == m.params[0].typ && f.name == m.name {
|
f.receiver.typ == m.params[0].typ && f.name == m.name
|
||||||
|
{
|
||||||
c.file = f.source_file // setup of file path for the warning
|
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)',
|
c.warn('mismatched parameters count between vweb method `${sym_app.name}.$m.name` ($nargs) and route attribute $m.attrs ($nroute_attributes)',
|
||||||
f.pos)
|
f.pos)
|
||||||
|
|
|
@ -158,7 +158,8 @@ fn (mut f Fmt) adjust_complete_line() {
|
||||||
// search for next position with low penalty and same precedence to form subexpression
|
// search for next position with low penalty and same precedence to form subexpression
|
||||||
for j in i .. f.penalties.len {
|
for j in i .. f.penalties.len {
|
||||||
if f.penalties[j] <= 1 &&
|
if f.penalties[j] <= 1 &&
|
||||||
f.precedences[j] == precedence && len_sub_expr >= max_len[1] {
|
f.precedences[j] == precedence && len_sub_expr >= max_len[1]
|
||||||
|
{
|
||||||
sub_expr_end_idx = j
|
sub_expr_end_idx = j
|
||||||
break
|
break
|
||||||
} else if f.precedences[j] < precedence {
|
} else if f.precedences[j] < precedence {
|
||||||
|
@ -1555,9 +1556,16 @@ pub fn (mut f Fmt) if_expr(it ast.IfExpr) {
|
||||||
}
|
}
|
||||||
if i < it.branches.len - 1 || !it.has_else {
|
if i < it.branches.len - 1 || !it.has_else {
|
||||||
f.write('${dollar}if ')
|
f.write('${dollar}if ')
|
||||||
|
cur_pos := f.out.len
|
||||||
f.expr(branch.cond)
|
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('{')
|
f.write('{')
|
||||||
if single_line {
|
if single_line {
|
||||||
f.write(' ')
|
f.write(' ')
|
||||||
|
@ -1857,11 +1865,13 @@ pub fn (mut f Fmt) array_init(it ast.ArrayInit) {
|
||||||
mut penalty := if line_break && !is_same_line_comment { 0 } else { 3 }
|
mut penalty := if line_break && !is_same_line_comment { 0 } else { 3 }
|
||||||
if penalty > 0 {
|
if penalty > 0 {
|
||||||
if i == 0 || it.exprs[i - 1] is ast.ArrayInit || it.exprs[i - 1] is ast.StructInit ||
|
if i == 0 || it.exprs[i - 1] is ast.ArrayInit || it.exprs[i - 1] is ast.StructInit ||
|
||||||
it.exprs[i - 1] is ast.MapInit || it.exprs[i - 1] is ast.CallExpr {
|
it.exprs[i - 1] is ast.MapInit || it.exprs[i - 1] is ast.CallExpr
|
||||||
|
{
|
||||||
penalty--
|
penalty--
|
||||||
}
|
}
|
||||||
if expr is ast.ArrayInit ||
|
if expr is ast.ArrayInit ||
|
||||||
expr is ast.StructInit || expr is ast.MapInit || expr is ast.CallExpr {
|
expr is ast.StructInit || expr is ast.MapInit || expr is ast.CallExpr
|
||||||
|
{
|
||||||
penalty--
|
penalty--
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2021,7 +2031,8 @@ pub fn (mut f Fmt) struct_init(it ast.StructInit) {
|
||||||
f.comments(field.next_comments, inline: false, has_nl: true, level: .keep)
|
f.comments(field.next_comments, inline: false, has_nl: true, level: .keep)
|
||||||
if single_line_fields &&
|
if single_line_fields &&
|
||||||
(field.comments.len > 0 ||
|
(field.comments.len > 0 ||
|
||||||
field.next_comments.len > 0 || !expr_is_single_line(field.expr) || f.line_len > max_len.last()) {
|
field.next_comments.len > 0 || !expr_is_single_line(field.expr) || f.line_len > max_len.last())
|
||||||
|
{
|
||||||
single_line_fields = false
|
single_line_fields = false
|
||||||
f.out.go_back_to(fields_start)
|
f.out.go_back_to(fields_start)
|
||||||
f.line_len = fields_start
|
f.line_len = fields_start
|
||||||
|
|
|
@ -12,7 +12,8 @@ fn string_inter_lit(mut c checker.Checker, mut node ast.StringInterLiteral) tabl
|
||||||
mut fmt := node.fmts[i]
|
mut fmt := node.fmts[i]
|
||||||
// analyze and validate format specifier
|
// analyze and validate format specifier
|
||||||
if fmt !in
|
if fmt !in
|
||||||
[`E`, `F`, `G`, `e`, `f`, `g`, `d`, `u`, `x`, `X`, `o`, `c`, `s`, `p`, `_`] {
|
[`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])
|
c.error('unknown format specifier `${fmt:c}`', node.fmt_poss[i])
|
||||||
}
|
}
|
||||||
if node.precisions[i] != 987698 && !typ.is_float() {
|
if node.precisions[i] != 987698 && !typ.is_float() {
|
||||||
|
@ -27,7 +28,8 @@ fn string_inter_lit(mut c checker.Checker, mut node ast.StringInterLiteral) tabl
|
||||||
(typ.is_float() && fmt !in [`E`, `F`, `G`, `e`, `f`, `g`]) ||
|
(typ.is_float() && fmt !in [`E`, `F`, `G`, `e`, `f`, `g`]) ||
|
||||||
(typ.is_pointer() && fmt !in [`p`, `x`, `X`]) ||
|
(typ.is_pointer() && fmt !in [`p`, `x`, `X`]) ||
|
||||||
(typ.is_string() && fmt != `s`) ||
|
(typ.is_string() && fmt != `s`) ||
|
||||||
(typ.idx() in [table.i64_type_idx, table.f64_type_idx] && fmt == `c`) {
|
(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)}`',
|
c.error('illegal format specifier `${fmt:c}` for type `${c.table.get_type_name(ftyp)}`',
|
||||||
node.fmt_poss[i])
|
node.fmt_poss[i])
|
||||||
}
|
}
|
||||||
|
@ -54,7 +56,8 @@ fn main() {
|
||||||
' that is followd by an even longer part that should go to another line')
|
' that is followd by an even longer part that should go to another line')
|
||||||
if (a == b && b > r) ||
|
if (a == b && b > r) ||
|
||||||
(d > r) || (a < b) || (b < d && a + b > r) ||
|
(d > r) || (a < b) || (b < d && a + b > r) ||
|
||||||
(a + b + d >= 0 && r < 0) || (a > b && d - r < b) {
|
(a + b + d >= 0 && r < 0) || (a > b && d - r < b)
|
||||||
|
{
|
||||||
println('ok')
|
println('ok')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -73,7 +76,8 @@ struct Parser {
|
||||||
|
|
||||||
fn (mut p Parser) name_expr() {
|
fn (mut p Parser) name_expr() {
|
||||||
if p.peek_tok.kind == .lpar ||
|
if p.peek_tok.kind == .lpar ||
|
||||||
(p.peek_tok.kind == .lt && p.peek_tok2.kind == .name && p.peek_tok3.kind == .gt) {
|
(p.peek_tok.kind == .lt && p.peek_tok2.kind == .name && p.peek_tok3.kind == .gt)
|
||||||
|
{
|
||||||
println(p.peek_tok.lit)
|
println(p.peek_tok.lit)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -108,7 +108,8 @@ fn test_select_blocks() {
|
||||||
else {
|
else {
|
||||||
h = 2
|
h = 2
|
||||||
}
|
}
|
||||||
} {
|
}
|
||||||
|
{
|
||||||
panic('channel is still open')
|
panic('channel is still open')
|
||||||
} else {
|
} else {
|
||||||
is_open = false
|
is_open = false
|
||||||
|
|
|
@ -41,7 +41,8 @@ fn (g &Gen) type_to_fmt(typ table.Type) string {
|
||||||
if typ.is_ptr() && (typ.is_int() || typ.is_float()) {
|
if typ.is_ptr() && (typ.is_int() || typ.is_float()) {
|
||||||
return '%.*s\\000'
|
return '%.*s\\000'
|
||||||
} else if sym.kind in
|
} else if sym.kind in
|
||||||
[.struct_, .array, .array_fixed, .map, .bool, .enum_, .interface_, .sum_type, .function] {
|
[.struct_, .array, .array_fixed, .map, .bool, .enum_, .interface_, .sum_type, .function]
|
||||||
|
{
|
||||||
return '%.*s\\000'
|
return '%.*s\\000'
|
||||||
} else if sym.kind == .string {
|
} else if sym.kind == .string {
|
||||||
return "'%.*s\\000'"
|
return "'%.*s\\000'"
|
||||||
|
|
|
@ -989,7 +989,8 @@ fn (mut g Gen) stmt(node ast.Stmt) {
|
||||||
mod := if g.is_builtin_mod { 'builtin' } else { node.name.all_before_last('.') }
|
mod := if g.is_builtin_mod { 'builtin' } else { node.name.all_before_last('.') }
|
||||||
if (mod != g.module_built &&
|
if (mod != g.module_built &&
|
||||||
node.mod != g.module_built.after('/')) ||
|
node.mod != g.module_built.after('/')) ||
|
||||||
should_bundle_module {
|
should_bundle_module
|
||||||
|
{
|
||||||
// Skip functions that don't have to be generated for this 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')
|
// println('skip bm $node.name mod=$node.mod module_built=$g.module_built')
|
||||||
skip = true
|
skip = true
|
||||||
|
@ -1014,12 +1015,14 @@ fn (mut g Gen) stmt(node ast.Stmt) {
|
||||||
g.has_main = true
|
g.has_main = true
|
||||||
}
|
}
|
||||||
if node.name == 'backtrace' ||
|
if node.name == 'backtrace' ||
|
||||||
node.name == 'backtrace_symbols' || node.name == 'backtrace_symbols_fd' {
|
node.name == 'backtrace_symbols' || node.name == 'backtrace_symbols_fd'
|
||||||
|
{
|
||||||
g.write('\n#ifndef __cplusplus\n')
|
g.write('\n#ifndef __cplusplus\n')
|
||||||
}
|
}
|
||||||
g.gen_fn_decl(node, skip)
|
g.gen_fn_decl(node, skip)
|
||||||
if node.name == 'backtrace' ||
|
if node.name == 'backtrace' ||
|
||||||
node.name == 'backtrace_symbols' || node.name == 'backtrace_symbols_fd' {
|
node.name == 'backtrace_symbols' || node.name == 'backtrace_symbols_fd'
|
||||||
|
{
|
||||||
g.write('\n#endif\n')
|
g.write('\n#endif\n')
|
||||||
}
|
}
|
||||||
g.fn_decl = keep_fn_decl
|
g.fn_decl = keep_fn_decl
|
||||||
|
@ -1963,7 +1966,8 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
|
||||||
if ((left_sym.kind == .struct_ &&
|
if ((left_sym.kind == .struct_ &&
|
||||||
right_sym.kind == .struct_) || (left_sym.kind == .alias &&
|
right_sym.kind == .struct_) || (left_sym.kind == .alias &&
|
||||||
right_sym.kind == .alias)) &&
|
right_sym.kind == .alias)) &&
|
||||||
assign_stmt.op in [.plus_assign, .minus_assign, .div_assign, .mult_assign, .mod_assign] {
|
assign_stmt.op in [.plus_assign, .minus_assign, .div_assign, .mult_assign, .mod_assign]
|
||||||
|
{
|
||||||
extracted_op := match assign_stmt.op {
|
extracted_op := match assign_stmt.op {
|
||||||
.plus_assign { '+' }
|
.plus_assign { '+' }
|
||||||
.minus_assign { '-' }
|
.minus_assign { '-' }
|
||||||
|
@ -2296,7 +2300,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 !isnil(scope.parent) && line_nr > 0 {
|
||||||
if free_parent_scopes && !isnil(scope.parent) &&
|
if free_parent_scopes && !isnil(scope.parent) &&
|
||||||
(stop_pos == -1 || scope.parent.start_pos >= stop_pos) {
|
(stop_pos == -1 || scope.parent.start_pos >= stop_pos)
|
||||||
|
{
|
||||||
g.writeln('// af parent scope:')
|
g.writeln('// af parent scope:')
|
||||||
g.autofree_scope_vars2(scope.parent, start_pos, end_pos, line_nr, true, stop_pos)
|
g.autofree_scope_vars2(scope.parent, start_pos, end_pos, line_nr, true, stop_pos)
|
||||||
}
|
}
|
||||||
|
@ -2455,7 +2460,8 @@ fn (mut g Gen) expr(node ast.Expr) {
|
||||||
// println('before:' + node.autofree_pregen)
|
// println('before:' + node.autofree_pregen)
|
||||||
// }
|
// }
|
||||||
if g.is_autofree && !g.is_builtin_mod && !g.is_js_call && g.strs_to_free0.len == 0 &&
|
if g.is_autofree && !g.is_builtin_mod && !g.is_js_call && g.strs_to_free0.len == 0 &&
|
||||||
!g.inside_lambda { // && g.inside_ternary ==
|
!g.inside_lambda
|
||||||
|
{ // && g.inside_ternary ==
|
||||||
// if len != 0, that means we are handling call expr inside call expr (arg)
|
// 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()
|
// and it'll get messed up here, since it's handled recursively in autofree_call_pregen()
|
||||||
// so just skip it
|
// so just skip it
|
||||||
|
@ -2522,13 +2528,15 @@ fn (mut g Gen) expr(node ast.Expr) {
|
||||||
mut cast_label := ''
|
mut cast_label := ''
|
||||||
// `table.string_type` is done for MSVC's bug
|
// `table.string_type` is done for MSVC's bug
|
||||||
if sym.kind != .alias ||
|
if sym.kind != .alias ||
|
||||||
(sym.info as table.Alias).parent_type !in [node.expr_type, table.string_type] {
|
(sym.info as table.Alias).parent_type !in [node.expr_type, table.string_type]
|
||||||
|
{
|
||||||
cast_label = '($styp)'
|
cast_label = '($styp)'
|
||||||
}
|
}
|
||||||
g.write('(${cast_label}(')
|
g.write('(${cast_label}(')
|
||||||
g.expr(node.expr)
|
g.expr(node.expr)
|
||||||
if node.expr is ast.IntegerLiteral &&
|
if node.expr is ast.IntegerLiteral &&
|
||||||
node.typ in [table.u64_type, table.u32_type, table.u16_type] {
|
node.typ in [table.u64_type, table.u32_type, table.u16_type]
|
||||||
|
{
|
||||||
g.write('U')
|
g.write('U')
|
||||||
}
|
}
|
||||||
g.write('))')
|
g.write('))')
|
||||||
|
@ -2995,7 +3003,8 @@ fn (mut g Gen) infix_expr(node ast.InfixExpr) {
|
||||||
} else if unaliased_left == table.string_type_idx && node.op !in [.key_in, .not_in] {
|
} else if unaliased_left == table.string_type_idx && node.op !in [.key_in, .not_in] {
|
||||||
// `str == ''` -> `str.len == 0` optimization
|
// `str == ''` -> `str.len == 0` optimization
|
||||||
if node.op in [.eq, .ne] &&
|
if node.op in [.eq, .ne] &&
|
||||||
node.right is ast.StringLiteral && (node.right as ast.StringLiteral).val == '' {
|
node.right is ast.StringLiteral && (node.right as ast.StringLiteral).val == ''
|
||||||
|
{
|
||||||
arrow := if left_type.is_ptr() { '->' } else { '.' }
|
arrow := if left_type.is_ptr() { '->' } else { '.' }
|
||||||
g.write('(')
|
g.write('(')
|
||||||
g.expr(node.left)
|
g.expr(node.left)
|
||||||
|
@ -3052,7 +3061,8 @@ fn (mut g Gen) infix_expr(node ast.InfixExpr) {
|
||||||
g.expr(node.right)
|
g.expr(node.right)
|
||||||
g.write(')')
|
g.write(')')
|
||||||
} else if node.op in [.eq, .ne] &&
|
} else if node.op in [.eq, .ne] &&
|
||||||
left_sym.kind == .array_fixed && right_sym.kind == .array_fixed {
|
left_sym.kind == .array_fixed && right_sym.kind == .array_fixed
|
||||||
|
{
|
||||||
ptr_typ := g.gen_fixed_array_equality_fn(left_type)
|
ptr_typ := g.gen_fixed_array_equality_fn(left_type)
|
||||||
if node.op == .ne {
|
if node.op == .ne {
|
||||||
g.write('!')
|
g.write('!')
|
||||||
|
@ -3091,7 +3101,8 @@ fn (mut g Gen) infix_expr(node ast.InfixExpr) {
|
||||||
g.expr(node.right)
|
g.expr(node.right)
|
||||||
g.write(')')
|
g.write(')')
|
||||||
} else if node.op in [.eq, .ne] &&
|
} else if node.op in [.eq, .ne] &&
|
||||||
left_sym.kind == .struct_ && right_sym.kind == .struct_ && has_eq_overloaded && has_ne_overloaded {
|
left_sym.kind == .struct_ && right_sym.kind == .struct_ && has_eq_overloaded && has_ne_overloaded
|
||||||
|
{
|
||||||
ptr_typ := g.gen_struct_equality_fn(left_type)
|
ptr_typ := g.gen_struct_equality_fn(left_type)
|
||||||
if node.op == .eq {
|
if node.op == .eq {
|
||||||
g.write('${ptr_typ}_struct_eq(')
|
g.write('${ptr_typ}_struct_eq(')
|
||||||
|
@ -3233,18 +3244,22 @@ fn (mut g Gen) infix_expr(node ast.InfixExpr) {
|
||||||
g.or_block(tmp_opt, node.or_block, table.void_type)
|
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() &&
|
} 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] {
|
node.op in [.eq, .ne, .gt, .lt, .ge, .le]
|
||||||
|
{
|
||||||
bitsize := if unaliased_left.idx() == table.u32_type_idx &&
|
bitsize := if unaliased_left.idx() == table.u32_type_idx &&
|
||||||
unaliased_right.idx() != table.i64_type_idx { 32 } else { 64 }
|
unaliased_right.idx() != table.i64_type_idx
|
||||||
|
{ 32 } else { 64 }
|
||||||
g.write('_us${bitsize}_${cmp_str[int(node.op) - int(token.Kind.eq)]}(')
|
g.write('_us${bitsize}_${cmp_str[int(node.op) - int(token.Kind.eq)]}(')
|
||||||
g.expr(node.left)
|
g.expr(node.left)
|
||||||
g.write(',')
|
g.write(',')
|
||||||
g.expr(node.right)
|
g.expr(node.right)
|
||||||
g.write(')')
|
g.write(')')
|
||||||
} else if unaliased_right.idx() in [table.u32_type_idx, table.u64_type_idx] && unaliased_left.is_signed() &&
|
} 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] {
|
node.op in [.eq, .ne, .gt, .lt, .ge, .le]
|
||||||
|
{
|
||||||
bitsize := if unaliased_right.idx() == table.u32_type_idx &&
|
bitsize := if unaliased_right.idx() == table.u32_type_idx &&
|
||||||
unaliased_left.idx() != table.i64_type_idx { 32 } else { 64 }
|
unaliased_left.idx() != table.i64_type_idx
|
||||||
|
{ 32 } else { 64 }
|
||||||
g.write('_us${bitsize}_${cmp_rev[int(node.op) - int(token.Kind.eq)]}(')
|
g.write('_us${bitsize}_${cmp_rev[int(node.op) - int(token.Kind.eq)]}(')
|
||||||
g.expr(node.right)
|
g.expr(node.right)
|
||||||
g.write(',')
|
g.write(',')
|
||||||
|
@ -3261,7 +3276,8 @@ fn (mut g Gen) infix_expr(node ast.InfixExpr) {
|
||||||
// Do not generate operator overloading with these `right_sym.kind`.
|
// Do not generate operator overloading with these `right_sym.kind`.
|
||||||
e := right_sym.kind !in [.voidptr, .int_literal, .int]
|
e := right_sym.kind !in [.voidptr, .int_literal, .int]
|
||||||
if node.op in [.plus, .minus, .mul, .div, .mod, .lt, .gt, .eq, .ne, .le, .ge] &&
|
if node.op in [.plus, .minus, .mul, .div, .mod, .lt, .gt, .eq, .ne, .le, .ge] &&
|
||||||
((a && b && e) || c || d) {
|
((a && b && e) || c || d)
|
||||||
|
{
|
||||||
// Overloaded operators
|
// Overloaded operators
|
||||||
g.write(g.typ(if !d {
|
g.write(g.typ(if !d {
|
||||||
left_type
|
left_type
|
||||||
|
@ -3466,7 +3482,8 @@ fn (mut g Gen) match_expr_classic(node ast.MatchExpr, is_expr bool, cond_var str
|
||||||
mut skip_low := false
|
mut skip_low := false
|
||||||
if expr.low is ast.IntegerLiteral {
|
if expr.low is ast.IntegerLiteral {
|
||||||
if node.cond_type in [table.u16_type, table.u32_type, table.u64_type] &&
|
if node.cond_type in [table.u16_type, table.u32_type, table.u64_type] &&
|
||||||
expr.low.val == '0' {
|
expr.low.val == '0'
|
||||||
|
{
|
||||||
skip_low = true
|
skip_low = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3533,7 +3550,8 @@ fn (mut g Gen) select_expr(node ast.SelectExpr) {
|
||||||
expr := branch.stmt.expr as ast.InfixExpr
|
expr := branch.stmt.expr as ast.InfixExpr
|
||||||
channels << expr.left
|
channels << expr.left
|
||||||
if expr.right is ast.Ident ||
|
if expr.right is ast.Ident ||
|
||||||
expr.right is ast.IndexExpr || expr.right is ast.SelectorExpr || expr.right is ast.StructInit {
|
expr.right is ast.IndexExpr || expr.right is ast.SelectorExpr || expr.right is ast.StructInit
|
||||||
|
{
|
||||||
// addressable objects in the `C` output
|
// addressable objects in the `C` output
|
||||||
objs << expr.right
|
objs << expr.right
|
||||||
tmp_objs << ''
|
tmp_objs << ''
|
||||||
|
@ -3554,7 +3572,8 @@ fn (mut g Gen) select_expr(node ast.SelectExpr) {
|
||||||
is_push << false
|
is_push << false
|
||||||
// create tmp unless the object with *exactly* the type we need exists already
|
// create tmp unless the object with *exactly* the type we need exists already
|
||||||
if branch.stmt.op == .decl_assign ||
|
if branch.stmt.op == .decl_assign ||
|
||||||
branch.stmt.right_types[0] != branch.stmt.left_types[0] {
|
branch.stmt.right_types[0] != branch.stmt.left_types[0]
|
||||||
|
{
|
||||||
tmp_obj := g.new_tmp_var()
|
tmp_obj := g.new_tmp_var()
|
||||||
tmp_objs << tmp_obj
|
tmp_objs << tmp_obj
|
||||||
el_stype := g.typ(branch.stmt.right_types[0])
|
el_stype := g.typ(branch.stmt.right_types[0])
|
||||||
|
@ -4078,7 +4097,8 @@ fn (mut g Gen) index_expr(node ast.IndexExpr) {
|
||||||
g.write('$zero }))')
|
g.write('$zero }))')
|
||||||
}
|
}
|
||||||
} else if (g.inside_map_postfix || g.inside_map_infix) ||
|
} else if (g.inside_map_postfix || g.inside_map_infix) ||
|
||||||
(g.is_assign_lhs && !g.is_array_set && get_and_set_types) {
|
(g.is_assign_lhs && !g.is_array_set && get_and_set_types)
|
||||||
|
{
|
||||||
zero := g.type_default(info.value_type)
|
zero := g.type_default(info.value_type)
|
||||||
g.write('(*($elem_type_str*)map_get_and_set_1(')
|
g.write('(*($elem_type_str*)map_get_and_set_1(')
|
||||||
if !left_is_ptr {
|
if !left_is_ptr {
|
||||||
|
@ -4543,7 +4563,8 @@ fn (mut g Gen) struct_init(struct_init ast.StructInit) {
|
||||||
}
|
}
|
||||||
if !cloned {
|
if !cloned {
|
||||||
if field.expected_type.is_ptr() && !(field.typ.is_ptr() || field.typ.is_pointer()) &&
|
if field.expected_type.is_ptr() && !(field.typ.is_ptr() || field.typ.is_pointer()) &&
|
||||||
!field.typ.is_number() {
|
!field.typ.is_number()
|
||||||
|
{
|
||||||
g.write('/* autoref */&')
|
g.write('/* autoref */&')
|
||||||
}
|
}
|
||||||
g.expr_with_cast(field.expr, field.typ, field.expected_type)
|
g.expr_with_cast(field.expr, field.typ, field.expected_type)
|
||||||
|
@ -4615,7 +4636,8 @@ fn (mut g Gen) struct_init(struct_init ast.StructInit) {
|
||||||
g.interface_call(sfield.typ, sfield.expected_type)
|
g.interface_call(sfield.typ, sfield.expected_type)
|
||||||
}
|
}
|
||||||
if sfield.expected_type.is_ptr() && !(sfield.typ.is_ptr() || sfield.typ.is_pointer()) &&
|
if sfield.expected_type.is_ptr() && !(sfield.typ.is_ptr() || sfield.typ.is_pointer()) &&
|
||||||
!sfield.typ.is_number() {
|
!sfield.typ.is_number()
|
||||||
|
{
|
||||||
g.write('/* autoref */&')
|
g.write('/* autoref */&')
|
||||||
}
|
}
|
||||||
g.expr_with_cast(sfield.expr, sfield.typ, sfield.expected_type)
|
g.expr_with_cast(sfield.expr, sfield.typ, sfield.expected_type)
|
||||||
|
@ -5066,7 +5088,8 @@ fn (mut g Gen) or_block(var_name string, or_block ast.OrExpr, return_type table.
|
||||||
}
|
}
|
||||||
stmts := or_block.stmts
|
stmts := or_block.stmts
|
||||||
if stmts.len > 0 && stmts[or_block.stmts.len - 1] is ast.ExprStmt && (stmts[stmts.len -
|
if stmts.len > 0 && stmts[or_block.stmts.len - 1] is ast.ExprStmt && (stmts[stmts.len -
|
||||||
1] as ast.ExprStmt).typ != table.void_type {
|
1] as ast.ExprStmt).typ != table.void_type
|
||||||
|
{
|
||||||
g.indent++
|
g.indent++
|
||||||
for i, stmt in stmts {
|
for i, stmt in stmts {
|
||||||
if i == stmts.len - 1 {
|
if i == stmts.len - 1 {
|
||||||
|
@ -5279,7 +5302,8 @@ fn (mut g Gen) comp_if_to_ifdef(name string, is_comptime_optional bool) ?string
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if is_comptime_optional ||
|
if is_comptime_optional ||
|
||||||
(g.pref.compile_defines_all.len > 0 && name in g.pref.compile_defines_all) {
|
(g.pref.compile_defines_all.len > 0 && name in g.pref.compile_defines_all)
|
||||||
|
{
|
||||||
return 'CUSTOM_DEFINE_$name'
|
return 'CUSTOM_DEFINE_$name'
|
||||||
}
|
}
|
||||||
return error('bad os ifdef name "$name"') // should never happen, caught in the checker
|
return error('bad os ifdef name "$name"') // should never happen, caught in the checker
|
||||||
|
|
|
@ -18,7 +18,8 @@ fn (mut g Gen) comptime_selector(node ast.ComptimeSelector) {
|
||||||
if node.field_expr is ast.SelectorExpr {
|
if node.field_expr is ast.SelectorExpr {
|
||||||
if node.field_expr.expr is ast.Ident {
|
if node.field_expr.expr is ast.Ident {
|
||||||
if node.field_expr.expr.name == g.comp_for_field_var &&
|
if node.field_expr.expr.name == g.comp_for_field_var &&
|
||||||
node.field_expr.field_name == 'name' {
|
node.field_expr.field_name == 'name'
|
||||||
|
{
|
||||||
g.write(g.comp_for_field_value.name)
|
g.write(g.comp_for_field_value.name)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -127,7 +127,8 @@ fn (mut g Gen) gen_fn_decl(it ast.FnDecl, skip bool) {
|
||||||
fargs, fargtypes := g.fn_args(it.params, it.is_variadic)
|
fargs, fargtypes := g.fn_args(it.params, it.is_variadic)
|
||||||
arg_str := g.out.after(arg_start_pos)
|
arg_str := g.out.after(arg_start_pos)
|
||||||
if it.no_body ||
|
if it.no_body ||
|
||||||
((g.pref.use_cache && g.pref.build_mode != .build_module) && it.is_builtin) || skip {
|
((g.pref.use_cache && g.pref.build_mode != .build_module) && it.is_builtin) || skip
|
||||||
|
{
|
||||||
// Just a function header. Builtin function bodies are defined in builtin.o
|
// Just a function header. Builtin function bodies are defined in builtin.o
|
||||||
g.definitions.writeln(');') // // NO BODY')
|
g.definitions.writeln(');') // // NO BODY')
|
||||||
g.writeln(');')
|
g.writeln(');')
|
||||||
|
@ -297,7 +298,8 @@ fn (mut g Gen) call_expr(node ast.CallExpr) {
|
||||||
}
|
}
|
||||||
if node.is_method && !node.is_field {
|
if node.is_method && !node.is_field {
|
||||||
if node.name == 'writeln' && g.pref.experimental && node.args.len > 0 && node.args[0].expr is
|
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' {
|
ast.StringInterLiteral && g.table.get_type_symbol(node.receiver_type).name == 'strings.Builder'
|
||||||
|
{
|
||||||
g.string_inter_literal_sb_optimized(node)
|
g.string_inter_literal_sb_optimized(node)
|
||||||
} else {
|
} else {
|
||||||
g.method_call(node)
|
g.method_call(node)
|
||||||
|
@ -408,7 +410,8 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
|
||||||
}
|
}
|
||||||
// TODO performance, detect `array` method differently
|
// TODO performance, detect `array` method differently
|
||||||
if left_sym.kind == .array && node.name in
|
if left_sym.kind == .array && node.name in
|
||||||
['repeat', 'sort_with_compare', 'free', 'push_many', 'trim', 'first', 'last', 'pop', 'clone', 'reverse', 'slice'] {
|
['repeat', 'sort_with_compare', 'free', 'push_many', 'trim', 'first', 'last', 'pop', 'clone', 'reverse', 'slice']
|
||||||
|
{
|
||||||
// && rec_sym.name == 'array' {
|
// && rec_sym.name == 'array' {
|
||||||
// && rec_sym.name == 'array' && receiver_name.starts_with('array') {
|
// && rec_sym.name == 'array' && receiver_name.starts_with('array') {
|
||||||
// `array_byte_clone` => `array_clone`
|
// `array_byte_clone` => `array_clone`
|
||||||
|
@ -469,7 +472,8 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
|
||||||
g.write('&')
|
g.write('&')
|
||||||
}
|
}
|
||||||
} else if !node.receiver_type.is_ptr() && node.left_type.is_ptr() && node.name != 'str' &&
|
} else if !node.receiver_type.is_ptr() && node.left_type.is_ptr() && node.name != 'str' &&
|
||||||
node.from_embed_type == 0 {
|
node.from_embed_type == 0
|
||||||
|
{
|
||||||
g.write('/*rec*/*')
|
g.write('/*rec*/*')
|
||||||
}
|
}
|
||||||
if g.is_autofree && node.free_receiver && !g.inside_lambda && !g.is_builtin_mod {
|
if g.is_autofree && node.free_receiver && !g.inside_lambda && !g.is_builtin_mod {
|
||||||
|
|
|
@ -341,7 +341,8 @@ fn (mut g Gen) gen_expr_to_string(expr ast.Expr, etype table.Type) {
|
||||||
g.write('")')
|
g.write('")')
|
||||||
}
|
}
|
||||||
} else if sym_has_str_method || sym.kind in
|
} else if sym_has_str_method || sym.kind in
|
||||||
[.array, .array_fixed, .map, .struct_, .multi_return, .sum_type, .interface_] {
|
[.array, .array_fixed, .map, .struct_, .multi_return, .sum_type, .interface_]
|
||||||
|
{
|
||||||
is_ptr := typ.is_ptr()
|
is_ptr := typ.is_ptr()
|
||||||
str_fn_name := g.gen_str_for_type(typ)
|
str_fn_name := g.gen_str_for_type(typ)
|
||||||
if is_ptr {
|
if is_ptr {
|
||||||
|
|
|
@ -278,7 +278,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] &&
|
if p.tok.kind in [.plus, .minus, .mul, .div, .mod, .gt, .lt, .eq, .ne, .le, .ge] &&
|
||||||
p.peek_tok.kind == .lpar {
|
p.peek_tok.kind == .lpar
|
||||||
|
{
|
||||||
name = p.tok.kind.str() // op_to_fn_name()
|
name = p.tok.kind.str() // op_to_fn_name()
|
||||||
if rec_type == table.void_type {
|
if rec_type == table.void_type {
|
||||||
p.error_with_pos('cannot use operator overloading with normal functions',
|
p.error_with_pos('cannot use operator overloading with normal functions',
|
||||||
|
@ -318,7 +319,8 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
|
||||||
// Return type
|
// Return type
|
||||||
mut return_type := table.void_type
|
mut return_type := table.void_type
|
||||||
if p.tok.kind.is_start_of_type() ||
|
if p.tok.kind.is_start_of_type() ||
|
||||||
(p.tok.kind == .key_fn && p.tok.line_nr == p.prev_tok.line_nr) {
|
(p.tok.kind == .key_fn && p.tok.line_nr == p.prev_tok.line_nr)
|
||||||
|
{
|
||||||
return_type = p.parse_type()
|
return_type = p.parse_type()
|
||||||
}
|
}
|
||||||
mut type_sym_method_idx := 0
|
mut type_sym_method_idx := 0
|
||||||
|
@ -687,7 +689,8 @@ fn (mut p Parser) fn_args() ([]table.Param, bool, bool) {
|
||||||
fn (mut p Parser) check_fn_mutable_arguments(typ table.Type, pos token.Position) {
|
fn (mut p Parser) check_fn_mutable_arguments(typ table.Type, pos token.Position) {
|
||||||
sym := p.table.get_type_symbol(typ)
|
sym := p.table.get_type_symbol(typ)
|
||||||
if sym.kind !in [.array, .array_fixed, .struct_, .map, .placeholder, .sum_type] &&
|
if sym.kind !in [.array, .array_fixed, .struct_, .map, .placeholder, .sum_type] &&
|
||||||
!typ.is_ptr() && !typ.is_pointer() {
|
!typ.is_ptr() && !typ.is_pointer()
|
||||||
|
{
|
||||||
p.error_with_pos('mutable arguments are only allowed for arrays, maps, structs and pointers\n' +
|
p.error_with_pos('mutable arguments are only allowed for arrays, maps, structs and pointers\n' +
|
||||||
'return values instead: `fn foo(mut n $sym.name) {` => `fn foo(n $sym.name) $sym.name {`',
|
'return values instead: `fn foo(mut n $sym.name) {` => `fn foo(n $sym.name) $sym.name {`',
|
||||||
pos)
|
pos)
|
||||||
|
|
|
@ -79,7 +79,8 @@ fn (mut p Parser) for_stmt() ast.Stmt {
|
||||||
p.close_scope()
|
p.close_scope()
|
||||||
return for_c_stmt
|
return for_c_stmt
|
||||||
} else if p.peek_tok.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]) {
|
(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`
|
// `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 val_is_mut := p.tok.kind == .key_mut
|
||||||
if val_is_mut {
|
if val_is_mut {
|
||||||
|
|
|
@ -178,7 +178,8 @@ fn (mut p Parser) match_expr() ast.MatchExpr {
|
||||||
} else if (p.tok.kind == .name && !(p.tok.lit == 'C' &&
|
} 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.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.peek_tok.kind == .dot && p.peek_tok2.lit.len > 0 && p.peek_tok2.lit[0].is_capital()))) ||
|
||||||
p.tok.kind == .lsbr {
|
p.tok.kind == .lsbr
|
||||||
|
{
|
||||||
mut types := []table.Type{}
|
mut types := []table.Type{}
|
||||||
for {
|
for {
|
||||||
// Sum type match
|
// Sum type match
|
||||||
|
|
|
@ -53,7 +53,8 @@ pub fn (mut p Parser) parse_map_type() table.Type {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
if !(key_type in [table.string_type_idx, table.voidptr_type_idx] ||
|
if !(key_type in [table.string_type_idx, table.voidptr_type_idx] ||
|
||||||
(key_type.is_int() && !key_type.is_ptr())) {
|
(key_type.is_int() && !key_type.is_ptr()))
|
||||||
|
{
|
||||||
s := p.table.type_to_str(key_type)
|
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.error_with_pos('maps only support string, integer, rune or voidptr keys for now (not `$s`)',
|
||||||
p.tok.position())
|
p.tok.position())
|
||||||
|
|
|
@ -128,7 +128,8 @@ pub fn (mut p Parser) set_path(path string) {
|
||||||
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
|
p.file_backend_mode = .c
|
||||||
} else if path.ends_with('_js.v') || path.ends_with('.js.v') || path.ends_with('.js.vv') ||
|
} else if path.ends_with('_js.v') || path.ends_with('.js.v') || path.ends_with('.js.vv') ||
|
||||||
path.ends_with('.js.vsh') {
|
path.ends_with('.js.vsh')
|
||||||
|
{
|
||||||
p.file_backend_mode = .js
|
p.file_backend_mode = .js
|
||||||
} else {
|
} else {
|
||||||
p.file_backend_mode = .v
|
p.file_backend_mode = .v
|
||||||
|
@ -673,7 +674,8 @@ pub fn (mut p Parser) stmt(is_top_level bool) ast.Stmt {
|
||||||
p.error_with_pos('unexpected name `$p.peek_tok.lit`', p.peek_tok.position())
|
p.error_with_pos('unexpected name `$p.peek_tok.lit`', p.peek_tok.position())
|
||||||
return ast.Stmt{}
|
return ast.Stmt{}
|
||||||
} else if !p.inside_if_expr && !p.inside_match_body && !p.inside_or_expr &&
|
} 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.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())
|
p.error_with_pos('`$p.tok.lit` evaluated but not used', p.tok.position())
|
||||||
return ast.Stmt{}
|
return ast.Stmt{}
|
||||||
}
|
}
|
||||||
|
@ -992,7 +994,8 @@ fn (mut p Parser) parse_multi_expr(is_top_level bool) ast.Stmt {
|
||||||
} else if tok.kind !in [.key_if, .key_match, .key_lock, .key_rlock, .key_select] &&
|
} 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.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
|
!(left0 is ast.InfixExpr && (left0 as ast.InfixExpr).op in [.left_shift, .arrow]) && left0 !is
|
||||||
ast.ComptimeCall && left0 !is ast.SelectorExpr {
|
ast.ComptimeCall && left0 !is ast.SelectorExpr
|
||||||
|
{
|
||||||
p.error_with_pos('expression evaluated but not used', left0.position())
|
p.error_with_pos('expression evaluated but not used', left0.position())
|
||||||
return ast.Stmt{}
|
return ast.Stmt{}
|
||||||
}
|
}
|
||||||
|
@ -1189,7 +1192,8 @@ pub fn (mut p Parser) name_expr() ast.Expr {
|
||||||
known_var := p.mark_var_as_used(p.tok.lit)
|
known_var := p.mark_var_as_used(p.tok.lit)
|
||||||
mut is_mod_cast := false
|
mut is_mod_cast := false
|
||||||
if p.peek_tok.kind == .dot && !known_var &&
|
if p.peek_tok.kind == .dot && !known_var &&
|
||||||
(language != .v || p.known_import(p.tok.lit) || p.mod.all_after_last('.') == p.tok.lit) {
|
(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
|
// p.tok.lit has been recognized as a module
|
||||||
if language == .c {
|
if language == .c {
|
||||||
mod = 'C'
|
mod = 'C'
|
||||||
|
@ -1200,10 +1204,12 @@ pub fn (mut p Parser) name_expr() ast.Expr {
|
||||||
// mark the imported module as used
|
// mark the imported module as used
|
||||||
p.register_used_import(p.tok.lit)
|
p.register_used_import(p.tok.lit)
|
||||||
if p.peek_tok.kind == .dot &&
|
if p.peek_tok.kind == .dot &&
|
||||||
p.peek_tok2.kind != .eof && p.peek_tok2.lit.len > 0 && p.peek_tok2.lit[0].is_capital() {
|
p.peek_tok2.kind != .eof && p.peek_tok2.lit.len > 0 && p.peek_tok2.lit[0].is_capital()
|
||||||
|
{
|
||||||
is_mod_cast = true
|
is_mod_cast = true
|
||||||
} else if p.peek_tok.kind == .dot &&
|
} else if p.peek_tok.kind == .dot &&
|
||||||
p.peek_tok2.kind != .eof && p.peek_tok2.lit.len == 0 {
|
p.peek_tok2.kind != .eof && p.peek_tok2.lit.len == 0
|
||||||
|
{
|
||||||
// incomplete module selector must be handled by dot_expr instead
|
// incomplete module selector must be handled by dot_expr instead
|
||||||
node = p.parse_ident(language)
|
node = p.parse_ident(language)
|
||||||
return node
|
return node
|
||||||
|
@ -1237,7 +1243,8 @@ pub fn (mut p Parser) name_expr() ast.Expr {
|
||||||
// if name in table.builtin_type_names {
|
// if name in table.builtin_type_names {
|
||||||
if (!known_var && (name in p.table.type_idxs ||
|
if (!known_var && (name in p.table.type_idxs ||
|
||||||
name_w_mod in p.table.type_idxs) && name !in ['C.stat', 'C.sigaction']) ||
|
name_w_mod in p.table.type_idxs) && name !in ['C.stat', 'C.sigaction']) ||
|
||||||
is_mod_cast || (language == .v && name[0].is_capital()) {
|
is_mod_cast || (language == .v && name[0].is_capital())
|
||||||
|
{
|
||||||
// MainLetter(x) is *always* a cast, as long as it is not `C.`
|
// MainLetter(x) is *always* a cast, as long as it is not `C.`
|
||||||
// TODO handle C.stat()
|
// TODO handle C.stat()
|
||||||
start_pos := p.tok.position()
|
start_pos := p.tok.position()
|
||||||
|
@ -1281,7 +1288,8 @@ pub fn (mut p Parser) name_expr() ast.Expr {
|
||||||
(p.peek_tok.kind == .lt && lit0_is_capital)) &&
|
(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_match || (p.inside_select && prev_tok_kind == .arrow && lit0_is_capital)) && !p.inside_match_case &&
|
||||||
(!p.inside_if || p.inside_select) &&
|
(!p.inside_if || p.inside_select) &&
|
||||||
(!p.inside_for || p.inside_select) { // && (p.tok.lit[0].is_capital() || p.builtin_mod) {
|
(!p.inside_for || p.inside_select)
|
||||||
|
{ // && (p.tok.lit[0].is_capital() || p.builtin_mod) {
|
||||||
return p.struct_init(false) // short_syntax: false
|
return p.struct_init(false) // short_syntax: false
|
||||||
} else if p.peek_tok.kind == .dot && (lit0_is_capital && !known_var && language == .v) {
|
} else if p.peek_tok.kind == .dot && (lit0_is_capital && !known_var && language == .v) {
|
||||||
// T.name
|
// T.name
|
||||||
|
@ -2004,7 +2012,8 @@ const (
|
||||||
fn (mut p Parser) global_decl() ast.GlobalDecl {
|
fn (mut p Parser) global_decl() ast.GlobalDecl {
|
||||||
if !p.pref.translated && !p.pref.is_livemain && !p.builtin_mod && !p.pref.building_v &&
|
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 != 'ui' && p.mod != 'gg2' && p.mod != 'uiold' && !p.pref.enable_globals && !p.pref.is_fmt &&
|
||||||
p.mod !in global_enabled_mods {
|
p.mod !in global_enabled_mods
|
||||||
|
{
|
||||||
p.error('use `v --enable-globals ...` to enable globals')
|
p.error('use `v --enable-globals ...` to enable globals')
|
||||||
return ast.GlobalDecl{}
|
return ast.GlobalDecl{}
|
||||||
}
|
}
|
||||||
|
|
|
@ -380,7 +380,8 @@ fn (mut p Parser) infix_expr(left ast.Expr) ast.Expr {
|
||||||
right = p.expr(precedence)
|
right = p.expr(precedence)
|
||||||
p.expecting_type = prev_expecting_type
|
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 ==
|
if p.pref.is_vet && op in [.key_in, .not_in] && right is ast.ArrayInit && (right as ast.ArrayInit).exprs.len ==
|
||||||
1 {
|
1
|
||||||
|
{
|
||||||
p.vet_error('Use `var == value` instead of `var in [value]`', pos.line_nr, vet.FixKind.vfmt)
|
p.vet_error('Use `var == value` instead of `var in [value]`', pos.line_nr, vet.FixKind.vfmt)
|
||||||
}
|
}
|
||||||
mut or_stmts := []ast.Stmt{}
|
mut or_stmts := []ast.Stmt{}
|
||||||
|
|
|
@ -66,7 +66,8 @@ fn (mut p Parser) struct_decl() ast.StructDecl {
|
||||||
return ast.StructDecl{}
|
return ast.StructDecl{}
|
||||||
}
|
}
|
||||||
if language == .v &&
|
if language == .v &&
|
||||||
p.mod != 'builtin' && name.len > 0 && !name[0].is_capital() && !p.pref.translated {
|
p.mod != 'builtin' && name.len > 0 && !name[0].is_capital() && !p.pref.translated
|
||||||
|
{
|
||||||
p.error_with_pos('struct name `$name` must begin with capital letter', name_pos)
|
p.error_with_pos('struct name `$name` must begin with capital letter', name_pos)
|
||||||
return ast.StructDecl{}
|
return ast.StructDecl{}
|
||||||
}
|
}
|
||||||
|
|
|
@ -482,7 +482,8 @@ pub fn parse_args(args []string) (&Preferences, string) {
|
||||||
}
|
}
|
||||||
must_exist(res.path)
|
must_exist(res.path)
|
||||||
if !res.path.ends_with('.v') && os.is_executable(res.path) && os.is_file(res.path) &&
|
if !res.path.ends_with('.v') && os.is_executable(res.path) && os.is_file(res.path) &&
|
||||||
os.is_file(res.path + '.v') {
|
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.')
|
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'
|
res.path += '.v'
|
||||||
}
|
}
|
||||||
|
|
|
@ -884,11 +884,13 @@ fn (mut s Scanner) text_scan() token.Token {
|
||||||
s.pos++
|
s.pos++
|
||||||
return s.new_token(.ne, '', 2)
|
return s.new_token(.ne, '', 2)
|
||||||
} else if s.text.len > s.pos + 3 &&
|
} else if s.text.len > s.pos + 3 &&
|
||||||
nextc == `i` && s.text[s.pos + 2] == `n` && s.text[s.pos + 3].is_space() {
|
nextc == `i` && s.text[s.pos + 2] == `n` && s.text[s.pos + 3].is_space()
|
||||||
|
{
|
||||||
s.pos += 2
|
s.pos += 2
|
||||||
return s.new_token(.not_in, '', 3)
|
return s.new_token(.not_in, '', 3)
|
||||||
} else if s.text.len > s.pos + 3 &&
|
} else if s.text.len > s.pos + 3 &&
|
||||||
nextc == `i` && s.text[s.pos + 2] == `s` && s.text[s.pos + 3].is_space() {
|
nextc == `i` && s.text[s.pos + 2] == `s` && s.text[s.pos + 3].is_space()
|
||||||
|
{
|
||||||
s.pos += 2
|
s.pos += 2
|
||||||
return s.new_token(.not_is, '', 3)
|
return s.new_token(.not_is, '', 3)
|
||||||
} else {
|
} else {
|
||||||
|
@ -1016,7 +1018,8 @@ fn (mut s Scanner) ident_string() string {
|
||||||
mut n_cr_chars := 0
|
mut n_cr_chars := 0
|
||||||
mut start := s.pos
|
mut start := s.pos
|
||||||
if s.text[start] == s.quote ||
|
if s.text[start] == s.quote ||
|
||||||
(s.text[start] == s.inter_quote && (s.is_inter_start || s.is_enclosed_inter)) {
|
(s.text[start] == s.inter_quote && (s.is_inter_start || s.is_enclosed_inter))
|
||||||
|
{
|
||||||
start++
|
start++
|
||||||
}
|
}
|
||||||
s.is_inside_string = false
|
s.is_inside_string = false
|
||||||
|
@ -1046,7 +1049,8 @@ fn (mut s Scanner) ident_string() string {
|
||||||
// Don't allow \0
|
// Don't allow \0
|
||||||
if c == `0` && s.pos > 2 && prevc == slash {
|
if c == `0` && s.pos > 2 && prevc == slash {
|
||||||
if (s.pos < s.text.len - 1 && s.text[s.pos + 1].is_digit()) ||
|
if (s.pos < s.text.len - 1 && s.text[s.pos + 1].is_digit()) ||
|
||||||
s.count_symbol_before(s.pos - 1, slash) % 2 == 0 {
|
s.count_symbol_before(s.pos - 1, slash) % 2 == 0
|
||||||
|
{
|
||||||
} else if !is_cstr && !is_raw {
|
} else if !is_cstr && !is_raw {
|
||||||
s.error(r'cannot use `\0` (NULL character) in the string literal')
|
s.error(r'cannot use `\0` (NULL character) in the string literal')
|
||||||
}
|
}
|
||||||
|
@ -1068,7 +1072,8 @@ fn (mut s Scanner) ident_string() string {
|
||||||
if c == `u` && (s.text[s.pos + 1] == s.quote ||
|
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 + 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 + 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.text[s.pos + 4].is_hex_digit())
|
||||||
|
{
|
||||||
s.error(r'`\u` incomplete unicode character value')
|
s.error(r'`\u` incomplete unicode character value')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1082,7 +1087,8 @@ fn (mut s Scanner) ident_string() string {
|
||||||
}
|
}
|
||||||
// $var
|
// $var
|
||||||
if prevc == `$` && util.is_name_char(c) && !is_raw && s.count_symbol_before(s.pos - 2, slash) %
|
if prevc == `$` && util.is_name_char(c) && !is_raw && s.count_symbol_before(s.pos - 2, slash) %
|
||||||
2 == 0 {
|
2 == 0
|
||||||
|
{
|
||||||
s.is_inside_string = true
|
s.is_inside_string = true
|
||||||
s.is_inter_start = true
|
s.is_inter_start = true
|
||||||
s.pos -= 2
|
s.pos -= 2
|
||||||
|
|
|
@ -424,7 +424,8 @@ fn handle_conn<T>(mut conn net.TcpConn, mut app T) {
|
||||||
// should be called first.
|
// should be called first.
|
||||||
if (req_method_str == '' &&
|
if (req_method_str == '' &&
|
||||||
url_words[0] == method.name && url_words.len == 1) ||
|
url_words[0] == method.name && url_words.len == 1) ||
|
||||||
(req_method_str == 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 {
|
$if debug {
|
||||||
println('easy match method=$method.name')
|
println('easy match method=$method.name')
|
||||||
}
|
}
|
||||||
|
@ -449,7 +450,8 @@ fn handle_conn<T>(mut conn net.TcpConn, mut app T) {
|
||||||
req_method << route_words[0]
|
req_method << route_words[0]
|
||||||
}
|
}
|
||||||
if url_words.len == route_words.len ||
|
if url_words.len == route_words.len ||
|
||||||
(url_words.len >= route_words.len - 1 && route_words.len > 0 && route_words.last().ends_with('...')) {
|
(url_words.len >= route_words.len - 1 && route_words.len > 0 && route_words.last().ends_with('...'))
|
||||||
|
{
|
||||||
if req_method.len > 0 {
|
if req_method.len > 0 {
|
||||||
if req_method_str.to_lower()[1..] !in req_method {
|
if req_method_str.to_lower()[1..] !in req_method {
|
||||||
continue
|
continue
|
||||||
|
|
|
@ -119,7 +119,8 @@ fn (mut ws Client) read_handshake_str() ?string {
|
||||||
msg[total_bytes_read] = buffer[0]
|
msg[total_bytes_read] = buffer[0]
|
||||||
total_bytes_read++
|
total_bytes_read++
|
||||||
if total_bytes_read > 5 && msg[total_bytes_read - 1] == `\n` && msg[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` {
|
2] == `\r` && msg[total_bytes_read - 3] == `\n` && msg[total_bytes_read - 4] == `\r`
|
||||||
|
{
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,7 +43,8 @@ pub fn (mut ws Client) validate_frame(frame &Frame) ? {
|
||||||
return error('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) ||
|
if (int(frame.opcode) >= 3 && int(frame.opcode) <= 7) ||
|
||||||
(int(frame.opcode) >= 11 && int(frame.opcode) <= 15) {
|
(int(frame.opcode) >= 11 && int(frame.opcode) <= 15)
|
||||||
|
{
|
||||||
ws.close(1002, 'use of reserved opcode') ?
|
ws.close(1002, 'use of reserved opcode') ?
|
||||||
return error('use of reserved opcode')
|
return error('use of reserved opcode')
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue