2020-01-23 21:04:46 +01:00
|
|
|
// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved.
|
2020-01-02 08:30:15 +01:00
|
|
|
// Use of this source code is governed by an MIT license
|
|
|
|
// that can be found in the LICENSE file.
|
|
|
|
module parser
|
|
|
|
|
2020-04-14 19:32:23 +02:00
|
|
|
import v.ast
|
|
|
|
import v.table
|
|
|
|
import v.scanner
|
|
|
|
import v.token
|
2020-04-16 11:29:36 +02:00
|
|
|
import v.util
|
2020-01-02 08:30:15 +01:00
|
|
|
|
2020-04-21 05:11:50 +02:00
|
|
|
pub fn (mut p Parser) call_expr(is_c, is_js bool, mod string) ast.CallExpr {
|
2020-04-10 14:53:06 +02:00
|
|
|
first_pos := p.tok.position()
|
2020-02-19 07:16:38 +01:00
|
|
|
name := p.check_name()
|
2020-04-07 01:02:48 +02:00
|
|
|
fn_name := if is_c {
|
|
|
|
'C.$name'
|
2020-04-15 23:16:49 +02:00
|
|
|
} else if is_js {
|
|
|
|
'JS.$name'
|
2020-04-07 01:02:48 +02:00
|
|
|
} else if mod.len > 0 {
|
|
|
|
'${mod}.$name'
|
|
|
|
} else {
|
|
|
|
name
|
|
|
|
}
|
2020-01-02 08:30:15 +01:00
|
|
|
p.check(.lpar)
|
2020-03-14 11:11:43 +01:00
|
|
|
args := p.call_args()
|
2020-04-10 14:53:06 +02:00
|
|
|
last_pos := p.tok.position()
|
|
|
|
p.check(.rpar)
|
|
|
|
pos := token.Position{
|
|
|
|
line_nr: first_pos.line_nr
|
|
|
|
pos: first_pos.pos
|
|
|
|
len: last_pos.pos - first_pos.pos + last_pos.len
|
|
|
|
}
|
2020-04-26 09:17:13 +02:00
|
|
|
mut or_stmts := []ast.Stmt{}
|
2020-04-21 05:11:50 +02:00
|
|
|
mut is_or_block_used := false
|
2020-02-29 15:03:32 +01:00
|
|
|
if p.tok.kind == .key_orelse {
|
|
|
|
p.next()
|
2020-03-18 09:56:19 +01:00
|
|
|
p.open_scope()
|
2020-04-04 05:14:40 +02:00
|
|
|
p.scope.register('err', ast.Var{
|
2020-03-18 09:56:19 +01:00
|
|
|
name: 'err'
|
2020-03-18 10:00:33 +01:00
|
|
|
typ: table.string_type
|
2020-03-18 09:56:19 +01:00
|
|
|
})
|
2020-04-04 20:47:57 +02:00
|
|
|
p.scope.register('errcode', ast.Var{
|
|
|
|
name: 'errcode'
|
|
|
|
typ: table.int_type
|
|
|
|
})
|
2020-04-07 16:36:00 +02:00
|
|
|
is_or_block_used = true
|
2020-03-18 09:56:19 +01:00
|
|
|
or_stmts = p.parse_block_no_scope()
|
|
|
|
p.close_scope()
|
2020-02-29 15:03:32 +01:00
|
|
|
}
|
2020-01-02 08:30:15 +01:00
|
|
|
node := ast.CallExpr{
|
|
|
|
name: fn_name
|
|
|
|
args: args
|
2020-04-04 05:14:40 +02:00
|
|
|
mod: p.mod
|
2020-04-10 14:53:06 +02:00
|
|
|
pos: pos
|
2020-02-18 18:13:34 +01:00
|
|
|
is_c: is_c
|
2020-04-15 23:16:49 +02:00
|
|
|
is_js: is_js
|
2020-02-29 15:03:32 +01:00
|
|
|
or_block: ast.OrExpr{
|
2020-04-07 16:36:00 +02:00
|
|
|
stmts: or_stmts
|
|
|
|
is_used: is_or_block_used
|
|
|
|
}
|
2020-02-04 17:44:39 +01:00
|
|
|
}
|
2020-02-15 13:37:48 +01:00
|
|
|
return node
|
2020-01-02 08:30:15 +01:00
|
|
|
}
|
|
|
|
|
2020-04-21 05:11:50 +02:00
|
|
|
pub fn (mut p Parser) call_args() []ast.CallArg {
|
2020-04-26 09:17:13 +02:00
|
|
|
mut args := []ast.CallArg{}
|
2020-01-07 01:08:24 +01:00
|
|
|
for p.tok.kind != .rpar {
|
2020-04-21 05:11:50 +02:00
|
|
|
mut is_mut := false
|
2020-02-04 12:50:58 +01:00
|
|
|
if p.tok.kind == .key_mut {
|
|
|
|
p.check(.key_mut)
|
2020-03-14 11:11:43 +01:00
|
|
|
is_mut = true
|
2020-02-04 12:50:58 +01:00
|
|
|
}
|
2020-03-05 12:13:45 +01:00
|
|
|
e := p.expr(0)
|
2020-03-14 11:11:43 +01:00
|
|
|
args << ast.CallArg{
|
|
|
|
is_mut: is_mut
|
|
|
|
expr: e
|
|
|
|
}
|
2020-01-07 01:08:24 +01:00
|
|
|
if p.tok.kind != .rpar {
|
|
|
|
p.check(.comma)
|
|
|
|
}
|
|
|
|
}
|
2020-03-14 11:11:43 +01:00
|
|
|
return args
|
2020-01-07 01:08:24 +01:00
|
|
|
}
|
|
|
|
|
2020-04-21 05:11:50 +02:00
|
|
|
fn (mut p Parser) fn_decl() ast.FnDecl {
|
2020-04-19 00:07:57 +02:00
|
|
|
start_pos := p.tok.position()
|
2020-03-05 16:13:14 +01:00
|
|
|
is_deprecated := p.attr == 'deprecated'
|
2020-01-02 20:09:15 +01:00
|
|
|
is_pub := p.tok.kind == .key_pub
|
|
|
|
if is_pub {
|
|
|
|
p.next()
|
|
|
|
}
|
2020-01-02 08:30:15 +01:00
|
|
|
p.check(.key_fn)
|
2020-04-22 13:11:58 +02:00
|
|
|
p.open_scope()
|
2020-04-15 23:16:49 +02:00
|
|
|
// C. || JS.
|
2020-02-04 09:54:15 +01:00
|
|
|
is_c := p.tok.kind == .name && p.tok.lit == 'C'
|
2020-04-15 23:16:49 +02:00
|
|
|
is_js := p.tok.kind == .name && p.tok.lit == 'JS'
|
|
|
|
if is_c || is_js {
|
2020-02-04 09:54:15 +01:00
|
|
|
p.next()
|
|
|
|
p.check(.dot)
|
|
|
|
}
|
2020-01-02 20:09:15 +01:00
|
|
|
// Receiver?
|
2020-04-21 05:11:50 +02:00
|
|
|
mut rec_name := ''
|
|
|
|
mut is_method := false
|
|
|
|
mut rec_type := table.void_type
|
|
|
|
mut rec_mut := false
|
2020-04-26 09:17:13 +02:00
|
|
|
mut args := []table.Arg{}
|
2020-01-02 20:09:15 +01:00
|
|
|
if p.tok.kind == .lpar {
|
2020-04-21 05:07:49 +02:00
|
|
|
p.next() // (
|
2020-01-07 13:10:05 +01:00
|
|
|
is_method = true
|
2020-04-21 05:07:49 +02:00
|
|
|
rec_mut = p.tok.kind in [.key_var, .key_mut]
|
2020-04-15 01:45:27 +02:00
|
|
|
if rec_mut {
|
2020-04-21 05:07:49 +02:00
|
|
|
p.next() // `var`
|
2020-04-15 01:45:27 +02:00
|
|
|
}
|
2020-01-02 20:09:15 +01:00
|
|
|
rec_name = p.check_name()
|
2020-04-15 01:45:27 +02:00
|
|
|
if !rec_mut {
|
|
|
|
rec_mut = p.tok.kind == .key_mut
|
|
|
|
}
|
2020-04-11 02:24:00 +02:00
|
|
|
is_amp := p.peek_tok.kind == .amp
|
2020-03-11 16:10:46 +01:00
|
|
|
// if rec_mut {
|
2020-03-11 21:11:27 +01:00
|
|
|
// p.check(.key_mut)
|
2020-03-11 16:10:46 +01:00
|
|
|
// }
|
|
|
|
// TODO: talk to alex, should mut be parsed with the type like this?
|
|
|
|
// or should it be a property of the arg, like this ptr/mut becomes indistinguishable
|
2020-04-16 15:40:21 +02:00
|
|
|
rec_type = p.parse_type_with_mut(rec_mut)
|
2020-04-11 02:24:00 +02:00
|
|
|
if is_amp && rec_mut {
|
|
|
|
p.error('use `(f mut Foo)` or `(f &Foo)` instead of `(f mut &Foo)`')
|
|
|
|
}
|
2020-03-14 23:21:36 +01:00
|
|
|
args << table.Arg{
|
2020-03-10 23:21:26 +01:00
|
|
|
name: rec_name
|
2020-03-11 16:10:46 +01:00
|
|
|
is_mut: rec_mut
|
2020-03-10 23:21:26 +01:00
|
|
|
typ: rec_type
|
|
|
|
}
|
2020-01-02 20:09:15 +01:00
|
|
|
p.check(.rpar)
|
|
|
|
}
|
2020-04-21 05:11:50 +02:00
|
|
|
mut name := ''
|
2020-02-03 07:02:54 +01:00
|
|
|
if p.tok.kind == .name {
|
2020-03-11 21:11:27 +01:00
|
|
|
// TODO high order fn
|
2020-02-03 07:02:54 +01:00
|
|
|
name = p.check_name()
|
2020-04-15 23:16:49 +02:00
|
|
|
if !is_js && !is_c && !p.pref.translated && scanner.contains_capital(name) {
|
2020-04-04 14:09:58 +02:00
|
|
|
p.error('function names cannot contain uppercase letters, use snake_case instead')
|
|
|
|
}
|
2020-04-07 01:02:48 +02:00
|
|
|
if is_method && p.table.get_type_symbol(rec_type).has_method(name) {
|
2020-04-07 01:09:25 +02:00
|
|
|
p.error('duplicate method `$name`')
|
2020-04-07 01:02:48 +02:00
|
|
|
}
|
2020-02-03 07:02:54 +01:00
|
|
|
}
|
2020-03-10 14:40:30 +01:00
|
|
|
if p.tok.kind in [.plus, .minus, .mul, .div, .mod] {
|
2020-04-21 05:07:49 +02:00
|
|
|
name = p.tok.kind.str() // op_to_fn_name()
|
2020-03-10 14:40:30 +01:00
|
|
|
p.next()
|
|
|
|
}
|
2020-02-03 07:44:52 +01:00
|
|
|
// <T>
|
2020-04-14 18:09:59 +02:00
|
|
|
is_generic := p.tok.kind == .lt
|
|
|
|
if is_generic {
|
2020-02-03 07:44:52 +01:00
|
|
|
p.next()
|
|
|
|
p.next()
|
|
|
|
p.check(.gt)
|
|
|
|
}
|
2020-01-02 08:30:15 +01:00
|
|
|
// Args
|
2020-04-07 01:02:48 +02:00
|
|
|
args2, is_variadic := p.fn_args()
|
2020-03-14 23:21:36 +01:00
|
|
|
args << args2
|
|
|
|
for arg in args {
|
2020-04-04 05:14:40 +02:00
|
|
|
p.scope.register(arg.name, ast.Var{
|
2020-03-14 23:21:36 +01:00
|
|
|
name: arg.name
|
|
|
|
typ: arg.typ
|
2020-04-26 10:25:54 +02:00
|
|
|
is_mut: arg.is_mut
|
2020-02-15 13:37:48 +01:00
|
|
|
})
|
2020-02-11 13:03:10 +01:00
|
|
|
}
|
2020-04-21 05:11:50 +02:00
|
|
|
mut end_pos := p.prev_tok.position()
|
2020-01-02 08:30:15 +01:00
|
|
|
// Return type
|
2020-04-21 05:11:50 +02:00
|
|
|
mut return_type := table.void_type
|
2020-02-11 13:21:41 +01:00
|
|
|
if p.tok.kind.is_start_of_type() {
|
2020-04-19 00:07:57 +02:00
|
|
|
end_pos = p.tok.position()
|
2020-03-11 16:10:46 +01:00
|
|
|
return_type = p.parse_type()
|
2020-01-02 08:30:15 +01:00
|
|
|
}
|
2020-04-25 15:57:11 +02:00
|
|
|
ctdefine := p.attr_ctdefine
|
2020-02-27 17:21:13 +01:00
|
|
|
// Register
|
2020-01-08 10:19:12 +01:00
|
|
|
if is_method {
|
2020-04-21 05:11:50 +02:00
|
|
|
mut type_sym := p.table.get_type_symbol(rec_type)
|
2020-02-27 17:21:13 +01:00
|
|
|
// p.warn('reg method $type_sym.name . $name ()')
|
2020-03-11 10:48:45 +01:00
|
|
|
type_sym.register_method(table.Fn{
|
2020-01-08 10:19:12 +01:00
|
|
|
name: name
|
|
|
|
args: args
|
2020-03-11 16:10:46 +01:00
|
|
|
return_type: return_type
|
2020-03-24 12:39:11 +01:00
|
|
|
is_variadic: is_variadic
|
2020-04-14 18:09:59 +02:00
|
|
|
is_generic: is_generic
|
2020-04-17 17:16:14 +02:00
|
|
|
is_pub: is_pub
|
2020-04-25 15:57:11 +02:00
|
|
|
ctdefine: ctdefine
|
2020-01-08 10:19:12 +01:00
|
|
|
})
|
2020-04-07 01:02:48 +02:00
|
|
|
} else {
|
2020-02-29 07:24:28 +01:00
|
|
|
if is_c {
|
|
|
|
name = 'C.$name'
|
2020-04-15 23:16:49 +02:00
|
|
|
} else if is_js {
|
|
|
|
name = 'JS.$name'
|
2020-04-07 01:02:48 +02:00
|
|
|
} else {
|
2020-02-19 08:08:08 +01:00
|
|
|
name = p.prepend_mod(name)
|
|
|
|
}
|
2020-04-13 19:59:57 +02:00
|
|
|
if _ := p.table.find_fn(name) {
|
2020-04-26 07:16:58 +02:00
|
|
|
p.fn_redefinition_error(name)
|
2020-04-13 19:59:57 +02:00
|
|
|
}
|
2020-01-07 13:10:05 +01:00
|
|
|
p.table.register_fn(table.Fn{
|
2020-02-19 08:08:08 +01:00
|
|
|
name: name
|
2020-01-07 13:10:05 +01:00
|
|
|
args: args
|
2020-03-11 16:10:46 +01:00
|
|
|
return_type: return_type
|
2020-02-08 09:50:12 +01:00
|
|
|
is_variadic: is_variadic
|
2020-02-07 07:34:18 +01:00
|
|
|
is_c: is_c
|
2020-04-15 23:16:49 +02:00
|
|
|
is_js: is_js
|
2020-04-14 18:09:59 +02:00
|
|
|
is_generic: is_generic
|
2020-04-17 17:16:14 +02:00
|
|
|
is_pub: is_pub
|
2020-04-25 15:57:11 +02:00
|
|
|
ctdefine: ctdefine
|
2020-01-07 13:10:05 +01:00
|
|
|
})
|
|
|
|
}
|
2020-04-08 19:08:54 +02:00
|
|
|
// Body
|
2020-04-26 09:17:13 +02:00
|
|
|
mut stmts := []ast.Stmt{}
|
2020-03-06 16:31:40 +01:00
|
|
|
no_body := p.tok.kind != .lcbr
|
2020-02-04 09:54:15 +01:00
|
|
|
if p.tok.kind == .lcbr {
|
2020-04-22 13:15:38 +02:00
|
|
|
stmts = p.parse_block_no_scope()
|
2020-02-04 09:54:15 +01:00
|
|
|
}
|
2020-02-15 13:37:48 +01:00
|
|
|
p.close_scope()
|
2020-03-05 16:13:14 +01:00
|
|
|
p.attr = ''
|
2020-04-25 15:57:11 +02:00
|
|
|
p.attr_ctdefine = ''
|
2020-01-02 08:30:15 +01:00
|
|
|
return ast.FnDecl{
|
|
|
|
name: name
|
|
|
|
stmts: stmts
|
2020-03-11 16:10:46 +01:00
|
|
|
return_type: return_type
|
2020-03-14 23:21:36 +01:00
|
|
|
args: args
|
2020-03-05 16:13:14 +01:00
|
|
|
is_deprecated: is_deprecated
|
2020-01-02 20:09:15 +01:00
|
|
|
is_pub: is_pub
|
2020-02-08 09:50:12 +01:00
|
|
|
is_variadic: is_variadic
|
2020-01-02 20:09:15 +01:00
|
|
|
receiver: ast.Field{
|
2020-04-10 18:11:43 +02:00
|
|
|
name: rec_name
|
|
|
|
typ: rec_type
|
|
|
|
}
|
2020-02-18 20:20:15 +01:00
|
|
|
is_method: is_method
|
|
|
|
rec_mut: rec_mut
|
2020-03-04 17:08:28 +01:00
|
|
|
is_c: is_c
|
2020-04-15 23:16:49 +02:00
|
|
|
is_js: is_js
|
2020-03-06 16:31:40 +01:00
|
|
|
no_body: no_body
|
2020-04-19 00:07:57 +02:00
|
|
|
pos: start_pos.extend(end_pos)
|
2020-04-16 11:29:36 +02:00
|
|
|
is_builtin: p.builtin_mod || p.mod in util.builtin_module_parts
|
2020-04-25 15:57:11 +02:00
|
|
|
ctdefine: ctdefine
|
2020-01-02 08:30:15 +01:00
|
|
|
}
|
|
|
|
}
|
2020-02-11 13:03:10 +01:00
|
|
|
|
2020-04-21 05:11:50 +02:00
|
|
|
fn (mut p Parser) anon_fn() ast.AnonFn {
|
2020-04-17 21:59:19 +02:00
|
|
|
pos := p.tok.position()
|
|
|
|
p.check(.key_fn)
|
2020-04-22 13:11:58 +02:00
|
|
|
p.open_scope()
|
2020-04-17 21:59:19 +02:00
|
|
|
// TODO generics
|
|
|
|
args, is_variadic := p.fn_args()
|
|
|
|
for arg in args {
|
|
|
|
p.scope.register(arg.name, ast.Var{
|
|
|
|
name: arg.name
|
|
|
|
typ: arg.typ
|
|
|
|
})
|
|
|
|
}
|
2020-04-21 05:11:50 +02:00
|
|
|
mut return_type := table.void_type
|
2020-04-17 21:59:19 +02:00
|
|
|
if p.tok.kind.is_start_of_type() {
|
|
|
|
return_type = p.parse_type()
|
|
|
|
}
|
2020-04-26 09:17:13 +02:00
|
|
|
mut stmts := []ast.Stmt{}
|
2020-04-17 21:59:19 +02:00
|
|
|
no_body := p.tok.kind != .lcbr
|
|
|
|
if p.tok.kind == .lcbr {
|
2020-04-22 13:15:38 +02:00
|
|
|
stmts = p.parse_block_no_scope()
|
2020-04-17 21:59:19 +02:00
|
|
|
}
|
2020-04-22 13:11:58 +02:00
|
|
|
p.close_scope()
|
2020-04-17 21:59:19 +02:00
|
|
|
func := table.Fn{
|
|
|
|
args: args
|
|
|
|
is_variadic: is_variadic
|
|
|
|
return_type: return_type
|
|
|
|
}
|
2020-04-21 05:23:36 +02:00
|
|
|
name := 'anon_${p.tok.pos}_$func.signature()'
|
|
|
|
func.name = name
|
|
|
|
idx := p.table.find_or_register_fn_type(func, true, false)
|
2020-04-17 21:59:19 +02:00
|
|
|
typ := table.new_type(idx)
|
2020-04-25 17:49:16 +02:00
|
|
|
// name := p.table.get_type_name(typ)
|
2020-04-17 21:59:19 +02:00
|
|
|
return ast.AnonFn{
|
|
|
|
decl: ast.FnDecl{
|
|
|
|
name: name
|
|
|
|
stmts: stmts
|
|
|
|
return_type: return_type
|
|
|
|
args: args
|
|
|
|
is_variadic: is_variadic
|
|
|
|
is_method: false
|
|
|
|
is_anon: true
|
|
|
|
no_body: no_body
|
|
|
|
pos: pos
|
|
|
|
}
|
|
|
|
typ: typ
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-21 05:11:50 +02:00
|
|
|
fn (mut p Parser) fn_args() ([]table.Arg, bool) {
|
2020-02-11 13:21:41 +01:00
|
|
|
p.check(.lpar)
|
2020-04-26 09:17:13 +02:00
|
|
|
mut args := []table.Arg{}
|
2020-04-21 05:11:50 +02:00
|
|
|
mut is_variadic := false
|
2020-02-11 13:03:10 +01:00
|
|
|
// `int, int, string` (no names, just types)
|
2020-04-08 19:08:54 +02:00
|
|
|
types_only := p.tok.kind in [.amp, .and] || (p.peek_tok.kind == .comma && p.table.known_type(p.tok.lit)) ||
|
2020-04-07 01:02:48 +02:00
|
|
|
p.peek_tok.kind == .rpar
|
2020-02-11 13:03:10 +01:00
|
|
|
if types_only {
|
2020-04-07 01:02:48 +02:00
|
|
|
// p.warn('types only')
|
2020-04-21 05:11:50 +02:00
|
|
|
mut arg_no := 1
|
2020-02-11 13:03:10 +01:00
|
|
|
for p.tok.kind != .rpar {
|
|
|
|
arg_name := 'arg_$arg_no'
|
2020-03-11 16:10:46 +01:00
|
|
|
is_mut := p.tok.kind == .key_mut
|
|
|
|
if is_mut {
|
|
|
|
p.check(.key_mut)
|
|
|
|
}
|
2020-02-11 13:03:10 +01:00
|
|
|
if p.tok.kind == .ellipsis {
|
|
|
|
p.check(.ellipsis)
|
|
|
|
is_variadic = true
|
|
|
|
}
|
2020-04-21 05:11:50 +02:00
|
|
|
mut arg_type := p.parse_type()
|
2020-02-29 09:04:47 +01:00
|
|
|
if is_variadic {
|
2020-04-25 09:08:53 +02:00
|
|
|
arg_type = arg_type.set_flag(.variadic)
|
2020-02-29 09:04:47 +01:00
|
|
|
}
|
2020-02-11 13:03:10 +01:00
|
|
|
if p.tok.kind == .comma {
|
|
|
|
if is_variadic {
|
|
|
|
p.error('cannot use ...(variadic) with non-final parameter no $arg_no')
|
|
|
|
}
|
|
|
|
p.next()
|
|
|
|
}
|
2020-03-14 23:21:36 +01:00
|
|
|
args << table.Arg{
|
2020-02-11 13:03:10 +01:00
|
|
|
name: arg_name
|
2020-03-11 16:10:46 +01:00
|
|
|
is_mut: is_mut
|
2020-02-11 13:03:10 +01:00
|
|
|
typ: arg_type
|
|
|
|
}
|
2020-03-14 10:24:45 +01:00
|
|
|
arg_no++
|
2020-02-11 13:03:10 +01:00
|
|
|
}
|
2020-04-07 01:02:48 +02:00
|
|
|
} else {
|
2020-02-11 13:03:10 +01:00
|
|
|
for p.tok.kind != .rpar {
|
2020-04-21 05:11:50 +02:00
|
|
|
mut arg_names := [p.check_name()]
|
2020-02-11 13:03:10 +01:00
|
|
|
// `a, b, c int`
|
|
|
|
for p.tok.kind == .comma {
|
|
|
|
p.check(.comma)
|
|
|
|
arg_names << p.check_name()
|
|
|
|
}
|
2020-03-11 16:10:46 +01:00
|
|
|
is_mut := p.tok.kind == .key_mut
|
2020-03-11 21:11:27 +01:00
|
|
|
// if is_mut {
|
|
|
|
// p.check(.key_mut)
|
|
|
|
// }
|
2020-02-11 13:03:10 +01:00
|
|
|
if p.tok.kind == .ellipsis {
|
|
|
|
p.check(.ellipsis)
|
|
|
|
is_variadic = true
|
|
|
|
}
|
2020-04-21 05:11:50 +02:00
|
|
|
mut typ := p.parse_type()
|
2020-02-29 09:04:47 +01:00
|
|
|
if is_variadic {
|
2020-04-25 09:08:53 +02:00
|
|
|
typ = typ.set_flag(.variadic)
|
2020-02-29 09:04:47 +01:00
|
|
|
}
|
2020-02-11 13:03:10 +01:00
|
|
|
for arg_name in arg_names {
|
2020-03-14 23:21:36 +01:00
|
|
|
args << table.Arg{
|
2020-02-11 13:03:10 +01:00
|
|
|
name: arg_name
|
2020-03-11 16:10:46 +01:00
|
|
|
is_mut: is_mut
|
2020-02-11 13:03:10 +01:00
|
|
|
typ: typ
|
|
|
|
}
|
|
|
|
// if typ.typ.kind == .variadic && p.tok.kind == .comma {
|
|
|
|
if is_variadic && p.tok.kind == .comma {
|
|
|
|
p.error('cannot use ...(variadic) with non-final parameter $arg_name')
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if p.tok.kind != .rpar {
|
|
|
|
p.check(.comma)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
p.check(.rpar)
|
2020-04-07 01:02:48 +02:00
|
|
|
return args, is_variadic
|
2020-02-11 13:03:10 +01:00
|
|
|
}
|
2020-03-27 08:46:54 +01:00
|
|
|
|
2020-04-26 07:16:58 +02:00
|
|
|
fn (p &Parser) fileis(s string) bool {
|
2020-03-27 08:46:54 +01:00
|
|
|
return p.file_name.contains(s)
|
|
|
|
}
|
2020-04-26 07:16:58 +02:00
|
|
|
|
|
|
|
fn (mut p Parser) fn_redefinition_error(name string) {
|
|
|
|
// Find where this function was already declared
|
|
|
|
// TODO
|
|
|
|
/*
|
|
|
|
for file in p.ast_files {
|
|
|
|
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
p.error('redefinition of function `$name`')
|
|
|
|
}
|