all: use the new types with old syntax (#6922)

pull/6937/head
Daniel Däschle 2020-11-24 13:58:29 +01:00 committed by GitHub
parent 8be9bdacd1
commit aa6303f0b2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 303 additions and 300 deletions

View File

@ -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 | SumTypeDecl | 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 |
@ -16,14 +16,14 @@ pub __type Expr = AnonFn | ArrayInit | AsCast | Assoc | AtExpr | BoolLiteral | C
RangeExpr | SelectExpr | SelectorExpr | SizeOf | SqlExpr | StringInterLiteral | StringLiteral | RangeExpr | SelectExpr | SelectorExpr | SizeOf | SqlExpr | StringInterLiteral | StringLiteral |
StructInit | Type | TypeOf | UnsafeExpr StructInit | Type | TypeOf | UnsafeExpr
pub type Stmt = AssertStmt | AssignStmt | Block | BranchStmt | CompFor | ConstDecl | DeferStmt | pub __type Stmt = AssertStmt | AssignStmt | Block | BranchStmt | CompFor | ConstDecl |
EnumDecl | ExprStmt | FnDecl | ForCStmt | ForInStmt | ForStmt | GlobalDecl | GoStmt | DeferStmt | EnumDecl | ExprStmt | FnDecl | ForCStmt | ForInStmt | ForStmt | GlobalDecl |
GotoLabel | GotoStmt | HashStmt | Import | InterfaceDecl | Module | Return | SqlStmt | GoStmt | GotoLabel | GotoStmt | HashStmt | Import | InterfaceDecl | Module | Return |
StructDecl | TypeDecl SqlStmt | StructDecl | TypeDecl
// NB: when you add a new Expr or Stmt type with a .pos field, remember to update // NB: when you add a new Expr or Stmt type with a .pos field, remember to update
// the .position() token.Position methods too. // the .position() token.Position methods too.
pub type ScopeObject = ConstField | GlobalField | Var pub __type ScopeObject = ConstField | GlobalField | Var
pub struct Type { pub struct Type {
pub: pub:
@ -430,7 +430,7 @@ pub mut:
share table.ShareType share table.ShareType
} }
pub type IdentInfo = IdentFn | IdentVar pub __type IdentInfo = IdentFn | IdentVar
pub enum IdentKind { pub enum IdentKind {
unresolved unresolved
@ -457,9 +457,9 @@ pub mut:
} }
pub fn (i &Ident) var_info() IdentVar { pub fn (i &Ident) var_info() IdentVar {
match i.info as info { match union mut i.info {
IdentVar { IdentVar {
return *info return i.info
} }
else { else {
// return IdentVar{} // return IdentVar{}
@ -1123,7 +1123,7 @@ pub fn (expr Expr) is_expr() bool {
// check if stmt can be an expression in C // check if stmt can be an expression in C
pub fn (stmt Stmt) check_c_expr() ? { pub fn (stmt Stmt) check_c_expr() ? {
match stmt { match union stmt {
AssignStmt { AssignStmt {
return return
} }
@ -1148,10 +1148,10 @@ pub:
} }
pub fn (stmt Stmt) position() token.Position { pub fn (stmt Stmt) position() token.Position {
match stmt { match union stmt {
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 stmt { TypeDecl { match union stmt {
AliasTypeDecl, FnTypeDecl, SumTypeDecl, UnionSumTypeDecl { return stmt.pos } AliasTypeDecl, FnTypeDecl, SumTypeDecl, UnionSumTypeDecl { return stmt.pos }
} } } }
// Please, do NOT use else{} here. // Please, do NOT use else{} here.

View File

@ -73,8 +73,8 @@ pub fn (s &Scope) is_known(name string) bool {
pub fn (s &Scope) find_var(name string) ?&Var { pub fn (s &Scope) find_var(name string) ?&Var {
if obj := s.find(name) { if obj := s.find(name) {
match obj { match union obj {
Var { return obj } Var { return &obj }
else {} else {}
} }
} }
@ -83,8 +83,8 @@ pub fn (s &Scope) find_var(name string) ?&Var {
pub fn (s &Scope) find_const(name string) ?&ConstField { pub fn (s &Scope) find_const(name string) ?&ConstField {
if obj := s.find(name) { if obj := s.find(name) {
match obj { match union obj {
ConstField { return obj } ConstField { return &obj }
else {} else {}
} }
} }
@ -100,12 +100,13 @@ pub fn (s &Scope) known_var(name string) bool {
pub fn (mut s Scope) update_var_type(name string, typ table.Type) { pub fn (mut s Scope) update_var_type(name string, typ table.Type) {
s.end_pos = s.end_pos // TODO mut bug s.end_pos = s.end_pos // TODO mut bug
match mut s.objects[name] { mut obj := s.objects[name]
match union mut obj {
Var { Var {
if it.typ == typ { if obj.typ == typ {
return return
} }
it.typ = typ obj.typ = typ
} }
else {} else {}
} }
@ -181,7 +182,7 @@ pub fn (sc &Scope) show(depth int, max_depth int) string {
} }
out += '$indent# $sc.start_pos - $sc.end_pos\n' out += '$indent# $sc.start_pos - $sc.end_pos\n'
for _, obj in sc.objects { for _, obj in sc.objects {
match obj { match union obj {
ConstField { out += '$indent * const: $obj.name - $obj.typ\n' } ConstField { out += '$indent * const: $obj.name - $obj.typ\n' }
Var { out += '$indent * var: $obj.name - $obj.typ\n' } Var { out += '$indent * var: $obj.name - $obj.typ\n' }
else {} else {}

View File

@ -302,7 +302,7 @@ pub fn (node &BranchStmt) str() string {
} }
pub fn (node Stmt) str() string { pub fn (node Stmt) str() string {
match node { match union node {
AssignStmt { AssignStmt {
mut out := '' mut out := ''
for i, left in node.left { for i, left in node.left {

View File

@ -9,7 +9,7 @@ pub fn (b &Builder) generic_struct_insts_to_concrete() {
if typ.kind == .generic_struct_inst { if typ.kind == .generic_struct_inst {
info := typ.info as table.GenericStructInst info := typ.info as table.GenericStructInst
parent := b.table.types[info.parent_idx] parent := b.table.types[info.parent_idx]
mut parent_info := *(parent.info as table.Struct) mut parent_info := parent.info as table.Struct
mut fields := parent_info.fields.clone() mut fields := parent_info.fields.clone()
for i, _ in fields { for i, _ in fields {
mut field := fields[i] mut field := fields[i]

View File

@ -95,7 +95,7 @@ pub fn (mut c Checker) check(ast_file &ast.File) {
pub fn (mut c Checker) check_scope_vars(sc &ast.Scope) { pub fn (mut c Checker) check_scope_vars(sc &ast.Scope) {
for _, obj in sc.objects { for _, obj in sc.objects {
match obj { match union obj {
ast.Var { ast.Var {
if !c.pref.is_repl { if !c.pref.is_repl {
if !obj.is_used && obj.name[0] != `_` { if !obj.is_used && obj.name[0] != `_` {
@ -178,7 +178,7 @@ const (
fn (mut c Checker) check_file_in_main(file ast.File) bool { fn (mut c Checker) check_file_in_main(file ast.File) bool {
mut has_main_fn := false mut has_main_fn := false
for stmt in file.stmts { for stmt in file.stmts {
match stmt { match union stmt {
ast.ConstDecl { ast.ConstDecl {
if stmt.is_pub { if stmt.is_pub {
c.warn('const $no_pub_in_main_warning', stmt.pos) c.warn('const $no_pub_in_main_warning', stmt.pos)
@ -278,7 +278,7 @@ fn (mut c Checker) check_valid_pascal_case(name string, identifier string, pos t
} }
pub fn (mut c Checker) type_decl(node ast.TypeDecl) { pub fn (mut c Checker) type_decl(node ast.TypeDecl) {
match node { match union node {
ast.AliasTypeDecl { ast.AliasTypeDecl {
// TODO Replace `c.file.mod.name != 'time'` by `it.language != .v` once available // TODO Replace `c.file.mod.name != 'time'` by `it.language != .v` once available
if c.file.mod.name != 'time' && c.file.mod.name != 'builtin' { if c.file.mod.name != 'time' && c.file.mod.name != 'builtin' {
@ -347,21 +347,22 @@ pub fn (mut c Checker) struct_decl(decl ast.StructDecl) {
if decl.language == .v && !c.is_builtin_mod { if decl.language == .v && !c.is_builtin_mod {
c.check_valid_pascal_case(decl.name, 'struct name', decl.pos) c.check_valid_pascal_case(decl.name, 'struct name', decl.pos)
} }
struct_sym := c.table.find_type(decl.name) or { mut struct_sym := c.table.find_type(decl.name) or {
table.TypeSymbol{} table.TypeSymbol{}
} }
mut struct_info := struct_sym.info as table.Struct if mut struct_sym.info is table.Struct {
for i, field in decl.fields { for i, field in decl.fields {
if decl.language == .v && !field.is_embed { if decl.language == .v && !field.is_embed {
c.check_valid_snake_case(field.name, 'field name', field.pos) c.check_valid_snake_case(field.name, 'field name', field.pos)
} }
sym := c.table.get_type_symbol(field.typ) sym := c.table.get_type_symbol(field.typ)
if field.is_embed { if field.is_embed {
if sym.info is table.Struct as sym_info { if mut sym.info is table.Struct {
for embed_field in sym_info.fields { for embed_field in sym.info.fields {
already_exists := struct_info.fields.filter(it.name == embed_field.name).len > 0 already_exists := struct_sym.info.fields.filter(it.name == embed_field.name).len >
0
if !already_exists { if !already_exists {
struct_info.fields << { struct_sym.info.fields << {
embed_field | embed_field |
embed_alias_for: field.name embed_alias_for: field.name
} }
@ -410,7 +411,8 @@ pub fn (mut c Checker) struct_decl(decl ast.StructDecl) {
c.expected_type = field.typ c.expected_type = field.typ
field_expr_type := c.expr(field.default_expr) field_expr_type := c.expr(field.default_expr)
c.check_expected(field_expr_type, field.typ) or { c.check_expected(field_expr_type, field.typ) or {
c.error('incompatible initializer for field `$field.name`: $err', field.default_expr.position()) c.error('incompatible initializer for field `$field.name`: $err',
field.default_expr.position())
} }
// Check for unnecessary inits like ` = 0` and ` = ''` // Check for unnecessary inits like ` = 0` and ` = ''`
if field.typ.is_ptr() { if field.typ.is_ptr() {
@ -434,6 +436,7 @@ pub fn (mut c Checker) struct_decl(decl ast.StructDecl) {
} }
} }
} }
}
} }
pub fn (mut c Checker) struct_init(mut struct_init ast.StructInit) table.Type { pub fn (mut c Checker) struct_init(mut struct_init ast.StructInit) table.Type {
@ -938,9 +941,8 @@ fn (mut c Checker) fail_if_immutable(expr ast.Expr) (string, token.Position) {
return '', pos return '', pos
} }
mut typ_sym := c.table.get_type_symbol(c.unwrap_generic(expr.expr_type)) mut typ_sym := c.table.get_type_symbol(c.unwrap_generic(expr.expr_type))
if typ_sym.kind == .alias { if mut typ_sym.info is table.Alias {
alias_info := typ_sym.info as table.Alias typ_sym = c.table.get_type_symbol(typ_sym.info.parent_type)
typ_sym = c.table.get_type_symbol(alias_info.parent_type)
} }
match typ_sym.kind { match typ_sym.kind {
.struct_ { .struct_ {
@ -1148,8 +1150,8 @@ pub fn (mut c Checker) call_method(mut call_expr ast.CallExpr) table.Type {
arg_sym := c.table.get_type_symbol(arg_type) arg_sym := c.table.get_type_symbol(arg_type)
// FIXME: match expr failed for now // FIXME: match expr failed for now
mut ret_type := 0 mut ret_type := 0
match arg_sym.info as info { match union mut arg_sym.info {
table.FnType { ret_type = info.func.return_type } table.FnType { ret_type = arg_sym.info.func.return_type }
else { ret_type = arg_type } else { ret_type = arg_type }
} }
call_expr.return_type = c.table.find_or_register_array(ret_type, 1, c.mod) call_expr.return_type = c.table.find_or_register_array(ret_type, 1, c.mod)
@ -1616,7 +1618,7 @@ pub fn (mut c Checker) call_fn(mut call_expr ast.CallExpr) table.Type {
fn (mut c Checker) type_implements(typ table.Type, inter_typ table.Type, pos token.Position) bool { fn (mut c Checker) type_implements(typ table.Type, inter_typ table.Type, pos token.Position) bool {
typ_sym := c.table.get_type_symbol(typ) typ_sym := c.table.get_type_symbol(typ)
inter_sym := c.table.get_type_symbol(inter_typ) mut inter_sym := c.table.get_type_symbol(inter_typ)
styp := c.table.type_to_str(typ) styp := c.table.type_to_str(typ)
for imethod in inter_sym.methods { for imethod in inter_sym.methods {
if method := typ_sym.find_method(imethod.name) { if method := typ_sym.find_method(imethod.name) {
@ -1632,9 +1634,10 @@ fn (mut c Checker) type_implements(typ table.Type, inter_typ table.Type, pos tok
} }
c.error("`$styp` doesn't implement method `$imethod.name`", pos) c.error("`$styp` doesn't implement method `$imethod.name`", pos)
} }
mut inter_info := inter_sym.info as table.Interface if mut inter_sym.info is table.Interface {
if typ !in inter_info.types && typ_sym.kind != .interface_ { if typ !in inter_sym.info.types && typ_sym.kind != .interface_ {
inter_info.types << typ inter_sym.info.types << typ
}
} }
return true return true
} }
@ -1686,7 +1689,7 @@ pub fn (mut c Checker) check_or_expr(or_expr ast.OrExpr, ret_type table.Type, ex
} }
last_stmt := or_expr.stmts[stmts_len - 1] last_stmt := or_expr.stmts[stmts_len - 1]
if ret_type != table.void_type { if ret_type != table.void_type {
match last_stmt { match union last_stmt {
ast.ExprStmt { ast.ExprStmt {
last_stmt_typ := c.expr(last_stmt.expr) last_stmt_typ := c.expr(last_stmt.expr)
type_fits := c.check_types(last_stmt_typ, ret_type) type_fits := c.check_types(last_stmt_typ, ret_type)
@ -1721,7 +1724,7 @@ pub fn (mut c Checker) check_or_expr(or_expr ast.OrExpr, ret_type table.Type, ex
} }
} }
} else { } else {
match last_stmt { match union last_stmt {
ast.ExprStmt { ast.ExprStmt {
if last_stmt.typ == table.void_type { if last_stmt.typ == table.void_type {
return return
@ -2141,9 +2144,9 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) {
ident_var_info.typ = left_type ident_var_info.typ = left_type
left.info = ident_var_info left.info = ident_var_info
if left_type != 0 { if left_type != 0 {
match mut left.obj as v { match union mut left.obj {
ast.Var { v.typ = left_type } ast.Var { left.obj.typ = left_type }
ast.GlobalField { v.typ = left_type } ast.GlobalField { left.obj.typ = left_type }
else {} else {}
} }
/* /*
@ -2444,7 +2447,7 @@ fn (mut c Checker) stmt(node ast.Stmt) {
eprintln('checking file: ${c.file.path:-30} | stmt pos: ${stmt_pos.str():-45} | stmt') eprintln('checking file: ${c.file.path:-30} | stmt pos: ${stmt_pos.str():-45} | stmt')
} }
// c.expected_type = table.void_type // c.expected_type = table.void_type
match mut node { match union mut node {
ast.AssertStmt { ast.AssertStmt {
cur_exp_typ := c.expected_type cur_exp_typ := c.expected_type
assert_type := c.expr(node.expr) assert_type := c.expr(node.expr)
@ -3071,9 +3074,9 @@ pub fn (mut c Checker) cast_expr(mut node ast.CastExpr) table.Type {
c.error('cannot cast `$from_type_sym.source_name` to `$to_type_sym.source_name`', c.error('cannot cast `$from_type_sym.source_name` to `$to_type_sym.source_name`',
node.pos) node.pos)
} }
} else if to_type_sym.info is table.Alias as alias_info { } else if mut to_type_sym.info is table.Alias {
if !c.check_types(node.expr_type, alias_info.parent_type) { if !c.check_types(node.expr_type, to_type_sym.info.parent_type) {
parent_type_sym := c.table.get_type_symbol(alias_info.parent_type) parent_type_sym := c.table.get_type_symbol(to_type_sym.info.parent_type)
c.error('cannot convert type `$from_type_sym.source_name` to `$to_type_sym.source_name` (alias to `$parent_type_sym.source_name`)', c.error('cannot convert type `$from_type_sym.source_name` to `$to_type_sym.source_name` (alias to `$parent_type_sym.source_name`)',
node.pos) node.pos)
} }
@ -3217,14 +3220,14 @@ pub fn (mut c Checker) ident(mut ident ast.Ident) table.Type {
c.error('`mut` not allowed with `=` (use `:=` to declare a variable)', ident.pos) c.error('`mut` not allowed with `=` (use `:=` to declare a variable)', ident.pos)
} }
start_scope := c.file.scope.innermost(ident.pos.pos) start_scope := c.file.scope.innermost(ident.pos.pos)
if obj1 := start_scope.find(ident.name) { if obj := start_scope.find(ident.name) {
match mut obj1 as obj { match union mut obj {
ast.GlobalField { ast.GlobalField {
ident.kind = .global ident.kind = .global
ident.info = ast.IdentVar{ ident.info = ast.IdentVar{
typ: obj.typ typ: obj.typ
} }
ident.obj = obj1 ident.obj = obj
return obj.typ return obj.typ
} }
ast.Var { ast.Var {
@ -3269,7 +3272,7 @@ pub fn (mut c Checker) ident(mut ident ast.Ident) table.Type {
if !is_sum_type_cast { if !is_sum_type_cast {
obj.typ = typ obj.typ = typ
} }
ident.obj = obj1 ident.obj = obj
// unwrap optional (`println(x)`) // unwrap optional (`println(x)`)
if is_optional { if is_optional {
return typ.clear_flag(.optional) return typ.clear_flag(.optional)
@ -3284,8 +3287,8 @@ pub fn (mut c Checker) ident(mut ident ast.Ident) table.Type {
if !name.contains('.') && ident.mod != 'builtin' { if !name.contains('.') && ident.mod != 'builtin' {
name = '${ident.mod}.$ident.name' name = '${ident.mod}.$ident.name'
} }
if obj1 := c.file.global_scope.find(name) { if obj := c.file.global_scope.find(name) {
match mut obj1 as obj { match union mut obj {
ast.ConstField { ast.ConstField {
mut typ := obj.typ mut typ := obj.typ
if typ == 0 { if typ == 0 {
@ -3297,7 +3300,7 @@ pub fn (mut c Checker) ident(mut ident ast.Ident) table.Type {
typ: typ typ: typ
} }
obj.typ = typ obj.typ = typ
ident.obj = obj1 ident.obj = obj
return typ return typ
} }
else {} else {}
@ -3398,7 +3401,8 @@ pub fn (mut c Checker) match_expr(mut node ast.MatchExpr) table.Type {
} }
// If the last statement is an expression, return its type // If the last statement is an expression, return its type
if branch.stmts.len > 0 { if branch.stmts.len > 0 {
match mut branch.stmts[branch.stmts.len - 1] as stmt { mut stmt := branch.stmts[branch.stmts.len - 1]
match union mut stmt {
ast.ExprStmt { ast.ExprStmt {
ret_type = c.expr(stmt.expr) ret_type = c.expr(stmt.expr)
stmt.typ = ret_type stmt.typ = ret_type
@ -3513,8 +3517,8 @@ fn (mut c Checker) match_exprs(mut node ast.MatchExpr, type_sym table.TypeSymbol
// c.type_implements(expr_type, c.expected_type, expr.position()) // c.type_implements(expr_type, c.expected_type, expr.position())
expr_pos := expr.position() expr_pos := expr.position()
c.type_implements(expr_type, c.expected_type, expr_pos) c.type_implements(expr_type, c.expected_type, expr_pos)
} else if cond_type_sym.info is table.UnionSumType as info { } else if mut cond_type_sym.info is table.UnionSumType {
if expr_type !in info.variants { if expr_type !in cond_type_sym.info.variants {
expr_str := c.table.type_to_str(expr_type) expr_str := c.table.type_to_str(expr_type)
expect_str := c.table.type_to_str(c.expected_type) expect_str := c.table.type_to_str(c.expected_type)
c.error('`$expect_str` has no variant `$expr_str`', expr.position()) c.error('`$expect_str` has no variant `$expr_str`', expr.position())
@ -3616,9 +3620,9 @@ fn (mut c Checker) match_exprs(mut node ast.MatchExpr, type_sym table.TypeSymbol
// by listing all variants or values // by listing all variants or values
mut is_exhaustive := true mut is_exhaustive := true
mut unhandled := []string{} mut unhandled := []string{}
match type_sym.info as info { match union mut type_sym.info {
table.SumType { table.SumType {
for v in 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)
if v_str !in branch_exprs { if v_str !in branch_exprs {
is_exhaustive = false is_exhaustive = false
@ -3627,7 +3631,7 @@ fn (mut c Checker) match_exprs(mut node ast.MatchExpr, type_sym table.TypeSymbol
} }
} }
table.UnionSumType { table.UnionSumType {
for v in 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)
if v_str !in branch_exprs { if v_str !in branch_exprs {
is_exhaustive = false is_exhaustive = false
@ -3637,7 +3641,7 @@ fn (mut c Checker) match_exprs(mut node ast.MatchExpr, type_sym table.TypeSymbol
} }
// //
table.Enum { table.Enum {
for v in info.vals { for v in type_sym.info.vals {
if v !in branch_exprs { if v !in branch_exprs {
is_exhaustive = false is_exhaustive = false
unhandled << '`.$v`' unhandled << '`.$v`'
@ -3690,27 +3694,27 @@ pub fn (mut c Checker) select_expr(mut node ast.SelectExpr) table.Type {
node.expected_type = c.expected_type node.expected_type = c.expected_type
for branch in node.branches { for branch in node.branches {
c.stmt(branch.stmt) c.stmt(branch.stmt)
match branch.stmt as stmt { match union branch.stmt {
ast.ExprStmt { ast.ExprStmt {
if branch.is_timeout { if branch.is_timeout {
if !stmt.typ.is_int() { if !branch.stmt.typ.is_int() {
tsym := c.table.get_type_symbol(stmt.typ) tsym := c.table.get_type_symbol(branch.stmt.typ)
c.error('invalid type `$tsym.name` for timeout - expected integer type aka `time.Duration`', c.error('invalid type `$tsym.name` for timeout - expected integer type aka `time.Duration`',
stmt.pos) branch.stmt.pos)
} }
} else { } else {
if stmt.expr is ast.InfixExpr { if branch.stmt.expr is ast.InfixExpr {
if stmt.expr.left !is ast.Ident && if branch.stmt.expr.left !is ast.Ident &&
stmt.expr.left !is ast.SelectorExpr && stmt.expr.left !is ast.IndexExpr { branch.stmt.expr.left !is ast.SelectorExpr && branch.stmt.expr.left !is ast.IndexExpr {
c.error('channel in `select` key must be predefined', stmt.expr.left.position()) c.error('channel in `select` key must be predefined', branch.stmt.expr.left.position())
} }
} else { } else {
c.error('invalid expression for `select` key', stmt.expr.position()) c.error('invalid expression for `select` key', branch.stmt.expr.position())
} }
} }
} }
ast.AssignStmt { ast.AssignStmt {
expr := stmt.right[0] expr := branch.stmt.right[0]
match union expr { match union expr {
ast.PrefixExpr { ast.PrefixExpr {
if expr.right !is ast.Ident && if expr.right !is ast.Ident &&
@ -3723,7 +3727,7 @@ pub fn (mut c Checker) select_expr(mut node ast.SelectExpr) table.Type {
} }
} }
else { else {
c.error('`<-` receive expression expected', stmt.right[0].position()) c.error('`<-` receive expression expected', branch.stmt.right[0].position())
} }
} }
} }
@ -3742,8 +3746,8 @@ pub fn (mut c Checker) lock_expr(mut node ast.LockExpr) table.Type {
for i in 0 .. node.lockeds.len { for i in 0 .. node.lockeds.len {
c.ident(mut node.lockeds[i]) c.ident(mut node.lockeds[i])
id := node.lockeds[i] id := node.lockeds[i]
if id.obj is ast.Var as v { if mut id.obj is ast.Var {
if v.typ.share() != .shared_t { if id.obj.typ.share() != .shared_t {
c.error('`$id.name` must be declared `shared` to be locked', id.pos) c.error('`$id.name` must be declared `shared` to be locked', id.pos)
} }
} else { } else {

View File

@ -122,7 +122,7 @@ pub fn (mut d Doc) stmt(stmt ast.Stmt, filename string) ?DocNode {
if node.name.len == 0 && node.comment.len == 0 && node.content.len == 0 { if node.name.len == 0 && node.comment.len == 0 && node.content.len == 0 {
return error('empty stmt') return error('empty stmt')
} }
match stmt { match union stmt {
ast.ConstDecl { ast.ConstDecl {
node.kind = .const_group node.kind = .const_group
node.parent_name = 'Constants' node.parent_name = 'Constants'

View File

@ -77,7 +77,7 @@ fn (mut d Doc) convert_pos(filename string, pos token.Position) DocPos {
} }
pub fn (mut d Doc) stmt_signature(stmt ast.Stmt) string { pub fn (mut d Doc) stmt_signature(stmt ast.Stmt) string {
match stmt { match union stmt {
ast.Module { ast.Module {
return 'module $stmt.name' return 'module $stmt.name'
} }
@ -93,9 +93,9 @@ pub fn (mut d Doc) stmt_signature(stmt ast.Stmt) string {
} }
pub fn (d Doc) stmt_name(stmt ast.Stmt) string { pub fn (d Doc) stmt_name(stmt ast.Stmt) string {
match 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 stmt { ast.TypeDecl { match union stmt {
ast.SumTypeDecl, ast.FnTypeDecl, ast.AliasTypeDecl, ast.UnionSumTypeDecl { return stmt.name } ast.SumTypeDecl, ast.FnTypeDecl, ast.AliasTypeDecl, ast.UnionSumTypeDecl { return stmt.name }
} } } }
ast.ConstDecl { return '' } // leave it blank ast.ConstDecl { return '' } // leave it blank

View File

@ -8,7 +8,7 @@ import v.checker
import v.table import v.table
import v.pref import v.pref
pub type Object = int | string pub __type Object = int | string
pub struct Eval { pub struct Eval {
mut: mut:
@ -33,14 +33,14 @@ pub fn (mut e Eval) eval(file ast.File, table &table.Table) string {
} }
fn print_object(o Object) { fn print_object(o Object) {
match o { match union o {
int { println(o) } int { println(o) }
else { println('unknown object') } else { println('unknown object') }
} }
} }
pub fn (o Object) str() string { pub fn (o Object) str() string {
match o { match union o {
int { return o.str() } int { return o.str() }
else { println('unknown object') } else { println('unknown object') }
} }

View File

@ -245,7 +245,7 @@ pub fn (mut f Fmt) stmt(node ast.Stmt) {
if f.is_debug { if f.is_debug {
eprintln('stmt: ${node.position():-42} | node: ${typeof(node):-20}') eprintln('stmt: ${node.position():-42} | node: ${typeof(node):-20}')
} }
match node { match union node {
ast.AssignStmt { ast.AssignStmt {
f.comments(node.comments, {}) f.comments(node.comments, {})
for i, left in node.left { for i, left in node.left {
@ -480,18 +480,18 @@ pub fn (mut f Fmt) stmt(node ast.Stmt) {
f.writeln('}') f.writeln('}')
} }
ast.StructDecl { ast.StructDecl {
f.struct_decl(it) f.struct_decl(node)
} }
ast.TypeDecl { ast.TypeDecl {
// already handled in f.imports // already handled in f.imports
f.type_decl(it) f.type_decl(node)
} }
} }
} }
pub fn (mut f Fmt) type_decl(node ast.TypeDecl) { pub fn (mut f Fmt) type_decl(node ast.TypeDecl) {
mut comments := []ast.Comment{} mut comments := []ast.Comment{}
match node { match union node {
ast.AliasTypeDecl { ast.AliasTypeDecl {
if node.is_pub { if node.is_pub {
f.write('pub ') f.write('pub ')
@ -962,8 +962,8 @@ pub fn (mut f Fmt) expr(node ast.Expr) {
f.write('> ') f.write('> ')
} }
f.single_line_if = true f.single_line_if = true
match branch.stmt as stmt { match branch.stmt {
ast.ExprStmt { f.expr(stmt.expr) } ast.ExprStmt { f.expr(branch.stmt.expr) }
else { f.stmt(branch.stmt) } else { f.stmt(branch.stmt) }
} }
f.single_line_if = false f.single_line_if = false
@ -1691,7 +1691,7 @@ fn (mut f Fmt) write_language_prefix(lang table.Language) {
} }
fn stmt_is_single_line(stmt ast.Stmt) bool { fn stmt_is_single_line(stmt ast.Stmt) bool {
match stmt { match union stmt {
ast.ExprStmt { return expr_is_single_line(stmt.expr) } ast.ExprStmt { return expr_is_single_line(stmt.expr) }
ast.Return { return true } ast.Return { return true }
ast.AssignStmt { return true } ast.AssignStmt { return true }

View File

@ -10,9 +10,9 @@ import v.util
fn (mut g Gen) gen_str_for_type_with_styp(typ table.Type, styp string) string { fn (mut g Gen) gen_str_for_type_with_styp(typ table.Type, styp string) string {
mut sym := g.table.get_type_symbol(g.unwrap_generic(typ)) mut sym := g.table.get_type_symbol(g.unwrap_generic(typ))
mut str_fn_name := styp_to_str_fn_name(styp) mut str_fn_name := styp_to_str_fn_name(styp)
if sym.info is table.Alias as sym_info { if mut sym.info is table.Alias {
if sym_info.is_import { if sym.info.is_import {
sym = g.table.get_type_symbol((sym.info as table.Alias).parent_type) sym = g.table.get_type_symbol(sym.info.parent_type)
str_fn_name = styp_to_str_fn_name(sym.name.replace('.', '__')) str_fn_name = styp_to_str_fn_name(sym.name.replace('.', '__'))
} }
} }
@ -47,37 +47,37 @@ fn (mut g Gen) gen_str_for_type_with_styp(typ table.Type, styp string) string {
eprintln('> gen_str_for_type_with_styp: |typ: ${typ:5}, ${sym.name:20}|has_str: ${sym_has_str_method:5}|expects_ptr: ${str_method_expects_ptr:5}|nr_args: ${str_nr_args:1}|fn_name: ${str_fn_name:20}') eprintln('> gen_str_for_type_with_styp: |typ: ${typ:5}, ${sym.name:20}|has_str: ${sym_has_str_method:5}|expects_ptr: ${str_method_expects_ptr:5}|nr_args: ${str_nr_args:1}|fn_name: ${str_fn_name:20}')
} }
g.str_types << already_generated_key g.str_types << already_generated_key
match sym.info as sym_info { match union mut sym.info {
table.Alias { table.Alias {
if sym_info.is_import { if sym.info.is_import {
g.gen_str_default(sym, styp, str_fn_name) g.gen_str_default(sym, styp, str_fn_name)
} else { } else {
g.gen_str_for_alias(sym_info, styp, str_fn_name) g.gen_str_for_alias(sym.info, styp, str_fn_name)
} }
} }
table.Array { table.Array {
g.gen_str_for_array(it, styp, str_fn_name) g.gen_str_for_array(sym.info, styp, str_fn_name)
} }
table.ArrayFixed { table.ArrayFixed {
g.gen_str_for_array_fixed(it, styp, str_fn_name) g.gen_str_for_array_fixed(sym.info, styp, str_fn_name)
} }
table.Enum { table.Enum {
g.gen_str_for_enum(it, styp, str_fn_name) g.gen_str_for_enum(sym.info, styp, str_fn_name)
} }
table.Struct { table.Struct {
g.gen_str_for_struct(it, styp, str_fn_name) g.gen_str_for_struct(sym.info, styp, str_fn_name)
} }
table.Map { table.Map {
g.gen_str_for_map(it, styp, str_fn_name) g.gen_str_for_map(sym.info, styp, str_fn_name)
} }
table.MultiReturn { table.MultiReturn {
g.gen_str_for_multi_return(it, styp, str_fn_name) g.gen_str_for_multi_return(sym.info, styp, str_fn_name)
} }
table.SumType { table.SumType {
g.gen_str_for_sum_type(it, styp, str_fn_name) g.gen_str_for_sum_type(sym.info, styp, str_fn_name)
} }
table.UnionSumType { table.UnionSumType {
g.gen_str_for_union_sum_type(it, styp, str_fn_name) g.gen_str_for_union_sum_type(sym.info, styp, str_fn_name)
} }
else { else {
verror("could not generate string method $str_fn_name for type \'$styp\'") verror("could not generate string method $str_fn_name for type \'$styp\'")
@ -120,9 +120,9 @@ fn (mut g Gen) gen_str_for_alias(info table.Alias, styp string, str_fn_name stri
fn (mut g Gen) gen_str_for_array(info table.Array, styp string, str_fn_name string) { fn (mut g Gen) gen_str_for_array(info table.Array, styp string, str_fn_name string) {
mut typ := info.elem_type mut typ := info.elem_type
mut sym := g.table.get_type_symbol(info.elem_type) mut sym := g.table.get_type_symbol(info.elem_type)
if sym.info is table.Alias as alias_info { if mut sym.info is table.Alias {
typ = alias_info.parent_type typ = sym.info.parent_type
sym = g.table.get_type_symbol(alias_info.parent_type) sym = g.table.get_type_symbol(typ)
} }
field_styp := g.typ(typ) field_styp := g.typ(typ)
is_elem_ptr := typ.is_ptr() is_elem_ptr := typ.is_ptr()
@ -188,9 +188,9 @@ fn (mut g Gen) gen_str_for_array(info table.Array, styp string, str_fn_name stri
fn (mut g Gen) gen_str_for_array_fixed(info table.ArrayFixed, styp string, str_fn_name string) { fn (mut g Gen) gen_str_for_array_fixed(info table.ArrayFixed, styp string, str_fn_name string) {
mut typ := info.elem_type mut typ := info.elem_type
mut sym := g.table.get_type_symbol(info.elem_type) mut sym := g.table.get_type_symbol(info.elem_type)
if sym.info is table.Alias as alias_info { if mut sym.info is table.Alias {
typ = alias_info.parent_type typ = sym.info.parent_type
sym = g.table.get_type_symbol(alias_info.parent_type) sym = g.table.get_type_symbol(typ)
} }
field_styp := g.typ(typ) field_styp := g.typ(typ)
is_elem_ptr := typ.is_ptr() is_elem_ptr := typ.is_ptr()

View File

@ -801,7 +801,7 @@ fn (mut g Gen) stmt(node ast.Stmt) {
} }
// println('cgen.stmt()') // println('cgen.stmt()')
// g.writeln('//// stmt start') // g.writeln('//// stmt start')
match node { match union node {
ast.AssertStmt { ast.AssertStmt {
g.write_v_source_line_info(node.pos) g.write_v_source_line_info(node.pos)
g.gen_assert_stmt(node) g.gen_assert_stmt(node)
@ -843,7 +843,7 @@ fn (mut g Gen) stmt(node ast.Stmt) {
g.comp_for(node) g.comp_for(node)
} }
ast.DeferStmt { ast.DeferStmt {
mut defer_stmt := *node mut defer_stmt := node
defer_stmt.ifdef = g.defer_ifdef defer_stmt.ifdef = g.defer_ifdef
g.defer_stmts << defer_stmt g.defer_stmts << defer_stmt
} }
@ -914,7 +914,7 @@ fn (mut g Gen) stmt(node ast.Stmt) {
} }
} }
keep_fn_decl := g.fn_decl keep_fn_decl := g.fn_decl
g.fn_decl = node g.fn_decl = &node
if node.name == 'main.main' { if node.name == 'main.main' {
g.has_main = true g.has_main = true
} }
@ -2098,25 +2098,24 @@ fn (mut g Gen) autofree_scope_vars2(scope &ast.Scope, start_pos int, end_pos int
return return
} }
for _, obj in scope.objects { for _, obj in scope.objects {
match obj { match union obj {
ast.Var { ast.Var {
g.writeln('// var $obj.name pos=$obj.pos.pos') g.writeln('// var $obj.name pos=$obj.pos.pos')
// if var.typ == 0 { // if var.typ == 0 {
// // TODO why 0? // // TODO why 0?
// continue // continue
// } // }
v := *obj
// if v.pos.pos > end_pos { // if v.pos.pos > end_pos {
if v.pos.pos > end_pos || (v.pos.pos < start_pos && v.pos.line_nr == line_nr) { if obj.pos.pos > end_pos || (obj.pos.pos < start_pos && obj.pos.line_nr == line_nr) {
// Do not free vars that were declared after this scope // Do not free vars that were declared after this scope
continue continue
} }
is_optional := v.typ.has_flag(.optional) is_optional := obj.typ.has_flag(.optional)
if is_optional { if is_optional {
// TODO: free optionals // TODO: free optionals
continue continue
} }
g.autofree_variable(v) g.autofree_variable(obj)
} }
else {} else {}
} }
@ -2573,8 +2572,8 @@ fn (mut g Gen) expr(node ast.Expr) {
if i != 0 { if i != 0 {
sum_type_deref_field += ').' sum_type_deref_field += ').'
} }
if cast_sym.info is table.Aggregate as sym_info { if mut cast_sym.info is table.Aggregate {
sum_type_deref_field += '_${sym_info.types[g.aggregate_type_idx]}' sum_type_deref_field += '_${cast_sym.info.types[g.aggregate_type_idx]}'
} else { } else {
sum_type_deref_field += '_$typ' sum_type_deref_field += '_$typ'
} }
@ -3253,10 +3252,10 @@ fn (mut g Gen) select_expr(node ast.SelectExpr) {
exception_branch = j exception_branch = j
timeout_expr = (branch.stmt as ast.ExprStmt).expr timeout_expr = (branch.stmt as ast.ExprStmt).expr
} else { } else {
match branch.stmt as stmt { match union branch.stmt {
ast.ExprStmt { ast.ExprStmt {
// send expression // send expression
expr := stmt.expr as ast.InfixExpr expr := branch.stmt.expr as ast.InfixExpr
channels << expr.left channels << expr.left
if expr.right is ast.Ident || if expr.right is ast.Ident ||
expr.right is ast.IndexExpr || expr.right is ast.SelectorExpr || expr.right is ast.StructInit { expr.right is ast.IndexExpr || expr.right is ast.SelectorExpr || expr.right is ast.StructInit {
@ -3275,15 +3274,16 @@ fn (mut g Gen) select_expr(node ast.SelectExpr) {
is_push << true is_push << true
} }
ast.AssignStmt { ast.AssignStmt {
rec_expr := stmt.right[0] as ast.PrefixExpr rec_expr := branch.stmt.right[0] as ast.PrefixExpr
channels << rec_expr.right channels << rec_expr.right
is_push << false is_push << false
// create tmp unless the object with *exactly* the type we need exists already // create tmp unless the object with *exactly* the type we need exists already
if stmt.op == .decl_assign || stmt.right_types[0] != stmt.left_types[0] { if branch.stmt.op == .decl_assign ||
branch.stmt.right_types[0] != branch.stmt.left_types[0] {
tmp_obj := g.new_tmp_var() tmp_obj := g.new_tmp_var()
tmp_objs << tmp_obj tmp_objs << tmp_obj
el_stype := g.typ(stmt.right_types[0]) el_stype := g.typ(branch.stmt.right_types[0])
elem_types << if stmt.op == .decl_assign { elem_types << if branch.stmt.op == .decl_assign {
el_stype + ' ' el_stype + ' '
} else { } else {
'' ''
@ -3293,7 +3293,7 @@ fn (mut g Gen) select_expr(node ast.SelectExpr) {
tmp_objs << '' tmp_objs << ''
elem_types << '' elem_types << ''
} }
objs << stmt.left[0] objs << branch.stmt.left[0]
} }
else {} else {}
} }
@ -3418,8 +3418,8 @@ fn (mut g Gen) ident(node ast.Ident) {
if i == 0 { if i == 0 {
g.write(name) g.write(name)
} }
if cast_sym.info is table.Aggregate as sym_info { if mut cast_sym.info is table.Aggregate {
g.write('._${sym_info.types[g.aggregate_type_idx]}') g.write('._${cast_sym.info.types[g.aggregate_type_idx]}')
} else { } else {
g.write('._$typ') g.write('._$typ')
} }
@ -3447,16 +3447,17 @@ fn (mut g Gen) should_write_asterisk_due_to_match_sumtype(expr ast.Expr) bool {
fn (mut g Gen) match_sumtype_has_no_struct_and_contains(node ast.Ident) bool { fn (mut g Gen) match_sumtype_has_no_struct_and_contains(node ast.Ident) bool {
for i, expr in g.match_sumtype_exprs { for i, expr in g.match_sumtype_exprs {
if expr is ast.Ident && node.name == (expr as ast.Ident).name { if expr is ast.Ident && node.name == (expr as ast.Ident).name {
match g.match_sumtype_syms[i].info as sumtype { info := g.match_sumtype_syms[i].info
match union info {
table.SumType { table.SumType {
for typ in sumtype.variants { for typ in info.variants {
if g.table.get_type_symbol(typ).kind == .struct_ { if g.table.get_type_symbol(typ).kind == .struct_ {
return false return false
} }
} }
} }
table.UnionSumType { table.UnionSumType {
for typ in sumtype.variants { for typ in info.variants {
if g.table.get_type_symbol(typ).kind == .struct_ { if g.table.get_type_symbol(typ).kind == .struct_ {
return false return false
} }
@ -3500,9 +3501,11 @@ fn (mut g Gen) if_expr(node ast.IfExpr) {
// easier to use a temp var, than do C tricks with commas, introduce special vars etc // easier to use a temp var, than do C tricks with commas, introduce special vars etc
// (as it used to be done). // (as it used to be done).
// Always use this in -autofree, since ?: can have tmp expressions that have to be freed. // Always use this in -autofree, since ?: can have tmp expressions that have to be freed.
first_branch := node.branches[0]
needs_tmp_var := node.is_expr && needs_tmp_var := node.is_expr &&
(g.pref.autofree || (g.pref.experimental && (g.pref.autofree || (g.pref.experimental &&
(node.branches[0].stmts.len > 1 || node.branches[0].stmts[0] is ast.IfExpr))) (first_branch.stmts.len > 1 || (first_branch.stmts[0] is ast.ExprStmt &&
(first_branch.stmts[0] as ast.ExprStmt).expr is ast.IfExpr))))
/* /*
needs_tmp_var := node.is_expr && needs_tmp_var := node.is_expr &&
(g.pref.autofree || g.pref.experimental) && (g.pref.autofree || g.pref.experimental) &&
@ -4224,8 +4227,8 @@ fn (mut g Gen) struct_init(struct_init ast.StructInit) {
mut initialized := false mut initialized := false
for i, field in struct_init.fields { for i, field in struct_init.fields {
inited_fields[field.name] = i inited_fields[field.name] = i
if sym.info is table.Struct as struct_info { if mut sym.info is table.Struct {
equal_fields := struct_info.fields.filter(it.name == field.name) equal_fields := sym.info.fields.filter(it.name == field.name)
if equal_fields.len == 0 { if equal_fields.len == 0 {
continue continue
} }
@ -4276,8 +4279,8 @@ fn (mut g Gen) struct_init(struct_init ast.StructInit) {
// g.zero_struct_fields(info, inited_fields) // g.zero_struct_fields(info, inited_fields)
// nr_fields = info.fields.len // nr_fields = info.fields.len
for field in info.fields { for field in info.fields {
if sym.info is table.Struct as struct_info { if mut sym.info is table.Struct {
equal_fields := struct_info.fields.filter(it.name == field.name) equal_fields := sym.info.fields.filter(it.name == field.name)
if equal_fields.len == 0 { if equal_fields.len == 0 {
continue continue
} }
@ -4590,9 +4593,9 @@ fn (mut g Gen) write_types(types []table.TypeSymbol) {
} }
// sym := g.table.get_type_symbol(typ) // sym := g.table.get_type_symbol(typ)
mut name := util.no_dots(typ.name) mut name := util.no_dots(typ.name)
match typ.info as info { match union mut typ.info {
table.Struct { table.Struct {
if info.generic_types.len > 0 { if typ.info.generic_types.len > 0 {
continue continue
} }
// TODO: yuck // TODO: yuck
@ -4602,13 +4605,13 @@ fn (mut g Gen) write_types(types []table.TypeSymbol) {
} }
// TODO avoid buffer manip // TODO avoid buffer manip
start_pos := g.type_definitions.len start_pos := g.type_definitions.len
if info.is_union { if typ.info.is_union {
g.type_definitions.writeln('union $name {') g.type_definitions.writeln('union $name {')
} else { } else {
g.type_definitions.writeln('struct $name {') g.type_definitions.writeln('struct $name {')
} }
if info.fields.len > 0 { if typ.info.fields.len > 0 {
for field in info.fields.filter(it.embed_alias_for == '') { for field in typ.info.fields.filter(it.embed_alias_for == '') {
// Some of these structs may want to contain // Some of these structs may want to contain
// optionals that may not be defined at this point // optionals that may not be defined at this point
// if this is the case then we are going to // if this is the case then we are going to
@ -4642,7 +4645,7 @@ fn (mut g Gen) write_types(types []table.TypeSymbol) {
table.SumType { table.SumType {
g.type_definitions.writeln('') g.type_definitions.writeln('')
g.type_definitions.writeln('// Sum type $name = ') g.type_definitions.writeln('// Sum type $name = ')
for sv in it.variants { for sv in typ.info.variants {
g.type_definitions.writeln('// | ${sv:4d} = ${g.typ(sv):-20s}') g.type_definitions.writeln('// | ${sv:4d} = ${g.typ(sv):-20s}')
} }
g.type_definitions.writeln('typedef struct {') g.type_definitions.writeln('typedef struct {')
@ -4655,12 +4658,12 @@ fn (mut g Gen) write_types(types []table.TypeSymbol) {
g.typedefs.writeln('typedef struct $name $name;') g.typedefs.writeln('typedef struct $name $name;')
g.type_definitions.writeln('') g.type_definitions.writeln('')
g.type_definitions.writeln('// Union sum type $name = ') g.type_definitions.writeln('// Union sum type $name = ')
for variant in it.variants { for variant in typ.info.variants {
g.type_definitions.writeln('// | ${variant:4d} = ${g.typ(variant.idx()):-20s}') g.type_definitions.writeln('// | ${variant:4d} = ${g.typ(variant.idx()):-20s}')
} }
g.type_definitions.writeln('struct $name {') g.type_definitions.writeln('struct $name {')
g.type_definitions.writeln(' union {') g.type_definitions.writeln(' union {')
for variant in it.variants { for variant in typ.info.variants {
g.type_definitions.writeln(' ${g.typ(variant.to_ptr())} _$variant.idx();') g.type_definitions.writeln(' ${g.typ(variant.to_ptr())} _$variant.idx();')
} }
g.type_definitions.writeln(' };') g.type_definitions.writeln(' };')
@ -4702,19 +4705,18 @@ fn (g &Gen) sort_structs(typesa []table.TypeSymbol) []table.TypeSymbol {
} }
// create list of deps // create list of deps
mut field_deps := []string{} mut field_deps := []string{}
match t.info { match union mut t.info {
table.ArrayFixed { table.ArrayFixed {
dep := g.table.get_type_symbol(it.elem_type).name dep := g.table.get_type_symbol(t.info.elem_type).name
if dep in type_names { if dep in type_names {
field_deps << dep field_deps << dep
} }
} }
table.Struct { table.Struct {
info := t.info as table.Struct
// if info.is_interface { // if info.is_interface {
// continue // continue
// } // }
for field in info.fields { for field in t.info.fields {
dep := g.table.get_type_symbol(field.typ).name dep := g.table.get_type_symbol(field.typ).name
// skip if not in types list or already in deps // skip if not in types list or already in deps
if dep !in type_names || dep in field_deps || field.typ.is_ptr() { if dep !in type_names || dep in field_deps || field.typ.is_ptr() {
@ -4747,11 +4749,11 @@ fn (g &Gen) sort_structs(typesa []table.TypeSymbol) []table.TypeSymbol {
fn (mut g Gen) gen_expr_to_string(expr ast.Expr, etype table.Type) ?bool { fn (mut g Gen) gen_expr_to_string(expr ast.Expr, etype table.Type) ?bool {
mut typ := etype mut typ := etype
mut sym := g.table.get_type_symbol(typ) mut sym := g.table.get_type_symbol(typ)
if sym.info is table.Alias as alias_info { if mut sym.info is table.Alias {
parent_sym := g.table.get_type_symbol(alias_info.parent_type) parent_sym := g.table.get_type_symbol(sym.info.parent_type)
if parent_sym.has_method('str') { if parent_sym.has_method('str') {
typ = sym.info.parent_type
sym = parent_sym sym = parent_sym
typ = alias_info.parent_type
} }
} }
sym_has_str_method, str_method_expects_ptr, _ := sym.str_method_info() sym_has_str_method, str_method_expects_ptr, _ := sym.str_method_info()

View File

@ -549,9 +549,9 @@ fn (mut g Gen) fn_call(node ast.CallExpr) {
g.checker_bug('print arg.typ is 0', node.pos) g.checker_bug('print arg.typ is 0', node.pos)
} }
mut sym := g.table.get_type_symbol(typ) mut sym := g.table.get_type_symbol(typ)
if sym.info is table.Alias as alias_info { if mut sym.info is table.Alias {
typ = alias_info.parent_type typ = sym.info.parent_type
sym = g.table.get_type_symbol(alias_info.parent_type) sym = g.table.get_type_symbol(typ)
} }
// check if alias parent also not a string // check if alias parent also not a string
if typ != table.string_type { if typ != table.string_type {
@ -685,7 +685,7 @@ fn (mut g Gen) autofree_call_pregen(node ast.CallExpr) {
// instead of `string t = ...`, and we need to mark this variable as unused, // instead of `string t = ...`, and we need to mark this variable as unused,
// so that it's freed after the call. (Used tmp arg vars are not freed to avoid double frees). // so that it's freed after the call. (Used tmp arg vars are not freed to avoid double frees).
if x := scope.find(t) { if x := scope.find(t) {
match mut x { match union mut x {
ast.Var { x.is_used = false } ast.Var { x.is_used = false }
else {} else {}
} }
@ -740,27 +740,26 @@ fn (mut g Gen) autofree_call_postgen(node_pos int) {
// g.write('/* postgen */') // g.write('/* postgen */')
scope := g.file.scope.innermost(node_pos) scope := g.file.scope.innermost(node_pos)
for _, obj in scope.objects { for _, obj in scope.objects {
match mut obj { match union mut obj {
ast.Var { ast.Var {
// if var.typ == 0 { // if var.typ == 0 {
// // TODO why 0? // // TODO why 0?
// continue // continue
// } // }
v := *obj is_optional := obj.typ.has_flag(.optional)
is_optional := v.typ.has_flag(.optional)
if is_optional { if is_optional {
// TODO: free optionals // TODO: free optionals
continue continue
} }
if !v.is_autofree_tmp { if !obj.is_autofree_tmp {
continue continue
} }
if v.is_used { if obj.is_used {
// this means this tmp expr var has already been freed // this means this tmp expr var has already been freed
continue continue
} }
obj.is_used = true obj.is_used = true
g.autofree_variable(v) g.autofree_variable(obj)
// g.nr_vars_to_free-- // g.nr_vars_to_free--
} }
else {} else {}

View File

@ -164,7 +164,7 @@ pub fn (mut g JsGen) push_pub_var(s string) {
pub fn (mut g JsGen) find_class_methods(stmts []ast.Stmt) { pub fn (mut g JsGen) find_class_methods(stmts []ast.Stmt) {
for stmt in stmts { for stmt in stmts {
match stmt { match union stmt {
ast.FnDecl { ast.FnDecl {
if stmt.is_method { if stmt.is_method {
// Found struct method, store it to be generated along with the class. // Found struct method, store it to be generated along with the class.
@ -437,7 +437,7 @@ fn (mut g JsGen) stmts(stmts []ast.Stmt) {
fn (mut g JsGen) stmt(node ast.Stmt) { fn (mut g JsGen) stmt(node ast.Stmt) {
g.stmt_start_pos = g.out.len g.stmt_start_pos = g.out.len
match node { match union node {
ast.AssertStmt { ast.AssertStmt {
g.gen_assert_stmt(node) g.gen_assert_stmt(node)
} }
@ -456,7 +456,7 @@ fn (mut g JsGen) stmt(node ast.Stmt) {
g.gen_const_decl(node) g.gen_const_decl(node)
} }
ast.DeferStmt { ast.DeferStmt {
g.defer_stmts << *node g.defer_stmts << node
} }
ast.EnumDecl { ast.EnumDecl {
g.gen_enum_decl(node) g.gen_enum_decl(node)
@ -466,7 +466,7 @@ fn (mut g JsGen) stmt(node ast.Stmt) {
g.gen_expr_stmt(node) g.gen_expr_stmt(node)
} }
ast.FnDecl { ast.FnDecl {
g.fn_decl = node g.fn_decl = &node
g.gen_fn_decl(node) g.gen_fn_decl(node)
} }
ast.ForCStmt { ast.ForCStmt {

View File

@ -603,7 +603,7 @@ pub fn (mut g Gen) call_fn(node ast.CallExpr) {
} }
fn (mut g Gen) stmt(node ast.Stmt) { fn (mut g Gen) stmt(node ast.Stmt) {
match node { match union node {
ast.AssignStmt { ast.AssignStmt {
g.assign_stmt(node) g.assign_stmt(node)
} }

View File

@ -103,7 +103,7 @@ fn (mut p Parser) vweb() ast.ComptimeCall {
if obj is ast.Var { if obj is ast.Var {
mut v := obj mut v := obj
v.pos = stmt.body_pos v.pos = stmt.body_pos
tmpl_scope.register(v.name, *v) tmpl_scope.register(v.name, v)
// set the controller action var to used // set the controller action var to used
// if its unused in the template it will warn // if its unused in the template it will warn
v.is_used = true v.is_used = true

View File

@ -443,12 +443,12 @@ fn (mut p Parser) select_expr() ast.SelectExpr {
} }
p.inside_match = false p.inside_match = false
p.inside_select = false p.inside_select = false
match stmt { match union mut stmt {
ast.ExprStmt { ast.ExprStmt {
if !stmt.is_expr { if !stmt.is_expr {
p.error_with_pos('select: invalid expression', stmt.pos) p.error_with_pos('select: invalid expression', stmt.pos)
} else { } else {
match union stmt.expr { match union mut stmt.expr {
ast.InfixExpr { ast.InfixExpr {
if stmt.expr.op != .arrow { if stmt.expr.op != .arrow {
p.error_with_pos('select key: `<-` operator expected', p.error_with_pos('select key: `<-` operator expected',

View File

@ -608,18 +608,18 @@ pub fn (mut p Parser) stmt(is_top_level bool) ast.Stmt {
p.next() p.next()
if p.tok.kind == .key_for { if p.tok.kind == .key_for {
mut stmt := p.stmt(is_top_level) mut stmt := p.stmt(is_top_level)
match mut stmt { match union mut stmt {
ast.ForStmt { ast.ForStmt {
stmt.label = name stmt.label = name
return *stmt return stmt
} }
ast.ForInStmt { ast.ForInStmt {
stmt.label = name stmt.label = name
return *stmt return stmt
} }
ast.ForCStmt { ast.ForCStmt {
stmt.label = name stmt.label = name
return *stmt return stmt
} }
else { else {
assert false assert false
@ -2139,7 +2139,7 @@ fn (mut p Parser) rewind_scanner_to_current_token_in_new_mode() {
pub fn (mut p Parser) mark_var_as_used(varname string) bool { pub fn (mut p Parser) mark_var_as_used(varname string) bool {
if obj := p.scope.find(varname) { if obj := p.scope.find(varname) {
match mut obj { match union mut obj {
ast.Var { ast.Var {
obj.is_used = true obj.is_used = true
return true return true

View File

@ -263,12 +263,12 @@ pub fn (t &Table) struct_find_field(s &TypeSymbol, name string) ?Field {
// println('struct_find_field($s.name, $name) types.len=$t.types.len s.parent_idx=$s.parent_idx') // println('struct_find_field($s.name, $name) types.len=$t.types.len s.parent_idx=$s.parent_idx')
mut ts := s mut ts := s
for { for {
if ts.info is Struct as struct_info { if mut ts.info is Struct {
if field := struct_info.find_field(name) { if field := ts.info.find_field(name) {
return field return field
} }
} else if ts.info is Aggregate as agg_info { } else if mut ts.info is Aggregate {
if field := agg_info.find_field(name) { if field := ts.info.find_field(name) {
return field return field
} }
field := t.register_aggregate_field(mut ts, name) or { field := t.register_aggregate_field(mut ts, name) or {

View File

@ -15,8 +15,8 @@ import strings
pub type Type = int pub type Type = int
pub type TypeInfo = Aggregate | Alias | Array | ArrayFixed | Chan | Enum | FnType | GenericStructInst | pub __type TypeInfo = Aggregate | Alias | Array | ArrayFixed | Chan | Enum | FnType |
Interface | Map | MultiReturn | Struct | SumType | UnionSumType GenericStructInst | Interface | Map | MultiReturn | Struct | SumType | UnionSumType
pub enum Language { pub enum Language {
v v
@ -421,56 +421,56 @@ pub fn (t &TypeSymbol) str() string {
[inline] [inline]
pub fn (t &TypeSymbol) enum_info() Enum { pub fn (t &TypeSymbol) enum_info() Enum {
match t.info { match union mut t.info {
Enum { return *it } Enum { return t.info }
else { panic('TypeSymbol.enum_info(): no enum info for type: $t.name') } else { panic('TypeSymbol.enum_info(): no enum info for type: $t.name') }
} }
} }
[inline] [inline]
pub fn (t &TypeSymbol) mr_info() MultiReturn { pub fn (t &TypeSymbol) mr_info() MultiReturn {
match t.info { match union mut t.info {
MultiReturn { return *it } MultiReturn { return t.info }
else { panic('TypeSymbol.mr_info(): no multi return info for type: $t.name') } else { panic('TypeSymbol.mr_info(): no multi return info for type: $t.name') }
} }
} }
[inline] [inline]
pub fn (t &TypeSymbol) array_info() Array { pub fn (t &TypeSymbol) array_info() Array {
match t.info { match union mut t.info {
Array { return *it } Array { return t.info }
else { panic('TypeSymbol.array_info(): no array info for type: $t.name') } else { panic('TypeSymbol.array_info(): no array info for type: $t.name') }
} }
} }
[inline] [inline]
pub fn (t &TypeSymbol) array_fixed_info() ArrayFixed { pub fn (t &TypeSymbol) array_fixed_info() ArrayFixed {
match t.info { match union mut t.info {
ArrayFixed { return *it } ArrayFixed { return t.info }
else { panic('TypeSymbol.array_fixed(): no array fixed info for type: $t.name') } else { panic('TypeSymbol.array_fixed(): no array fixed info for type: $t.name') }
} }
} }
[inline] [inline]
pub fn (t &TypeSymbol) chan_info() Chan { pub fn (t &TypeSymbol) chan_info() Chan {
match t.info { match union mut t.info {
Chan { return *it } Chan { return t.info }
else { panic('TypeSymbol.chan_info(): no chan info for type: $t.name') } else { panic('TypeSymbol.chan_info(): no chan info for type: $t.name') }
} }
} }
[inline] [inline]
pub fn (t &TypeSymbol) map_info() Map { pub fn (t &TypeSymbol) map_info() Map {
match t.info { match union mut t.info {
Map { return *it } Map { return t.info }
else { panic('TypeSymbol.map_info(): no map info for type: $t.name') } else { panic('TypeSymbol.map_info(): no map info for type: $t.name') }
} }
} }
[inline] [inline]
pub fn (t &TypeSymbol) struct_info() Struct { pub fn (t &TypeSymbol) struct_info() Struct {
match t.info { match union mut t.info {
Struct { return *it } Struct { return t.info }
else { panic('TypeSymbol.struct_info(): no struct info for type: $t.name') } else { panic('TypeSymbol.struct_info(): no struct info for type: $t.name') }
} }
} }
@ -790,7 +790,7 @@ pub:
// NB: FExpr here is a actually an ast.Expr . // NB: FExpr here is a actually an ast.Expr .
// It should always be used by casting to ast.Expr, using ast.fe2ex()/ast.ex2fe() // It should always be used by casting to ast.Expr, using ast.fe2ex()/ast.ex2fe()
// That hack is needed to break an import cycle between v.ast and v.table . // That hack is needed to break an import cycle between v.ast and v.table .
pub type FExpr = byteptr | voidptr pub __type FExpr = byteptr | voidptr
pub struct Field { pub struct Field {
pub: pub:

View File

@ -11,7 +11,7 @@ import v.util
import v.pref import v.pref
// `Any` is a sum type that lists the possible types to be decoded and used. // `Any` is a sum type that lists the possible types to be decoded and used.
pub type Any = string | int | i64 | f32 | f64 | any_int | any_float | bool | Null | []Any | map[string]Any pub __type Any = string | int | i64 | f32 | f64 | any_int | any_float | bool | Null | []Any | map[string]Any
// `Null` struct is a simple representation of the `null` value in JSON. // `Null` struct is a simple representation of the `null` value in JSON.
pub struct Null {} pub struct Null {}

View File

@ -51,21 +51,20 @@ pub fn (flds []Any) str() string {
// String representation of the `Any` type. // String representation of the `Any` type.
pub fn (f Any) str() string { pub fn (f Any) str() string {
match f { match union f {
string { return *f } string { return f }
int { return (*f).str() } int { return f.str() }
i64 { return (*f).str() } i64 { return f.str() }
f32 { return (*f).str() } f32 { return f.str() }
f64 { return (*f).str() } f64 { return f.str() }
any_int { return (*f).str() } any_int { return f.str() }
any_float { return (*f).str() } any_float { return f.str() }
bool { return (*f).str() } bool { return f.str() }
map[string]Any { return (*f).str() } map[string]Any { return f.str() }
Null { return 'null' } Null { return 'null' }
else { else {
if f is []Any { if f is []Any {
arr := f return f.str()
return (*arr).str()
} }
return '' return ''
} }

View File

@ -66,11 +66,10 @@ pub fn null() Null {
// Use `Any` as a map. // Use `Any` as a map.
pub fn (f Any) as_map() map[string]Any { pub fn (f Any) as_map() map[string]Any {
if f is map[string]Any { if f is map[string]Any {
return *f return f
} else if f is []Any { } else if f is []Any {
mut mp := map[string]Any mut mp := map[string]Any
arr := f for i, fi in f {
for i, fi in arr {
mp['$i'] = fi mp['$i'] = fi
} }
return mp return mp
@ -80,9 +79,9 @@ pub fn (f Any) as_map() map[string]Any {
// Use `Any` as an integer. // Use `Any` as an integer.
pub fn (f Any) int() int { pub fn (f Any) int() int {
match f { match union f {
int { return *f } int { return f }
i64 { return int(*f) } i64 { return int(f) }
f64 { return f.str().int() } f64 { return f.str().int() }
f32 { return f.str().int() } f32 { return f.str().int() }
bool { return int(f) } bool { return int(f) }
@ -92,9 +91,9 @@ pub fn (f Any) int() int {
// Use `Any` as a 64-bit integer. // Use `Any` as a 64-bit integer.
pub fn (f Any) i64() i64 { pub fn (f Any) i64() i64 {
match f { match union f {
int { return *f } int { return f }
i64 { return int(*f) } i64 { return int(f) }
f64 { return f.str().i64() } f64 { return f.str().i64() }
f32 { return f.str().i64() } f32 { return f.str().i64() }
bool { return int(f) } bool { return int(f) }
@ -104,33 +103,32 @@ pub fn (f Any) i64() i64 {
// Use `Any` as a 32-bit float. // Use `Any` as a 32-bit float.
pub fn (f Any) f32() f32 { pub fn (f Any) f32() f32 {
match f { match union f {
int { return *f } int { return f }
i64 { return (*f).str().f32() } i64 { return f.str().f32() }
f64 { return (*f).str().f32() } f64 { return f.str().f32() }
f32 { return *f } f32 { return f }
else { return 0.0 } else { return 0.0 }
} }
} }
// Use `Any` as a float. // Use `Any` as a float.
pub fn (f Any) f64() f64 { pub fn (f Any) f64() f64 {
match f { match union f {
int { return *f } int { return f }
i64 { return *f } i64 { return f }
f64 { return *f } f64 { return f }
f32 { return (*f).str().f64() } f32 { return f.str().f64() }
else { return 0.0 } else { return 0.0 }
} }
} }
// Use `Any` as an array. // Use `Any` as an array.
pub fn (f Any) arr() []Any { pub fn (f Any) arr() []Any {
if f is []Any { if f is []Any {
return *f return f
} else if f is map[string]Any { } else if f is map[string]Any {
mut arr := []Any{} mut arr := []Any{}
mp := *f for _, v in f {
for _, v in mp {
arr << v arr << v
} }
return arr return arr
@ -140,9 +138,9 @@ pub fn (f Any) arr() []Any {
// Use `Any` as a bool // Use `Any` as a bool
pub fn (f Any) bool() bool { pub fn (f Any) bool() bool {
match f { match union f {
bool { return *f } bool { return f }
string { return (*f).bool() } string { return f.bool() }
else { return false } else { return false }
} }
} }