all: remove old sumtype code (#6937)
parent
aa6303f0b2
commit
a042966082
|
@ -7,7 +7,7 @@ import v.token
|
|||
import v.table
|
||||
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 |
|
||||
CallExpr | CastExpr | ChanInit | CharLiteral | Comment | ComptimeCall | ConcatExpr | EnumVal |
|
||||
|
@ -529,15 +529,14 @@ pub mut:
|
|||
|
||||
pub struct IfBranch {
|
||||
pub:
|
||||
cond Expr
|
||||
pos token.Position
|
||||
body_pos token.Position
|
||||
comments []Comment
|
||||
left_as_name string // `name` in `if cond is SumType as name`
|
||||
is_mut_name bool // `if mut name is`
|
||||
cond Expr
|
||||
pos token.Position
|
||||
body_pos token.Position
|
||||
comments []Comment
|
||||
is_mut_name bool // `if mut name is`
|
||||
pub mut:
|
||||
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
|
||||
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
|
||||
}
|
||||
|
||||
pub struct UnsafeExpr {
|
||||
|
@ -564,8 +563,7 @@ pub:
|
|||
branches []MatchBranch
|
||||
pos token.Position
|
||||
is_mut bool // `match mut ast_node {`
|
||||
var_name string // `match cond as var_name {`
|
||||
is_union_match bool // temporary union key after match
|
||||
is_union_match bool // TODO: remove
|
||||
pub mut:
|
||||
is_expr bool // returns a value
|
||||
return_type table.Type
|
||||
|
@ -748,15 +746,6 @@ pub:
|
|||
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
|
||||
pub struct UnionSumTypeDecl {
|
||||
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 }
|
||||
GoStmt { return stmt.call_expr.position() }
|
||||
TypeDecl { match union stmt {
|
||||
AliasTypeDecl, FnTypeDecl, SumTypeDecl, UnionSumTypeDecl { return stmt.pos }
|
||||
AliasTypeDecl, FnTypeDecl, UnionSumTypeDecl { return stmt.pos }
|
||||
} }
|
||||
// Please, do NOT use else{} here.
|
||||
// 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] ||
|
||||
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') {
|
||||
return `s`
|
||||
} else {
|
||||
|
|
|
@ -237,7 +237,7 @@ fn (mut c Checker) check_file_in_main(file ast.File) bool {
|
|||
if stmt.is_pub {
|
||||
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 {
|
||||
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 {
|
||||
c.check_valid_pascal_case(node.name, 'sum type', node.pos)
|
||||
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)
|
||||
}
|
||||
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()
|
||||
c.error('cast to sum type using `${type_sym.source_name}($sexpr)` not `$type_sym.source_name{$sexpr}`',
|
||||
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',
|
||||
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',
|
||||
infix_expr.pos)
|
||||
} else if left.kind == .union_sum_type {
|
||||
info := left.info as table.UnionSumType
|
||||
if type_expr.typ !in info.variants {
|
||||
} else if mut left.info is table.UnionSumType {
|
||||
if type_expr.typ !in left.info.variants {
|
||||
c.error('`$left.source_name` has no variant `$right.source_name`',
|
||||
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())
|
||||
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
|
||||
}
|
||||
// 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 {
|
||||
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 {
|
||||
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)
|
||||
expr_type_sym := c.table.get_type_symbol(node.expr_type)
|
||||
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 {
|
||||
// Unknown type used in the right part of `as`
|
||||
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 {
|
||||
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.'
|
||||
}
|
||||
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.',
|
||||
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] {
|
||||
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)
|
||||
}
|
||||
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
|
||||
}
|
||||
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
|
||||
if (!is_mut || node.is_mut) && !is_already_casted {
|
||||
sum_type_casts << expr_type
|
||||
scope.register(node.var_name, ast.Var{
|
||||
name: node.var_name
|
||||
scope.register(node.cond.name, ast.Var{
|
||||
name: node.cond.name
|
||||
typ: node.cond_type
|
||||
pos: node.cond.pos
|
||||
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 unhandled := []string{}
|
||||
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 {
|
||||
for v in type_sym.info.variants {
|
||||
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 }
|
||||
// Register shadow variable or `as` variable with actual type
|
||||
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 scope := c.file.scope.innermost(branch.body_pos.pos)
|
||||
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
|
||||
sum_type_casts << v.sum_type_casts
|
||||
}
|
||||
// smartcast either if the value is immutable or if the mut argument is explicitly given
|
||||
if (!is_mut || branch.is_mut_name) &&
|
||||
left_sym.kind == .union_sum_type {
|
||||
sum_type_casts << right_expr.typ
|
||||
scope.register(branch.left_as_name, ast.Var{
|
||||
name: branch.left_as_name
|
||||
typ: infix.left_type
|
||||
if left_sym.kind == .union_sum_type {
|
||||
// smartcast either if the value is immutable or if the mut argument is explicitly given
|
||||
if !is_mut || branch.is_mut_name {
|
||||
sum_type_casts << right_expr.typ
|
||||
scope.register(infix.left.name, ast.Var{
|
||||
name: infix.left.name
|
||||
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
|
||||
pos: infix.left.pos
|
||||
is_used: true
|
||||
is_mut: is_mut
|
||||
})
|
||||
// TODO: remove that later @danieldaeschle
|
||||
node.branches[i].smartcast = true
|
||||
}
|
||||
} else if mut infix.left is ast.SelectorExpr {
|
||||
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
|
||||
} else if cond.name in valid_comp_if_other {
|
||||
// TODO: This should probably be moved
|
||||
match cond.name as name {
|
||||
match cond.name {
|
||||
'js' { return c.pref.backend != .js }
|
||||
'debug' { return !c.pref.is_debug }
|
||||
'test' { return !c.pref.is_test }
|
||||
|
@ -4525,7 +4506,7 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) {
|
|||
if sym.kind == .interface_ {
|
||||
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)
|
||||
}
|
||||
// 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 |
|
||||
13 | fn main() {
|
||||
14 | if IoS(1) is byte {
|
||||
| ~~~~~~~~~~~~~~~~~
|
||||
| ~~
|
||||
15 | println('not cool')
|
||||
16 | }
|
||||
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 {
|
||||
| ~~~~~~~~~~~
|
||||
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() {
|
||||
4 | match IoS(1) {
|
||||
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`
|
||||
23 | match NATOAlphabet(a) as l {
|
||||
24 | Alfa, Charlie {
|
||||
25 | assert l.char == `a`
|
||||
vlib/v/checker/tests/match_sumtype_multiple_types.vv:26:13: error: type `Charlie` has no field or method `char`
|
||||
24 | match l {
|
||||
25 | Alfa, Charlie {
|
||||
26 | assert l.char == `a`
|
||||
| ~~~~
|
||||
26 | assert l.letter() == 'a'
|
||||
27 | }
|
||||
vlib/v/checker/tests/match_sumtype_multiple_types.vv:26:13: error: unknown method: `Charlie.letter`
|
||||
24 | Alfa, Charlie {
|
||||
25 | assert l.char == `a`
|
||||
26 | assert l.letter() == 'a'
|
||||
27 | assert l.letter() == 'a'
|
||||
28 | }
|
||||
vlib/v/checker/tests/match_sumtype_multiple_types.vv:27:13: error: unknown method: `Charlie.letter`
|
||||
25 | Alfa, Charlie {
|
||||
26 | assert l.char == `a`
|
||||
27 | assert l.letter() == 'a'
|
||||
| ~~~~~~~~~
|
||||
27 | }
|
||||
28 | Bravo {
|
||||
28 | }
|
||||
29 | Bravo {
|
|
@ -20,7 +20,8 @@ type NATOAlphabet = Alfa | Bravo | Charlie
|
|||
|
||||
fn method_not_exists() {
|
||||
a := Alfa{}
|
||||
match NATOAlphabet(a) as l {
|
||||
l := NATOAlphabet(a)
|
||||
match l {
|
||||
Alfa, Charlie {
|
||||
assert l.char == `a`
|
||||
assert l.letter() == 'a'
|
||||
|
|
|
@ -96,7 +96,7 @@ pub fn (d Doc) stmt_name(stmt ast.Stmt) string {
|
|||
match union stmt {
|
||||
ast.FnDecl, ast.StructDecl, ast.EnumDecl, ast.InterfaceDecl { return stmt.name }
|
||||
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
|
||||
else { return '' }
|
||||
|
|
|
@ -454,7 +454,7 @@ pub fn (mut f Fmt) stmt(node ast.Stmt) {
|
|||
f.write('sql ')
|
||||
f.expr(node.db_expr)
|
||||
f.writeln(' {')
|
||||
match node.kind as k {
|
||||
match node.kind {
|
||||
.insert {
|
||||
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
|
||||
}
|
||||
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 {
|
||||
if node.is_pub {
|
||||
f.write('pub ')
|
||||
|
@ -1412,15 +1392,6 @@ pub fn (mut f Fmt) if_expr(it ast.IfExpr) {
|
|||
(it.is_expr || f.is_assign)
|
||||
f.single_line_if = single_line
|
||||
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 {
|
||||
// first `if`
|
||||
f.comments(branch.comments, {})
|
||||
|
@ -1440,9 +1411,6 @@ pub fn (mut f Fmt) if_expr(it ast.IfExpr) {
|
|||
f.write('mut ')
|
||||
}
|
||||
f.expr(branch.cond)
|
||||
if smartcast_as {
|
||||
f.write(' as $branch.left_as_name')
|
||||
}
|
||||
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) {
|
||||
f.write('match ')
|
||||
// TODO: temporary, remove again
|
||||
if it.is_union_match {
|
||||
f.write('union ')
|
||||
}
|
||||
|
@ -1570,12 +1537,6 @@ pub fn (mut f Fmt) match_expr(it ast.MatchExpr) {
|
|||
f.expr(it.cond)
|
||||
if it.cond is ast.Ident {
|
||||
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.indent++
|
||||
|
|
|
@ -4,7 +4,7 @@ struct IfExpr {
|
|||
struct MatchExpr {
|
||||
}
|
||||
|
||||
type Expr = IfExpr | MatchExpr
|
||||
__type Expr = IfExpr | MatchExpr
|
||||
|
||||
fn sum_types(a []Expr) {
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ fn handle_users(users []User) {
|
|||
fn (u &User) foo(u2 &User) {
|
||||
}
|
||||
|
||||
type Expr = IfExpr | IntegerLiteral
|
||||
__type Expr = IfExpr | IntegerLiteral
|
||||
|
||||
fn exprs(e []Expr) {
|
||||
println(e.len)
|
||||
|
|
|
@ -6,17 +6,15 @@ mut:
|
|||
struct S2 {
|
||||
}
|
||||
|
||||
type Sum = S1 | S2
|
||||
__type Sum = S1 | S2
|
||||
|
||||
fn f(sum Sum) {
|
||||
if mut sum is S1 {
|
||||
sum.i++
|
||||
}
|
||||
if sum is S1 as s1 {
|
||||
if sum is S1 {
|
||||
}
|
||||
a := [sum]
|
||||
if a[0] is S2 {
|
||||
}
|
||||
if a[0] is S2 as s2 {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
// 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
|
||||
type MyInt = int
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
type Uint = u16 | u64
|
||||
| u32
|
||||
| byte // This should stay on the same line
|
||||
| byte
|
||||
type
|
||||
Float =
|
||||
f32 |
|
||||
|
|
|
@ -73,9 +73,6 @@ fn (mut g Gen) gen_str_for_type_with_styp(typ table.Type, styp string) string {
|
|||
table.MultiReturn {
|
||||
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 {
|
||||
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 '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 {
|
||||
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('}')
|
||||
}
|
||||
|
||||
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) {
|
||||
mut gen_fn_names := map[string]string{}
|
||||
for typ in info.variants {
|
||||
|
|
|
@ -370,22 +370,6 @@ pub fn (mut g Gen) finish() {
|
|||
pub fn (mut g Gen) write_typeof_functions() {
|
||||
g.writeln('')
|
||||
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 {
|
||||
if typ.kind == .union_sum_type {
|
||||
sum_info := typ.info as table.UnionSumType
|
||||
|
@ -2293,7 +2277,7 @@ fn (mut g Gen) expr(node ast.Expr) {
|
|||
g.expr(node.arg)
|
||||
}
|
||||
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)
|
||||
} else if sym.kind == .struct_ && !node.typ.is_ptr() && !(sym.info as table.Struct).is_typedef {
|
||||
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) {
|
||||
sym := g.table.get_type_symbol(node.expr_type)
|
||||
if sym.kind == .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 {
|
||||
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()
|
||||
|
@ -3098,7 +3075,7 @@ fn (mut g Gen) match_expr_sumtype(node ast.MatchExpr, is_expr bool, cond_var str
|
|||
}
|
||||
g.write(cond_var)
|
||||
// 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 { '.' }
|
||||
g.write(dot_or_ptr)
|
||||
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('/* 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)
|
||||
if g.inside_ternary == 0 {
|
||||
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 {
|
||||
info := g.match_sumtype_syms[i].info
|
||||
match union info {
|
||||
table.SumType {
|
||||
for typ in info.variants {
|
||||
if g.table.get_type_symbol(typ).kind == .struct_ {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
table.UnionSumType {
|
||||
for typ in info.variants {
|
||||
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 {
|
||||
infix := branch.cond as ast.InfixExpr
|
||||
right_type := infix.right as ast.Type
|
||||
left_type := infix.left_type
|
||||
it_type := g.typ(right_type.typ)
|
||||
g.write('\t$it_type* _sc_tmp_$branch.pos.pos = ($it_type*)')
|
||||
g.expr(infix.left)
|
||||
if left_type.is_ptr() {
|
||||
g.write('->')
|
||||
} else {
|
||||
g.write('.')
|
||||
if mut infix.left is ast.Ident {
|
||||
right_type := infix.right as ast.Type
|
||||
left_type := infix.left_type
|
||||
it_type := g.typ(right_type.typ)
|
||||
g.write('\t$it_type* _sc_tmp_$branch.pos.pos = ($it_type*)')
|
||||
g.expr(infix.left)
|
||||
if left_type.is_ptr() {
|
||||
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 {
|
||||
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')
|
||||
}
|
||||
table.Alias {
|
||||
// table.Alias, table.SumType { 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.Alias { TODO
|
||||
}
|
||||
table.UnionSumType {
|
||||
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('")')
|
||||
}
|
||||
} 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()
|
||||
val_type := if is_p { typ.deref() } else { typ }
|
||||
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 {}
|
||||
}
|
||||
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) }
|
||||
else { '0' }
|
||||
}
|
||||
|
@ -5604,23 +5545,7 @@ fn (mut g Gen) as_cast(node ast.AsCast) {
|
|||
// g.insert_before('
|
||||
styp := g.typ(node.typ)
|
||||
expr_type_sym := g.table.get_type_symbol(node.expr_type)
|
||||
if expr_type_sym.kind == .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 {
|
||||
if expr_type_sym.kind == .union_sum_type {
|
||||
dot := if node.expr_type.is_ptr() { '->' } else { '.' }
|
||||
g.write('/* as */ *($styp*)__as_cast((')
|
||||
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)
|
||||
g.write('_${c_name(sym.name)}_${c_name(sub_sym.name)}_index')
|
||||
return
|
||||
} else if sym.kind in [.sum_type, .union_sum_type] {
|
||||
} else if sym.kind == .union_sum_type {
|
||||
g.write('typ $eq ')
|
||||
}
|
||||
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
|
||||
} else if sym.kind == .u64 {
|
||||
return '%lld\\000'
|
||||
} else if sym.kind == .sum_type {
|
||||
} else if sym.kind == .union_sum_type {
|
||||
return '%.*s\\000'
|
||||
}
|
||||
return '%d\\000'
|
||||
|
|
|
@ -366,8 +366,8 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
|
|||
else {}
|
||||
}
|
||||
}
|
||||
if left_sym.kind == .sum_type && node.name == 'type_name' {
|
||||
g.write('tos3( /* $left_sym.name */ v_typeof_sumtype_${node.receiver_type}( (')
|
||||
if left_sym.kind == .union_sum_type && node.name == 'type_name' {
|
||||
g.write('tos3( /* $left_sym.name */ v_typeof_unionsumtype_${node.receiver_type}( (')
|
||||
g.expr(node.left)
|
||||
g.write(').typ ))')
|
||||
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)
|
||||
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) {
|
||||
g.write('(voidptr)&/*qq*/')
|
||||
}
|
||||
|
|
|
@ -257,10 +257,6 @@ pub fn (mut g JsGen) typ(t table.Type) string {
|
|||
joined := types.join(', ')
|
||||
styp = '[$joined]'
|
||||
}
|
||||
.sum_type {
|
||||
// TODO: Implement sumtypes
|
||||
styp = 'sym_type'
|
||||
}
|
||||
.union_sum_type {
|
||||
// TODO: Implement sumtypes
|
||||
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) {
|
||||
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
|
||||
} else if sym.kind == .array_fixed {
|
||||
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) {
|
||||
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' +
|
||||
'return values instead: `fn foo(mut n $sym.name) {` => `fn foo(n $sym.name) $sym.name {`',
|
||||
pos)
|
||||
|
|
|
@ -6,7 +6,6 @@ module parser
|
|||
import v.ast
|
||||
import v.table
|
||||
import v.token
|
||||
import strings
|
||||
|
||||
fn (mut p Parser) if_expr(is_comptime bool) ast.IfExpr {
|
||||
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)
|
||||
}
|
||||
comments << p.eat_comments()
|
||||
mut left_as_name := ''
|
||||
if mut cond is ast.InfixExpr {
|
||||
// if sum is T
|
||||
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 {
|
||||
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)
|
||||
body_pos: body_pos.extend(p.prev_tok.position())
|
||||
comments: comments
|
||||
left_as_name: left_as_name
|
||||
is_mut_name: is_mut_name
|
||||
}
|
||||
comments = p.eat_comments()
|
||||
|
@ -195,14 +180,8 @@ fn (mut p Parser) match_expr() ast.MatchExpr {
|
|||
if is_mut {
|
||||
p.next()
|
||||
}
|
||||
cond_pos := p.tok.position()
|
||||
cond := p.expr(0)
|
||||
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
|
||||
if !no_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' &&
|
||||
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())) {
|
||||
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{}
|
||||
for {
|
||||
// Sum type match
|
||||
|
@ -251,52 +216,6 @@ fn (mut p Parser) match_expr() ast.MatchExpr {
|
|||
}
|
||||
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
|
||||
} else {
|
||||
// Expression match
|
||||
|
@ -366,10 +285,9 @@ fn (mut p Parser) match_expr() ast.MatchExpr {
|
|||
branches: branches
|
||||
cond: cond
|
||||
is_sum_type: is_sum_type
|
||||
is_union_match: is_union_match
|
||||
pos: pos
|
||||
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)
|
||||
p.table.register_type_symbol(table.TypeSymbol{
|
||||
kind: .sum_type
|
||||
kind: .union_sum_type
|
||||
name: prepend_mod_name
|
||||
source_name: prepend_mod_name
|
||||
mod: p.mod
|
||||
info: table.SumType{
|
||||
info: table.UnionSumType{
|
||||
variants: sum_variants
|
||||
}
|
||||
is_public: is_pub
|
||||
})
|
||||
comments = p.eat_lineend_comments()
|
||||
return ast.SumTypeDecl{
|
||||
return ast.UnionSumTypeDecl{
|
||||
name: name
|
||||
is_pub: is_pub
|
||||
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*)`
|
||||
pub fn (table &Table) sumtype_has_variant(parent Type, variant Type) bool {
|
||||
parent_sym := table.get_type_symbol(parent)
|
||||
if parent_sym.kind == .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 {
|
||||
if parent_sym.kind == .union_sum_type {
|
||||
parent_info := parent_sym.info as UnionSumType
|
||||
for v in parent_info.variants {
|
||||
if v.idx() == variant.idx() {
|
||||
|
|
|
@ -16,7 +16,7 @@ import strings
|
|||
pub type Type = int
|
||||
|
||||
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 {
|
||||
v
|
||||
|
@ -404,7 +404,6 @@ pub enum Kind {
|
|||
struct_
|
||||
generic_struct_inst
|
||||
multi_return
|
||||
sum_type
|
||||
union_sum_type
|
||||
alias
|
||||
enum_
|
||||
|
@ -719,7 +718,6 @@ pub fn (k Kind) str() string {
|
|||
.map { 'map' }
|
||||
.chan { 'chan' }
|
||||
.multi_return { 'multi_return' }
|
||||
.sum_type { 'sum_type' }
|
||||
.union_sum_type { 'union_sum_type' }
|
||||
.alias { 'alias' }
|
||||
.enum_ { 'enum' }
|
||||
|
@ -843,11 +841,6 @@ pub mut:
|
|||
value_type Type
|
||||
}
|
||||
|
||||
pub struct SumType {
|
||||
pub:
|
||||
variants []Type
|
||||
}
|
||||
|
||||
pub struct UnionSumType {
|
||||
pub:
|
||||
variants []Type
|
||||
|
|
|
@ -18,12 +18,12 @@ fn test_if_smartcast() {
|
|||
|
||||
fn test_mutable() {
|
||||
mut x := Alphabet(Abc{'original'})
|
||||
if x is Abc {
|
||||
if mut x is Abc {
|
||||
assert x.val == 'original'
|
||||
x.val = 'changed'
|
||||
assert x.val == 'changed'
|
||||
}
|
||||
if x is Abc {
|
||||
if mut x is Abc {
|
||||
assert x.val == 'changed'
|
||||
}
|
||||
}
|
||||
|
@ -38,11 +38,9 @@ fn test_nested_if_smartcast() {
|
|||
}
|
||||
}
|
||||
|
||||
fn test_as_cast() {
|
||||
x := Alphabet(Abc{'test'})
|
||||
if x is Abc as test {
|
||||
assert test.val == 'test'
|
||||
}
|
||||
struct MutContainer {
|
||||
mut:
|
||||
abc Alphabet
|
||||
}
|
||||
|
||||
struct Container {
|
||||
|
@ -50,29 +48,24 @@ struct Container {
|
|||
}
|
||||
|
||||
fn test_mutable_with_struct() {
|
||||
mut c := Container{Abc{'original'}}
|
||||
if c.abc is Abc as abc {
|
||||
assert abc.val == 'original'
|
||||
mut mabc := abc
|
||||
// NB: since `abc` is a pointer,
|
||||
// `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'
|
||||
mut c := MutContainer{Abc{'original'}}
|
||||
if mut c.abc is Abc {
|
||||
assert c.abc.val == 'original'
|
||||
c.abc.val = 'xyz'
|
||||
assert c.abc.val == 'xyz'
|
||||
}
|
||||
if c.abc is Abc as another {
|
||||
if mut c.abc is Abc {
|
||||
// NB: in this second smart cast, `another` is
|
||||
// the same wrapped value, that was changed in
|
||||
// the first smart cast:
|
||||
assert another.val == 'xyz'
|
||||
assert c.abc.val == 'xyz'
|
||||
}
|
||||
}
|
||||
|
||||
fn test_as_cast_with_struct() {
|
||||
x := Container{Abc{'test'}}
|
||||
if x.abc is Abc as test {
|
||||
assert test.val == 'test'
|
||||
if x.abc is Abc {
|
||||
assert x.abc.val == 'test'
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -113,19 +106,19 @@ fn test_mutability() {
|
|||
}
|
||||
mut cell := Cell{}
|
||||
cell = cell_str
|
||||
if cell is CellStr {
|
||||
if mut cell is CellStr {
|
||||
println('$cell.str')
|
||||
}
|
||||
cell = cell_itg
|
||||
if cell is CellInt {
|
||||
if mut cell is CellInt {
|
||||
println('$cell.itg')
|
||||
}
|
||||
cell = cell_flt
|
||||
if cell is CellFloat {
|
||||
if mut cell is CellFloat {
|
||||
println('$cell.flt')
|
||||
}
|
||||
cell = cell_u32
|
||||
if cell is CellU32 {
|
||||
if mut cell is CellU32 {
|
||||
println('$cell.u')
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ const (
|
|||
fn test_shadow() {
|
||||
mut animal := Animal{}
|
||||
animal = cat
|
||||
match animal {
|
||||
match mut animal {
|
||||
Cat {
|
||||
assert animal.name == cat.name
|
||||
}
|
||||
|
@ -24,9 +24,9 @@ fn test_shadow() {
|
|||
fn test_as() {
|
||||
mut animal := Animal{}
|
||||
animal = dog
|
||||
match animal as animal_kind {
|
||||
match mut animal {
|
||||
Dog {
|
||||
assert animal_kind.name == dog.name
|
||||
assert animal.name == dog.name
|
||||
}
|
||||
else{
|
||||
assert false
|
||||
|
|
|
@ -205,7 +205,8 @@ type NATOAlphabet = Alfa | Bravo | Charlie
|
|||
|
||||
fn test_match_sumtype_multiple_types() {
|
||||
a := Alfa{}
|
||||
match NATOAlphabet(a) as l {
|
||||
l := NATOAlphabet(a)
|
||||
match l {
|
||||
Alfa, Bravo {
|
||||
assert l.char == `a`
|
||||
// TODO make methods work
|
||||
|
@ -216,7 +217,7 @@ fn test_match_sumtype_multiple_types() {
|
|||
}
|
||||
}
|
||||
// test one branch
|
||||
match NATOAlphabet(a) as l {
|
||||
match l {
|
||||
Alfa, Bravo, Charlie {
|
||||
assert l.char == `a`
|
||||
}
|
||||
|
|
|
@ -28,8 +28,7 @@ fn handle(e Expr) string {
|
|||
}
|
||||
match e {
|
||||
IntegerLiteral {
|
||||
assert it.val == '12'
|
||||
// assert e.val == '12' // TODO
|
||||
assert e.val == '12'
|
||||
return 'int'
|
||||
}
|
||||
IfExpr {
|
||||
|
@ -56,10 +55,10 @@ fn test_assignment_and_push() {
|
|||
arr1 << expr
|
||||
match arr1[0] {
|
||||
IntegerLiteral {
|
||||
arr1 << it
|
||||
arr1 << arr1[0]
|
||||
// should ref/dereference on assignent be made automatic?
|
||||
// currently it is done for return stmt and fn args
|
||||
expr1 = *it
|
||||
expr1 = arr1[0]
|
||||
}
|
||||
else {}
|
||||
}
|
||||
|
@ -96,7 +95,7 @@ fn test_converting_down() {
|
|||
mut res := []Sub2{cap: out.len}
|
||||
for d in out {
|
||||
match d {
|
||||
Sub2 { res << it }
|
||||
Sub2 { res << d }
|
||||
else {}
|
||||
}
|
||||
}
|
||||
|
@ -107,26 +106,6 @@ fn test_converting_down() {
|
|||
}
|
||||
|
||||
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}))
|
||||
if c is Expr {
|
||||
if c is IfExpr {
|
||||
|
@ -202,8 +181,8 @@ fn is_gt_nested(val string, dst Number) bool {
|
|||
return val.int() > dst
|
||||
}
|
||||
// this branch should never been hit
|
||||
else {
|
||||
return val.int() < dst
|
||||
else {
|
||||
return val.int() < dst
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -213,8 +192,8 @@ fn is_gt_nested(val string, dst Number) bool {
|
|||
return dst < val.f64()
|
||||
}
|
||||
// this branch should never been hit
|
||||
else {
|
||||
return dst > val.f64()
|
||||
else {
|
||||
return dst > val.f64()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -255,7 +234,7 @@ fn test_sum_type_match() {
|
|||
assert is_gt_simple('3', 2)
|
||||
assert !is_gt_simple('3', 5)
|
||||
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', 5)
|
||||
assert is_gt_nested('3', 1.2)
|
||||
|
|
|
@ -51,8 +51,8 @@ type MySumType = int | f32 | FooBar
|
|||
|
||||
pub fn (ms MySumType) str() string {
|
||||
match ms {
|
||||
int { return it.str() }
|
||||
f32 { return it.str() }
|
||||
int { return ms.str() }
|
||||
f32 { return ms.str() }
|
||||
//FooBar { return it.x.str() }
|
||||
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(FooBar{}) == 'FooBar'
|
||||
|
||||
|
||||
assert array_item_type([v]) == 'int'
|
||||
assert array_item_type([[v]]) == '[]int'
|
||||
//assert array_item_type([&v]) == '&int'
|
||||
|
|
Loading…
Reference in New Issue