compiler: re assignable blank identifier `_` & no longer a variable

pull/2100/head
joe-conigliaro 2019-09-25 21:53:44 +10:00 committed by Alexander Medvednikov
parent ab52b453cb
commit 746655c1d5
3 changed files with 58 additions and 8 deletions

View File

@ -68,6 +68,34 @@ fn (p mut Parser) gen_fn_decl(f Fn, typ, str_args string) {
p.genln('$dll_export_linkage$typ $fn_name_cgen($str_args) {') p.genln('$dll_export_linkage$typ $fn_name_cgen($str_args) {')
} }
// blank identifer assignment `_ = 111`
fn (p mut Parser) gen_blank_identifier_assign() {
p.next()
p.check(.assign)
pos := p.cgen.add_placeholder()
mut typ := p.bool_expression()
tmp := p.get_tmp()
// handle or
if p.tok == .key_orelse {
p.cgen.set_placeholder(pos, '$typ $tmp = ')
p.genln(';')
typ = typ.replace('Option_', '')
p.next()
p.check(.lcbr)
p.genln('if (!$tmp .ok) {')
p.register_var(Var {
name: 'err'
typ: 'string'
is_mut: false
is_used: true
})
p.genln('string err = $tmp . error;')
p.statements()
p.returns = false
}
p.gen(';')
}
fn types_to_c(types []Type, table &Table) string { fn types_to_c(types []Type, table &Table) string {
mut sb := strings.new_builder(10) mut sb := strings.new_builder(10)
for t in types { for t in types {

View File

@ -33,6 +33,15 @@ fn (p mut Parser) gen_fn_decl(f Fn, typ, _str_args string) {
} }
} }
fn (p mut Parser) gen_blank_identifier_assign() {
typ := p.bool_expression()
or_else := p.tok == .key_orelse
//tmp := p.get_tmp()
if or_else {
//panic('optionals todo')
}
}
fn types_to_c(types []Type, table &Table) string { fn types_to_c(types []Type, table &Table) string {
mut sb := strings.new_builder(10) mut sb := strings.new_builder(10)
for t in types { for t in types {

View File

@ -1196,6 +1196,10 @@ fn (p mut Parser) statement(add_semi bool) string {
//p.log('var decl') //p.log('var decl')
p.var_decl() p.var_decl()
} }
// `_ = 777`
else if p.lit == '_' && p.peek() == .assign {
p.gen_blank_identifier_assign()
}
else { else {
// panic and exit count as returns since they stop the function // panic and exit count as returns since they stop the function
if p.lit == 'panic' || p.lit == 'exit' { if p.lit == 'panic' || p.lit == 'exit' {
@ -1373,15 +1377,13 @@ fn (p mut Parser) var_decl() {
types = t.replace('_V_MulRet_', '').replace('_PTR_', '*').split('_V_') types = t.replace('_V_MulRet_', '').replace('_PTR_', '*').split('_V_')
} }
for i, name in names { for i, name in names {
if name == '_' {
// if names.len == 1 {
// p.error('no new variables on left side of :=')
// }
continue
}
typ := types[i] typ := types[i]
if names.len > 1 {
if names.len != types.len {
mr_fn := p.cgen.cur_line.find_between('=', '(').trim_space()
p.error('assignment mismatch: ${names.len} variables but `$mr_fn` returns $types.len values.')
}
p.gen(';\n')
p.gen('$typ $name = ${mr_var_name}.var_$i')
}
// println('var decl tok=${p.strtok()} ismut=$is_mut') // println('var decl tok=${p.strtok()} ismut=$is_mut')
var_scanner_pos := p.scanner.get_scanner_pos() var_scanner_pos := p.scanner.get_scanner_pos()
// name := p.check_name() // name := p.check_name()
@ -1395,6 +1397,14 @@ fn (p mut Parser) var_decl() {
if name.len > 1 && contains_capital(name) { if name.len > 1 && contains_capital(name) {
p.error('variable names cannot contain uppercase letters, use snake_case instead') p.error('variable names cannot contain uppercase letters, use snake_case instead')
} }
if names.len > 1 {
if names.len != types.len {
mr_fn := p.cgen.cur_line.find_between('=', '(').trim_space()
p.error('assignment mismatch: ${names.len} variables but `$mr_fn` returns $types.len values.')
}
p.gen(';\n')
p.gen('$typ $name = ${mr_var_name}.var_$i')
}
// p.check_space(.decl_assign) // := // p.check_space(.decl_assign) // :=
// typ := p.gen_var_decl(name, is_static) // typ := p.gen_var_decl(name, is_static)
p.register_var(Var { p.register_var(Var {
@ -1588,6 +1598,9 @@ fn (p mut Parser) name_expr() string {
} }
// Variable // Variable
for { // TODO remove for { // TODO remove
if name == '_' {
p.error('cannot use `_` as value.')
}
mut v := p.find_var_check_new_var(name) or { break } mut v := p.find_var_check_new_var(name) or { break }
if ptr { if ptr {
p.gen('& /*v*/ ') p.gen('& /*v*/ ')