v2: add method call receiver to cgen & check method args
parent
7a92a47eb3
commit
49f3ce0571
|
@ -170,6 +170,7 @@ pub:
|
||||||
args []Expr
|
args []Expr
|
||||||
muts []bool
|
muts []bool
|
||||||
or_block OrExpr
|
or_block OrExpr
|
||||||
|
mut:
|
||||||
typ table.Type
|
typ table.Type
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -117,7 +117,7 @@ pub fn (s &Scope) innermost(pos int) ?&Scope {
|
||||||
|
|
||||||
[inline]
|
[inline]
|
||||||
fn (s &Scope) contains(pos int) bool {
|
fn (s &Scope) contains(pos int) bool {
|
||||||
return pos > s.start_pos && pos < s.end_pos
|
return pos >= s.start_pos && pos <= s.end_pos
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (sc &Scope) show(level int) string {
|
pub fn (sc &Scope) show(level int) string {
|
||||||
|
|
|
@ -145,7 +145,7 @@ pub fn (c mut Checker) infix_expr(infix_expr ast.InfixExpr) table.Type {
|
||||||
return left_type
|
return left_type
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (c mut Checker) check_assign_expr(assign_expr ast.AssignExpr) {
|
fn (c mut Checker) assign_expr(assign_expr ast.AssignExpr) {
|
||||||
match assign_expr.left {
|
match assign_expr.left {
|
||||||
ast.Ident {
|
ast.Ident {
|
||||||
if it.kind == .blank_ident {
|
if it.kind == .blank_ident {
|
||||||
|
@ -239,25 +239,52 @@ pub fn (c mut Checker) call_expr(call_expr ast.CallExpr) table.Type {
|
||||||
return f.return_type
|
return f.return_type
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (c mut Checker) check_method_call_expr(method_call_expr ast.MethodCallExpr) table.Type {
|
// TODO: clean this up, remove dupe code & consider merging method/fn call everywhere
|
||||||
|
pub fn (c mut Checker) method_call_expr(method_call_expr mut ast.MethodCallExpr) table.Type {
|
||||||
typ := c.expr(method_call_expr.expr)
|
typ := c.expr(method_call_expr.expr)
|
||||||
|
method_call_expr.typ = typ
|
||||||
typ_sym := c.table.get_type_symbol(typ)
|
typ_sym := c.table.get_type_symbol(typ)
|
||||||
name := method_call_expr.name
|
name := method_call_expr.name
|
||||||
if method := typ_sym.find_method(name) {
|
|
||||||
return method.return_type
|
|
||||||
}
|
|
||||||
if typ_sym.kind == .array && name in ['filter', 'clone'] {
|
if typ_sym.kind == .array && name in ['filter', 'clone'] {
|
||||||
|
if name == 'filter' {
|
||||||
|
array_info := typ_sym.info as table.Array
|
||||||
|
elem_type_sym := c.table.get_type_symbol(array_info.elem_type)
|
||||||
|
mut scope := c.file.scope.innermost(method_call_expr.pos.pos) or {
|
||||||
|
c.file.scope
|
||||||
|
}
|
||||||
|
scope.override_var(ast.VarDecl{
|
||||||
|
name: 'it'
|
||||||
|
typ: array_info.elem_type
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if method := typ_sym.find_method(name) {
|
||||||
|
for i, arg_expr in method_call_expr.args {
|
||||||
|
c.expected_type = method.args[i].typ
|
||||||
|
c.expr(arg_expr)
|
||||||
|
}
|
||||||
|
}
|
||||||
return typ
|
return typ
|
||||||
}
|
}
|
||||||
if typ_sym.kind == .array && name in ['first', 'last'] {
|
else if typ_sym.kind == .array && name in ['first', 'last'] {
|
||||||
info := typ_sym.info as table.Array
|
info := typ_sym.info as table.Array
|
||||||
return info.elem_type
|
return info.elem_type
|
||||||
}
|
}
|
||||||
|
if method := typ_sym.find_method(name) {
|
||||||
|
for i, arg_expr in method_call_expr.args {
|
||||||
|
c.expected_type = method.args[i].typ
|
||||||
|
c.expr(arg_expr)
|
||||||
|
}
|
||||||
|
return method.return_type
|
||||||
|
}
|
||||||
// check parent
|
// check parent
|
||||||
if typ_sym.parent_idx != 0 {
|
if typ_sym.parent_idx != 0 {
|
||||||
parent := &c.table.types[typ_sym.parent_idx]
|
parent := &c.table.types[typ_sym.parent_idx]
|
||||||
if method := parent.find_method(name) {
|
if method := parent.find_method(name) {
|
||||||
// println('got method $name, returning')
|
// println('got method $name, returning')
|
||||||
|
for i, arg_expr in method_call_expr.args {
|
||||||
|
c.expected_type = method.args[i].typ
|
||||||
|
c.expr(arg_expr)
|
||||||
|
}
|
||||||
return method.return_type
|
return method.return_type
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -493,7 +520,7 @@ pub fn (c mut Checker) expr(node ast.Expr) table.Type {
|
||||||
return it.typ
|
return it.typ
|
||||||
}
|
}
|
||||||
ast.AssignExpr {
|
ast.AssignExpr {
|
||||||
c.check_assign_expr(it)
|
c.assign_expr(it)
|
||||||
}
|
}
|
||||||
ast.Assoc {
|
ast.Assoc {
|
||||||
scope := c.file.scope.innermost(it.pos.pos) or {
|
scope := c.file.scope.innermost(it.pos.pos) or {
|
||||||
|
@ -547,7 +574,7 @@ pub fn (c mut Checker) expr(node ast.Expr) table.Type {
|
||||||
return c.match_expr(mut it)
|
return c.match_expr(mut it)
|
||||||
}
|
}
|
||||||
ast.MethodCallExpr {
|
ast.MethodCallExpr {
|
||||||
return c.check_method_call_expr(it)
|
return c.method_call_expr(mut it)
|
||||||
}
|
}
|
||||||
ast.PostfixExpr {
|
ast.PostfixExpr {
|
||||||
return c.postfix_expr(it)
|
return c.postfix_expr(it)
|
||||||
|
|
|
@ -491,9 +491,17 @@ fn (g mut Gen) expr(node ast.Expr) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast.MethodCallExpr {
|
ast.MethodCallExpr {
|
||||||
typ := 'TODO'
|
mut receiver_name := 'TODO'
|
||||||
name := it.name.replace('.', '__')
|
// TODO: there are still due to unchecked exprs (opt/some fn arg)
|
||||||
g.write('${typ}_${name}(')
|
if it.typ != 0 {
|
||||||
|
typ_sym := g.table.get_type_symbol(it.typ)
|
||||||
|
receiver_name = typ_sym.name
|
||||||
|
}
|
||||||
|
name := '${receiver_name}_$it.name'.replace('.', '__')
|
||||||
|
if table.type_is_ptr(it.typ) {
|
||||||
|
g.write('&')
|
||||||
|
}
|
||||||
|
g.write('${name}(')
|
||||||
g.expr(it.expr)
|
g.expr(it.expr)
|
||||||
if it.args.len > 0 {
|
if it.args.len > 0 {
|
||||||
g.write(', ')
|
g.write(', ')
|
||||||
|
|
|
@ -450,12 +450,13 @@ pub fn (p &Parser) warn(s string) {
|
||||||
|
|
||||||
pub fn (p mut Parser) parse_ident(is_c bool) ast.Ident {
|
pub fn (p mut Parser) parse_ident(is_c bool) ast.Ident {
|
||||||
// p.warn('name ')
|
// p.warn('name ')
|
||||||
|
pos := p.tok.position()
|
||||||
mut name := p.check_name()
|
mut name := p.check_name()
|
||||||
if name == '_' {
|
if name == '_' {
|
||||||
return ast.Ident{
|
return ast.Ident{
|
||||||
name: '_'
|
name: '_'
|
||||||
kind: .blank_ident
|
kind: .blank_ident
|
||||||
pos: p.tok.position()
|
pos: pos
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if p.expr_mod.len > 0 {
|
if p.expr_mod.len > 0 {
|
||||||
|
@ -465,7 +466,7 @@ pub fn (p mut Parser) parse_ident(is_c bool) ast.Ident {
|
||||||
kind: .unresolved
|
kind: .unresolved
|
||||||
name: name
|
name: name
|
||||||
is_c: is_c
|
is_c: is_c
|
||||||
pos: p.tok.position()
|
pos: pos
|
||||||
}
|
}
|
||||||
// variable
|
// variable
|
||||||
if p.expr_mod.len == 0 {
|
if p.expr_mod.len == 0 {
|
||||||
|
@ -635,11 +636,9 @@ pub fn (p mut Parser) expr(precedence int) ast.Expr {
|
||||||
}
|
}
|
||||||
.dot {
|
.dot {
|
||||||
// .enum_val
|
// .enum_val
|
||||||
// node,typ = p.enum_val()
|
|
||||||
node = p.enum_val()
|
node = p.enum_val()
|
||||||
}
|
}
|
||||||
.chartoken {
|
.chartoken {
|
||||||
typ = table.byte_type
|
|
||||||
node = ast.CharLiteral{
|
node = ast.CharLiteral{
|
||||||
val: p.tok.lit
|
val: p.tok.lit
|
||||||
}
|
}
|
||||||
|
@ -656,11 +655,9 @@ pub fn (p mut Parser) expr(precedence int) ast.Expr {
|
||||||
node = ast.BoolLiteral{
|
node = ast.BoolLiteral{
|
||||||
val: p.tok.kind == .key_true
|
val: p.tok.kind == .key_true
|
||||||
}
|
}
|
||||||
typ = table.bool_type
|
|
||||||
p.next()
|
p.next()
|
||||||
}
|
}
|
||||||
.key_match {
|
.key_match {
|
||||||
// node,typ = p.match_expr()
|
|
||||||
node = p.match_expr()
|
node = p.match_expr()
|
||||||
}
|
}
|
||||||
.number {
|
.number {
|
||||||
|
@ -682,7 +679,6 @@ pub fn (p mut Parser) expr(precedence int) ast.Expr {
|
||||||
}
|
}
|
||||||
.key_none {
|
.key_none {
|
||||||
p.next()
|
p.next()
|
||||||
typ = table.none_type
|
|
||||||
node = ast.None{}
|
node = ast.None{}
|
||||||
}
|
}
|
||||||
.key_sizeof {
|
.key_sizeof {
|
||||||
|
@ -700,7 +696,6 @@ pub fn (p mut Parser) expr(precedence int) ast.Expr {
|
||||||
node = ast.SizeOf{
|
node = ast.SizeOf{
|
||||||
type_name: type_name
|
type_name: type_name
|
||||||
}
|
}
|
||||||
typ = table.int_type
|
|
||||||
}
|
}
|
||||||
// Map `{"age": 20}` or `{ x | foo:bar, a:10 }`
|
// Map `{"age": 20}` or `{ x | foo:bar, a:10 }`
|
||||||
.lcbr {
|
.lcbr {
|
||||||
|
@ -761,7 +756,7 @@ pub fn (p mut Parser) expr(precedence int) ast.Expr {
|
||||||
node = p.assign_expr(node)
|
node = p.assign_expr(node)
|
||||||
}
|
}
|
||||||
else if p.tok.kind == .dot {
|
else if p.tok.kind == .dot {
|
||||||
node = p.dot_expr(node, typ)
|
node = p.dot_expr(node)
|
||||||
}
|
}
|
||||||
else if p.tok.kind == .lsbr {
|
else if p.tok.kind == .lsbr {
|
||||||
node = p.index_expr(node)
|
node = p.index_expr(node)
|
||||||
|
@ -852,15 +847,6 @@ fn (p mut Parser) index_expr(left ast.Expr) ast.IndexExpr {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// get the element type
|
|
||||||
/*
|
|
||||||
mut typ := left_type
|
|
||||||
left_type_sym := p.table.get_type_symbol(left_type)
|
|
||||||
if left_type_sym.kind == .array {
|
|
||||||
info := left_type_sym.info as table.Array
|
|
||||||
typ = info.elem_type
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
// [expr]
|
// [expr]
|
||||||
p.check(.rsbr)
|
p.check(.rsbr)
|
||||||
return ast.IndexExpr{
|
return ast.IndexExpr{
|
||||||
|
@ -870,24 +856,25 @@ fn (p mut Parser) index_expr(left ast.Expr) ast.IndexExpr {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (p mut Parser) filter(typ table.Type) {
|
fn (p mut Parser) filter() {
|
||||||
p.scope.register_var(ast.VarDecl{
|
p.scope.register_var(ast.VarDecl{
|
||||||
name: 'it'
|
name: 'it'
|
||||||
typ: typ
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (p mut Parser) dot_expr(left ast.Expr, left_type table.Type) ast.Expr {
|
fn (p mut Parser) dot_expr(left ast.Expr) ast.Expr {
|
||||||
p.next()
|
p.next()
|
||||||
field_name := p.check_name()
|
field_name := p.check_name()
|
||||||
if field_name == 'filter' {
|
if field_name == 'filter' {
|
||||||
p.open_scope()
|
p.open_scope()
|
||||||
p.filter(left_type)
|
p.filter()
|
||||||
defer {
|
// wrong tok position when using defer
|
||||||
p.close_scope()
|
// defer {
|
||||||
}
|
// p.close_scope()
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
// Method call
|
// Method call
|
||||||
|
pos := p.tok.position()
|
||||||
if p.tok.kind == .lpar {
|
if p.tok.kind == .lpar {
|
||||||
p.next()
|
p.next()
|
||||||
args,muts := p.call_args()
|
args,muts := p.call_args()
|
||||||
|
@ -901,13 +888,16 @@ fn (p mut Parser) dot_expr(left ast.Expr, left_type table.Type) ast.Expr {
|
||||||
name: field_name
|
name: field_name
|
||||||
args: args
|
args: args
|
||||||
muts: muts
|
muts: muts
|
||||||
pos: p.tok.position()
|
pos: pos
|
||||||
or_block: ast.OrExpr{
|
or_block: ast.OrExpr{
|
||||||
stmts: or_stmts
|
stmts: or_stmts
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mut node := ast.Expr{}
|
mut node := ast.Expr{}
|
||||||
node = mcall_expr
|
node = mcall_expr
|
||||||
|
if field_name == 'filter' {
|
||||||
|
p.close_scope()
|
||||||
|
}
|
||||||
return node
|
return node
|
||||||
}
|
}
|
||||||
sel_expr := ast.SelectorExpr{
|
sel_expr := ast.SelectorExpr{
|
||||||
|
@ -917,6 +907,9 @@ fn (p mut Parser) dot_expr(left ast.Expr, left_type table.Type) ast.Expr {
|
||||||
}
|
}
|
||||||
mut node := ast.Expr{}
|
mut node := ast.Expr{}
|
||||||
node = sel_expr
|
node = sel_expr
|
||||||
|
if field_name == 'filter' {
|
||||||
|
p.close_scope()
|
||||||
|
}
|
||||||
return node
|
return node
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue