parser: allow `!` only with bools

pull/2067/head
luoheng 2019-09-21 23:21:45 +08:00 committed by Alexander Medvednikov
parent c01edc650d
commit f1d5f8e2bf
5 changed files with 50 additions and 39 deletions

View File

@ -45,7 +45,7 @@ fn find_windows_kit_internal(key RegKey, versions []string) ?string {
alloc_length := (required_bytes + 2)
mut value := &u16(malloc(alloc_length))
if !value {
if isnil(value) {
continue
}

View File

@ -2079,6 +2079,44 @@ struct IndexCfg {
}
// in and dot have higher priority than `!`
fn (p mut Parser) indot_expr() string {
ph := p.cgen.add_placeholder()
mut typ := p.term()
if p.tok == .dot {
for p.tok == .dot {
typ = p.dot(typ, ph)
}
}
// `a in [1, 2, 3]`
// `key in map`
if p.tok == .key_in {
p.fgen(' ')
p.check(.key_in)
p.fgen(' ')
p.gen('), ')
arr_typ := p.expression()
is_map := arr_typ.starts_with('map_')
if !arr_typ.starts_with('array_') && !is_map {
p.error('`in` requires an array/map')
}
T := p.table.find_type(arr_typ)
if !is_map && !T.has_method('contains') {
p.error('$arr_typ has no method `contains`')
}
// `typ` is element's type
if is_map {
p.cgen.set_placeholder(ph, '_IN_MAP( (')
}
else {
p.cgen.set_placeholder(ph, '_IN($typ, (')
}
p.gen(')')
return 'bool'
}
return typ
}
// returns resulting type
fn (p mut Parser) expression() string {
if p.scanner.file_path.contains('test_test') {
@ -2086,7 +2124,7 @@ fn (p mut Parser) expression() string {
p.print_tok()
}
ph := p.cgen.add_placeholder()
mut typ := p.term()
mut typ := p.indot_expr()
is_str := typ=='string'
is_ustr := typ=='ustring'
// `a << b` ==> `array_push(&a, b)`
@ -2119,43 +2157,12 @@ fn (p mut Parser) expression() string {
return 'int'
}
}
// `a in [1, 2, 3]`
// `key in map`
if p.tok == .key_in {
p.fgen(' ')
p.check(.key_in)
p.fgen(' ')
p.gen('), ')
arr_typ := p.expression()
is_map := arr_typ.starts_with('map_')
if !arr_typ.starts_with('array_') && !is_map {
p.error('`in` requires an array/map')
}
T := p.table.find_type(arr_typ)
if !is_map && !T.has_method('contains') {
p.error('$arr_typ has no method `contains`')
}
// `typ` is element's type
if is_map {
p.cgen.set_placeholder(ph, '_IN_MAP( (')
}
else {
p.cgen.set_placeholder(ph, '_IN($typ, (')
}
p.gen(')')
return 'bool'
}
if p.tok == .righ_shift {
p.next()
p.gen(' >> ')
p.check_types(p.expression(), typ)
return 'int'
}
if p.tok == .dot {
for p.tok == .dot {
typ = p.dot(typ, ph)
}
}
// + - | ^
for p.tok == .plus || p.tok == .minus || p.tok == .pipe || p.tok == .amp ||
p.tok == .xor {
@ -2261,8 +2268,12 @@ fn (p mut Parser) unary() string {
case Token.not:
p.gen('!')
p.check(.not)
typ = 'bool'
p.bool_expression()
// typ should be bool type
typ = p.indot_expr()
if typ != 'bool' {
p.error('operator ! requires bool type, not `$typ`')
}
case Token.bit_not:
p.gen('~')
p.check(.bit_not)
@ -2313,7 +2324,7 @@ fn (p mut Parser) factor() string {
p.fgen('sizeof(')
p.next()
p.check(.lpar)
mut sizeof_typ := p.get_type()
mut sizeof_typ := p.get_type()
p.check(.rpar)
p.gen('$sizeof_typ)')
p.fgen('$sizeof_typ)')

View File

@ -146,7 +146,7 @@ fn run_repl() []string {
cerror(err)
return []string
}
if !func_call && !s.exit_code {
if !func_call && s.exit_code == 0 {
for r.temp_lines.len > 0 {
if !r.temp_lines[0].starts_with('print') {
r.lines << r.temp_lines[0]

View File

@ -10,7 +10,7 @@ module gl
pub fn init_glad() {
ok := C.gladLoadGL()
if !ok {
if isnil(ok) {
println('Failed to initialize glad OpenGL context')
exit(1)
}

View File

@ -513,7 +513,7 @@ fn _parse(rawurl string, via_request bool) ?URL {
}
}
if (url.scheme != '' || !via_request && !rest.starts_with('///')) && rest.starts_with('//') {
if ((url.scheme != '' || !via_request) && !rest.starts_with('///')) && rest.starts_with('//') {
parts := split(rest.right(2), '/', false)
authority := parts[0]
rest = parts[1]