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)
infix_expr.left_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)
infix_expr.right_type = 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) {
if c.pref.is_verbose {
print_backtrace()
}
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()
return g.hashes() +
'\n// V typedefs:\n' + g.typedefs.str() +
'\n// V typedefs2:\n' + g.typedefs2.str() +
'\n// V cheaders:\n' + g.cheaders.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()
return g.hashes() + '\n// V typedefs:\n' + g.typedefs.str() + '\n// V typedefs2:\n' + g.typedefs2.str() +
'\n// V cheaders:\n' + g.cheaders.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 {
@ -1211,6 +1206,10 @@ fn (g mut Gen) infix_expr(node ast.InfixExpr) {
// string + string, string == string etc
// g.infix_op = node.op
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)
if node.left_type == table.string_type_idx && node.op != .key_in && node.op != .not_in {
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
fn (g mut Gen) gen_str_for_type(sym table.TypeSymbol, styp string) {
if sym.has_method('str') || styp in g.str_types {

View File

@ -21,7 +21,7 @@ mut:
peek_tok token.Token
table &table.Table
is_c bool
is_js bool
is_js bool
inside_if bool
inside_for bool
inside_fn bool
@ -39,6 +39,7 @@ mut:
inside_match bool // to separate `match A { }` 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
inside_is bool // `is Type`, expecting type
}
// 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 {
var node := ast.Expr{}
if p.inside_is {
return ast.Type{
typ: p.parse_type()
}
}
is_c := p.tok.lit == 'C'
is_js := p.tok.lit == 'JS'
var mod := ''
@ -635,8 +641,8 @@ pub fn (p mut Parser) name_expr() ast.Expr {
return p.string_expr()
}
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('.') ==
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('.') == p.tok.lit) {
if is_c {
mod = 'C'
} else if is_js {
@ -1044,7 +1050,11 @@ fn (p mut Parser) infix_expr(left ast.Expr) ast.Expr {
pos := p.tok.position()
p.next()
var right := ast.Expr{}
if op == .key_is {
p.inside_is = true
}
right = p.expr(precedence)
p.inside_is = false
var expr := ast.Expr{}
expr = ast.InfixExpr{
left: left
@ -1511,7 +1521,7 @@ fn (p mut Parser) const_decl() ast.ConstDecl {
if p.tok.kind != .lpar {
p.error('consts must be grouped, e.g.\nconst (\n\ta = 1\n)')
}
p.next() // (
p.next() // (
var fields := []ast.ConstField
for p.tok.kind != .rpar {
if p.tok.kind == .comment {

View File

@ -14,7 +14,7 @@ fn foo(b int, a mut []int) {
}
fn test_mut() {
mut numbers := [1, 2, 3]
var numbers := [1, 2, 3]
foo(7, mut numbers)
assert numbers.len == 3
// TODO bring back once << works with mutable args
@ -23,15 +23,16 @@ fn test_mut() {
// assert numbers[3] == 4
println(numbers)
n := 1
mut b := &n
*b = 10
//mut b := mut a
//b = 10
var b := &n
//
(*b) = 10
// mut b := mut a
// b = 10
}
fn test_mut_2() {
zero := 0
mut b := B{}
var b := B{}
b.a << A{}
b.a[0].v = [9, 8, 7]
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_in
key_interface
key_is
// key_it
key_match
key_module
@ -246,6 +247,7 @@ fn build_token_str() []string {
s[Kind.key_select] = 'select'
s[Kind.key_none] = 'none'
s[Kind.key_offsetof] = '__offsetof'
s[Kind.key_is] = 'is'
s[Kind.key_var] = 'var'
return s
}
@ -385,7 +387,7 @@ pub fn (tok Token) precedence() int {
.left_shift_assign, .right_shift_assign, .mult_assign, .xor_assign {
return int(Precedence.assign)
}
.key_in, .not_in, .key_as {
.key_in, .not_in, .key_as, .key_is {
return int(Precedence.in_as)
}
.logical_or, .and {
@ -425,7 +427,7 @@ pub fn (k Kind) is_start_of_type() bool {
pub fn (kind Kind) is_infix() bool {
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]
}