compiler: vargs - for loop support & indexing / dot fixes

pull/2174/head
joe-conigliaro 2019-10-01 00:11:12 +10:00 committed by Alexander Medvednikov
parent 5ac62bbb75
commit 7311db60a0
4 changed files with 69 additions and 52 deletions

View File

@ -886,6 +886,7 @@ fn (p mut Parser) fn_call_args(f mut Fn) &Fn {
p.gen('/*YY f=$f.name arg=$arg.name is_moved=$arg.is_moved*/string_clone(') p.gen('/*YY f=$f.name arg=$arg.name is_moved=$arg.is_moved*/string_clone(')
} }
mut typ := p.bool_expression() mut typ := p.bool_expression()
if typ.starts_with('...') { typ = typ.right(3) }
if clone { if clone {
p.gen(')') p.gen(')')
} }

View File

@ -12,6 +12,7 @@ fn (p mut Parser) gen_var_decl(name string, is_static bool) string {
// `[typ] [name] = bool_expression();` // `[typ] [name] = bool_expression();`
pos := p.cgen.add_placeholder() pos := p.cgen.add_placeholder()
mut typ := p.bool_expression() mut typ := p.bool_expression()
if typ.starts_with('...') { typ = typ.right(3) }
//p.gen('/*after expr*/') //p.gen('/*after expr*/')
// Option check ? or { // Option check ? or {
or_else := p.tok == .key_orelse or_else := p.tok == .key_orelse
@ -284,6 +285,12 @@ fn (p mut Parser) gen_for_map_header(i, tmp, var_typ, val, typ string) {
p.genln('$var_typ $val = $def; map_get($tmp, $i, & $val);') p.genln('$var_typ $val = $def; map_get($tmp, $i, & $val);')
} }
fn (p mut Parser) gen_for_varg_header(i, varg, var_typ, val string) {
p.genln('for (int $i = 0; $i < ${varg}->len; $i++) {')
if val == '_' { return }
p.genln('$var_typ $val = (($var_typ *) $varg->args)[$i];')
}
fn (p mut Parser) gen_array_init(typ string, no_alloc bool, new_arr_ph int, nr_elems int) { fn (p mut Parser) gen_array_init(typ string, no_alloc bool, new_arr_ph int, nr_elems int) {
mut new_arr := 'new_array_from_c_array' mut new_arr := 'new_array_from_c_array'
if no_alloc { if no_alloc {

View File

@ -8,7 +8,8 @@ const (
fn (p mut Parser) gen_var_decl(name string, is_static bool) string { fn (p mut Parser) gen_var_decl(name string, is_static bool) string {
p.gen('var $name /* typ */ = ') p.gen('var $name /* typ */ = ')
typ := p.bool_expression() mut typ := p.bool_expression()
if typ.starts_with('...') { typ = typ.right(3) }
or_else := p.tok == .key_orelse or_else := p.tok == .key_orelse
//tmp := p.get_tmp() //tmp := p.get_tmp()
if or_else { if or_else {
@ -121,6 +122,12 @@ fn (p mut Parser) gen_for_map_header(i, tmp, var_typ, val, typ string) {
p.genln('var $val = $tmp[$i];') p.genln('var $val = $tmp[$i];')
} }
fn (p mut Parser) gen_for_varg_header(i, varg, var_typ, val string) {
p.genln('for (var $i = 0; $i < ${varg}.len; $i++) {')
if val == '_' { return }
p.genln('var $val = ${varg}.args[$i];')
}
fn (p mut Parser) gen_array_init(typ string, no_alloc bool, new_arr_ph int, nr_elems int) { fn (p mut Parser) gen_array_init(typ string, no_alloc bool, new_arr_ph int, nr_elems int) {
p.cgen.set_placeholder(new_arr_ph, '[') p.cgen.set_placeholder(new_arr_ph, '[')
p.gen(']') p.gen(']')

View File

@ -1954,10 +1954,8 @@ fn (p mut Parser) dot(str_typ_ string, method_ph int) string {
mut str_typ := str_typ_ mut str_typ := str_typ_
p.check(.dot) p.check(.dot)
is_variadic_arg := str_typ.starts_with('...') is_variadic_arg := str_typ.starts_with('...')
if is_variadic_arg { if is_variadic_arg { str_typ = str_typ.right(3) }
str_typ = str_typ.right(3) mut typ := p.find_type(str_typ)
}
typ := p.find_type(str_typ)
if typ.name.len == 0 { if typ.name.len == 0 {
p.error('dot(): cannot find type `$str_typ`') p.error('dot(): cannot find type `$str_typ`')
} }
@ -1973,10 +1971,7 @@ fn (p mut Parser) dot(str_typ_ string, method_ph int) string {
//} //}
has_field := p.table.type_has_field(typ, p.table.var_cgen_name(field_name)) has_field := p.table.type_has_field(typ, p.table.var_cgen_name(field_name))
mut has_method := p.table.type_has_method(typ, field_name) mut has_method := p.table.type_has_method(typ, field_name)
if is_variadic_arg { if is_variadic_arg && field_name == 'len' {
if field_name != 'len' {
p.error('the only field you can access on variadic args is `.len`')
}
p.gen('->$field_name') p.gen('->$field_name')
p.next() p.next()
return 'int' return 'int'
@ -2192,25 +2187,23 @@ fn (p mut Parser) index_expr(typ_ string, fn_ph int) string {
p.expr_var = v p.expr_var = v
} }
// accessing variadiac args // accessing variadiac args
if !p.first_pass() && is_variadic_arg { if is_variadic_arg {
typ = typ.right(3) // TODO: why was this here?
if p.calling_c { // if p.calling_c {
p.error('you cannot currently pass varg to a C function.') // p.error('you cannot currently pass varg to a C function.')
// }
if is_indexer {
l := p.cgen.cur_line.trim_space()
index_val := l.right(l.last_index(' ')).trim_space()
p.cgen.resetln(l.left(fn_ph))
p.table.varg_access << VargAccess{
fn_name: p.cur_fn.name,
tok_idx: p.token_idx,
index: index_val.int()
}
p.cgen.set_placeholder(fn_ph, '${v.name}->args[$index_val]')
return typ
} }
if !is_indexer {
p.error('You must use array access syntax for variadic arguments.')
}
varg_type := typ.right(3)
l := p.cgen.cur_line.trim_space()
index_val := l.right(l.last_index(' ')).trim_space()
p.cgen.resetln(l.left(fn_ph))
p.table.varg_access << VargAccess{
fn_name: p.cur_fn.name,
tok_idx: p.token_idx,
index: index_val.int()
}
p.cgen.set_placeholder(fn_ph, '${v.name}->args[$index_val]')
return typ
} }
// TODO move this from index_expr() // TODO move this from index_expr()
// TODO if p.tok in ... // TODO if p.tok in ...
@ -3264,21 +3257,27 @@ fn (p mut Parser) for_st() {
p.fgen(' ') p.fgen(' ')
tmp := p.get_tmp() tmp := p.get_tmp()
p.cgen.start_tmp() p.cgen.start_tmp()
typ := p.bool_expression() mut typ := p.bool_expression()
is_arr := typ.starts_with('array_') is_arr := typ.starts_with('array_')
is_map := typ.starts_with('map_') is_map := typ.starts_with('map_')
is_str := typ == 'string' is_str := typ == 'string'
if !is_arr && !is_str && !is_map { is_variadic_arg := typ.starts_with('...')
if is_variadic_arg { typ = typ.right(3) }
if !is_arr && !is_str && !is_map && !is_variadic_arg {
p.error('cannot range over type `$typ`') p.error('cannot range over type `$typ`')
} }
expr := p.cgen.end_tmp() expr := p.cgen.end_tmp()
if p.is_js { if !is_variadic_arg {
p.genln('var $tmp = $expr;') if p.is_js {
} else { p.genln('var $tmp = $expr;')
p.genln('$typ $tmp = $expr;') } else {
} p.genln('$typ $tmp = $expr;')
}
}
pad := if is_arr { 6 } else { 4 } pad := if is_arr { 6 } else { 4 }
var_typ := if is_str { 'byte' } else { typ.right(pad) } var_typ := if is_str { 'byte' }
else if is_variadic_arg { typ }
else { typ.right(pad) }
// typ = strings.Replace(typ, "_ptr", "*", -1) // typ = strings.Replace(typ, "_ptr", "*", -1)
mut i_var_type := 'int' mut i_var_type := 'int'
if is_arr { if is_arr {
@ -3292,6 +3291,9 @@ fn (p mut Parser) for_st() {
i_var_type = 'byte' i_var_type = 'byte'
p.gen_for_str_header(i, tmp, var_typ, val) p.gen_for_str_header(i, tmp, var_typ, val)
} }
else if is_variadic_arg {
p.gen_for_varg_header(i, expr, typ, val)
}
// Register temp vars // Register temp vars
if i != '_' { if i != '_' {
p.register_var(Var { p.register_var(Var {
@ -3317,9 +3319,11 @@ fn (p mut Parser) for_st() {
p.fspace() p.fspace()
tmp := p.get_tmp() tmp := p.get_tmp()
p.cgen.start_tmp() p.cgen.start_tmp()
typ := p.bool_expression() mut typ := p.bool_expression()
expr := p.cgen.end_tmp() expr := p.cgen.end_tmp()
is_range := p.tok == .dotdot is_range := p.tok == .dotdot
is_variadic_arg := typ.starts_with('...')
if is_variadic_arg { typ = typ.right(3) }
mut range_end := '' mut range_end := ''
if is_range { if is_range {
p.check_types(typ, 'int') p.check_types(typ, 'int')
@ -3330,24 +3334,32 @@ fn (p mut Parser) for_st() {
} }
is_arr := typ.contains('array') is_arr := typ.contains('array')
is_str := typ == 'string' is_str := typ == 'string'
if !is_arr && !is_str && !is_range { if !is_arr && !is_str && !is_range && !is_variadic_arg {
p.error('cannot range over type `$typ`') p.error('cannot range over type `$typ`')
} }
if p.is_js { if !is_variadic_arg {
p.genln('var $tmp = $expr;') if p.is_js {
} else { p.genln('var $tmp = $expr;')
p.genln('$typ $tmp = $expr;') } else {
p.genln('$typ $tmp = $expr;')
}
} }
// TODO var_type := if... // TODO var_type := if...
mut var_type := '' i := p.get_tmp()
mut var_type := typ
if is_arr { if is_arr {
var_type = typ.right(6)// all after `array_` var_type = typ.right(6)// all after `array_`
p.gen_for_header(i, tmp, var_type, val)
} }
else if is_str { else if is_str {
var_type = 'byte' var_type = 'byte'
p.gen_for_str_header(i, tmp, var_type, val)
} }
else if is_range { else if is_range {
var_type = 'int' var_type = 'int'
p.gen_for_range_header(i, range_end, tmp, var_type, val)
} else if is_variadic_arg {
p.gen_for_varg_header(i, expr, typ, val)
} }
// println('for typ=$typ vartyp=$var_typ') // println('for typ=$typ vartyp=$var_typ')
// Register temp var // Register temp var
@ -3359,16 +3371,6 @@ fn (p mut Parser) for_st() {
is_changed: true is_changed: true
}) })
} }
i := p.get_tmp()
if is_arr {
p.gen_for_header(i, tmp, var_type, val)
}
else if is_str {
p.gen_for_str_header(i, tmp, var_type, val)
}
else if is_range {
p.gen_for_range_header(i, range_end, tmp, var_type, val)
}
} else { } else {
// `for a < b {` // `for a < b {`
p.gen('while (') p.gen('while (')