diff --git a/vlib/builtin/string_interpolation.v b/vlib/builtin/string_interpolation.v index c6176eec2d..2331956e6d 100644 --- a/vlib/builtin/string_interpolation.v +++ b/vlib/builtin/string_interpolation.v @@ -212,38 +212,45 @@ fn (data &StrIntpData) process_str_intp_data(mut sb strings.Builder) { unsafe { // strings if typ == .si_s { - mut s := '' if upper_case { - s = data.d.d_s.to_upper() + s := data.d.d_s.to_upper() + if width == 0 { + sb.write_string(s) + } else { + strconv.format_str_sb(s, bf, mut sb) + } + s.free() } else { - s = data.d.d_s.clone() + if width == 0 { + sb.write_string(data.d.d_s) + } else { + strconv.format_str_sb(data.d.d_s, bf, mut sb) + } } - if width == 0 { - sb.write_string(s) - } else { - strconv.format_str_sb(s, bf, mut sb) - } - s.free() return } if typ == .si_r { if width > 0 { - mut s := '' if upper_case { - s = data.d.d_s.to_upper() + s := data.d.d_s.to_upper() + for _ in 1 .. (1 + (if width > 0 { + width + } else { + 0 + })) { + sb.write_string(s) + } + s.free() } else { - s = data.d.d_s.clone() + for _ in 1 .. (1 + (if width > 0 { + width + } else { + 0 + })) { + sb.write_string(data.d.d_s) + } } - - for _ in 1 .. (1 + (if width > 0 { - width - } else { - 0 - })) { - sb.write_string(s) - } - s.free() } return } diff --git a/vlib/strings/builder.c.v b/vlib/strings/builder.c.v index 93cbba8261..84f1af1f56 100644 --- a/vlib/strings/builder.c.v +++ b/vlib/strings/builder.c.v @@ -65,11 +65,13 @@ pub fn (mut b Builder) clear() { } // write_u8 appends a single `data` byte to the accumulated buffer +@[inline] pub fn (mut b Builder) write_u8(data u8) { b << data } // write_byte appends a single `data` byte to the accumulated buffer +@[inline] pub fn (mut b Builder) write_byte(data u8) { b << data } diff --git a/vlib/v/ast/table.v b/vlib/v/ast/table.v index 60c6691aef..5cb41fef2f 100644 --- a/vlib/v/ast/table.v +++ b/vlib/v/ast/table.v @@ -676,9 +676,10 @@ pub fn (t &Table) sym_by_idx(idx int) &TypeSymbol { return t.type_symbols[idx] } +@[direct_array_access] pub fn (t &Table) sym(typ Type) &TypeSymbol { idx := typ.idx() - if idx > 0 { + if idx > 0 && idx < t.type_symbols.len { return t.type_symbols[idx] } // this should never happen @@ -688,10 +689,10 @@ pub fn (t &Table) sym(typ Type) &TypeSymbol { } // final_sym follows aliases until it gets to a "real" Type -@[inline] +@[direct_array_access] pub fn (t &Table) final_sym(typ Type) &TypeSymbol { mut idx := typ.idx() - if idx > 0 { + if idx > 0 && idx < t.type_symbols.len { cur_sym := t.type_symbols[idx] if cur_sym.info is Alias { idx = cur_sym.info.parent_type.idx() diff --git a/vlib/v/ast/types.v b/vlib/v/ast/types.v index 79e2d6db06..9130e9995f 100644 --- a/vlib/v/ast/types.v +++ b/vlib/v/ast/types.v @@ -312,7 +312,7 @@ pub fn (t Type) nr_muls() int { pub fn (t Type) is_ptr() bool { // any normal pointer, i.e. &Type, &&Type etc; // Note: voidptr, charptr and byteptr are NOT included! - return (int(t) >> 16) & 0xff > 0 + return (int(t) >> 16) & 0xff != 0 } // is_pointer returns true if `typ` is any of the builtin pointer types (voidptr, byteptr, charptr) @@ -331,7 +331,7 @@ pub fn (typ Type) is_voidptr() bool { // is_any_kind_of_pointer returns true if t is any type of pointer @[inline] pub fn (t Type) is_any_kind_of_pointer() bool { - return (int(t) >> 16) & 0xff > 0 || (u16(t) & 0xffff) in ast.pointer_type_idxs + return (int(t) >> 16) & 0xff != 0 || (u16(t) & 0xffff) in ast.pointer_type_idxs } // set nr_muls on `t` and return it @@ -398,7 +398,7 @@ pub fn (t Type) clear_option_and_result() Type { // return true if `flag` is set on `t` @[inline] pub fn (t Type) has_flag(flag TypeFlag) bool { - return int(t) & (1 << (int(flag) + 24)) > 0 + return int(t) & (1 << (int(flag) + 24)) != 0 } @[inline] diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index bd02219e37..4d4f305a71 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -1437,8 +1437,10 @@ fn (mut c Checker) selector_expr(mut node ast.SelectorExpr) ast.Type { using_new_err_struct_save := c.using_new_err_struct // TODO: remove; this avoids a breaking change in syntax - if '${node.expr}' == 'err' { - c.using_new_err_struct = true + if node.expr is ast.Ident { + if node.expr.str() == 'err' { + c.using_new_err_struct = true + } } // T.name, typeof(expr).name @@ -1545,7 +1547,7 @@ fn (mut c Checker) selector_expr(mut node ast.SelectorExpr) ast.Type { return ast.u32_type } } - mut unknown_field_msg := 'type `${sym.name}` has no field named `${field_name}`' + mut unknown_field_msg := '' mut has_field := false mut field := ast.StructField{} if field_name.len > 0 && field_name[0].is_capital() && sym.info is ast.Struct @@ -1698,6 +1700,9 @@ fn (mut c Checker) selector_expr(mut node ast.SelectorExpr) ast.Type { c.error('`${unwrapped_sym.name}` has no property `${node.field_name}`', node.pos) } } else { + if unknown_field_msg == '' { + unknown_field_msg = 'type `${sym.name}` has no field named `${field_name}`' + } if sym.info is ast.Struct { if c.smartcast_mut_pos != token.Pos{} { c.note('smartcasting requires either an immutable value, or an explicit mut keyword before the value', diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index f4d3083e55..69a2081d49 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -2650,7 +2650,7 @@ fn cescape_nonascii(original string) string { write_octal_escape(mut b, c) continue } - b.write_u8(c) + b << c } res := b.str() return res diff --git a/vlib/v/gen/c/fn.v b/vlib/v/gen/c/fn.v index c8a6acb5af..c437bc54a9 100644 --- a/vlib/v/gen/c/fn.v +++ b/vlib/v/gen/c/fn.v @@ -890,7 +890,7 @@ fn (mut g Gen) call_expr(node ast.CallExpr) { } } if node.is_method && !node.is_field { - if node.name == 'writeln' && g.pref.experimental && node.args.len > 0 + if g.pref.experimental && node.args.len > 0 && node.name == 'writeln' && node.args[0].expr is ast.StringInterLiteral && g.table.sym(node.receiver_type).name == 'strings.Builder' { g.string_inter_literal_sb_optimized(node) diff --git a/vlib/v/gen/c/str.v b/vlib/v/gen/c/str.v index 803ee873b9..4483b12e92 100644 --- a/vlib/v/gen/c/str.v +++ b/vlib/v/gen/c/str.v @@ -8,9 +8,13 @@ import v.util fn (mut g Gen) string_literal(node ast.StringLiteral) { escaped_val := cescape_nonascii(util.smart_quote(node.val, node.is_raw)) if node.language == .c { - g.write('"${escaped_val}"') + g.write('"') + g.write(escaped_val) + g.write('"') } else { - g.write('_SLIT("${escaped_val}")') + g.write('_SLIT("') + g.write(escaped_val) + g.write('")') } } @@ -149,7 +153,8 @@ fn (mut g Gen) gen_expr_to_string(expr ast.Expr, etype ast.Type) { g.write(') ? _SLIT("nil") : ') } } - g.write('${str_fn_name}(') + g.write(str_fn_name) + g.write('(') if str_method_expects_ptr && !is_ptr { if is_dump_expr || (g.pref.ccompiler_type != .tinyc && expr is ast.CallExpr) { g.write('ADDR(${g.typ(typ)}, ') diff --git a/vlib/v/gen/c/str_intp.v b/vlib/v/gen/c/str_intp.v index fb2323515a..bf74ef2be6 100644 --- a/vlib/v/gen/c/str_intp.v +++ b/vlib/v/gen/c/str_intp.v @@ -261,14 +261,18 @@ fn (mut g Gen) string_inter_literal(node ast.StringInterLiteral) { } } } - g.write(' str_intp(${node.vals.len}, ') + g.write(' str_intp(') + g.write(node.vals.len.str()) + g.write(', ') g.write('_MOV((StrIntpData[]){') for i, val in node.vals { mut escaped_val := cescape_nonascii(util.smart_quote(val, false)) escaped_val = escaped_val.replace('\0', '\\0') if escaped_val.len > 0 { - g.write('{_SLIT("${escaped_val}"), ') + g.write('{_SLIT("') + g.write(escaped_val) + g.write('"), ') } else { g.write('{_SLIT0, ') } @@ -280,7 +284,11 @@ fn (mut g Gen) string_inter_literal(node ast.StringInterLiteral) { } ft_u64, ft_str := g.str_format(node, i, fmts) - g.write('0x${ft_u64.hex()}, {.d_${ft_str} = ') + g.write('0x') + g.write(ft_u64.hex()) + g.write(', {.d_') + g.write(ft_str) + g.write(' = ') // for pointers we need a void* cast if unsafe { ft_str.str[0] } == `p` { diff --git a/vlib/v/util/util.v b/vlib/v/util/util.v index 8a16d11692..eb7f4be57b 100644 --- a/vlib/v/util/util.v +++ b/vlib/v/util/util.v @@ -16,7 +16,7 @@ import runtime // math.bits is needed by strconv.ftoa pub const builtin_module_parts = ['math.bits', 'strconv', 'dlmalloc', 'strconv.ftoa', 'strings', 'builtin'] -pub const bundle_modules = ['clipboard', 'fontstash', 'gg', 'gx', 'sokol', 'szip', 'ui'] +pub const bundle_modules = ['clipboard', 'fontstash', 'gg', 'gx', 'sokol', 'szip', 'ui']! pub const external_module_dependencies_for_tool = { 'vdoc': ['markdown'] @@ -34,7 +34,7 @@ const const_tabs = [ '\t\t\t\t\t\t\t\t', '\t\t\t\t\t\t\t\t\t', '\t\t\t\t\t\t\t\t\t\t', -] +]! pub const nr_jobs = runtime.nr_jobs() @@ -42,8 +42,9 @@ pub fn module_is_builtin(mod string) bool { return mod in util.builtin_module_parts } +@[direct_array_access] pub fn tabs(n int) string { - return if n < util.const_tabs.len { util.const_tabs[n] } else { '\t'.repeat(n) } + return if n >= 0 && n < util.const_tabs.len { util.const_tabs[n] } else { '\t'.repeat(n) } } //