generics: generic call inside generic call; checker: check mut args at call
parent
f0a9b88ac4
commit
81b44dc2c9
|
@ -17,7 +17,7 @@ fn main() {
|
|||
vweb.run<App>(port)
|
||||
}
|
||||
|
||||
pub fn (mut app App) init() {
|
||||
pub fn (app App) init() {
|
||||
app.vweb.handle_static('.')
|
||||
}
|
||||
|
||||
|
|
|
@ -116,7 +116,7 @@ pub fn (mut pool PoolProcessor) work_on_pointers(items []voidptr) {
|
|||
pool.thread_contexts << [voidptr(0)].repeat(pool.items.len)
|
||||
pool.waitgroup.add(njobs)
|
||||
for i := 0; i < njobs; i++ {
|
||||
go process_in_thread(pool,i)
|
||||
go process_in_thread(mut pool,i)
|
||||
}
|
||||
pool.waitgroup.wait()
|
||||
}
|
||||
|
|
|
@ -860,6 +860,16 @@ pub fn (mut c Checker) call_fn(mut call_expr ast.CallExpr) table.Type {
|
|||
// TODO: impl typeof properly (probably not going to be a fn call)
|
||||
return table.string_type
|
||||
}
|
||||
if call_expr.generic_type == table.t_type {
|
||||
if c.mod != '' && c.mod != 'main' {
|
||||
// Need to prepend the module when adding a generic type to a function
|
||||
// `fn_gen_types['mymod.myfn'] == ['string', 'int']`
|
||||
c.table.register_fn_gen_type(c.mod + '.' + fn_name, c.cur_generic_type)
|
||||
} else {
|
||||
c.table.register_fn_gen_type(fn_name, c.cur_generic_type)
|
||||
}
|
||||
// call_expr.generic_type = c.unwrap_generic(call_expr.generic_type)
|
||||
}
|
||||
// if c.fileis('json_test.v') {
|
||||
// println(fn_name)
|
||||
// }
|
||||
|
@ -984,6 +994,10 @@ pub fn (mut c Checker) call_fn(mut call_expr ast.CallExpr) table.Type {
|
|||
if f.is_variadic && typ.flag_is(.variadic) && call_expr.args.len - 1 > i {
|
||||
c.error('when forwarding a varg variable, it must be the final argument', call_expr.pos)
|
||||
}
|
||||
if arg.is_mut && !call_arg.is_mut {
|
||||
c.error('`$arg.name` is a mutable argument, you need to provide `mut`: `${call_expr.name}(mut ...)`',
|
||||
call_arg.expr.position())
|
||||
}
|
||||
// Handle expected interface
|
||||
if arg_typ_sym.kind == .interface_ {
|
||||
c.type_implements(typ, arg.typ, call_arg.expr.position())
|
||||
|
|
|
@ -384,8 +384,10 @@ typedef struct {
|
|||
.alias {
|
||||
parent := &g.table.types[typ.parent_idx]
|
||||
styp := typ.name.replace('.', '__')
|
||||
is_c_parent := parent.name.len > 2 && parent.name[0] == `C` && parent.name[1] == `.`
|
||||
parent_styp := if is_c_parent { 'struct ' + parent.name[2..].replace('.', '__') } else { parent.name.replace('.', '__') }
|
||||
is_c_parent := parent.name.len > 2 && parent.name[0] == `C` && parent.name[1] ==
|
||||
`.`
|
||||
parent_styp := if is_c_parent { 'struct ' + parent.name[2..].replace('.', '__') } else { parent.name.replace('.',
|
||||
'__') }
|
||||
g.definitions.writeln('typedef $parent_styp $styp;')
|
||||
}
|
||||
.array {
|
||||
|
@ -842,7 +844,9 @@ fn (mut g Gen) expr_with_cast(expr ast.Expr, got_type, expected_type table.Type)
|
|||
got_is_ptr := got_type.is_ptr()
|
||||
expected_is_ptr := expected_type.is_ptr()
|
||||
neither_void := table.voidptr_type !in [got_type, expected_type]
|
||||
if got_is_ptr && !expected_is_ptr && neither_void && expected_sym.kind !in [.interface_, .placeholder] {
|
||||
if got_is_ptr && !expected_is_ptr && neither_void && expected_sym.kind !in [.interface_,
|
||||
.placeholder
|
||||
] {
|
||||
got_deref_type := got_type.deref()
|
||||
deref_sym := g.table.get_type_symbol(got_deref_type)
|
||||
deref_will_match := expected_type in [got_type, got_deref_type, deref_sym.parent_idx]
|
||||
|
@ -901,7 +905,8 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
|
|||
if return_type != table.void_type && return_type != 0 {
|
||||
sym := g.table.get_type_symbol(return_type)
|
||||
// the left vs. right is ugly and should be removed
|
||||
if sym.kind == .multi_return || assign_stmt.left.len > assign_stmt.right.len || assign_stmt.left.len > 1 {
|
||||
if sym.kind == .multi_return || assign_stmt.left.len > assign_stmt.right.len || assign_stmt.left.len >
|
||||
1 {
|
||||
// multi return
|
||||
// TODO Handle in if_expr
|
||||
is_optional := return_type.flag_is(.optional)
|
||||
|
@ -1317,6 +1322,9 @@ fn (mut g Gen) expr(node ast.Expr) {
|
|||
ast.CharLiteral {
|
||||
g.write("'$it.val'")
|
||||
}
|
||||
ast.ComptimeCall {
|
||||
g.write('/*c*/')
|
||||
}
|
||||
ast.ConcatExpr {
|
||||
g.concat_expr(it)
|
||||
}
|
||||
|
@ -1836,7 +1844,8 @@ fn (mut g Gen) match_expr(node ast.MatchExpr) {
|
|||
g.writeln('// match 0')
|
||||
return
|
||||
}
|
||||
is_expr := (node.is_expr && node.return_type != table.void_type) || g.inside_ternary > 0
|
||||
is_expr := (node.is_expr && node.return_type != table.void_type) || g.inside_ternary >
|
||||
0
|
||||
if is_expr {
|
||||
g.inside_ternary++
|
||||
// g.write('/* EM ret type=${g.typ(node.return_type)} expected_type=${g.typ(node.expected_type)} */')
|
||||
|
@ -2202,14 +2211,9 @@ fn (mut g Gen) index_expr(node ast.IndexExpr) {
|
|||
[inline]
|
||||
fn (g Gen) expr_is_multi_return_call(expr ast.Expr) bool {
|
||||
match expr {
|
||||
ast.CallExpr {
|
||||
return g.table.get_type_symbol(it.return_type).kind == .multi_return
|
||||
ast.CallExpr { return g.table.get_type_symbol(it.return_type).kind == .multi_return }
|
||||
else { return false }
|
||||
}
|
||||
else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fn (mut g Gen) return_statement(node ast.Return) {
|
||||
|
@ -2247,20 +2251,15 @@ fn (mut g Gen) return_statement(node ast.Return) {
|
|||
} else {
|
||||
styp = g.typ(g.fn_decl.return_type)
|
||||
}
|
||||
|
||||
// Use this to keep the tmp assignments in order
|
||||
mut multi_unpack := ''
|
||||
|
||||
|
||||
g.write('($styp){')
|
||||
|
||||
mut arg_idx := 0
|
||||
for i, expr in node.exprs {
|
||||
// Check if we are dealing with a multi return and handle it seperately
|
||||
if g.expr_is_multi_return_call(expr) {
|
||||
c := expr as ast.CallExpr
|
||||
expr_sym := g.table.get_type_symbol(c.return_type)
|
||||
|
||||
// Create a tmp for this call
|
||||
tmp := g.new_tmp_var()
|
||||
s := g.go_before_stmt(0)
|
||||
|
@ -2270,7 +2269,6 @@ fn (mut g Gen) return_statement(node ast.Return) {
|
|||
g.writeln(';')
|
||||
multi_unpack += g.go_before_stmt(0)
|
||||
g.write(s)
|
||||
|
||||
expr_types := expr_sym.mr_info().types
|
||||
for j, _ in expr_types {
|
||||
g.write('.arg$arg_idx=${tmp}.arg$j')
|
||||
|
@ -2279,10 +2277,8 @@ fn (mut g Gen) return_statement(node ast.Return) {
|
|||
}
|
||||
arg_idx++
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
g.write('.arg$arg_idx=')
|
||||
g.expr(expr)
|
||||
arg_idx++
|
||||
|
@ -2291,11 +2287,9 @@ fn (mut g Gen) return_statement(node ast.Return) {
|
|||
}
|
||||
}
|
||||
g.write('}')
|
||||
|
||||
if fn_return_is_optional {
|
||||
g.write(' }, sizeof($styp))')
|
||||
}
|
||||
|
||||
// Make sure to add our unpacks
|
||||
g.insert_before_stmt(multi_unpack)
|
||||
} else if node.exprs.len >= 1 {
|
||||
|
|
|
@ -12,6 +12,9 @@ fn (mut g Gen) gen_fn_decl(it ast.FnDecl) {
|
|||
// || it.no_body {
|
||||
return
|
||||
}
|
||||
//if g.fileis('vweb.v') {
|
||||
//println('\ngen_fn_decl() $it.name $it.is_generic $g.cur_generic_type')
|
||||
//}
|
||||
former_cur_fn := g.cur_fn
|
||||
g.cur_fn = &it
|
||||
defer {
|
||||
|
@ -760,3 +763,7 @@ fn (mut g Gen) is_gui_app() bool {
|
|||
}
|
||||
return false
|
||||
}
|
||||
|
||||
fn (g &Gen) fileis(s string) bool {
|
||||
return g.file.path.contains(s)
|
||||
}
|
||||
|
|
|
@ -30,10 +30,16 @@ pub fn (mut p Parser) call_expr(language table.Language, mod string) ast.CallExp
|
|||
// `foo<int>(10)`
|
||||
p.next() // `<`
|
||||
p.expr_mod = ''
|
||||
generic_type = p.parse_type()
|
||||
mut generic_type = p.parse_type()
|
||||
if generic_type == table.t_type {
|
||||
// Handle `foo<T>()`
|
||||
// generic_type = p.cur_gen_type
|
||||
}
|
||||
p.check(.gt) // `>`
|
||||
if generic_type != table.t_type {
|
||||
p.table.register_fn_gen_type(fn_name, generic_type)
|
||||
}
|
||||
}
|
||||
p.check(.lpar)
|
||||
args := p.call_args()
|
||||
last_pos := p.tok.position()
|
||||
|
|
|
@ -482,6 +482,6 @@ pub fn (table &Table) register_fn_gen_type(fn_name string, typ Type) {
|
|||
}
|
||||
a << typ
|
||||
// sym := table.get_type_symbol(typ)
|
||||
// println('registering fn gen type $sym.name')
|
||||
// println('registering fn ($fn_name) gen type $sym.name')
|
||||
table.fn_gen_types[fn_name] = a
|
||||
}
|
||||
|
|
|
@ -210,6 +210,6 @@ fn test_generic_fn_with_variadics(){
|
|||
p(s)
|
||||
p(i)
|
||||
p(abc)
|
||||
p('Good','morning','world')
|
||||
p('Good', 'morning', 'world')
|
||||
}
|
||||
*/
|
||||
|
|
|
@ -142,7 +142,7 @@ pub fn run<T>(port int) {
|
|||
//app.reset()
|
||||
for {
|
||||
conn := l.accept() or { panic('accept() failed') }
|
||||
handle_conn(conn, mut app)
|
||||
handle_conn<T>(conn, mut app)
|
||||
//foobar<T>()
|
||||
// TODO move this to handle_conn<T>(conn, app)
|
||||
//message := readall(conn)
|
||||
|
|
Loading…
Reference in New Issue