parser/cgen: is keyword

pull/4447/head
Alexander Medvednikov 2020-04-16 15:32:11 +02:00
parent cc9828b481
commit af224b4933
6 changed files with 76 additions and 21 deletions

View File

@ -196,6 +196,9 @@ pub fn (c mut Checker) infix_expr(infix_expr mut ast.InfixExpr) table.Type {
left_type := c.expr(infix_expr.left) left_type := c.expr(infix_expr.left)
infix_expr.left_type = left_type infix_expr.left_type = left_type
c.expected_type = left_type c.expected_type = left_type
if infix_expr.op == .key_is {
return table.bool_type
}
right_type := c.expr(infix_expr.right) right_type := c.expr(infix_expr.right)
infix_expr.right_type = right_type infix_expr.right_type = right_type
right := c.table.get_type_symbol(right_type) right := c.table.get_type_symbol(right_type)
@ -1709,6 +1712,9 @@ pub fn (c mut Checker) warn(s string, pos token.Position) {
} }
pub fn (c mut Checker) error(message string, pos token.Position) { pub fn (c mut Checker) error(message string, pos token.Position) {
if c.pref.is_verbose {
print_backtrace()
}
c.warn_or_error(message, pos, false) c.warn_or_error(message, pos, false)
} }

View File

@ -126,15 +126,10 @@ pub fn cgen(files []ast.File, table &table.Table, pref &pref.Preferences) string
} }
// //
g.finish() g.finish()
return g.hashes() + return g.hashes() + '\n// V typedefs:\n' + g.typedefs.str() + '\n// V typedefs2:\n' + g.typedefs2.str() +
'\n// V typedefs:\n' + g.typedefs.str() + '\n// V cheaders:\n' + g.cheaders.str() + '\n// V includes:\n' + g.includes.str() + '\n// V definitions:\n' +
'\n// V typedefs2:\n' + g.typedefs2.str() + g.definitions.str() + '\n// V gowrappers:\n' + g.gowrappers.str() + '\n// V stringliterals:\n' +
'\n// V cheaders:\n' + g.cheaders.str() + g.stringliterals.str() + '\n// V out\n' + g.out.str()
'\n// V includes:\n' + g.includes.str() +
'\n// V definitions:\n' + g.definitions.str() +
'\n// V gowrappers:\n' + g.gowrappers.str() +
'\n// V stringliterals:\n' + g.stringliterals.str() +
'\n// V out\n' + g.out.str()
} }
pub fn (g Gen) hashes() string { pub fn (g Gen) hashes() string {
@ -1211,6 +1206,10 @@ fn (g mut Gen) infix_expr(node ast.InfixExpr) {
// string + string, string == string etc // string + string, string == string etc
// g.infix_op = node.op // g.infix_op = node.op
left_sym := g.table.get_type_symbol(node.left_type) left_sym := g.table.get_type_symbol(node.left_type)
if node.op == .key_is {
g.is_expr(node)
return
}
right_sym := g.table.get_type_symbol(node.right_type) right_sym := g.table.get_type_symbol(node.right_type)
if node.left_type == table.string_type_idx && node.op != .key_in && node.op != .not_in { if node.left_type == table.string_type_idx && node.op != .key_in && node.op != .not_in {
fn_name := match node.op { fn_name := match node.op {
@ -2828,6 +2827,12 @@ fn (g mut Gen) go_stmt(node ast.GoStmt) {
} }
} }
fn (g mut Gen) is_expr(node ast.InfixExpr) {
g.expr(node.left)
g.write('.typ == ')
g.expr(node.right)
}
// already generated styp, reuse it // already generated styp, reuse it
fn (g mut Gen) gen_str_for_type(sym table.TypeSymbol, styp string) { fn (g mut Gen) gen_str_for_type(sym table.TypeSymbol, styp string) {
if sym.has_method('str') || styp in g.str_types { if sym.has_method('str') || styp in g.str_types {

View File

@ -21,7 +21,7 @@ mut:
peek_tok token.Token peek_tok token.Token
table &table.Table table &table.Table
is_c bool is_c bool
is_js bool is_js bool
inside_if bool inside_if bool
inside_for bool inside_for bool
inside_fn bool inside_fn bool
@ -39,6 +39,7 @@ mut:
inside_match bool // to separate `match A { }` from `Struct{}` inside_match bool // to separate `match A { }` from `Struct{}`
inside_match_case bool // to separate `match_expr { }` from `Struct{}` inside_match_case bool // to separate `match_expr { }` from `Struct{}`
is_stmt_ident bool // true while the beginning of a statement is an ident/selector is_stmt_ident bool // true while the beginning of a statement is an ident/selector
inside_is bool // `is Type`, expecting type
} }
// for tests // for tests
@ -616,6 +617,11 @@ fn (p mut Parser) struct_init(short_syntax bool) ast.StructInit {
pub fn (p mut Parser) name_expr() ast.Expr { pub fn (p mut Parser) name_expr() ast.Expr {
var node := ast.Expr{} var node := ast.Expr{}
if p.inside_is {
return ast.Type{
typ: p.parse_type()
}
}
is_c := p.tok.lit == 'C' is_c := p.tok.lit == 'C'
is_js := p.tok.lit == 'JS' is_js := p.tok.lit == 'JS'
var mod := '' var mod := ''
@ -635,8 +641,8 @@ pub fn (p mut Parser) name_expr() ast.Expr {
return p.string_expr() return p.string_expr()
} }
known_var := p.scope.known_var(p.tok.lit) known_var := p.scope.known_var(p.tok.lit)
if p.peek_tok.kind == .dot && !known_var && (is_c || is_js || p.known_import(p.tok.lit) || p.mod.all_after('.') == if p.peek_tok.kind == .dot && !known_var && (is_c || is_js || p.known_import(p.tok.lit) ||
p.tok.lit) { p.mod.all_after('.') == p.tok.lit) {
if is_c { if is_c {
mod = 'C' mod = 'C'
} else if is_js { } else if is_js {
@ -1044,7 +1050,11 @@ fn (p mut Parser) infix_expr(left ast.Expr) ast.Expr {
pos := p.tok.position() pos := p.tok.position()
p.next() p.next()
var right := ast.Expr{} var right := ast.Expr{}
if op == .key_is {
p.inside_is = true
}
right = p.expr(precedence) right = p.expr(precedence)
p.inside_is = false
var expr := ast.Expr{} var expr := ast.Expr{}
expr = ast.InfixExpr{ expr = ast.InfixExpr{
left: left left: left
@ -1511,7 +1521,7 @@ fn (p mut Parser) const_decl() ast.ConstDecl {
if p.tok.kind != .lpar { if p.tok.kind != .lpar {
p.error('consts must be grouped, e.g.\nconst (\n\ta = 1\n)') p.error('consts must be grouped, e.g.\nconst (\n\ta = 1\n)')
} }
p.next() // ( p.next() // (
var fields := []ast.ConstField var fields := []ast.ConstField
for p.tok.kind != .rpar { for p.tok.kind != .rpar {
if p.tok.kind == .comment { if p.tok.kind == .comment {

View File

@ -14,7 +14,7 @@ fn foo(b int, a mut []int) {
} }
fn test_mut() { fn test_mut() {
mut numbers := [1, 2, 3] var numbers := [1, 2, 3]
foo(7, mut numbers) foo(7, mut numbers)
assert numbers.len == 3 assert numbers.len == 3
// TODO bring back once << works with mutable args // TODO bring back once << works with mutable args
@ -23,15 +23,16 @@ fn test_mut() {
// assert numbers[3] == 4 // assert numbers[3] == 4
println(numbers) println(numbers)
n := 1 n := 1
mut b := &n var b := &n
*b = 10 //
//mut b := mut a (*b) = 10
//b = 10 // mut b := mut a
// b = 10
} }
fn test_mut_2() { fn test_mut_2() {
zero := 0 zero := 0
mut b := B{} var b := B{}
b.a << A{} b.a << A{}
b.a[0].v = [9, 8, 7] b.a[0].v = [9, 8, 7]
b.a[0].v << 6 b.a[0].v << 6

View File

@ -0,0 +1,31 @@
type Expr = IfExpr | IntegerLiteral
struct IfExpr {
pos int
}
struct IntegerLiteral {
val string
}
fn handle(e Expr) string {
assert e is IntegerLiteral
if e is IntegerLiteral {
println('int')
}
match e {
IntegerLiteral {
return 'int'
}
IfExpr {
return 'if'
}
}
return ''
}
fn test_expr() {
expr := IntegerLiteral{'12'}
assert handle(expr) == 'int'
// assert expr is IntegerLiteral
}

View File

@ -101,6 +101,7 @@ pub enum Kind {
key_import_const key_import_const
key_in key_in
key_interface key_interface
key_is
// key_it // key_it
key_match key_match
key_module key_module
@ -246,6 +247,7 @@ fn build_token_str() []string {
s[Kind.key_select] = 'select' s[Kind.key_select] = 'select'
s[Kind.key_none] = 'none' s[Kind.key_none] = 'none'
s[Kind.key_offsetof] = '__offsetof' s[Kind.key_offsetof] = '__offsetof'
s[Kind.key_is] = 'is'
s[Kind.key_var] = 'var' s[Kind.key_var] = 'var'
return s return s
} }
@ -385,7 +387,7 @@ pub fn (tok Token) precedence() int {
.left_shift_assign, .right_shift_assign, .mult_assign, .xor_assign { .left_shift_assign, .right_shift_assign, .mult_assign, .xor_assign {
return int(Precedence.assign) return int(Precedence.assign)
} }
.key_in, .not_in, .key_as { .key_in, .not_in, .key_as, .key_is {
return int(Precedence.in_as) return int(Precedence.in_as)
} }
.logical_or, .and { .logical_or, .and {
@ -425,7 +427,7 @@ pub fn (k Kind) is_start_of_type() bool {
pub fn (kind Kind) is_infix() bool { pub fn (kind Kind) is_infix() bool {
return kind in [.plus, .minus, .mod, .mul, .div, .eq, .ne, .gt, .lt, .key_in, return kind in [.plus, .minus, .mod, .mul, .div, .eq, .ne, .gt, .lt, .key_in,
// //
.key_as, .ge, .le, .logical_or, .xor, .not_in, .key_as, .ge, .le, .logical_or, .xor, .not_in, .key_is,
// //
.and, .dot, .pipe, .amp, .left_shift, .right_shift] .and, .dot, .pipe, .amp, .left_shift, .right_shift]
} }