checker: check that type exists in TypeDecl
							parent
							
								
									541b058e90
								
							
						
					
					
						commit
						0b3412cdb5
					
				| 
						 | 
				
			
			@ -155,6 +155,40 @@ fn (mut c Checker) check_file_in_main(file ast.File) bool {
 | 
			
		|||
	return has_main_fn
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn (mut c Checker) type_decl(node ast.TypeDecl) {
 | 
			
		||||
	match node {
 | 
			
		||||
		ast.AliasTypeDecl {
 | 
			
		||||
			typ_sym := c.table.get_type_symbol(it.parent_type)
 | 
			
		||||
			if typ_sym.kind == .placeholder {
 | 
			
		||||
				c.error("type `$typ_sym.name` doesn't exist", it.pos)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		ast.FnTypeDecl {
 | 
			
		||||
			typ_sym := c.table.get_type_symbol(it.typ)
 | 
			
		||||
			fn_typ_info := typ_sym.info as table.FnType
 | 
			
		||||
			fn_info := fn_typ_info.func
 | 
			
		||||
			ret_sym := c.table.get_type_symbol(fn_info.return_type)
 | 
			
		||||
			if ret_sym.kind == .placeholder {
 | 
			
		||||
				c.error("type `$ret_sym.name` doesn't exist", it.pos)
 | 
			
		||||
			}
 | 
			
		||||
			for arg in fn_info.args {
 | 
			
		||||
				arg_sym := c.table.get_type_symbol(arg.typ)
 | 
			
		||||
				if arg_sym.kind == .placeholder {
 | 
			
		||||
					c.error("type `$arg_sym.name` doesn't exist", it.pos)
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		ast.SumTypeDecl {
 | 
			
		||||
			for typ in it.sub_types {
 | 
			
		||||
				typ_sym := c.table.get_type_symbol(typ)
 | 
			
		||||
				if typ_sym.kind == .placeholder {
 | 
			
		||||
					c.error("type `$typ_sym.name` doesn't exist", it.pos)
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn (mut c Checker) struct_decl(decl ast.StructDecl) {
 | 
			
		||||
	splitted_full_name := decl.name.split('.')
 | 
			
		||||
	is_builtin := splitted_full_name[0] == 'builtin'
 | 
			
		||||
| 
						 | 
				
			
			@ -1088,6 +1122,7 @@ fn (mut c Checker) stmt(node ast.Stmt) {
 | 
			
		|||
					it.pos)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		// ast.Attr {}
 | 
			
		||||
		ast.AssignStmt {
 | 
			
		||||
			c.assign_stmt(mut it)
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -1099,7 +1134,6 @@ fn (mut c Checker) stmt(node ast.Stmt) {
 | 
			
		|||
				c.error('$it.tok.lit statement not within a loop', it.tok.position())
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		// ast.Attr {}
 | 
			
		||||
		ast.CompIf {
 | 
			
		||||
			// c.expr(it.cond)
 | 
			
		||||
			c.stmts(it.stmts)
 | 
			
		||||
| 
						 | 
				
			
			@ -1170,17 +1204,6 @@ fn (mut c Checker) stmt(node ast.Stmt) {
 | 
			
		|||
			}
 | 
			
		||||
			c.returns = false
 | 
			
		||||
		}
 | 
			
		||||
		ast.ForStmt {
 | 
			
		||||
			c.in_for_count++
 | 
			
		||||
			typ := c.expr(it.cond)
 | 
			
		||||
			if !it.is_inf && typ.idx() != table.bool_type_idx {
 | 
			
		||||
				c.error('non-bool used as for condition', it.pos)
 | 
			
		||||
			}
 | 
			
		||||
			// TODO: update loop var type
 | 
			
		||||
			// how does this work currenly?
 | 
			
		||||
			c.stmts(it.stmts)
 | 
			
		||||
			c.in_for_count--
 | 
			
		||||
		}
 | 
			
		||||
		ast.ForCStmt {
 | 
			
		||||
			c.in_for_count++
 | 
			
		||||
			c.stmt(it.init)
 | 
			
		||||
| 
						 | 
				
			
			@ -1230,8 +1253,20 @@ fn (mut c Checker) stmt(node ast.Stmt) {
 | 
			
		|||
			c.stmts(it.stmts)
 | 
			
		||||
			c.in_for_count--
 | 
			
		||||
		}
 | 
			
		||||
		ast.ForStmt {
 | 
			
		||||
			c.in_for_count++
 | 
			
		||||
			typ := c.expr(it.cond)
 | 
			
		||||
			if !it.is_inf && typ.idx() != table.bool_type_idx {
 | 
			
		||||
				c.error('non-bool used as for condition', it.pos)
 | 
			
		||||
			}
 | 
			
		||||
			// TODO: update loop var type
 | 
			
		||||
			// how does this work currenly?
 | 
			
		||||
			c.stmts(it.stmts)
 | 
			
		||||
			c.in_for_count--
 | 
			
		||||
		}
 | 
			
		||||
		// ast.GlobalDecl {}
 | 
			
		||||
		ast.GoStmt {
 | 
			
		||||
			if !is_call_expr(it.call_expr) {
 | 
			
		||||
			if !(it.call_expr is ast.CallExpr) {
 | 
			
		||||
				c.error('expression in `go` must be a function call', it.call_expr.position())
 | 
			
		||||
			}
 | 
			
		||||
			c.expr(it.call_expr)
 | 
			
		||||
| 
						 | 
				
			
			@ -1242,7 +1277,6 @@ fn (mut c Checker) stmt(node ast.Stmt) {
 | 
			
		|||
			c.mod = it.name
 | 
			
		||||
			c.is_builtin_mod = it.name == 'builtin'
 | 
			
		||||
		}
 | 
			
		||||
		// ast.GlobalDecl {}
 | 
			
		||||
		ast.Return {
 | 
			
		||||
			c.returns = true
 | 
			
		||||
			c.return_stmt(mut it)
 | 
			
		||||
| 
						 | 
				
			
			@ -1250,6 +1284,9 @@ fn (mut c Checker) stmt(node ast.Stmt) {
 | 
			
		|||
		ast.StructDecl {
 | 
			
		||||
			c.struct_decl(it)
 | 
			
		||||
		}
 | 
			
		||||
		ast.TypeDecl {
 | 
			
		||||
			c.type_decl(it)
 | 
			
		||||
		}
 | 
			
		||||
		ast.UnsafeStmt {
 | 
			
		||||
			c.stmts(it.stmts)
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -1260,13 +1297,6 @@ fn (mut c Checker) stmt(node ast.Stmt) {
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn is_call_expr(expr ast.Expr) bool {
 | 
			
		||||
	return match expr {
 | 
			
		||||
		ast.CallExpr { true }
 | 
			
		||||
		else { false }
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn (mut c Checker) stmts(stmts []ast.Stmt) {
 | 
			
		||||
	c.expected_type = table.void_type
 | 
			
		||||
	for stmt in stmts {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,5 @@
 | 
			
		|||
vlib/v/checker/tests/inout/alias_type_exists.v:1:1: error: type `Bird` doesn't exist
 | 
			
		||||
    1| type Pigeon = Bird
 | 
			
		||||
       ~~~~~~~~~~~
 | 
			
		||||
    2|
 | 
			
		||||
    3| fn main() {
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,5 @@
 | 
			
		|||
type Pigeon = Bird
 | 
			
		||||
 | 
			
		||||
fn main() {
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,12 @@
 | 
			
		|||
vlib/v/checker/tests/inout/fn_type_exists.v:1:1: error: type `Pants` doesn't exist
 | 
			
		||||
    1| type PantsCreator = fn (a Shirt) Pants
 | 
			
		||||
       ~~~~~~~~~~~~~~~~~
 | 
			
		||||
    2|
 | 
			
		||||
    3| type PantsConsumer = fn (p Pants)
 | 
			
		||||
vlib/v/checker/tests/inout/fn_type_exists.v:3:1: error: type `Pants` doesn't exist
 | 
			
		||||
    1| type PantsCreator = fn (a Shirt) Pants
 | 
			
		||||
    2|
 | 
			
		||||
    3| type PantsConsumer = fn (p Pants)
 | 
			
		||||
       ~~~~~~~~~~~~~~~~~~
 | 
			
		||||
    4|
 | 
			
		||||
    5| fn main() {
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,7 @@
 | 
			
		|||
type PantsCreator = fn (a Shirt) Pants
 | 
			
		||||
 | 
			
		||||
type PantsConsumer = fn (p Pants)
 | 
			
		||||
 | 
			
		||||
fn main() {
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,5 @@
 | 
			
		|||
vlib/v/checker/tests/inout/sum_type_exists.v:1:1: error: type `Nope` doesn't exist
 | 
			
		||||
    1| type Miscellaneous = Nope | Inexistant | int
 | 
			
		||||
       ~~~~~~~~~~~~~~~~~~
 | 
			
		||||
    2|
 | 
			
		||||
    3| fn main() {
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,5 @@
 | 
			
		|||
type Miscellaneous = Nope | Inexistant | int
 | 
			
		||||
 | 
			
		||||
fn main() {
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
		Reference in New Issue