all: remove old sumtype code (#6937)
parent
aa6303f0b2
commit
a042966082
|
@ -7,7 +7,7 @@ import v.token
|
||||||
import v.table
|
import v.table
|
||||||
import v.errors
|
import v.errors
|
||||||
|
|
||||||
pub __type TypeDecl = AliasTypeDecl | FnTypeDecl | SumTypeDecl | UnionSumTypeDecl
|
pub __type TypeDecl = AliasTypeDecl | FnTypeDecl | UnionSumTypeDecl
|
||||||
|
|
||||||
pub __type Expr = AnonFn | ArrayInit | AsCast | Assoc | AtExpr | BoolLiteral | CTempVar |
|
pub __type Expr = AnonFn | ArrayInit | AsCast | Assoc | AtExpr | BoolLiteral | CTempVar |
|
||||||
CallExpr | CastExpr | ChanInit | CharLiteral | Comment | ComptimeCall | ConcatExpr | EnumVal |
|
CallExpr | CastExpr | ChanInit | CharLiteral | Comment | ComptimeCall | ConcatExpr | EnumVal |
|
||||||
|
@ -529,15 +529,14 @@ pub mut:
|
||||||
|
|
||||||
pub struct IfBranch {
|
pub struct IfBranch {
|
||||||
pub:
|
pub:
|
||||||
cond Expr
|
cond Expr
|
||||||
pos token.Position
|
pos token.Position
|
||||||
body_pos token.Position
|
body_pos token.Position
|
||||||
comments []Comment
|
comments []Comment
|
||||||
left_as_name string // `name` in `if cond is SumType as name`
|
is_mut_name bool // `if mut name is`
|
||||||
is_mut_name bool // `if mut name is`
|
|
||||||
pub mut:
|
pub mut:
|
||||||
stmts []Stmt
|
stmts []Stmt
|
||||||
smartcast bool // true when cond is `x is SumType`, set in checker.if_expr // no longer needed with union sum types TODO: remove
|
smartcast bool // true when cond is `x is SumType`, set in checker.if_expr // no longer needed with union sum types TODO: remove
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct UnsafeExpr {
|
pub struct UnsafeExpr {
|
||||||
|
@ -564,8 +563,7 @@ pub:
|
||||||
branches []MatchBranch
|
branches []MatchBranch
|
||||||
pos token.Position
|
pos token.Position
|
||||||
is_mut bool // `match mut ast_node {`
|
is_mut bool // `match mut ast_node {`
|
||||||
var_name string // `match cond as var_name {`
|
is_union_match bool // TODO: remove
|
||||||
is_union_match bool // temporary union key after match
|
|
||||||
pub mut:
|
pub mut:
|
||||||
is_expr bool // returns a value
|
is_expr bool // returns a value
|
||||||
return_type table.Type
|
return_type table.Type
|
||||||
|
@ -748,15 +746,6 @@ pub:
|
||||||
comments []Comment
|
comments []Comment
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct SumTypeDecl {
|
|
||||||
pub:
|
|
||||||
name string
|
|
||||||
is_pub bool
|
|
||||||
sub_types []table.Type
|
|
||||||
pos token.Position
|
|
||||||
comments []Comment
|
|
||||||
}
|
|
||||||
|
|
||||||
// New implementation of sum types
|
// New implementation of sum types
|
||||||
pub struct UnionSumTypeDecl {
|
pub struct UnionSumTypeDecl {
|
||||||
pub:
|
pub:
|
||||||
|
@ -1152,7 +1141,7 @@ pub fn (stmt Stmt) position() token.Position {
|
||||||
AssertStmt, AssignStmt, Block, BranchStmt, CompFor, ConstDecl, DeferStmt, EnumDecl, ExprStmt, FnDecl, ForCStmt, ForInStmt, ForStmt, GotoLabel, GotoStmt, Import, Return, StructDecl, GlobalDecl, HashStmt, InterfaceDecl, Module, SqlStmt { return stmt.pos }
|
AssertStmt, AssignStmt, Block, BranchStmt, CompFor, ConstDecl, DeferStmt, EnumDecl, ExprStmt, FnDecl, ForCStmt, ForInStmt, ForStmt, GotoLabel, GotoStmt, Import, Return, StructDecl, GlobalDecl, HashStmt, InterfaceDecl, Module, SqlStmt { return stmt.pos }
|
||||||
GoStmt { return stmt.call_expr.position() }
|
GoStmt { return stmt.call_expr.position() }
|
||||||
TypeDecl { match union stmt {
|
TypeDecl { match union stmt {
|
||||||
AliasTypeDecl, FnTypeDecl, SumTypeDecl, UnionSumTypeDecl { return stmt.pos }
|
AliasTypeDecl, FnTypeDecl, UnionSumTypeDecl { return stmt.pos }
|
||||||
} }
|
} }
|
||||||
// Please, do NOT use else{} here.
|
// Please, do NOT use else{} here.
|
||||||
// This match is exhaustive *on purpose*, to help force
|
// This match is exhaustive *on purpose*, to help force
|
||||||
|
|
|
@ -325,7 +325,7 @@ 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] || ftyp.has_flag(.optional) ||
|
[.enum_, .array, .array_fixed, .struct_, .map, .multi_return, .union_sum_type] || ftyp.has_flag(.optional) ||
|
||||||
sym.has_method('str') {
|
sym.has_method('str') {
|
||||||
return `s`
|
return `s`
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -237,7 +237,7 @@ fn (mut c Checker) check_file_in_main(file ast.File) bool {
|
||||||
if stmt.is_pub {
|
if stmt.is_pub {
|
||||||
c.warn('type alias `$stmt.name` $no_pub_in_main_warning', stmt.pos)
|
c.warn('type alias `$stmt.name` $no_pub_in_main_warning', stmt.pos)
|
||||||
}
|
}
|
||||||
} else if stmt is ast.SumTypeDecl {
|
} else if stmt is ast.UnionSumTypeDecl {
|
||||||
if stmt.is_pub {
|
if stmt.is_pub {
|
||||||
c.warn('sum type `$stmt.name` $no_pub_in_main_warning', stmt.pos)
|
c.warn('sum type `$stmt.name` $no_pub_in_main_warning', stmt.pos)
|
||||||
}
|
}
|
||||||
|
@ -311,17 +311,6 @@ pub fn (mut c Checker) type_decl(node ast.TypeDecl) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast.SumTypeDecl {
|
|
||||||
c.check_valid_pascal_case(node.name, 'sum type', node.pos)
|
|
||||||
for typ in node.sub_types {
|
|
||||||
typ_sym := c.table.get_type_symbol(typ)
|
|
||||||
if typ_sym.kind == .placeholder {
|
|
||||||
c.error("type `$typ_sym.source_name` doesn't exist", node.pos)
|
|
||||||
} else if typ_sym.kind == .interface_ {
|
|
||||||
c.error('sum type cannot hold an interface', node.pos)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ast.UnionSumTypeDecl {
|
ast.UnionSumTypeDecl {
|
||||||
c.check_valid_pascal_case(node.name, 'sum type', node.pos)
|
c.check_valid_pascal_case(node.name, 'sum type', node.pos)
|
||||||
for typ in node.sub_types {
|
for typ in node.sub_types {
|
||||||
|
@ -456,7 +445,7 @@ pub fn (mut c Checker) struct_init(mut struct_init ast.StructInit) table.Type {
|
||||||
c.error('unknown type', struct_init.pos)
|
c.error('unknown type', struct_init.pos)
|
||||||
}
|
}
|
||||||
type_sym := c.table.get_type_symbol(struct_init.typ)
|
type_sym := c.table.get_type_symbol(struct_init.typ)
|
||||||
if type_sym.kind == .sum_type && struct_init.fields.len == 1 {
|
if type_sym.kind == .union_sum_type && struct_init.fields.len == 1 {
|
||||||
sexpr := struct_init.fields[0].expr.str()
|
sexpr := struct_init.fields[0].expr.str()
|
||||||
c.error('cast to sum type using `${type_sym.source_name}($sexpr)` not `$type_sym.source_name{$sexpr}`',
|
c.error('cast to sum type using `${type_sym.source_name}($sexpr)` not `$type_sym.source_name{$sexpr}`',
|
||||||
struct_init.pos)
|
struct_init.pos)
|
||||||
|
@ -804,12 +793,11 @@ pub fn (mut c Checker) infix_expr(mut infix_expr ast.InfixExpr) table.Type {
|
||||||
c.error('$infix_expr.op.str(): type `$typ_sym.source_name` does not exist',
|
c.error('$infix_expr.op.str(): type `$typ_sym.source_name` does not exist',
|
||||||
type_expr.pos)
|
type_expr.pos)
|
||||||
}
|
}
|
||||||
if left.kind !in [.interface_, .sum_type, .union_sum_type] {
|
if left.kind !in [.interface_, .union_sum_type] {
|
||||||
c.error('`$infix_expr.op.str()` can only be used with interfaces and sum types',
|
c.error('`$infix_expr.op.str()` can only be used with interfaces and sum types',
|
||||||
infix_expr.pos)
|
infix_expr.pos)
|
||||||
} else if left.kind == .union_sum_type {
|
} else if mut left.info is table.UnionSumType {
|
||||||
info := left.info as table.UnionSumType
|
if type_expr.typ !in left.info.variants {
|
||||||
if type_expr.typ !in info.variants {
|
|
||||||
c.error('`$left.source_name` has no variant `$right.source_name`',
|
c.error('`$left.source_name` has no variant `$right.source_name`',
|
||||||
infix_expr.pos)
|
infix_expr.pos)
|
||||||
}
|
}
|
||||||
|
@ -1110,7 +1098,7 @@ pub fn (mut c Checker) call_method(mut call_expr ast.CallExpr) table.Type {
|
||||||
c.error('optional type cannot be called directly', call_expr.left.position())
|
c.error('optional type cannot be called directly', call_expr.left.position())
|
||||||
return table.void_type
|
return table.void_type
|
||||||
}
|
}
|
||||||
if left_type_sym.kind == .sum_type && method_name == 'type_name' {
|
if left_type_sym.kind == .union_sum_type && method_name == 'type_name' {
|
||||||
return table.string_type
|
return table.string_type
|
||||||
}
|
}
|
||||||
// TODO: remove this for actual methods, use only for compiler magic
|
// TODO: remove this for actual methods, use only for compiler magic
|
||||||
|
@ -2294,7 +2282,7 @@ pub fn (mut c Checker) array_init(mut array_init ast.ArrayInit) table.Type {
|
||||||
if array_init.has_default {
|
if array_init.has_default {
|
||||||
c.expr(array_init.default_expr)
|
c.expr(array_init.default_expr)
|
||||||
}
|
}
|
||||||
if sym.kind in [.sum_type, .union_sum_type] {
|
if sym.kind == .union_sum_type {
|
||||||
if array_init.has_len && !array_init.has_default {
|
if array_init.has_len && !array_init.has_default {
|
||||||
c.error('cannot initalize sum type array without default value', array_init.elem_type_pos)
|
c.error('cannot initalize sum type array without default value', array_init.elem_type_pos)
|
||||||
}
|
}
|
||||||
|
@ -2799,7 +2787,7 @@ pub fn (mut c Checker) expr(node ast.Expr) table.Type {
|
||||||
node.expr_type = c.expr(node.expr)
|
node.expr_type = c.expr(node.expr)
|
||||||
expr_type_sym := c.table.get_type_symbol(node.expr_type)
|
expr_type_sym := c.table.get_type_symbol(node.expr_type)
|
||||||
type_sym := c.table.get_type_symbol(node.typ)
|
type_sym := c.table.get_type_symbol(node.typ)
|
||||||
if expr_type_sym.kind == .sum_type || expr_type_sym.kind == .union_sum_type {
|
if expr_type_sym.kind == .union_sum_type {
|
||||||
if type_sym.kind == .placeholder {
|
if type_sym.kind == .placeholder {
|
||||||
// Unknown type used in the right part of `as`
|
// Unknown type used in the right part of `as`
|
||||||
c.error('unknown type `$type_sym.source_name`', node.pos)
|
c.error('unknown type `$type_sym.source_name`', node.pos)
|
||||||
|
@ -2811,7 +2799,7 @@ pub fn (mut c Checker) expr(node ast.Expr) table.Type {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
mut s := 'cannot cast non-sum type `$expr_type_sym.source_name` using `as`'
|
mut s := 'cannot cast non-sum type `$expr_type_sym.source_name` using `as`'
|
||||||
if type_sym.kind == .sum_type || expr_type_sym.kind == .union_sum_type {
|
if type_sym.kind == .union_sum_type {
|
||||||
s += ' - use e.g. `${type_sym.source_name}(some_expr)` instead.'
|
s += ' - use e.g. `${type_sym.source_name}(some_expr)` instead.'
|
||||||
}
|
}
|
||||||
c.error(s, node.pos)
|
c.error(s, node.pos)
|
||||||
|
@ -3066,7 +3054,7 @@ pub fn (mut c Checker) cast_expr(mut node ast.CastExpr) table.Type {
|
||||||
c.error('can not cast type `byte` to string, use `${node.expr.str()}.str()` instead.',
|
c.error('can not cast type `byte` to string, use `${node.expr.str()}.str()` instead.',
|
||||||
node.pos)
|
node.pos)
|
||||||
}
|
}
|
||||||
if to_type_sym.kind == .sum_type || to_type_sym.kind == .union_sum_type {
|
if to_type_sym.kind == .union_sum_type {
|
||||||
if node.expr_type in [table.any_int_type, table.any_flt_type] {
|
if node.expr_type in [table.any_int_type, table.any_flt_type] {
|
||||||
node.expr_type = c.promote_num(node.expr_type, if node.expr_type == table.any_int_type { table.int_type } else { table.f64_type })
|
node.expr_type = c.promote_num(node.expr_type, if node.expr_type == table.any_int_type { table.int_type } else { table.f64_type })
|
||||||
}
|
}
|
||||||
|
@ -3377,7 +3365,7 @@ pub fn (mut c Checker) match_expr(mut node ast.MatchExpr) table.Type {
|
||||||
c.error('compiler bug: match 0 cond type', node.pos)
|
c.error('compiler bug: match 0 cond type', node.pos)
|
||||||
}
|
}
|
||||||
cond_type_sym := c.table.get_type_symbol(cond_type)
|
cond_type_sym := c.table.get_type_symbol(cond_type)
|
||||||
if cond_type_sym.kind !in [.sum_type, .interface_, .union_sum_type] {
|
if cond_type_sym.kind !in [.interface_, .union_sum_type] {
|
||||||
node.is_sum_type = false
|
node.is_sum_type = false
|
||||||
}
|
}
|
||||||
c.match_exprs(mut node, cond_type_sym)
|
c.match_exprs(mut node, cond_type_sym)
|
||||||
|
@ -3599,8 +3587,8 @@ fn (mut c Checker) match_exprs(mut node ast.MatchExpr, type_sym table.TypeSymbol
|
||||||
// smartcast either if the value is immutable or if the mut argument is explicitly given
|
// smartcast either if the value is immutable or if the mut argument is explicitly given
|
||||||
if (!is_mut || node.is_mut) && !is_already_casted {
|
if (!is_mut || node.is_mut) && !is_already_casted {
|
||||||
sum_type_casts << expr_type
|
sum_type_casts << expr_type
|
||||||
scope.register(node.var_name, ast.Var{
|
scope.register(node.cond.name, ast.Var{
|
||||||
name: node.var_name
|
name: node.cond.name
|
||||||
typ: node.cond_type
|
typ: node.cond_type
|
||||||
pos: node.cond.pos
|
pos: node.cond.pos
|
||||||
is_used: true
|
is_used: true
|
||||||
|
@ -3621,15 +3609,6 @@ fn (mut c Checker) match_exprs(mut node ast.MatchExpr, type_sym table.TypeSymbol
|
||||||
mut is_exhaustive := true
|
mut is_exhaustive := true
|
||||||
mut unhandled := []string{}
|
mut unhandled := []string{}
|
||||||
match union mut type_sym.info {
|
match union mut type_sym.info {
|
||||||
table.SumType {
|
|
||||||
for v in type_sym.info.variants {
|
|
||||||
v_str := c.table.type_to_str(v)
|
|
||||||
if v_str !in branch_exprs {
|
|
||||||
is_exhaustive = false
|
|
||||||
unhandled << '`$v_str`'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
table.UnionSumType {
|
table.UnionSumType {
|
||||||
for v in type_sym.info.variants {
|
for v in type_sym.info.variants {
|
||||||
v_str := c.table.type_to_str(v)
|
v_str := c.table.type_to_str(v)
|
||||||
|
@ -3833,7 +3812,7 @@ pub fn (mut c Checker) if_expr(mut node ast.IfExpr) table.Type {
|
||||||
is_variable := if mut infix.left is ast.Ident { infix.left.kind == .variable } else { true }
|
is_variable := if mut infix.left is ast.Ident { infix.left.kind == .variable } else { true }
|
||||||
// Register shadow variable or `as` variable with actual type
|
// Register shadow variable or `as` variable with actual type
|
||||||
if is_variable {
|
if is_variable {
|
||||||
if left_sym.kind in [.sum_type, .interface_, .union_sum_type] {
|
if left_sym.kind in [.interface_, .union_sum_type] {
|
||||||
mut is_mut := false
|
mut is_mut := false
|
||||||
mut scope := c.file.scope.innermost(branch.body_pos.pos)
|
mut scope := c.file.scope.innermost(branch.body_pos.pos)
|
||||||
if mut infix.left is ast.Ident {
|
if mut infix.left is ast.Ident {
|
||||||
|
@ -3842,18 +3821,30 @@ pub fn (mut c Checker) if_expr(mut node ast.IfExpr) table.Type {
|
||||||
is_mut = v.is_mut
|
is_mut = v.is_mut
|
||||||
sum_type_casts << v.sum_type_casts
|
sum_type_casts << v.sum_type_casts
|
||||||
}
|
}
|
||||||
// smartcast either if the value is immutable or if the mut argument is explicitly given
|
if left_sym.kind == .union_sum_type {
|
||||||
if (!is_mut || branch.is_mut_name) &&
|
// smartcast either if the value is immutable or if the mut argument is explicitly given
|
||||||
left_sym.kind == .union_sum_type {
|
if !is_mut || branch.is_mut_name {
|
||||||
sum_type_casts << right_expr.typ
|
sum_type_casts << right_expr.typ
|
||||||
scope.register(branch.left_as_name, ast.Var{
|
scope.register(infix.left.name, ast.Var{
|
||||||
name: branch.left_as_name
|
name: infix.left.name
|
||||||
typ: infix.left_type
|
typ: infix.left_type
|
||||||
|
sum_type_casts: sum_type_casts
|
||||||
|
pos: infix.left.pos
|
||||||
|
is_used: true
|
||||||
|
is_mut: is_mut
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else if left_sym.kind == .interface_ {
|
||||||
|
scope.register(infix.left.name, ast.Var{
|
||||||
|
name: infix.left.name
|
||||||
|
typ: right_expr.typ.to_ptr()
|
||||||
sum_type_casts: sum_type_casts
|
sum_type_casts: sum_type_casts
|
||||||
pos: infix.left.pos
|
pos: infix.left.pos
|
||||||
is_used: true
|
is_used: true
|
||||||
is_mut: is_mut
|
is_mut: is_mut
|
||||||
})
|
})
|
||||||
|
// TODO: remove that later @danieldaeschle
|
||||||
|
node.branches[i].smartcast = true
|
||||||
}
|
}
|
||||||
} else if mut infix.left is ast.SelectorExpr {
|
} else if mut infix.left is ast.SelectorExpr {
|
||||||
mut sum_type_casts := []table.Type{}
|
mut sum_type_casts := []table.Type{}
|
||||||
|
@ -3881,16 +3872,6 @@ pub fn (mut c Checker) if_expr(mut node ast.IfExpr) table.Type {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if left_sym.kind != .union_sum_type && branch.left_as_name.len > 0 {
|
|
||||||
scope.register(branch.left_as_name, ast.Var{
|
|
||||||
name: branch.left_as_name
|
|
||||||
typ: right_expr.typ.to_ptr()
|
|
||||||
pos: infix.left.position()
|
|
||||||
is_used: true
|
|
||||||
is_mut: is_mut
|
|
||||||
})
|
|
||||||
node.branches[i].smartcast = true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4068,7 +4049,7 @@ fn (mut c Checker) comp_if_branch(cond ast.Expr, pos token.Position) bool {
|
||||||
return false // TODO
|
return false // TODO
|
||||||
} else if cond.name in valid_comp_if_other {
|
} else if cond.name in valid_comp_if_other {
|
||||||
// TODO: This should probably be moved
|
// TODO: This should probably be moved
|
||||||
match cond.name as name {
|
match cond.name {
|
||||||
'js' { return c.pref.backend != .js }
|
'js' { return c.pref.backend != .js }
|
||||||
'debug' { return !c.pref.is_debug }
|
'debug' { return !c.pref.is_debug }
|
||||||
'test' { return !c.pref.is_test }
|
'test' { return !c.pref.is_test }
|
||||||
|
@ -4525,7 +4506,7 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) {
|
||||||
if sym.kind == .interface_ {
|
if sym.kind == .interface_ {
|
||||||
c.error('interfaces cannot be used as method receiver', node.receiver_pos)
|
c.error('interfaces cannot be used as method receiver', node.receiver_pos)
|
||||||
}
|
}
|
||||||
if sym.kind == .sum_type && node.name == 'type_name' {
|
if sym.kind == .union_sum_type && node.name == 'type_name' {
|
||||||
c.error('method overrides built-in sum type method', node.pos)
|
c.error('method overrides built-in sum type method', node.pos)
|
||||||
}
|
}
|
||||||
// if sym.has_method(node.name) {
|
// if sym.has_method(node.name) {
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
vlib/v/checker/tests/is_type_invalid.vv:14:2: error: cannot use type `byte` as type `IoS`
|
vlib/v/checker/tests/is_type_invalid.vv:14:12: error: `IoS` has no variant `byte`
|
||||||
12 |
|
12 |
|
||||||
13 | fn main() {
|
13 | fn main() {
|
||||||
14 | if IoS(1) is byte {
|
14 | if IoS(1) is byte {
|
||||||
| ~~~~~~~~~~~~~~~~~
|
| ~~
|
||||||
15 | println('not cool')
|
15 | println('not cool')
|
||||||
16 | }
|
16 | }
|
||||||
vlib/v/checker/tests/is_type_invalid.vv:18:2: error: `Cat` doesn't implement method `speak`
|
vlib/v/checker/tests/is_type_invalid.vv:18:2: error: `Cat` doesn't implement method `speak`
|
||||||
|
@ -11,4 +11,4 @@ vlib/v/checker/tests/is_type_invalid.vv:18:2: error: `Cat` doesn't implement met
|
||||||
18 | if a is Cat {
|
18 | if a is Cat {
|
||||||
| ~~~~~~~~~~~
|
| ~~~~~~~~~~~
|
||||||
19 | println('not cool either')
|
19 | println('not cool either')
|
||||||
20 | }
|
20 | }
|
|
@ -1,4 +1,4 @@
|
||||||
vlib/v/checker/tests/match_invalid_type.vv:5:3: error: cannot match `byte` with `IoS` condition
|
vlib/v/checker/tests/match_invalid_type.vv:5:3: error: `IoS` has no variant `byte`
|
||||||
3 | fn sum() {
|
3 | fn sum() {
|
||||||
4 | match IoS(1) {
|
4 | match IoS(1) {
|
||||||
5 | byte {
|
5 | byte {
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
vlib/v/checker/tests/match_sumtype_multiple_types.vv:25:13: error: type `Charlie` has no field or method `char`
|
vlib/v/checker/tests/match_sumtype_multiple_types.vv:26:13: error: type `Charlie` has no field or method `char`
|
||||||
23 | match NATOAlphabet(a) as l {
|
24 | match l {
|
||||||
24 | Alfa, Charlie {
|
25 | Alfa, Charlie {
|
||||||
25 | assert l.char == `a`
|
26 | assert l.char == `a`
|
||||||
| ~~~~
|
| ~~~~
|
||||||
26 | assert l.letter() == 'a'
|
27 | assert l.letter() == 'a'
|
||||||
27 | }
|
28 | }
|
||||||
vlib/v/checker/tests/match_sumtype_multiple_types.vv:26:13: error: unknown method: `Charlie.letter`
|
vlib/v/checker/tests/match_sumtype_multiple_types.vv:27:13: error: unknown method: `Charlie.letter`
|
||||||
24 | Alfa, Charlie {
|
25 | Alfa, Charlie {
|
||||||
25 | assert l.char == `a`
|
26 | assert l.char == `a`
|
||||||
26 | assert l.letter() == 'a'
|
27 | assert l.letter() == 'a'
|
||||||
| ~~~~~~~~~
|
| ~~~~~~~~~
|
||||||
27 | }
|
28 | }
|
||||||
28 | Bravo {
|
29 | Bravo {
|
|
@ -20,7 +20,8 @@ type NATOAlphabet = Alfa | Bravo | Charlie
|
||||||
|
|
||||||
fn method_not_exists() {
|
fn method_not_exists() {
|
||||||
a := Alfa{}
|
a := Alfa{}
|
||||||
match NATOAlphabet(a) as l {
|
l := NATOAlphabet(a)
|
||||||
|
match l {
|
||||||
Alfa, Charlie {
|
Alfa, Charlie {
|
||||||
assert l.char == `a`
|
assert l.char == `a`
|
||||||
assert l.letter() == 'a'
|
assert l.letter() == 'a'
|
||||||
|
|
|
@ -96,7 +96,7 @@ pub fn (d Doc) stmt_name(stmt ast.Stmt) string {
|
||||||
match union stmt {
|
match union stmt {
|
||||||
ast.FnDecl, ast.StructDecl, ast.EnumDecl, ast.InterfaceDecl { return stmt.name }
|
ast.FnDecl, ast.StructDecl, ast.EnumDecl, ast.InterfaceDecl { return stmt.name }
|
||||||
ast.TypeDecl { match union stmt {
|
ast.TypeDecl { match union stmt {
|
||||||
ast.SumTypeDecl, ast.FnTypeDecl, ast.AliasTypeDecl, ast.UnionSumTypeDecl { return stmt.name }
|
ast.FnTypeDecl, ast.AliasTypeDecl, ast.UnionSumTypeDecl { return stmt.name }
|
||||||
} }
|
} }
|
||||||
ast.ConstDecl { return '' } // leave it blank
|
ast.ConstDecl { return '' } // leave it blank
|
||||||
else { return '' }
|
else { return '' }
|
||||||
|
|
|
@ -454,7 +454,7 @@ pub fn (mut f Fmt) stmt(node ast.Stmt) {
|
||||||
f.write('sql ')
|
f.write('sql ')
|
||||||
f.expr(node.db_expr)
|
f.expr(node.db_expr)
|
||||||
f.writeln(' {')
|
f.writeln(' {')
|
||||||
match node.kind as k {
|
match node.kind {
|
||||||
.insert {
|
.insert {
|
||||||
f.writeln('\tinsert $node.object_var_name into ${util.strip_mod_name(node.table_name)}')
|
f.writeln('\tinsert $node.object_var_name into ${util.strip_mod_name(node.table_name)}')
|
||||||
}
|
}
|
||||||
|
@ -544,26 +544,6 @@ pub fn (mut f Fmt) type_decl(node ast.TypeDecl) {
|
||||||
}
|
}
|
||||||
comments << node.comments
|
comments << node.comments
|
||||||
}
|
}
|
||||||
ast.SumTypeDecl {
|
|
||||||
if node.is_pub {
|
|
||||||
f.write('pub ')
|
|
||||||
}
|
|
||||||
f.write('type $node.name = ')
|
|
||||||
mut sum_type_names := []string{}
|
|
||||||
for t in node.sub_types {
|
|
||||||
sum_type_names << f.table.type_to_str(t)
|
|
||||||
}
|
|
||||||
sum_type_names.sort()
|
|
||||||
for i, name in sum_type_names {
|
|
||||||
f.write(name)
|
|
||||||
if i < sum_type_names.len - 1 {
|
|
||||||
f.write(' | ')
|
|
||||||
}
|
|
||||||
f.wrap_long_line(2, true)
|
|
||||||
}
|
|
||||||
// f.write(sum_type_names.join(' | '))
|
|
||||||
comments << node.comments
|
|
||||||
}
|
|
||||||
ast.UnionSumTypeDecl {
|
ast.UnionSumTypeDecl {
|
||||||
if node.is_pub {
|
if node.is_pub {
|
||||||
f.write('pub ')
|
f.write('pub ')
|
||||||
|
@ -1412,15 +1392,6 @@ pub fn (mut f Fmt) if_expr(it ast.IfExpr) {
|
||||||
(it.is_expr || f.is_assign)
|
(it.is_expr || f.is_assign)
|
||||||
f.single_line_if = single_line
|
f.single_line_if = single_line
|
||||||
for i, branch in it.branches {
|
for i, branch in it.branches {
|
||||||
// Check `sum is T` smartcast
|
|
||||||
mut smartcast_as := false
|
|
||||||
if branch.cond is ast.InfixExpr {
|
|
||||||
if branch.cond.op == .key_is {
|
|
||||||
// left_as_name is either empty, branch.cond.left.str() or the `as` name
|
|
||||||
smartcast_as = branch.left_as_name.len > 0 &&
|
|
||||||
branch.cond.left.str() != branch.left_as_name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
// first `if`
|
// first `if`
|
||||||
f.comments(branch.comments, {})
|
f.comments(branch.comments, {})
|
||||||
|
@ -1440,9 +1411,6 @@ pub fn (mut f Fmt) if_expr(it ast.IfExpr) {
|
||||||
f.write('mut ')
|
f.write('mut ')
|
||||||
}
|
}
|
||||||
f.expr(branch.cond)
|
f.expr(branch.cond)
|
||||||
if smartcast_as {
|
|
||||||
f.write(' as $branch.left_as_name')
|
|
||||||
}
|
|
||||||
f.write(' ')
|
f.write(' ')
|
||||||
}
|
}
|
||||||
f.write('{')
|
f.write('{')
|
||||||
|
@ -1560,7 +1528,6 @@ pub fn (mut f Fmt) call_expr(node ast.CallExpr) {
|
||||||
|
|
||||||
pub fn (mut f Fmt) match_expr(it ast.MatchExpr) {
|
pub fn (mut f Fmt) match_expr(it ast.MatchExpr) {
|
||||||
f.write('match ')
|
f.write('match ')
|
||||||
// TODO: temporary, remove again
|
|
||||||
if it.is_union_match {
|
if it.is_union_match {
|
||||||
f.write('union ')
|
f.write('union ')
|
||||||
}
|
}
|
||||||
|
@ -1570,12 +1537,6 @@ pub fn (mut f Fmt) match_expr(it ast.MatchExpr) {
|
||||||
f.expr(it.cond)
|
f.expr(it.cond)
|
||||||
if it.cond is ast.Ident {
|
if it.cond is ast.Ident {
|
||||||
f.it_name = it.cond.name
|
f.it_name = it.cond.name
|
||||||
} else if it.cond is ast.SelectorExpr {
|
|
||||||
// `x.y as z`
|
|
||||||
// if ident.name != it.var_name && it.var_name != '' {
|
|
||||||
}
|
|
||||||
if it.var_name != '' && f.it_name != it.var_name {
|
|
||||||
f.write(' as $it.var_name')
|
|
||||||
}
|
}
|
||||||
f.writeln(' {')
|
f.writeln(' {')
|
||||||
f.indent++
|
f.indent++
|
||||||
|
|
|
@ -4,7 +4,7 @@ struct IfExpr {
|
||||||
struct MatchExpr {
|
struct MatchExpr {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Expr = IfExpr | MatchExpr
|
__type Expr = IfExpr | MatchExpr
|
||||||
|
|
||||||
fn sum_types(a []Expr) {
|
fn sum_types(a []Expr) {
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ fn handle_users(users []User) {
|
||||||
fn (u &User) foo(u2 &User) {
|
fn (u &User) foo(u2 &User) {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Expr = IfExpr | IntegerLiteral
|
__type Expr = IfExpr | IntegerLiteral
|
||||||
|
|
||||||
fn exprs(e []Expr) {
|
fn exprs(e []Expr) {
|
||||||
println(e.len)
|
println(e.len)
|
||||||
|
|
|
@ -6,17 +6,15 @@ mut:
|
||||||
struct S2 {
|
struct S2 {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Sum = S1 | S2
|
__type Sum = S1 | S2
|
||||||
|
|
||||||
fn f(sum Sum) {
|
fn f(sum Sum) {
|
||||||
if mut sum is S1 {
|
if mut sum is S1 {
|
||||||
sum.i++
|
sum.i++
|
||||||
}
|
}
|
||||||
if sum is S1 as s1 {
|
if sum is S1 {
|
||||||
}
|
}
|
||||||
a := [sum]
|
a := [sum]
|
||||||
if a[0] is S2 {
|
if a[0] is S2 {
|
||||||
}
|
}
|
||||||
if a[0] is S2 as s2 {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
// Sumtype
|
// Sumtype
|
||||||
type FooBar = Bar | Foo
|
__type FooBar = Bar | Foo
|
||||||
|
|
||||||
pub type PublicBar = Bar | Foo | FooBar
|
pub __type PublicBar = Bar | Foo | FooBar
|
||||||
|
|
||||||
type Uint = byte | u16 | u32 | u64 // This should stay on the same line
|
__type Uint = byte | u16 | u32 | u64
|
||||||
|
|
||||||
type Float = f32 | f64
|
__type Float = f32 | f64
|
||||||
|
|
||||||
// Alias type
|
// Alias type
|
||||||
type MyInt = int
|
type MyInt = int
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
type Uint = u16 | u64
|
type Uint = u16 | u64
|
||||||
| u32
|
| u32
|
||||||
| byte // This should stay on the same line
|
| byte
|
||||||
type
|
type
|
||||||
Float =
|
Float =
|
||||||
f32 |
|
f32 |
|
||||||
|
|
|
@ -73,9 +73,6 @@ fn (mut g Gen) gen_str_for_type_with_styp(typ table.Type, styp string) string {
|
||||||
table.MultiReturn {
|
table.MultiReturn {
|
||||||
g.gen_str_for_multi_return(sym.info, styp, str_fn_name)
|
g.gen_str_for_multi_return(sym.info, styp, str_fn_name)
|
||||||
}
|
}
|
||||||
table.SumType {
|
|
||||||
g.gen_str_for_sum_type(sym.info, styp, str_fn_name)
|
|
||||||
}
|
|
||||||
table.UnionSumType {
|
table.UnionSumType {
|
||||||
g.gen_str_for_union_sum_type(sym.info, styp, str_fn_name)
|
g.gen_str_for_union_sum_type(sym.info, styp, str_fn_name)
|
||||||
}
|
}
|
||||||
|
@ -441,7 +438,7 @@ fn struct_auto_str_func(sym table.TypeSymbol, field_type table.Type, fn_name str
|
||||||
return '${fn_name}($obj)'
|
return '${fn_name}($obj)'
|
||||||
}
|
}
|
||||||
return 'indent_${fn_name}($obj, indent_count + 1)'
|
return 'indent_${fn_name}($obj, indent_count + 1)'
|
||||||
} else if sym.kind in [.array, .array_fixed, .map, .sum_type] {
|
} else if sym.kind in [.array, .array_fixed, .map, .union_sum_type] {
|
||||||
if has_custom_str {
|
if has_custom_str {
|
||||||
return '${fn_name}(it->${c_name(field_name)})'
|
return '${fn_name}(it->${c_name(field_name)})'
|
||||||
}
|
}
|
||||||
|
@ -485,50 +482,6 @@ fn (mut g Gen) gen_str_for_enum(info table.Enum, styp string, str_fn_name string
|
||||||
g.auto_str_funcs.writeln('}')
|
g.auto_str_funcs.writeln('}')
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut g Gen) gen_str_for_sum_type(info table.SumType, styp string, str_fn_name string) {
|
|
||||||
mut gen_fn_names := map[string]string{}
|
|
||||||
for typ in info.variants {
|
|
||||||
sym := g.table.get_type_symbol(typ)
|
|
||||||
if !sym.has_method('str') {
|
|
||||||
field_styp := g.typ(typ)
|
|
||||||
field_fn_name := g.gen_str_for_type_with_styp(typ, field_styp)
|
|
||||||
gen_fn_names[field_styp] = field_fn_name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// _str() functions should have a single argument, the indenting ones take 2:
|
|
||||||
g.type_definitions.writeln('string ${str_fn_name}($styp x); // auto')
|
|
||||||
g.auto_str_funcs.writeln('string ${str_fn_name}($styp x) { return indent_${str_fn_name}(x, 0); }')
|
|
||||||
g.type_definitions.writeln('string indent_${str_fn_name}($styp x, int indent_count); // auto')
|
|
||||||
g.auto_str_funcs.writeln('string indent_${str_fn_name}($styp x, int indent_count) {')
|
|
||||||
mut clean_sum_type_v_type_name := styp.replace('__', '.')
|
|
||||||
if styp.ends_with('*') {
|
|
||||||
clean_sum_type_v_type_name = '&' + clean_sum_type_v_type_name.replace('*', '')
|
|
||||||
}
|
|
||||||
clean_sum_type_v_type_name = util.strip_main_name(clean_sum_type_v_type_name)
|
|
||||||
g.auto_str_funcs.writeln('\tswitch(x.typ) {')
|
|
||||||
for typ in info.variants {
|
|
||||||
mut value_fmt := '%.*s\\000'
|
|
||||||
if typ == table.string_type {
|
|
||||||
value_fmt = "\'$value_fmt\'"
|
|
||||||
}
|
|
||||||
typ_str := g.typ(typ)
|
|
||||||
mut func_name := if typ_str in gen_fn_names { gen_fn_names[typ_str] } else { g.gen_str_for_type_with_styp(typ,
|
|
||||||
typ_str) }
|
|
||||||
sym := g.table.get_type_symbol(typ)
|
|
||||||
if sym.kind == .struct_ {
|
|
||||||
func_name = 'indent_$func_name'
|
|
||||||
}
|
|
||||||
g.auto_str_funcs.write('\t\tcase $typ: return _STR("${clean_sum_type_v_type_name}($value_fmt)", 2, ${func_name}(*($typ_str*)x._object')
|
|
||||||
if sym.kind == .struct_ {
|
|
||||||
g.auto_str_funcs.write(', indent_count')
|
|
||||||
}
|
|
||||||
g.auto_str_funcs.writeln('));')
|
|
||||||
}
|
|
||||||
g.auto_str_funcs.writeln('\t\tdefault: return tos_lit("unknown sum type value");')
|
|
||||||
g.auto_str_funcs.writeln('\t}')
|
|
||||||
g.auto_str_funcs.writeln('}')
|
|
||||||
}
|
|
||||||
|
|
||||||
fn (mut g Gen) gen_str_for_union_sum_type(info table.UnionSumType, styp string, str_fn_name string) {
|
fn (mut g Gen) gen_str_for_union_sum_type(info table.UnionSumType, styp string, str_fn_name string) {
|
||||||
mut gen_fn_names := map[string]string{}
|
mut gen_fn_names := map[string]string{}
|
||||||
for typ in info.variants {
|
for typ in info.variants {
|
||||||
|
|
|
@ -370,22 +370,6 @@ pub fn (mut g Gen) finish() {
|
||||||
pub fn (mut g Gen) write_typeof_functions() {
|
pub fn (mut g Gen) write_typeof_functions() {
|
||||||
g.writeln('')
|
g.writeln('')
|
||||||
g.writeln('// >> typeof() support for sum types')
|
g.writeln('// >> typeof() support for sum types')
|
||||||
for typ in g.table.types {
|
|
||||||
if typ.kind == .sum_type {
|
|
||||||
sum_info := typ.info as table.SumType
|
|
||||||
tidx := g.table.find_type_idx(typ.name)
|
|
||||||
g.writeln('char * v_typeof_sumtype_${tidx}(int sidx) { /* $typ.name */ ')
|
|
||||||
g.writeln(' switch(sidx) {')
|
|
||||||
g.writeln(' case $tidx: return "${util.strip_main_name(typ.name)}";')
|
|
||||||
for v in sum_info.variants {
|
|
||||||
subtype := g.table.get_type_symbol(v)
|
|
||||||
g.writeln(' case $v: return "${util.strip_main_name(subtype.name)}";')
|
|
||||||
}
|
|
||||||
g.writeln(' default: return "unknown ${util.strip_main_name(typ.name)}";')
|
|
||||||
g.writeln(' }')
|
|
||||||
g.writeln('}')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for typ in g.table.types {
|
for typ in g.table.types {
|
||||||
if typ.kind == .union_sum_type {
|
if typ.kind == .union_sum_type {
|
||||||
sum_info := typ.info as table.UnionSumType
|
sum_info := typ.info as table.UnionSumType
|
||||||
|
@ -2293,7 +2277,7 @@ fn (mut g Gen) expr(node ast.Expr) {
|
||||||
g.expr(node.arg)
|
g.expr(node.arg)
|
||||||
}
|
}
|
||||||
g.write(')')
|
g.write(')')
|
||||||
} else if sym.kind in [.sum_type, .union_sum_type] {
|
} else if sym.kind == .union_sum_type {
|
||||||
g.expr_with_cast(node.expr, node.expr_type, node.typ)
|
g.expr_with_cast(node.expr, node.expr_type, node.typ)
|
||||||
} else if sym.kind == .struct_ && !node.typ.is_ptr() && !(sym.info as table.Struct).is_typedef {
|
} else if sym.kind == .struct_ && !node.typ.is_ptr() && !(sym.info as table.Struct).is_typedef {
|
||||||
styp := g.typ(node.typ)
|
styp := g.typ(node.typ)
|
||||||
|
@ -2649,14 +2633,7 @@ fn (mut g Gen) type_name(type_ table.Type) {
|
||||||
|
|
||||||
fn (mut g Gen) typeof_expr(node ast.TypeOf) {
|
fn (mut g Gen) typeof_expr(node ast.TypeOf) {
|
||||||
sym := g.table.get_type_symbol(node.expr_type)
|
sym := g.table.get_type_symbol(node.expr_type)
|
||||||
if sym.kind == .sum_type {
|
if sym.kind == .union_sum_type {
|
||||||
// When encountering a .sum_type, typeof() should be done at runtime,
|
|
||||||
// because the subtype of the expression may change:
|
|
||||||
sum_type_idx := node.expr_type.idx()
|
|
||||||
g.write('tos3( /* $sym.name */ v_typeof_sumtype_${sum_type_idx}( (')
|
|
||||||
g.expr(node.expr)
|
|
||||||
g.write(').typ ))')
|
|
||||||
} else if sym.kind == .union_sum_type {
|
|
||||||
// When encountering a .sum_type, typeof() should be done at runtime,
|
// When encountering a .sum_type, typeof() should be done at runtime,
|
||||||
// because the subtype of the expression may change:
|
// because the subtype of the expression may change:
|
||||||
sum_type_idx := node.expr_type.idx()
|
sum_type_idx := node.expr_type.idx()
|
||||||
|
@ -3098,7 +3075,7 @@ fn (mut g Gen) match_expr_sumtype(node ast.MatchExpr, is_expr bool, cond_var str
|
||||||
}
|
}
|
||||||
g.write(cond_var)
|
g.write(cond_var)
|
||||||
// branch_sym := g.table.get_type_symbol(branch.typ)
|
// branch_sym := g.table.get_type_symbol(branch.typ)
|
||||||
if sym.kind in [.sum_type, .union_sum_type] {
|
if sym.kind == .union_sum_type {
|
||||||
dot_or_ptr := if node.cond_type.is_ptr() { '->' } else { '.' }
|
dot_or_ptr := if node.cond_type.is_ptr() { '->' } else { '.' }
|
||||||
g.write(dot_or_ptr)
|
g.write(dot_or_ptr)
|
||||||
g.write('typ == ')
|
g.write('typ == ')
|
||||||
|
@ -3113,25 +3090,6 @@ fn (mut g Gen) match_expr_sumtype(node ast.MatchExpr, is_expr bool, cond_var str
|
||||||
g.writeln(') {')
|
g.writeln(') {')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// g.writeln('/* M sum_type=$node.is_sum_type is_expr=$node.is_expr exp_type=${g.typ(node.expected_type)}*/')
|
|
||||||
if sym.kind != .union_sum_type && !branch.is_else && !node.is_expr {
|
|
||||||
// Use the nodes in the expr to generate `it` variable.
|
|
||||||
type_expr := branch.exprs[sumtype_index]
|
|
||||||
if type_expr !is ast.Type {
|
|
||||||
verror('match sum type')
|
|
||||||
}
|
|
||||||
it_type := g.typ((type_expr as ast.Type).typ)
|
|
||||||
// g.writeln('$it_type* it = ($it_type*)${tmp}.obj; // ST it')
|
|
||||||
g.write('\t$it_type* it = ($it_type*)')
|
|
||||||
g.write(cond_var)
|
|
||||||
dot_or_ptr := if node.cond_type.is_ptr() { '->' } else { '.' }
|
|
||||||
g.write(dot_or_ptr)
|
|
||||||
g.writeln('_object; // ST it')
|
|
||||||
if node.var_name.len > 0 {
|
|
||||||
// for now we just copy it
|
|
||||||
g.writeln('\t$it_type* $node.var_name = it;')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
g.stmts(branch.stmts)
|
g.stmts(branch.stmts)
|
||||||
if g.inside_ternary == 0 {
|
if g.inside_ternary == 0 {
|
||||||
g.write('}')
|
g.write('}')
|
||||||
|
@ -3449,13 +3407,6 @@ fn (mut g Gen) match_sumtype_has_no_struct_and_contains(node ast.Ident) bool {
|
||||||
if expr is ast.Ident && node.name == (expr as ast.Ident).name {
|
if expr is ast.Ident && node.name == (expr as ast.Ident).name {
|
||||||
info := g.match_sumtype_syms[i].info
|
info := g.match_sumtype_syms[i].info
|
||||||
match union info {
|
match union info {
|
||||||
table.SumType {
|
|
||||||
for typ in info.variants {
|
|
||||||
if g.table.get_type_symbol(typ).kind == .struct_ {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
table.UnionSumType {
|
table.UnionSumType {
|
||||||
for typ in info.variants {
|
for typ in info.variants {
|
||||||
if g.table.get_type_symbol(typ).kind == .struct_ {
|
if g.table.get_type_symbol(typ).kind == .struct_ {
|
||||||
|
@ -3591,18 +3542,20 @@ fn (mut g Gen) if_expr(node ast.IfExpr) {
|
||||||
}
|
}
|
||||||
if branch.smartcast && branch.stmts.len > 0 {
|
if branch.smartcast && branch.stmts.len > 0 {
|
||||||
infix := branch.cond as ast.InfixExpr
|
infix := branch.cond as ast.InfixExpr
|
||||||
right_type := infix.right as ast.Type
|
if mut infix.left is ast.Ident {
|
||||||
left_type := infix.left_type
|
right_type := infix.right as ast.Type
|
||||||
it_type := g.typ(right_type.typ)
|
left_type := infix.left_type
|
||||||
g.write('\t$it_type* _sc_tmp_$branch.pos.pos = ($it_type*)')
|
it_type := g.typ(right_type.typ)
|
||||||
g.expr(infix.left)
|
g.write('\t$it_type* _sc_tmp_$branch.pos.pos = ($it_type*)')
|
||||||
if left_type.is_ptr() {
|
g.expr(infix.left)
|
||||||
g.write('->')
|
if left_type.is_ptr() {
|
||||||
} else {
|
g.write('->')
|
||||||
g.write('.')
|
} else {
|
||||||
|
g.write('.')
|
||||||
|
}
|
||||||
|
g.writeln('_object;')
|
||||||
|
g.writeln('\t$it_type* $infix.left.name = _sc_tmp_$branch.pos.pos;')
|
||||||
}
|
}
|
||||||
g.writeln('_object;')
|
|
||||||
g.writeln('\t$it_type* $branch.left_as_name = _sc_tmp_$branch.pos.pos;')
|
|
||||||
}
|
}
|
||||||
if needs_tmp_var {
|
if needs_tmp_var {
|
||||||
g.stmts_with_tmp_var(branch.stmts, tmp)
|
g.stmts_with_tmp_var(branch.stmts, tmp)
|
||||||
|
@ -4640,19 +4593,7 @@ fn (mut g Gen) write_types(types []table.TypeSymbol) {
|
||||||
g.type_definitions.writeln('};\n')
|
g.type_definitions.writeln('};\n')
|
||||||
}
|
}
|
||||||
table.Alias {
|
table.Alias {
|
||||||
// table.Alias, table.SumType { TODO
|
// table.Alias { TODO
|
||||||
}
|
|
||||||
table.SumType {
|
|
||||||
g.type_definitions.writeln('')
|
|
||||||
g.type_definitions.writeln('// Sum type $name = ')
|
|
||||||
for sv in typ.info.variants {
|
|
||||||
g.type_definitions.writeln('// | ${sv:4d} = ${g.typ(sv):-20s}')
|
|
||||||
}
|
|
||||||
g.type_definitions.writeln('typedef struct {')
|
|
||||||
g.type_definitions.writeln(' void* _object;')
|
|
||||||
g.type_definitions.writeln(' int typ;')
|
|
||||||
g.type_definitions.writeln('} $name;')
|
|
||||||
g.type_definitions.writeln('')
|
|
||||||
}
|
}
|
||||||
table.UnionSumType {
|
table.UnionSumType {
|
||||||
g.typedefs.writeln('typedef struct $name $name;')
|
g.typedefs.writeln('typedef struct $name $name;')
|
||||||
|
@ -4781,7 +4722,7 @@ fn (mut g Gen) gen_expr_to_string(expr ast.Expr, etype table.Type) ?bool {
|
||||||
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] {
|
[.array, .array_fixed, .map, .struct_, .multi_return, .union_sum_type] {
|
||||||
is_p := typ.is_ptr()
|
is_p := typ.is_ptr()
|
||||||
val_type := if is_p { typ.deref() } else { typ }
|
val_type := if is_p { typ.deref() } else { typ }
|
||||||
str_fn_name := g.gen_str_for_type(val_type)
|
str_fn_name := g.gen_str_for_type(val_type)
|
||||||
|
@ -5449,7 +5390,7 @@ fn (mut g Gen) type_default(typ_ table.Type) string {
|
||||||
else {}
|
else {}
|
||||||
}
|
}
|
||||||
return match sym.kind {
|
return match sym.kind {
|
||||||
.interface_, .union_sum_type, .sum_type, .array_fixed, .multi_return { '{0}' }
|
.interface_, .union_sum_type, .array_fixed, .multi_return { '{0}' }
|
||||||
.alias { g.type_default((sym.info as table.Alias).parent_type) }
|
.alias { g.type_default((sym.info as table.Alias).parent_type) }
|
||||||
else { '0' }
|
else { '0' }
|
||||||
}
|
}
|
||||||
|
@ -5604,23 +5545,7 @@ fn (mut g Gen) as_cast(node ast.AsCast) {
|
||||||
// g.insert_before('
|
// g.insert_before('
|
||||||
styp := g.typ(node.typ)
|
styp := g.typ(node.typ)
|
||||||
expr_type_sym := g.table.get_type_symbol(node.expr_type)
|
expr_type_sym := g.table.get_type_symbol(node.expr_type)
|
||||||
if expr_type_sym.kind == .sum_type {
|
if expr_type_sym.kind == .union_sum_type {
|
||||||
/*
|
|
||||||
g.write('*($styp*)')
|
|
||||||
g.expr(node.expr)
|
|
||||||
g.write('.obj')
|
|
||||||
*/
|
|
||||||
dot := if node.expr_type.is_ptr() { '->' } else { '.' }
|
|
||||||
g.write('/* as */ ($styp*)__as_cast((')
|
|
||||||
g.expr(node.expr)
|
|
||||||
g.write(')')
|
|
||||||
g.write(dot)
|
|
||||||
g.write('_object, (')
|
|
||||||
g.expr(node.expr)
|
|
||||||
g.write(')')
|
|
||||||
g.write(dot)
|
|
||||||
g.write('typ, /*expected:*/$node.typ)')
|
|
||||||
} else if expr_type_sym.kind == .union_sum_type {
|
|
||||||
dot := if node.expr_type.is_ptr() { '->' } else { '.' }
|
dot := if node.expr_type.is_ptr() { '->' } else { '.' }
|
||||||
g.write('/* as */ *($styp*)__as_cast((')
|
g.write('/* as */ *($styp*)__as_cast((')
|
||||||
g.expr(node.expr)
|
g.expr(node.expr)
|
||||||
|
@ -5652,7 +5577,7 @@ fn (mut g Gen) is_expr(node ast.InfixExpr) {
|
||||||
sub_sym := g.table.get_type_symbol(sub_type.typ)
|
sub_sym := g.table.get_type_symbol(sub_type.typ)
|
||||||
g.write('_${c_name(sym.name)}_${c_name(sub_sym.name)}_index')
|
g.write('_${c_name(sym.name)}_${c_name(sub_sym.name)}_index')
|
||||||
return
|
return
|
||||||
} else if sym.kind in [.sum_type, .union_sum_type] {
|
} else if sym.kind == .union_sum_type {
|
||||||
g.write('typ $eq ')
|
g.write('typ $eq ')
|
||||||
}
|
}
|
||||||
g.expr(node.right)
|
g.expr(node.right)
|
||||||
|
@ -5719,7 +5644,7 @@ fn (g &Gen) type_to_fmt(typ table.Type) string {
|
||||||
return '%g\\000' // g removes trailing zeros unlike %f
|
return '%g\\000' // g removes trailing zeros unlike %f
|
||||||
} else if sym.kind == .u64 {
|
} else if sym.kind == .u64 {
|
||||||
return '%lld\\000'
|
return '%lld\\000'
|
||||||
} else if sym.kind == .sum_type {
|
} else if sym.kind == .union_sum_type {
|
||||||
return '%.*s\\000'
|
return '%.*s\\000'
|
||||||
}
|
}
|
||||||
return '%d\\000'
|
return '%d\\000'
|
||||||
|
|
|
@ -366,8 +366,8 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
|
||||||
else {}
|
else {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if left_sym.kind == .sum_type && node.name == 'type_name' {
|
if left_sym.kind == .union_sum_type && node.name == 'type_name' {
|
||||||
g.write('tos3( /* $left_sym.name */ v_typeof_sumtype_${node.receiver_type}( (')
|
g.write('tos3( /* $left_sym.name */ v_typeof_unionsumtype_${node.receiver_type}( (')
|
||||||
g.expr(node.left)
|
g.expr(node.left)
|
||||||
g.write(').typ ))')
|
g.write(').typ ))')
|
||||||
return
|
return
|
||||||
|
@ -887,7 +887,7 @@ fn (mut g Gen) ref_or_deref_arg(arg ast.CallArg, expected_type table.Type) {
|
||||||
}
|
}
|
||||||
arg_typ_sym := g.table.get_type_symbol(arg.typ)
|
arg_typ_sym := g.table.get_type_symbol(arg.typ)
|
||||||
expected_deref_type := if expected_type.is_ptr() { expected_type.deref() } else { expected_type }
|
expected_deref_type := if expected_type.is_ptr() { expected_type.deref() } else { expected_type }
|
||||||
is_sum_type := g.table.get_type_symbol(expected_deref_type).kind == .sum_type
|
is_sum_type := g.table.get_type_symbol(expected_deref_type).kind == .union_sum_type
|
||||||
if !((arg_typ_sym.kind == .function) || is_sum_type) {
|
if !((arg_typ_sym.kind == .function) || is_sum_type) {
|
||||||
g.write('(voidptr)&/*qq*/')
|
g.write('(voidptr)&/*qq*/')
|
||||||
}
|
}
|
||||||
|
|
|
@ -257,10 +257,6 @@ pub fn (mut g JsGen) typ(t table.Type) string {
|
||||||
joined := types.join(', ')
|
joined := types.join(', ')
|
||||||
styp = '[$joined]'
|
styp = '[$joined]'
|
||||||
}
|
}
|
||||||
.sum_type {
|
|
||||||
// TODO: Implement sumtypes
|
|
||||||
styp = 'sym_type'
|
|
||||||
}
|
|
||||||
.union_sum_type {
|
.union_sum_type {
|
||||||
// TODO: Implement sumtypes
|
// TODO: Implement sumtypes
|
||||||
styp = 'union_sym_type'
|
styp = 'union_sym_type'
|
||||||
|
@ -1504,7 +1500,7 @@ fn (mut g JsGen) gen_struct_init(it ast.StructInit) {
|
||||||
|
|
||||||
fn (mut g JsGen) gen_typeof_expr(it ast.TypeOf) {
|
fn (mut g JsGen) gen_typeof_expr(it ast.TypeOf) {
|
||||||
sym := g.table.get_type_symbol(it.expr_type)
|
sym := g.table.get_type_symbol(it.expr_type)
|
||||||
if sym.kind == .sum_type {
|
if sym.kind == .union_sum_type {
|
||||||
// TODO: JS sumtypes not implemented yet
|
// TODO: JS sumtypes not implemented yet
|
||||||
} else if sym.kind == .array_fixed {
|
} else if sym.kind == .array_fixed {
|
||||||
fixed_info := sym.info as table.ArrayFixed
|
fixed_info := sym.info as table.ArrayFixed
|
||||||
|
|
|
@ -567,7 +567,7 @@ 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, .struct_, .map, .placeholder, .sum_type] && !typ.is_ptr() {
|
if sym.kind !in [.array, .struct_, .map, .placeholder, .union_sum_type] && !typ.is_ptr() {
|
||||||
p.error_with_pos('mutable arguments are only allowed for arrays, maps, and structs\n' +
|
p.error_with_pos('mutable arguments are only allowed for arrays, maps, and structs\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)
|
||||||
|
|
|
@ -6,7 +6,6 @@ module parser
|
||||||
import v.ast
|
import v.ast
|
||||||
import v.table
|
import v.table
|
||||||
import v.token
|
import v.token
|
||||||
import strings
|
|
||||||
|
|
||||||
fn (mut p Parser) if_expr(is_comptime bool) ast.IfExpr {
|
fn (mut p Parser) if_expr(is_comptime bool) ast.IfExpr {
|
||||||
was_inside_if_expr := p.inside_if_expr
|
was_inside_if_expr := p.inside_if_expr
|
||||||
|
@ -121,22 +120,9 @@ fn (mut p Parser) if_expr(is_comptime bool) ast.IfExpr {
|
||||||
cond = p.expr(0)
|
cond = p.expr(0)
|
||||||
}
|
}
|
||||||
comments << p.eat_comments()
|
comments << p.eat_comments()
|
||||||
mut left_as_name := ''
|
|
||||||
if mut cond is ast.InfixExpr {
|
if mut cond is ast.InfixExpr {
|
||||||
// if sum is T
|
// if sum is T
|
||||||
is_is_cast := cond.op == .key_is
|
is_is_cast := cond.op == .key_is
|
||||||
is_ident := cond.left is ast.Ident
|
|
||||||
left_as_name = if is_comptime {
|
|
||||||
''
|
|
||||||
} else if is_is_cast && p.tok.kind == .key_as {
|
|
||||||
p.next()
|
|
||||||
p.check_name()
|
|
||||||
} else if is_ident {
|
|
||||||
ident := cond.left as ast.Ident
|
|
||||||
ident.name
|
|
||||||
} else {
|
|
||||||
''
|
|
||||||
}
|
|
||||||
if !is_is_cast && is_mut_name {
|
if !is_is_cast && is_mut_name {
|
||||||
p.error_with_pos('remove unnecessary `mut`', mut_pos)
|
p.error_with_pos('remove unnecessary `mut`', mut_pos)
|
||||||
}
|
}
|
||||||
|
@ -156,7 +142,6 @@ fn (mut p Parser) if_expr(is_comptime bool) ast.IfExpr {
|
||||||
pos: start_pos.extend(end_pos)
|
pos: start_pos.extend(end_pos)
|
||||||
body_pos: body_pos.extend(p.prev_tok.position())
|
body_pos: body_pos.extend(p.prev_tok.position())
|
||||||
comments: comments
|
comments: comments
|
||||||
left_as_name: left_as_name
|
|
||||||
is_mut_name: is_mut_name
|
is_mut_name: is_mut_name
|
||||||
}
|
}
|
||||||
comments = p.eat_comments()
|
comments = p.eat_comments()
|
||||||
|
@ -195,14 +180,8 @@ fn (mut p Parser) match_expr() ast.MatchExpr {
|
||||||
if is_mut {
|
if is_mut {
|
||||||
p.next()
|
p.next()
|
||||||
}
|
}
|
||||||
cond_pos := p.tok.position()
|
|
||||||
cond := p.expr(0)
|
cond := p.expr(0)
|
||||||
p.inside_match = false
|
p.inside_match = false
|
||||||
mut var_name := ''
|
|
||||||
if p.tok.kind == .key_as {
|
|
||||||
p.next()
|
|
||||||
var_name = p.check_name()
|
|
||||||
}
|
|
||||||
no_lcbr := p.tok.kind != .lcbr
|
no_lcbr := p.tok.kind != .lcbr
|
||||||
if !no_lcbr {
|
if !no_lcbr {
|
||||||
p.check(.lcbr)
|
p.check(.lcbr)
|
||||||
|
@ -222,20 +201,6 @@ 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[0].is_capital())) {
|
(p.peek_tok.kind == .dot && p.peek_tok2.lit[0].is_capital())) {
|
||||||
if var_name.len == 0 {
|
|
||||||
match union cond {
|
|
||||||
ast.Ident {
|
|
||||||
// shadow match cond variable
|
|
||||||
var_name = cond.name
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// ast.SelectorExpr {
|
|
||||||
// p.error('expecting `as` (eg. `match user.attribute as user_attr`) when matching struct fields')
|
|
||||||
// }
|
|
||||||
// p.error('only variables can be used in sum types matches')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mut types := []table.Type{}
|
mut types := []table.Type{}
|
||||||
for {
|
for {
|
||||||
// Sum type match
|
// Sum type match
|
||||||
|
@ -251,52 +216,6 @@ fn (mut p Parser) match_expr() ast.MatchExpr {
|
||||||
}
|
}
|
||||||
p.check(.comma)
|
p.check(.comma)
|
||||||
}
|
}
|
||||||
if !is_union_match {
|
|
||||||
mut it_typ := table.void_type
|
|
||||||
if types.len == 1 {
|
|
||||||
it_typ = types[0]
|
|
||||||
} else {
|
|
||||||
// there is more than one types, so we must create a type aggregate
|
|
||||||
mut agg_name := strings.new_builder(20)
|
|
||||||
agg_name.write('(')
|
|
||||||
for i, typ in types {
|
|
||||||
if i > 0 {
|
|
||||||
agg_name.write(' | ')
|
|
||||||
}
|
|
||||||
type_str := p.table.type_to_str(typ)
|
|
||||||
agg_name.write(p.prepend_mod(type_str))
|
|
||||||
}
|
|
||||||
agg_name.write(')')
|
|
||||||
name := agg_name.str()
|
|
||||||
it_typ = p.table.register_type_symbol(table.TypeSymbol{
|
|
||||||
name: name
|
|
||||||
source_name: name
|
|
||||||
kind: .aggregate
|
|
||||||
mod: p.mod
|
|
||||||
info: table.Aggregate{
|
|
||||||
types: types
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
p.scope.register('it', ast.Var{
|
|
||||||
name: 'it'
|
|
||||||
typ: it_typ.to_ptr()
|
|
||||||
pos: cond_pos
|
|
||||||
is_used: true
|
|
||||||
is_mut: is_mut
|
|
||||||
})
|
|
||||||
if var_name.len > 0 {
|
|
||||||
// Register shadow variable or `as` variable with actual type
|
|
||||||
p.scope.register(var_name, ast.Var{
|
|
||||||
name: var_name
|
|
||||||
typ: it_typ.to_ptr()
|
|
||||||
pos: cond_pos
|
|
||||||
is_used: true
|
|
||||||
is_changed: true // TODO mut unchanged warning hack, remove
|
|
||||||
is_mut: is_mut
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
is_sum_type = true
|
is_sum_type = true
|
||||||
} else {
|
} else {
|
||||||
// Expression match
|
// Expression match
|
||||||
|
@ -366,10 +285,9 @@ fn (mut p Parser) match_expr() ast.MatchExpr {
|
||||||
branches: branches
|
branches: branches
|
||||||
cond: cond
|
cond: cond
|
||||||
is_sum_type: is_sum_type
|
is_sum_type: is_sum_type
|
||||||
is_union_match: is_union_match
|
|
||||||
pos: pos
|
pos: pos
|
||||||
is_mut: is_mut
|
is_mut: is_mut
|
||||||
var_name: var_name
|
is_union_match: is_union_match
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1999,17 +1999,17 @@ fn (mut p Parser) type_decl() ast.TypeDecl {
|
||||||
}
|
}
|
||||||
prepend_mod_name := p.prepend_mod(name)
|
prepend_mod_name := p.prepend_mod(name)
|
||||||
p.table.register_type_symbol(table.TypeSymbol{
|
p.table.register_type_symbol(table.TypeSymbol{
|
||||||
kind: .sum_type
|
kind: .union_sum_type
|
||||||
name: prepend_mod_name
|
name: prepend_mod_name
|
||||||
source_name: prepend_mod_name
|
source_name: prepend_mod_name
|
||||||
mod: p.mod
|
mod: p.mod
|
||||||
info: table.SumType{
|
info: table.UnionSumType{
|
||||||
variants: sum_variants
|
variants: sum_variants
|
||||||
}
|
}
|
||||||
is_public: is_pub
|
is_public: is_pub
|
||||||
})
|
})
|
||||||
comments = p.eat_lineend_comments()
|
comments = p.eat_lineend_comments()
|
||||||
return ast.SumTypeDecl{
|
return ast.UnionSumTypeDecl{
|
||||||
name: name
|
name: name
|
||||||
is_pub: is_pub
|
is_pub: is_pub
|
||||||
sub_types: sum_variants
|
sub_types: sum_variants
|
||||||
|
|
|
@ -722,17 +722,7 @@ pub fn (mut table Table) register_fn_gen_type(fn_name string, typ Type) {
|
||||||
// so until fixed at least show v (not C) error `x(variant) = y(SumType*)`
|
// so until fixed at least show v (not C) error `x(variant) = y(SumType*)`
|
||||||
pub fn (table &Table) sumtype_has_variant(parent Type, variant Type) bool {
|
pub fn (table &Table) sumtype_has_variant(parent Type, variant Type) bool {
|
||||||
parent_sym := table.get_type_symbol(parent)
|
parent_sym := table.get_type_symbol(parent)
|
||||||
if parent_sym.kind == .sum_type {
|
if parent_sym.kind == .union_sum_type {
|
||||||
parent_info := parent_sym.info as SumType
|
|
||||||
for v in parent_info.variants {
|
|
||||||
if v.idx() == variant.idx() {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if table.sumtype_has_variant(v, variant) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if parent_sym.kind == .union_sum_type {
|
|
||||||
parent_info := parent_sym.info as UnionSumType
|
parent_info := parent_sym.info as UnionSumType
|
||||||
for v in parent_info.variants {
|
for v in parent_info.variants {
|
||||||
if v.idx() == variant.idx() {
|
if v.idx() == variant.idx() {
|
||||||
|
|
|
@ -16,7 +16,7 @@ import strings
|
||||||
pub type Type = int
|
pub type Type = int
|
||||||
|
|
||||||
pub __type TypeInfo = Aggregate | Alias | Array | ArrayFixed | Chan | Enum | FnType |
|
pub __type TypeInfo = Aggregate | Alias | Array | ArrayFixed | Chan | Enum | FnType |
|
||||||
GenericStructInst | Interface | Map | MultiReturn | Struct | SumType | UnionSumType
|
GenericStructInst | Interface | Map | MultiReturn | Struct | UnionSumType
|
||||||
|
|
||||||
pub enum Language {
|
pub enum Language {
|
||||||
v
|
v
|
||||||
|
@ -404,7 +404,6 @@ pub enum Kind {
|
||||||
struct_
|
struct_
|
||||||
generic_struct_inst
|
generic_struct_inst
|
||||||
multi_return
|
multi_return
|
||||||
sum_type
|
|
||||||
union_sum_type
|
union_sum_type
|
||||||
alias
|
alias
|
||||||
enum_
|
enum_
|
||||||
|
@ -719,7 +718,6 @@ pub fn (k Kind) str() string {
|
||||||
.map { 'map' }
|
.map { 'map' }
|
||||||
.chan { 'chan' }
|
.chan { 'chan' }
|
||||||
.multi_return { 'multi_return' }
|
.multi_return { 'multi_return' }
|
||||||
.sum_type { 'sum_type' }
|
|
||||||
.union_sum_type { 'union_sum_type' }
|
.union_sum_type { 'union_sum_type' }
|
||||||
.alias { 'alias' }
|
.alias { 'alias' }
|
||||||
.enum_ { 'enum' }
|
.enum_ { 'enum' }
|
||||||
|
@ -843,11 +841,6 @@ pub mut:
|
||||||
value_type Type
|
value_type Type
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct SumType {
|
|
||||||
pub:
|
|
||||||
variants []Type
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct UnionSumType {
|
pub struct UnionSumType {
|
||||||
pub:
|
pub:
|
||||||
variants []Type
|
variants []Type
|
||||||
|
|
|
@ -18,12 +18,12 @@ fn test_if_smartcast() {
|
||||||
|
|
||||||
fn test_mutable() {
|
fn test_mutable() {
|
||||||
mut x := Alphabet(Abc{'original'})
|
mut x := Alphabet(Abc{'original'})
|
||||||
if x is Abc {
|
if mut x is Abc {
|
||||||
assert x.val == 'original'
|
assert x.val == 'original'
|
||||||
x.val = 'changed'
|
x.val = 'changed'
|
||||||
assert x.val == 'changed'
|
assert x.val == 'changed'
|
||||||
}
|
}
|
||||||
if x is Abc {
|
if mut x is Abc {
|
||||||
assert x.val == 'changed'
|
assert x.val == 'changed'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,11 +38,9 @@ fn test_nested_if_smartcast() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_as_cast() {
|
struct MutContainer {
|
||||||
x := Alphabet(Abc{'test'})
|
mut:
|
||||||
if x is Abc as test {
|
abc Alphabet
|
||||||
assert test.val == 'test'
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Container {
|
struct Container {
|
||||||
|
@ -50,29 +48,24 @@ struct Container {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_mutable_with_struct() {
|
fn test_mutable_with_struct() {
|
||||||
mut c := Container{Abc{'original'}}
|
mut c := MutContainer{Abc{'original'}}
|
||||||
if c.abc is Abc as abc {
|
if mut c.abc is Abc {
|
||||||
assert abc.val == 'original'
|
assert c.abc.val == 'original'
|
||||||
mut mabc := abc
|
c.abc.val = 'xyz'
|
||||||
// NB: since `abc` is a pointer,
|
assert c.abc.val == 'xyz'
|
||||||
// `mabc` points to the same data:
|
|
||||||
assert mabc.val == 'original'
|
|
||||||
// Modifying `mabc`, modifies the data of abc too.
|
|
||||||
mabc.val = 'xyz'
|
|
||||||
assert abc.val == 'xyz'
|
|
||||||
}
|
}
|
||||||
if c.abc is Abc as another {
|
if mut c.abc is Abc {
|
||||||
// NB: in this second smart cast, `another` is
|
// NB: in this second smart cast, `another` is
|
||||||
// the same wrapped value, that was changed in
|
// the same wrapped value, that was changed in
|
||||||
// the first smart cast:
|
// the first smart cast:
|
||||||
assert another.val == 'xyz'
|
assert c.abc.val == 'xyz'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_as_cast_with_struct() {
|
fn test_as_cast_with_struct() {
|
||||||
x := Container{Abc{'test'}}
|
x := Container{Abc{'test'}}
|
||||||
if x.abc is Abc as test {
|
if x.abc is Abc {
|
||||||
assert test.val == 'test'
|
assert x.abc.val == 'test'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,19 +106,19 @@ fn test_mutability() {
|
||||||
}
|
}
|
||||||
mut cell := Cell{}
|
mut cell := Cell{}
|
||||||
cell = cell_str
|
cell = cell_str
|
||||||
if cell is CellStr {
|
if mut cell is CellStr {
|
||||||
println('$cell.str')
|
println('$cell.str')
|
||||||
}
|
}
|
||||||
cell = cell_itg
|
cell = cell_itg
|
||||||
if cell is CellInt {
|
if mut cell is CellInt {
|
||||||
println('$cell.itg')
|
println('$cell.itg')
|
||||||
}
|
}
|
||||||
cell = cell_flt
|
cell = cell_flt
|
||||||
if cell is CellFloat {
|
if mut cell is CellFloat {
|
||||||
println('$cell.flt')
|
println('$cell.flt')
|
||||||
}
|
}
|
||||||
cell = cell_u32
|
cell = cell_u32
|
||||||
if cell is CellU32 {
|
if mut cell is CellU32 {
|
||||||
println('$cell.u')
|
println('$cell.u')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ const (
|
||||||
fn test_shadow() {
|
fn test_shadow() {
|
||||||
mut animal := Animal{}
|
mut animal := Animal{}
|
||||||
animal = cat
|
animal = cat
|
||||||
match animal {
|
match mut animal {
|
||||||
Cat {
|
Cat {
|
||||||
assert animal.name == cat.name
|
assert animal.name == cat.name
|
||||||
}
|
}
|
||||||
|
@ -24,9 +24,9 @@ fn test_shadow() {
|
||||||
fn test_as() {
|
fn test_as() {
|
||||||
mut animal := Animal{}
|
mut animal := Animal{}
|
||||||
animal = dog
|
animal = dog
|
||||||
match animal as animal_kind {
|
match mut animal {
|
||||||
Dog {
|
Dog {
|
||||||
assert animal_kind.name == dog.name
|
assert animal.name == dog.name
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
assert false
|
assert false
|
||||||
|
|
|
@ -205,7 +205,8 @@ type NATOAlphabet = Alfa | Bravo | Charlie
|
||||||
|
|
||||||
fn test_match_sumtype_multiple_types() {
|
fn test_match_sumtype_multiple_types() {
|
||||||
a := Alfa{}
|
a := Alfa{}
|
||||||
match NATOAlphabet(a) as l {
|
l := NATOAlphabet(a)
|
||||||
|
match l {
|
||||||
Alfa, Bravo {
|
Alfa, Bravo {
|
||||||
assert l.char == `a`
|
assert l.char == `a`
|
||||||
// TODO make methods work
|
// TODO make methods work
|
||||||
|
@ -216,7 +217,7 @@ fn test_match_sumtype_multiple_types() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// test one branch
|
// test one branch
|
||||||
match NATOAlphabet(a) as l {
|
match l {
|
||||||
Alfa, Bravo, Charlie {
|
Alfa, Bravo, Charlie {
|
||||||
assert l.char == `a`
|
assert l.char == `a`
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,8 +28,7 @@ fn handle(e Expr) string {
|
||||||
}
|
}
|
||||||
match e {
|
match e {
|
||||||
IntegerLiteral {
|
IntegerLiteral {
|
||||||
assert it.val == '12'
|
assert e.val == '12'
|
||||||
// assert e.val == '12' // TODO
|
|
||||||
return 'int'
|
return 'int'
|
||||||
}
|
}
|
||||||
IfExpr {
|
IfExpr {
|
||||||
|
@ -56,10 +55,10 @@ fn test_assignment_and_push() {
|
||||||
arr1 << expr
|
arr1 << expr
|
||||||
match arr1[0] {
|
match arr1[0] {
|
||||||
IntegerLiteral {
|
IntegerLiteral {
|
||||||
arr1 << it
|
arr1 << arr1[0]
|
||||||
// should ref/dereference on assignent be made automatic?
|
// should ref/dereference on assignent be made automatic?
|
||||||
// currently it is done for return stmt and fn args
|
// currently it is done for return stmt and fn args
|
||||||
expr1 = *it
|
expr1 = arr1[0]
|
||||||
}
|
}
|
||||||
else {}
|
else {}
|
||||||
}
|
}
|
||||||
|
@ -96,7 +95,7 @@ fn test_converting_down() {
|
||||||
mut res := []Sub2{cap: out.len}
|
mut res := []Sub2{cap: out.len}
|
||||||
for d in out {
|
for d in out {
|
||||||
match d {
|
match d {
|
||||||
Sub2 { res << it }
|
Sub2 { res << d }
|
||||||
else {}
|
else {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -107,26 +106,6 @@ fn test_converting_down() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_nested_sumtype() {
|
fn test_nested_sumtype() {
|
||||||
mut a := Node{}
|
|
||||||
mut b := Node{}
|
|
||||||
a = StructDecl{pos: 1}
|
|
||||||
b = IfExpr{pos: 1}
|
|
||||||
match a {
|
|
||||||
StructDecl {
|
|
||||||
assert true
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
assert false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// TODO: not working
|
|
||||||
// assert b is IfExpr
|
|
||||||
if b is IfExpr {
|
|
||||||
assert true
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
assert false
|
|
||||||
}
|
|
||||||
c := Node(Expr(IfExpr{pos:1}))
|
c := Node(Expr(IfExpr{pos:1}))
|
||||||
if c is Expr {
|
if c is Expr {
|
||||||
if c is IfExpr {
|
if c is IfExpr {
|
||||||
|
@ -202,8 +181,8 @@ fn is_gt_nested(val string, dst Number) bool {
|
||||||
return val.int() > dst
|
return val.int() > dst
|
||||||
}
|
}
|
||||||
// this branch should never been hit
|
// this branch should never been hit
|
||||||
else {
|
else {
|
||||||
return val.int() < dst
|
return val.int() < dst
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -213,8 +192,8 @@ fn is_gt_nested(val string, dst Number) bool {
|
||||||
return dst < val.f64()
|
return dst < val.f64()
|
||||||
}
|
}
|
||||||
// this branch should never been hit
|
// this branch should never been hit
|
||||||
else {
|
else {
|
||||||
return dst > val.f64()
|
return dst > val.f64()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -255,7 +234,7 @@ fn test_sum_type_match() {
|
||||||
assert is_gt_simple('3', 2)
|
assert is_gt_simple('3', 2)
|
||||||
assert !is_gt_simple('3', 5)
|
assert !is_gt_simple('3', 5)
|
||||||
assert is_gt_simple('3', 1.2)
|
assert is_gt_simple('3', 1.2)
|
||||||
assert !is_gt_simple('3', 3.5)
|
assert !is_gt_simple('3', 3.5)
|
||||||
assert is_gt_nested('3', 2)
|
assert is_gt_nested('3', 2)
|
||||||
assert !is_gt_nested('3', 5)
|
assert !is_gt_nested('3', 5)
|
||||||
assert is_gt_nested('3', 1.2)
|
assert is_gt_nested('3', 1.2)
|
||||||
|
|
|
@ -51,8 +51,8 @@ type MySumType = int | f32 | FooBar
|
||||||
|
|
||||||
pub fn (ms MySumType) str() string {
|
pub fn (ms MySumType) str() string {
|
||||||
match ms {
|
match ms {
|
||||||
int { return it.str() }
|
int { return ms.str() }
|
||||||
f32 { return it.str() }
|
f32 { return ms.str() }
|
||||||
//FooBar { return it.x.str() }
|
//FooBar { return it.x.str() }
|
||||||
else { return 'unknown: ' + typeof(ms) }
|
else { return 'unknown: ' + typeof(ms) }
|
||||||
}
|
}
|
||||||
|
@ -144,7 +144,7 @@ fn test_generic_type() {
|
||||||
assert type_name([v]) == '[]int'
|
assert type_name([v]) == '[]int'
|
||||||
assert type_name([[v]]) == '[][]int'
|
assert type_name([[v]]) == '[][]int'
|
||||||
assert type_name(FooBar{}) == 'FooBar'
|
assert type_name(FooBar{}) == 'FooBar'
|
||||||
|
|
||||||
assert array_item_type([v]) == 'int'
|
assert array_item_type([v]) == 'int'
|
||||||
assert array_item_type([[v]]) == '[]int'
|
assert array_item_type([[v]]) == '[]int'
|
||||||
//assert array_item_type([&v]) == '&int'
|
//assert array_item_type([&v]) == '&int'
|
||||||
|
|
Loading…
Reference in New Issue