From 192d6d2b8420bff4a145f1a171c425bba65d09e6 Mon Sep 17 00:00:00 2001 From: Delyan Angelov Date: Wed, 15 Nov 2023 20:32:16 +0200 Subject: [PATCH] v: support `$if T is $array_dynamic {` and `$if T is $array_fixed {` in addition to `$if T is $array {` (#19882) --- doc/docs.md | 2 ++ vlib/v/ast/ast.v | 6 ++++ vlib/v/ast/table.v | 9 +++++ vlib/v/fmt/fmt.v | 3 ++ vlib/v/gen/golang/golang.v | 3 ++ vlib/v/parser/comptime.v | 49 +++++++++++++++----------- vlib/v/tests/comptime_kinds_test.v | 56 ++++++++++++++++++++++++++++++ vlib/v/tests/comptime_type_test.v | 8 ++++- 8 files changed, 115 insertions(+), 21 deletions(-) diff --git a/doc/docs.md b/doc/docs.md index 242be7bfcfb9dd..1bc77c0190de20 100644 --- a/doc/docs.md +++ b/doc/docs.md @@ -5798,6 +5798,8 @@ V supports the following compile time types: - `$alias` => matches [Type aliases](#type-aliases). - `$array` => matches [Arrays](#arrays) and [Fixed Size Arrays](#fixed-size-arrays). +- `$array_dynamic` => matches [Arrays](#arrays), but not [Fixed Size Arrays](#fixed-size-arrays). +- `$array_fixed` => matches [Fixed Size Arrays](#fixed-size-arrays), but not [Arrays](#arrays) - `$enum` => matches [Enums](#enums). - `$float` => matches `f32`, `f64` and float literals. - `$function` => matches [Function Types](#function-types). diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index 4f1930643530ed..d99be1839f366b 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -130,12 +130,15 @@ pub mut: } pub enum ComptimeTypeKind { + unknown map_ int float struct_ iface array + array_fixed + array_dynamic sum_type enum_ alias @@ -151,12 +154,15 @@ pub: pub fn (cty ComptimeType) str() string { return match cty.kind { + .unknown { '\$unknown' } .map_ { '\$map' } .int { '\$int' } .float { '\$float' } .struct_ { '\$struct' } .iface { '\$interface' } .array { '\$array' } + .array_dynamic { '\$array_dynamic' } + .array_fixed { '\$array_fixed' } .sum_type { '\$sumtype' } .enum_ { '\$enum' } .alias { '\$alias' } diff --git a/vlib/v/ast/table.v b/vlib/v/ast/table.v index 18941413f246ba..097546c1586b3b 100644 --- a/vlib/v/ast/table.v +++ b/vlib/v/ast/table.v @@ -2303,6 +2303,9 @@ pub fn (t &Table) get_generic_names(generic_types []Type) []string { pub fn (t &Table) is_comptime_type(x Type, y ComptimeType) bool { x_kind := t.type_kind(x) match y.kind { + .unknown { + return false + } .map_ { return x_kind == .map } @@ -2322,6 +2325,12 @@ pub fn (t &Table) is_comptime_type(x Type, y ComptimeType) bool { .array { return x_kind in [.array, .array_fixed] } + .array_dynamic { + return x_kind == .array + } + .array_fixed { + return x_kind == .array_fixed + } .sum_type { return x_kind == .sum_type } diff --git a/vlib/v/fmt/fmt.v b/vlib/v/fmt/fmt.v index 8ee903b9a6a820..a2b92d9a42c075 100644 --- a/vlib/v/fmt/fmt.v +++ b/vlib/v/fmt/fmt.v @@ -757,7 +757,10 @@ pub fn (mut f Fmt) expr(node_ ast.Expr) { } ast.ComptimeType { match node.kind { + .unknown { f.write('\$unknown') } .array { f.write('\$array') } + .array_dynamic { f.write('\$array_dynamic') } + .array_fixed { f.write('\$array_fixed') } .struct_ { f.write('\$struct') } .iface { f.write('\$interface') } .map_ { f.write('\$map') } diff --git a/vlib/v/gen/golang/golang.v b/vlib/v/gen/golang/golang.v index 2cbd17e3663a9d..1688f97ab4365d 100644 --- a/vlib/v/gen/golang/golang.v +++ b/vlib/v/gen/golang/golang.v @@ -660,7 +660,10 @@ pub fn (mut f Gen) expr(node_ ast.Expr) { } ast.ComptimeType { match node.kind { + .unknown { f.write('\$unknown') } .array { f.write('\$array') } + .array_dynamic { f.write('\$array_dynamic') } + .array_fixed { f.write('\$array_fixed') } .struct_ { f.write('\$struct') } .iface { f.write('\$interface') } .map_ { f.write('\$map') } diff --git a/vlib/v/parser/comptime.v b/vlib/v/parser/comptime.v index 5a88dc22bcbb12..1b8b3cd2020339 100644 --- a/vlib/v/parser/comptime.v +++ b/vlib/v/parser/comptime.v @@ -11,57 +11,66 @@ import v.token const ( supported_comptime_calls = ['html', 'tmpl', 'env', 'embed_file', 'pkgconfig', 'compile_error', 'compile_warn', 'res'] - comptime_types = ['map', 'array', 'int', 'float', 'struct', 'interface', 'enum', - 'sumtype', 'alias', 'function', 'option'] + comptime_types = ['map', 'array', 'array_dynamic', 'array_fixed', 'int', 'float', + 'struct', 'interface', 'enum', 'sumtype', 'alias', 'function', 'option'] ) fn (mut p Parser) parse_comptime_type() ast.ComptimeType { - mut node := ast.ComptimeType{ast.ComptimeTypeKind.map_, p.tok.pos()} - + pos := p.tok.pos() p.check(.dollar) name := p.check_name() if name !in parser.comptime_types { p.error('unsupported compile-time type `${name}`: only ${parser.comptime_types} are supported') } - mut cty := ast.ComptimeTypeKind.map_ - match name { + mut kind := ast.ComptimeTypeKind.unknown + kind = match name { 'map' { - cty = .map_ + .map_ } 'struct' { - cty = .struct_ + .struct_ } 'interface' { - cty = .iface + .iface } 'int' { - cty = .int + .int } 'float' { - cty = .float + .float } 'alias' { - cty = .alias + .alias } 'function' { - cty = .function + .function } 'array' { - cty = .array + .array + } + 'array_fixed' { + .array_fixed + } + 'array_dynamic' { + .array_dynamic } 'enum' { - cty = .enum_ + .enum_ } 'sumtype' { - cty = .sum_type + .sum_type } 'option' { - cty = .option + .option } - else {} + else { + .unknown + } + } + return ast.ComptimeType{ + kind: kind + pos: pos } - node = ast.ComptimeType{cty, node.pos} - return node } // // #include, #flag, #v diff --git a/vlib/v/tests/comptime_kinds_test.v b/vlib/v/tests/comptime_kinds_test.v index b53b0b0d5c8fb0..eeef19264b45b3 100644 --- a/vlib/v/tests/comptime_kinds_test.v +++ b/vlib/v/tests/comptime_kinds_test.v @@ -14,6 +14,22 @@ fn assert_array[T]() { } } +fn assert_array_dynamic[T]() { + $if T is $array_dynamic { + assert true + } $else { + assert false + } +} + +fn assert_array_fixed[T]() { + $if T is $array_fixed { + assert true + } $else { + assert false + } +} + fn assert_struct[T]() { $if T is $struct { assert true @@ -46,6 +62,22 @@ fn assert_not_array[T]() { } } +fn assert_not_array_dynamic[T]() { + $if T is $array_dynamic { + assert false + } $else { + assert true + } +} + +fn assert_not_array_fixed[T]() { + $if T is $array_fixed { + assert false + } $else { + assert true + } +} + struct Abc {} struct Bc {} @@ -73,6 +105,30 @@ fn test_kind_array() { assert_not_array[map[int]int]() } +fn test_kind_array_dynamic() { + assert_array_dynamic[[]int]() + assert_array_dynamic[[]f32]() + assert_array_dynamic[[]string]() + + assert_not_array_dynamic[Abc]() + assert_not_array_dynamic[string]() + assert_not_array_dynamic[int]() + assert_not_array_dynamic[map[int]int]() + assert_not_array_dynamic[[3]int]() +} + +fn test_kind_array_fixed() { + assert_array_fixed[[3]int]() + assert_array_fixed[[5]f32]() + assert_array_fixed[[6]string]() + + assert_not_array_fixed[Abc]() + assert_not_array_fixed[string]() + assert_not_array_fixed[int]() + assert_not_array_fixed[map[int]int]() + assert_not_array_fixed[[]int]() +} + fn test_kind_struct() { assert_struct[Abc]() assert_struct[Bc]() diff --git a/vlib/v/tests/comptime_type_test.v b/vlib/v/tests/comptime_type_test.v index 2c07d75b3a287b..5a2734c4b3dc32 100644 --- a/vlib/v/tests/comptime_type_test.v +++ b/vlib/v/tests/comptime_type_test.v @@ -11,6 +11,8 @@ type Sumtype = int | string struct Foo {} +fn dummy_fn() {} + struct Test { a Abc b map[string]string @@ -20,7 +22,7 @@ struct Test { f f64 g Alias h Foo - i fn () + i fn () = dummy_fn j Sumtype k ?int } @@ -37,11 +39,14 @@ fn test_comptime_types() { mut c_fn := 0 mut c_sum := 0 mut c_option := 0 + mut fixeda := 0 $for f in Test.fields { $if f.typ is $alias { c_alias++ } $else $if f.typ is $interface { i++ + } $else $if f.typ is $array_fixed { + fixeda++ } $else $if f.typ is $array { a++ } $else $if f.typ is $map { @@ -66,6 +71,7 @@ fn test_comptime_types() { assert a == 1 assert m == 1 assert e == 1 + assert fixeda == 0 assert c_int == 1 assert c_float == 1 assert c_alias == 1