v2: module/type/fn name fixes, compile fixes
							parent
							
								
									05329d6731
								
							
						
					
					
						commit
						fcd97f513a
					
				|  | @ -327,11 +327,12 @@ pub fn (v mut V) compile2() { | |||
| 		println(v.files) | ||||
| 	} | ||||
| 	// v1 compiler files
 | ||||
| 	v.add_v_files_to_compile() | ||||
| 	//v.add_v_files_to_compile()
 | ||||
| 	//v.files << v.dir
 | ||||
| 	// v2 compiler
 | ||||
| 	//v.files << v.get_builtin_files()
 | ||||
| 	//v.files << v.get_user_files()
 | ||||
| 	v.files << v.get_builtin_files() | ||||
| 	v.files << v.get_user_files() | ||||
| 	v.set_module_lookup_paths() | ||||
| 	if v.pref.is_verbose { | ||||
| 		println('all .v files:') | ||||
| 		println(v.files) | ||||
|  |  | |||
|  | @ -212,7 +212,7 @@ pub: | |||
| 	mod     Module | ||||
| 	imports []Import | ||||
| 	stmts   []Stmt | ||||
| 	scope   Scope | ||||
| 	scope   &Scope | ||||
| } | ||||
| 
 | ||||
| pub struct IdentFunc { | ||||
|  |  | |||
|  | @ -105,16 +105,23 @@ fn (s &Scope) contains(pos int) bool { | |||
| 	return pos > s.start_pos && pos < s.end_pos | ||||
| } | ||||
| 
 | ||||
| pub fn (sc &Scope) print_vars(level int) { | ||||
| pub fn (sc &Scope) show(level int) string { | ||||
| 	mut out := '' | ||||
| 	mut indent := '' | ||||
| 	for _ in 0 .. level * 4 { | ||||
| 		indent += ' ' | ||||
| 	} | ||||
| 	println('$indent# $sc.start_pos - $sc.end_pos') | ||||
| 	out += '$indent# $sc.start_pos - $sc.end_pos\n' | ||||
| 	for _, var in sc.vars { | ||||
| 		println('$indent  * $var.name - $var.typ') | ||||
| 		out += '$indent  * $var.name - $var.typ\n' | ||||
| 	} | ||||
| 	for child in sc.children { | ||||
| 		child.print_vars(level + 1) | ||||
| 		out += child.show(level + 1) | ||||
| 	} | ||||
| 	return out | ||||
| } | ||||
| 
 | ||||
| pub fn (sc &Scope) str() string { | ||||
| 	return sc.show(0) | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -18,21 +18,18 @@ const ( | |||
| pub struct Checker { | ||||
| 	table     &table.Table | ||||
| mut: | ||||
| 	file_name string | ||||
| 	scope     &ast.Scope | ||||
| 	file      ast.File | ||||
| 	nr_errors int | ||||
| } | ||||
| 
 | ||||
| pub fn new_checker(table &table.Table) Checker { | ||||
| 	return Checker{ | ||||
| 		table: table | ||||
| 		scope: 0 | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| pub fn (c mut Checker) check(ast_file ast.File) { | ||||
| 	c.file_name = ast_file.path | ||||
| 	c.scope = &ast_file.scope | ||||
| 	c.file = ast_file | ||||
| 	for stmt in ast_file.stmts { | ||||
| 		c.stmt(stmt) | ||||
| 	} | ||||
|  | @ -124,30 +121,44 @@ fn (c mut Checker) check_assign_expr(assign_expr ast.AssignExpr) { | |||
| 
 | ||||
| pub fn (c mut Checker) call_expr(call_expr ast.CallExpr) table.Type { | ||||
| 	fn_name := call_expr.name | ||||
| 	if f := c.table.find_fn(fn_name) { | ||||
| 		// return_ti := f.return_ti
 | ||||
| 		if f.is_c || call_expr.is_c { | ||||
| 			return f.return_type | ||||
| 		} | ||||
| 		if call_expr.args.len < f.args.len { | ||||
| 			c.error('too few arguments in call to `$fn_name`', call_expr.pos) | ||||
| 		} | ||||
| 		else if !f.is_variadic && call_expr.args.len > f.args.len { | ||||
| 			c.error('too many arguments in call to `$fn_name` ($call_expr.args.len instead of $f.args.len)', call_expr.pos) | ||||
| 		} | ||||
| 		for i, arg_expr in call_expr.args { | ||||
| 			arg := if f.is_variadic && i >= f.args.len - 1 { f.args[f.args.len - 1] } else { f.args[i] } | ||||
| 			typ := c.expr(arg_expr) | ||||
| 			typ_sym := c.table.get_type_symbol(typ) | ||||
| 			arg_typ_sym := c.table.get_type_symbol(arg.typ) | ||||
| 			if !c.table.check(typ, arg.typ) { | ||||
| 				c.error('!cannot use type `$typ_sym.name` as type `$arg_typ_sym.name` in argument ${i+1} to `$fn_name`', call_expr.pos) | ||||
| 			} | ||||
| 
 | ||||
| 	mut found := false | ||||
| 	// look for function in format `mod.fn` or `fn` (main/builtin)
 | ||||
| 	mut f := table.Fn{} | ||||
| 	if f1 := c.table.find_fn(fn_name) { | ||||
| 		found = true | ||||
| 		f = f1 | ||||
| 	} | ||||
| 	// try prefix with current module as it would have never gotten prefixed
 | ||||
| 	if !found && !fn_name.contains('.') { | ||||
| 		if f1 := c.table.find_fn('${c.file.mod.name}.$fn_name') { | ||||
| 			found = true | ||||
| 			f = f1 | ||||
| 		} | ||||
| 	} | ||||
| 	if !found { | ||||
| 		c.error('unknown fn: $fn_name', call_expr.pos) | ||||
| 	} | ||||
| 
 | ||||
| 	if f.is_c || call_expr.is_c { | ||||
| 		return f.return_type | ||||
| 	} | ||||
| 	c.error('unknown fn: $fn_name', call_expr.pos) | ||||
| 	exit(1) | ||||
| 	if call_expr.args.len < f.args.len { | ||||
| 		c.error('too few arguments in call to `$fn_name`', call_expr.pos) | ||||
| 	} | ||||
| 	else if !f.is_variadic && call_expr.args.len > f.args.len { | ||||
| 		c.error('too many arguments in call to `$fn_name` ($call_expr.args.len instead of $f.args.len)', call_expr.pos) | ||||
| 	} | ||||
| 	for i, arg_expr in call_expr.args { | ||||
| 		arg := if f.is_variadic && i >= f.args.len - 1 { f.args[f.args.len - 1] } else { f.args[i] } | ||||
| 		typ := c.expr(arg_expr) | ||||
| 		typ_sym := c.table.get_type_symbol(typ) | ||||
| 		arg_typ_sym := c.table.get_type_symbol(arg.typ) | ||||
| 		if !c.table.check(typ, arg.typ) { | ||||
| 			c.error('!cannot use type `$typ_sym.name` as type `$arg_typ_sym.name` in argument ${i+1} to `$fn_name`', call_expr.pos) | ||||
| 		} | ||||
| 	} | ||||
| 	return f.return_type | ||||
| } | ||||
| 
 | ||||
| pub fn (c mut Checker) check_method_call_expr(method_call_expr ast.MethodCallExpr) table.Type { | ||||
|  | @ -399,8 +410,8 @@ pub fn (c mut Checker) ident(ident mut ast.Ident) table.Type { | |||
| 		if info.typ != 0 { | ||||
| 			return info.typ | ||||
| 		} | ||||
| 		start_scope := c.scope.innermost(ident.pos.pos) or { | ||||
| 			c.scope | ||||
| 		start_scope := c.file.scope.innermost(ident.pos.pos) or { | ||||
| 			c.file.scope | ||||
| 		} | ||||
| 		mut found := true | ||||
| 		mut var_scope := &ast.Scope(0) | ||||
|  | @ -597,7 +608,7 @@ pub fn (c mut Checker) index_expr(node ast.IndexExpr) table.Type { | |||
| pub fn (c mut Checker) error(s string, pos token.Position) { | ||||
| 	c.nr_errors++ | ||||
| 	print_backtrace() | ||||
| 	mut path := c.file_name | ||||
| 	mut path := c.file.path | ||||
| 	// Get relative path
 | ||||
| 	workdir := os.getwd() + filepath.separator | ||||
| 	if path.starts_with(workdir) { | ||||
|  |  | |||
|  | @ -18,7 +18,6 @@ pub fn (p mut Parser) call_expr(is_c bool, mod string) ast.CallExpr { | |||
| 		name: fn_name | ||||
| 		args: args | ||||
| 		// tok: tok
 | ||||
| 		 | ||||
| 		pos: tok.position() | ||||
| 		is_c: is_c | ||||
| 	} | ||||
|  | @ -26,9 +25,6 @@ pub fn (p mut Parser) call_expr(is_c bool, mod string) ast.CallExpr { | |||
| 		p.next() | ||||
| 		p.parse_block() | ||||
| 	} | ||||
| 	if f := p.table.find_fn(fn_name) { | ||||
| 		return node | ||||
| 	} | ||||
| 	return node | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -2,3 +2,16 @@ | |||
| // Use of this source code is governed by an MIT license
 | ||||
| // that can be found in the LICENSE file.
 | ||||
| module parser | ||||
| 
 | ||||
| // return true if file being parsed imports `mod`
 | ||||
| pub fn (p &Parser) known_import(mod string) bool { | ||||
| 	return mod in p.imports | ||||
| } | ||||
| 
 | ||||
| fn (p &Parser) prepend_mod(name string) string { | ||||
| 	if p.builtin_mod || p.mod == 'main' { | ||||
| 		return name | ||||
| 	} | ||||
| 	return '${p.mod}.$name' | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -101,13 +101,14 @@ pub fn (p mut Parser) parse_type() table.Type { | |||
| 	// `module.Type`
 | ||||
| 	if p.peek_tok.kind == .dot { | ||||
| 		// /if !(p.tok.lit in p.table.imports) {
 | ||||
| 		if !p.table.known_import(p.tok.lit) { | ||||
| 		if !p.known_import(name) { | ||||
| 			println(p.table.imports) | ||||
| 			p.error('unknown module `$p.tok.lit`') | ||||
| 		} | ||||
| 		p.next() | ||||
| 		p.check(.dot) | ||||
| 		name += '.' + p.tok.lit | ||||
| 		// prefix with full module
 | ||||
| 		name = '${p.imports[name]}.$p.tok.lit' | ||||
| 	} | ||||
| 	// `Foo` in module `mod` means `mod.Foo`
 | ||||
| 	else if !(p.mod in ['builtin', 'main']) && !(name in table.builtin_type_names) { | ||||
|  |  | |||
|  | @ -109,7 +109,7 @@ pub fn parse_file(path string, table &table.Table) ast.File { | |||
| 		mod: module_decl | ||||
| 		imports: imports | ||||
| 		stmts: stmts | ||||
| 		scope: *p.scope | ||||
| 		scope: p.scope | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  | @ -520,9 +520,10 @@ pub fn (p mut Parser) name_expr() ast.Expr { | |||
| 	mut node := ast.Expr{} | ||||
| 	is_c := p.tok.lit == 'C' | ||||
| 	mut mod := '' | ||||
| 	if p.peek_tok.kind == .dot && (is_c || p.tok.lit in p.imports) { | ||||
| 	if p.peek_tok.kind == .dot && (is_c || p.known_import(p.tok.lit)) { | ||||
| 		if !is_c { | ||||
| 			mod = p.tok.lit | ||||
| 			// prepend the full import
 | ||||
| 			mod = p.imports[p.tok.lit] | ||||
| 		} | ||||
| 		p.next() | ||||
| 		p.check(.dot) | ||||
|  | @ -1655,13 +1656,6 @@ fn (p mut Parser) type_decl() ast.TypeDecl { | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| fn (p &Parser) prepend_mod(name string) string { | ||||
| 	if p.builtin_mod || p.mod == 'main' { | ||||
| 		return name | ||||
| 	} | ||||
| 	return '${p.mod}.${name}' | ||||
| } | ||||
| 
 | ||||
| fn verror(s string) { | ||||
| 	println(s) | ||||
| 	exit(1) | ||||
|  |  | |||
|  | @ -34,14 +34,14 @@ fn test_eval() { | |||
| 	] | ||||
| 	/* | ||||
| 	table := table.new_table() | ||||
| 	mut scope := ast.Scope{start_pos: 0, parent: 0} | ||||
| 	mut scope := &ast.Scope{start_pos: 0, parent: 0} | ||||
| 	mut stmts := []ast.Stmt | ||||
| 	for input in inputs { | ||||
| 		stmts << parse_stmt(input, table, &scope) | ||||
| 		stmts << parse_stmt(input, table, scope) | ||||
| 	} | ||||
| 	file := ast.File{ | ||||
| 		stmts: stmts | ||||
| 		scope: &scope | ||||
| 		scope: scope | ||||
| 	} | ||||
| 	mut checker := checker.new_checker(table) | ||||
| 	checker.check(file) | ||||
|  | @ -87,10 +87,10 @@ fn test_one() { | |||
| 	] | ||||
| 	expected := 'int a = 10;int b = -a;int c = 20;' | ||||
| 	table := table.new_table() | ||||
| 	mut scope := ast.Scope{start_pos: 0, parent: 0} | ||||
| 	mut scope := &ast.Scope{start_pos: 0, parent: 0} | ||||
| 	mut e := []ast.Stmt | ||||
| 	for line in input { | ||||
| 		e << parse_stmt(line, table, &scope) | ||||
| 		e << parse_stmt(line, table, scope) | ||||
| 	} | ||||
| 	program := ast.File{ | ||||
| 		stmts: e | ||||
|  | @ -179,10 +179,10 @@ fn test_parse_expr() { | |||
| 	mut e := []ast.Stmt | ||||
| 	table := table.new_table() | ||||
| 	mut checker := checker.new_checker(table) | ||||
| 	mut scope := ast.Scope{start_pos: 0, parent: 0} | ||||
| 	mut scope := &ast.Scope{start_pos: 0, parent: 0} | ||||
| 	for s in input { | ||||
| 		println('\n\nst="$s"') | ||||
| 		e << parse_stmt(s, table, &scope) | ||||
| 		e << parse_stmt(s, table, scope) | ||||
| 	} | ||||
| 	program := ast.File{ | ||||
| 		stmts: e | ||||
|  |  | |||
|  | @ -3,11 +3,6 @@ | |||
| // that can be found in the LICENSE file.
 | ||||
| module table | ||||
| 
 | ||||
| import ( | ||||
| 	v.token | ||||
| 	// v.ast
 | ||||
| ) | ||||
| 
 | ||||
| pub struct Table { | ||||
| 	// struct_fields map[string][]string
 | ||||
| pub mut: | ||||
|  | @ -400,11 +395,3 @@ pub fn (t &Table) check(got, expected Type) bool { | |||
| 	return true | ||||
| } | ||||
| 
 | ||||
| pub fn (t &Table) known_import(name string) bool { | ||||
| 	for i in t.imports { | ||||
| 		if i.all_after('.') == name { | ||||
| 			return true | ||||
| 		} | ||||
| 	} | ||||
| 	return false | ||||
| } | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue