package eval
import (
)
type closure struct {
ArgNames []string
RestArg int
OptNames []string
OptDefaults []interface{}
Op effectOp
NewLocal []string
Captured *Ns
SrcMeta parse.Source
DefRange diag.Ranging
}
var _ Callable = &closure{}
func (*closure) () string {
return "fn"
}
func ( *closure) ( interface{}) bool {
return ==
}
func ( *closure) () uint32 {
return hash.Pointer(unsafe.Pointer())
}
func ( *closure) (int) string {
return fmt.Sprintf("<closure %p>", )
}
func ( *closure) ( *Frame, []interface{}, map[string]interface{}) error {
if .RestArg != -1 {
if len() < len(.ArgNames)-1 {
return errs.ArityMismatch{
What: "arguments here",
ValidLow: len(.ArgNames) - 1, ValidHigh: -1, Actual: len()}
}
} else {
if len() != len(.ArgNames) {
return errs.ArityMismatch{
What: "arguments here",
ValidLow: len(.ArgNames), ValidHigh: len(.ArgNames), Actual: len()}
}
}
:= make(map[string]struct{})
for , := range .OptNames {
, := []
if {
[] = struct{}{}
}
}
if len() < len() {
:= make([]string, 0, len()-len())
for := range {
, := []
if ! {
= append(, parse.Quote())
}
}
sort.Strings()
return UnsupportedOptionsError{}
}
.up = .Captured
:= len(.ArgNames) + len(.OptNames) + len(.NewLocal)
:= &Ns{make([]vars.Var, ), make([]string, ), make([]bool, )}
for , := range .ArgNames {
.names[] =
}
if .RestArg == -1 {
for := range .ArgNames {
.slots[] = vars.FromInit([])
}
} else {
for := 0; < .RestArg; ++ {
.slots[] = vars.FromInit([])
}
:= len() - len(.ArgNames)
.slots[.RestArg] = vars.FromInit(
vals.MakeList([.RestArg : .RestArg++1]...))
for := .RestArg + 1; < len(.ArgNames); ++ {
.slots[] = vars.FromInit([+])
}
}
:= len(.ArgNames)
for , := range .OptNames {
, := []
if ! {
= .OptDefaults[]
}
.names[+] =
.slots[+] = vars.FromInit()
}
+= len(.OptNames)
for , := range .NewLocal {
.names[+] =
.slots[+] = MakeVarFromName()
}
.local =
.srcMeta = .SrcMeta
return .Op.exec()
}
func ( string) vars.Var {
switch {
case strings.HasSuffix(, FnSuffix):
:= NewGoFn("nop~", nop)
return vars.FromPtr(&)
case strings.HasSuffix(, NsSuffix):
:= (*Ns)(nil)
return vars.FromPtr(&)
default:
return vars.FromInit(nil)
}
}
type UnsupportedOptionsError struct {
Options []string
}
func ( UnsupportedOptionsError) () string {
if len(.Options) == 1 {
return fmt.Sprintf("unsupported option: %s", .Options[0])
}
return fmt.Sprintf("unsupported options: %s", strings.Join(.Options, ", "))
}
func ( *closure) () vals.StructMap { return closureFields{} }
type closureFields struct{ c *closure }
func (closureFields) () {}
func ( closureFields) () vals.List { return listOfStrings(.c.ArgNames) }
func ( closureFields) () string { return strconv.Itoa(.c.RestArg) }
func ( closureFields) () vals.List { return listOfStrings(.c.OptNames) }
func ( closureFields) () parse.Source { return .c.SrcMeta }
func ( closureFields) () vals.List {
return vals.MakeList(.c.OptDefaults...)
}
func ( closureFields) () string {
:= .c.Op.(diag.Ranger).Range()
return .c.SrcMeta.Code[.From:.To]
}
func ( closureFields) () string {
return .c.SrcMeta.Code[.c.DefRange.From:.c.DefRange.To]
}
func ( []string) vals.List {
:= vals.EmptyList
for , := range {
= .Cons()
}
return
}