func (lambda *Lambda) prepareArgs(args List) { l := len(args) formals := make(List, len(args)) if l == 0 { lambda.Meta["parameters parsex"] = []Var{} return } lidx := l - 1 last := args[lidx].(Atom) // variadic function args formal as (last[::Type] ... ) isVariadic := false if last.Name == "..." && len(args) > 1 { isVariadic = true } lambda.Meta["is variadic"] = isVariadic ps := make([]px.Parser, l+1) for idx, arg := range args[:lidx] { ps[idx] = argParser(arg.(Atom)) formals[idx] = arg } if isVariadic { varArg := args[l-2].(Atom) ps[lidx] = px.Many(argParser(last)) larg := Atom{varArg.Name, varArg.Type} formals[lidx] = larg } else { ps[lidx] = argParser(last) formals[lidx] = last } ps[l] = px.Eof lambda.Meta["formal parameters"] = formals lambda.Meta["parameter parsexs"] = ps }
// argParser 构造一个 parsex 解析器,判断输入数据是否与给定类型一致,如果判断成功,构造对应的 // Var。 func argParser(atom Atom) px.Parser { one := func(st px.ParsexState) (interface{}, error) { var err error if data, err := st.Next(typeis(atom)); err == nil { slot := VarSlot(atom.Type) slot.Set(data) return slot, nil } return nil, err } if atom.Name == "..." { return px.Many(one) } return one }
return nil, ParsexSignErrorf( "Many1 Arg Error:except 1 parser arg but %v.", reflect.TypeOf(param)) } }, "many": func(env Env, args ...interface{}) (Lisp, error) { if len(args) != 1 { return nil, ParsexSignErrorf("Parsex Parser Many Error: only accept one parsex parser as arg but %v", args) } param, err := Eval(env, args[0]) if err != nil { return nil, err } switch parser := param.(type) { case Parsexer: return ParsexBox(px.Many(parser.Parser)), nil default: return nil, ParsexSignErrorf( "Many Arg Error:except 1 parser arg but %v.", reflect.TypeOf(param)) } }, "failed": func(env Env, args ...interface{}) (Lisp, error) { if len(args) != 1 { return nil, ParsexSignErrorf("Parsex Parser Failed Error: only accept one string as arg but %v", args) } param, err := Eval(env, args[0]) if err != nil { return nil, err } var str string