checker/gen: more generics fixes; ComptimeCall
							parent
							
								
									ec7863d174
								
							
						
					
					
						commit
						1ef8eacd6e
					
				|  | @ -15,10 +15,10 @@ pub type Expr = AnonFn | ArrayInit | AsCast | AssignExpr | Assoc | BoolLiteral | | |||
| 	PrefixExpr | RangeExpr | SelectorExpr | SizeOf | StringInterLiteral | StringLiteral | StructInit | | ||||
| 	Type | TypeOf | ||||
| 
 | ||||
| pub type Stmt = AssertStmt | AssignStmt | Attr | Block | BranchStmt | Comment | CompIf | ConstDecl | | ||||
| 	DeferStmt | EnumDecl | ExprStmt | FnDecl | ForCStmt | ForInStmt | ForStmt | GlobalDecl | GoStmt | | ||||
| 	GotoLabel | GotoStmt | HashStmt | Import | InterfaceDecl | Module | Return | StructDecl | TypeDecl | | ||||
| 	UnsafeStmt | ||||
| pub type Stmt = AssertStmt | AssignStmt | Attr | Block | BranchStmt | Comment | CompIf | ComptimeCall | | ||||
| 	ConstDecl | DeferStmt | EnumDecl | ExprStmt | FnDecl | ForCStmt | ForInStmt | ForStmt | GlobalDecl | | ||||
| 	GoStmt | GotoLabel | GotoStmt | HashStmt | Import | InterfaceDecl | Module | Return | StructDecl | | ||||
| 	TypeDecl | UnsafeStmt | ||||
| 
 | ||||
| pub type ScopeObject = ConstField | GlobalDecl | Var | ||||
| 
 | ||||
|  | @ -731,7 +731,7 @@ pub struct OrExpr { | |||
| pub: | ||||
| 	stmts []Stmt | ||||
| 	kind  OrKind | ||||
| 	pos      token.Position | ||||
| 	pos   token.Position | ||||
| } | ||||
| 
 | ||||
| pub struct Assoc { | ||||
|  | @ -772,6 +772,10 @@ pub mut: | |||
| 	return_type table.Type | ||||
| } | ||||
| 
 | ||||
| pub struct ComptimeCall { | ||||
| 	name string | ||||
| } | ||||
| 
 | ||||
