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 |
|
PrefixExpr | RangeExpr | SelectorExpr | SizeOf | StringInterLiteral | StringLiteral | StructInit |
|
||||||
Type | TypeOf
|
Type | TypeOf
|
||||||
|
|
||||||
pub type Stmt = AssertStmt | AssignStmt | Attr | Block | BranchStmt | Comment | CompIf | ConstDecl |
|
pub type Stmt = AssertStmt | AssignStmt | Attr | Block | BranchStmt | Comment | CompIf | ComptimeCall |
|
||||||
DeferStmt | EnumDecl | ExprStmt | FnDecl | ForCStmt | ForInStmt | ForStmt | GlobalDecl | GoStmt |
|
ConstDecl | DeferStmt | EnumDecl | ExprStmt | FnDecl | ForCStmt | ForInStmt | ForStmt | GlobalDecl |
|
||||||
GotoLabel | GotoStmt | HashStmt | Import | InterfaceDecl | Module | Return | StructDecl | TypeDecl |
|
GoStmt | GotoLabel | GotoStmt | HashStmt | Import | InterfaceDecl | Module | Return | StructDecl |
|
||||||
UnsafeStmt
|
TypeDecl | UnsafeStmt
|
||||||
|
|
||||||
pub type ScopeObject = ConstField | GlobalDecl | Var
|
pub type ScopeObject = ConstField | GlobalDecl | Var
|
||||||
|
|
||||||
|
@ -731,7 +731,7 @@ pub struct OrExpr {
|
||||||
pub:
|
pub:
|
||||||
stmts []Stmt
|
stmts []Stmt
|
||||||
kind OrKind
|
kind OrKind
|
||||||
pos token.Position
|
pos token.Position
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Assoc {
|
pub struct Assoc {
|
||||||
|
@ -772,6 +772,10 @@ pub mut:
|
||||||
return_type table.Type
|
return_type table.Type
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct ComptimeCall {
|
||||||
|
name string
|
||||||
|
}
|
||||||
|
|
||||||
pub struct None {
|
pub struct None {
|
||||||
pub:
|
pub:
|
||||||
foo int // todo
|
foo int // todo
|
||||||
|
@ -888,7 +892,7 @@ pub fn (expr Expr) position() token.Position {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (stmt Stmt) position() token.Position {
|
pub fn (stmt Stmt) position() token.Position {
|
||||||
match mut stmt {
|
match stmt {
|
||||||
AssertStmt { return it.pos }
|
AssertStmt { return it.pos }
|
||||||
AssignStmt { 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 = former_expected_type
|
||||||
}
|
}
|
||||||
c.expected_type = table.void_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
|
infix_expr.left_type = left_type
|
||||||
c.expected_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
|
infix_expr.right_type = right_type
|
||||||
right := c.table.get_type_symbol(right_type)
|
right := c.table.get_type_symbol(right_type)
|
||||||
left := c.table.get_type_symbol(left_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) {
|
fn (mut c Checker) assign_expr(mut assign_expr ast.AssignExpr) {
|
||||||
c.expected_type = table.void_type
|
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
|
c.expected_type = left_type
|
||||||
assign_expr.left_type = left_type
|
assign_expr.left_type = left_type
|
||||||
// println('setting exp type to $c.expected_type $t.name')
|
// 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
|
assign_expr.right_type = right_type
|
||||||
right := c.table.get_type_symbol(right_type)
|
right := c.table.get_type_symbol(right_type)
|
||||||
left := c.table.get_type_symbol(left_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 {
|
for i, exp_type in expected_types {
|
||||||
got_typ := got_types[i]
|
got_typ := got_types[i]
|
||||||
/*
|
is_generic := exp_type == table.t_type
|
||||||
ok := if exp_type == table.t_type { c.check_types(got_typ, c.cur_generic_type) } else { c.check_types(got_typ,
|
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) }
|
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) {
|
if !ok { // !c.table.check(got_typ, exp_typ) {
|
||||||
got_typ_sym := c.table.get_type_symbol(got_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()
|
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',
|
c.error('cannot use `$got_typ_sym.name` as type `$exp_typ_sym.name` in return argument',
|
||||||
pos)
|
pos)
|
||||||
}
|
}
|
||||||
|
@ -1643,6 +1651,14 @@ fn (mut c Checker) stmts(stmts []ast.Stmt) {
|
||||||
c.expected_type = table.void_type
|
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 {
|
pub fn (mut c Checker) expr(node ast.Expr) table.Type {
|
||||||
match mut node {
|
match mut node {
|
||||||
ast.AnonFn {
|
ast.AnonFn {
|
||||||
|
@ -1870,12 +1886,12 @@ pub fn (mut c Checker) ident(mut ident ast.Ident) table.Type {
|
||||||
typ: typ
|
typ: typ
|
||||||
is_optional: is_optional
|
is_optional: is_optional
|
||||||
}
|
}
|
||||||
if typ == table.t_type {
|
// if typ == table.t_type {
|
||||||
sym := c.table.get_type_symbol(c.cur_generic_type)
|
// sym := c.table.get_type_symbol(c.cur_generic_type)
|
||||||
println('IDENT T unresolved $ident.name typ=$sym.name')
|
// println('IDENT T unresolved $ident.name typ=$sym.name')
|
||||||
// Got a var with type T, return current generic type
|
// Got a var with type T, return current generic type
|
||||||
// typ = c.cur_generic_type
|
// typ = c.cur_generic_type
|
||||||
}
|
// }
|
||||||
// } else {
|
// } else {
|
||||||
it.typ = typ
|
it.typ = typ
|
||||||
// unwrap optional (`println(x)`)
|
// unwrap optional (`println(x)`)
|
||||||
|
|
|
@ -359,6 +359,7 @@ pub fn (mut f Fmt) stmt(node ast.Stmt) {
|
||||||
f.stmts(it.stmts)
|
f.stmts(it.stmts)
|
||||||
f.writeln('}')
|
f.writeln('}')
|
||||||
}
|
}
|
||||||
|
ast.ComptimeCall {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -873,6 +874,9 @@ pub fn (mut f Fmt) call_expr(node ast.CallExpr) {
|
||||||
f.write(')')
|
f.write(')')
|
||||||
f.or_expr(node.or_block)
|
f.or_expr(node.or_block)
|
||||||
} else {
|
} else {
|
||||||
|
if node.language == .c {
|
||||||
|
f.write('C.')
|
||||||
|
}
|
||||||
name := f.short_module(node.name)
|
name := f.short_module(node.name)
|
||||||
f.mark_module_as_used(name)
|
f.mark_module_as_used(name)
|
||||||
f.write('${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)
|
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 {
|
if left_type == table.ustring_type_idx && node.op != .key_in && node.op != .not_in {
|
||||||
fn_name := match node.op {
|
fn_name := match node.op {
|
||||||
.plus { 'ustring_add(' }
|
.plus {
|
||||||
.eq { 'ustring_eq(' }
|
'ustring_add('
|
||||||
.ne { 'ustring_ne(' }
|
}
|
||||||
.lt { 'ustring_lt(' }
|
.eq {
|
||||||
.le { 'ustring_le(' }
|
'ustring_eq('
|
||||||
.gt { 'ustring_gt(' }
|
}
|
||||||
.ge { 'ustring_ge(' }
|
.ne {
|
||||||
else { '/*node error*/' }
|
'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.write(fn_name)
|
||||||
g.expr(node.left)
|
g.expr(node.left)
|
||||||
|
@ -1596,14 +1613,31 @@ fn (mut g Gen) infix_expr(node ast.InfixExpr) {
|
||||||
g.write(')')
|
g.write(')')
|
||||||
} else if left_type == table.string_type_idx && node.op != .key_in && node.op != .not_in {
|
} else if left_type == table.string_type_idx && node.op != .key_in && node.op != .not_in {
|
||||||
fn_name := match node.op {
|
fn_name := match node.op {
|
||||||
.plus { 'string_add(' }
|
.plus {
|
||||||
.eq { 'string_eq(' }
|
'string_add('
|
||||||
.ne { 'string_ne(' }
|
}
|
||||||
.lt { 'string_lt(' }
|
.eq {
|
||||||
.le { 'string_le(' }
|
'string_eq('
|
||||||
.gt { 'string_gt(' }
|
}
|
||||||
.ge { 'string_ge(' }
|
.ne {
|
||||||
else { '/*node error*/' }
|
'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.write(fn_name)
|
||||||
g.expr(node.left)
|
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
|
// loop thru each generic type and generate a function
|
||||||
for gen_type in g.table.fn_gen_types[it.name] {
|
for gen_type in g.table.fn_gen_types[it.name] {
|
||||||
sym := g.table.get_type_symbol(gen_type)
|
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.cur_generic_type = gen_type
|
||||||
g.gen_fn_decl(it)
|
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()
|
pos := p.tok.position()
|
||||||
p.next()
|
p.next()
|
||||||
|
if p.tok.kind == .name && p.tok.lit == 'vweb' {
|
||||||
|
return p.vweb()
|
||||||
|
}
|
||||||
p.check(.key_if)
|
p.check(.key_if)
|
||||||
is_not := p.tok.kind == .not
|
is_not := p.tok.kind == .not
|
||||||
if is_not {
|
if is_not {
|
||||||
|
|
|
@ -25,15 +25,20 @@ fn test_generic_fn() {
|
||||||
assert plus<string>('a', 'b') == 'ab'
|
assert plus<string>('a', 'b') == 'ab'
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
fn sum<T>(l []T) T {
|
fn sum<T>(l []T) T {
|
||||||
mut r := T(0)
|
mut r := T(0)
|
||||||
for e in l {
|
for e in l {
|
||||||
r += e
|
r += e
|
||||||
}
|
}
|
||||||
return r
|
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 {
|
fn map_f<T,U>(l []T, f fn(T)U) []U {
|
||||||
mut r := []U{}
|
mut r := []U{}
|
||||||
for e in l {
|
for e in l {
|
||||||
|
|
Loading…
Reference in New Issue