func (p *Parser) processFuncArg(inf funcArgInfo) *oop.Var {
	var paramSet bool
	length := *inf.index - *inf.lastComma
	if length < 1 {
		fract.IPanic(inf.tk, obj.SyntaxPanic, "Value is not given!")
	} else if *inf.count >= len(inf.fn.Params) {
		fract.IPanic(inf.tk, obj.SyntaxPanic, "Argument overflow!")
	}
	param := inf.fn.Params[*inf.count]
	resultVar := &oop.Var{Name: param.Name}
	valTokens := inf.tokens[*inf.lastComma:*inf.index]
	inf.tk = valTokens[0]
	if length >= 2 && isParamSet(valTokens) {
		length -= 2
		if length < 1 {
			fract.IPanic(inf.tk, obj.SyntaxPanic, "Value is not given!")
		}
		for _, param := range inf.fn.Params {
			if param.Name == inf.tk.Val {
				for _, name := range *inf.names {
					if name == inf.tk.Val {
						fract.IPanic(inf.tk, obj.SyntaxPanic,
							"Keyword argument repeated!")
					}
				}
				*inf.count++
				*inf.names = append(*inf.names, inf.tk.Val)
				resultVar.Name = inf.tk.Val
				if param.Variadic {
					*inf.lastComma += 2
					resultVar.Val = p.variadicArgValues(inf.tokens, inf.index, inf.lastComma, param.Type)
				} else {
					resultVar.Val = p.procFuncArgVal(valTokens[2:], param.Type)
				}
				valTokens = nil
				resultVar.Val.Const = isConstParam(param)
				return resultVar
			}
		}
		fract.IPanic(inf.tk, obj.NamePanic,
			"Parameter is not defined in this name: "+inf.tk.Val)
	}
	if paramSet {
		fract.IPanic(inf.tk, obj.SyntaxPanic,
			"After the parameter has been given a special value, all parameters must be shown privately!")
	}
	*inf.count++
	*inf.names = append(*inf.names, resultVar.Name)
	if param.Variadic {
		resultVar.Val = p.variadicArgValues(inf.tokens, inf.index, inf.lastComma, param.Type)
	} else {
		resultVar.Val = p.procFuncArgVal(valTokens, param.Type)
	}
	resultVar.Val.Const = isConstParam(param)
	valTokens = nil
	return resultVar
}
Process function argument.
package parser
import (
	"fmt"
	"strings"
	"github.com/fract-lang/fract/oop"
	"github.com/fract-lang/fract/pkg/fract"
	"github.com/fract-lang/fract/pkg/obj"
)
type funcCall struct {
	fn    *oop.Function
	errTk obj.Token
	args  []oop.VarDef
}
func (c *funcCall) Func() *oop.Function { return c.fn }
func (c *funcCall) Call() *oop.Val {
	var returnVal oop.Val
	if c.fn.Tokens == nil {
		returnVal = c.fn.Src.(func(obj.Token, []oop.VarDef) oop.Val)(c.errTk, c.args)
		c.args = nil
		c.fn = nil
		return &returnVal
	}
	deferLen := len(defers)
	src := c.fn.Src.(*Parser)
	p := Parser{
		defs: oop.DefMap{
			Vars:  append(c.args, c.fn.Args...),
			Funcs: src.defs.Funcs,
		},
		packages:     src.packages,
		funcTempVars: src.funcTempVars,
		loopCount:    0,
		funcCount:    1,
		Tokens:       c.fn.Tokens[:len(c.fn.Tokens):len(c.fn.Tokens)],
	}
	if p.funcTempVars == -1 {
		p.funcTempVars = 0
	}
	if p.funcTempVars == 0 {
		p.defs.Vars = append(p.defs.Vars, src.defs.Vars...)
	} else {
		p.defs.Vars = append(p.defs.Vars,
			src.defs.Vars[:len(src.defs.Vars)-p.funcTempVars]...)
	}
	p.funcTempVars = len(c.args)
	block := obj.Block{
		Try: func() {
			for p.index = 0; p.index < len(p.Tokens); p.index++ {
				if p.processExpression(p.Tokens[p.index]) == fract.FUNCReturn {
					src.returnVal = p.returnVal
					if src.returnVal == nil {
						break
					}
					returnVal = *src.returnVal
					src.returnVal = nil
					break
				}
			}
		},
	}
	block.Do()
	if block.Panic.Msg != "" {
		defers = defers[:deferLen]
		panic(block.Panic.Msg)
	}
	for i := len(defers) - 1; i >= deferLen; i-- {
		defers[i].Call()
	}
	defers = defers[:deferLen]
	c.args = nil
	c.fn = nil
	return &returnVal
}
func isParamSet(tokens []obj.Token) bool {
	return len(tokens) >= 2 &&
		tokens[0].Type == fract.Name &&
		tokens[1].Val == "="
}
func (p *Parser) procFuncArgVal(tokens []obj.Token, paramType string) oop.Val {
	if paramType != "" && paramType != "const" {
		if paramType == "mut" || paramType == "const mut" {
			return *p.processValue(tokens, "mut")
		}
		return *p.processValue(tokens, "var")
	}
	return *p.processValTokens(tokens)
}
type variadicArgsInfo struct {
	index     *int
	token     obj.Token
	paramType string
	result    oop.Val
	values    oop.ListType
	valTokens []obj.Token
}
func (p *Parser) pushVariadicArg(info *variadicArgsInfo) {
	variadic := false
	if l := len(info.valTokens); info.valTokens[l-1].Type == fract.Variadic {
		info.token = info.valTokens[l-1]
		variadic = true
		info.valTokens = info.valTokens[:l-1]
	}
	val := p.procFuncArgVal(info.valTokens, info.paramType)
	if variadic {
		if val.Type != oop.List {
			fract.IPanic(info.token, obj.ValuePanic,
				"Notation is can used for only lists!")
		}
		info.values = append(info.values, *val.Data.(*oop.ListType)...)
	} else {
		info.values = append(info.values, val)
	}
	info.valTokens = nil
}
func (p *Parser) variadicArgValues(tokens []obj.Token, index, lastComma *int, paramType string) oop.Val {
	info := variadicArgsInfo{
		index:     index,
		paramType: paramType,
		result:    oop.Val{Type: oop.List},
	}
	braceCount := 0
	for ; *index < len(tokens); *index++ {
		info.token = tokens[*index]
		switch info.token.Type {
		case fract.Brace:
			switch info.token.Val {
			case "{", "[", "(":
				braceCount++
			default:
				braceCount--
			}
		case fract.Comma:
			if braceCount != 0 {
				break
			}
			info.valTokens = tokens[*lastComma:*index]
			if isParamSet(info.valTokens) {
				*index -= 4
				goto result
			}
			p.pushVariadicArg(&info)
			*lastComma = *index + 1
		}
	}
	if *lastComma < len(tokens) {
		info.valTokens = tokens[*lastComma:]
		if isParamSet(info.valTokens) {
			*index -= 4
			goto result
		}
		p.pushVariadicArg(&info)
	}
result:
	info.result.Data = &info.values
	return info.result
}
type funcArgInfo struct {
	fn        *oop.Function
	names     *[]string
	tokens    []obj.Token
	tk        obj.Token
	index     *int
	count     *int
	lastComma *int
}
func isConstParam(param oop.Param) bool {
	return param.Type == "const" ||
		param.Type == "const var" ||
		param.Type == "const mut"
}