cgen: variadic for in loop

pull/4110/head
Joe Conigliaro 2020-03-24 19:42:16 +11:00
parent 309a905409
commit 3d2fafa580
2 changed files with 28 additions and 11 deletions

View File

@ -28,7 +28,7 @@ mut:
file ast.File
fn_decl &ast.FnDecl // pointer to the FnDecl we are currently inside otherwise 0
tmp_count int
varaidic_args map[string]int
variadic_args map[string]int
is_c_call bool // e.g. `C.printf("v")`
is_assign_expr bool // inside left part of assign expr (for array_set(), etc)
is_array_set bool
@ -202,10 +202,10 @@ pub fn (g mut Gen) write_multi_return_types() {
}
pub fn (g mut Gen) write_variadic_types() {
if g.varaidic_args.size > 0 {
if g.variadic_args.size > 0 {
g.definitions.writeln('// variadic structs')
}
for type_str, arg_len in g.varaidic_args {
for type_str, arg_len in g.variadic_args {
typ := table.Type(type_str.int())
type_name := g.typ(typ)
struct_name := 'varg_' + type_name.replace('*', '_ptr')
@ -393,6 +393,19 @@ fn (g mut Gen) stmt(node ast.Stmt) {
g.stmts(it.stmts)
g.writeln('}')
}
else if table.type_is_variadic(it.cond_type) {
g.writeln('// FOR IN')
i := if it.key_var == '' { g.new_tmp_var() } else { it.key_var }
g.write('for (int $i = 0; $i < ')
g.expr(it.cond)
g.writeln('.len; $i++) {')
styp := g.typ(it.cond_type)
g.write('$styp $it.val_var = ')
g.expr(it.cond)
g.writeln('.args[$i];')
g.stmts(it.stmts)
g.writeln('}')
}
}
ast.ForStmt {
g.write('while (')
@ -670,7 +683,10 @@ fn (g mut Gen) fn_args(args []table.Arg, is_variadic bool) {
mut arg_type_name := g.typ(arg.typ) // arg_type_sym.name.replace('.', '__')
is_varg := i == args.len - 1 && is_variadic
if is_varg {
g.varaidic_args[int(arg.typ).str()] = 0
varg_type_str := int(arg.typ).str()
if (!varg_type_str in g.variadic_args) {
g.variadic_args[int(arg.typ).str()] = 0
}
arg_type_name = 'varg_' + g.typ(arg.typ).replace('*', '_ptr')
}
if arg_type_sym.kind == .function {
@ -1661,8 +1677,9 @@ fn (g mut Gen) call_args(args []ast.CallArg) {
struct_name := 'varg_' + g.typ(arg.expected_type).replace('*', '_ptr')
len := args.len - i
type_str := int(arg.expected_type).str()
if len > g.varaidic_args[type_str] {
g.varaidic_args[type_str] = len
if len > g.variadic_args[type_str] {
x := g.variadic_args[type_str]
g.variadic_args[type_str] = len
}
g.write('($struct_name){.len=$len,.args={')
for j in i .. args.len {

View File

@ -414,7 +414,11 @@ pub fn (t mut Table) add_placeholder_type(name string) int {
[inline]
pub fn (t &Table) value_type(typ Type) Type {
typ_sym := t.get_type_symbol(typ)
if typ_sym.kind == .array {
if type_is_variadic(typ) {
// ...string => string
return type_clear_extra(typ)
}
else if typ_sym.kind == .array {
// Check index type
info := typ_sym.info as Array
return info.elem_type
@ -435,10 +439,6 @@ pub fn (t &Table) value_type(typ Type) Type {
// bytes[0] is a byte, not byte*
return type_deref(typ)
}
else if type_is_variadic(typ) {
// ...string => string
return type_clear_extra(typ)
}
else {
// TODO: remove when map_string is removed
if typ_sym.name == 'map_string' {