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