From e8f0deafe1cfb4b10c99121b972d3a8cae45173d Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Thu, 2 Jan 2025 09:27:14 -0300 Subject: [PATCH 01/17] fix --- vlib/v/checker/assign.v | 2 +- .../comptime/comptime_infix_assign_test.v | 62 +++++++++++++++++++ 2 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 vlib/v/tests/comptime/comptime_infix_assign_test.v diff --git a/vlib/v/checker/assign.v b/vlib/v/checker/assign.v index 2f897013ab8030..3b7fbafe2261af 100644 --- a/vlib/v/checker/assign.v +++ b/vlib/v/checker/assign.v @@ -25,7 +25,7 @@ fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) { mut right_first_type := ast.void_type for i, mut right in node.right { if right in [ast.CallExpr, ast.IfExpr, ast.LockExpr, ast.MatchExpr, ast.DumpExpr, - ast.SelectorExpr, ast.ParExpr, ast.ComptimeCall] { + ast.SelectorExpr, ast.ParExpr, ast.ComptimeCall, ast.InfixExpr] { if right in [ast.IfExpr, ast.MatchExpr] && node.left.len == node.right.len && !is_decl && node.left[i] in [ast.Ident, ast.SelectorExpr] && !node.left[i].is_blank_ident() { mut expr := node.left[i] diff --git a/vlib/v/tests/comptime/comptime_infix_assign_test.v b/vlib/v/tests/comptime/comptime_infix_assign_test.v new file mode 100644 index 00000000000000..eb8c08df435d96 --- /dev/null +++ b/vlib/v/tests/comptime/comptime_infix_assign_test.v @@ -0,0 +1,62 @@ +enum Flag { + usa_old_glory + all_other_bad_excuses_for_a_flag +} + +struct Test { + is_foo bool + name [5]u8 +} + +fn enc[T](item T) string { + $if T is $int { + len := match typeof(item).name { + 'i8', 'u8' { u8(2) } + 'i16', 'u16' { 4 } + 'int', 'u32', 'i32' { 8 } + 'i64', 'u64' { 16 } + else { return '' } + } + return u64_to_hex(item, len) + } $else $if T is $array { + mut hex := '' + for val in item { + hex += enc(val) + } + return hex + } $else $if T is $struct { + mut hex := '' + $for field in T.fields { + hex += enc(item.$(field.name)) + '_' + } + return hex + } $else { + if typeof(item).name == 'bool' { + return enc(int(item)) + } + $if debug { + println('cannot encode ${T}(s)') + } + return '' + } +} + +@[direct_array_access; inline] +fn u64_to_hex(nn u64, len u8) string { + mut n := nn + mut buf := [17]u8{} + buf[len] = 0 + mut i := 0 + for i = len - 1; i >= 0; i-- { + d := u8(n & 0xF) + buf[i] = if d < 10 { d + `0` } else { d + 87 } + n = n >> 4 + } + return unsafe { tos(memdup(&buf[0], len + 1), len) } +} + +fn test_main() { + assert enc(Test{}) == '00000000_0000000000_' + assert enc(Test{ is_foo: true }) == '00000001_0000000000_' + assert enc(Test{ name: [u8(1), 2, 3, 4, 5]! }) == '00000000_0102030405_' +} From 7d3abcd39052d1f4bab4b64550c0f3d31c279409 Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Thu, 2 Jan 2025 10:25:37 -0300 Subject: [PATCH 02/17] fix test --- vlib/math/stats/stats_test.v | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/vlib/math/stats/stats_test.v b/vlib/math/stats/stats_test.v index d77c773d0b106c..3f59d7fb55684d 100644 --- a/vlib/math/stats/stats_test.v +++ b/vlib/math/stats/stats_test.v @@ -428,13 +428,13 @@ fn test_covariance() { fn test_lag1_autocorrelation() { mut data := [10.0, 4.45, 5.9, 2.7] mut o := stats.lag1_autocorrelation(data) - assert math.alike(o, -0.554228566606572) + assert math.alike(o, -0.5542285495255542) data = [-3.0, 67.31, 4.4, 1.89] o = stats.lag1_autocorrelation(data) - assert math.alike(o, -0.5102510823460722) + assert math.alike(o, -0.5102510688760657) data = [12.0, 7.88, 76.122, 54.83] o = stats.lag1_autocorrelation(data) - assert math.alike(o, 0.10484451825170164) + assert math.alike(o, 0.10484451223403927) // test for int, i64, f32 array assert stats.lag1_autocorrelation[int]([1, 2, 3, 1]) == 0 From 9ccb6857f90470fa57d67cd4ca64f8033f127e46 Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Thu, 2 Jan 2025 11:02:52 -0300 Subject: [PATCH 03/17] fix recheck checking --- vlib/v/checker/assign.v | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/vlib/v/checker/assign.v b/vlib/v/checker/assign.v index 3b7fbafe2261af..52131f55491402 100644 --- a/vlib/v/checker/assign.v +++ b/vlib/v/checker/assign.v @@ -23,6 +23,12 @@ fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) { node.left_types = [] mut right_len := node.right.len mut right_first_type := ast.void_type + old_recheck := c.inside_recheck + // check if we are rechecking an already checked expression on generic rechecking + c.inside_recheck = old_recheck || node.right_types.len > 0 + defer { + c.inside_recheck = old_recheck + } for i, mut right in node.right { if right in [ast.CallExpr, ast.IfExpr, ast.LockExpr, ast.MatchExpr, ast.DumpExpr, ast.SelectorExpr, ast.ParExpr, ast.ComptimeCall, ast.InfixExpr] { @@ -182,16 +188,13 @@ fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) { node.right_types << c.check_expr_option_or_result_call(node.right[i], right_type) } - } else { + } else if c.inside_recheck { // on generic recheck phase it might be needed to resolve the rhs again if i < node.right.len && c.comptime.has_comptime_expr(node.right[i]) { mut expr := mut node.right[i] - old_inside_recheck := c.inside_recheck - c.inside_recheck = true right_type := c.expr(mut expr) node.right_types[i] = c.check_expr_option_or_result_call(node.right[i], right_type) - c.inside_recheck = old_inside_recheck } } mut right := if i < node.right.len { node.right[i] } else { node.right[0] } From 1ad5a070c4e998a3dd4aed00330169c9c0b052e0 Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Thu, 2 Jan 2025 11:56:53 -0300 Subject: [PATCH 04/17] Update assign.v --- vlib/v/checker/assign.v | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vlib/v/checker/assign.v b/vlib/v/checker/assign.v index 52131f55491402..07f664219646c5 100644 --- a/vlib/v/checker/assign.v +++ b/vlib/v/checker/assign.v @@ -58,7 +58,7 @@ fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) { node.right_types = right_type_sym.mr_info().types right_len = node.right_types.len } else if right_type == ast.void_type { - right_len = 0 + right_len = if c.inside_recheck { right_len } else { 0 } if mut right is ast.IfExpr { last_branch := right.branches.last() last_stmts := last_branch.stmts.filter(it is ast.ExprStmt) @@ -95,7 +95,7 @@ fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) { } } } - if node.left.len != right_len { + if !c.inside_recheck && node.left.len != right_len { if mut right_first is ast.CallExpr { if node.left_types.len > 0 && node.left_types[0] == ast.void_type { // If it's a void type, it's an unknown variable, already had an error earlier. From 04b5caa5b24af1aa1f28b28841080683837644aa Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Thu, 2 Jan 2025 13:05:53 -0300 Subject: [PATCH 05/17] fix --- vlib/v/checker/assign.v | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/vlib/v/checker/assign.v b/vlib/v/checker/assign.v index 07f664219646c5..c01c377be475b7 100644 --- a/vlib/v/checker/assign.v +++ b/vlib/v/checker/assign.v @@ -31,7 +31,7 @@ fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) { } for i, mut right in node.right { if right in [ast.CallExpr, ast.IfExpr, ast.LockExpr, ast.MatchExpr, ast.DumpExpr, - ast.SelectorExpr, ast.ParExpr, ast.ComptimeCall, ast.InfixExpr] { + ast.SelectorExpr, ast.ParExpr, ast.ComptimeCall] { if right in [ast.IfExpr, ast.MatchExpr] && node.left.len == node.right.len && !is_decl && node.left[i] in [ast.Ident, ast.SelectorExpr] && !node.left[i].is_blank_ident() { mut expr := node.left[i] @@ -58,7 +58,7 @@ fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) { node.right_types = right_type_sym.mr_info().types right_len = node.right_types.len } else if right_type == ast.void_type { - right_len = if c.inside_recheck { right_len } else { 0 } + right_len = 0 if mut right is ast.IfExpr { last_branch := right.branches.last() last_stmts := last_branch.stmts.filter(it is ast.ExprStmt) @@ -68,11 +68,12 @@ fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) { } } } - } - if mut right is ast.InfixExpr { + } else if mut right is ast.InfixExpr { if right.op == .arrow { c.error('cannot use `<-` on the right-hand side of an assignment, as it does not return any values', right.pos) + } else if c.inside_recheck { + c.expr(mut right) } } if mut right is ast.Ident { @@ -95,7 +96,7 @@ fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) { } } } - if !c.inside_recheck && node.left.len != right_len { + if node.left.len != right_len { if mut right_first is ast.CallExpr { if node.left_types.len > 0 && node.left_types[0] == ast.void_type { // If it's a void type, it's an unknown variable, already had an error earlier. From 32c3acbddf6168537f3e23a45f4c6aa5c8399481 Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Thu, 2 Jan 2025 13:18:46 -0300 Subject: [PATCH 06/17] fix --- vlib/v/checker/assign.v | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/vlib/v/checker/assign.v b/vlib/v/checker/assign.v index c01c377be475b7..aeee42b65c2463 100644 --- a/vlib/v/checker/assign.v +++ b/vlib/v/checker/assign.v @@ -43,7 +43,9 @@ fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) { } right_type_sym := c.table.sym(right_type) // fixed array returns an struct, but when assigning it must be the array type - right_type = c.cast_fixed_array_ret(right_type, right_type_sym) + if right_type_sym.info is ast.ArrayFixed { + right_type = c.cast_fixed_array_ret(right_type, right_type_sym) + } if i == 0 { right_first_type = right_type node.right_types = [ @@ -73,7 +75,18 @@ fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) { c.error('cannot use `<-` on the right-hand side of an assignment, as it does not return any values', right.pos) } else if c.inside_recheck { - c.expr(mut right) + mut right_type := c.expr(mut right) + right_type_sym := c.table.sym(right_type) + // fixed array returns an struct, but when assigning it must be the array type + if right_type_sym.info is ast.ArrayFixed { + right_type = c.cast_fixed_array_ret(right_type, right_type_sym) + } + if i == 0 { + right_first_type = right_type + node.right_types = [ + c.check_expr_option_or_result_call(right, right_first_type), + ] + } } } if mut right is ast.Ident { From 6dcfa64cb2dcf82e467be61a4cf3b20ab3296839 Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Thu, 2 Jan 2025 16:05:05 -0300 Subject: [PATCH 07/17] fix --- vlib/math/stats/stats_test.v | 30 ++++++++++++------------- vlib/v/checker/assign.v | 5 +++++ vlib/v/gen/c/assign.v | 8 +++++++ vlib/v/type_resolver/generic_resolver.v | 2 +- vlib/v/type_resolver/type_resolver.v | 19 ++++++++++++++++ 5 files changed, 48 insertions(+), 16 deletions(-) diff --git a/vlib/math/stats/stats_test.v b/vlib/math/stats/stats_test.v index 3f59d7fb55684d..4610baba66acec 100644 --- a/vlib/math/stats/stats_test.v +++ b/vlib/math/stats/stats_test.v @@ -400,15 +400,15 @@ fn test_covariance() { mut data0 := [10.0, 4.45, 5.9, 2.7] mut data1 := [5.0, 14.45, -15.9, 22.7] mut o := stats.covariance(data0, data1) - assert math.alike(o, -17.37078207731247) + assert math.alike(o, -17.37078125) data0 = [-3.0, 67.31, 4.4, 1.89] data1 = [5.0, 77.31, 44.4, 11.89] o = stats.covariance(data0, data1) - assert math.alike(o, 740.0695419311523) + assert math.alike(o, 740.06955) data0 = [12.0, 7.88, 76.122, 54.83] data1 = [2.0, 5.88, 7.122, 5.83] o = stats.covariance(data0, data1) - assert math.alike(o, 36.65028190612793) + assert math.alike(o, 36.650282000000004) // test for int, i64, f32 array data0_int := [1, 2, 3, 1] @@ -428,13 +428,13 @@ fn test_covariance() { fn test_lag1_autocorrelation() { mut data := [10.0, 4.45, 5.9, 2.7] mut o := stats.lag1_autocorrelation(data) - assert math.alike(o, -0.5542285495255542) + assert math.alike(o, -0.5542285481446095) data = [-3.0, 67.31, 4.4, 1.89] o = stats.lag1_autocorrelation(data) - assert math.alike(o, -0.5102510688760657) + assert math.alike(o, -0.5102510654033415) data = [12.0, 7.88, 76.122, 54.83] o = stats.lag1_autocorrelation(data) - assert math.alike(o, 0.10484451223403927) + assert math.alike(o, 0.10484450460892072) // test for int, i64, f32 array assert stats.lag1_autocorrelation[int]([1, 2, 3, 1]) == 0 @@ -446,13 +446,13 @@ fn test_lag1_autocorrelation() { fn test_kurtosis() { mut data := [10.0, 4.45, 5.9, 2.7] mut o := stats.kurtosis(data) - assert math.alike(o, -1.0443214689384779) + assert math.alike(o, -1.0443212849233845) data = [-3.0, 67.31, 4.4, 1.89] o = stats.kurtosis(data) - assert math.alike(o, -0.688495594786176) + assert math.alike(o, -0.6884953374814851) data = [12.0, 7.88, 76.122, 54.83] o = stats.kurtosis(data) - assert math.alike(o, -1.7323772574195067) + assert math.alike(o, -1.7323772836921467) // test for int, i64, f32 array assert stats.kurtosis[int]([1, 2, 3, 1]) == 1 @@ -464,13 +464,13 @@ fn test_kurtosis() { fn test_skew() { mut data := [10.0, 4.45, 5.9, 2.7] mut o := stats.skew(data) - assert math.alike(o, 0.5754020379048158) + assert math.alike(o, 0.5754021106320453) data = [-3.0, 67.31, 4.4, 1.89] o = stats.skew(data) - assert math.alike(o, 1.1248732608899568) + assert math.alike(o, 1.1248733711136492) data = [12.0, 7.88, 76.122, 54.83] o = stats.skew(data) - assert math.alike(o, 0.19007917421924964) + assert math.alike(o, 0.19007911706827735) // test for int, i64, f32 array assert stats.skew[int]([1, 2, 3, 1]) == 2 @@ -484,13 +484,13 @@ fn test_quantile() { mut data := [2.7, 4.45, 5.9, 10.0] mut o := stats.quantile(data, 0.1)! - assert math.alike(o, 3.225000020861626) + assert math.alike(o, 3.2249999046325684) data = [-3.0, 1.89, 4.4, 67.31] o = stats.quantile(data, 0.2)! - assert math.alike(o, -0.06599988341331486) + assert math.alike(o, -0.06600001454353333) data = [7.88, 12.0, 54.83, 76.122] o = stats.quantile(data, 0.3)! - assert math.alike(o, 11.587999901771546) + assert math.alike(o, 11.588000297546387) stats.quantile(data, -0.3) or { assert err.msg() == 'index out of range' } diff --git a/vlib/v/checker/assign.v b/vlib/v/checker/assign.v index aeee42b65c2463..2c578c354cc837 100644 --- a/vlib/v/checker/assign.v +++ b/vlib/v/checker/assign.v @@ -410,6 +410,11 @@ fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) { left.obj.ct_type_var = .field_var left.obj.typ = c.comptime.comptime_for_field_type } + } else if mut right is ast.InfixExpr { + right_ct_var := c.comptime.get_ct_type_var(right.left) + if right_ct_var in [.generic_var, .generic_param] { + left.obj.ct_type_var = right_ct_var + } } else if mut right is ast.Ident && right.obj is ast.Var && right.or_expr.kind == .absent { right_obj_var := right.obj as ast.Var diff --git a/vlib/v/gen/c/assign.v b/vlib/v/gen/c/assign.v index a62d8b80f4b0bf..922fcf0d009f07 100644 --- a/vlib/v/gen/c/assign.v +++ b/vlib/v/gen/c/assign.v @@ -371,6 +371,14 @@ fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) { left.obj.typ = var_type g.assign_ct_type = var_type } + } else if val is ast.InfixExpr { + ctyp := g.unwrap_generic(g.type_resolver.get_type(val.left)) + if ctyp != ast.void_type { + var_type = ctyp + val_type = var_type + left.obj.typ = var_type + g.assign_ct_type = var_type + } } is_auto_heap = left.obj.is_auto_heap } diff --git a/vlib/v/type_resolver/generic_resolver.v b/vlib/v/type_resolver/generic_resolver.v index dbbce60de0a3c0..d4cd21dbf28dfc 100644 --- a/vlib/v/type_resolver/generic_resolver.v +++ b/vlib/v/type_resolver/generic_resolver.v @@ -303,7 +303,7 @@ pub fn (mut t TypeResolver) resolve_args(cur_fn &ast.FnDecl, func &ast.Fn, mut n comptime_args[k] = m.return_type } } - } else if mut call_arg.expr is ast.CastExpr { + } else if mut call_arg.expr is ast.CastExpr && call_arg.expr.typ.has_flag(.generic) { cparam_type_sym := t.table.sym(t.resolver.unwrap_generic(call_arg.expr.typ)) param_typ_sym := t.table.sym(param_typ) if param_typ_sym.kind == .map && cparam_type_sym.info is ast.Map { diff --git a/vlib/v/type_resolver/type_resolver.v b/vlib/v/type_resolver/type_resolver.v index fc0225faa0f937..c74cc58f888ae3 100644 --- a/vlib/v/type_resolver/type_resolver.v +++ b/vlib/v/type_resolver/type_resolver.v @@ -119,6 +119,19 @@ pub fn (mut t TypeResolver) get_type_or_default(node ast.Expr, default_typ ast.T return t.get_type_or_default(node.left, default_typ) } } + ast.IndexExpr { + if node.left is ast.Ident && node.left.ct_expr { + ctyp := t.get_type(node) + if ctyp != ast.void_type { + return ctyp + } + } + } + ast.CastExpr { + if node.typ.has_flag(.generic) { + return t.resolver.unwrap_generic(node.typ) + } + } else { return default_typ } @@ -184,6 +197,12 @@ pub fn (mut t TypeResolver) get_type(node ast.Expr) ast.Type { nltype := t.get_type(node.left) nltype_unwrapped := t.resolver.unwrap_generic(nltype) return t.table.value_type(nltype_unwrapped) + } else if node is ast.ParExpr && t.info.is_comptime(node.expr) { + return t.get_type(node.expr) + } else if node is ast.InfixExpr && t.info.is_comptime(node.left) { + return t.get_type(node.left) + } else if node is ast.CastExpr && node.typ.has_flag(.generic) { + return t.resolver.unwrap_generic(node.typ) } return ast.void_type } From d8a06a865b6e1256886fedb38706b1b5e6ddf858 Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Thu, 2 Jan 2025 17:00:21 -0300 Subject: [PATCH 08/17] fix --- vlib/math/stats/stats_test.v | 4 ++-- vlib/v/checker/assign.v | 8 +++++++- vlib/v/gen/c/assign.v | 6 +++++- vlib/v/type_resolver/comptime_resolver.v | 4 ++++ 4 files changed, 18 insertions(+), 4 deletions(-) diff --git a/vlib/math/stats/stats_test.v b/vlib/math/stats/stats_test.v index 4610baba66acec..ebbd3bf88f0b61 100644 --- a/vlib/math/stats/stats_test.v +++ b/vlib/math/stats/stats_test.v @@ -458,7 +458,7 @@ fn test_kurtosis() { assert stats.kurtosis[int]([1, 2, 3, 1]) == 1 assert stats.kurtosis[i64]([i64(1), 2, 3, 1]) == 1 o = stats.kurtosis[f32]([f32(1.0), 3, 5, 7, 3]) - assert math.alike(o, -1.0443782806396484) + assert math.alike(o, -1.044378399848938) } fn test_skew() { @@ -476,7 +476,7 @@ fn test_skew() { assert stats.skew[int]([1, 2, 3, 1]) == 2 assert stats.skew[i64]([i64(1), 2, 3, 1]) == 2 o = stats.skew[f32]([f32(1.0), 3, 5, 7, 3]) - assert math.alike(o, 0.2715454697608948) + assert math.alike(o, 0.27154541015625) } fn test_quantile() { diff --git a/vlib/v/checker/assign.v b/vlib/v/checker/assign.v index 2c578c354cc837..bdb270be7c0951 100644 --- a/vlib/v/checker/assign.v +++ b/vlib/v/checker/assign.v @@ -412,7 +412,13 @@ fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) { } } else if mut right is ast.InfixExpr { right_ct_var := c.comptime.get_ct_type_var(right.left) - if right_ct_var in [.generic_var, .generic_param] { + if right_ct_var != .no_comptime { + left.obj.ct_type_var = right_ct_var + } + } else if mut right is ast.IndexExpr + && c.comptime.is_comptime(right) { + right_ct_var := c.comptime.get_ct_type_var(right.left) + if right_ct_var != .no_comptime { left.obj.ct_type_var = right_ct_var } } else if mut right is ast.Ident && right.obj is ast.Var diff --git a/vlib/v/gen/c/assign.v b/vlib/v/gen/c/assign.v index 922fcf0d009f07..9d1413ab7bb805 100644 --- a/vlib/v/gen/c/assign.v +++ b/vlib/v/gen/c/assign.v @@ -371,9 +371,13 @@ fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) { left.obj.typ = var_type g.assign_ct_type = var_type } - } else if val is ast.InfixExpr { + } else if val is ast.InfixExpr && g.comptime.is_comptime(val.left) { ctyp := g.unwrap_generic(g.type_resolver.get_type(val.left)) if ctyp != ast.void_type { + ct_type_var := g.comptime.get_ct_type_var(val.left) + if ct_type_var in [.key_var, .value_var] { + g.type_resolver.update_ct_type(left.name, g.unwrap_generic(ctyp)) + } var_type = ctyp val_type = var_type left.obj.typ = var_type diff --git a/vlib/v/type_resolver/comptime_resolver.v b/vlib/v/type_resolver/comptime_resolver.v index 46c7cd91d51868..a01813dc08d307 100644 --- a/vlib/v/type_resolver/comptime_resolver.v +++ b/vlib/v/type_resolver/comptime_resolver.v @@ -76,6 +76,10 @@ pub fn (t &ResolverInfo) get_ct_type_var(node ast.Expr) ast.ComptimeVarKind { } } else if node is ast.IndexExpr { return t.get_ct_type_var(node.left) + } else if node is ast.InfixExpr { + return t.get_ct_type_var(node.left) + } else if node is ast.ParExpr { + return t.get_ct_type_var(node.expr) } return .no_comptime } From 58a74596d387452b1392fc7fc23d8d027ca4c7a8 Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Thu, 2 Jan 2025 17:16:56 -0300 Subject: [PATCH 09/17] log --- vlib/math/stats/stats_test.v | 2 ++ 1 file changed, 2 insertions(+) diff --git a/vlib/math/stats/stats_test.v b/vlib/math/stats/stats_test.v index ebbd3bf88f0b61..ee37d2bb051eaf 100644 --- a/vlib/math/stats/stats_test.v +++ b/vlib/math/stats/stats_test.v @@ -446,6 +446,7 @@ fn test_lag1_autocorrelation() { fn test_kurtosis() { mut data := [10.0, 4.45, 5.9, 2.7] mut o := stats.kurtosis(data) + dump(o) assert math.alike(o, -1.0443212849233845) data = [-3.0, 67.31, 4.4, 1.89] o = stats.kurtosis(data) @@ -464,6 +465,7 @@ fn test_kurtosis() { fn test_skew() { mut data := [10.0, 4.45, 5.9, 2.7] mut o := stats.skew(data) + dump(o) assert math.alike(o, 0.5754021106320453) data = [-3.0, 67.31, 4.4, 1.89] o = stats.skew(data) From e9bec4fdd507248b5aa6da7ccee2099b435e7e62 Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Thu, 2 Jan 2025 17:32:34 -0300 Subject: [PATCH 10/17] fix --- vlib/math/stats/stats_test.v | 1 - 1 file changed, 1 deletion(-) diff --git a/vlib/math/stats/stats_test.v b/vlib/math/stats/stats_test.v index ee37d2bb051eaf..ba8189695622cf 100644 --- a/vlib/math/stats/stats_test.v +++ b/vlib/math/stats/stats_test.v @@ -446,7 +446,6 @@ fn test_lag1_autocorrelation() { fn test_kurtosis() { mut data := [10.0, 4.45, 5.9, 2.7] mut o := stats.kurtosis(data) - dump(o) assert math.alike(o, -1.0443212849233845) data = [-3.0, 67.31, 4.4, 1.89] o = stats.kurtosis(data) From 07e8dc5385ad9364581eb869f167877ebb911488 Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Thu, 2 Jan 2025 17:55:01 -0300 Subject: [PATCH 11/17] fix --- vlib/v/gen/c/assign.v | 3 ++- vlib/v/type_resolver/comptime_resolver.v | 6 +++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/vlib/v/gen/c/assign.v b/vlib/v/gen/c/assign.v index 9d1413ab7bb805..609dadb5e71e49 100644 --- a/vlib/v/gen/c/assign.v +++ b/vlib/v/gen/c/assign.v @@ -371,7 +371,8 @@ fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) { left.obj.typ = var_type g.assign_ct_type = var_type } - } else if val is ast.InfixExpr && g.comptime.is_comptime(val.left) { + } else if val is ast.InfixExpr && val.op in [.plus, .minus, .mul, .div, .mod] + && g.comptime.is_comptime(val.left) { ctyp := g.unwrap_generic(g.type_resolver.get_type(val.left)) if ctyp != ast.void_type { ct_type_var := g.comptime.get_ct_type_var(val.left) diff --git a/vlib/v/type_resolver/comptime_resolver.v b/vlib/v/type_resolver/comptime_resolver.v index a01813dc08d307..c7cf6b0236df60 100644 --- a/vlib/v/type_resolver/comptime_resolver.v +++ b/vlib/v/type_resolver/comptime_resolver.v @@ -50,7 +50,11 @@ pub fn (t &ResolverInfo) is_comptime(node ast.Expr) bool { return node.expr is ast.Ident && node.expr.ct_expr } ast.InfixExpr { - return t.is_comptime(node.left) || t.is_comptime(node.right) + if node.op in [.plus, .minus, .mul, .div, .mod] { + t.is_comptime(node.left) || t.is_comptime(node.right) + } else { + false + } } ast.ParExpr { return t.is_comptime(node.expr) From 35f5acb2e3e1cd138cab279085aa2a8feabdcc3c Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Thu, 2 Jan 2025 18:37:23 -0300 Subject: [PATCH 12/17] fix --- vlib/math/stats/stats_test.v | 7 +++---- vlib/v/gen/c/infix.v | 4 +++- vlib/v/type_resolver/type_resolver.v | 13 ++++++++++--- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/vlib/math/stats/stats_test.v b/vlib/math/stats/stats_test.v index ba8189695622cf..4472421714b12a 100644 --- a/vlib/math/stats/stats_test.v +++ b/vlib/math/stats/stats_test.v @@ -464,7 +464,6 @@ fn test_kurtosis() { fn test_skew() { mut data := [10.0, 4.45, 5.9, 2.7] mut o := stats.skew(data) - dump(o) assert math.alike(o, 0.5754021106320453) data = [-3.0, 67.31, 4.4, 1.89] o = stats.skew(data) @@ -485,13 +484,13 @@ fn test_quantile() { mut data := [2.7, 4.45, 5.9, 10.0] mut o := stats.quantile(data, 0.1)! - assert math.alike(o, 3.2249999046325684) + assert math.alike(o, 3.225) data = [-3.0, 1.89, 4.4, 67.31] o = stats.quantile(data, 0.2)! - assert math.alike(o, -0.06600001454353333) + assert math.alike(o, -0.06599999999999961) data = [7.88, 12.0, 54.83, 76.122] o = stats.quantile(data, 0.3)! - assert math.alike(o, 11.588000297546387) + assert math.alike(o, 11.588) stats.quantile(data, -0.3) or { assert err.msg() == 'index out of range' } diff --git a/vlib/v/gen/c/infix.v b/vlib/v/gen/c/infix.v index bb446e4ddea887..ad68ab8db72351 100644 --- a/vlib/v/gen/c/infix.v +++ b/vlib/v/gen/c/infix.v @@ -1188,8 +1188,10 @@ fn (mut g Gen) gen_plain_infix_expr(node ast.InfixExpr) { && node.op in [.plus, .minus, .mul, .div, .mod] && !(g.pref.translated || g.file.is_translated) if needs_cast { - typ_str := if g.comptime.is_comptime(node.left) { + typ_str := if !node.left.is_literal() && g.comptime.is_comptime(node.left) { g.styp(g.type_resolver.get_type_or_default(node.left, node.promoted_type)) + } else if !node.right.is_literal() && g.comptime.is_comptime(node.right) { + g.styp(g.type_resolver.get_type_or_default(node.right, node.promoted_type)) } else { g.styp(node.promoted_type) } diff --git a/vlib/v/type_resolver/type_resolver.v b/vlib/v/type_resolver/type_resolver.v index c74cc58f888ae3..0bdeb8b48d4bbf 100644 --- a/vlib/v/type_resolver/type_resolver.v +++ b/vlib/v/type_resolver/type_resolver.v @@ -115,9 +115,12 @@ pub fn (mut t TypeResolver) get_type_or_default(node ast.Expr, default_typ ast.T return t.get_type_or_default(node.expr, default_typ) } ast.InfixExpr { - if node.op in [.plus, .minus, .mul, .div, .mod] { + if !node.left.is_literal() && node.op in [.plus, .minus, .mul, .div, .mod] { return t.get_type_or_default(node.left, default_typ) } + if !node.right.is_literal() && node.op in [.plus, .minus, .mul, .div, .mod] { + return t.get_type_or_default(node.right, default_typ) + } } ast.IndexExpr { if node.left is ast.Ident && node.left.ct_expr { @@ -199,8 +202,12 @@ pub fn (mut t TypeResolver) get_type(node ast.Expr) ast.Type { return t.table.value_type(nltype_unwrapped) } else if node is ast.ParExpr && t.info.is_comptime(node.expr) { return t.get_type(node.expr) - } else if node is ast.InfixExpr && t.info.is_comptime(node.left) { - return t.get_type(node.left) + } else if node is ast.InfixExpr { + if !node.left.is_literal() && t.info.is_comptime(node.left) { + return t.get_type(node.left) + } else if !node.right.is_literal() && t.info.is_comptime(node.right) { + return t.get_type(node.right) + } } else if node is ast.CastExpr && node.typ.has_flag(.generic) { return t.resolver.unwrap_generic(node.typ) } From 8f63c39534d9698bc9277da15d51bf26d5b1c564 Mon Sep 17 00:00:00 2001 From: Delyan Angelov Date: Fri, 3 Jan 2025 20:20:44 +0200 Subject: [PATCH 13/17] fix stats_test.v, when run with `v -exclude @vlib/math/*.c.v vlib/math/stats/stats_test.v` --- vlib/math/stats/stats_test.v | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/vlib/math/stats/stats_test.v b/vlib/math/stats/stats_test.v index 4472421714b12a..7c9dcb30886457 100644 --- a/vlib/math/stats/stats_test.v +++ b/vlib/math/stats/stats_test.v @@ -443,13 +443,19 @@ fn test_lag1_autocorrelation() { assert math.alike(o, 0.1975308507680893) } +fn diff(actual f64, expected f64) string { + return '\nactual:\n${actual}\nexpected:\n${expected}' +} + fn test_kurtosis() { mut data := [10.0, 4.45, 5.9, 2.7] mut o := stats.kurtosis(data) - assert math.alike(o, -1.0443212849233845) + mut e := -1.0443212849233845 + assert math.close(o, e), diff(o, e) data = [-3.0, 67.31, 4.4, 1.89] o = stats.kurtosis(data) - assert math.alike(o, -0.6884953374814851) + e = -0.6884953374814851 + assert math.close(o, e), diff(o, e) data = [12.0, 7.88, 76.122, 54.83] o = stats.kurtosis(data) assert math.alike(o, -1.7323772836921467) @@ -464,10 +470,12 @@ fn test_kurtosis() { fn test_skew() { mut data := [10.0, 4.45, 5.9, 2.7] mut o := stats.skew(data) - assert math.alike(o, 0.5754021106320453) + mut e := 0.5754021106320453 + assert math.veryclose(o, e), diff(o, e) data = [-3.0, 67.31, 4.4, 1.89] o = stats.skew(data) - assert math.alike(o, 1.1248733711136492) + e = 1.1248733711136492 + assert math.veryclose(o, e), diff(o, e) data = [12.0, 7.88, 76.122, 54.83] o = stats.skew(data) assert math.alike(o, 0.19007911706827735) From f30f95066c2b117793bd0637954c36e713f25959 Mon Sep 17 00:00:00 2001 From: Delyan Angelov Date: Fri, 3 Jan 2025 21:19:43 +0200 Subject: [PATCH 14/17] fixes for clang on macos --- vlib/math/stats/stats.v | 16 +++++++++++----- vlib/math/stats/stats_test.v | 17 +++++++++++------ 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/vlib/math/stats/stats.v b/vlib/math/stats/stats.v index ed071d6bacb640..6462a743ced615 100644 --- a/vlib/math/stats/stats.v +++ b/vlib/math/stats/stats.v @@ -434,7 +434,7 @@ pub fn covariance_mean[T](data1 []T, data2 []T, mean1 T, mean2 T) T { for i in 0 .. n { delta1 := data1[i] - mean1 delta2 := data2[i] - mean2 - covariance += T((delta1 * delta2 - covariance) / (i + T(1))) + covariance += T((delta1 * delta2 - covariance) / (T(i) + T(1))) } return covariance } @@ -459,8 +459,11 @@ pub fn lag1_autocorrelation_mean[T](data []T, mean T) T { for i := 1; i < data.len; i++ { delta0 := data[i - 1] - mean delta1 := data[i] - mean - q += T((delta0 * delta1 - q) / (i + T(1))) - v += T((delta1 * delta1 - v) / (T(i) + T(1))) + d01 := delta0 * delta1 + d11 := delta1 * delta1 + ti1 := T(i) + T(1) + q += T((d01 - q) / ti1) + v += T((d11 - v) / ti1) } return T(q / v) } @@ -486,7 +489,9 @@ pub fn kurtosis_mean_stddev[T](data []T, mean T, sd T) T { */ for i, v in data { x := (v - mean) / sd - avg += T((x * x * x * x - avg) / (i + T(1))) + x4 := x * x * x * x + ti1 := (T(i) + T(1)) + avg += T((x4 - avg) / ti1) } return avg - T(3) } @@ -511,7 +516,8 @@ pub fn skew_mean_stddev[T](data []T, mean T, sd T) T { */ for i, v in data { x := (v - mean) / sd - skew += T((x * x * x - skew) / (i + T(1))) + x3 := x * x * x + skew += T((x3 - skew) / (T(i) + T(1))) } return skew } diff --git a/vlib/math/stats/stats_test.v b/vlib/math/stats/stats_test.v index 7c9dcb30886457..dbdafc789449e9 100644 --- a/vlib/math/stats/stats_test.v +++ b/vlib/math/stats/stats_test.v @@ -428,13 +428,15 @@ fn test_covariance() { fn test_lag1_autocorrelation() { mut data := [10.0, 4.45, 5.9, 2.7] mut o := stats.lag1_autocorrelation(data) + mut e := 0.0 assert math.alike(o, -0.5542285481446095) data = [-3.0, 67.31, 4.4, 1.89] o = stats.lag1_autocorrelation(data) assert math.alike(o, -0.5102510654033415) data = [12.0, 7.88, 76.122, 54.83] o = stats.lag1_autocorrelation(data) - assert math.alike(o, 0.10484450460892072) + e = 0.10484450460892072 + assert math.veryclose(o, e), diff(o, e) // test for int, i64, f32 array assert stats.lag1_autocorrelation[int]([1, 2, 3, 1]) == 0 @@ -444,7 +446,7 @@ fn test_lag1_autocorrelation() { } fn diff(actual f64, expected f64) string { - return '\nactual:\n${actual}\nexpected:\n${expected}' + return '\n actual:${actual:40.35f}\nexpected:${expected:40.35f}\n diff:${actual - expected:40.35f}' } fn test_kurtosis() { @@ -464,27 +466,30 @@ fn test_kurtosis() { assert stats.kurtosis[int]([1, 2, 3, 1]) == 1 assert stats.kurtosis[i64]([i64(1), 2, 3, 1]) == 1 o = stats.kurtosis[f32]([f32(1.0), 3, 5, 7, 3]) - assert math.alike(o, -1.044378399848938) + e = -1.044378399848938 + assert math.alike(o, e), diff(o, e) } fn test_skew() { mut data := [10.0, 4.45, 5.9, 2.7] mut o := stats.skew(data) mut e := 0.5754021106320453 - assert math.veryclose(o, e), diff(o, e) + assert math.close(o, e), diff(o, e) data = [-3.0, 67.31, 4.4, 1.89] o = stats.skew(data) e = 1.1248733711136492 assert math.veryclose(o, e), diff(o, e) data = [12.0, 7.88, 76.122, 54.83] o = stats.skew(data) - assert math.alike(o, 0.19007911706827735) + e = 0.19007911706827735 + assert math.veryclose(o, e), diff(o, e) // test for int, i64, f32 array assert stats.skew[int]([1, 2, 3, 1]) == 2 assert stats.skew[i64]([i64(1), 2, 3, 1]) == 2 o = stats.skew[f32]([f32(1.0), 3, 5, 7, 3]) - assert math.alike(o, 0.27154541015625) + e = 0.27154541015625 + assert math.close(o, e), diff(o, e) } fn test_quantile() { From bb64e14f7a40c2229119ab2a7d78f2be3765f3db Mon Sep 17 00:00:00 2001 From: Delyan Angelov Date: Fri, 3 Jan 2025 21:23:35 +0200 Subject: [PATCH 15/17] change stats_test.v to use math.alike again --- vlib/math/stats/stats_test.v | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/vlib/math/stats/stats_test.v b/vlib/math/stats/stats_test.v index dbdafc789449e9..cf68f5532d8071 100644 --- a/vlib/math/stats/stats_test.v +++ b/vlib/math/stats/stats_test.v @@ -436,7 +436,7 @@ fn test_lag1_autocorrelation() { data = [12.0, 7.88, 76.122, 54.83] o = stats.lag1_autocorrelation(data) e = 0.10484450460892072 - assert math.veryclose(o, e), diff(o, e) + assert math.alike(o, e), diff(o, e) // test for int, i64, f32 array assert stats.lag1_autocorrelation[int]([1, 2, 3, 1]) == 0 @@ -453,11 +453,11 @@ fn test_kurtosis() { mut data := [10.0, 4.45, 5.9, 2.7] mut o := stats.kurtosis(data) mut e := -1.0443212849233845 - assert math.close(o, e), diff(o, e) + assert math.alike(o, e), diff(o, e) data = [-3.0, 67.31, 4.4, 1.89] o = stats.kurtosis(data) e = -0.6884953374814851 - assert math.close(o, e), diff(o, e) + assert math.alike(o, e), diff(o, e) data = [12.0, 7.88, 76.122, 54.83] o = stats.kurtosis(data) assert math.alike(o, -1.7323772836921467) @@ -474,22 +474,22 @@ fn test_skew() { mut data := [10.0, 4.45, 5.9, 2.7] mut o := stats.skew(data) mut e := 0.5754021106320453 - assert math.close(o, e), diff(o, e) + assert math.alike(o, e), diff(o, e) data = [-3.0, 67.31, 4.4, 1.89] o = stats.skew(data) e = 1.1248733711136492 - assert math.veryclose(o, e), diff(o, e) + assert math.alike(o, e), diff(o, e) data = [12.0, 7.88, 76.122, 54.83] o = stats.skew(data) e = 0.19007911706827735 - assert math.veryclose(o, e), diff(o, e) + assert math.alike(o, e), diff(o, e) // test for int, i64, f32 array assert stats.skew[int]([1, 2, 3, 1]) == 2 assert stats.skew[i64]([i64(1), 2, 3, 1]) == 2 o = stats.skew[f32]([f32(1.0), 3, 5, 7, 3]) e = 0.27154541015625 - assert math.close(o, e), diff(o, e) + assert math.alike(o, e), diff(o, e) } fn test_quantile() { From 9f3ca79cefe0b7842e10726523786206e540ee78 Mon Sep 17 00:00:00 2001 From: Delyan Angelov Date: Fri, 3 Jan 2025 21:28:05 +0200 Subject: [PATCH 16/17] relax the stats_test.v checks a bit for linux --- vlib/math/stats/stats_test.v | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/vlib/math/stats/stats_test.v b/vlib/math/stats/stats_test.v index cf68f5532d8071..72944e6064dcc6 100644 --- a/vlib/math/stats/stats_test.v +++ b/vlib/math/stats/stats_test.v @@ -453,11 +453,11 @@ fn test_kurtosis() { mut data := [10.0, 4.45, 5.9, 2.7] mut o := stats.kurtosis(data) mut e := -1.0443212849233845 - assert math.alike(o, e), diff(o, e) + assert math.close(o, e), diff(o, e) data = [-3.0, 67.31, 4.4, 1.89] o = stats.kurtosis(data) e = -0.6884953374814851 - assert math.alike(o, e), diff(o, e) + assert math.close(o, e), diff(o, e) data = [12.0, 7.88, 76.122, 54.83] o = stats.kurtosis(data) assert math.alike(o, -1.7323772836921467) @@ -474,11 +474,11 @@ fn test_skew() { mut data := [10.0, 4.45, 5.9, 2.7] mut o := stats.skew(data) mut e := 0.5754021106320453 - assert math.alike(o, e), diff(o, e) + assert math.veryclose(o, e), diff(o, e) data = [-3.0, 67.31, 4.4, 1.89] o = stats.skew(data) e = 1.1248733711136492 - assert math.alike(o, e), diff(o, e) + assert math.veryclose(o, e), diff(o, e) data = [12.0, 7.88, 76.122, 54.83] o = stats.skew(data) e = 0.19007911706827735 From aa956e1a2f367c2584c40fd6a613bdddfaa9f67c Mon Sep 17 00:00:00 2001 From: Delyan Angelov Date: Sat, 4 Jan 2025 00:00:26 +0200 Subject: [PATCH 17/17] fix `./v -cg -keepc -gc none -cc clang-18 -cflags -fsanitize=memory vlib/math/stats/stats_test.v` --- vlib/strconv/format.v | 16 ++++++++++++++++ vlib/strconv/format_mem.c.v | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/vlib/strconv/format.v b/vlib/strconv/format.v index 368cae42245647..9009da8aacbf64 100644 --- a/vlib/strconv/format.v +++ b/vlib/strconv/format.v @@ -43,6 +43,22 @@ const dec_round = [ 0.000000000000000005, 0.0000000000000000005, 0.00000000000000000005, + 0.000000000000000000005, + 0.0000000000000000000005, + 0.00000000000000000000005, + 0.000000000000000000000005, + 0.0000000000000000000000005, + 0.00000000000000000000000005, + 0.000000000000000000000000005, + 0.0000000000000000000000000005, + 0.00000000000000000000000000005, + 0.000000000000000000000000000005, + 0.0000000000000000000000000000005, + 0.00000000000000000000000000000005, + 0.000000000000000000000000000000005, + 0.0000000000000000000000000000000005, + 0.00000000000000000000000000000000005, + 0.000000000000000000000000000000000005, ]! // Single format functions diff --git a/vlib/strconv/format_mem.c.v b/vlib/strconv/format_mem.c.v index 1b5dca4200aa1f..e079c609a02769 100644 --- a/vlib/strconv/format_mem.c.v +++ b/vlib/strconv/format_mem.c.v @@ -209,7 +209,7 @@ pub fn f64_to_str_lnd1(f f64, dec_digit int) string { // allocate exp+32 chars for the return string // mut res := []u8{len:exp+32,init:`0`} - mut res := []u8{len: exp + 32, init: 0} + mut res := []u8{len: exp + 40, init: 0} mut r_i := 0 // result string buffer index // println("s:${sgn} b:${b[0]} es:${exp_sgn} exp:${exp}")