| pub struct None { | ||||
| pub: | ||||
| 	foo int // todo
 | ||||
|  | @ -888,7 +892,7 @@ pub fn (expr Expr) position() token.Position { | |||
| } | ||||
| 
 | ||||
| pub fn (stmt Stmt) position() token.Position { | ||||
| 	match mut stmt { | ||||
| 	match stmt { | ||||
| 		AssertStmt { return it.pos } | ||||
| 		AssignStmt { return it.pos } | ||||
| 		/* | ||||
|  |  | |||
|  | @ -395,10 +395,16 @@ pub fn (mut c Checker) infix_expr(mut infix_expr ast.InfixExpr) table.Type { | |||
| 		c.expected_type = former_expected_type | ||||
| 	} | ||||
| 	c.expected_type = table.void_type | ||||
| 	left_type := c.expr(infix_expr.left) | ||||
| 	mut left_type := c.expr(infix_expr.left) | ||||
| 	if false && left_type == table.t_type { | ||||
| 		left_type = c.cur_generic_type | ||||
| 	} | ||||
| 	infix_expr.left_type = left_type | ||||
| 	c.expected_type = left_type | ||||
| 	right_type := c.expr(infix_expr.right) | ||||
| 	mut right_type := c.expr(infix_expr.right) | ||||
| 	if false && right_type == table.t_type { | ||||
| 		right_type = c.cur_generic_type | ||||
| 	} | ||||
| 	infix_expr.right_type = right_type | ||||
| 	right := c.table.get_type_symbol(right_type) | ||||
| 	left := c.table.get_type_symbol(left_type) | ||||
|  | @ -613,11 +619,11 @@ fn (mut c Checker) fail_if_immutable(expr ast.Expr) { | |||
| 
 | ||||
| fn (mut c Checker) assign_expr(mut assign_expr ast.AssignExpr) { | ||||
| 	c.expected_type = table.void_type | ||||
| 	left_type := c.expr(assign_expr.left) | ||||
| 	left_type := c.unwrap_generic(c.expr(assign_expr.left)) | ||||
| 	c.expected_type = left_type | ||||
| 	assign_expr.left_type = left_type | ||||
| 	// println('setting exp type to $c.expected_type $t.name')
 | ||||
| 	right_type := c.expr(assign_expr.val) | ||||
| 	right_type := c.unwrap_generic(c.expr(assign_expr.val)) | ||||
| 	assign_expr.right_type = right_type | ||||
| 	right := c.table.get_type_symbol(right_type) | ||||
| 	left := c.table.get_type_symbol(left_type) | ||||
|  | @ -1162,15 +1168,17 @@ pub fn (mut c Checker) return_stmt(mut return_stmt ast.Return) { | |||
| 	} | ||||
| 	for i, exp_type in expected_types { | ||||
| 		got_typ := got_types[i] | ||||
| 		/* | ||||
| 		ok := if exp_type == table.t_type { c.check_types(got_typ, c.cur_generic_type) } else { c.check_types(got_typ, | ||||
| 		is_generic := exp_type == table.t_type | ||||
| 		ok := if is_generic { c.check_types(got_typ, c.cur_generic_type) || got_typ == exp_type } else { c.check_types(got_typ, | ||||
| 				exp_type) } | ||||
| 		*/ | ||||
| 		ok := c.check_types(got_typ, exp_type) | ||||
| 		// ok := c.check_types(got_typ, exp_type)
 | ||||
| 		if !ok { // !c.table.check(got_typ, exp_typ) {
 | ||||
| 			got_typ_sym := c.table.get_type_symbol(got_typ) | ||||
| 			exp_typ_sym := c.table.get_type_symbol(exp_type) | ||||
| 			mut exp_typ_sym := c.table.get_type_symbol(exp_type) | ||||
| 			pos := return_stmt.exprs[i].position() | ||||
| 			if is_generic { | ||||
| 				exp_typ_sym = c.table.get_type_symbol(c.cur_generic_type) | ||||
| 			} | ||||
| 			c.error('cannot use `$got_typ_sym.name` as type `$exp_typ_sym.name` in return argument', | ||||
| 				pos) | ||||
| 		} | ||||
|  | @ -1643,6 +1651,14 @@ fn (mut c Checker) stmts(stmts []ast.Stmt) { | |||
| 	c.expected_type = table.void_type | ||||
| } | ||||
| 
 | ||||
| pub fn (mut c Checker) unwrap_generic(typ table.Type) table.Type { | ||||
| 	if typ == table.t_type { | ||||
| 		return c.cur_generic_type | ||||
| 	} | ||||
| 	return typ | ||||
| } | ||||
| 
 | ||||
| // TODO node must be mut
 | ||||
| pub fn (mut c Checker) expr(node ast.Expr) table.Type { | ||||
| 	match mut node { | ||||
| 		ast.AnonFn { | ||||
|  | @ -1870,12 +1886,12 @@ pub fn (mut c Checker) ident(mut ident ast.Ident) table.Type { | |||
| 						typ: typ | ||||
| 						is_optional: is_optional | ||||
| 					} | ||||
| 					if typ == table.t_type { | ||||
| 						sym := c.table.get_type_symbol(c.cur_generic_type) | ||||
| 						println('IDENT T unresolved $ident.name typ=$sym.name') | ||||
| 						// Got a var with type T, return current generic type
 | ||||
| 						// typ = c.cur_generic_type
 | ||||
| 					} | ||||
| 					// if typ == table.t_type {
 | ||||
| 					// sym := c.table.get_type_symbol(c.cur_generic_type)
 | ||||
| 					// println('IDENT T unresolved $ident.name typ=$sym.name')
 | ||||
| 					// Got a var with type T, return current generic type
 | ||||
| 					// typ = c.cur_generic_type
 | ||||
| 					// }
 | ||||
| 					// } else {
 | ||||
| 					it.typ = typ | ||||
| 					// unwrap optional (`println(x)`)
 | ||||
|  |  | |||
|  | @ -359,6 +359,7 @@ pub fn (mut f Fmt) stmt(node ast.Stmt) { | |||
| 			f.stmts(it.stmts) | ||||
| 			f.writeln('}') | ||||
| 		} | ||||
| 		ast.ComptimeCall {} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  | @ -873,6 +874,9 @@ pub fn (mut f Fmt) call_expr(node ast.CallExpr) { | |||
| 		f.write(')') | ||||
| 		f.or_expr(node.or_block) | ||||
| 	} else { | ||||
| 		if node.language == .c { | ||||
| 			f.write('C.') | ||||
| 		} | ||||
| 		name := f.short_module(node.name) | ||||
| 		f.mark_module_as_used(name) | ||||
| 		f.write('${name}') | ||||
|  |  | |||
|  | @ -1580,14 +1580,31 @@ fn (mut g Gen) infix_expr(node ast.InfixExpr) { | |||
| 	right_sym := g.table.get_type_symbol(node.right_type) | ||||
| 	if left_type == table.ustring_type_idx && node.op != .key_in && node.op != .not_in { | ||||
| 		fn_name := match node.op { | ||||
| 			.plus { 'ustring_add(' } | ||||
| 			.eq { 'ustring_eq(' } | ||||
| 			.ne { 'ustring_ne(' } | ||||
| 			.lt { 'ustring_lt(' } | ||||
| 			.le { 'ustring_le(' } | ||||
| 			.gt { 'ustring_gt(' } | ||||
| 			.ge { 'ustring_ge(' } | ||||
| 			else { '/*node error*/' } | ||||
| 			.plus { | ||||
| 				'ustring_add(' | ||||
| 			} | ||||
| 			.eq { | ||||
| 				'ustring_eq(' | ||||
| 			} | ||||
| 			.ne { | ||||
| 				'ustring_ne(' | ||||
| 			} | ||||
| 			.lt { | ||||
| 				'ustring_lt(' | ||||
| 			} | ||||
| 			.le { | ||||
| 				'ustring_le(' | ||||
| 			} | ||||
| 			.gt { | ||||
| 				'ustring_gt(' | ||||
| 			} | ||||
| 			.ge { | ||||
| 				'ustring_ge(' | ||||
| 			} | ||||
| 			else { | ||||
| 				verror('op error for type `$left_sym.name`') | ||||
| 				'/*node error*/' | ||||
| 			} | ||||
| 		} | ||||
| 		g.write(fn_name) | ||||
| 		g.expr(node.left) | ||||
|  | @ -1596,14 +1613,31 @@ fn (mut g Gen) infix_expr(node ast.InfixExpr) { | |||
| 		g.write(')') | ||||
| 	} else if left_type == table.string_type_idx && node.op != .key_in && node.op != .not_in { | ||||
| 		fn_name := match node.op { | ||||
| 			.plus { 'string_add(' } | ||||
| 			.eq { 'string_eq(' } | ||||
| 			.ne { 'string_ne(' } | ||||
| 			.lt { 'string_lt(' } | ||||
| 			.le { 'string_le(' } | ||||
| 			.gt { 'string_gt(' } | ||||
| 			.ge { 'string_ge(' } | ||||
| 			else { '/*node error*/' } | ||||
| 			.plus { | ||||
| 				'string_add(' | ||||
| 			} | ||||
| 			.eq { | ||||
| 				'string_eq(' | ||||
| 			} | ||||
| 			.ne { | ||||
| 				'string_ne(' | ||||
| 			} | ||||
| 			.lt { | ||||
| 				'string_lt(' | ||||
| 			} | ||||
| 			.le { | ||||
| 				'string_le(' | ||||
| 			} | ||||
| 			.gt { | ||||
| 				'string_gt(' | ||||
| 			} | ||||
| 			.ge { | ||||
| 				'string_ge(' | ||||
| 			} | ||||
| 			else { | ||||
| 				verror('op error for type `$left_sym.name`') | ||||
| 				'/*node error*/' | ||||
| 			} | ||||
| 		} | ||||
| 		g.write(fn_name) | ||||
| 		g.expr(node.left) | ||||
|  |  | |||
|  | @ -0,0 +1,49 @@ | |||
| // Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved.
 | ||||
| // Use of this source code is governed by an MIT license
 | ||||
| // that can be found in the LICENSE file.
 | ||||
| module gen | ||||
| 
 | ||||
| import vweb.tmpl | ||||
| import os | ||||
| 
 | ||||
| // $vweb.html()
 | ||||
| fn (mut g Gen) vweb_html() { | ||||
| 	// Compile vweb html template to V code, parse that V code and embed the resulting V functions
 | ||||
| 	// that returns an html string
 | ||||
| 	mut path := g.cur_fn.name + '.html' | ||||
| 	println('html path=$path') | ||||
| 	if g.pref.is_debug { | ||||
| 		println('>>> compiling vweb HTML template "$path"') | ||||
| 	} | ||||
| 	if !os.exists(path) { | ||||
| 		// Can't find the template file in current directory,
 | ||||
| 		// try looking next to the vweb program, in case it's run with
 | ||||
| 		// v path/to/vweb_app.v
 | ||||
| 		// path = os.dir(g.scanner.file_path) + '/' + path
 | ||||
| 		// if !os.exists(path) {
 | ||||
| 		verror('vweb HTML template "$path" not found') | ||||
| 		// }
 | ||||
| 	} | ||||
| 	v_code := tmpl.compile_template(path) | ||||
| 	if g.pref.is_verbose { | ||||
| 		println('\n\n') | ||||
| 		println('>>> vweb template for ${path}:') | ||||
| 		println(v_code) | ||||
| 		println('>>> vweb template END') | ||||
| 		println('\n\n') | ||||
| 	} | ||||
| 	// is_strings_imorted := p.import_table.known_import('strings')
 | ||||
| 	// if !is_strings_imorted {
 | ||||
| 	// p.register_import('strings', 0) // used by v_code
 | ||||
| 	// }
 | ||||
| 	// p.import_table.register_used_import('strings')
 | ||||
| 	g.writeln('/////////////////// tmpl start') | ||||
| 	// g.statements_from_text(v_code, false, path)
 | ||||
| 	g.writeln('/////////////////// tmpl end') | ||||
| 	receiver := g.cur_fn.args[0] | ||||
| 	dot := '.' // if receiver.is_mut || receiver.ptr || receiver.typ.ends_with('*') { '->' } else { '.' }
 | ||||
| 	g.writeln('vweb__Context_html(&$receiver.name /*!*/$dot vweb, tmpl_res)') | ||||
| } | ||||
| 
 | ||||
| fn fooo() { | ||||
| } | ||||
|  | @ -22,7 +22,9 @@ fn (mut g Gen) gen_fn_decl(it ast.FnDecl) { | |||
| 		// loop thru each generic type and generate a function
 | ||||
| 		for gen_type in g.table.fn_gen_types[it.name] { | ||||
| 			sym := g.table.get_type_symbol(gen_type) | ||||
| 			println('gen fn `$it.name` for type `$sym.name`') | ||||
| 			if g.pref.is_verbose { | ||||
| 				println('gen fn `$it.name` for type `$sym.name`') | ||||
| 			} | ||||
| 			g.cur_generic_type = gen_type | ||||
| 			g.gen_fn_decl(it) | ||||
| 		} | ||||
|  |  | |||
|  | @ -53,9 +53,21 @@ fn (mut p Parser) hash() ast.HashStmt { | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| fn (mut p Parser) comp_if() ast.CompIf { | ||||
| fn (mut p Parser) vweb() ast.ComptimeCall { | ||||
| 	p.check(.name) // skip `vweb.html()` TODO
 | ||||
| 	p.check(.dot) | ||||
| 	p.check(.name) | ||||
| 	p.check(.lpar) | ||||
| 	p.check(.rpar) | ||||
| 	return ast.ComptimeCall{} | ||||
| } | ||||
| 
 | ||||
| fn (mut p Parser) comp_if() ast.Stmt { | ||||
| 	pos := p.tok.position() | ||||
| 	p.next() | ||||
| 	if p.tok.kind == .name && p.tok.lit == 'vweb' { | ||||
| 		return p.vweb() | ||||
| 	} | ||||
| 	p.check(.key_if) | ||||
| 	is_not := p.tok.kind == .not | ||||
| 	if is_not { | ||||
|  |  | |||
|  | @ -25,15 +25,20 @@ fn test_generic_fn() { | |||
| 	assert plus<string>('a', 'b') == 'ab' | ||||
| } | ||||
| 
 | ||||
| /* | ||||
| fn sum<T>(l []T) T { | ||||
|     mut r := T(0) | ||||
|     for e in l { | ||||
|         r += e | ||||
|     } | ||||
|     return r | ||||
| 	mut r := T(0) | ||||
| 	for e in l { | ||||
| 		r += e | ||||
| 	} | ||||
| 	return r | ||||
| } | ||||
| 
 | ||||
| fn test_foo() { | ||||
| 	b := [1, 2, 3] | ||||
| 	assert sum<int>(b) == 6 | ||||
| } | ||||
| 
 | ||||
| /* | ||||
| fn map_f<T,U>(l []T, f fn(T)U) []U { | ||||
|     mut r := []U{} | ||||
|     for e in l { | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue