parser: minor `match` simplification

pull/6104/head
Alexander Medvednikov 2020-08-10 19:54:38 +02:00
parent c3cdfa1c96
commit 88988817d0
7 changed files with 50 additions and 25 deletions

View File

@ -411,6 +411,7 @@ pub fn (b []byte) clone() []byte {
return res
}
// TODO remove this once runes are implemented
pub fn (b []byte) bytestr() string {
return bytes2string(b)
}

View File

@ -21,7 +21,7 @@ pub fn (mut b Builder) build_x64(v_files []string, out_file string) {
t2 := time.ticks()
check_time := t2 - t1
b.timing_message('CHECK', check_time)
x64.gen(b.parsed_files, out_file, b.pref)
x64.gen(b.parsed_files, b.table, out_file, b.pref)
t3 := time.ticks()
gen_time := t3 - t2
b.timing_message('x64 GEN', gen_time)

View File

@ -1589,6 +1589,9 @@ pub fn (mut c Checker) enum_decl(decl ast.EnumDecl) {
pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) {
c.expected_type = table.none_type // TODO a hack to make `x := if ... work`
defer {
c.expected_type = table.void_type
}
right_first := assign_stmt.right[0]
mut right_len := assign_stmt.right.len
if right_first is ast.CallExpr || right_first is ast.IfExpr || right_first is ast.MatchExpr {
@ -1720,6 +1723,10 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) {
assign_stmt.op !in [.assign, .decl_assign] && !c.inside_unsafe {
c.warn('pointer arithmetic is only allowed in `unsafe` blocks', assign_stmt.pos)
}
if c.pref.translated {
// TODO fix this in C2V instead, for example cast enums to int before using `|` on them.
return
}
// Single side check
match assign_stmt.op {
.assign {} // No need to do single side check for =. But here put it first for speed.
@ -1774,7 +1781,6 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) {
right.position())
}
}
c.expected_type = table.void_type
}
fn (mut c Checker) check_array_init_para_type(para string, expr ast.Expr, pos token.Position) {

View File

@ -49,6 +49,7 @@ fn (mut g Gen) gen_str_for_type_with_styp(typ table.Type, styp string) string {
table.Struct { g.gen_str_for_struct(it, styp, str_fn_name) }
table.Map { g.gen_str_for_map(it, styp, str_fn_name) }
table.MultiReturn { g.gen_str_for_multi_return(it, styp, str_fn_name) }
table.SumType {}
else { verror("could not generate string method $str_fn_name for type \'$styp\'") }
}
}

View File

@ -10,11 +10,13 @@ import v.errors
import v.pref
import term
import strings
import v.table
pub struct Gen {
out_name string
pref &pref.Preferences // Preferences shared from V struct
mut:
table &table.Table
buf []byte
sect_header_name_pos int
offset i64
@ -78,8 +80,9 @@ enum Size {
_64
}
pub fn gen(files []ast.File, out_name string, pref &pref.Preferences) {
pub fn gen(files []ast.File, table &table.Table, out_name string, pref &pref.Preferences) {
mut g := Gen{
table: table
sect_header_name_pos: 0
out_name: out_name
pref: pref
@ -725,11 +728,22 @@ fn (mut g Gen) assign_stmt(node ast.AssignStmt) {
g.allocate_var(name, 4, 0)
// `mov DWORD PTR [rbp-0x8],eax`
offset := g.get_var_offset(name)
println('ASS $name offset=$offset.hex2()')
println('infix assignment $name offset=$offset.hex2()')
g.mov_reg_to_rbp(offset, .eax)
}
ast.StructInit {
sym := g.table.get_type_symbol(right.typ)
// println(sym)
// println(typeof(sym.info))
info := sym.info as table.Struct
for field in info.fields {
field_name := name + '.' + field.name
println(field_name)
g.allocate_var(field_name, 4, 0)
}
}
else {
g.error_with_pos('assign_stmt unhandled expr: ' + typeof(right), right.position())
g.error_with_pos('x64 assign_stmt unhandled expr: ' + typeof(right), right.position())
}
}
// }

View File

@ -152,7 +152,9 @@ fn (mut p Parser) match_expr() ast.MatchExpr {
p.next()
var_name = p.check_name()
}
p.check(.lcbr)
if p.tok.kind == .lcbr {
p.check(.lcbr)
}
mut branches := []ast.MatchBranch{}
for {
branch_first_pos := p.tok.position()
@ -164,9 +166,9 @@ fn (mut p Parser) match_expr() ast.MatchExpr {
if p.tok.kind == .key_else {
is_else = true
p.next()
} else if p.tok.kind == .name && !(p.tok.lit == 'C' && p.peek_tok.kind == .dot) &&
(p.tok.lit in table.builtin_type_names || p.tok.lit[0].is_capital() ||
(p.peek_tok.kind == .dot && p.peek_tok2.lit[0].is_capital())) {
} else if p.tok.kind == .name && !(p.tok.lit == 'C' &&
p.peek_tok.kind == .dot) && (p.tok.lit in table.builtin_type_names || p.tok.lit[0].is_capital() ||
(p.peek_tok.kind == .dot && p.peek_tok2.lit[0].is_capital())) {
if var_name.len == 0 {
match cond {
ast.Ident {
@ -256,7 +258,7 @@ fn (mut p Parser) match_expr() ast.MatchExpr {
post_comments: post_comments
}
p.close_scope()
if p.tok.kind == .rcbr {
if p.tok.kind == .rcbr || is_else {
break
}
}
@ -266,7 +268,9 @@ fn (mut p Parser) match_expr() ast.MatchExpr {
pos: match_first_pos.pos
len: match_last_pos.pos - match_first_pos.pos + match_last_pos.len
}
p.check(.rcbr)
if p.tok.kind == .rcbr {
p.check(.rcbr)
}
// return ast.StructInit{}
return ast.MatchExpr{
branches: branches

View File

@ -11,20 +11,19 @@ pub fn (c Color) str() string {
fn test_match_integers() {
mut a := 3
mut b := 0
match a {
2 {
println('two')
}
3 {
println('three')
b = 3
}
4 {
println('four')
}
else {
println('???')
}
match a
2 {
println('two')
}
3 {
println('three')
b = 3
}
4 {
println('four')
}
else {
println('???')
}
assert b == 3
assert match 2 {