1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

all: comptime type lowercase ($int, $enum, $option, etc) (#17732)

This commit is contained in:
Felipe Pena 2023-03-22 20:02:42 -03:00 committed by GitHub
parent 0afb41f7e1
commit 9a9cfe425c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 203 additions and 122 deletions

View File

@ -139,17 +139,17 @@ pub:
pub fn (cty ComptimeType) str() string {
return match cty.kind {
.map_ { '\$Map' }
.int { '\$Int' }
.float { '\$Float' }
.struct_ { '\$Struct' }
.iface { '\$Interface' }
.array { '\$Array' }
.sum_type { '\$Sumtype' }
.enum_ { '\$Enum' }
.alias { '\$Alias' }
.function { '\$Function' }
.option { '\$Option' }
.map_ { '\$map' }
.int { '\$int' }
.float { '\$float' }
.struct_ { '\$struct' }
.iface { '\$interface' }
.array { '\$array' }
.sum_type { '\$sumtype' }
.enum_ { '\$enum' }
.alias { '\$alias' }
.function { '\$function' }
.option { '\$option' }
}
}

View File

@ -732,17 +732,17 @@ pub fn (mut f Fmt) expr(node_ ast.Expr) {
}
ast.ComptimeType {
match node.kind {
.array { f.write('\$Array') }
.struct_ { f.write('\$Struct') }
.iface { f.write('\$Interface') }
.map_ { f.write('\$Map') }
.int { f.write('\$Int') }
.float { f.write('\$Float') }
.sum_type { f.write('\$Sumtype') }
.enum_ { f.write('\$Enum') }
.alias { f.write('\$Alias') }
.function { f.write('\$Function') }
.option { f.write('\$Option') }
.array { f.write('\$array') }
.struct_ { f.write('\$struct') }
.iface { f.write('\$interface') }
.map_ { f.write('\$map') }
.int { f.write('\$int') }
.float { f.write('\$float') }
.sum_type { f.write('\$sumtype') }
.enum_ { f.write('\$enum') }
.alias { f.write('\$alias') }
.function { f.write('\$function') }
.option { f.write('\$option') }
}
}
}

View File

@ -651,17 +651,17 @@ pub fn (mut f Gen) expr(node_ ast.Expr) {
}
ast.ComptimeType {
match node.kind {
.array { f.write('\$Array') }
.struct_ { f.write('\$Struct') }
.iface { f.write('\$Interface') }
.map_ { f.write('\$Map') }
.int { f.write('\$Int') }
.float { f.write('\$Float') }
.sum_type { f.write('\$Sumtype') }
.enum_ { f.write('\$Enum') }
.alias { f.write('\$Alias') }
.function { f.write('\$Function') }
.option { f.write('\$Option') }
.array { f.write('\$array') }
.struct_ { f.write('\$struct') }
.iface { f.write('\$interface') }
.map_ { f.write('\$map') }
.int { f.write('\$int') }
.float { f.write('\$float') }
.sum_type { f.write('\$sumtype') }
.enum_ { f.write('\$enum') }
.alias { f.write('\$alias') }
.function { f.write('\$function') }
.option { f.write('\$option') }
}
}
}

View File

@ -11,8 +11,8 @@ import v.token
const (
supported_comptime_calls = ['html', 'tmpl', 'env', 'embed_file', 'pkgconfig', 'compile_error',
'compile_warn']
comptime_types = ['Map', 'Array', 'Int', 'Float', 'Struct', 'Interface', 'Enum',
'Sumtype', 'Alias', 'Function', 'Option']
comptime_types = ['map', 'array', 'int', 'float', 'struct', 'interface', 'enum',
'sumtype', 'alias', 'function', 'option']
)
pub fn (mut p Parser) parse_comptime_type() ast.ComptimeType {
@ -25,37 +25,37 @@ pub fn (mut p Parser) parse_comptime_type() ast.ComptimeType {
}
mut cty := ast.ComptimeTypeKind.map_
match name {
'Map' {
'map' {
cty = .map_
}
'Struct' {
'struct' {
cty = .struct_
}
'Interface' {
'interface' {
cty = .iface
}
'Int' {
'int' {
cty = .int
}
'Float' {
'float' {
cty = .float
}
'Alias' {
'alias' {
cty = .alias
}
'Function' {
'function' {
cty = .function
}
'Array' {
'array' {
cty = .array
}
'Enum' {
'enum' {
cty = .enum_
}
'Sumtype' {
'sumtype' {
cty = .sum_type
}
'Option' {
'option' {
cty = .option
}
else {}

View File

@ -79,7 +79,7 @@ pub fn (mut p Parser) check_expr(precedence int) !ast.Expr {
}
.dollar {
match p.peek_tok.kind {
.name {
.name, .key_struct, .key_enum, .key_interface {
if p.peek_tok.lit in comptime_types {
node = p.parse_comptime_type()
} else {

View File

@ -674,7 +674,12 @@ fn (mut p Parser) check_name() string {
if p.peek_tok.kind == .dot && name in p.imports {
p.register_used_import(name)
}
p.check(.name)
match p.tok.kind {
.key_struct { p.check(.key_struct) }
.key_enum { p.check(.key_enum) }
.key_interface { p.check(.key_interface) }
else { p.check(.name) }
}
return name
}

View File

@ -7,7 +7,7 @@ fn main() {
}
fn func[T](mut t T) {
$if T is $Array {
$if T is $array {
for i in 0 .. t.len {
println(t[i])
}

View File

@ -10,15 +10,15 @@ pub fn func1[T](t &T) {
[inline]
pub fn func2[T](t &T) {
$if T is $Array {
$if T is $array {
unsafe {
for i in 0 .. t.len {
func2(&t[i])
}
}
} $else $if T is $Map {
} $else $if T is $map {
// fake_map(t, df)
} $else $if T is $Struct {
} $else $if T is $struct {
$for f in T.fields {
$if f.typ is string {
}

View File

@ -11,19 +11,19 @@ struct Test {
}
fn check[T](val T) string {
$if T in [$Array, $Struct] {
$if T in [$array, $struct] {
return 'array or struct'
} $else $if T in [u8, u16, u32] {
return 'unsigned int'
} $else $if T in [int, $Int] {
} $else $if T in [int, $int] {
return 'int'
} $else $if T in [$Float, f64, f32] {
} $else $if T in [$float, f64, f32] {
return 'f64'
} $else $if T in [$Map, map] {
} $else $if T in [$map, map] {
return 'map'
} $else $if T in [Abc, Abc] {
return 'Abc'
} $else $if T in [$Sumtype, Abc] {
} $else $if T in [$sumtype, Abc] {
return 'sumtype'
}
@ -32,22 +32,22 @@ fn check[T](val T) string {
fn check_not[T](val T) string {
mut str := string{}
$if T !in [$Array, $Array] {
$if T !in [$array, $array] {
str += '1'
}
$if T !in [u8, u16, u32] {
str += '2'
}
$if T !in [int, $Int] {
$if T !in [int, $int] {
str += '3'
}
$if T !in [$Float, f64, f32] {
$if T !in [$float, f64, f32] {
str += '4'
} $else $if T !in [$Map, map] {
} $else $if T !in [$map, map] {
str += '5'
} $else $if T !in [Abc, Abc] {
str += '6'
} $else $if T !in [$Sumtype, Abc] {
} $else $if T !in [$sumtype, Abc] {
str += '7'
}

View File

@ -1,5 +1,5 @@
fn assert_map[T]() {
$if T is $Map {
$if T is $map {
assert true
} $else {
assert false
@ -7,7 +7,7 @@ fn assert_map[T]() {
}
fn assert_array[T]() {
$if T is $Array {
$if T is $array {
assert true
} $else {
assert false
@ -15,7 +15,7 @@ fn assert_array[T]() {
}
fn assert_struct[T]() {
$if T is $Struct {
$if T is $struct {
assert true
} $else {
assert false
@ -23,7 +23,7 @@ fn assert_struct[T]() {
}
fn assert_not_struct[T]() {
$if T is $Struct {
$if T is $struct {
assert false
} $else {
assert true
@ -31,7 +31,7 @@ fn assert_not_struct[T]() {
}
fn assert_not_map[T]() {
$if T is $Map {
$if T is $map {
assert false
} $else {
assert true
@ -39,7 +39,7 @@ fn assert_not_map[T]() {
}
fn assert_not_array[T]() {
$if T is $Array {
$if T is $array {
assert false
} $else {
assert true
@ -90,7 +90,7 @@ type AliasOfint = int
type AliasOfstring = string
fn assert_alias[T]() {
$if T is $Alias {
$if T is $alias {
assert true
} $else {
assert false
@ -98,7 +98,7 @@ fn assert_alias[T]() {
}
fn assert_not_alias[T]() {
$if T is $Alias {
$if T is $alias {
assert false
} $else {
assert true
@ -119,7 +119,7 @@ fn test_kind_alias() {
//
fn assert_function[T](f T) {
$if T is $Function {
$if T is $function {
assert true
} $else {
assert false
@ -127,7 +127,7 @@ fn assert_function[T](f T) {
}
fn assert_not_function[T](f T) {
$if T is $Function {
$if T is $function {
assert false
} $else {
assert true

View File

@ -27,7 +27,7 @@ fn test_comptimeselector_map_different_types() {
mut vals := []string{}
$for field in Data.fields {
$if field.typ is $Map {
$if field.typ is $map {
for k, v in data.$(field.name) {
keys << k.str()
vals << v.str()
@ -57,7 +57,7 @@ fn test_comptime_var_map_different_types() {
mut vals := []string{}
$for field in Data.fields {
$if field.typ is $Map {
$if field.typ is $map {
gg := data.$(field.name)
for k, v in gg {
keys << k.str()
@ -85,7 +85,7 @@ fn test_comptime_with_dump() {
}
$for field in Data.fields {
$if field.typ is $Map {
$if field.typ is $map {
for k, v in data.$(field.name) {
dump(k)
dump(v)
@ -111,7 +111,7 @@ fn test_comptime_dump_for_key_and_value() {
mut val_types := []string{}
$for field in Data.fields {
$if field.typ is $Map {
$if field.typ is $map {
for k, v in data.$(field.name) {
key_types << typeof(k).name
val_types << typeof(v).name
@ -141,7 +141,7 @@ fn test_comptime_key_value_var() {
mut vals := []string{}
$for field in Data.fields {
$if field.typ is $Map {
$if field.typ is $map {
for k, v in data.$(field.name) {
if k == 'a' {
keys << dump(k)
@ -176,7 +176,7 @@ fn test_comptime_generic_argument() {
}
$for field in Data.fields {
$if field.typ is $Map {
$if field.typ is $map {
for k, v in data.$(field.name) {
process_value_from_map(v)
assert k in ['a', 'b']
@ -186,12 +186,12 @@ fn test_comptime_generic_argument() {
}
fn process_value_from_map[T](v T) {
$if T is $Map {
$if T is $map {
assert typeof(v).name == 'map[string]int'
assert v.str() == "{'c': 10}"
assert true
return
} $else $if T is $Struct {
} $else $if T is $struct {
assert typeof(v).name == 'StructType'
assert v.str() == "StructType{
val: 'string from StructType'

View File

@ -10,7 +10,7 @@ struct Test {
fn test_option_comptime() {
mut opts := []string{}
$for f in Test.fields {
$if f.typ is $Option {
$if f.typ is $option {
opts << f.name
}
}

View File

@ -10,7 +10,7 @@ fn test_main() {
}
fn map_from[T](t T) {
$if T is $Struct {
$if T is $struct {
$for field in T.fields {
assert Any('string').str() == "Any('string')"
assert t.$(field.name).str() == 'true'

View File

@ -0,0 +1,76 @@
interface Abc {}
enum EnumTest {
a
b
}
type Alias = Abc
type Sumtype = int | string
struct Foo {}
struct Test {
a Abc
b map[string]string
c []int
d EnumTest
e int
f f64
g Alias
h Foo
i fn ()
j Sumtype
k ?int
}
fn test_comptime_types() {
mut i := 0
mut a := 0
mut m := 0
mut e := 0
mut c_int := 0
mut c_float := 0
mut c_alias := 0
mut c_struct := 0
mut c_fn := 0
mut c_sum := 0
mut c_option := 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 {
a++
} $else $if f.typ is $map {
m++
} $else $if f.typ is $enum {
e++
} $else $if f.typ is $int {
c_int++
} $else $if f.typ is $float {
c_float++
} $else $if f.typ is $struct {
c_struct++
} $else $if f.typ is $function {
c_fn++
} $else $if f.typ is $sumtype {
c_sum++
} $else $if f.typ is $option {
c_option++
}
}
assert i == 1
assert a == 1
assert m == 1
assert e == 1
assert c_int == 1
assert c_float == 1
assert c_alias == 1
assert c_struct == 1
assert c_fn == 1
assert c_sum == 1
assert c_option == 1
}

View File

@ -6,7 +6,7 @@ fn encode_array[U](val []U) []string {
mut out := []string{}
$if U is int {
out << 'is int'
} $else $if U is $Struct {
} $else $if U is $struct {
out << 'is struct'
}
return out

View File

@ -6,7 +6,7 @@ fn fn_a[T](data T, depth int, nl bool) {
print('int: ${data}')
} $else $if T.typ is string {
print('string: ${data}')
} $else $if T is $Array {
} $else $if T is $array {
println('array: [')
for i, elem in data {
fn_a(elem, depth + 1, false)
@ -16,7 +16,7 @@ fn fn_a[T](data T, depth int, nl bool) {
println('')
}
print(']')
} $else $if T is $Map {
} $else $if T is $map {
println('map: {')
for key, value in data {
print('\t(key) ')
@ -25,7 +25,7 @@ fn fn_a[T](data T, depth int, nl bool) {
fn_a(value, depth, true)
}
print('}')
} $else $if T is $Struct {
} $else $if T is $struct {
println('struct ${T.name}: {')
$for field in T.fields {
print('\t(${field.name}) ')

View File

@ -4,7 +4,7 @@ fn (t Test) test[T](val T) {
$for f in T.fields {
value := val.$(f.name)
$if f.is_option {
$if f.typ is $Struct {
$if f.typ is $struct {
_ := 1
t.test(value)
} $else $if f.typ is string {
@ -15,7 +15,7 @@ fn (t Test) test[T](val T) {
_ := 4
}
} $else {
$if f.typ is $Struct {
$if f.typ is $struct {
t.test(value)
} $else $if f.typ is string {
_ := 5

View File

@ -13,7 +13,7 @@ fn (e &Encoder) encode_array[T](val []T) []T {
fn encode_struct[T](val T) []string {
e := Encoder{}
mut out := []string{}
$if T is $Struct {
$if T is $struct {
$for field in T.fields {
out << field.name
out << field.is_array.str()

View File

@ -23,7 +23,7 @@ fn (wr &Writer) write2[T](val T) {
fn encode_struct[T](val T) map[string][]string {
wr := Writer{}
mut out := map[string][]string{}
$if T is $Struct {
$if T is $struct {
$for field in T.fields {
value := val.$(field.name)
$if field.typ is ?int {

View File

@ -14,7 +14,7 @@ fn new_static_router2(route_not_found_handler ?HandlerFn) fn () {
fn test_option_fn_alias_decl_with_none() {
b := new_static_router2(none)
$if b is $Function {
$if b is $function {
assert true
} $else {
assert false
@ -23,7 +23,7 @@ fn test_option_fn_alias_decl_with_none() {
fn test_option_fn_decl_with_none() {
a := new_static_router(none)
$if a is $Function {
$if a is $function {
assert true
} $else {
assert false

View File

@ -16,16 +16,16 @@ fn test_main() {
mut out := map[string][]string{}
$for field in Foo.fields {
print('${field.name} is ')
$if field.unaliased_typ is $Int {
$if field.unaliased_typ is $int {
println('numeric')
out[field.name] << 'numeric'
} $else $if field.unaliased_typ is $Array {
} $else $if field.unaliased_typ is $array {
println('array')
out[field.name] << 'array'
} $else $if field.unaliased_typ is $Float {
} $else $if field.unaliased_typ is $float {
println('float')
out[field.name] << 'float'
} $else $if field.unaliased_typ is $Map {
} $else $if field.unaliased_typ is $map {
println('map')
out[field.name] << 'map'
} $else $if field.unaliased_typ is string || field.unaliased_typ is ?string {

View File

@ -5,18 +5,18 @@ struct Test {
fn test_main() {
hh := 1 // i64(4)
$if hh is $Int {
$if hh is $int {
println('int')
assert true
} $else $if hh !is $Int {
} $else $if hh !is $int {
println('string')
assert false
}
b := 1.2
$if b is $Int {
$if b is $int {
assert false
} $else $if b is $Float {
} $else $if b is $float {
println('float')
assert true
}

View File

@ -132,11 +132,11 @@ fn (e &Encoder) encode_value_with_level[T](val T, level int, mut wr io.Writer) !
e.encode_any(val, level, mut wr)!
} $else $if T is Encodable {
wr.write(val.json_str().bytes())!
} $else $if T is $Struct {
} $else $if T is $struct {
e.encode_struct(val, level, mut wr)!
} $else $if T is $Enum {
} $else $if T is $enum {
e.encode_any(Any(int(val)), level, mut wr)!
} $else $if T in [Null, bool, $Float, $Int] {
} $else $if T in [Null, bool, $float, $int] {
e.encode_any(val, level, mut wr)!
} $else {
// dump(val.str())
@ -245,21 +245,21 @@ fn (e &Encoder) encode_struct[U](val U, level int, mut wr io.Writer) ! {
wr.write(json2.quote_bytes)!
wr.write(val.$(field.name).format_rfc3339().bytes())!
wr.write(json2.quote_bytes)!
} $else $if field.typ in [bool, $Float, $Int] {
} $else $if field.typ in [bool, $float, $int] {
wr.write(val.$(field.name).str().bytes())!
} $else $if field.is_array {
// TODO - replace for `field.typ is $Array`
// TODO - replace for `field.typ is $array`
e.encode_array(value, level + 1, mut wr)!
} $else $if field.typ is $Array {
} $else $if field.typ is $array {
// e.encode_array(value, level + 1, mut wr)! // FIXME - error: could not infer generic type `U` in call to `encode_array`
} $else $if field.typ is $Struct {
} $else $if field.typ is $struct {
e.encode_struct(value, level + 1, mut wr)!
} $else $if field.is_enum {
// TODO - replace for `field.typ is $Enum`
// TODO - replace for `field.typ is $enum`
wr.write(int(val.$(field.name)).str().bytes())!
} $else $if field.typ is $Enum {
} $else $if field.typ is $enum {
// wr.write(int(val.$(field.name)).str().bytes())! // FIXME - error: cannot cast string to `int`, use `val.$field.name.int()` instead.
} $else $if field.typ is $Sumtype {
} $else $if field.typ is $sumtype {
// dump(val.$(field.name).str())
// dump(is_none)
sum_type_value := value.str()#[typeof(val.$(field.name)).name.len + 1..-1]
@ -319,27 +319,27 @@ fn (e &Encoder) encode_struct[U](val U, level int, mut wr io.Writer) ! {
if is_string {
e.encode_string(sum_type_value#[1..-1], mut wr)!
}
} $else $if field.typ is $Alias {
} $else $if field.typ is $alias {
$if field.unaliased_typ is string {
e.encode_string(val.$(field.name).str(), mut wr)!
} $else $if field.unaliased_typ is time.Time {
parsed_time := time.parse(val.$(field.name).str()) or { time.Time{} }
e.encode_string(parsed_time.format_rfc3339(), mut wr)!
} $else $if field.unaliased_typ in [bool, $Float, $Int] {
} $else $if field.unaliased_typ in [bool, $float, $int] {
wr.write(val.$(field.name).str().bytes())!
} $else $if field.unaliased_typ is $Array {
} $else $if field.unaliased_typ is $array {
// e.encode_array(val.$(field.name), level + 1, mut wr)! // FIXME - error: could not infer generic type `U` in call to `encode_array`
} $else $if field.unaliased_typ is $Struct {
} $else $if field.unaliased_typ is $struct {
// e.encode_struct(val.$(field.name), level + 1, mut wr)! // FIXME - error: cannot use `BoolAlias` as `StringAlias` in argument 1 to `x.json2.Encoder.encode_struct`
e.encode_struct(value, level + 1, mut wr)!
} $else $if field.unaliased_typ is $Enum {
} $else $if field.unaliased_typ is $enum {
// enum_value := val.$(field.name)
// dump(int(val.$(field.name))) // FIXME
// dump(val.$(field.name).int()) // FIXME - error: unknown method or field: `BoolAlias.int`
// dump(val.$(field.name).int()) // FIXME - error: cannot convert 'enum <anonymous>' to 'struct string'
// wr.write(val.$(field.name).int().str().bytes())! // FIXME - error: unknown method or field: `BoolAlias.int`
} $else $if field.unaliased_typ is $Sumtype {
} $else $if field.unaliased_typ is $sumtype {
} $else {
return error('the alias ${typeof(val).name} cannot be encoded')
}
@ -390,18 +390,18 @@ fn (e &Encoder) encode_array[U](val []U, level int, mut wr io.Writer) ! {
e.encode_any(u32(val[i]), level + 1, mut wr)!
} $else $if U is u64 {
e.encode_any(u64(val[i]), level + 1, mut wr)!
} $else $if U is $Array {
} $else $if U is $array {
// FIXME - error: could not infer generic type `U` in call to `encode_array`
// e.encode_array(val[i], level + 1, mut wr)!
} $else $if U is $Struct {
} $else $if U is $struct {
e.encode_struct(val[i], level + 1, mut wr)!
} $else $if U is $Sumtype {
} $else $if U is $sumtype {
$if U is Any {
e.encode_any(val[i], level + 1, mut wr)!
} $else {
// TODO
}
} $else $if U is $Enum {
} $else $if U is $enum {
e.encode_any(i64(val[i]), level + 1, mut wr)!
} $else {
return error('type ${typeof(val).name} cannot be array encoded')

View File

@ -135,7 +135,7 @@ pub fn decode[T](src string) !T {
// encode is a generic function that encodes a type into a JSON string.
pub fn encode[T](val T) string {
$if T is $Array {
$if T is $array {
$compile_error('Cannot use `json.encode` to encode array. Try `json.encode_array` instead')
}
mut sb := strings.new_builder(64)
@ -406,7 +406,7 @@ pub fn (f Any) to_time() !time.Time {
fn map_from[T](t T) map[string]Any {
mut m := map[string]Any{}
$if T is $Struct {
$if T is $struct {
$for field in T.fields {
value := t.$(field.name)