diff --git a/.gitignore b/.gitignore index cacd30331..37529c034 100644 --- a/.gitignore +++ b/.gitignore @@ -175,6 +175,7 @@ AGENTS.md # AOT codegen tool — built ad-hoc, not checked in /lgbgen /lginterop +/lgprimgen /bench-ratchet /perf-page diff --git a/Makefile b/Makefile index 0f7605832..21934fa5b 100644 --- a/Makefile +++ b/Makefile @@ -69,7 +69,19 @@ build-profile: $(LG-PROFILE) CORE-LG-FILES := $(shell find pkg/rt/core -name '*.lg' -type f 2>/dev/null) LGBGEN-SOURCES := $(shell find cmd/lgbgen -name '*.go' -type f 2>/dev/null) ROOT-GO-FILES := $(shell find . -maxdepth 1 -name '*.go' -type f 2>/dev/null) -pkg/rt/core_compiled.lgb: $(CORE-LG-FILES) $(LGBGEN-SOURCES) $(GO) + +# Primitive registrar. lgprimgen scans pkg/rt's //lg:native-annotated Go sources +# and emits this file. It is a PURE go/ast codegen tool (no pkg/compiler / pkg/rt +# import), so it MUST run before the lgbgen bootstrap that consumes it: when a +# primitive is hoisted out of installLangNS into a //lg:native decl, the bootstrap +# runtime cannot boot until this file carries its registration. A runtime-coupled +# generator here would depend on the very artifact it produces. Making the bundle +# depend on it breaks that cycle. +PRIMGEN-SOURCES := $(shell find pkg/rt -maxdepth 1 -name '*.go' -type f -not -name 'zz_*' -not -name '*_test.go' 2>/dev/null) $(shell find cmd/lgprimgen internal/primgen -name '*.go' -type f 2>/dev/null) +pkg/rt/zz_primitives_generated.go: $(PRIMGEN-SOURCES) $(GO) + go run ./cmd/lgprimgen -primitives pkg/rt -go-pkg github.com/nooga/let-go/pkg/rt -primitives-out pkg/rt/zz_primitives_generated.go + +pkg/rt/core_compiled.lgb: pkg/rt/zz_primitives_generated.go $(CORE-LG-FILES) $(LGBGEN-SOURCES) $(GO) go run -tags bootstrap ./cmd/lgbgen # Lowered-Go target. The -tags gogen_ir build path links these generated @@ -78,7 +90,7 @@ pkg/rt/core_compiled.lgb: $(CORE-LG-FILES) $(LGBGEN-SOURCES) $(GO) # the two engines silently disagree (parity-full diverges on bucket # hashes even when pass/fail counts match). lower_go.go is the timestamp # anchor for the whole tree — every regen rewrites it. -pkg/rt/core_go_lowered/ir/lower_go/lower_go.go: $(CORE-LG-FILES) $(LGBGEN-SOURCES) $(GO) +pkg/rt/core_go_lowered/ir/lower_go/lower_go.go: pkg/rt/zz_primitives_generated.go $(CORE-LG-FILES) $(LGBGEN-SOURCES) $(GO) go run -tags bootstrap ./cmd/lgbgen --target=go # Regenerate every committed code-gen artifact via the let-go orchestrator diff --git a/cmd/hoist-natives/main.go b/cmd/hoist-natives/main.go new file mode 100644 index 000000000..857f7ec6c --- /dev/null +++ b/cmd/hoist-natives/main.go @@ -0,0 +1,1060 @@ +// Command hoist-natives is a codemod that lifts the inline anonymous closures +// registered as clojure.core primitives in pkg/rt/lang.go into named, +// //lg:native-annotated top-level functions. +// +// Motivation (three wins at once): +// 1. Stack traces read `rt.corePlus` instead of `installCore.func42`. +// 2. Registration becomes declarative — the `ns.Def("+", plus)` call is +// dropped and lginterop emits the registration from the //lg:native + +// //lg:name annotations. +// 3. It is the #411 "Fn-adapter" done as a codemod: hand-built Fn values +// become annotated decls lginterop already consumes, with no runtime +// adapter. +// +// It only hoists closures that are SAFE to lift: no genuine enclosing-scope +// capture (package-level refs and params are fine; an installCore local is +// not), and a discoverable lg-name (an `ns.Def("", )` site). Anything +// else is reported and left untouched — the codemod never guesses. +// +// Default is a dry run: it prints a classification report and the proposed +// hoisted function for each safe site. `-apply` performs the rewrite. +package main + +import ( + "bytes" + "flag" + "fmt" + "go/ast" + "go/format" + "go/parser" + "go/token" + "os" + "path/filepath" + "regexp" + "sort" + "strconv" + "strings" + + "github.com/nooga/let-go/internal/primgen" +) + +func main() { + file := flag.String("file", "pkg/rt/lang.go", "Go file to codemod") + pkgDir := flag.String("pkg", "pkg/rt", "package dir (for resolving package-level names)") + only := flag.String("only", "", "regex; limit to lg-names matching it") + helpers := flag.String("helpers", "", "comma-separated installCore-local helper closures to lift to package level (instead of hoisting primitives)") + apply := flag.Bool("apply", false, "apply the rewrite (default: dry run + report)") + flag.Parse() + + var onlyRe *regexp.Regexp + if *only != "" { + onlyRe = regexp.MustCompile(*only) + } + + fset := token.NewFileSet() + f, err := parser.ParseFile(fset, *file, nil, parser.ParseComments) + if err != nil { + die("parse %s: %v", *file, err) + } + + pkgNames, err := packageLevelNames(*pkgDir) + if err != nil { + die("scan package: %v", err) + } + for name := range importNames(f) { + pkgNames[name] = true + } + + if *helpers != "" { + liftHelpers(*file, fset, f, splitSet(*helpers), pkgNames, *apply) + return + } + + defNames := collectNsDefNames(f) // fn-var name -> lg name (last wins) + allNames := collectNsDefAllNames(f) // fn-var name -> every lg name + lookupNames := lookupNamesInPackage(*pkgDir) // lg-names fetched via .Lookup("…") + // lg-names a pre-existing //lg:native decl already owns (native_prims.go etc.), + // excluding the file we're hoisting into. A candidate colliding with one is a + // redundant second registration; hoisting it would emit a duplicate. + existingNative, err := primgen.ScanNativeNames(*pkgDir, filepath.Base(*file)) + if err != nil { + die("scan existing //lg:native names: %v", err) + } + // lg-names a stdlib .lg source redefines — shadowed at load and not covered + // by the eager core reapply, so hoisting+guarding them would deviate. + lgRedefined := lgRedefinedNames(filepath.Join(*pkgDir, "core")) + + sites := findNativeFnSites(f) + + var safe []*site + skipCap := map[string][]string{} // var -> captured names + var skipNoName []string + var skipMulti []string + for _, s := range sites { + if onlyRe != nil { + lg := defNames[s.varName] + if lg == "" || !onlyRe.MatchString(lg) { + continue + } + } + lg, ok := defNames[s.varName] + if !ok { + skipNoName = append(skipNoName, s.varName) + continue + } + if len(allNames[s.varName]) > 1 { + // Registered under multiple names — hoisting to one //lg:name would + // silently drop the others from clojure.core. Leave it in place. + skipMulti = append(skipMulti, fmt.Sprintf("%s (%s)", s.varName, strings.Join(allNames[s.varName], "/"))) + continue + } + if lookupNames[lg] { + // Fetched by lg-name via `.Lookup("")` somewhere in the package + // (possibly another file) at init time, before the generated + // registrar runs — hoisting would leave that lookup nil. + skipMulti = append(skipMulti, fmt.Sprintf("%s (Lookup %q)", s.varName, lg)) + continue + } + if existingNative[lg] { + // Name already owned by a pre-existing //lg:native decl — hoisting + // this redundant registration would emit a duplicate in the registrar. + skipMulti = append(skipMulti, fmt.Sprintf("%s (dup of //lg:native %q)", s.varName, lg)) + continue + } + if lgRedefined[lg] { + // Shadowed by a stdlib .lg (defn %q) at load; the eager core reapply + // skips it, so a guarded native here deviates permanently. + skipMulti = append(skipMulti, fmt.Sprintf("%s (redefined in .lg %q)", s.varName, lg)) + continue + } + s.lgName = lg + captured := freeVars(s.lit, pkgNames) + if len(captured) > 0 { + skipCap[s.varName] = captured + continue + } + safe = append(safe, s) + } + if len(skipMulti) > 0 { + sort.Strings(skipMulti) + fmt.Printf("-- skipped: registered under multiple lg-names (would drop names) --\n %s\n\n", strings.Join(skipMulti, ", ")) + } + + // Demote any safe var still referenced by code that survives the rewrite. + // The rewrite removes only the var's own `X, err := …Wrap(…)` assignment and + // its single `ns.Def("name", X)` registration; a var referenced anywhere else + // — a second registration (`lgCore.Def("gt", gt)`), a helper, or a skipped + // site's closure body — would become an undefined identifier. freeVars flags + // captures WITHIN a hoisted closure; this flags uses OF the var by others. + safe, skipRef := demoteSurvivingRefs(f, safe) + + report(fset, safe, skipCap, skipNoName, defNames) + if len(skipRef) > 0 { + sort.Strings(skipRef) + fmt.Printf("-- skipped: still referenced by surviving code (2nd registration / helper / captured by a skip) --\n %s\n\n", strings.Join(skipRef, ", ")) + } + + if *apply { + if err := rewrite(*file, fset, f, safe, defNames); err != nil { + die("apply: %v", err) + } + fmt.Printf("\napplied: hoisted %d functions into %s\n", len(safe), *file) + } else { + fmt.Printf("\ndry run — pass -apply to write. proposed hoists for the %d safe sites:\n\n", len(safe)) + for _, s := range safe { + fmt.Println(genFunc(fset, s)) + } + } +} + +// --- site discovery ------------------------------------------------------- + +type site struct { + varName string // the local the closure was assigned to (plus, mul, …) + lgName string // the clojure.core name (from ns.Def) + ctx bool // true for NewCtxNativeFn (first param is ec) + lit *ast.FuncLit // the closure + assign *ast.AssignStmt +} + +// findNativeFnSites finds `X, _ := vm.NativeFnType.Wrap(func…)` / +// `.WrapNoErr(func…)` / `vm.NewCtxNativeFn(func…)` assignments. +func findNativeFnSites(f *ast.File) []*site { + var out []*site + ast.Inspect(f, func(n ast.Node) bool { + as, ok := n.(*ast.AssignStmt) + if !ok || as.Tok != token.DEFINE || len(as.Lhs) != 2 || len(as.Rhs) != 1 { + return true + } + lhs, ok := as.Lhs[0].(*ast.Ident) + if !ok || lhs.Name == "_" { + return true + } + call, ok := as.Rhs[0].(*ast.CallExpr) + if !ok || len(call.Args) != 1 { + return true + } + lit, ok := call.Args[0].(*ast.FuncLit) + if !ok { + return true + } + boxer, ctx := classifyBoxer(call.Fun) + if boxer == "" { + return true + } + out = append(out, &site{varName: lhs.Name, ctx: ctx, lit: lit, assign: as}) + return true + }) + return out +} + +// demoteSurvivingRefs returns the subset of safe whose local var is referenced +// ONLY by its own assignment target and the single `ns.Def("name", X)` call the +// rewrite cuts, plus the names it demoted. A var referenced by any surviving +// identifier (a second registration, a helper, or a skipped closure body) is +// not hoistable — removing its local would leave that reference undefined. +func demoteSurvivingRefs(f *ast.File, safe []*site) (kept []*site, demoted []string) { + byVar := map[string]*site{} + for _, s := range safe { + byVar[s.varName] = s + } + // Identifiers the rewrite removes: each safe assign's target and the arg of + // the single ns.Def(name, X) it cuts. Every OTHER occurrence survives. + accounted := map[*ast.Ident]bool{} + for _, s := range safe { + if id, ok := s.assign.Lhs[0].(*ast.Ident); ok { + accounted[id] = true + } + } + ast.Inspect(f, func(n ast.Node) bool { + call, ok := n.(*ast.CallExpr) + if !ok || len(call.Args) != 2 { + return true + } + sel, ok := call.Fun.(*ast.SelectorExpr) + if !ok || sel.Sel.Name != "Def" { + return true + } + if id, ok := sel.X.(*ast.Ident); !ok || id.Name != "ns" { + return true + } + if arg, ok := call.Args[1].(*ast.Ident); ok && byVar[arg.Name] != nil { + accounted[arg] = true + } + return true + }) + survives := map[string]bool{} + ast.Inspect(f, func(n ast.Node) bool { + id, ok := n.(*ast.Ident) + if !ok || byVar[id.Name] == nil || accounted[id] { + return true + } + survives[id.Name] = true + return true + }) + + // A primitive is also un-hoistable if surviving code fetches it BY LG-NAME + // via `ns.Lookup("name")` — for post-registration mutation (`.SetMacro()`) + // or to alias it under another name. installLangNS runs before the generated + // registrar, so such a lookup would hit an unregistered var. These references + // are string literals, invisible to the identifier scan above. + byLg := map[string]*site{} + for _, s := range safe { + byLg[s.lgName] = s + } + ast.Inspect(f, func(n ast.Node) bool { + call, ok := n.(*ast.CallExpr) + if !ok || len(call.Args) != 1 { + return true + } + sel, ok := call.Fun.(*ast.SelectorExpr) + if !ok || sel.Sel.Name != "Lookup" { + return true + } + lit, ok := call.Args[0].(*ast.BasicLit) + if !ok || lit.Kind != token.STRING { + return true + } + if name, err := strconv.Unquote(lit.Value); err == nil && byLg[name] != nil { + survives[byLg[name].varName] = true + } + return true + }) + for _, s := range safe { + if survives[s.varName] { + demoted = append(demoted, s.varName) + continue + } + kept = append(kept, s) + } + return kept, demoted +} + +// classifyBoxer returns ("Wrap"|"WrapNoErr"|"NewCtxNativeFn", isCtx) or ("",_). +func classifyBoxer(fun ast.Expr) (string, bool) { + sel, ok := fun.(*ast.SelectorExpr) + if !ok { + return "", false + } + switch sel.Sel.Name { + case "Wrap", "WrapNoErr": + // vm.NativeFnType.Wrap + if inner, ok := sel.X.(*ast.SelectorExpr); ok && inner.Sel.Name == "NativeFnType" { + return sel.Sel.Name, false + } + case "NewCtxNativeFn": + if id, ok := sel.X.(*ast.Ident); ok && id.Name == "vm" { + return sel.Sel.Name, true + } + } + return "", false +} + +// collectNsDefAllNames maps a registered fn-var to EVERY clojure name it is +// Def'd under. A var registered under several names (`ns.Def("int", intf)`, +// `ns.Def("byte", intf)`, `ns.Def("short", intf)`) can't be hoisted to a single +// //lg:native decl without dropping names, so the caller skips multi-name vars. +func collectNsDefAllNames(f *ast.File) map[string][]string { + out := map[string][]string{} + ast.Inspect(f, func(n ast.Node) bool { + call, ok := n.(*ast.CallExpr) + if !ok || len(call.Args) != 2 { + return true + } + sel, ok := call.Fun.(*ast.SelectorExpr) + if !ok || sel.Sel.Name != "Def" { + return true + } + if nsID, ok := sel.X.(*ast.Ident); !ok || nsID.Name != "ns" { + return true + } + lit, ok := call.Args[0].(*ast.BasicLit) + if !ok || lit.Kind != token.STRING { + return true + } + valID, ok := call.Args[1].(*ast.Ident) + if !ok { + return true + } + if name, err := strconv.Unquote(lit.Value); err == nil { + out[valID.Name] = append(out[valID.Name], name) + } + return true + }) + return out +} + +// collectNsDefNames maps a registered fn-var to its clojure name from +// `ns.Def("name", fnvar)` call sites. +func collectNsDefNames(f *ast.File) map[string]string { + out := map[string]string{} + ast.Inspect(f, func(n ast.Node) bool { + call, ok := n.(*ast.CallExpr) + if !ok || len(call.Args) != 2 { + return true + } + sel, ok := call.Fun.(*ast.SelectorExpr) + if !ok || sel.Sel.Name != "Def" { + return true + } + nsID, ok := sel.X.(*ast.Ident) + if !ok || nsID.Name != "ns" { + return true + } + lit, ok := call.Args[0].(*ast.BasicLit) + if !ok || lit.Kind != token.STRING { + return true + } + valID, ok := call.Args[1].(*ast.Ident) + if !ok { + return true + } + name, err := strconv.Unquote(lit.Value) + if err == nil { + out[valID.Name] = name + } + return true + }) + return out +} + +// --- free-variable analysis ---------------------------------------------- + +// freeVars returns identifiers used in the closure body that are neither +// declared within it nor package-level nor universe builtins — i.e. genuine +// enclosing-scope captures. Over-reports on shadowing rather than under, so a +// flagged site is skipped for human review, never mis-hoisted. +func freeVars(lit *ast.FuncLit, pkgNames map[string]bool) []string { + declared := map[string]bool{} + for _, fld := range lit.Type.Params.List { + for _, nm := range fld.Names { + declared[nm.Name] = true + } + } + // collect names bound anywhere inside the body + ast.Inspect(lit.Body, func(n ast.Node) bool { + switch x := n.(type) { + case *ast.AssignStmt: + if x.Tok == token.DEFINE { + for _, l := range x.Lhs { + if id, ok := l.(*ast.Ident); ok { + declared[id.Name] = true + } + } + } + case *ast.RangeStmt: + for _, e := range []ast.Expr{x.Key, x.Value} { + if id, ok := e.(*ast.Ident); ok { + declared[id.Name] = true + } + } + case *ast.DeclStmt: + if gd, ok := x.Decl.(*ast.GenDecl); ok { + for _, spec := range gd.Specs { + switch sp := spec.(type) { + case *ast.ValueSpec: + for _, nm := range sp.Names { + declared[nm.Name] = true + } + case *ast.TypeSpec: + declared[sp.Name.Name] = true + } + } + } + case *ast.FuncLit: + for _, fld := range x.Type.Params.List { + for _, nm := range fld.Names { + declared[nm.Name] = true + } + } + } + return true + }) + + // Idents that are NOT value references: a selector's field/method name + // (`x.Type` — `Type` is not a capture) and a struct composite's field key. + skip := map[*ast.Ident]bool{} + ast.Inspect(lit.Body, func(n ast.Node) bool { + switch x := n.(type) { + case *ast.SelectorExpr: + skip[x.Sel] = true + case *ast.CompositeLit: + // keys of a struct composite are field names. (Map/slice keys ARE + // values, so only skip when the type is a struct/named type — being + // conservative and NOT skipping when unsure would just over-flag.) + if isNamedType(x.Type) { + for _, elt := range x.Elts { + if kv, ok := elt.(*ast.KeyValueExpr); ok { + if id, ok := kv.Key.(*ast.Ident); ok { + skip[id] = true + } + } + } + } + } + return true + }) + + freeSet := map[string]bool{} + ast.Inspect(lit.Body, func(n ast.Node) bool { + if id, ok := n.(*ast.Ident); ok && !skip[id] { + considerIdent(id, declared, pkgNames, freeSet) + } + return true + }) + out := make([]string, 0, len(freeSet)) + for nm := range freeSet { + out = append(out, nm) + } + sort.Strings(out) + return out +} + +// isNamedType reports whether a composite-literal type is a named/struct type +// (T{…} or pkg.T{…}), whose keys are field names — as opposed to []T{…} / +// map[K]V{…} whose keys are values. +func isNamedType(e ast.Expr) bool { + switch e.(type) { + case *ast.Ident, *ast.SelectorExpr: + return true + default: + return false + } +} + +func considerIdent(id *ast.Ident, declared, pkg, free map[string]bool) { + nm := id.Name + if nm == "_" || declared[nm] || pkg[nm] || universe[nm] { + return + } + // treat obvious non-values out: capitalized single tokens that are types are + // usually package-level; if unknown, we flag (conservative). + free[nm] = true +} + +var universe = strSet( + "append", "cap", "clear", "close", "complex", "copy", "delete", "imag", + "len", "make", "max", "min", "new", "panic", "print", "println", "real", + "recover", "nil", "true", "false", "iota", + "bool", "byte", "rune", "string", "error", "int", "int8", "int16", "int32", + "int64", "uint", "uint8", "uint16", "uint32", "uint64", "uintptr", + "float32", "float64", "complex64", "complex128", "any", "comparable", +) + +// --- package-level name collection --------------------------------------- + +// lookupNamesInPackage collects every string literal passed to a `.Lookup("…")` +// call across all non-test .go files in dir. A primitive named by any of these +// lgRedefinedNames collects every name defined by a (def…)/(defn…)/(defmacro…) +// form in the stdlib .lg sources under dir/core. A primitive whose lg-name is +// redefined in core.lg is shadowed by that bootstrap definition at load; the +// eager core-namespace load does NOT reapply the native root over it (see +// coreload.go, which skips NameCoreNS), so a hoisted+guarded native there would +// deviate permanently (native-prims-intact? => false). On main these primitives +// were hand-registered but unguarded, so the .lg definition silently won — the +// behavior-preserving choice is to leave them un-hoisted. +func lgRedefinedNames(coreDir string) map[string]bool { + names := map[string]bool{} + re := regexp.MustCompile(`\(def(?:n|macro)?-?\s+([^\s()]+)`) + entries, err := os.ReadDir(coreDir) + if err != nil { + return names + } + for _, e := range entries { + if e.IsDir() || !strings.HasSuffix(e.Name(), ".lg") { + continue + } + src, err := os.ReadFile(filepath.Join(coreDir, e.Name())) + if err != nil { + continue + } + for _, m := range re.FindAllStringSubmatch(string(src), -1) { + names[m[1]] = true + } + } + return names +} + +// is fetched by lg-name at init time — possibly from ANOTHER file (host_core_fns +// aliases `class` to `ns.Lookup("type")`) before the generated registrar runs — +// so it must not be hoisted. Best-effort union across files. +func lookupNamesInPackage(dir string) map[string]bool { + names := map[string]bool{} + entries, err := os.ReadDir(dir) + if err != nil { + return names + } + fset := token.NewFileSet() + for _, e := range entries { + if e.IsDir() || !strings.HasSuffix(e.Name(), ".go") || strings.HasSuffix(e.Name(), "_test.go") { + continue + } + f, err := parser.ParseFile(fset, filepath.Join(dir, e.Name()), nil, 0) + if err != nil { + continue + } + ast.Inspect(f, func(n ast.Node) bool { + call, ok := n.(*ast.CallExpr) + if !ok || len(call.Args) != 1 { + return true + } + sel, ok := call.Fun.(*ast.SelectorExpr) + if !ok || sel.Sel.Name != "Lookup" { + return true + } + if lit, ok := call.Args[0].(*ast.BasicLit); ok && lit.Kind == token.STRING { + if name, err := strconv.Unquote(lit.Value); err == nil { + names[name] = true + } + } + return true + }) + } + return names +} + +func packageLevelNames(dir string) (map[string]bool, error) { + names := map[string]bool{} + entries, err := os.ReadDir(dir) + if err != nil { + return nil, err + } + fset := token.NewFileSet() + for _, e := range entries { + if e.IsDir() || !strings.HasSuffix(e.Name(), ".go") || strings.HasSuffix(e.Name(), "_test.go") { + continue + } + f, err := parser.ParseFile(fset, filepath.Join(dir, e.Name()), nil, 0) + if err != nil { + continue // tolerate build-tag / partial parse issues; names union is best-effort + } + for _, d := range f.Decls { + switch decl := d.(type) { + case *ast.FuncDecl: + if decl.Recv == nil { + names[decl.Name.Name] = true + } + case *ast.GenDecl: + for _, spec := range decl.Specs { + switch sp := spec.(type) { + case *ast.ValueSpec: + for _, nm := range sp.Names { + names[nm.Name] = true + } + case *ast.TypeSpec: + names[sp.Name.Name] = true + } + } + } + } + } + return names, nil +} + +func importNames(f *ast.File) map[string]bool { + out := map[string]bool{} + for _, imp := range f.Imports { + if imp.Name != nil { + out[imp.Name.Name] = true + continue + } + p, _ := strconv.Unquote(imp.Path.Value) + base := p + if i := strings.LastIndex(p, "/"); i >= 0 { + base = p[i+1:] + } + out[base] = true + } + return out +} + +// --- generation ----------------------------------------------------------- + +// genFunc renders the hoisted, annotated function for a safe site. +func genFunc(fset *token.FileSet, s *site) string { + name := hoistName(s.varName) + params := convertSignature(fset, s.lit.Type.Params) + results := renderResults(fset, s.lit.Type.Results) + body := nodeString(fset, s.lit.Body) + + var b strings.Builder + b.WriteString("//lg:native\n") + b.WriteString("//lg:name " + s.lgName + "\n") + fmt.Fprintf(&b, "func %s(%s) %s %s", name, params, results, body) + // gofmt the fragment + src := "package rt\n" + b.String() + "\n" + if out, err := format.Source([]byte(src)); err == nil { + return strings.TrimPrefix(string(out), "package rt\n\n") + } + return b.String() +} + +// convertSignature renders params, turning a trailing `vs []vm.Value` into the +// variadic `vs ...vm.Value` shape lginterop's native model consumes. Typed +// params (ec *vm.ExecContext, coll vm.Value, i int) pass through unchanged. +func convertSignature(fset *token.FileSet, params *ast.FieldList) string { + var parts []string + for i, fld := range params.List { + typ := fld.Type + if i == len(params.List)-1 { + if arr, ok := typ.(*ast.ArrayType); ok && arr.Len == nil && nodeString(fset, arr.Elt) == "vm.Value" { + name := "args" + if len(fld.Names) > 0 { + name = fld.Names[0].Name + } + parts = append(parts, name+" ...vm.Value") + continue + } + } + parts = append(parts, renderField(fset, fld)) + } + return strings.Join(parts, ", ") +} + +// renderField renders `[name[, name] ]type` for a param/result field. +// format.Node handles the type (an ast.Expr) but not *ast.Field itself. +func renderField(fset *token.FileSet, fld *ast.Field) string { + typ := nodeString(fset, fld.Type) + if len(fld.Names) == 0 { + return typ + } + names := make([]string, len(fld.Names)) + for i, nm := range fld.Names { + names[i] = nm.Name + } + return strings.Join(names, ", ") + " " + typ +} + +// renderResults renders the result list, parenthesised when needed. +func renderResults(fset *token.FileSet, results *ast.FieldList) string { + if results == nil || len(results.List) == 0 { + return "" + } + parts := make([]string, len(results.List)) + named := false + for i, fld := range results.List { + if len(fld.Names) > 0 { + named = true + } + parts[i] = renderField(fset, fld) + } + joined := strings.Join(parts, ", ") + if len(results.List) > 1 || named { + return "(" + joined + ") " + } + return joined + " " +} + +func hoistName(varName string) string { + // plus -> CorePlus, excludeInCurrentNs -> CoreExcludeInCurrentNs. + // EXPORTED (capital C): the gogen_ir lowered tree lives in sibling packages + // that direct-call these primitives as `rt.Core…`, so an unexported name + // would be invisible there (undefined: rt.corePlus). + if varName == "" { + return "CoreFn" + } + return "Core" + strings.ToUpper(varName[:1]) + varName[1:] +} + +// --- rewrite (apply) ------------------------------------------------------ + +// rewrite deletes each safe site's `X, _ := …` assignment and its +// `ns.Def("name", X)` statement, then appends the hoisted funcs, at the text +// level (position-based) so formatting elsewhere is untouched. gofmt at the end. +func rewrite(path string, fset *token.FileSet, f *ast.File, safe []*site, defNames map[string]string) error { + src, err := os.ReadFile(path) + if err != nil { + return err + } + type span struct{ start, end int } + var cuts []span + byVar := map[string]*site{} + for _, s := range safe { + byVar[s.varName] = s + cuts = append(cuts, span{fset.Position(s.assign.Pos()).Offset, lineEnd(src, fset.Position(s.assign.End()).Offset)}) + } + // find the ns.Def statements to cut + ast.Inspect(f, func(n ast.Node) bool { + call, ok := n.(*ast.CallExpr) + if !ok || len(call.Args) != 2 { + return true + } + sel, ok := call.Fun.(*ast.SelectorExpr) + if !ok || sel.Sel.Name != "Def" { + return true + } + if id, ok := sel.X.(*ast.Ident); !ok || id.Name != "ns" { + return true + } + valID, ok := call.Args[1].(*ast.Ident) + if !ok || byVar[valID.Name] == nil { + return true + } + cuts = append(cuts, span{lineStart(src, fset.Position(call.Pos()).Offset), lineEnd(src, fset.Position(call.End()).Offset)}) + return true + }) + + // Cut `if err != nil { … }` guards left dead by the removal. An `err` local + // is typically threaded through every Wrap assignment in a block — each with + // its own `if err != nil { panic(err) }`, plus a trailing consolidated + // `if err != nil { panic("… failed") }`. Once every assignment that DECLARES + // that err (via `:=`) is cut and no surviving `:=` redeclares it, the name is + // undefined and all its guards are dead. Work per block: a name declared only + // by cut assigns (and by no surviving `:=`) is orphaned, so cut every + // `if != nil {…}` guard in that block. Scoped this way, a guard whose + // err still has a live declaration is never touched. + safeAssigns := map[*ast.AssignStmt]bool{} + for _, s := range safe { + safeAssigns[s.assign] = true + } + declaredNames := func(as *ast.AssignStmt) []string { + if as.Tok != token.DEFINE { + return nil + } + var ns []string + for _, l := range as.Lhs { + if id, ok := l.(*ast.Ident); ok && id.Name != "_" { + ns = append(ns, id.Name) + } + } + return ns + } + ast.Inspect(f, func(n ast.Node) bool { + blk, ok := n.(*ast.BlockStmt) + if !ok { + return true + } + cutDecl, surviveDecl := map[string]bool{}, map[string]bool{} + for _, st := range blk.List { + as, ok := st.(*ast.AssignStmt) + if !ok { + continue + } + names := declaredNames(as) + target := surviveDecl + if safeAssigns[as] { + target = cutDecl + } + for _, nm := range names { + target[nm] = true + } + } + for _, st := range blk.List { + name := errGuardName(st) + if name != "" && cutDecl[name] && !surviveDecl[name] { + cuts = append(cuts, span{lineStart(src, fset.Position(st.Pos()).Offset), lineEnd(src, fset.Position(st.End()).Offset)}) + } + } + return true + }) + + sort.Slice(cuts, func(i, j int) bool { return cuts[i].start > cuts[j].start }) + out := append([]byte(nil), src...) + for _, c := range cuts { + out = append(out[:c.start], out[c.end:]...) + } + + var appended bytes.Buffer + appended.WriteString("\n// --- hoisted native primitives (see cmd/hoist-natives) ---\n\n") + for _, s := range safe { + appended.WriteString(genFunc(fset, s)) + appended.WriteString("\n\n") + } + out = append(out, appended.Bytes()...) + + formatted, err := format.Source(out) + if err != nil { + // leave unformatted so the author can inspect; still write + formatted = out + } + return os.WriteFile(path, formatted, 0644) +} + +// errGuardName returns the identifier name X for a statement of the exact shape +// `if X != nil { … }` (no init/else), or "" otherwise. The caller decides +// whether X is orphaned before cutting, so this only classifies the shape. +func errGuardName(s ast.Stmt) string { + ifs, ok := s.(*ast.IfStmt) + if !ok || ifs.Init != nil || ifs.Else != nil { + return "" + } + bin, ok := ifs.Cond.(*ast.BinaryExpr) + if !ok || bin.Op != token.NEQ { + return "" + } + x, ok := bin.X.(*ast.Ident) + if !ok { + return "" + } + if y, ok := bin.Y.(*ast.Ident); !ok || y.Name != "nil" { + return "" + } + return x.Name +} + +func lineStart(src []byte, off int) int { + for off > 0 && src[off-1] != '\n' { + off-- + } + return off +} +func lineEnd(src []byte, off int) int { + for off < len(src) && src[off] != '\n' { + off++ + } + if off < len(src) { + off++ // include newline + } + return off +} + +// --- reporting ------------------------------------------------------------ + +func report(fset *token.FileSet, safe []*site, skipCap map[string][]string, skipNoName []string, defNames map[string]string) { + fmt.Printf("hoist-natives report\n====================\n") + fmt.Printf("safe to hoist: %d\n", len(safe)) + fmt.Printf("skipped (captures): %d\n", len(skipCap)) + fmt.Printf("skipped (no lg name): %d\n\n", len(skipNoName)) + + if len(skipCap) > 0 { + fmt.Println("-- skipped: genuine enclosing-scope captures (need ec-threading / manual) --") + keys := sortedKeys(skipCap) + for _, k := range keys { + fmt.Printf(" %-24s captures: %s (lg: %q)\n", k, strings.Join(skipCap[k], ", "), defNames[k]) + } + fmt.Println() + } + if len(skipNoName) > 0 { + sort.Strings(skipNoName) + fmt.Println("-- skipped: no ns.Def(\"name\", var) found (registered differently / internal) --") + fmt.Printf(" %s\n\n", strings.Join(skipNoName, ", ")) + } +} + +// --- helpers -------------------------------------------------------------- + +func nodeString(fset *token.FileSet, n ast.Node) string { + if n == nil { + return "" + } + var b bytes.Buffer + if err := format.Node(&b, fset, n); err != nil { + return "" + } + return b.String() +} + +func strSet(xs ...string) map[string]bool { + m := make(map[string]bool, len(xs)) + for _, x := range xs { + m[x] = true + } + return m +} + +func sortedKeys[V any](m map[string]V) []string { + ks := make([]string, 0, len(m)) + for k := range m { + ks = append(ks, k) + } + sort.Strings(ks) + return ks +} + +// --- helper lift ---------------------------------------------------------- + +type helperSite struct { + name string + lit *ast.FuncLit + assign *ast.AssignStmt +} + +// liftHelpers lifts named installCore-local helper closures (X := func…{…}) to +// package-level funcs. Helpers may call each other, so the requested set is +// treated as already-package-level for the capture check. +func liftHelpers(path string, fset *token.FileSet, f *ast.File, set, pkgNames map[string]bool, apply bool) { + for name := range set { + pkgNames[name] = true + } + sites := findHelperDecls(f, set) + found := map[string]bool{} + var safe []*helperSite + skipCap := map[string][]string{} + for _, h := range sites { + found[h.name] = true + if captured := freeVars(h.lit, pkgNames); len(captured) > 0 { + skipCap[h.name] = captured + continue + } + safe = append(safe, h) + } + + fmt.Printf("lift-helpers report\n===================\n") + fmt.Printf("requested: %d, found: %d, liftable: %d, capture-blocked: %d\n\n", + len(set), len(found), len(safe), len(skipCap)) + for name := range set { + if !found[name] { + fmt.Printf(" NOT FOUND as `%s := func…`\n", name) + } + } + for _, k := range sortedKeys(skipCap) { + fmt.Printf(" capture-blocked %-20s captures: %s\n", k, strings.Join(skipCap[k], ", ")) + } + fmt.Println() + + if apply { + if err := rewriteHelpers(path, fset, safe); err != nil { + die("lift-helpers apply: %v", err) + } + fmt.Printf("applied: lifted %d helpers into %s\n", len(safe), path) + return + } + fmt.Printf("dry run — proposed package-level funcs for the %d liftable helpers:\n\n", len(safe)) + for _, h := range safe { + fmt.Println(genHelper(fset, h)) + } +} + +func findHelperDecls(f *ast.File, set map[string]bool) []*helperSite { + var out []*helperSite + ast.Inspect(f, func(n ast.Node) bool { + as, ok := n.(*ast.AssignStmt) + if !ok || as.Tok != token.DEFINE || len(as.Lhs) != 1 || len(as.Rhs) != 1 { + return true + } + id, ok := as.Lhs[0].(*ast.Ident) + if !ok || !set[id.Name] { + return true + } + lit, ok := as.Rhs[0].(*ast.FuncLit) + if !ok { + return true + } + out = append(out, &helperSite{name: id.Name, lit: lit, assign: as}) + return true + }) + return out +} + +// genHelper renders a lifted helper as a package-level func — no annotations, no +// signature conversion (helpers keep their exact interface). +func genHelper(fset *token.FileSet, h *helperSite) string { + var params []string + for _, fld := range h.lit.Type.Params.List { + params = append(params, renderField(fset, fld)) + } + results := renderResults(fset, h.lit.Type.Results) + body := nodeString(fset, h.lit.Body) + src := fmt.Sprintf("package rt\nfunc %s(%s) %s%s\n", h.name, strings.Join(params, ", "), results, body) + if out, err := format.Source([]byte(src)); err == nil { + return strings.TrimPrefix(string(out), "package rt\n\n") + } + return src +} + +func rewriteHelpers(path string, fset *token.FileSet, safe []*helperSite) error { + src, err := os.ReadFile(path) + if err != nil { + return err + } + type span struct{ start, end int } + var cuts []span + for _, h := range safe { + cuts = append(cuts, span{ + lineStart(src, fset.Position(h.assign.Pos()).Offset), + lineEnd(src, fset.Position(h.assign.End()).Offset), + }) + } + sort.Slice(cuts, func(i, j int) bool { return cuts[i].start > cuts[j].start }) + out := append([]byte(nil), src...) + for _, c := range cuts { + out = append(out[:c.start], out[c.end:]...) + } + var appended bytes.Buffer + appended.WriteString("\n// --- lifted native helpers (see cmd/hoist-natives -helpers) ---\n\n") + for _, h := range safe { + appended.WriteString(genHelper(fset, h)) + appended.WriteString("\n\n") + } + out = append(out, appended.Bytes()...) + formatted, err := format.Source(out) + if err != nil { + formatted = out + } + return os.WriteFile(path, formatted, 0644) +} + +func splitSet(csv string) map[string]bool { + m := map[string]bool{} + for _, p := range strings.Split(csv, ",") { + if p = strings.TrimSpace(p); p != "" { + m[p] = true + } + } + return m +} + +func die(format string, args ...any) { + fmt.Fprintf(os.Stderr, "hoist-natives: "+format+"\n", args...) + os.Exit(1) +} diff --git a/cmd/lginterop/main.go b/cmd/lginterop/main.go index b90c618a7..b575dc67a 100644 --- a/cmd/lginterop/main.go +++ b/cmd/lginterop/main.go @@ -16,8 +16,8 @@ import ( "sort" "strconv" "strings" - "unicode" + "github.com/nooga/let-go/internal/primgen" "github.com/nooga/let-go/pkg/compiler" "github.com/nooga/let-go/pkg/vm" ) @@ -45,9 +45,12 @@ func main() { goPkg := flag.String("go-pkg", "", "Go import path of the scanned sources (used with -primitives)") flag.Parse() - // Handle -primitives mode (separate from the external interop path) + // Handle -primitives mode (separate from the external interop path). + // Delegates to the runtime-free primgen package — prefer the standalone + // cmd/lgprimgen binary, which does not import pkg/compiler and so can run + // mid-migration when the runtime this binary boots cannot. if *primitivesDir != "" { - if err := generatePrimitives(*primitivesDir, *primitivesOut, *goPkg); err != nil { + if err := primgen.Generate(*primitivesDir, *primitivesOut, *goPkg); err != nil { fmt.Fprintf(os.Stderr, "lginterop: %v\n", err) os.Exit(1) } @@ -123,94 +126,6 @@ func main() { fmt.Printf("lginterop: generated %d/%d package(s) in %s\n", okCount, len(entries), *out) } -// --- primitives generation (-primitives mode) -------------------------------- - -func generatePrimitives(srcDir, outPath, goPkg string) error { - // Walk srcDir and scan all .go files for //lg:native directives - var allSpecs []primSpec - - entries, err := os.ReadDir(srcDir) - if err != nil { - return fmt.Errorf("read directory %s: %w", srcDir, err) - } - - for _, entry := range entries { - // Skip test files and generated output: an //lg:native annotation in - // a _test.go or zz_ file would emit an unconditional reference to a - // symbol the normal build doesn't compile. - if entry.IsDir() || !strings.HasSuffix(entry.Name(), ".go") || - strings.HasSuffix(entry.Name(), "_test.go") || - strings.HasPrefix(entry.Name(), "zz_") { - continue - } - - fpath := filepath.Join(srcDir, entry.Name()) - src, err := os.ReadFile(fpath) - if err != nil { - return fmt.Errorf("read %s: %w", fpath, err) - } - - // Files under a build constraint may reference symbols absent from - // other targets; the registrar compiles unconditionally, so skip them. - if hasBuildConstraint(src) { - continue - } - - specs, err := scanSource(fpath, src) - if err != nil { - return fmt.Errorf("parse %s: %w", fpath, err) - } - allSpecs = append(allSpecs, specs...) - } - - if len(allSpecs) == 0 { - fmt.Printf("lginterop: no //lg:native directives found in %s; generating empty stub\n", srcDir) - // Fall through to generate an empty RegisterGeneratedPrimitives() stub - } - - // Set GoPkg on all specs - for i := range allSpecs { - if goPkg != "" { - allSpecs[i].GoPkg = goPkg - } else if allSpecs[i].GoPkg == "" { - // Fallback default - allSpecs[i].GoPkg = "github.com/nooga/let-go/pkg/rt/builtins" - } - } - - // Generate the file - output := emitFile(allSpecs) - - // Format with gofmt - formatted, err := gofmtCode(output) - if err != nil { - return fmt.Errorf("gofmt: %w", err) - } - - // Write the output file - if err := os.MkdirAll(filepath.Dir(outPath), 0755); err != nil { - return fmt.Errorf("mkdir %s: %w", filepath.Dir(outPath), err) - } - - if err := os.WriteFile(outPath, []byte(formatted), 0644); err != nil { - return fmt.Errorf("write %s: %w", outPath, err) - } - - fmt.Printf("lginterop: generated primitives → %s (%d specs)\n", outPath, len(allSpecs)) - return nil -} - -// gofmtCode formats Go source code using the gofmt command. -func gofmtCode(src string) (string, error) { - cmd := exec.Command("gofmt") - cmd.Stdin = strings.NewReader(src) - output, err := cmd.Output() - if err != nil { - return "", fmt.Errorf("gofmt failed: %w", err) - } - return string(output), nil -} - // --- repo root & lg binary discovery -------------------------------------- func findRepoRoot() (string, error) { @@ -697,7 +612,7 @@ func buildSkeleton(alias string, exports []export, smart bool) string { } if smart { - fmt.Fprintf(b, "(defn- %s\n", kebabCase(ex.name)) + fmt.Fprintf(b, "(defn- %s\n", primgen.KebabCase(ex.name)) fmt.Fprintf(b, " \"Wrapper for %s. Customize as needed.\"\n", qname) if variadic { fmt.Fprintf(b, " [& args]\n") @@ -710,7 +625,7 @@ func buildSkeleton(alias string, exports []export, smart bool) string { fmt.Fprintf(b, " (%s %s))\n\n", qname, strings.Join(argNames, " ")) } } else { - fmt.Fprintf(b, "(defn- %s\n", kebabCase(ex.name)) + fmt.Fprintf(b, "(defn- %s\n", primgen.KebabCase(ex.name)) fmt.Fprintf(b, " \"Wrapper for %s. Customize as needed.\"\n", qname) if variadic { fmt.Fprintf(b, " [& args]\n") @@ -730,33 +645,15 @@ func buildSkeleton(alias string, exports []export, smart bool) string { } case *types.Const: fmt.Fprintf(b, ";; Constant: %s\n", qname) - fmt.Fprintf(b, ";; (def %s %s)\n\n", kebabCase(ex.name), qname) + fmt.Fprintf(b, ";; (def %s %s)\n\n", primgen.KebabCase(ex.name), qname) case *types.Var: fmt.Fprintf(b, ";; Variable: %s\n", qname) - fmt.Fprintf(b, ";; (def %s %s)\n\n", kebabCase(ex.name), qname) + fmt.Fprintf(b, ";; (def %s %s)\n\n", primgen.KebabCase(ex.name), qname) } } return b.String() } -func kebabCase(s string) string { - var b strings.Builder - for i, r := range s { - if i > 0 { - prev := rune(s[i-1]) - if unicode.IsUpper(r) { - if unicode.IsLower(prev) { - b.WriteByte('-') - } else if i+1 < len(s) && unicode.IsLower(rune(s[i+1])) { - b.WriteByte('-') - } - } - } - b.WriteRune(unicode.ToLower(r)) - } - return b.String() -} - // Avoid "declared and not used" for runtime import. var _ = runtime.GOOS diff --git a/cmd/lgprimgen/main.go b/cmd/lgprimgen/main.go new file mode 100644 index 000000000..641b4e018 --- /dev/null +++ b/cmd/lgprimgen/main.go @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2026 Norman Nunley, Jr + * Part of the let-go project; see CONTRIBUTORS for full list of authors. + * SPDX-License-Identifier: MIT + */ + +// Command lgprimgen generates pkg/rt/zz_primitives_generated.go from the +// //lg:native directives in the runtime's Go sources. +// +// It is split out from cmd/lginterop precisely so it imports NOTHING that boots +// the let-go runtime (no pkg/compiler, no pkg/rt). lginterop pulls in +// pkg/compiler for its interop-EDN mode, whose package init compiles core.lg — +// which fails mid-migration, when primitives have been moved out of +// installLangNS but the registrar that replaces them hasn't been generated yet. +// The generator must run in exactly that inconsistent state (it is what makes it +// consistent again), so it stays a pure go/ast → Go codegen tool. +package main + +import ( + "flag" + "fmt" + "os" + + "github.com/nooga/let-go/internal/primgen" +) + +func main() { + srcDir := flag.String("primitives", "pkg/rt", "directory containing //lg:-annotated Go sources") + out := flag.String("primitives-out", "pkg/rt/zz_primitives_generated.go", "output file for the generated registrar") + goPkg := flag.String("go-pkg", "github.com/nooga/let-go/pkg/rt", "Go import path of the scanned sources") + flag.Parse() + + if err := primgen.Generate(*srcDir, *out, *goPkg); err != nil { + fmt.Fprintf(os.Stderr, "lgprimgen: %v\n", err) + os.Exit(1) + } +} diff --git a/internal/primgen/generate.go b/internal/primgen/generate.go new file mode 100644 index 000000000..2a152707b --- /dev/null +++ b/internal/primgen/generate.go @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2026 Norman Nunley, Jr + * Part of the let-go project; see CONTRIBUTORS for full list of authors. + * SPDX-License-Identifier: MIT + */ + +// Package primgen scans //lg:-annotated Go sources and emits the +// zz_primitives_generated.go registrar. It is deliberately a PURE source → +// source code generator: it depends only on go/ast + text templates and does +// NOT import the let-go runtime (pkg/compiler / pkg/rt). +// +// This independence is the whole point. The registrar it emits is what lets the +// NEXT-generation runtime boot; a generator that booted the current runtime +// would depend on the very artifacts it is about to produce (p0 depending on +// p1). During a large primitive migration — closures moved out of installLangNS +// but not yet in the generated registrar — that runtime cannot boot, so a +// runtime-coupled generator would deadlock the regeneration it exists to drive. +package primgen + +import ( + "fmt" + "os" + "os/exec" + "path/filepath" + "strings" + "unicode" +) + +// KebabCase converts a Go identifier (CamelCase) to a let-go kebab name. Used +// both to default a primitive's lg-name during scanning and by lginterop's +// skeleton emitter, so it lives in the shared runtime-free package. +func KebabCase(s string) string { + var b strings.Builder + for i, r := range s { + if i > 0 { + prev := rune(s[i-1]) + if unicode.IsUpper(r) { + if unicode.IsLower(prev) { + b.WriteByte('-') + } else if i+1 < len(s) && unicode.IsLower(rune(s[i+1])) { + b.WriteByte('-') + } + } + } + b.WriteRune(unicode.ToLower(r)) + } + return b.String() +} + +// Generate scans srcDir for //lg:native directives and writes the generated +// primitive registrar to outPath. goPkg is the Go import path of the scanned +// sources (used for cross-package symbol references); empty falls back to the +// per-spec GoPkg or the builtins default. +func Generate(srcDir, outPath, goPkg string) error { + var allSpecs []primSpec + + entries, err := os.ReadDir(srcDir) + if err != nil { + return fmt.Errorf("read directory %s: %w", srcDir, err) + } + + for _, entry := range entries { + // Skip test files and generated output: an //lg:native annotation in + // a _test.go or zz_ file would emit an unconditional reference to a + // symbol the normal build doesn't compile. + if entry.IsDir() || !strings.HasSuffix(entry.Name(), ".go") || + strings.HasSuffix(entry.Name(), "_test.go") || + strings.HasPrefix(entry.Name(), "zz_") { + continue + } + + fpath := filepath.Join(srcDir, entry.Name()) + src, err := os.ReadFile(fpath) + if err != nil { + return fmt.Errorf("read %s: %w", fpath, err) + } + + // Files under a build constraint may reference symbols absent from + // other targets; the registrar compiles unconditionally, so skip them. + if hasBuildConstraint(src) { + continue + } + + specs, err := scanSource(fpath, src) + if err != nil { + return fmt.Errorf("parse %s: %w", fpath, err) + } + allSpecs = append(allSpecs, specs...) + } + + if len(allSpecs) == 0 { + fmt.Printf("lgprimgen: no //lg:native directives found in %s; generating empty stub\n", srcDir) + // Fall through to generate an empty RegisterGeneratedPrimitives() stub + } + + for i := range allSpecs { + if goPkg != "" { + allSpecs[i].GoPkg = goPkg + } else if allSpecs[i].GoPkg == "" { + allSpecs[i].GoPkg = "github.com/nooga/let-go/pkg/rt/builtins" + } + } + + output := emitFile(allSpecs) + + formatted, err := gofmtCode(output) + if err != nil { + return fmt.Errorf("gofmt: %w", err) + } + + if err := os.MkdirAll(filepath.Dir(outPath), 0755); err != nil { + return fmt.Errorf("mkdir %s: %w", filepath.Dir(outPath), err) + } + if err := os.WriteFile(outPath, []byte(formatted), 0644); err != nil { + return fmt.Errorf("write %s: %w", outPath, err) + } + + fmt.Printf("lgprimgen: generated primitives → %s (%d specs)\n", outPath, len(allSpecs)) + return nil +} + +// ScanNativeNames returns the set of let-go names already claimed by //lg:native +// declarations in dir's Go sources, skipping excludeBase (a file basename, e.g. +// "lang.go"). The hoist codemod uses it to avoid hoisting a closure whose +// lg-name a pre-existing native decl already owns — doing so would emit a +// duplicate registration and fail to compile the generated registrar. Reuses +// the same scanner lgprimgen runs, so both agree on what a name is. +func ScanNativeNames(dir, excludeBase string) (map[string]bool, error) { + names := map[string]bool{} + entries, err := os.ReadDir(dir) + if err != nil { + return nil, err + } + for _, entry := range entries { + if entry.IsDir() || !strings.HasSuffix(entry.Name(), ".go") || + strings.HasSuffix(entry.Name(), "_test.go") || + strings.HasPrefix(entry.Name(), "zz_") || + entry.Name() == excludeBase { + continue + } + fpath := filepath.Join(dir, entry.Name()) + src, err := os.ReadFile(fpath) + if err != nil { + return nil, err + } + if hasBuildConstraint(src) { + continue + } + specs, err := scanSource(fpath, src) + if err != nil { + return nil, err + } + for _, s := range specs { + names[s.LgName] = true + } + } + return names, nil +} + +// gofmtCode formats Go source code using the gofmt command. On failure it +// surfaces gofmt's stderr (which carries the :: syntax-error +// location) and dumps the unformatted source to a temp file, so a bad emitted +// registrar is diagnosable instead of a bare "exit status 2". +func gofmtCode(src string) (string, error) { + cmd := exec.Command("gofmt") + cmd.Stdin = strings.NewReader(src) + var stderr strings.Builder + cmd.Stderr = &stderr + output, err := cmd.Output() + if err != nil { + dump := filepath.Join(os.TempDir(), "lgprimgen-unformatted.go") + _ = os.WriteFile(dump, []byte(src), 0644) + return "", fmt.Errorf("gofmt failed: %w\n%s(unformatted source written to %s)", err, stderr.String(), dump) + } + return string(output), nil +} diff --git a/cmd/lginterop/prims_emit.go b/internal/primgen/prims_emit.go similarity index 99% rename from cmd/lginterop/prims_emit.go rename to internal/primgen/prims_emit.go index a73892cdf..74f44f0e0 100644 --- a/cmd/lginterop/prims_emit.go +++ b/internal/primgen/prims_emit.go @@ -1,4 +1,4 @@ -package main +package primgen import ( "fmt" @@ -488,11 +488,11 @@ func generateAritySpecificAdapter(spec *primSpec, arity int, pkgAliasMap map[str fmt.Fprintf(&b, "%s", varName) } - // Add variadic arguments: pass remaining vs elements + // Add variadic arguments: pass remaining vs elements, then close the call. if len(spec.ParamSpecs) > 0 { - fmt.Fprintf(&b, ", vs[%d:]...\n", len(spec.ParamSpecs)) + fmt.Fprintf(&b, ", vs[%d:]...)\n", len(spec.ParamSpecs)) } else { - b.WriteString("vs...\n") + b.WriteString("vs...)\n") } } else { // Non-variadic: standard parameter coercion diff --git a/cmd/lginterop/prims_scan.go b/internal/primgen/prims_scan.go similarity index 99% rename from cmd/lginterop/prims_scan.go rename to internal/primgen/prims_scan.go index 26220a438..c0e320069 100644 --- a/cmd/lginterop/prims_scan.go +++ b/internal/primgen/prims_scan.go @@ -1,4 +1,4 @@ -package main +package primgen import ( "bytes" @@ -90,7 +90,7 @@ func scanSource(path string, src []byte) ([]primSpec, error) { // Determine lg name (default: kebab-cased GoIdent) lgName := name if lgName == "" { - lgName = kebabCase(goIdent) + lgName = KebabCase(goIdent) } // Parse parameters diff --git a/cmd/lginterop/prims_test.go b/internal/primgen/prims_test.go similarity index 99% rename from cmd/lginterop/prims_test.go rename to internal/primgen/prims_test.go index f36d1950d..3d7ac9603 100644 --- a/cmd/lginterop/prims_test.go +++ b/internal/primgen/prims_test.go @@ -1,4 +1,4 @@ -package main +package primgen import ( "go/parser" diff --git a/pkg/compiler/eval.go b/pkg/compiler/eval.go index 0160e7466..cd6b14a63 100644 --- a/pkg/compiler/eval.go +++ b/pkg/compiler/eval.go @@ -119,7 +119,17 @@ func evalInit() { c.SetSource("") _, _, err := c.CompileMultiple(strings.NewReader(rt.CoreSrc)) if err != nil { - panic("core.lg compilation failed: " + err.Error()) + // A bootstrap resolve failure ("Can't resolve X") usually means a + // generated //lg:native primitive registered into the wrong namespace. + // Attach the non-terminating registration audit so ALL misregistered + // primitives are reported at once (with where each actually landed), + // instead of re-running to discover them one panic at a time. + msg := "core.lg compilation failed: " + err.Error() + if audit := rt.AuditGeneratedPrimitives(); len(audit) > 0 { + msg += fmt.Sprintf("\n\ngenerated-primitive audit (%d not resolvable in canonical ns):\n %s", + len(audit), strings.Join(audit, "\n ")) + } + panic(msg) } // Bundle-path parity (purify-clojure-core ②): the lg baseline namespaces // (let-go.core, …) are auto-refer'd into every namespace but never explicitly diff --git a/pkg/rt/core_compiled.lgb b/pkg/rt/core_compiled.lgb index 405480a5b..1b22eacff 100644 Binary files a/pkg/rt/core_compiled.lgb and b/pkg/rt/core_compiled.lgb differ diff --git a/pkg/rt/generated.sums b/pkg/rt/generated.sums index b2e29b9cd..946c20595 100644 --- a/pkg/rt/generated.sums +++ b/pkg/rt/generated.sums @@ -2,4 +2,4 @@ # Content digest of all .lg + lgbgen sources that feed the .lgb # bundle and the lowered Go tree. The genmanifest staleness test # fails if this no longer matches the sources on disk. -0a3d203cefa6782f9266fe6aa86a36d1f34dc65170af0eb37708162ced4f4d6d +031b3c41c8f5ff3e2084e0629cb1227ae34de5bdb7bc95d6b35e238fe5731695 diff --git a/pkg/rt/generated_prim_audit_test.go b/pkg/rt/generated_prim_audit_test.go new file mode 100644 index 000000000..ccfeb27af --- /dev/null +++ b/pkg/rt/generated_prim_audit_test.go @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2026 Norman Nunley, Jr + * Part of the let-go project; see CONTRIBUTORS for full list of authors. + * SPDX-License-Identifier: MIT + */ + +package rt + +import ( + "strings" + "testing" + + "github.com/nooga/let-go/pkg/vm" +) + +// TestAuditGeneratedPrimitivesCleanAfterInit is the permanent regression guard +// for the alias-resolution bug (LookupOrRegisterNSNoLoad registering into a +// phantom "clojure.core" instead of canonical "core"): every generated +// primitive MUST be resolvable in its canonical namespace after init. This is +// also the gate to run after hoisting native closures to //lg:native decls — +// if any batch misregisters, this names each offender instead of leaving the +// bootstrap compile to die on the first `Can't resolve X`. +func TestAuditGeneratedPrimitivesCleanAfterInit(t *testing.T) { + if probs := AuditGeneratedPrimitives(); len(probs) > 0 { + t.Fatalf("generated primitives not all resolvable in their canonical namespace:\n %s", + strings.Join(probs, "\n ")) + } +} + +// TestAuditGeneratedPrimitivesFlagsMisregistration proves the audit is a +// non-terminating diagnostic: given a primitive recorded under a canonical ns +// but actually bound in a different ns (the exact shape of the alias bug), it +// reports the miss AND points at where the name actually landed. +func TestAuditGeneratedPrimitivesFlagsMisregistration(t *testing.T) { + const probe = "audit-probe-should-not-collide" + adapter, err := vm.NativeFnType.Wrap(func(_ []vm.Value) (vm.Value, error) { return vm.NIL, nil }) + if err != nil { + t.Fatalf("wrap adapter: %v", err) + } + + // Bind the probe in a phantom namespace (simulating a prim that landed in + // the wrong ns), and register it so whereNameBound can locate it. + phantom := vm.NewNamespace("clojure.audit.phantom") + phantom.Def(probe, adapter) + RegisterNS(phantom) + + // Record it under canonical "core", which does NOT bind the probe. + genPrimMu.Lock() + if genPrimBindings[NameCoreNS] == nil { + genPrimBindings[NameCoreNS] = map[string]vm.Value{} + } + genPrimBindings[NameCoreNS][probe] = adapter + genPrimMu.Unlock() + defer func() { + genPrimMu.Lock() + delete(genPrimBindings[NameCoreNS], probe) + genPrimMu.Unlock() + }() + + var line string + for _, p := range AuditGeneratedPrimitives() { + if strings.Contains(p, probe) { + line = p + } + } + if line == "" { + t.Fatalf("audit did not flag misregistered %q", probe) + } + if !strings.Contains(line, "not bound in canonical ns") { + t.Errorf("audit line missing reason: %s", line) + } + if !strings.Contains(line, "clojure.audit.phantom") { + t.Errorf("audit line did not point at the phantom ns: %s", line) + } +} diff --git a/pkg/rt/lang.go b/pkg/rt/lang.go index 82ab02b16..23ecde859 100644 --- a/pkg/rt/lang.go +++ b/pkg/rt/lang.go @@ -703,6 +703,18 @@ func LookupOrRegisterNS(name string) *vm.Namespace { } func LookupOrRegisterNSNoLoad(name string) *vm.Namespace { + // Resolve the alias BEFORE touching the registry, as the loading callers do. + // Without this, LookupOrRegisterNSNoLoad("clojure.core") registers a DISTINCT + // "clojure.core" namespace instead of returning the canonical "core" — so the + // generated primitive registrar (RegisterGeneratedPrimitives, which calls this + // with "clojure.core"/"clojure.string"/…) Defs into the wrong namespace, + // invisible to core.lg's own bootstrap compile. Hand-registered primitives + // hid this by also Def'ing into the canonical ns via installLangNS; a primitive + // hoisted to //lg:native has ONLY the generated registration, so it must land + // in the canonical namespace to resolve. + canonical := resolveNSAlias(name) + aliased := canonical != name + name = canonical nsMu.RLock() e := nsRegistry[name] nsMu.RUnlock() @@ -723,6 +735,17 @@ func LookupOrRegisterNSNoLoad(name string) *vm.Namespace { nsRegistry[name] = ns nsMu.Unlock() + // If we just PRE-CREATED a canonical ns from an alias (e.g. clojure.string → + // string) to home a generated native, its .lg source has NOT run — only the + // native being registered now exists. Flag it needs-load so a later + // (require 'clojure.string) still executes the .lg defns (join, split, …) + // instead of short-circuiting on this native-only ns in LookupOrRegisterNS. + // Core is exempt: it is installed eagerly (installLangNS) before any generated + // registrar runs, so it never reaches this newly-created branch. + if aliased { + MarkNSNeedsLoad(name) + } + return ns } @@ -1885,133 +1908,9 @@ func setRandSeed(seed int64) { } func installLangNS() { - plus, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) == 0 { - return vm.MakeInt(0), nil - } - if len(vs) == 1 { - return vs[0], nil - } - acc := vs[0] - for i := 1; i < len(vs); i++ { - var err error - acc, err = vm.NumAdd(acc, vs[i]) - if err != nil { - return vm.NIL, err - } - } - return acc, nil - }) - - mul, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) == 0 { - return vm.MakeInt(1), nil - } - if len(vs) == 1 { - return vs[0], nil - } - acc := vs[0] - for i := 1; i < len(vs); i++ { - var err error - acc, err = vm.NumMul(acc, vs[i]) - if err != nil { - return vm.NIL, err - } - } - return acc, nil - }) - - sub, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) < 1 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - if len(vs) == 1 { - return vm.NumNeg(vs[0]) - } - acc := vs[0] - for i := 1; i < len(vs); i++ { - var err error - acc, err = vm.NumSub(acc, vs[i]) - if err != nil { - return vm.NIL, err - } - } - return acc, nil - }) - - div, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) < 1 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - if len(vs) == 1 { - return vm.NumDiv(vm.MakeInt(1), vs[0]) - } - acc := vs[0] - for i := 1; i < len(vs); i++ { - var err error - acc, err = vm.NumDiv(acc, vs[i]) - if err != nil { - return vm.NIL, err - } - } - return acc, nil - }) // Apostrophe arithmetic: identical to + - * but promotes to BigInt on // int64 overflow instead of wrapping silently. - plusP, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) == 0 { - return vm.MakeInt(0), nil - } - if len(vs) == 1 { - return vs[0], nil - } - acc := vs[0] - for i := 1; i < len(vs); i++ { - var err error - acc, err = vm.NumAddP(acc, vs[i]) - if err != nil { - return vm.NIL, err - } - } - return acc, nil - }) - - mulP, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) == 0 { - return vm.MakeInt(1), nil - } - if len(vs) == 1 { - return vs[0], nil - } - acc := vs[0] - for i := 1; i < len(vs); i++ { - var err error - acc, err = vm.NumMulP(acc, vs[i]) - if err != nil { - return vm.NIL, err - } - } - return acc, nil - }) - - subP, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) < 1 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - if len(vs) == 1 { - return vm.NumNegP(vs[0]) - } - acc := vs[0] - for i := 1; i < len(vs); i++ { - var err error - acc, err = vm.NumSubP(acc, vs[i]) - if err != nil { - return vm.NIL, err - } - } - return acc, nil - }) // unchecked-* family — silent wrap on int64 overflow. // @@ -2028,257 +1927,6 @@ func installLangNS() { // long-arithmetic semantics). Use `+`/`-`/`*` for checked arithmetic, // or `+'`/`-'`/`*'` for BigInt-promoting arithmetic. - uncheckedAdd, err := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 2 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - a, ok := vm.ToInt(vs[0]) - if !ok { - return vm.NIL, fmt.Errorf("unchecked-add expected integer, got %s", vs[0].Type().Name()) - } - b, ok := vm.ToInt(vs[1]) - if !ok { - return vm.NIL, fmt.Errorf("unchecked-add expected integer, got %s", vs[1].Type().Name()) - } - return vm.MakeInt(int(int64(a) + int64(b))), nil - }) - if err != nil { - panic(err) - } - - uncheckedSubtract, err := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 2 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - a, ok := vm.ToInt(vs[0]) - if !ok { - return vm.NIL, fmt.Errorf("unchecked-subtract expected integer, got %s", vs[0].Type().Name()) - } - b, ok := vm.ToInt(vs[1]) - if !ok { - return vm.NIL, fmt.Errorf("unchecked-subtract expected integer, got %s", vs[1].Type().Name()) - } - return vm.MakeInt(int(int64(a) - int64(b))), nil - }) - if err != nil { - panic(err) - } - - uncheckedMultiply, err := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 2 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - a, ok := vm.ToInt(vs[0]) - if !ok { - return vm.NIL, fmt.Errorf("unchecked-multiply expected integer, got %s", vs[0].Type().Name()) - } - b, ok := vm.ToInt(vs[1]) - if !ok { - return vm.NIL, fmt.Errorf("unchecked-multiply expected integer, got %s", vs[1].Type().Name()) - } - return vm.MakeInt(int(int64(a) * int64(b))), nil - }) - if err != nil { - panic(err) - } - - uncheckedNegate, err := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - a, ok := vm.ToInt(vs[0]) - if !ok { - return vm.NIL, fmt.Errorf("unchecked-negate expected integer, got %s", vs[0].Type().Name()) - } - // Note: -Long/MIN_VALUE wraps to Long/MIN_VALUE in 2's-complement int64. - // This matches Clojure's unchecked-negate behavior. - return vm.MakeInt(int(-int64(a))), nil - }) - if err != nil { - panic(err) - } - - uncheckedDivideInt, err := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 2 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - a, ok := vm.ToInt(vs[0]) - if !ok { - return vm.NIL, fmt.Errorf("unchecked-divide-int expected integer, got %s", vs[0].Type().Name()) - } - b, ok := vm.ToInt(vs[1]) - if !ok { - return vm.NIL, fmt.Errorf("unchecked-divide-int expected integer, got %s", vs[1].Type().Name()) - } - if b == 0 { - return vm.NIL, fmt.Errorf("divide by zero") - } - // Note: Long/MIN_VALUE / -1 overflows in 2's-complement and throws. - // This matches Clojure's unchecked-divide-int (and JVM IDIV) behavior. - if int64(a) == math.MinInt64 && int64(b) == -1 { - return vm.NIL, fmt.Errorf("integer overflow") - } - return vm.MakeInt(int(int64(a) / int64(b))), nil - }) - if err != nil { - panic(err) - } - - uncheckedLong, err := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - switch v := vs[0].(type) { - case vm.Int: - return v, nil - case *vm.BigInt: - // Low-64 of two's-complement representation, matching Clojure JVM. - // big.Int doesn't expose two's-complement directly; mask with 2^64, - // then reinterpret the low-64 bits as signed int64. - mask := new(big.Int).Lsh(big.NewInt(1), 64) - lo := new(big.Int).Mod(v.Val(), mask) - return vm.MakeInt(int(int64(lo.Uint64()))), nil - case vm.Float: - return vm.MakeInt(int(int64(float64(v)))), nil - default: - return vm.NIL, fmt.Errorf("unchecked-long expected integer or float, got %s", vs[0].Type().Name()) - } - }) - if err != nil { - panic(err) - } - - uncheckedInt, err := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - switch v := vs[0].(type) { - case vm.Int: - return vm.MakeInt(int(int32(int64(v)))), nil - case *vm.BigInt: - // Low-32 of two's-complement representation, matching Clojure JVM. - // Mask with 2^64, take low-32 bits as int32, then sign-extend. - mask := new(big.Int).Lsh(big.NewInt(1), 64) - lo := new(big.Int).Mod(v.Val(), mask) - return vm.MakeInt(int(int32(lo.Uint64()))), nil - case vm.Float: - return vm.MakeInt(int(int32(float64(v)))), nil - default: - return vm.NIL, fmt.Errorf("unchecked-int expected integer or float, got %s", vs[0].Type().Name()) - } - }) - if err != nil { - panic(err) - } - - uncheckedShort, err := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - switch v := vs[0].(type) { - case vm.Int: - return vm.MakeInt(int(int16(int64(v)))), nil - case *vm.BigInt: - // Low-16 of two's-complement representation, matching Clojure JVM. - mask := new(big.Int).Lsh(big.NewInt(1), 64) - lo := new(big.Int).Mod(v.Val(), mask) - return vm.MakeInt(int(int16(lo.Uint64()))), nil - case vm.Float: - return vm.MakeInt(int(int16(float64(v)))), nil - default: - return vm.NIL, fmt.Errorf("unchecked-short expected integer or float, got %s", vs[0].Type().Name()) - } - }) - if err != nil { - panic(err) - } - - uncheckedByte, err := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - switch v := vs[0].(type) { - case vm.Int: - return vm.MakeInt(int(int8(int64(v)))), nil - case *vm.BigInt: - // Low-8 of two's-complement representation, matching Clojure JVM. - mask := new(big.Int).Lsh(big.NewInt(1), 64) - lo := new(big.Int).Mod(v.Val(), mask) - return vm.MakeInt(int(int8(lo.Uint64()))), nil - case vm.Float: - return vm.MakeInt(int(int8(float64(v)))), nil - default: - return vm.NIL, fmt.Errorf("unchecked-byte expected integer or float, got %s", vs[0].Type().Name()) - } - }) - if err != nil { - panic(err) - } - - uncheckedChar, err := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - switch v := vs[0].(type) { - case vm.Int: - return vm.Char(rune(uint16(int64(v)))), nil - case *vm.BigInt: - // Low-16 of two's-complement representation, then uint16 → Char (rune). - mask := new(big.Int).Lsh(big.NewInt(1), 64) - lo := new(big.Int).Mod(v.Val(), mask) - return vm.Char(rune(uint16(lo.Uint64()))), nil - case vm.Float: - return vm.Char(rune(uint16(int64(float64(v))))), nil - default: - return vm.NIL, fmt.Errorf("unchecked-char expected integer or float, got %s", vs[0].Type().Name()) - } - }) - if err != nil { - panic(err) - } - - uncheckedDouble, err := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - switch v := vs[0].(type) { - case vm.Int: - return vm.Float(float64(int64(v))), nil - case *vm.BigInt: - // Convert BigInt to float64 via big.Float (handles overflow → ±Inf). - f, _ := new(big.Float).SetInt(v.Val()).Float64() - return vm.Float(f), nil - case vm.Float: - return v, nil - default: - return vm.NIL, fmt.Errorf("unchecked-double expected numeric, got %s", vs[0].Type().Name()) - } - }) - if err != nil { - panic(err) - } - - uncheckedFloat, err := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - switch v := vs[0].(type) { - case vm.Int: - // Cast through float32 to introduce float32-precision loss + overflow → ±Inf. - return vm.Float(float64(float32(int64(v)))), nil - case *vm.BigInt: - f, _ := new(big.Float).SetInt(v.Val()).Float64() - return vm.Float(float64(float32(f))), nil - case vm.Float: - return vm.Float(float64(float32(float64(v)))), nil - default: - return vm.NIL, fmt.Errorf("unchecked-float expected numeric, got %s", vs[0].Type().Name()) - } - }) - if err != nil { - panic(err) - } - equals, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { length := len(vs) if length < 1 { @@ -2383,128 +2031,15 @@ func installLangNS() { return vm.TRUE, nil }) - mod, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 2 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - return vm.NumMod(vs[0], vs[1]) - }) - - abs, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - return vm.NumAbs(vs[0]) - }) - // and/or are now short-circuiting macros defined in core.lg // Body delegates to pkg/rt/builtins (the single source shared with the AOT // direct-call target registered in registerBuiltinsModule); the wrapper only // enforces interpreter arity. - not, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - return builtins.Not(vs[0]) - }) - - complement, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - f, ok := vm.AsFn(vs[0]) - if !ok { - return vm.NIL, fmt.Errorf("complement expected Fn") - } - // The returned fn resolves f in ITS caller's context at call time, so - // (complement f) used inside an eager HOF still sees live bindings. - wrapped := vm.NewCtxNativeFn("complemented-fn", func(cec *vm.ExecContext, args []vm.Value) (vm.Value, error) { - v, err := cec.Invoke(f, args) - if err != nil { - return vm.NIL, err - } - return vm.Boolean(!vm.IsTruthy(v)), nil - }) - return wrapped, nil - }) - - setMacro, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - m := vs[0].(*vm.Var) - m.SetMacro() - return m, nil - }) - - gensym, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - prefix := "G__" - if len(vs) == 1 { - arg, ok := vs[0].(vm.String) - if !ok { - return vm.NIL, fmt.Errorf("gensym expected String") - } - prefix = string(arg) - } - return vm.Symbol(fmt.Sprintf("%s%d", prefix, nextID())), nil - }) - vector, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - return builtins.Vector(vs...) - }) list, _ := vm.NativeFnType.WrapNoErr(vm.NewList) - hashMap, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs)%2 != 0 { - return vm.NIL, fmt.Errorf("hash-map requires an even number of arguments, got %d", len(vs)) - } - return vm.NewMap(vs), nil - }) - arrayMap, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs)%2 != 0 { - return vm.NIL, fmt.Errorf("array-map requires an even number of arguments, got %d", len(vs)) - } - return vm.NewArrayMap(vs), nil - }) hashSet, _ := vm.NativeFnType.WrapNoErr(vm.NewSet) - sortedMap, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs)%2 != 0 { - return vm.NIL, fmt.Errorf("sorted-map requires even number of arguments, got %d", len(vs)) - } - return vm.NewSortedMap(nil, vs), nil - }) - - sortedSet, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - return vm.NewSortedSet(nil, vs), nil - }) - - sortedMapBy, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) < 1 { - return vm.NIL, fmt.Errorf("sorted-map-by requires a comparator") - } - comp, ok := vm.AsFn(vs[0]) - if !ok { - return vm.NIL, fmt.Errorf("sorted-map-by first arg must be a function") - } - kvs := vs[1:] - if len(kvs)%2 != 0 { - return vm.NIL, fmt.Errorf("sorted-map-by requires even number of key-value arguments") - } - return vm.NewSortedMap(fnComparator(comp), kvs), nil - }) - - sortedSetBy, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) < 1 { - return vm.NIL, fmt.Errorf("sorted-set-by requires a comparator") - } - comp, ok := vm.AsFn(vs[0]) - if !ok { - return vm.NIL, fmt.Errorf("sorted-set-by first arg must be a function") - } - return vm.NewSortedSet(fnComparator(comp), vs[1:]), nil - }) - vec, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { if len(vs) != 1 { return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) @@ -2546,311 +2081,6 @@ func installLangNS() { // chunk-first / chunk-rest / chunk-next dispatch on IChunkedSeq (via // AsChunkedSeq, so they resolve through LazySeq wrappers). chunk-cons // builds a ChunkedCons; chunk-buffer / chunk-append / chunk are the - // mutable builder API. chunked-seq? answers the type predicate. - asChunked := func(v vm.Value, op string) (vm.IChunkedSeq, error) { - s, err := seqOf(v) - if err != nil { - return nil, fmt.Errorf("%s: not a sequence", op) - } - cs, ok := vm.AsChunkedSeq(s) - if !ok { - return nil, fmt.Errorf("%s: not a chunked seq", op) - } - return cs, nil - } - - chunkFirst, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("chunk-first: wrong number of arguments %d", len(vs)) - } - cs, err := asChunked(vs[0], "chunk-first") - if err != nil { - return vm.NIL, err - } - return cs.ChunkedFirst().(vm.Value), nil - }) - - chunkRest, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("chunk-rest: wrong number of arguments %d", len(vs)) - } - cs, err := asChunked(vs[0], "chunk-rest") - if err != nil { - return vm.NIL, err - } - m := cs.ChunkedMore() - if m == nil { - return vm.EmptyList, nil - } - return m.(vm.Value), nil - }) - - chunkNext, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("chunk-next: wrong number of arguments %d", len(vs)) - } - cs, err := asChunked(vs[0], "chunk-next") - if err != nil { - return vm.NIL, err - } - n := cs.ChunkedNext() - if n == nil { - return vm.NIL, nil - } - return n.(vm.Value), nil - }) - - chunkConsF, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 2 { - return vm.NIL, fmt.Errorf("chunk-cons: wrong number of arguments %d", len(vs)) - } - chunk, ok := vs[0].(vm.IChunk) - if !ok { - return vm.NIL, fmt.Errorf("chunk-cons: first arg must be a chunk") - } - var tail vm.Seq - if vs[1] != vm.NIL { - s, err := seqOf(vs[1]) - if err != nil { - return vm.NIL, fmt.Errorf("chunk-cons: second arg must be a seq or nil") - } - tail = s - } - out := vm.ConsChunk(chunk, tail) - if out == nil { - return vm.EmptyList, nil - } - return out.(vm.Value), nil - }) - - chunkedSeqP, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("chunked-seq?: wrong number of arguments %d", len(vs)) - } - if vs[0] == vm.NIL { - return vm.FALSE, nil - } - s, err := seqOf(vs[0]) - if err != nil || s == nil { - return vm.FALSE, nil - } - _, ok := vm.AsChunkedSeq(s) - return vm.Boolean(ok), nil - }) - - chunkBufferF, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("chunk-buffer: wrong number of arguments %d", len(vs)) - } - n, ok := vs[0].(vm.Int) - if !ok { - return vm.NIL, fmt.Errorf("chunk-buffer: arg must be Int") - } - return vm.NewChunkBuffer(int(n)), nil - }) - - chunkAppendF, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 2 { - return vm.NIL, fmt.Errorf("chunk-append: wrong number of arguments %d", len(vs)) - } - b, ok := vs[0].(*vm.ChunkBuffer) - if !ok { - return vm.NIL, fmt.Errorf("chunk-append: first arg must be a chunk-buffer") - } - b.Append(vs[1]) - return b, nil - }) - - chunkF, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("chunk: wrong number of arguments %d", len(vs)) - } - b, ok := vs[0].(*vm.ChunkBuffer) - if !ok { - return vm.NIL, fmt.Errorf("chunk: arg must be a chunk-buffer") - } - return b.Chunk().(vm.Value), nil - }) - - rangef, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) == 0 { - // Infinite range: (range) -> lazy seq 0, 1, 2, ... - return vm.NewInfiniteRange(0, 1), nil - } - if len(vs) > 3 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - var start, end, step vm.Int - step = 1 - var err error - var endArg vm.Value - switch len(vs) { - case 1: - endArg = vs[0] - case 2: - endArg = vs[1] - if start, err = rangeInt(vs[0], "start"); err != nil { - return vm.NIL, err - } - case 3: - endArg = vs[1] - if start, err = rangeInt(vs[0], "start"); err != nil { - return vm.NIL, err - } - if step, err = rangeInt(vs[2], "step"); err != nil { - return vm.NIL, err - } - } - // A float end still yields integers, like the JVM: infinite - // for ##Inf toward the step, else every int short of the end - // ((range 2 5.29) => 2 3 4 5). - if f, ok := endArg.(vm.Float); ok { - if math.IsInf(float64(f), 0) { - if (f > 0 && step > 0) || (f < 0 && step < 0) { - return vm.NewInfiniteRange(int(start), int(step)), nil - } - return vm.NewRange(0, 0, 1), nil - } - if step > 0 { - endArg = vm.Int(math.Ceil(float64(f))) - } else { - endArg = vm.Int(math.Floor(float64(f))) - } - } - if end, err = rangeInt(endArg, "end"); err != nil { - return vm.NIL, err - } - return vm.NewRange(start, end, step), nil - }) - - keyword, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) < 1 || len(vs) > 2 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - if len(vs) == 2 { - // (keyword ns name) — both must be strings (or nil ns) - var nsStr, nameStr string - if vs[0] != vm.NIL { - switch n := vs[0].(type) { - case vm.String: - nsStr = string(n) - default: - return vm.NIL, fmt.Errorf("keyword namespace must be a string, got %s", vs[0].Type()) - } - } - switch n := vs[1].(type) { - case vm.String: - nameStr = string(n) - default: - return vm.NIL, fmt.Errorf("keyword name must be a string, got %s", vs[1].Type()) - } - if nsStr == "" && vs[0] == vm.NIL { - return vm.Keyword(nameStr), nil - } - return vm.Keyword(nsStr + "/" + nameStr), nil - } - if vs[0] == vm.NIL { - return vm.NIL, nil - } - if k, ok := vs[0].(vm.Keyword); ok { - return k, nil - } - if k, ok := vs[0].(vm.Symbol); ok { - return vm.Keyword(k), nil - } - if k, ok := vs[0].(vm.String); ok { - return vm.Keyword(k), nil - } - return vm.NIL, fmt.Errorf("keyword expects keyword, symbol, or string, got %s", vs[0].Type()) - }) - - // symbol(name) or symbol(ns, name) - symbolf, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) < 1 || len(vs) > 2 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - toStr := func(v vm.Value) (string, bool) { - switch s := v.(type) { - case vm.String: - return string(s), true - case vm.Symbol: - return string(s), true - case vm.Keyword: - return string(s), true - default: - return "", false - } - } - if len(vs) == 1 { - if vs[0] == vm.NIL { - return vm.NIL, fmt.Errorf("symbol expected String, Symbol, Keyword, or Var") - } - if v, ok := vs[0].(*vm.Var); ok { - return vm.Symbol(externalNSName(v.NS()) + "/" + v.VarName()), nil - } - if s, ok := toStr(vs[0]); ok { - return vm.Symbol(s), nil - } - return vm.NIL, fmt.Errorf("symbol expected String or Symbol") - } - nsStr := "" - if vs[0] != vm.NIL { - ns, ok := vs[0].(vm.String) - if !ok { - return vm.NIL, fmt.Errorf("symbol expected String namespace") - } - nsStr = string(ns) - } - name, ok := vs[1].(vm.String) - if !ok { - return vm.NIL, fmt.Errorf("symbol expected String name") - } - nameStr := string(name) - if nsStr == "" && vs[0] == vm.NIL { - return vm.Symbol(nameStr), nil - } - return vm.Symbol(nsStr + "/" + nameStr), nil - }) - - assoc, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) < 3 || len(vs)%2 == 0 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - coll, ok := vs[0].(vm.Associative) - if !ok { - return vm.NIL, fmt.Errorf("assoc expected Associative") - } - ret := coll - for i := 1; i < len(vs); i += 2 { - ret = ret.Assoc(vs[i], vs[i+1]) - if ret == vm.NIL { - return vm.NIL, fmt.Errorf("assoc failed for key %s", vs[i].String()) - } - } - return ret, nil - }) - - dissoc, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) == 0 { - return vm.NIL, fmt.Errorf("wrong number of arguments 0") - } - if len(vs) == 1 { - return vs[0], nil - } - coll, ok := vs[0].(vm.Associative) - if !ok { - return vm.NIL, fmt.Errorf("dissoc expected Associative") - } - ret := coll - for i := 1; i < len(vs); i++ { - ret = ret.Dissoc(vs[i]) - if vs[0] != vm.NIL && ret == vm.NIL { - return vm.NIL, fmt.Errorf("dissoc failed for key %s", vs[i].String()) - } - } - return ret, nil - }) - update := vm.NewCtxNativeFn("update", func(ec *vm.ExecContext, vs []vm.Value) (vm.Value, error) { if len(vs) < 3 { return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) @@ -2883,13 +2113,6 @@ func installLangNS() { return colla.Assoc(key, v), nil }) - cons, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 2 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - return builtins.Cons(vs[0], vs[1]) - }) - conj, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { if len(vs) == 0 { return vm.ArrayVector{}, nil @@ -2929,46 +2152,6 @@ func installLangNS() { return seq, nil }) - disj, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) < 1 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - if vs[0] == vm.NIL { - return vm.NIL, nil - } - if len(vs) == 1 { - return vs[0], nil - } - switch s := vs[0].(type) { - case *vm.PersistentSet: - result := s - for _, v := range vs[1:] { - result = result.Disj(v) - } - return result, nil - case *vm.SortedSet: - result := s - for _, v := range vs[1:] { - result = result.Disj(v) - } - return result, nil - case vm.Set: - for _, v := range vs[1:] { - s = s.Disj(v) - } - return s, nil - default: - return vm.NIL, fmt.Errorf("disj expected Set") - } - }) - - contains, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 2 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - return builtins.Contains(vs[0], vs[1]) - }) - first, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { if len(vs) != 1 { return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) @@ -2996,42 +2179,14 @@ func installLangNS() { return vm.NIL, fmt.Errorf("first expected Seq") }) - second, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { + next, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { if len(vs) != 1 { return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) } if vs[0] == vm.NIL { return vm.NIL, nil } - // ArrayVector fast path: index the flat slice directly, no seq alloc. - if av, ok := vs[0].(vm.ArrayVector); ok { - if len(av) < 2 { - return vm.NIL, nil - } - return av[1], nil - } - seq, err := seqOf(vs[0]) - if err != nil { - return vm.NIL, fmt.Errorf("second expected Seq") - } - if seq == nil { - return vm.NIL, nil - } - n := seq.Next() - if n == nil { - return vm.NIL, nil - } - return n.First(), nil - }) - - next, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - if vs[0] == vm.NIL { - return vm.NIL, nil - } - // ArrayVector fast path: step in with one alloc instead of Seq()+Next(). + // ArrayVector fast path: step in with one alloc instead of Seq()+Next(). if av, ok := vs[0].(vm.ArrayVector); ok { n := av.SeqFrom(1) if n == nil { @@ -3127,14 +2282,6 @@ func installLangNS() { return vm.Boolean(ok), nil }) - isList, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - _, ok := vs[0].(*vm.List) - return vm.Boolean(ok), nil - }) - isColl, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { if len(vs) != 1 { return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) @@ -3147,26 +2294,6 @@ func installLangNS() { return vm.Boolean(ok), nil }) - empty, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - if vs[0] == vm.NIL || vs[0].Type() == vm.StringType { - return vm.NIL, nil - } - if _, ok := vs[0].(*vm.InfiniteRange); ok { - return vm.EmptyList, nil - } - if _, ok := vs[0].(*vm.Record); ok { - return vm.NIL, fmt.Errorf("empty is not supported on records") - } - coll, ok := vs[0].(vm.Collection) - if !ok { - return vm.NIL, nil - } - return coll.Empty(), nil - }) - get, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { vl := len(vs) if vl < 2 || vl > 3 { @@ -3187,26 +2314,6 @@ func installLangNS() { return as.ValueAtOr(key, vs[2]), nil }) - keyf, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - if e, ok := vs[0].(vm.MapEntry); ok { - return e.Key, nil - } - return vm.NIL, fmt.Errorf("key expects map entry") - }) - - valf, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - if e, ok := vs[0].(vm.MapEntry); ok { - return e.Value, nil - } - return vm.NIL, fmt.Errorf("val expects map entry") - }) - // nth: indexed access that works on any sequential type. // Fast path for vectors (O(1)), linear walk for seqs (O(n)). nthf, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { @@ -3264,23 +2371,6 @@ func installLangNS() { return notFound, nil }) - count, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - if vs[0] == vm.NIL { - return vm.MakeInt(0), nil - } - if s, ok := vs[0].(vm.String); ok { - return vm.MakeInt(len([]rune(string(s)))), nil - } - seq, ok := vs[0].(vm.Counted) - if !ok { - return vm.NIL, fmt.Errorf("count expected Counted") - } - return seq.Count(), nil - }) - // map builtin: always lazy. Clojure semantics require laziness on all // inputs — small counted collections must still defer realization so // consumers (rose trees, short-circuit take, side-effecting f) work. @@ -3612,138 +2702,17 @@ func installLangNS() { return nns, nil }) - excludeInCurrentNs, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - cns := CurrentNS.Deref().(*vm.Namespace) - for _, v := range vs { - sym, ok := v.(vm.Symbol) - if !ok { - return vm.NIL, fmt.Errorf("exclude-in-current-ns expected Symbol, got %s", v.Type().Name()) - } - cns.Exclude(string(sym)) - } - return vm.NIL, nil - }) - - use, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) < 1 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - cns := CurrentNS.Deref().(*vm.Namespace) - for i := range vs { - s, ok := vs[i].(vm.Symbol) - if !ok { - return vm.NIL, fmt.Errorf("use expected Symbol") - } - cns.Refer(NS(string(s)), "", true) - } - return vm.NIL, nil - }) - - aliasf, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 2 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - al, ok := vs[0].(vm.Symbol) - if !ok { - return vm.NIL, fmt.Errorf("alias expected Symbol") - } - nsSym, ok := vs[1].(vm.Symbol) - if !ok { - return vm.NIL, fmt.Errorf("alias expected Symbol") - } - cns := CurrentNS.Deref().(*vm.Namespace) - target := NS(string(nsSym)) - cns.Alias(al, target) - return vm.NIL, nil - }) - - referList, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 2 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - nsSym, ok := vs[0].(vm.Symbol) - if !ok { - return vm.NIL, fmt.Errorf("refer-list expected ns Symbol") - } - arr, ok := vs[1].(vm.ArrayVector) - if !ok { - return vm.NIL, fmt.Errorf("refer-list expected vector of Symbols") - } - syms := make([]vm.Symbol, 0, len(arr)) - for i := range arr { - if s, ok := arr[i].(vm.Symbol); ok { - syms = append(syms, s) - } - } - cns := CurrentNS.Deref().(*vm.Namespace) - target := NS(string(nsSym)) - // Convert []vm.Symbol to []vm.Symbol type alias in vm - vmSyms := make([]vm.Symbol, len(syms)) - copy(vmSyms, syms) - cns.ReferList(target, vmSyms) - return vm.NIL, nil - }) - // removed resolve-var helper (prefer compile-time resolution) now, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return vm.NewBoxed(time.Now()), nil }) - methodInvoke, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) < 2 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - name, ok := vs[1].(vm.Symbol) - if !ok { - return vm.NIL, fmt.Errorf("method-invoke expected Symbol") - } - rec, ok := vs[0].(vm.Receiver) - if !ok { - return invokeMethodFallback(vs[0], name, vs[2:], fmt.Errorf("method-invoke expected Receiver")) - } - result, err := rec.InvokeMethod(name, vs[2:]) - if err == nil { - return result, nil - } - return invokeMethodFallback(rec, name, vs[2:], err) - }) - // (register-host-method! Type 'name (fn [rec & args] ...)) — register a // handler for `.name` dot-forms on values of Type (the host-method seam). - registerHostMethod, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 3 { - return vm.NIL, fmt.Errorf("register-host-method! expected 3 arguments, got %d", len(vs)) - } - t, ok := vs[0].(vm.ValueType) - if !ok { - return vm.NIL, fmt.Errorf("register-host-method! expected a type, got %s", vs[0].Type().Name()) - } - name, ok := vs[1].(vm.Symbol) - if !ok { - return vm.NIL, fmt.Errorf("register-host-method! expected a Symbol method name") - } - fn, ok := vs[2].(vm.Fn) - if !ok { - return vm.NIL, fmt.Errorf("register-host-method! expected a fn") - } - RegisterHostMethod(t, name, fn) - return vm.NIL, nil - }) // (register-host-class! "java.util.Map" value) — make a bare class symbol // resolve to value (typically a let-go type) when used as a value. - registerHostClass, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 2 { - return vm.NIL, fmt.Errorf("register-host-class! expected 2 arguments, got %d", len(vs)) - } - name, ok := vs[0].(vm.String) - if !ok { - return vm.NIL, fmt.Errorf("register-host-class! expected a String class name") - } - RegisterHostClass(string(name), vs[1]) - return vm.NIL, nil - }) deref, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { switch len(vs) { @@ -3770,73 +2739,7 @@ func installLangNS() { } }) - concat, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - // Pre-size for the ArrayVector args (flat slices with known length) - // so their direct appends below don't regrow ret. - presize := 0 - for i := range vs { - if av, ok := vs[i].(vm.ArrayVector); ok { - presize += len(av) - } - } - ret := make([]vm.Value, 0, presize) - for i := range vs { - if vs[i] == vm.NIL { - continue - } - // ArrayVector fast path: bulk-append the flat slice — no seq, - // no chunk, no per-element successor allocation. - if av, ok := vs[i].(vm.ArrayVector); ok { - ret = append(ret, av...) - continue - } - vseq, err := seqOf(vs[i]) - if err != nil { - return vm.NIL, fmt.Errorf("concat expected Seq") - } - ret = appendSeqValues(ret, forceSeq(vseq)) - } - r, err := vm.ListType.Box(ret) - if err != nil { - return vm.NIL, fmt.Errorf("concat failed: %w", err) - } - return r, nil - }) - // slurp (reintroduced) - slurp, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - filename, ok := vs[0].(vm.String) - if !ok { - return vm.NIL, fmt.Errorf("slurp expected String") - } - data, err := os.ReadFile(string(filename)) - if err != nil { - return vm.NIL, fmt.Errorf("slurp failed: %w", err) - } - return vm.String(data), nil - }) - - spit, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 2 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - filename, ok := vs[0].(vm.String) - if !ok { - return vm.NIL, fmt.Errorf("spit expected String") - } - contents, ok := asBytes(vs[1]) - if !ok { - return vm.NIL, fmt.Errorf("spit expected String or byte-array") - } - err := os.WriteFile(string(filename), contents, 0644) - if err != nil { - return vm.NIL, fmt.Errorf("spit failed: %w", err) - } - return vm.NIL, nil - }) name, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { if len(vs) != 1 { @@ -3867,37 +2770,6 @@ func installLangNS() { return named.Namespace(), nil }) - atom, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) < 1 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - if (len(vs)-1)%2 != 0 { - return vm.NIL, fmt.Errorf("atom options must be key/value pairs") - } - var meta vm.Value - var validator vm.Fn - for i := 1; i < len(vs); i += 2 { - switch vs[i] { - case vm.Keyword("meta"): - if vs[i+1] != vm.NIL && !isMapType(vs[i+1]) { - return vm.NIL, fmt.Errorf("atom :meta must be nil or map") - } - meta = vs[i+1] - case vm.Keyword("validator"): - if vs[i+1] == vm.NIL { - validator = nil - continue - } - fn, ok := vm.AsFn(vs[i+1]) - if !ok { - return vm.NIL, fmt.Errorf("atom :validator must be nil or function") - } - validator = fn - } - } - return vm.NewAtomWithMetaValidator(vs[0], meta, validator) - }) - // (swap! a fn) swap := vm.NewCtxNativeFn("swap!", func(ec *vm.ExecContext, vs []vm.Value) (vm.Value, error) { if len(vs) < 2 { @@ -3915,35 +2787,8 @@ func installLangNS() { }) // (reset! a fn) - reset, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 2 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - at, ok := vs[0].(*vm.Atom) - if !ok { - return vm.NIL, fmt.Errorf("reset expected Atom") - } - return at.Reset(vs[1]) - }) // (compare-and-set! a old new): set to new iff current is identical to old. - compareAndSet, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 3 { - return vm.NIL, fmt.Errorf("compare-and-set! expected 3 arguments, got %d", len(vs)) - } - at, ok := vs[0].(*vm.Atom) - if !ok { - return vm.NIL, fmt.Errorf("compare-and-set! expected Atom") - } - swapped, err := at.CompareAndSet(vs[1], vs[2]) - if err != nil { - return vm.NIL, err - } - if swapped { - return vm.TRUE, nil - } - return vm.FALSE, nil - }) // swap-vals!: like swap! but returns [old new] swapVals := vm.NewCtxNativeFn("swap-vals!", func(ec *vm.ExecContext, vs []vm.Value) (vm.Value, error) { @@ -3967,20 +2812,6 @@ func installLangNS() { }) // reset-vals!: like reset! but returns [old new] - resetVals, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 2 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - at, ok := vs[0].(*vm.Atom) - if !ok { - return vm.NIL, fmt.Errorf("reset-vals! expected Atom") - } - old := at.Deref() - if _, err := at.Reset(vs[1]); err != nil { - return vm.NIL, err - } - return vm.ArrayVector{old, vs[1]}, nil - }) gof := vm.NewCtxNativeFn("go*", func(ec *vm.ExecContext, vs []vm.Value) (vm.Value, error) { if len(vs) != 1 { @@ -4017,13 +2848,6 @@ func installLangNS() { return ret, nil }) - chanf, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 0 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - return make(vm.Chan), nil - }) - scopeOpen := vm.NewCtxNativeFn("scope-open", func(ec *vm.ExecContext, vs []vm.Value) (vm.Value, error) { if len(vs) != 0 { return vm.NIL, fmt.Errorf("scope-open expects 0 arguments") @@ -4033,43 +2857,6 @@ func installLangNS() { return vm.OpenChildEC(ec), nil }) - scopeClose, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 2 { - return vm.NIL, fmt.Errorf("scope-close! expects 2 arguments (scope timeout-ms)") - } - s, ok := vs[0].(*vm.Scope) - if !ok { - return vm.NIL, fmt.Errorf("scope-close! expected a scope") - } - ms, ok := vs[1].(vm.Int) - if !ok { - return vm.NIL, fmt.Errorf("scope-close! expected an integer timeout-ms") - } - vm.CloseScoped(s, time.Duration(int64(ms))*time.Millisecond) - return vm.NIL, nil - }) - - scopeLive, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("scope-live expects 1 argument") - } - s, ok := vs[0].(*vm.Scope) - if !ok { - return vm.NIL, fmt.Errorf("scope-live expected a scope") - } - return vm.Int(s.LiveTree()), nil - }) - - scopeQmark, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("scope? expects 1 argument") - } - if _, ok := vs[0].(*vm.Scope); ok { - return vm.TRUE, nil - } - return vm.FALSE, nil - }) - chanput := vm.NewCtxNativeFn(">!", func(ec *vm.ExecContext, vs []vm.Value) (vm.Value, error) { if len(vs) != 2 { return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) @@ -4158,69 +2945,23 @@ func installLangNS() { return vm.MakeInt(i), nil }) - max, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) < 1 { + // compareValues delegates to the vm package's DefaultCompare + compareValues := vm.DefaultCompare + + // comparef is defined later (~line 4585); the earlier definition + // that lived here was unused — the later one shadowed it. + + sort := vm.NewCtxNativeFn("sort", func(ec *vm.ExecContext, vs []vm.Value) (vm.Value, error) { + if len(vs) < 1 || len(vs) > 2 { return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) } - m := vs[0] - if isNaNValue(m) { - return m, nil - } - for i := 1; i < len(vs); i++ { - if isNaNValue(vs[i]) { - return vs[i], nil - } - gt, err := vm.NumGt(vs[i], m) - if err != nil { - return vm.NIL, err - } - if gt { - m = vs[i] - } - } - return m, nil - }) - - min, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) < 1 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - m := vs[0] - if isNaNValue(m) { - return m, nil - } - for i := 1; i < len(vs); i++ { - if isNaNValue(vs[i]) { - return vs[i], nil - } - lt, err := vm.NumLt(vs[i], m) - if err != nil { - return vm.NIL, err - } - if lt { - m = vs[i] - } - } - return m, nil - }) - - // compareValues delegates to the vm package's DefaultCompare - compareValues := vm.DefaultCompare - - // comparef is defined later (~line 4585); the earlier definition - // that lived here was unused — the later one shadowed it. - - sort := vm.NewCtxNativeFn("sort", func(ec *vm.ExecContext, vs []vm.Value) (vm.Value, error) { - if len(vs) < 1 || len(vs) > 2 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - var comp vm.Comparator - var coll vm.Collection - var ok bool - if len(vs) == 2 { - compFn, ok := vm.AsFn(vs[0]) - if !ok { - return vm.NIL, fmt.Errorf("sort expected a comparator function") + var comp vm.Comparator + var coll vm.Collection + var ok bool + if len(vs) == 2 { + compFn, ok := vm.AsFn(vs[0]) + if !ok { + return vm.NIL, fmt.Errorf("sort expected a comparator function") } comp = fnComparator(ec.Bind(compFn)) coll, ok = vs[1].(vm.Collection) @@ -4301,47 +3042,6 @@ func installLangNS() { return ret, nil }) - strReplace, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 3 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - s, ok := vs[0].(vm.String) - if !ok { - return vm.NIL, fmt.Errorf("str-replace expected String") - } - // Function replacement (clojure.string/replace semantics). - if fn, isFn := vs[2].(vm.Fn); isFn { - switch m := vs[1].(type) { - case *vm.Regex: - out, err := m.ReplaceAllFunc(string(s), strReplaceCallback(fn)) - if err != nil { - return vm.NIL, err - } - return vm.String(out), nil - case vm.String: - return literalReplaceFn(string(m), string(s), fn, false) - default: - return vm.NIL, fmt.Errorf("str-replace expected String or Regex") - } - } - r, ok := vs[2].(vm.String) - if !ok { - return vm.NIL, fmt.Errorf("str-replace expected String") - } - switch vs[1].(type) { - case vm.String: - return vm.String(strings.ReplaceAll(string(s), string(vs[1].(vm.String)), string(r))), nil - case *vm.Regex: - out, err := vs[1].(*vm.Regex).ReplaceAll(string(s), string(r)) - if err != nil { - return vm.NIL, err - } - return vm.String(out), nil - default: - return vm.NIL, fmt.Errorf("str-replace expected String or Regex") - } - }) - strReplaceFirst, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { if len(vs) != 3 { return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) @@ -4430,274 +3130,6 @@ func installLangNS() { } }) - longf, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - const minInt64 = float64(-9223372036854775808) - const maxInt64 = float64(9223372036854775807) - coerce := func(f float64) (vm.Value, error) { - if f < minInt64 || f > maxInt64 { - return vm.NIL, fmt.Errorf("%s can't be coerced to long", vs[0]) - } - return vm.Int(int64(math.Trunc(f))), nil - } - switch v := vs[0].(type) { - case vm.Int: - return v, nil - case vm.Float: - return coerce(float64(v)) - case vm.Char: - return vm.Int(int(v)), nil - case *vm.BigInt: - if !v.Val().IsInt64() { - return vm.NIL, fmt.Errorf("%s can't be coerced to long", vs[0]) - } - return vm.Int(v.Val().Int64()), nil - case *vm.BigDecimal: - f, _ := v.Val().Float64() - return coerce(f) - case *vm.Ratio: - f, _ := v.Val().Float64() - return coerce(f) - case vm.Boolean: - if bool(v) { - return vm.MakeInt(1), nil - } - return vm.MakeInt(0), nil - default: - return vm.NIL, fmt.Errorf("%s can't be coerced to long", vs[0]) - } - }) - - floatf, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - f, ok := vm.ToFloat(vs[0]) - if !ok { - return vm.NIL, fmt.Errorf("%s can't be coerced to float", vs[0]) - } - if math.IsInf(f, 0) { - return vm.NIL, fmt.Errorf("%s can't be coerced to float", vs[0]) - } - f32 := float32(f) - if math.IsInf(float64(f32), 0) { - return vm.NIL, fmt.Errorf("%s can't be coerced to float", vs[0]) - } - return vm.Float32(float64(f32)), nil - }) - - doublef, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - f, ok := vm.ToFloat(vs[0]) - if !ok { - return vm.NIL, fmt.Errorf("%s can't be coerced to double", vs[0]) - } - return vm.Float(f), nil - }) - - isNumber, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - return vm.Boolean(vm.IsNumber(vs[0])), nil - }) - - isFloat, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - switch vs[0].(type) { - case vm.Float, vm.Float32: - return vm.TRUE, nil - } - ok := false - return vm.Boolean(ok), nil - }) - - isInt, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - _, ok := vs[0].(vm.Int) - return vm.Boolean(ok), nil - }) - - char, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("wrong number of arguments") - } - switch v := vs[0].(type) { - case vm.Int: - if int(v) < 0 || int(v) > 0x10FFFF { - return vm.NIL, fmt.Errorf("value out of range for char: %d", v) - } - return vm.Char(rune(v)), nil - case vm.Char: - return v, nil - case vm.String: - runes := []rune(string(v)) - if len(runes) == 1 { - return vm.Char(runes[0]), nil - } - return vm.NIL, fmt.Errorf("%s can't be coerced to char", vs[0]) - case *vm.BigInt: - n := v.Unbox().(*big.Int).Int64() - if n < 0 || n > 0x10FFFF { - return vm.NIL, fmt.Errorf("value out of range for char: %d", n) - } - return vm.Char(rune(n)), nil - default: - return vm.NIL, fmt.Errorf("%s can't be coerced to char", vs[0]) - } - }) - - regex, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - // (re-pattern p) on an already-compiled regex returns it unchanged, - // matching Clojure where re-pattern accepts a Pattern, not only a String. - if r, ok := vs[0].(*vm.Regex); ok { - return r, nil - } - if s, ok := vs[0].(vm.String); ok { - return vm.NewRegex(string(s)) - } - return vm.NIL, fmt.Errorf("regex expected String") - }) - - peek, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - if vs[0] == vm.NIL { - return vm.NIL, nil - } - switch v := vs[0].(type) { - case vm.ArrayVector: - if len(v) == 0 { - return vm.NIL, nil - } - return v[len(v)-1], nil - case vm.PersistentVector: - if v.RawCount() == 0 { - return vm.NIL, nil - } - return v.ValueAt(vm.Int(v.RawCount() - 1)), nil - case *vm.List: - if v == vm.EmptyList { - return vm.NIL, nil - } - return v.First(), nil - case *vm.PersistentQueue: - return v.Peek(), nil - default: - return vm.NIL, fmt.Errorf("peek not supported on %s", vs[0].Type()) - } - }) - - pop, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - if vs[0] == vm.NIL { - return vm.NIL, nil - } - switch vs[0].(type) { - case vm.PersistentVector: - v := vs[0].(vm.PersistentVector) - if v.RawCount() < 1 { - return vm.NIL, fmt.Errorf("can't pop empty vector") - } - // O(1)-amortized structural pop (was O(n) Unbox()+rebuild). - return v.Pop(), nil - case vm.ArrayVector: - v := vs[0].(vm.ArrayVector) - if v.RawCount() < 1 { - return vm.NIL, fmt.Errorf("can't pop empty vector") - } - return vm.ArrayVector(v[0 : len(v)-1]), nil - case vm.Seq: - s := vs[0].(vm.Seq) - // pop drops the first element and returns the rest. Use More (not - // Next): More yields the empty list () for a one-element seq, - // whereas Next returns nil there — which would wrongly read as - // "empty" and error. Only an already-empty seq is illegal to pop. - if s == vm.EmptyList { - return vm.NIL, fmt.Errorf("can't pop empty seq") - } - if c, ok := vs[0].(vm.Counted); ok && c.RawCount() == 0 { - return vm.NIL, fmt.Errorf("can't pop empty seq") - } - return s.More(), nil - case *vm.PersistentQueue: - return vs[0].(*vm.PersistentQueue).Pop(), nil - default: - return vm.NIL, fmt.Errorf("pop expected Seq or Vec") - } - }) - - iterate, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 2 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - f, ok := vm.AsFn(vs[0]) - if !ok { - return vm.NIL, fmt.Errorf("iterate expected a function") - } - return vm.NewIterate(f, vs[1]), nil - }) - - repeat, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) < 1 || len(vs) > 2 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - if len(vs) == 1 { - return vm.NewRepeat(vs[0], -1), nil - } - if _, ok := vs[0].(vm.Boolean); ok { - return vm.NIL, fmt.Errorf("repeat expected an Int") - } - ni, ok := vm.ToInt(vs[0]) - if !ok { - return vm.NIL, fmt.Errorf("repeat expected an Int") - } - n := vm.Int(ni) - if int(n) <= 0 { - return vm.EmptyList, nil - } - return vm.NewRepeat(vs[1], int(n)), nil - }) - - refer, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) < 2 || len(vs) > 3 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - cns := CurrentNS.Deref().(*vm.Namespace) - s, ok := vs[0].(vm.Symbol) - if !ok { - return vm.NIL, fmt.Errorf("refer expected Symbol") - } - alias := "" - if len(vs) > 1 { - if str, ok := vs[1].(vm.String); ok { - alias = string(str) - } - } - all := true - if len(vs) > 2 { - if b, ok := vs[2].(vm.Boolean); ok { - all = bool(b) - } - } - cns.Refer(NS(string(s)), alias, all) - return vm.NIL, nil - }) - // String utility builtins (for string namespace) trimf, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { if len(vs) != 1 { @@ -4867,90 +3299,11 @@ func installLangNS() { }) // format: sprintf-style string formatting - formatf, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) < 1 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - fmtStr, ok := vs[0].(vm.String) - if !ok { - return vm.NIL, fmt.Errorf("format expected String") - } - fmts := string(fmtStr) - args := make([]any, len(vs)-1) - // Scan format string to determine which args need float promotion - vi := 0 - for fi := 0; fi < len(fmts) && vi < len(args); fi++ { - if fmts[fi] != '%' { - continue - } - fi++ // skip % - if fi >= len(fmts) { - break - } - if fmts[fi] == '%' { - continue // %% literal - } - // Skip flags, width, precision - for fi < len(fmts) && (fmts[fi] == '-' || fmts[fi] == '+' || fmts[fi] == ' ' || fmts[fi] == '0' || fmts[fi] == '#' || (fmts[fi] >= '0' && fmts[fi] <= '9') || fmts[fi] == '.') { - fi++ - } - if fi >= len(fmts) { - break - } - verb := fmts[fi] - switch v := vs[vi+1].(type) { - case vm.Int: - if verb == 'f' || verb == 'e' || verb == 'g' || verb == 'E' || verb == 'G' { - args[vi] = float64(v) - } else { - args[vi] = int(v) - } - case vm.Float: - args[vi] = float64(v) - case vm.String: - args[vi] = string(v) - case vm.Boolean: - args[vi] = bool(v) - default: - args[vi] = vs[vi+1].Unbox() - } - vi++ - } - return vm.String(fmt.Sprintf(string(fmtStr), args...)), nil - }) // rand: returns a random float between 0 (inclusive) and 1 (exclusive) // or between 0 and n - randf, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) == 0 { - return vm.Float(rngFloat64()), nil - } - if len(vs) == 1 { - if n, ok := vs[0].(vm.Int); ok { - return vm.Float(rngFloat64() * float64(n)), nil - } - if n, ok := vs[0].(vm.Float); ok { - return vm.Float(rngFloat64() * float64(n)), nil - } - return vm.NIL, fmt.Errorf("rand expected number") - } - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - }) // rand-int: returns a random integer between 0 (inclusive) and n (exclusive) - randInt, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - n, ok := vs[0].(vm.Int) - if !ok { - return vm.NIL, fmt.Errorf("rand-int expected Int") - } - if int(n) <= 0 { - return vm.MakeInt(0), nil - } - return vm.MakeInt(rngIntn(int(n))), nil - }) // random-uuid: generate a random UUID v4 randomUUID, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { @@ -4967,490 +3320,59 @@ func installLangNS() { }) // rand-nth: returns a random element from a collection - randNth, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - if vs[0] == vm.NIL { - return vm.NIL, nil - } - coll, ok := vs[0].(vm.Collection) - if !ok { - return vm.NIL, fmt.Errorf("rand-nth expected Collection") - } - n := coll.RawCount() - if n == 0 { - return vm.NIL, fmt.Errorf("rand-nth called on empty collection") - } - idx := rngIntn(n) - if l, ok := vs[0].(vm.Lookup); ok { - return l.ValueAt(vm.Int(idx)), nil - } - // Fallback: iterate - s, _ := seqOf(vs[0]) - for range idx { - s = s.Next() - } - return s.First(), nil - }) // shuffle: returns a random permutation of a collection as a vector - shuffle, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - if vs[0] == vm.NIL { - return vm.NIL, fmt.Errorf("shuffle not supported on nil") - } - switch vs[0].(type) { - case vm.String: - return vm.NIL, fmt.Errorf("shuffle not supported on string") - case *vm.PersistentMap, vm.Map, *vm.SortedMap: - return vm.NIL, fmt.Errorf("shuffle not supported on map") - } - // Collect into slice. forceSeq realizes lazy seqs first, so - // an empty lazy seq yields [] rather than [nil]. - s, err := seqOf(vs[0]) - if err != nil { - return vm.NIL, err - } - vals := appendSeqValues(nil, forceSeq(s)) - // Fisher-Yates shuffle - rngShuffle(len(vals), func(i, j int) { - vals[i], vals[j] = vals[j], vals[i] - }) - return vm.NewArrayVector(vals), nil - }) // set-rand-seed!: seed the shared RNG so rand / rand-int / rand-nth / // shuffle / math/random produce a reproducible sequence. Returns nil. The // bang marks the process-wide mutation. For tests, benchmarks, and bug // repros — NOT a gameplay-determinism mechanism (use explicit state for // that). Reproducible only when rand calls happen in a deterministic order. - setRandSeedFn, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - n, ok := vs[0].(vm.Int) - if !ok { - return vm.NIL, fmt.Errorf("set-rand-seed! expected Int") - } - setRandSeed(int64(n)) - return vm.NIL, nil - }) // transient: create a transient (mutable) version of a persistent collection - transientf, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - switch v := vs[0].(type) { - case *vm.PersistentMap: - return vm.NewTransientMap(v), nil - case *vm.PersistentSet: - return vm.NewTransientSet(v), nil - case vm.ArrayVector: - return vm.NewTransientVector([]vm.Value(v)), nil - case vm.PersistentVector: - vals := v.Unbox().([]vm.Value) - return vm.NewTransientVector(vals), nil - default: - return vm.NIL, fmt.Errorf("transient not supported on %s", vs[0].Type().Name()) - } - }) // persistent!: freeze a transient back to a persistent collection - persistentf, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - switch v := vs[0].(type) { - case *vm.TransientMap: - return v.Persistent() - case *vm.TransientVector: - return v.Persistent() - case *vm.TransientSet: - return v.Persistent() - default: - return vm.NIL, fmt.Errorf("persistent! not supported on %s", vs[0].Type().Name()) - } - }) // conj!: mutating conj on a transient - conjBang, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) == 0 { - return vm.NewTransientVector(nil), nil - } - if len(vs) == 1 { - return vs[0], nil - } - switch t := vs[0].(type) { - case *vm.TransientMap: - var err error - for i := 1; i < len(vs); i++ { - t, err = t.Conj(vs[i]) - if err != nil { - return vm.NIL, err - } - } - return t, nil - case *vm.TransientVector: - var err error - for i := 1; i < len(vs); i++ { - t, err = t.Conj(vs[i]) - if err != nil { - return vm.NIL, err - } - } - return t, nil - case *vm.TransientSet: - var err error - for i := 1; i < len(vs); i++ { - t, err = t.Conj(vs[i]) - if err != nil { - return vm.NIL, err - } - } - return t, nil - default: - return vm.NIL, fmt.Errorf("conj! not supported on %s", vs[0].Type().Name()) - } - }) // assoc!: mutating assoc on a transient - assocBang, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) < 2 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - switch t := vs[0].(type) { - case *vm.TransientMap: - var err error - for i := 1; i < len(vs); i += 2 { - val := vm.Value(vm.NIL) - if i+1 < len(vs) { - val = vs[i+1] - } - t, err = t.Assoc(vs[i], val) - if err != nil { - return vm.NIL, err - } - } - return t, nil - case *vm.TransientVector: - var err error - for i := 1; i < len(vs); i += 2 { - val := vm.Value(vm.NIL) - if i+1 < len(vs) { - val = vs[i+1] - } - t, err = t.Assoc(vs[i], val) - if err != nil { - return vm.NIL, err - } - } - return t, nil - default: - return vm.NIL, fmt.Errorf("assoc! not supported on %s", vs[0].Type().Name()) - } - }) // disj!: mutating disj on a transient set - disjBang, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) < 2 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - t, ok := vs[0].(*vm.TransientSet) - if !ok { - return vm.NIL, fmt.Errorf("disj! expected TransientSet") - } - var err error - for i := 1; i < len(vs); i++ { - t, err = t.Disj(vs[i]) - if err != nil { - return vm.NIL, err - } - } - return t, nil - }) // dissoc!: mutating dissoc on a transient map - dissocBang, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) < 2 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - t, ok := vs[0].(*vm.TransientMap) - if !ok { - return vm.NIL, fmt.Errorf("dissoc! expected TransientMap") - } - var err error - for i := 1; i < len(vs); i++ { - t, err = t.Dissoc(vs[i]) - if err != nil { - return vm.NIL, err - } - } - return t, nil - }) // make-record-type: create a RecordType with name and field keywords - makeRecordType, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) < 1 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - name, ok := vs[0].(vm.String) - if !ok { - return vm.NIL, fmt.Errorf("make-record-type expected String name") - } - fields := make([]vm.Keyword, len(vs)-1) - for i := 1; i < len(vs); i++ { - kw, ok := vs[i].(vm.Keyword) - if !ok { - return vm.NIL, fmt.Errorf("make-record-type expected Keyword fields") - } - fields[i-1] = kw - } - return vm.NewRecordType(string(name), fields), nil - }) // make-record: create a Record from a RecordType and a map - makeRecord, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 2 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - rt, ok := vs[0].(*vm.RecordType) - if !ok { - return vm.NIL, fmt.Errorf("make-record expected RecordType") - } - m, ok := vs[1].(*vm.PersistentMap) - if !ok { - return vm.NIL, fmt.Errorf("make-record expected Map") - } - return vm.NewRecord(rt, m), nil - }) // record?: check if a value is a Record - isRecord, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - _, ok := vs[0].(*vm.Record) - return vm.Boolean(ok), nil - }) // make-deftype: create a DType (deftype class) with a name and field symbols. - makeDType, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) < 1 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - name, ok := vs[0].(vm.String) - if !ok { - return vm.NIL, fmt.Errorf("make-deftype expected String name") - } - fields := make([]vm.Symbol, len(vs)-1) - for i := 1; i < len(vs); i++ { - sym, ok := vs[i].(vm.Symbol) - if !ok { - return vm.NIL, fmt.Errorf("make-deftype expected Symbol fields") - } - fields[i-1] = sym - } - return vm.NewDType(string(name), fields), nil - }) // make-deftype-instance: construct an instance of a DType from positional field values. - makeDTypeInstance, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) < 1 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - dt, ok := vs[0].(*vm.DType) - if !ok { - return vm.NIL, fmt.Errorf("make-deftype-instance expected DType, got %s", vs[0].Type().Name()) - } - // Copy to avoid aliasing the VM's args slice (which may be reused). - fields := make([]vm.Value, len(vs)-1) - copy(fields, vs[1:]) - return vm.NewDTypeInstance(dt, fields), nil - }) // set-field!: mutate a deftype instance field in place (backs ^:mutable). // (set-field! instance 'field-name value) -> value - setField, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 3 { - return vm.NIL, fmt.Errorf("set-field! expected 3 arguments, got %d", len(vs)) - } - inst, ok := vs[0].(*vm.DTypeInstance) - if !ok { - return vm.NIL, fmt.Errorf("set-field! expected a deftype instance, got %s", vs[0].Type().Name()) - } - name, ok := vs[1].(vm.Symbol) - if !ok { - return vm.NIL, fmt.Errorf("set-field! expected a Symbol field name") - } - if err := inst.SetField(name, vs[2]); err != nil { - return vm.NIL, err - } - return vs[2], nil - }) // defprotocol*: create a protocol (called by defprotocol macro) - defProtocol, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) < 1 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - name, ok := vs[0].(vm.String) - if !ok { - return vm.NIL, fmt.Errorf("defprotocol* expected String name") - } - methods := make([]vm.Symbol, len(vs)-1) - for i := 1; i < len(vs); i++ { - s, ok := vs[i].(vm.Symbol) - if !ok { - return vm.NIL, fmt.Errorf("defprotocol* expected Symbol method names") - } - methods[i-1] = s - } - return vm.NewProtocol(string(name), methods), nil - }) // extend-type*: extend a protocol for a type (called by extend-type macro) - extendType, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 3 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - protocol, ok := vs[0].(*vm.Protocol) - if !ok { - return vm.NIL, fmt.Errorf("extend-type* expected Protocol") - } - implMap, ok := vs[2].(*vm.PersistentMap) - if !ok { - return vm.NIL, fmt.Errorf("extend-type* expected map of implementations") - } - // vs[1] is the type to extend — nil, a concrete ValueType, or a - // reusable TypeUnion descriptor for a compatibility interface. - if vs[1] == vm.NIL { - protocol.ExtendNil(implMap) - return vm.NIL, nil - } - if union, ok := vs[1].(*vm.TypeUnion); ok { - // Union fan-out must not clobber an exact extend-type on a member - // (Clojure: exact type beats interface, regardless of order). - for _, valueType := range union.Types() { - protocol.ExtendViaUnion(valueType, implMap) - } - return vm.NIL, nil - } - vt, ok := vs[1].(vm.ValueType) - if !ok { - return vm.NIL, fmt.Errorf("extend-type* expected a type, got %s", vs[1].Type().Name()) - } - protocol.Extend(vt, implMap) - return vm.NIL, nil - }) // make-protocol-fn: create a ProtocolFn for dispatch - makeProtocolFn, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 2 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - protocol, ok := vs[0].(*vm.Protocol) - if !ok { - return vm.NIL, fmt.Errorf("make-protocol-fn expected Protocol") - } - methodName, ok := vs[1].(vm.Symbol) - if !ok { - return vm.NIL, fmt.Errorf("make-protocol-fn expected Symbol") - } - return vm.NewProtocolFn(protocol, methodName), nil - }) // -set-invokable-protocol!: wire the VM's "invokable value" support to the // IFn protocol + its -invoke fn (called once from core after defining IFn). // Thereafter any value whose type satisfies IFn can be called like a fn. - setInvokableProtocol, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 2 { - return vm.NIL, fmt.Errorf("-set-invokable-protocol! expects 2 args") - } - protocol, ok := vs[0].(*vm.Protocol) - if !ok { - return vm.NIL, fmt.Errorf("-set-invokable-protocol! expected a Protocol") - } - invokeFn, ok := vs[1].(vm.Fn) - if !ok { - return vm.NIL, fmt.Errorf("-set-invokable-protocol! expected the -invoke fn") - } - vm.IFnProtocol = protocol - vm.IFnInvoke = invokeFn - return vm.NIL, nil - }) // -set-deref-protocol!: wire the VM's "derefable value" support to the // IDeref protocol + its -deref fn (called once from core after defining // IDeref). Thereafter any value whose type satisfies IDeref works with @/deref. - setDerefProtocol, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 2 { - return vm.NIL, fmt.Errorf("-set-deref-protocol! expects 2 args") - } - protocol, ok := vs[0].(*vm.Protocol) - if !ok { - return vm.NIL, fmt.Errorf("-set-deref-protocol! expected a Protocol") - } - derefFn, ok := vs[1].(vm.Fn) - if !ok { - return vm.NIL, fmt.Errorf("-set-deref-protocol! expected the -deref fn") - } - vm.IDerefProtocol = protocol - vm.IDerefDeref = derefFn - return vm.NIL, nil - }) // satisfies?: check if a value's type implements a protocol - satisfies, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 2 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - protocol, ok := vs[0].(*vm.Protocol) - if !ok { - return vm.NIL, fmt.Errorf("satisfies? expected Protocol") - } - return vm.Boolean(protocol.Satisfies(vs[1])), nil - }) // defmulti*: create a multimethod (called by defmulti macro) - defMulti, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) < 2 || len(vs) > 3 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - name, ok := vs[0].(vm.String) - if !ok { - return vm.NIL, fmt.Errorf("defmulti* expected String name") - } - dispatchFn, ok := vs[1].(vm.Fn) - if !ok { - return vm.NIL, fmt.Errorf("defmulti* expected Fn") - } - var defaultVal vm.Value = vm.Keyword("default") - if len(vs) == 3 { - defaultVal = vs[2] - } - return vm.NewMultiFn(string(name), dispatchFn, defaultVal), nil - }) // defmethod*: add a method to a multimethod (called by defmethod macro) - defMethod, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 3 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - mf, ok := vs[0].(*vm.MultiFn) - if !ok { - return vm.NIL, fmt.Errorf("defmethod* expected MultiFn") - } - dispatchVal := vs[1] - method, ok := vs[2].(vm.Fn) - if !ok { - return vm.NIL, fmt.Errorf("defmethod* expected Fn") - } - return mf.AddMethod(dispatchVal, method), nil - }) // methods: return the method map of a multimethod methods, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { @@ -5465,9 +3387,6 @@ func installLangNS() { }) // pr-str: print readably to string (with quotes on strings) - prStr, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - return prThroughToString(vs, true) - }) // prn: print readably + newline through *out* prn := vm.NewCtxNativeFn("prn", func(ec *vm.ExecContext, vs []vm.Value) (vm.Value, error) { @@ -5479,213 +3398,25 @@ func installLangNS() { }) // prn-str: print readably + newline to string - prnStr, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - s, err := prThroughToString(vs, true) - if err != nil { - return vm.NIL, err - } - return vm.String(string(s.(vm.String)) + "\n"), nil - }) // print-str: print human-readably to string (no quotes on strings) - printStr, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - return prThroughToString(vs, false) - }) // println-str: print human-readably + newline to string - printlnStr, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - s, err := prThroughToString(vs, false) - if err != nil { - return vm.NIL, err - } - return vm.String(string(s.(vm.String)) + "\n"), nil - }) // re-find: find first match of regex in string - reFind, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 2 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - re, ok := vs[0].(*vm.Regex) - if !ok { - return vm.NIL, fmt.Errorf("re-find expected Regex") - } - s, ok := vs[1].(vm.String) - if !ok { - return vm.NIL, fmt.Errorf("re-find expected String") - } - indices := re.FindStringSubmatchIndex(string(s)) - if indices == nil { - return vm.NIL, nil - } - return regexSubmatchValue(string(s), indices), nil - }) // re-matches: match entire string against regex - reMatches, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 2 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - re, ok := vs[0].(*vm.Regex) - if !ok { - return vm.NIL, fmt.Errorf("re-matches expected Regex") - } - s, ok := vs[1].(vm.String) - if !ok { - return vm.NIL, fmt.Errorf("re-matches expected String") - } - indices := re.FindStringSubmatchIndex(string(s)) - if indices == nil || indices[0] != 0 || indices[1] != len(s) { - return vm.NIL, nil - } - return regexSubmatchValue(string(s), indices), nil - }) // re-seq: return lazy seq of all matches - reSeq, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 2 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - re, ok := vs[0].(*vm.Regex) - if !ok { - return vm.NIL, fmt.Errorf("re-seq expected Regex") - } - s, ok := vs[1].(vm.String) - if !ok { - return vm.NIL, fmt.Errorf("re-seq expected String") - } - // Like Clojure (and re-find above): a groupless pattern yields - // the match string, capture groups yield [full g1 g2 ...]. - all := re.FindAllStringSubmatchIndex(string(s), -1) - if all == nil { - return vm.NIL, nil - } - vals := make([]vm.Value, len(all)) - for i, indices := range all { - vals[i] = regexSubmatchValue(string(s), indices) - } - return vm.ListType.Box(vals) - }) // require loads a namespace by name (like Clojure's require function for REPL use) // Supports: (require 'foo), (require '[foo :as f]), (require '[foo :refer [a b]]) - requiref, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - cns := CurrentNS.Deref().(*vm.Namespace) - for _, v := range vs { - switch arg := v.(type) { - case vm.Symbol: - if _, err := RequireNS(string(arg)); err != nil { - return vm.NIL, err - } - case vm.ArrayVector: - // Vector form: [ns-name :as alias] or [ns-name :refer [syms...]] - if arg.RawCount() < 1 { - return vm.NIL, fmt.Errorf("require: empty vector") - } - nsName, ok := arg.ValueAt(vm.Int(0)).(vm.Symbol) - if !ok { - return vm.NIL, fmt.Errorf("require: first element must be a symbol") - } - target, err := RequireNS(string(nsName)) - if err != nil { - return vm.NIL, err - } - // Parse options - for i := 1; i < arg.RawCount()-1; i += 2 { - opt := arg.ValueAt(vm.Int(int64(i))) - val := arg.ValueAt(vm.Int(int64(i + 1))) - switch opt { - case vm.Keyword("as"): - if alias, ok := val.(vm.Symbol); ok { - cns.Alias(alias, target) - } - case vm.Keyword("refer"): - if val == vm.Keyword("all") { - cns.Refer(target, "", true) - } else if vec, ok := val.(vm.ArrayVector); ok { - syms := make([]vm.Symbol, vec.RawCount()) - for j := 0; j < vec.RawCount(); j++ { - syms[j] = vec.ValueAt(vm.Int(int64(j))).(vm.Symbol) - } - cns.ReferList(target, syms) - } - } - } - default: - return vm.NIL, fmt.Errorf("require expected Symbol or Vector, got %s", v.Type().Name()) - } - } - return vm.NIL, nil - }) // find-ns returns the namespace with the given name, or nil - findNs, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - s, ok := vs[0].(vm.Symbol) - if !ok { - return vm.NIL, fmt.Errorf("find-ns expected Symbol") - } - nsMu.RLock() - ns := nsRegistry[string(s)] - nsMu.RUnlock() - if ns == nil { - return vm.NIL, nil - } - return ns, nil - }) - - resolvef, err := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - sym, ok := vs[0].(vm.Symbol) - if !ok { - return vm.NIL, fmt.Errorf("resolve expected Symbol") - } - cns := CurrentNS.Deref().(*vm.Namespace) - if v := cns.Lookup(sym); v != vm.NIL { - return v, nil - } - return vm.NIL, nil - }) - if err != nil { - panic(err) - } // all-ns returns a list of all loaded namespaces - allNs, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - nsMu.RLock() - var nss []vm.Value - for _, ns := range nsRegistry { - nss = append(nss, ns) - } - nsMu.RUnlock() - return vm.NewList(nss), nil - }) // the-ns returns the namespace for a symbol, throwing if not found - theNs, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - s, ok := vs[0].(vm.Symbol) - if !ok { - // If already a namespace, return it - if ns, ok := vs[0].(*vm.Namespace); ok { - return ns, nil - } - return vm.NIL, fmt.Errorf("the-ns expected Symbol or Namespace") - } - nsMu.RLock() - ns := nsRegistry[string(s)] - nsMu.RUnlock() - if ns == nil { - return vm.NIL, fmt.Errorf("no namespace: %s found", s) - } - return ns, nil - }) // ns-name returns the name of a namespace as a symbol nsName, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { @@ -5702,98 +3433,22 @@ func installLangNS() { // ns-publics returns a map of symbol -> Var for the public (non-private) // interned vars of a namespace, given either the namespace or a symbol // naming it (matching Clojure, which passes its arg through the-ns). - nsPublics, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - var ns *vm.Namespace - switch a := vs[0].(type) { - case *vm.Namespace: - ns = a - case vm.Symbol: - // resolveNSAlias canonicalizes the Clojure-facing names the rest of - // the runtime accepts (clojure.core -> core, clojure.string -> - // string, …); non-aliases pass through unchanged. - nsMu.RLock() - ns = nsRegistry[resolveNSAlias(string(a))] - nsMu.RUnlock() - if ns == nil { - return vm.NIL, fmt.Errorf("no namespace: %s found", a) - } - default: - return vm.NIL, fmt.Errorf("ns-publics expected Symbol or Namespace") - } - pubs := ns.PublicVars() - kvs := make([]vm.Value, 0, len(pubs)*2) - for sym, v := range pubs { - kvs = append(kvs, sym, v) - } - return vm.NewMap(kvs), nil - }) // find-var: (find-var 'ns/name) -> the interned var in that namespace, or // nil if the namespace or the name is not found. integrant's default // init-key resolves a component fn from a qualified keyword via // (some-> (find-var sym) var-get). - findVar, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - sym, ok := vs[0].(vm.Symbol) - if !ok { - return vm.NIL, fmt.Errorf("find-var expected a symbol") - } - nsV, nameV := sym.Namespaced() - nsSym, ok1 := nsV.(vm.Symbol) - nameSym, ok2 := nameV.(vm.Symbol) - if !ok1 || !ok2 { - return vm.NIL, fmt.Errorf("find-var expects a fully-qualified symbol: %s", sym) - } - nsMu.RLock() - targetNS := nsRegistry[resolveNSAlias(string(nsSym))] - nsMu.RUnlock() - if targetNS == nil { - return vm.NIL, nil - } - if v := targetNS.LookupLocal(nameSym); v != nil { - return v, nil - } - return vm.NIL, nil - }) // get-method: (get-method multifn dispatch-val) -> the method fn that value // would select (exact match, else the default method), or nil. integrant's // can-expand-key? uses it to test whether a key has an expand-key method. - getMethod, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 2 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - mf, ok := vs[0].(*vm.MultiFn) - if !ok { - return vm.NIL, fmt.Errorf("get-method expected a multimethod") - } - return mf.GetMethod(vs[1]), nil - }) // enumeration-seq: only reached by integrant's JVM-only classpath scanners // (resources/load-hierarchy/load-annotations). let-go has no java.util // Enumeration, so this is a compile-only stub — it lets those :clj defns // load, and fails loudly if actually called. - enumerationSeq, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - return vm.NIL, fmt.Errorf("enumeration-seq is not supported under let-go (no java.util.Enumeration)") - }) // lazy-seq* creates a LazySeq from a thunk function - lazySeq, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("lazy-seq* expected 1 argument, got %d", len(vs)) - } - fn, ok := vs[0].(vm.Fn) - if !ok { - return vm.NIL, fmt.Errorf("lazy-seq* expected a function") - } - return vm.NewLazySeq(fn), nil - }) // push-binding!/pop-binding! resolve against the *active* ExecContext // (ec.Invoke routes it in), so a `binding` form inside an isolated child @@ -5845,27 +3500,6 @@ func installLangNS() { return wrapped, nil }) - withMeta, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 2 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - if vs[0] == vm.NIL { - return vm.NIL, nil - } - m, ok := vs[0].(vm.IMeta) - if ok { - return m.WithMeta(vs[1]), nil - } - fn, ok := vs[0].(vm.Fn) - if ok { - return vm.NewMetaFn(fn, vs[1]), nil - } - // Other non-IMeta values pass through unchanged. This is - // load-bearing: value-position type hints compile to runtime - // with-meta calls, so hinted scalars must remain valid. - return vs[0], nil - }) - metaf, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { if len(vs) != 1 { return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) @@ -5881,75 +3515,14 @@ func installLangNS() { }) // throw - throwf, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - return vm.NIL, vm.NewThrownError(vs[0]) - }) // ex-info - exInfo, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) < 2 || len(vs) > 3 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - msg, ok := vs[0].(vm.String) - if !ok { - return vm.NIL, fmt.Errorf("ex-info expected String message") - } - data, ok := vs[1].(*vm.PersistentMap) - if !ok { - return vm.NIL, fmt.Errorf("ex-info expected Map data") - } - var cause error - if len(vs) == 3 { - if ei, ok := vs[2].(*vm.ExInfo); ok { - cause = ei - } - } - return vm.NewExInfo(string(msg), data, cause), nil - }) // ex-message - exMessage, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("wrong number of arguments") - } - if ei, ok := vs[0].(*vm.ExInfo); ok { - return vm.String(ei.Message()), nil - } - return vm.NIL, nil - }) // ex-data - exData, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("wrong number of arguments") - } - if ei, ok := vs[0].(*vm.ExInfo); ok { - // Class-tagged exceptions carry no data map; a nil - // *PersistentMap must surface as NIL, not a typed nil. - if d := ei.Data(); d != nil { - return d, nil - } - } - return vm.NIL, nil - }) // ex-cause - exCause, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("wrong number of arguments") - } - if ei, ok := vs[0].(*vm.ExInfo); ok { - if c := ei.Cause(); c != nil { - if cev, ok := c.(*vm.ExInfo); ok { - return cev, nil - } - } - } - return vm.NIL, nil - }) // transformer-seq* — (transformer-seq* xform coll) → lazy seq // Lazily pulls elements from coll through the transducer xform. @@ -6059,73 +3632,16 @@ func installLangNS() { }) // delay — (delay body) is a macro in core.lg, but we need delay* as the constructor - delayStar, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("delay* expects 1 arg (thunk fn)") - } - fn, ok := vs[0].(vm.Fn) - if !ok { - return vm.NIL, fmt.Errorf("delay* expected Fn") - } - return vm.NewDelay(fn), nil - }) // force — deref a delay (or return value if not a delay) - force, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("force expects 1 arg") - } - if d, ok := vs[0].(*vm.Delay); ok { - return d.Force() - } - return vs[0], nil - }) // delay? — test if value is a Delay - isDelay, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.FALSE, nil - } - _, ok := vs[0].(*vm.Delay) - return vm.Boolean(ok), nil - }) // realized? — test if a Delay, Promise, Future, or LazySeq has been realized - isRealized, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - if d, ok := vs[0].(*vm.Delay); ok { - return vm.Boolean(d.IsRealized()), nil - } - if p, ok := vs[0].(*vm.Promise); ok { - return vm.Boolean(p.IsRealized()), nil - } - if s, ok := vs[0].(*vm.LazySeq); ok { - return vm.Boolean(s.IsRealized()), nil - } - return vm.NIL, fmt.Errorf("realized? expected delay, promise, future, or lazy seq") - }) // volatile! — create a volatile mutable box - volatilef, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("volatile! expects 1 arg") - } - return vm.NewVolatile(vs[0]), nil - }) // vreset! — set volatile value - vreset, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 2 { - return vm.NIL, fmt.Errorf("vreset! expects 2 args") - } - v, ok := vs[0].(*vm.Volatile) - if !ok { - return vm.NIL, fmt.Errorf("vreset! expected Volatile") - } - return v.Reset(vs[1]), nil - }) // vswap! — apply fn to volatile value: (vswap! vol f args...) vswap := vm.NewCtxNativeFn("vswap!", func(ec *vm.ExecContext, vs []vm.Value) (vm.Value, error) { @@ -6151,20 +3667,8 @@ func installLangNS() { }) // reduced — wrap a value to signal early termination - reducedf, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("reduced expects 1 arg") - } - return vm.NewReduced(vs[0]), nil - }) // reduced? — test if value is Reduced - isReducedf, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.FALSE, nil - } - return vm.Boolean(vm.IsReduced(vs[0])), nil - }) // compare — generic comparison: -1, 0, 1 comparef, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { @@ -6207,232 +3711,21 @@ func installLangNS() { // --- Bitwise ops --- - bitAnd, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 2 { - return vm.NIL, fmt.Errorf("bit-and expects 2 args") - } - a, ok := vs[0].(vm.Int) - if !ok { - return vm.NIL, fmt.Errorf("bit-and expected Int") - } - b, ok := vs[1].(vm.Int) - if !ok { - return vm.NIL, fmt.Errorf("bit-and expected Int") - } - return vm.MakeInt(int(a) & int(b)), nil - }) + // re-groups — find all submatch groups: (re-groups regex str) → vector of [match group1 group2 ...] - bitOr, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 2 { - return vm.NIL, fmt.Errorf("bit-or expects 2 args") - } - a, ok := vs[0].(vm.Int) - if !ok { - return vm.NIL, fmt.Errorf("bit-or expected Int") - } - b, ok := vs[1].(vm.Int) - if !ok { - return vm.NIL, fmt.Errorf("bit-or expected Int") - } - return vm.MakeInt(int(a) | int(b)), nil - }) + // promise — create a promise - bitXor, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 2 { - return vm.NIL, fmt.Errorf("bit-xor expects 2 args") - } - a, ok := vs[0].(vm.Int) - if !ok { - return vm.NIL, fmt.Errorf("bit-xor expected Int") - } - b, ok := vs[1].(vm.Int) - if !ok { - return vm.NIL, fmt.Errorf("bit-xor expected Int") - } - return vm.MakeInt(int(a) ^ int(b)), nil - }) + // deliver — deliver a value to a promise - bitNot, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { + // future — run body in a goroutine, return a promise that delivers the result + // (future* thunk) — internal, macro wraps body + futureStar := vm.NewCtxNativeFn("future*", func(ec *vm.ExecContext, vs []vm.Value) (vm.Value, error) { if len(vs) != 1 { - return vm.NIL, fmt.Errorf("bit-not expects 1 arg") - } - a, ok := vs[0].(vm.Int) - if !ok { - return vm.NIL, fmt.Errorf("bit-not expected Int") - } - return vm.MakeInt(^int(a)), nil - }) - - bitShiftLeft, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 2 { - return vm.NIL, fmt.Errorf("bit-shift-left expects 2 args") - } - a, ok := vs[0].(vm.Int) - if !ok { - return vm.NIL, fmt.Errorf("bit-shift-left expected Int") + return vm.NIL, fmt.Errorf("future* expects 1 arg (thunk fn)") } - b, ok := vs[1].(vm.Int) + fn, ok := vs[0].(vm.Fn) if !ok { - return vm.NIL, fmt.Errorf("bit-shift-left expected Int") - } - return vm.MakeInt(int(a) << uint(b)), nil - }) - - bitShiftRight, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 2 { - return vm.NIL, fmt.Errorf("bit-shift-right expects 2 args") - } - a, ok := vs[0].(vm.Int) - if !ok { - return vm.NIL, fmt.Errorf("bit-shift-right expected Int") - } - b, ok := vs[1].(vm.Int) - if !ok { - return vm.NIL, fmt.Errorf("bit-shift-right expected Int") - } - return vm.MakeInt(int(a) >> uint(b)), nil - }) - - unsignedBitShiftRight, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 2 { - return vm.NIL, fmt.Errorf("unsigned-bit-shift-right expects 2 args") - } - a, ok := vs[0].(vm.Int) - if !ok { - return vm.NIL, fmt.Errorf("unsigned-bit-shift-right expected Int") - } - b, ok := vs[1].(vm.Int) - if !ok { - return vm.NIL, fmt.Errorf("unsigned-bit-shift-right expected Int") - } - return vm.MakeInt(int(uint(a) >> uint(b))), nil - }) - - bitTest, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 2 { - return vm.NIL, fmt.Errorf("bit-test expects 2 args") - } - a, ok := vs[0].(vm.Int) - if !ok { - return vm.NIL, fmt.Errorf("bit-test expected Int") - } - b, ok := vs[1].(vm.Int) - if !ok { - return vm.NIL, fmt.Errorf("bit-test expected Int") - } - return vm.Boolean(int(a)&(1< — debug tap queue (synchronous) - addTap, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("add-tap expects 1 arg") - } - fn, ok := vm.AsFn(vs[0]) - if !ok { - return vm.NIL, fmt.Errorf("add-tap expected Fn") - } - tapsMu.Lock() - taps = append(taps, fn) - tapsMu.Unlock() - return vm.NIL, nil - }) - - removeTap, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("remove-tap expects 1 arg") - } - tapsMu.Lock() - for i, t := range taps { - if t == vs[0] { - taps = append(taps[:i], taps[i+1:]...) - break - } - } - tapsMu.Unlock() - return vm.NIL, nil - }) - - tapBang, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("tap> expects 1 arg") - } - tapsMu.Lock() - snap := make([]vm.Fn, len(taps)) - copy(snap, taps) - tapsMu.Unlock() - for _, t := range snap { - _, _ = t.Invoke([]vm.Value{vs[0]}) - } - return vm.TRUE, nil - }) // add-watch — (add-watch atom-or-var key fn) - addWatch, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 3 { - return vm.NIL, fmt.Errorf("add-watch expects 3 args") - } - fn, ok := vm.AsFn(vs[2]) - if !ok { - return vm.NIL, fmt.Errorf("add-watch expected Fn") - } - switch ref := vs[0].(type) { - case *vm.Atom: - ref.AddWatch(vs[1], fn) - case *vm.Var: - ref.AddWatch(vs[1], fn) - default: - return vm.NIL, fmt.Errorf("add-watch expected Atom or Var") - } - return vs[0], nil - }) // remove-watch — (remove-watch atom-or-var key) - removeWatch, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 2 { - return vm.NIL, fmt.Errorf("remove-watch expects 2 args") - } - switch ref := vs[0].(type) { - case *vm.Atom: - ref.RemoveWatch(vs[1]) - case *vm.Var: - ref.RemoveWatch(vs[1]) - default: - return vm.NIL, fmt.Errorf("remove-watch expected Atom or Var") - } - return vs[0], nil - }) // alter-meta! — (alter-meta! ref f & args) alterMeta := vm.NewCtxNativeFn("alter-meta!", func(ec *vm.ExecContext, vs []vm.Value) (vm.Value, error) { @@ -6552,64 +3771,7 @@ func installLangNS() { } }) - getValidator, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("get-validator expects 1 arg") - } - a, ok := vs[0].(*vm.Atom) - if !ok { - return vm.NIL, fmt.Errorf("get-validator expected Atom") - } - return a.Validator(), nil - }) - // subvec — (subvec v start) or (subvec v start end) - subvecf, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) < 2 || len(vs) > 3 { - return vm.NIL, fmt.Errorf("subvec expects 2-3 args") - } - s, ok := vm.ToInt(vs[1]) - if !ok { - return vm.NIL, fmt.Errorf("subvec expected Int start") - } - - switch v := vs[0].(type) { - case vm.ArrayVector: - end := len(v) - if len(vs) == 3 { - e, ok := vm.ToInt(vs[2]) - if !ok { - return vm.NIL, fmt.Errorf("subvec expected Int end") - } - end = e - } - if s < 0 || end > len(v) || s > end { - return vm.NIL, fmt.Errorf("subvec: index out of bounds") - } - result := make([]vm.Value, end-s) - copy(result, v[s:end]) - return vm.NewArrayVector(result), nil - case vm.PersistentVector: - end := int(v.Count().(vm.Int)) - if len(vs) == 3 { - e, ok := vm.ToInt(vs[2]) - if !ok { - return vm.NIL, fmt.Errorf("subvec expected Int end") - } - end = e - } - if s < 0 || end > int(v.Count().(vm.Int)) || s > end { - return vm.NIL, fmt.Errorf("subvec: index out of bounds") - } - result := make([]vm.Value, end-s) - for i := s; i < end; i++ { - result[i-s] = v.ValueAt(vm.Int(i)) - } - return vm.NewArrayVector(result), nil - default: - return vm.NIL, fmt.Errorf("subvec expected vector") - } - }) // fn? — test if value is callable isFn, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { @@ -6627,108 +3789,18 @@ func installLangNS() { }) // double? — true only for float64 values; float? accepts float32 and float64. - isDouble, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.FALSE, nil - } - _, ok := vs[0].(vm.Float) - return vm.Boolean(ok), nil - }) // instance? — type check (simplified: checks if type name matches) - instancep, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 2 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - // We accept type objects (e.g. IntType) and check if the value's type matches - if t, ok := vs[0].(vm.ValueType); ok { - if vs[1].Type() == t { - return vm.TRUE, nil - } - // Walk registered ancestry so subclass values answer true for - // parent classes, e.g. (instance? Throwable (Exception. "m")). - // Types with no registered parents keep exact-match semantics. - if anc := directTypeAncestors(vs[1].Type()); anc != nil { - return anc.Contains(t), nil - } - return vm.FALSE, nil - } - if union, ok := vs[0].(*vm.TypeUnion); ok { - return vm.Boolean(union.Contains(vs[1].Type())), nil - } - // Clojure-compat interface markers (e.g. clojure.lang.IEditableCollection) - // are registered as plain symbols by installClojureCompatAliases. Answer - // instance? for them via the type→interface hierarchy so libraries that - // branch on (instance? clojure.lang.IEditableCollection coll) — like - // medley — observe the JVM-equivalent answer. - if marker, ok := vs[0].(vm.Symbol); ok { - if anc := directTypeAncestors(vs[1].Type()); anc != nil { - return vm.Boolean(anc.Contains(marker) == vm.TRUE), nil - } - } - // A protocol behaves like an interface: (instance? SomeProtocol x) is a - // membership test, matching Clojure where defprotocol generates a host - // interface. - if p, ok := vs[0].(*vm.Protocol); ok { - return vm.Boolean(p.Satisfies(vs[1])), nil - } - return vm.FALSE, nil - }) // ifn? — true if value implements Fn (invokable: functions, keywords, maps, sets, vectors) - isIFn, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.FALSE, nil - } - switch vs[0].(type) { - case vm.Fn, vm.Keyword, vm.Symbol, *vm.PersistentMap, *vm.PersistentSet, - vm.ArrayVector, vm.PersistentVector, *vm.SortedMap, *vm.SortedSet, *vm.Promise: - return vm.TRUE, nil - } - return vm.FALSE, nil - }) // identical? — reference/value identity - identical, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 2 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - return vm.Boolean(identicalValue(vs[0], vs[1])), nil - }) // any? — returns true for everything (every value satisfies any?) - anyp, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - return vm.TRUE, nil - }) // unreduced — unwrap Reduced, or return value as-is - unreduced, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("unreduced expects 1 arg") - } - if r, ok := vs[0].(*vm.Reduced); ok { - return r.Deref(), nil - } - return vs[0], nil - }) // ensure-reduced — if already Reduced, return as-is; otherwise wrap - ensureReduced, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("ensure-reduced expects 1 arg") - } - if _, ok := vs[0].(*vm.Reduced); ok { - return vs[0], nil - } - return vm.NewReduced(vs[0]), nil - }) - - if err != nil { - panic("lang NS init failed") - } ns := vm.NewNamespace(NameCoreNS) @@ -6840,25 +3912,6 @@ func installLangNS() { (ns.Lookup("ns").(*vm.Var)).SetMacro() // primitive fns - ns.Def("+", plus) - ns.Def("*", mul) - ns.Def("-", sub) - ns.Def("/", div) - ns.Def("+'", plusP) - ns.Def("*'", mulP) - ns.Def("-'", subP) - ns.Def("unchecked-add", uncheckedAdd) - ns.Def("unchecked-subtract", uncheckedSubtract) - ns.Def("unchecked-multiply", uncheckedMultiply) - ns.Def("unchecked-negate", uncheckedNegate) - ns.Def("unchecked-divide-int", uncheckedDivideInt) - ns.Def("unchecked-long", uncheckedLong) - ns.Def("unchecked-int", uncheckedInt) - ns.Def("unchecked-short", uncheckedShort) - ns.Def("unchecked-byte", uncheckedByte) - ns.Def("unchecked-char", uncheckedChar) - ns.Def("unchecked-double", uncheckedDouble) - ns.Def("unchecked-float", uncheckedFloat) ns.Def("=", equals) ns.Def("not=", notEq) @@ -6869,78 +3922,38 @@ func installLangNS() { ns.Def("<", lt) ns.Def(">=", ge) ns.Def("<=", le) - ns.Def("mod", mod) - ns.Def("abs", abs) // and/or are now macros in core.lg (short-circuiting) // ns.Def("and", and) // ns.Def("or", or) - ns.Def("not", not) - ns.Def("complement", complement) - ns.Def("set-macro!", setMacro) - ns.Def("gensym", gensym) ns.Def("in-ns", inNs) - ns.Def("exclude-in-current-ns", excludeInCurrentNs) - ns.Def("use", use) - ns.Def("alias", aliasf) ns.Def("name", name) ns.Def("namespace", namespace) - ns.Def("vector", vector) ns.Def("vec", vec) - ns.Def("hash-map", hashMap) - ns.Def("array-map", arrayMap) ns.Def("list", list) - ns.Def("range", rangef) - ns.Def("keyword", keyword) - ns.Def("symbol", symbolf) ns.Def("hash-set", hashSet) - ns.Def("sorted-map", sortedMap) - ns.Def("sorted-set", sortedSet) - ns.Def("sorted-map-by", sortedMapBy) - ns.Def("sorted-set-by", sortedSetBy) ns.Def("seq", seq) ns.Def("seq?", isSeq) - ns.Def("list?", isList) // basic predicates needed during early core bootstrap ns.Def("coll?", isColl) - ns.Def("empty", empty) - - ns.Def("assoc", assoc) - ns.Def("dissoc", dissoc) ns.Def("update", update) - ns.Def("cons", cons) ns.Def("conj", conj) - ns.Def("disj", disj) ns.Def("first", first) - ns.Def("second", second) ns.Def("next", next) ns.Def("rest", rest) ns.Def("get", get) - ns.Def("key", keyf) - ns.Def("val", valf) ns.Def("nth", nthf) - ns.Def("count", count) - ns.Def("contains?", contains) ns.Def("map*", mapf) ns.Def("mapv", mapv) parMapV := vm.NewCtxNativeFn("pmapv", parallelMapV) ns.Def("pmapv", parMapV) - ns.Def("chunk-first", chunkFirst) - ns.Def("chunk-rest", chunkRest) - ns.Def("chunk-next", chunkNext) - ns.Def("chunk-cons", chunkConsF) - ns.Def("chunked-seq?", chunkedSeqP) - ns.Def("chunk-buffer", chunkBufferF) - ns.Def("chunk-append", chunkAppendF) - ns.Def("chunk", chunkF) ns.Def("reduce", reduce) - ns.Def("concat*", concat) ns.Def("some", some) ns.Def("println", printlnf) @@ -6949,61 +3962,34 @@ func installLangNS() { ns.Def("apply*", apply) ns.Def("deref", deref) - ns.Def("register-host-method!", registerHostMethod) - ns.Def("register-host-class!", registerHostClass) - ns.Def("atom", atom) - ns.Def("reset!", reset) ns.Def("swap!", swap) - ns.Def("compare-and-set!", compareAndSet) ns.Def("swap-vals!", swapVals) - ns.Def("reset-vals!", resetVals) // now/lines are lg-isms → let-go.core (see the lgCore block below). - ns.Def("slurp", slurp) - ns.Def("spit", spit) // parse-int is an lg-ism → let-go.core; parse-long is the Clojure name. ns.Def("parse-long", parseInt) - ns.Def("max", max) - ns.Def("min", min) ns.Def("compare", comparef) ns.Def("sort", sort) - ns.Def(".", methodInvoke) - // async ns.Def("go*", gof) - ns.Def("chan", chanf) ns.Def(">!", chanput) ns.Def("!!", chanput) ns.Def("", tapBang) - ns.Def("add-watch", addWatch) - ns.Def("remove-watch", removeWatch) ns.Def("alter-meta!", alterMeta) - ns.Def("get-validator", getValidator) - ns.Def("subvec", subvecf) ns.Def("print", printf) ns.Def("pr", prf) - ns.Def("reduced", reducedf) - ns.Def("reduced?", isReducedf) - ns.Def("unreduced", unreduced) - ns.Def("ensure-reduced", ensureReduced) // quot — integer division (truncated toward zero) - quotf, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 2 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - return vm.NumQuot(vs[0], vs[1]) - }) - ns.Def("quot", quotf) // rem — remainder of truncated division (sign follows dividend) - remf, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 2 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - return vm.NumRem(vs[0], vs[1]) - }) - ns.Def("rem", remf) // hash — returns the hash code of a value - hashf, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - return vm.MakeInt(int(vm.HashValue(vs[0]))), nil - }) - ns.Def("hash", hashf) // parse-double — parse string to float - parseDouble, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - s, ok := vs[0].(vm.String) - if !ok { - return vm.NIL, fmt.Errorf("parse-double expected String") - } - f, err := strconv.ParseFloat(string(s), 64) - if err != nil { - return vm.NIL, nil // Clojure returns nil for unparseable - } - return vm.Float(f), nil - }) - ns.Def("parse-double", parseDouble) // parse-boolean — parse "true"/"false" to boolean - parseBool, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - s, ok := vs[0].(vm.String) - if !ok { - return vm.NIL, fmt.Errorf("parse-boolean expected String") - } - switch string(s) { - case "true": - return vm.TRUE, nil - case "false": - return vm.FALSE, nil - } - return vm.NIL, nil - }) - ns.Def("parse-boolean", parseBool) // NaN? — test if value is NaN - isNaN, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.FALSE, nil - } - switch v := vs[0].(type) { - case vm.Float: - return vm.Boolean(math.IsNaN(float64(v))), nil - case vm.Float32: - return vm.Boolean(math.IsNaN(float64(v))), nil - case vm.Int, *vm.BigInt, *vm.Ratio, *vm.BigDecimal: - return vm.FALSE, nil - default: - return vm.NIL, fmt.Errorf("NaN? requires a number, got %s", vs[0].Type().Name()) - } - }) - ns.Def("NaN?", isNaN) // infinite? — test if value is +/-Inf - isInfinite, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.FALSE, nil - } - if f, ok := vs[0].(vm.Float); ok { - return vm.Boolean(math.IsInf(float64(f), 0)), nil - } - return vm.FALSE, nil - }) - ns.Def("infinite?", isInfinite) // boolean? — test if value is boolean - isBool, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.FALSE, nil - } - _, ok := vs[0].(vm.Boolean) - return vm.Boolean(ok), nil - }) - ns.Def("boolean?", isBool) // char? — test if value is char - isChar, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.FALSE, nil - } - _, ok := vs[0].(vm.Char) - return vm.Boolean(ok), nil - }) - ns.Def("char?", isChar) // var? — test if value is a var - isVar, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.FALSE, nil - } - _, ok := vs[0].(*vm.Var) - return vm.Boolean(ok), nil - }) - ns.Def("var?", isVar) // string/index-of — find first rune index of substring/char indexOf, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { @@ -7665,88 +4196,6 @@ func installLangNS() { // --- Array operations --- // Helper: build a typed array from size or seq - buildArray := func(kind vm.ArrayKind, vs []vm.Value) (vm.Value, error) { - if len(vs) == 0 || len(vs) > 2 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - // (x-array n) or (x-array n init) - if n, ok := vs[0].(vm.Int); ok { - size := int(n) - if size < 0 { - return vm.NIL, fmt.Errorf("negative array size: %d", size) - } - var arr *vm.TypedArray - switch kind { - case vm.ArrayByte: - arr = vm.NewByteArray(size) - case vm.ArrayInt: - arr = vm.NewIntArray(size) - case vm.ArrayFloat: - arr = vm.NewFloatArray(size) - case vm.ArrayObject: - arr = vm.NewObjectArray(size) - } - if len(vs) == 2 { - for i := range size { - if err := arr.Set(i, vs[1]); err != nil { - return vm.NIL, err - } - } - } - return arr, nil - } - // (x-array coll) - s, serr := seqOf(vs[0]) - if serr != nil { - return vm.NIL, serr - } - var vals []vm.Value - for ; s != nil; s = s.Next() { - vals = append(vals, s.First()) - } - var arr *vm.TypedArray - switch kind { - case vm.ArrayByte: - data := make([]byte, len(vals)) - for i, v := range vals { - n, ok := v.(vm.Int) - if !ok { - return vm.NIL, fmt.Errorf("byte-array element must be Int, got %s", v.Type().Name()) - } - data[i] = byte(n) - } - arr = vm.NewByteArrayFrom(data) - case vm.ArrayInt: - data := make([]int64, len(vals)) - for i, v := range vals { - switch n := v.(type) { - case vm.Int: - data[i] = int64(n) - default: - return vm.NIL, fmt.Errorf("int-array element must be Int, got %s", v.Type().Name()) - } - } - arr = vm.NewIntArrayFrom(data) - case vm.ArrayFloat: - data := make([]float64, len(vals)) - for i, v := range vals { - f, ok := vm.ToFloat(v) - if !ok { - return vm.NIL, fmt.Errorf("double-array element must be numeric, got %s", v.Type().Name()) - } - data[i] = f - } - arr = vm.NewFloatArrayFrom(data) - case vm.ArrayObject: - arr = vm.NewObjectArrayFrom(vals) - } - return arr, nil - } - - byteArrayf, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - return buildArray(vm.ArrayByte, vs) - }) - ns.Def("byte-array", byteArrayf) intArrayf, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return buildArray(vm.ArrayInt, vs) @@ -7760,131 +4209,15 @@ func installLangNS() { ns.Def("double-array", doubleArrayf) ns.Def("float-array", doubleArrayf) - objectArrayf, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - return buildArray(vm.ArrayObject, vs) - }) - ns.Def("object-array", objectArrayf) - // make-array — (make-array type size) - makeArrayf, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 2 { - return vm.NIL, fmt.Errorf("make-array expects 2 args (type, size)") - } - size, ok := vs[1].(vm.Int) - if !ok { - return vm.NIL, fmt.Errorf("make-array size must be Int") - } - n := int(size) - if n < 0 { - return vm.NIL, fmt.Errorf("negative array size: %d", n) - } - switch t := vs[0].(type) { - case vm.Keyword: - switch string(t) { - case "byte": - return vm.NewByteArray(n), nil - case "int", "long": - return vm.NewIntArray(n), nil - case "double", "float": - return vm.NewFloatArray(n), nil - case "object": - return vm.NewObjectArray(n), nil - } - return vm.NIL, fmt.Errorf("unknown array type: %s", t) - default: - // Default to object-array - return vm.NewObjectArray(n), nil - } - }) - ns.Def("make-array", makeArrayf) // aget — (aget arr idx) or (aget arr idx idx2 ...) - agetf, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) < 2 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - arr, ok := vs[0].(*vm.TypedArray) - if !ok { - return vm.NIL, fmt.Errorf("aget expects array, got %s", vs[0].Type().Name()) - } - idx, ok := vs[1].(vm.Int) - if !ok { - return vm.NIL, fmt.Errorf("aget index must be Int") - } - i := int(idx) - if i < 0 || i >= arr.Len() { - return vm.NIL, fmt.Errorf("array index %d out of bounds for length %d", i, arr.Len()) - } - val := arr.Get(i) - // Support nested access: (aget arr i j k ...) - for _, extra := range vs[2:] { - inner, ok := val.(*vm.TypedArray) - if !ok { - return vm.NIL, fmt.Errorf("aget nested: expected array, got %s", val.Type().Name()) - } - idx, ok := extra.(vm.Int) - if !ok { - return vm.NIL, fmt.Errorf("aget index must be Int") - } - j := int(idx) - if j < 0 || j >= inner.Len() { - return vm.NIL, fmt.Errorf("array index %d out of bounds for length %d", j, inner.Len()) - } - val = inner.Get(j) - } - return val, nil - }) - ns.Def("aget", agetf) // aset — (aset arr idx val) - asetf, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 3 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - arr, ok := vs[0].(*vm.TypedArray) - if !ok { - return vm.NIL, fmt.Errorf("aset expects array, got %s", vs[0].Type().Name()) - } - idx, ok := vs[1].(vm.Int) - if !ok { - return vm.NIL, fmt.Errorf("aset index must be Int") - } - i := int(idx) - if i < 0 || i >= arr.Len() { - return vm.NIL, fmt.Errorf("array index %d out of bounds for length %d", i, arr.Len()) - } - if err := arr.Set(i, vs[2]); err != nil { - return vm.NIL, err - } - return vs[2], nil - }) - ns.Def("aset", asetf) // alength — (alength arr) - alengthf, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - arr, ok := vs[0].(*vm.TypedArray) - if !ok { - return vm.NIL, fmt.Errorf("alength expects array, got %s", vs[0].Type().Name()) - } - return vm.MakeInt(arr.Len()), nil - }) - ns.Def("alength", alengthf) // aclone — (aclone arr) - aclonef, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - arr, ok := vs[0].(*vm.TypedArray) - if !ok { - return vm.NIL, fmt.Errorf("aclone expects array, got %s", vs[0].Type().Name()) - } - return arr.Clone(), nil - }) - ns.Def("aclone", aclonef) // to-array — (to-array coll) creates object-array from seq toArrayf, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { @@ -7934,22 +4267,6 @@ func installLangNS() { ns.Def("into-array", intoArrayf) // bytes — coerce string to byte-array - bytesf, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - switch v := vs[0].(type) { - case vm.String: - data := []byte(string(v)) - return vm.NewByteArrayFrom(data), nil - case *vm.TypedArray: - if v.Kind() == vm.ArrayByte { - return v, nil - } - } - return vm.NIL, fmt.Errorf("bytes expects String or byte-array, got %s", vs[0].Type().Name()) - }) - ns.Def("bytes", bytesf) // base64-encode — (base64-encode x) → standard padded base64 String. x is a // String or byte-array; pairs with the byte-array sinks and read-bytes. @@ -8030,16 +4347,6 @@ func installLangNS() { ns.Def("longs", intsf) // doubles — coerce seq to double-array - doublesf, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - if a, ok := vs[0].(*vm.TypedArray); ok && a.Kind() == vm.ArrayFloat { - return a, nil - } - return buildArray(vm.ArrayFloat, vs) - }) - ns.Def("doubles", doublesf) // array? — type predicate isArrayf, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { @@ -8054,14 +4361,6 @@ func installLangNS() { // bytes?: true iff the value is a byte-kind TypedArray (backing []byte). // array? doesn't distinguish element kind, and a TypedArray's Kind() is // not reachable from .lg, so this lives in Go alongside array?. - bytesP, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.FALSE, nil - } - a, ok := vs[0].(*vm.TypedArray) - return vm.Boolean(ok && a.Kind() == vm.ArrayByte), nil - }) - ns.Def("bytes?", bytesP) // alter-var-root — alter a var's root binding via (f root & args). // Reads/writes the root, bypassing any current dynamic binding. @@ -8089,51 +4388,16 @@ func installLangNS() { ns.Def("alter-var-root", alterVarRoot) // var-get — get the value of a Var - varGet, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("var-get expects 1 arg") - } - v, ok := vs[0].(*vm.Var) - if !ok { - return vm.NIL, fmt.Errorf("var-get expects a Var") - } - return v.Deref(), nil - }) - ns.Def("var-get", varGet) // bound? — true when the var has a bound value: a root binding or an active // dynamic binding (matching Clojure). Distinguishes a forward-declared/ // compiler-interned var from one that has actually been set, which `defonce` // relies on. - boundQ, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("bound? expects 1 arg") - } - v, ok := vs[0].(*vm.Var) - if !ok { - return vm.NIL, fmt.Errorf("bound? expects a Var") - } - if v.IsBound() { - return vm.TRUE, nil - } - return vm.FALSE, nil - }) - ns.Def("bound?", boundQ) // -copy-form-source! carries reader source metadata across macro and IR // rewrites which necessarily allocate a fresh list. It is intentionally a // core implementation detail: ordinary metadata cannot represent the // side-table spans retained by FormSource. - copyFormSource, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 2 { - return vm.NIL, fmt.Errorf("-copy-form-source! expects 2 args") - } - if info := vm.FormSource.Get(vs[0]); info != nil { - vm.FormSource.Set(vs[1], *info) - } - return vs[1], nil - }) - ns.Def("-copy-form-source!", copyFormSource) warnReflection := vm.NewCtxNativeFn("-warn-reflection!", func(ec *vm.ExecContext, vs []vm.Value) (vm.Value, error) { if len(vs) != 3 { @@ -8239,50 +4503,10 @@ func installLangNS() { // arity and variadic flag. Used by the IR-compile path of the defn // macro so the embedded function value flows back into the standard // compile pipeline as a constant. - chunkToFnFn, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 3 { - return vm.NIL, fmt.Errorf("chunk->fn expects (arity variadic? chunk), got %d args", len(vs)) - } - arityV, ok := vs[0].(vm.Int) - if !ok { - return vm.NIL, fmt.Errorf("chunk->fn: arity must be Int, got %s", vs[0].Type().Name()) - } - variadic := false - if b, ok := vs[1].(vm.Boolean); ok { - variadic = bool(b) - } else if vs[1] != vm.NIL { - return vm.NIL, fmt.Errorf("chunk->fn: variadic? must be Boolean or nil, got %s", vs[1].Type().Name()) - } - boxed, ok := vs[2].(*vm.Boxed) - if !ok { - return vm.NIL, fmt.Errorf("chunk->fn: third arg must be boxed CodeChunk, got %s", vs[2].Type().Name()) - } - chunk, ok := boxed.Unbox().(*vm.CodeChunk) - if !ok { - return vm.NIL, fmt.Errorf("chunk->fn: boxed value is not a CodeChunk") - } - return vm.MakeFunc(int(arityV), variadic, chunk), nil - }) - ns.Def("chunk->fn", chunkToFnFn) // make-multi-arity — combine a list of *Func/*Closure values into a // *MultiArityFn. Used by the IR pipeline to assemble multi-arity // functions at compile time. - makeMultiArityFn, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("make-multi-arity expects 1 arg (list of functions)") - } - list, ok := vs[0].(*vm.List) - if !ok { - return vm.NIL, fmt.Errorf("make-multi-arity expects a list, got %s", vs[0].Type().Name()) - } - var fns []vm.Value - for e := vm.Seq(list); e != nil; e = e.Next() { - fns = append(fns, e.First()) - } - return vm.MakeMultiArity(fns) - }) - ns.Def("make-multi-arity", makeMultiArityFn) // with-arity — (with-arity f arity variadic?) wraps callable f in a native // that DECLARES the given arity. ir.direct's invokers are necessarily @@ -8367,89 +4591,15 @@ func installLangNS() { ns.Def("sleep", sleepf) // intern — intern a var in a namespace - internf, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) < 2 || len(vs) > 3 { - return vm.NIL, fmt.Errorf("intern expects 2 or 3 args") - } - var targetNS *vm.Namespace - switch n := vs[0].(type) { - case vm.Symbol: - targetNS = nsRegistry[resolveNSAlias(string(n))] - case *vm.Namespace: - targetNS = n - default: - return vm.NIL, fmt.Errorf("intern expects a namespace or symbol") - } - if targetNS == nil { - return vm.NIL, fmt.Errorf("namespace not found") - } - sym, ok := vs[1].(vm.Symbol) - if !ok { - return vm.NIL, fmt.Errorf("intern expects a symbol name") - } - if len(vs) == 2 { - if existing := targetNS.LookupLocal(sym); existing != nil { - return existing, nil - } - return targetNS.Def(string(sym), vm.NIL), nil - } - // 3-arg form. If the Var already exists, UPDATE its root in - // place; otherwise create a fresh Var. This matters when - // other compiled code holds a captured Var pointer in its - // const pool — recreating the Var would leave those pointers - // referencing the old nil-rooted Var (the chicken-and-egg - // problem from Phase F's data-layer rollout). - if existing := targetNS.LookupLocal(sym); existing != nil { - existing.SetRoot(vs[2]) - return existing, nil - } - v := targetNS.Def(string(sym), vs[2]) - return v, nil - }) - ns.Def("intern", internf) // apply-def-meta! — apply def metadata (and the :dynamic / :private flags it // implies) to a Var, mirroring the bytecode defCompiler. Used by the IR // build-def lowering, which interns the var at build time and so must apply // its meta then, just as defCompiler does at compile time. - applyDefMetaf, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 2 { - return vm.NIL, fmt.Errorf("apply-def-meta! expects 2 args") - } - v, ok := vs[0].(*vm.Var) - if !ok { - return vm.NIL, fmt.Errorf("apply-def-meta! expects a Var") - } - ApplyVarMeta(v, vs[1]) - return v, nil - }) - ns.Def("apply-def-meta!", applyDefMetaf) // create-ns — create or return existing namespace - createNsf, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("create-ns expects 1 arg") - } - sym, ok := vs[0].(vm.Symbol) - if !ok { - return vm.NIL, fmt.Errorf("create-ns expects a symbol") - } - return NS(string(sym)), nil - }) - ns.Def("create-ns", createNsf) // pop! — pop from a transient vector - popBang, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("pop! expects 1 arg") - } - tv, ok := vs[0].(*vm.TransientVector) - if !ok { - return vm.NIL, fmt.Errorf("pop! expects a transient vector") - } - return tv.Pop() - }) - ns.Def("pop!", popBang) // with-out-str* — capture *out* output as string. Binding-based capture // (no process-global os.Stdout swap). Rebinds *out* to a bytes.Buffer- @@ -8493,55 +4643,12 @@ func installLangNS() { ns.Def("with-out-str*", withOutStrf) // uuid? — type predicate for UUID - isUUID, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.FALSE, nil - } - _, ok := vs[0].(*vm.UUID) - return vm.Boolean(ok), nil - }) - ns.Def("uuid?", isUUID) // inst? — type predicate for Instant - isInst, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.FALSE, nil - } - _, ok := vs[0].(*vm.Instant) - return vm.Boolean(ok), nil - }) - ns.Def("inst?", isInst) // parse-uuid — parse a string into a UUID - parseUUID, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("parse-uuid expects 1 arg") - } - s, ok := vs[0].(vm.String) - if !ok { - return vm.NIL, fmt.Errorf("parse-uuid expects a string, got %s", vs[0].Type().Name()) - } - u := vm.ParseUUID(string(s)) - if u == nil { - return vm.NIL, nil - } - return u, nil - }) - ns.Def("parse-uuid", parseUUID) // == — numeric equality across numeric categories. - numericEq, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { - if len(vs) < 2 { - return vm.TRUE, nil - } - for i := 1; i < len(vs); i++ { - if !vm.NumEquivalent(vs[0], vs[i]) { - return vm.FALSE, nil - } - } - return vm.TRUE, nil - }) - ns.Def("==", numericEq) // IR namespace primitives — declared in pkg/ir/ir_bridge.lg, // generated into pkg/rt/ir_bridge_generated.go via 'make generate-ir-bridge'. @@ -8863,3 +4970,4186 @@ func strValue(v vm.Value) string { } return v.String() } + +// --- lifted native helpers (see cmd/hoist-natives -helpers) --- + +func asChunked(v vm.Value, op string) (vm.IChunkedSeq, error) { + s, err := seqOf(v) + if err != nil { + return nil, fmt.Errorf("%s: not a sequence", op) + } + cs, ok := vm.AsChunkedSeq(s) + if !ok { + return nil, fmt.Errorf("%s: not a chunked seq", op) + } + return cs, nil +} + +func buildArray(kind vm.ArrayKind, vs []vm.Value) (vm.Value, error) { + if len(vs) == 0 || len(vs) > 2 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + + if n, ok := vs[0].(vm.Int); ok { + size := int(n) + if size < 0 { + return vm.NIL, fmt.Errorf("negative array size: %d", size) + } + var arr *vm.TypedArray + switch kind { + case vm.ArrayByte: + arr = vm.NewByteArray(size) + case vm.ArrayInt: + arr = vm.NewIntArray(size) + case vm.ArrayFloat: + arr = vm.NewFloatArray(size) + case vm.ArrayObject: + arr = vm.NewObjectArray(size) + } + if len(vs) == 2 { + for i := range size { + if err := arr.Set(i, vs[1]); err != nil { + return vm.NIL, err + } + } + } + return arr, nil + } + + s, serr := seqOf(vs[0]) + if serr != nil { + return vm.NIL, serr + } + var vals []vm.Value + for ; s != nil; s = s.Next() { + vals = append(vals, s.First()) + } + var arr *vm.TypedArray + switch kind { + case vm.ArrayByte: + data := make([]byte, len(vals)) + for i, v := range vals { + n, ok := v.(vm.Int) + if !ok { + return vm.NIL, fmt.Errorf("byte-array element must be Int, got %s", v.Type().Name()) + } + data[i] = byte(n) + } + arr = vm.NewByteArrayFrom(data) + case vm.ArrayInt: + data := make([]int64, len(vals)) + for i, v := range vals { + switch n := v.(type) { + case vm.Int: + data[i] = int64(n) + default: + return vm.NIL, fmt.Errorf("int-array element must be Int, got %s", v.Type().Name()) + } + } + arr = vm.NewIntArrayFrom(data) + case vm.ArrayFloat: + data := make([]float64, len(vals)) + for i, v := range vals { + f, ok := vm.ToFloat(v) + if !ok { + return vm.NIL, fmt.Errorf("double-array element must be numeric, got %s", v.Type().Name()) + } + data[i] = f + } + arr = vm.NewFloatArrayFrom(data) + case vm.ArrayObject: + arr = vm.NewObjectArrayFrom(vals) + } + return arr, nil +} + +// --- hoisted native primitives (see cmd/hoist-natives) --- + +//lg:native +//lg:name + +func CorePlus(vs ...vm.Value) (vm.Value, error) { + if len(vs) == 0 { + return vm.MakeInt(0), nil + } + if len(vs) == 1 { + return vs[0], nil + } + acc := vs[0] + for i := 1; i < len(vs); i++ { + var err error + acc, err = vm.NumAdd(acc, vs[i]) + if err != nil { + return vm.NIL, err + } + } + return acc, nil +} + +//lg:native +//lg:name * +func CoreMul(vs ...vm.Value) (vm.Value, error) { + if len(vs) == 0 { + return vm.MakeInt(1), nil + } + if len(vs) == 1 { + return vs[0], nil + } + acc := vs[0] + for i := 1; i < len(vs); i++ { + var err error + acc, err = vm.NumMul(acc, vs[i]) + if err != nil { + return vm.NIL, err + } + } + return acc, nil +} + +//lg:native +//lg:name - +func CoreSub(vs ...vm.Value) (vm.Value, error) { + if len(vs) < 1 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + if len(vs) == 1 { + return vm.NumNeg(vs[0]) + } + acc := vs[0] + for i := 1; i < len(vs); i++ { + var err error + acc, err = vm.NumSub(acc, vs[i]) + if err != nil { + return vm.NIL, err + } + } + return acc, nil +} + +//lg:native +//lg:name / +func CoreDiv(vs ...vm.Value) (vm.Value, error) { + if len(vs) < 1 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + if len(vs) == 1 { + return vm.NumDiv(vm.MakeInt(1), vs[0]) + } + acc := vs[0] + for i := 1; i < len(vs); i++ { + var err error + acc, err = vm.NumDiv(acc, vs[i]) + if err != nil { + return vm.NIL, err + } + } + return acc, nil +} + +//lg:native +//lg:name +' +func CorePlusP(vs ...vm.Value) (vm.Value, error) { + if len(vs) == 0 { + return vm.MakeInt(0), nil + } + if len(vs) == 1 { + return vs[0], nil + } + acc := vs[0] + for i := 1; i < len(vs); i++ { + var err error + acc, err = vm.NumAddP(acc, vs[i]) + if err != nil { + return vm.NIL, err + } + } + return acc, nil +} + +//lg:native +//lg:name *' +func CoreMulP(vs ...vm.Value) (vm.Value, error) { + if len(vs) == 0 { + return vm.MakeInt(1), nil + } + if len(vs) == 1 { + return vs[0], nil + } + acc := vs[0] + for i := 1; i < len(vs); i++ { + var err error + acc, err = vm.NumMulP(acc, vs[i]) + if err != nil { + return vm.NIL, err + } + } + return acc, nil +} + +//lg:native +//lg:name -' +func CoreSubP(vs ...vm.Value) (vm.Value, error) { + if len(vs) < 1 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + if len(vs) == 1 { + return vm.NumNegP(vs[0]) + } + acc := vs[0] + for i := 1; i < len(vs); i++ { + var err error + acc, err = vm.NumSubP(acc, vs[i]) + if err != nil { + return vm.NIL, err + } + } + return acc, nil +} + +//lg:native +//lg:name unchecked-add +func CoreUncheckedAdd(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 2 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + a, ok := vm.ToInt(vs[0]) + if !ok { + return vm.NIL, fmt.Errorf("unchecked-add expected integer, got %s", vs[0].Type().Name()) + } + b, ok := vm.ToInt(vs[1]) + if !ok { + return vm.NIL, fmt.Errorf("unchecked-add expected integer, got %s", vs[1].Type().Name()) + } + return vm.MakeInt(int(int64(a) + int64(b))), nil +} + +//lg:native +//lg:name unchecked-subtract +func CoreUncheckedSubtract(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 2 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + a, ok := vm.ToInt(vs[0]) + if !ok { + return vm.NIL, fmt.Errorf("unchecked-subtract expected integer, got %s", vs[0].Type().Name()) + } + b, ok := vm.ToInt(vs[1]) + if !ok { + return vm.NIL, fmt.Errorf("unchecked-subtract expected integer, got %s", vs[1].Type().Name()) + } + return vm.MakeInt(int(int64(a) - int64(b))), nil +} + +//lg:native +//lg:name unchecked-multiply +func CoreUncheckedMultiply(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 2 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + a, ok := vm.ToInt(vs[0]) + if !ok { + return vm.NIL, fmt.Errorf("unchecked-multiply expected integer, got %s", vs[0].Type().Name()) + } + b, ok := vm.ToInt(vs[1]) + if !ok { + return vm.NIL, fmt.Errorf("unchecked-multiply expected integer, got %s", vs[1].Type().Name()) + } + return vm.MakeInt(int(int64(a) * int64(b))), nil +} + +//lg:native +//lg:name unchecked-negate +func CoreUncheckedNegate(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + a, ok := vm.ToInt(vs[0]) + if !ok { + return vm.NIL, fmt.Errorf("unchecked-negate expected integer, got %s", vs[0].Type().Name()) + } + + return vm.MakeInt(int(-int64(a))), nil +} + +//lg:native +//lg:name unchecked-divide-int +func CoreUncheckedDivideInt(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 2 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + a, ok := vm.ToInt(vs[0]) + if !ok { + return vm.NIL, fmt.Errorf("unchecked-divide-int expected integer, got %s", vs[0].Type().Name()) + } + b, ok := vm.ToInt(vs[1]) + if !ok { + return vm.NIL, fmt.Errorf("unchecked-divide-int expected integer, got %s", vs[1].Type().Name()) + } + if b == 0 { + return vm.NIL, fmt.Errorf("divide by zero") + } + + if int64(a) == math.MinInt64 && int64(b) == -1 { + return vm.NIL, fmt.Errorf("integer overflow") + } + return vm.MakeInt(int(int64(a) / int64(b))), nil +} + +//lg:native +//lg:name unchecked-long +func CoreUncheckedLong(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + switch v := vs[0].(type) { + case vm.Int: + return v, nil + case *vm.BigInt: + + mask := new(big.Int).Lsh(big.NewInt(1), 64) + lo := new(big.Int).Mod(v.Val(), mask) + return vm.MakeInt(int(int64(lo.Uint64()))), nil + case vm.Float: + return vm.MakeInt(int(int64(float64(v)))), nil + default: + return vm.NIL, fmt.Errorf("unchecked-long expected integer or float, got %s", vs[0].Type().Name()) + } +} + +//lg:native +//lg:name unchecked-int +func CoreUncheckedInt(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + switch v := vs[0].(type) { + case vm.Int: + return vm.MakeInt(int(int32(int64(v)))), nil + case *vm.BigInt: + + mask := new(big.Int).Lsh(big.NewInt(1), 64) + lo := new(big.Int).Mod(v.Val(), mask) + return vm.MakeInt(int(int32(lo.Uint64()))), nil + case vm.Float: + return vm.MakeInt(int(int32(float64(v)))), nil + default: + return vm.NIL, fmt.Errorf("unchecked-int expected integer or float, got %s", vs[0].Type().Name()) + } +} + +//lg:native +//lg:name unchecked-short +func CoreUncheckedShort(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + switch v := vs[0].(type) { + case vm.Int: + return vm.MakeInt(int(int16(int64(v)))), nil + case *vm.BigInt: + + mask := new(big.Int).Lsh(big.NewInt(1), 64) + lo := new(big.Int).Mod(v.Val(), mask) + return vm.MakeInt(int(int16(lo.Uint64()))), nil + case vm.Float: + return vm.MakeInt(int(int16(float64(v)))), nil + default: + return vm.NIL, fmt.Errorf("unchecked-short expected integer or float, got %s", vs[0].Type().Name()) + } +} + +//lg:native +//lg:name unchecked-byte +func CoreUncheckedByte(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + switch v := vs[0].(type) { + case vm.Int: + return vm.MakeInt(int(int8(int64(v)))), nil + case *vm.BigInt: + + mask := new(big.Int).Lsh(big.NewInt(1), 64) + lo := new(big.Int).Mod(v.Val(), mask) + return vm.MakeInt(int(int8(lo.Uint64()))), nil + case vm.Float: + return vm.MakeInt(int(int8(float64(v)))), nil + default: + return vm.NIL, fmt.Errorf("unchecked-byte expected integer or float, got %s", vs[0].Type().Name()) + } +} + +//lg:native +//lg:name unchecked-char +func CoreUncheckedChar(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + switch v := vs[0].(type) { + case vm.Int: + return vm.Char(rune(uint16(int64(v)))), nil + case *vm.BigInt: + + mask := new(big.Int).Lsh(big.NewInt(1), 64) + lo := new(big.Int).Mod(v.Val(), mask) + return vm.Char(rune(uint16(lo.Uint64()))), nil + case vm.Float: + return vm.Char(rune(uint16(int64(float64(v))))), nil + default: + return vm.NIL, fmt.Errorf("unchecked-char expected integer or float, got %s", vs[0].Type().Name()) + } +} + +//lg:native +//lg:name unchecked-double +func CoreUncheckedDouble(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + switch v := vs[0].(type) { + case vm.Int: + return vm.Float(float64(int64(v))), nil + case *vm.BigInt: + + f, _ := new(big.Float).SetInt(v.Val()).Float64() + return vm.Float(f), nil + case vm.Float: + return v, nil + default: + return vm.NIL, fmt.Errorf("unchecked-double expected numeric, got %s", vs[0].Type().Name()) + } +} + +//lg:native +//lg:name unchecked-float +func CoreUncheckedFloat(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + switch v := vs[0].(type) { + case vm.Int: + + return vm.Float(float64(float32(int64(v)))), nil + case *vm.BigInt: + f, _ := new(big.Float).SetInt(v.Val()).Float64() + return vm.Float(float64(float32(f))), nil + case vm.Float: + return vm.Float(float64(float32(float64(v)))), nil + default: + return vm.NIL, fmt.Errorf("unchecked-float expected numeric, got %s", vs[0].Type().Name()) + } +} + +//lg:native +//lg:name mod +func CoreMod(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 2 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + return vm.NumMod(vs[0], vs[1]) +} + +//lg:native +//lg:name abs +func CoreAbs(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + return vm.NumAbs(vs[0]) +} + +//lg:native +//lg:name not +func CoreNot(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + return builtins.Not(vs[0]) +} + +//lg:native +//lg:name complement +func CoreComplement(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + f, ok := vm.AsFn(vs[0]) + if !ok { + return vm.NIL, fmt.Errorf("complement expected Fn") + } + + wrapped := vm.NewCtxNativeFn("complemented-fn", func(cec *vm.ExecContext, args []vm.Value) (vm.Value, error) { + v, err := cec.Invoke(f, args) + if err != nil { + return vm.NIL, err + } + return vm.Boolean(!vm.IsTruthy(v)), nil + }) + return wrapped, nil +} + +//lg:native +//lg:name set-macro! +func CoreSetMacro(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + m := vs[0].(*vm.Var) + m.SetMacro() + return m, nil +} + +//lg:native +//lg:name gensym +func CoreGensym(vs ...vm.Value) (vm.Value, error) { + prefix := "G__" + if len(vs) == 1 { + arg, ok := vs[0].(vm.String) + if !ok { + return vm.NIL, fmt.Errorf("gensym expected String") + } + prefix = string(arg) + } + return vm.Symbol(fmt.Sprintf("%s%d", prefix, nextID())), nil +} + +//lg:native +//lg:name vector +func CoreVector(vs ...vm.Value) (vm.Value, error) { + return builtins.Vector(vs...) +} + +//lg:native +//lg:name hash-map +func CoreHashMap(vs ...vm.Value) (vm.Value, error) { + if len(vs)%2 != 0 { + return vm.NIL, fmt.Errorf("hash-map requires an even number of arguments, got %d", len(vs)) + } + return vm.NewMap(vs), nil +} + +//lg:native +//lg:name array-map +func CoreArrayMap(vs ...vm.Value) (vm.Value, error) { + if len(vs)%2 != 0 { + return vm.NIL, fmt.Errorf("array-map requires an even number of arguments, got %d", len(vs)) + } + return vm.NewArrayMap(vs), nil +} + +//lg:native +//lg:name sorted-map +func CoreSortedMap(vs ...vm.Value) (vm.Value, error) { + if len(vs)%2 != 0 { + return vm.NIL, fmt.Errorf("sorted-map requires even number of arguments, got %d", len(vs)) + } + return vm.NewSortedMap(nil, vs), nil +} + +//lg:native +//lg:name sorted-set +func CoreSortedSet(vs ...vm.Value) (vm.Value, error) { + return vm.NewSortedSet(nil, vs), nil +} + +//lg:native +//lg:name sorted-map-by +func CoreSortedMapBy(vs ...vm.Value) (vm.Value, error) { + if len(vs) < 1 { + return vm.NIL, fmt.Errorf("sorted-map-by requires a comparator") + } + comp, ok := vm.AsFn(vs[0]) + if !ok { + return vm.NIL, fmt.Errorf("sorted-map-by first arg must be a function") + } + kvs := vs[1:] + if len(kvs)%2 != 0 { + return vm.NIL, fmt.Errorf("sorted-map-by requires even number of key-value arguments") + } + return vm.NewSortedMap(fnComparator(comp), kvs), nil +} + +//lg:native +//lg:name sorted-set-by +func CoreSortedSetBy(vs ...vm.Value) (vm.Value, error) { + if len(vs) < 1 { + return vm.NIL, fmt.Errorf("sorted-set-by requires a comparator") + } + comp, ok := vm.AsFn(vs[0]) + if !ok { + return vm.NIL, fmt.Errorf("sorted-set-by first arg must be a function") + } + return vm.NewSortedSet(fnComparator(comp), vs[1:]), nil +} + +//lg:native +//lg:name chunk-first +func CoreChunkFirst(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("chunk-first: wrong number of arguments %d", len(vs)) + } + cs, err := asChunked(vs[0], "chunk-first") + if err != nil { + return vm.NIL, err + } + return cs.ChunkedFirst().(vm.Value), nil +} + +//lg:native +//lg:name chunk-rest +func CoreChunkRest(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("chunk-rest: wrong number of arguments %d", len(vs)) + } + cs, err := asChunked(vs[0], "chunk-rest") + if err != nil { + return vm.NIL, err + } + m := cs.ChunkedMore() + if m == nil { + return vm.EmptyList, nil + } + return m.(vm.Value), nil +} + +//lg:native +//lg:name chunk-next +func CoreChunkNext(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("chunk-next: wrong number of arguments %d", len(vs)) + } + cs, err := asChunked(vs[0], "chunk-next") + if err != nil { + return vm.NIL, err + } + n := cs.ChunkedNext() + if n == nil { + return vm.NIL, nil + } + return n.(vm.Value), nil +} + +//lg:native +//lg:name chunk-cons +func CoreChunkConsF(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 2 { + return vm.NIL, fmt.Errorf("chunk-cons: wrong number of arguments %d", len(vs)) + } + chunk, ok := vs[0].(vm.IChunk) + if !ok { + return vm.NIL, fmt.Errorf("chunk-cons: first arg must be a chunk") + } + var tail vm.Seq + if vs[1] != vm.NIL { + s, err := seqOf(vs[1]) + if err != nil { + return vm.NIL, fmt.Errorf("chunk-cons: second arg must be a seq or nil") + } + tail = s + } + out := vm.ConsChunk(chunk, tail) + if out == nil { + return vm.EmptyList, nil + } + return out.(vm.Value), nil +} + +//lg:native +//lg:name chunked-seq? +func CoreChunkedSeqP(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("chunked-seq?: wrong number of arguments %d", len(vs)) + } + if vs[0] == vm.NIL { + return vm.FALSE, nil + } + s, err := seqOf(vs[0]) + if err != nil || s == nil { + return vm.FALSE, nil + } + _, ok := vm.AsChunkedSeq(s) + return vm.Boolean(ok), nil +} + +//lg:native +//lg:name chunk-buffer +func CoreChunkBufferF(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("chunk-buffer: wrong number of arguments %d", len(vs)) + } + n, ok := vs[0].(vm.Int) + if !ok { + return vm.NIL, fmt.Errorf("chunk-buffer: arg must be Int") + } + return vm.NewChunkBuffer(int(n)), nil +} + +//lg:native +//lg:name chunk-append +func CoreChunkAppendF(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 2 { + return vm.NIL, fmt.Errorf("chunk-append: wrong number of arguments %d", len(vs)) + } + b, ok := vs[0].(*vm.ChunkBuffer) + if !ok { + return vm.NIL, fmt.Errorf("chunk-append: first arg must be a chunk-buffer") + } + b.Append(vs[1]) + return b, nil +} + +//lg:native +//lg:name chunk +func CoreChunkF(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("chunk: wrong number of arguments %d", len(vs)) + } + b, ok := vs[0].(*vm.ChunkBuffer) + if !ok { + return vm.NIL, fmt.Errorf("chunk: arg must be a chunk-buffer") + } + return b.Chunk().(vm.Value), nil +} + +//lg:native +//lg:name range +func CoreRangef(vs ...vm.Value) (vm.Value, error) { + if len(vs) == 0 { + + return vm.NewInfiniteRange(0, 1), nil + } + if len(vs) > 3 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + var start, end, step vm.Int + step = 1 + var err error + var endArg vm.Value + switch len(vs) { + case 1: + endArg = vs[0] + case 2: + endArg = vs[1] + if start, err = rangeInt(vs[0], "start"); err != nil { + return vm.NIL, err + } + case 3: + endArg = vs[1] + if start, err = rangeInt(vs[0], "start"); err != nil { + return vm.NIL, err + } + if step, err = rangeInt(vs[2], "step"); err != nil { + return vm.NIL, err + } + } + + if f, ok := endArg.(vm.Float); ok { + if math.IsInf(float64(f), 0) { + if (f > 0 && step > 0) || (f < 0 && step < 0) { + return vm.NewInfiniteRange(int(start), int(step)), nil + } + return vm.NewRange(0, 0, 1), nil + } + if step > 0 { + endArg = vm.Int(math.Ceil(float64(f))) + } else { + endArg = vm.Int(math.Floor(float64(f))) + } + } + if end, err = rangeInt(endArg, "end"); err != nil { + return vm.NIL, err + } + return vm.NewRange(start, end, step), nil +} + +//lg:native +//lg:name keyword +func CoreKeyword(vs ...vm.Value) (vm.Value, error) { + if len(vs) < 1 || len(vs) > 2 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + if len(vs) == 2 { + // (keyword ns name) — both must be strings (or nil ns) + var nsStr, nameStr string + if vs[0] != vm.NIL { + switch n := vs[0].(type) { + case vm.String: + nsStr = string(n) + default: + return vm.NIL, fmt.Errorf("keyword namespace must be a string, got %s", vs[0].Type()) + } + } + switch n := vs[1].(type) { + case vm.String: + nameStr = string(n) + default: + return vm.NIL, fmt.Errorf("keyword name must be a string, got %s", vs[1].Type()) + } + if nsStr == "" && vs[0] == vm.NIL { + return vm.Keyword(nameStr), nil + } + return vm.Keyword(nsStr + "/" + nameStr), nil + } + if vs[0] == vm.NIL { + return vm.NIL, nil + } + if k, ok := vs[0].(vm.Keyword); ok { + return k, nil + } + if k, ok := vs[0].(vm.Symbol); ok { + return vm.Keyword(k), nil + } + if k, ok := vs[0].(vm.String); ok { + return vm.Keyword(k), nil + } + return vm.NIL, fmt.Errorf("keyword expects keyword, symbol, or string, got %s", vs[0].Type()) +} + +//lg:native +//lg:name symbol +func CoreSymbolf(vs ...vm.Value) (vm.Value, error) { + if len(vs) < 1 || len(vs) > 2 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + toStr := func(v vm.Value) (string, bool) { + switch s := v.(type) { + case vm.String: + return string(s), true + case vm.Symbol: + return string(s), true + case vm.Keyword: + return string(s), true + default: + return "", false + } + } + if len(vs) == 1 { + if vs[0] == vm.NIL { + return vm.NIL, fmt.Errorf("symbol expected String, Symbol, Keyword, or Var") + } + if v, ok := vs[0].(*vm.Var); ok { + return vm.Symbol(externalNSName(v.NS()) + "/" + v.VarName()), nil + } + if s, ok := toStr(vs[0]); ok { + return vm.Symbol(s), nil + } + return vm.NIL, fmt.Errorf("symbol expected String or Symbol") + } + nsStr := "" + if vs[0] != vm.NIL { + ns, ok := vs[0].(vm.String) + if !ok { + return vm.NIL, fmt.Errorf("symbol expected String namespace") + } + nsStr = string(ns) + } + name, ok := vs[1].(vm.String) + if !ok { + return vm.NIL, fmt.Errorf("symbol expected String name") + } + nameStr := string(name) + if nsStr == "" && vs[0] == vm.NIL { + return vm.Symbol(nameStr), nil + } + return vm.Symbol(nsStr + "/" + nameStr), nil +} + +//lg:native +//lg:name assoc +func CoreAssoc(vs ...vm.Value) (vm.Value, error) { + if len(vs) < 3 || len(vs)%2 == 0 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + coll, ok := vs[0].(vm.Associative) + if !ok { + return vm.NIL, fmt.Errorf("assoc expected Associative") + } + ret := coll + for i := 1; i < len(vs); i += 2 { + ret = ret.Assoc(vs[i], vs[i+1]) + if ret == vm.NIL { + return vm.NIL, fmt.Errorf("assoc failed for key %s", vs[i].String()) + } + } + return ret, nil +} + +//lg:native +//lg:name dissoc +func CoreDissoc(vs ...vm.Value) (vm.Value, error) { + if len(vs) == 0 { + return vm.NIL, fmt.Errorf("wrong number of arguments 0") + } + if len(vs) == 1 { + return vs[0], nil + } + coll, ok := vs[0].(vm.Associative) + if !ok { + return vm.NIL, fmt.Errorf("dissoc expected Associative") + } + ret := coll + for i := 1; i < len(vs); i++ { + ret = ret.Dissoc(vs[i]) + if vs[0] != vm.NIL && ret == vm.NIL { + return vm.NIL, fmt.Errorf("dissoc failed for key %s", vs[i].String()) + } + } + return ret, nil +} + +//lg:native +//lg:name cons +func CoreCons(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 2 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + return builtins.Cons(vs[0], vs[1]) +} + +//lg:native +//lg:name disj +func CoreDisj(vs ...vm.Value) (vm.Value, error) { + if len(vs) < 1 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + if vs[0] == vm.NIL { + return vm.NIL, nil + } + if len(vs) == 1 { + return vs[0], nil + } + switch s := vs[0].(type) { + case *vm.PersistentSet: + result := s + for _, v := range vs[1:] { + result = result.Disj(v) + } + return result, nil + case *vm.SortedSet: + result := s + for _, v := range vs[1:] { + result = result.Disj(v) + } + return result, nil + case vm.Set: + for _, v := range vs[1:] { + s = s.Disj(v) + } + return s, nil + default: + return vm.NIL, fmt.Errorf("disj expected Set") + } +} + +//lg:native +//lg:name contains? +func CoreContains(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 2 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + return builtins.Contains(vs[0], vs[1]) +} + +//lg:native +//lg:name second +func CoreSecond(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + if vs[0] == vm.NIL { + return vm.NIL, nil + } + + if av, ok := vs[0].(vm.ArrayVector); ok { + if len(av) < 2 { + return vm.NIL, nil + } + return av[1], nil + } + seq, err := seqOf(vs[0]) + if err != nil { + return vm.NIL, fmt.Errorf("second expected Seq") + } + if seq == nil { + return vm.NIL, nil + } + n := seq.Next() + if n == nil { + return vm.NIL, nil + } + return n.First(), nil +} + +//lg:native +//lg:name list? +func CoreIsList(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + _, ok := vs[0].(*vm.List) + return vm.Boolean(ok), nil +} + +//lg:native +//lg:name empty +func CoreEmpty(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + if vs[0] == vm.NIL || vs[0].Type() == vm.StringType { + return vm.NIL, nil + } + if _, ok := vs[0].(*vm.InfiniteRange); ok { + return vm.EmptyList, nil + } + if _, ok := vs[0].(*vm.Record); ok { + return vm.NIL, fmt.Errorf("empty is not supported on records") + } + coll, ok := vs[0].(vm.Collection) + if !ok { + return vm.NIL, nil + } + return coll.Empty(), nil +} + +//lg:native +//lg:name key +func CoreKeyf(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + if e, ok := vs[0].(vm.MapEntry); ok { + return e.Key, nil + } + return vm.NIL, fmt.Errorf("key expects map entry") +} + +//lg:native +//lg:name val +func CoreValf(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + if e, ok := vs[0].(vm.MapEntry); ok { + return e.Value, nil + } + return vm.NIL, fmt.Errorf("val expects map entry") +} + +//lg:native +//lg:name count +func CoreCount(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + if vs[0] == vm.NIL { + return vm.MakeInt(0), nil + } + if s, ok := vs[0].(vm.String); ok { + return vm.MakeInt(len([]rune(string(s)))), nil + } + seq, ok := vs[0].(vm.Counted) + if !ok { + return vm.NIL, fmt.Errorf("count expected Counted") + } + return seq.Count(), nil +} + +//lg:native +//lg:name exclude-in-current-ns +func CoreExcludeInCurrentNs(vs ...vm.Value) (vm.Value, error) { + cns := CurrentNS.Deref().(*vm.Namespace) + for _, v := range vs { + sym, ok := v.(vm.Symbol) + if !ok { + return vm.NIL, fmt.Errorf("exclude-in-current-ns expected Symbol, got %s", v.Type().Name()) + } + cns.Exclude(string(sym)) + } + return vm.NIL, nil +} + +//lg:native +//lg:name use +func CoreUse(vs ...vm.Value) (vm.Value, error) { + if len(vs) < 1 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + cns := CurrentNS.Deref().(*vm.Namespace) + for i := range vs { + s, ok := vs[i].(vm.Symbol) + if !ok { + return vm.NIL, fmt.Errorf("use expected Symbol") + } + cns.Refer(NS(string(s)), "", true) + } + return vm.NIL, nil +} + +//lg:native +//lg:name alias +func CoreAliasf(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 2 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + al, ok := vs[0].(vm.Symbol) + if !ok { + return vm.NIL, fmt.Errorf("alias expected Symbol") + } + nsSym, ok := vs[1].(vm.Symbol) + if !ok { + return vm.NIL, fmt.Errorf("alias expected Symbol") + } + cns := CurrentNS.Deref().(*vm.Namespace) + target := NS(string(nsSym)) + cns.Alias(al, target) + return vm.NIL, nil +} + +//lg:native +//lg:name refer-list +func CoreReferList(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 2 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + nsSym, ok := vs[0].(vm.Symbol) + if !ok { + return vm.NIL, fmt.Errorf("refer-list expected ns Symbol") + } + arr, ok := vs[1].(vm.ArrayVector) + if !ok { + return vm.NIL, fmt.Errorf("refer-list expected vector of Symbols") + } + syms := make([]vm.Symbol, 0, len(arr)) + for i := range arr { + if s, ok := arr[i].(vm.Symbol); ok { + syms = append(syms, s) + } + } + cns := CurrentNS.Deref().(*vm.Namespace) + target := NS(string(nsSym)) + + vmSyms := make([]vm.Symbol, len(syms)) + copy(vmSyms, syms) + cns.ReferList(target, vmSyms) + return vm.NIL, nil +} + +//lg:native +//lg:name . +func CoreMethodInvoke(vs ...vm.Value) (vm.Value, error) { + if len(vs) < 2 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + name, ok := vs[1].(vm.Symbol) + if !ok { + return vm.NIL, fmt.Errorf("method-invoke expected Symbol") + } + rec, ok := vs[0].(vm.Receiver) + if !ok { + return invokeMethodFallback(vs[0], name, vs[2:], fmt.Errorf("method-invoke expected Receiver")) + } + result, err := rec.InvokeMethod(name, vs[2:]) + if err == nil { + return result, nil + } + return invokeMethodFallback(rec, name, vs[2:], err) +} + +//lg:native +//lg:name register-host-method! +func CoreRegisterHostMethod(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 3 { + return vm.NIL, fmt.Errorf("register-host-method! expected 3 arguments, got %d", len(vs)) + } + t, ok := vs[0].(vm.ValueType) + if !ok { + return vm.NIL, fmt.Errorf("register-host-method! expected a type, got %s", vs[0].Type().Name()) + } + name, ok := vs[1].(vm.Symbol) + if !ok { + return vm.NIL, fmt.Errorf("register-host-method! expected a Symbol method name") + } + fn, ok := vs[2].(vm.Fn) + if !ok { + return vm.NIL, fmt.Errorf("register-host-method! expected a fn") + } + RegisterHostMethod(t, name, fn) + return vm.NIL, nil +} + +//lg:native +//lg:name register-host-class! +func CoreRegisterHostClass(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 2 { + return vm.NIL, fmt.Errorf("register-host-class! expected 2 arguments, got %d", len(vs)) + } + name, ok := vs[0].(vm.String) + if !ok { + return vm.NIL, fmt.Errorf("register-host-class! expected a String class name") + } + RegisterHostClass(string(name), vs[1]) + return vm.NIL, nil +} + +//lg:native +//lg:name concat* +func CoreConcat(vs ...vm.Value) (vm.Value, error) { + + presize := 0 + for i := range vs { + if av, ok := vs[i].(vm.ArrayVector); ok { + presize += len(av) + } + } + ret := make([]vm.Value, 0, presize) + for i := range vs { + if vs[i] == vm.NIL { + continue + } + + if av, ok := vs[i].(vm.ArrayVector); ok { + ret = append(ret, av...) + continue + } + vseq, err := seqOf(vs[i]) + if err != nil { + return vm.NIL, fmt.Errorf("concat expected Seq") + } + ret = appendSeqValues(ret, forceSeq(vseq)) + } + r, err := vm.ListType.Box(ret) + if err != nil { + return vm.NIL, fmt.Errorf("concat failed: %w", err) + } + return r, nil +} + +//lg:native +//lg:name slurp +func CoreSlurp(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + filename, ok := vs[0].(vm.String) + if !ok { + return vm.NIL, fmt.Errorf("slurp expected String") + } + data, err := os.ReadFile(string(filename)) + if err != nil { + return vm.NIL, fmt.Errorf("slurp failed: %w", err) + } + return vm.String(data), nil +} + +//lg:native +//lg:name spit +func CoreSpit(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 2 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + filename, ok := vs[0].(vm.String) + if !ok { + return vm.NIL, fmt.Errorf("spit expected String") + } + contents, ok := asBytes(vs[1]) + if !ok { + return vm.NIL, fmt.Errorf("spit expected String or byte-array") + } + err := os.WriteFile(string(filename), contents, 0644) + if err != nil { + return vm.NIL, fmt.Errorf("spit failed: %w", err) + } + return vm.NIL, nil +} + +//lg:native +//lg:name atom +func CoreAtom(vs ...vm.Value) (vm.Value, error) { + if len(vs) < 1 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + if (len(vs)-1)%2 != 0 { + return vm.NIL, fmt.Errorf("atom options must be key/value pairs") + } + var meta vm.Value + var validator vm.Fn + for i := 1; i < len(vs); i += 2 { + switch vs[i] { + case vm.Keyword("meta"): + if vs[i+1] != vm.NIL && !isMapType(vs[i+1]) { + return vm.NIL, fmt.Errorf("atom :meta must be nil or map") + } + meta = vs[i+1] + case vm.Keyword("validator"): + if vs[i+1] == vm.NIL { + validator = nil + continue + } + fn, ok := vm.AsFn(vs[i+1]) + if !ok { + return vm.NIL, fmt.Errorf("atom :validator must be nil or function") + } + validator = fn + } + } + return vm.NewAtomWithMetaValidator(vs[0], meta, validator) +} + +//lg:native +//lg:name reset! +func CoreReset(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 2 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + at, ok := vs[0].(*vm.Atom) + if !ok { + return vm.NIL, fmt.Errorf("reset expected Atom") + } + return at.Reset(vs[1]) +} + +//lg:native +//lg:name compare-and-set! +func CoreCompareAndSet(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 3 { + return vm.NIL, fmt.Errorf("compare-and-set! expected 3 arguments, got %d", len(vs)) + } + at, ok := vs[0].(*vm.Atom) + if !ok { + return vm.NIL, fmt.Errorf("compare-and-set! expected Atom") + } + swapped, err := at.CompareAndSet(vs[1], vs[2]) + if err != nil { + return vm.NIL, err + } + if swapped { + return vm.TRUE, nil + } + return vm.FALSE, nil +} + +//lg:native +//lg:name reset-vals! +func CoreResetVals(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 2 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + at, ok := vs[0].(*vm.Atom) + if !ok { + return vm.NIL, fmt.Errorf("reset-vals! expected Atom") + } + old := at.Deref() + if _, err := at.Reset(vs[1]); err != nil { + return vm.NIL, err + } + return vm.ArrayVector{old, vs[1]}, nil +} + +//lg:native +//lg:name chan +func CoreChanf(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 0 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + return make(vm.Chan), nil +} + +//lg:native +//lg:name scope-close! +func CoreScopeClose(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 2 { + return vm.NIL, fmt.Errorf("scope-close! expects 2 arguments (scope timeout-ms)") + } + s, ok := vs[0].(*vm.Scope) + if !ok { + return vm.NIL, fmt.Errorf("scope-close! expected a scope") + } + ms, ok := vs[1].(vm.Int) + if !ok { + return vm.NIL, fmt.Errorf("scope-close! expected an integer timeout-ms") + } + vm.CloseScoped(s, time.Duration(int64(ms))*time.Millisecond) + return vm.NIL, nil +} + +//lg:native +//lg:name scope-live +func CoreScopeLive(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("scope-live expects 1 argument") + } + s, ok := vs[0].(*vm.Scope) + if !ok { + return vm.NIL, fmt.Errorf("scope-live expected a scope") + } + return vm.Int(s.LiveTree()), nil +} + +//lg:native +//lg:name scope? +func CoreScopeQmark(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("scope? expects 1 argument") + } + if _, ok := vs[0].(*vm.Scope); ok { + return vm.TRUE, nil + } + return vm.FALSE, nil +} + +//lg:native +//lg:name max +func CoreMax(vs ...vm.Value) (vm.Value, error) { + if len(vs) < 1 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + m := vs[0] + if isNaNValue(m) { + return m, nil + } + for i := 1; i < len(vs); i++ { + if isNaNValue(vs[i]) { + return vs[i], nil + } + gt, err := vm.NumGt(vs[i], m) + if err != nil { + return vm.NIL, err + } + if gt { + m = vs[i] + } + } + return m, nil +} + +//lg:native +//lg:name min +func CoreMin(vs ...vm.Value) (vm.Value, error) { + if len(vs) < 1 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + m := vs[0] + if isNaNValue(m) { + return m, nil + } + for i := 1; i < len(vs); i++ { + if isNaNValue(vs[i]) { + return vs[i], nil + } + lt, err := vm.NumLt(vs[i], m) + if err != nil { + return vm.NIL, err + } + if lt { + m = vs[i] + } + } + return m, nil +} + +//lg:native +//lg:name str-replace +func CoreStrReplace(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 3 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + s, ok := vs[0].(vm.String) + if !ok { + return vm.NIL, fmt.Errorf("str-replace expected String") + } + + if fn, isFn := vs[2].(vm.Fn); isFn { + switch m := vs[1].(type) { + case *vm.Regex: + out, err := m.ReplaceAllFunc(string(s), strReplaceCallback(fn)) + if err != nil { + return vm.NIL, err + } + return vm.String(out), nil + case vm.String: + return literalReplaceFn(string(m), string(s), fn, false) + default: + return vm.NIL, fmt.Errorf("str-replace expected String or Regex") + } + } + r, ok := vs[2].(vm.String) + if !ok { + return vm.NIL, fmt.Errorf("str-replace expected String") + } + switch vs[1].(type) { + case vm.String: + return vm.String(strings.ReplaceAll(string(s), string(vs[1].(vm.String)), string(r))), nil + case *vm.Regex: + out, err := vs[1].(*vm.Regex).ReplaceAll(string(s), string(r)) + if err != nil { + return vm.NIL, err + } + return vm.String(out), nil + default: + return vm.NIL, fmt.Errorf("str-replace expected String or Regex") + } +} + +//lg:native +//lg:name long +func CoreLongf(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + const minInt64 = float64(-9223372036854775808) + const maxInt64 = float64(9223372036854775807) + coerce := func(f float64) (vm.Value, error) { + if f < minInt64 || f > maxInt64 { + return vm.NIL, fmt.Errorf("%s can't be coerced to long", vs[0]) + } + return vm.Int(int64(math.Trunc(f))), nil + } + switch v := vs[0].(type) { + case vm.Int: + return v, nil + case vm.Float: + return coerce(float64(v)) + case vm.Char: + return vm.Int(int(v)), nil + case *vm.BigInt: + if !v.Val().IsInt64() { + return vm.NIL, fmt.Errorf("%s can't be coerced to long", vs[0]) + } + return vm.Int(v.Val().Int64()), nil + case *vm.BigDecimal: + f, _ := v.Val().Float64() + return coerce(f) + case *vm.Ratio: + f, _ := v.Val().Float64() + return coerce(f) + case vm.Boolean: + if bool(v) { + return vm.MakeInt(1), nil + } + return vm.MakeInt(0), nil + default: + return vm.NIL, fmt.Errorf("%s can't be coerced to long", vs[0]) + } +} + +//lg:native +//lg:name float +func CoreFloatf(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + f, ok := vm.ToFloat(vs[0]) + if !ok { + return vm.NIL, fmt.Errorf("%s can't be coerced to float", vs[0]) + } + if math.IsInf(f, 0) { + return vm.NIL, fmt.Errorf("%s can't be coerced to float", vs[0]) + } + f32 := float32(f) + if math.IsInf(float64(f32), 0) { + return vm.NIL, fmt.Errorf("%s can't be coerced to float", vs[0]) + } + return vm.Float32(float64(f32)), nil +} + +//lg:native +//lg:name double +func CoreDoublef(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + f, ok := vm.ToFloat(vs[0]) + if !ok { + return vm.NIL, fmt.Errorf("%s can't be coerced to double", vs[0]) + } + return vm.Float(f), nil +} + +//lg:native +//lg:name number? +func CoreIsNumber(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + return vm.Boolean(vm.IsNumber(vs[0])), nil +} + +//lg:native +//lg:name float? +func CoreIsFloat(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + switch vs[0].(type) { + case vm.Float, vm.Float32: + return vm.TRUE, nil + } + ok := false + return vm.Boolean(ok), nil +} + +//lg:native +//lg:name int? +func CoreIsInt(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + _, ok := vs[0].(vm.Int) + return vm.Boolean(ok), nil +} + +//lg:native +//lg:name char +func CoreChar(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("wrong number of arguments") + } + switch v := vs[0].(type) { + case vm.Int: + if int(v) < 0 || int(v) > 0x10FFFF { + return vm.NIL, fmt.Errorf("value out of range for char: %d", v) + } + return vm.Char(rune(v)), nil + case vm.Char: + return v, nil + case vm.String: + runes := []rune(string(v)) + if len(runes) == 1 { + return vm.Char(runes[0]), nil + } + return vm.NIL, fmt.Errorf("%s can't be coerced to char", vs[0]) + case *vm.BigInt: + n := v.Unbox().(*big.Int).Int64() + if n < 0 || n > 0x10FFFF { + return vm.NIL, fmt.Errorf("value out of range for char: %d", n) + } + return vm.Char(rune(n)), nil + default: + return vm.NIL, fmt.Errorf("%s can't be coerced to char", vs[0]) + } +} + +//lg:native +//lg:name re-pattern +func CoreRegex(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + + if r, ok := vs[0].(*vm.Regex); ok { + return r, nil + } + if s, ok := vs[0].(vm.String); ok { + return vm.NewRegex(string(s)) + } + return vm.NIL, fmt.Errorf("regex expected String") +} + +//lg:native +//lg:name peek +func CorePeek(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + if vs[0] == vm.NIL { + return vm.NIL, nil + } + switch v := vs[0].(type) { + case vm.ArrayVector: + if len(v) == 0 { + return vm.NIL, nil + } + return v[len(v)-1], nil + case vm.PersistentVector: + if v.RawCount() == 0 { + return vm.NIL, nil + } + return v.ValueAt(vm.Int(v.RawCount() - 1)), nil + case *vm.List: + if v == vm.EmptyList { + return vm.NIL, nil + } + return v.First(), nil + case *vm.PersistentQueue: + return v.Peek(), nil + default: + return vm.NIL, fmt.Errorf("peek not supported on %s", vs[0].Type()) + } +} + +//lg:native +//lg:name pop +func CorePop(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + if vs[0] == vm.NIL { + return vm.NIL, nil + } + switch vs[0].(type) { + case vm.PersistentVector: + v := vs[0].(vm.PersistentVector) + if v.RawCount() < 1 { + return vm.NIL, fmt.Errorf("can't pop empty vector") + } + + return v.Pop(), nil + case vm.ArrayVector: + v := vs[0].(vm.ArrayVector) + if v.RawCount() < 1 { + return vm.NIL, fmt.Errorf("can't pop empty vector") + } + return vm.ArrayVector(v[0 : len(v)-1]), nil + case vm.Seq: + s := vs[0].(vm.Seq) + + if s == vm.EmptyList { + return vm.NIL, fmt.Errorf("can't pop empty seq") + } + if c, ok := vs[0].(vm.Counted); ok && c.RawCount() == 0 { + return vm.NIL, fmt.Errorf("can't pop empty seq") + } + return s.More(), nil + case *vm.PersistentQueue: + return vs[0].(*vm.PersistentQueue).Pop(), nil + default: + return vm.NIL, fmt.Errorf("pop expected Seq or Vec") + } +} + +//lg:native +//lg:name iterate +func CoreIterate(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 2 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + f, ok := vm.AsFn(vs[0]) + if !ok { + return vm.NIL, fmt.Errorf("iterate expected a function") + } + return vm.NewIterate(f, vs[1]), nil +} + +//lg:native +//lg:name repeat +func CoreRepeat(vs ...vm.Value) (vm.Value, error) { + if len(vs) < 1 || len(vs) > 2 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + if len(vs) == 1 { + return vm.NewRepeat(vs[0], -1), nil + } + if _, ok := vs[0].(vm.Boolean); ok { + return vm.NIL, fmt.Errorf("repeat expected an Int") + } + ni, ok := vm.ToInt(vs[0]) + if !ok { + return vm.NIL, fmt.Errorf("repeat expected an Int") + } + n := vm.Int(ni) + if int(n) <= 0 { + return vm.EmptyList, nil + } + return vm.NewRepeat(vs[1], int(n)), nil +} + +//lg:native +//lg:name refer +func CoreRefer(vs ...vm.Value) (vm.Value, error) { + if len(vs) < 2 || len(vs) > 3 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + cns := CurrentNS.Deref().(*vm.Namespace) + s, ok := vs[0].(vm.Symbol) + if !ok { + return vm.NIL, fmt.Errorf("refer expected Symbol") + } + alias := "" + if len(vs) > 1 { + if str, ok := vs[1].(vm.String); ok { + alias = string(str) + } + } + all := true + if len(vs) > 2 { + if b, ok := vs[2].(vm.Boolean); ok { + all = bool(b) + } + } + cns.Refer(NS(string(s)), alias, all) + return vm.NIL, nil +} + +//lg:native +//lg:name format +func CoreFormatf(vs ...vm.Value) (vm.Value, error) { + if len(vs) < 1 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + fmtStr, ok := vs[0].(vm.String) + if !ok { + return vm.NIL, fmt.Errorf("format expected String") + } + fmts := string(fmtStr) + args := make([]any, len(vs)-1) + + vi := 0 + for fi := 0; fi < len(fmts) && vi < len(args); fi++ { + if fmts[fi] != '%' { + continue + } + fi++ + if fi >= len(fmts) { + break + } + if fmts[fi] == '%' { + continue + } + + for fi < len(fmts) && (fmts[fi] == '-' || fmts[fi] == '+' || fmts[fi] == ' ' || fmts[fi] == '0' || fmts[fi] == '#' || (fmts[fi] >= '0' && fmts[fi] <= '9') || fmts[fi] == '.') { + fi++ + } + if fi >= len(fmts) { + break + } + verb := fmts[fi] + switch v := vs[vi+1].(type) { + case vm.Int: + if verb == 'f' || verb == 'e' || verb == 'g' || verb == 'E' || verb == 'G' { + args[vi] = float64(v) + } else { + args[vi] = int(v) + } + case vm.Float: + args[vi] = float64(v) + case vm.String: + args[vi] = string(v) + case vm.Boolean: + args[vi] = bool(v) + default: + args[vi] = vs[vi+1].Unbox() + } + vi++ + } + return vm.String(fmt.Sprintf(string(fmtStr), args...)), nil +} + +//lg:native +//lg:name rand +func CoreRandf(vs ...vm.Value) (vm.Value, error) { + if len(vs) == 0 { + return vm.Float(rngFloat64()), nil + } + if len(vs) == 1 { + if n, ok := vs[0].(vm.Int); ok { + return vm.Float(rngFloat64() * float64(n)), nil + } + if n, ok := vs[0].(vm.Float); ok { + return vm.Float(rngFloat64() * float64(n)), nil + } + return vm.NIL, fmt.Errorf("rand expected number") + } + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) +} + +//lg:native +//lg:name rand-int +func CoreRandInt(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + n, ok := vs[0].(vm.Int) + if !ok { + return vm.NIL, fmt.Errorf("rand-int expected Int") + } + if int(n) <= 0 { + return vm.MakeInt(0), nil + } + return vm.MakeInt(rngIntn(int(n))), nil +} + +//lg:native +//lg:name rand-nth +func CoreRandNth(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + if vs[0] == vm.NIL { + return vm.NIL, nil + } + coll, ok := vs[0].(vm.Collection) + if !ok { + return vm.NIL, fmt.Errorf("rand-nth expected Collection") + } + n := coll.RawCount() + if n == 0 { + return vm.NIL, fmt.Errorf("rand-nth called on empty collection") + } + idx := rngIntn(n) + if l, ok := vs[0].(vm.Lookup); ok { + return l.ValueAt(vm.Int(idx)), nil + } + + s, _ := seqOf(vs[0]) + for range idx { + s = s.Next() + } + return s.First(), nil +} + +//lg:native +//lg:name shuffle +func CoreShuffle(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + if vs[0] == vm.NIL { + return vm.NIL, fmt.Errorf("shuffle not supported on nil") + } + switch vs[0].(type) { + case vm.String: + return vm.NIL, fmt.Errorf("shuffle not supported on string") + case *vm.PersistentMap, vm.Map, *vm.SortedMap: + return vm.NIL, fmt.Errorf("shuffle not supported on map") + } + + s, err := seqOf(vs[0]) + if err != nil { + return vm.NIL, err + } + vals := appendSeqValues(nil, forceSeq(s)) + + rngShuffle(len(vals), func(i, j int) { + vals[i], vals[j] = vals[j], vals[i] + }) + return vm.NewArrayVector(vals), nil +} + +//lg:native +//lg:name set-rand-seed! +func CoreSetRandSeedFn(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + n, ok := vs[0].(vm.Int) + if !ok { + return vm.NIL, fmt.Errorf("set-rand-seed! expected Int") + } + setRandSeed(int64(n)) + return vm.NIL, nil +} + +//lg:native +//lg:name transient +func CoreTransientf(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + switch v := vs[0].(type) { + case *vm.PersistentMap: + return vm.NewTransientMap(v), nil + case *vm.PersistentSet: + return vm.NewTransientSet(v), nil + case vm.ArrayVector: + return vm.NewTransientVector([]vm.Value(v)), nil + case vm.PersistentVector: + vals := v.Unbox().([]vm.Value) + return vm.NewTransientVector(vals), nil + default: + return vm.NIL, fmt.Errorf("transient not supported on %s", vs[0].Type().Name()) + } +} + +//lg:native +//lg:name persistent! +func CorePersistentf(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + switch v := vs[0].(type) { + case *vm.TransientMap: + return v.Persistent() + case *vm.TransientVector: + return v.Persistent() + case *vm.TransientSet: + return v.Persistent() + default: + return vm.NIL, fmt.Errorf("persistent! not supported on %s", vs[0].Type().Name()) + } +} + +//lg:native +//lg:name conj! +func CoreConjBang(vs ...vm.Value) (vm.Value, error) { + if len(vs) == 0 { + return vm.NewTransientVector(nil), nil + } + if len(vs) == 1 { + return vs[0], nil + } + switch t := vs[0].(type) { + case *vm.TransientMap: + var err error + for i := 1; i < len(vs); i++ { + t, err = t.Conj(vs[i]) + if err != nil { + return vm.NIL, err + } + } + return t, nil + case *vm.TransientVector: + var err error + for i := 1; i < len(vs); i++ { + t, err = t.Conj(vs[i]) + if err != nil { + return vm.NIL, err + } + } + return t, nil + case *vm.TransientSet: + var err error + for i := 1; i < len(vs); i++ { + t, err = t.Conj(vs[i]) + if err != nil { + return vm.NIL, err + } + } + return t, nil + default: + return vm.NIL, fmt.Errorf("conj! not supported on %s", vs[0].Type().Name()) + } +} + +//lg:native +//lg:name assoc! +func CoreAssocBang(vs ...vm.Value) (vm.Value, error) { + if len(vs) < 2 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + switch t := vs[0].(type) { + case *vm.TransientMap: + var err error + for i := 1; i < len(vs); i += 2 { + val := vm.Value(vm.NIL) + if i+1 < len(vs) { + val = vs[i+1] + } + t, err = t.Assoc(vs[i], val) + if err != nil { + return vm.NIL, err + } + } + return t, nil + case *vm.TransientVector: + var err error + for i := 1; i < len(vs); i += 2 { + val := vm.Value(vm.NIL) + if i+1 < len(vs) { + val = vs[i+1] + } + t, err = t.Assoc(vs[i], val) + if err != nil { + return vm.NIL, err + } + } + return t, nil + default: + return vm.NIL, fmt.Errorf("assoc! not supported on %s", vs[0].Type().Name()) + } +} + +//lg:native +//lg:name disj! +func CoreDisjBang(vs ...vm.Value) (vm.Value, error) { + if len(vs) < 2 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + t, ok := vs[0].(*vm.TransientSet) + if !ok { + return vm.NIL, fmt.Errorf("disj! expected TransientSet") + } + var err error + for i := 1; i < len(vs); i++ { + t, err = t.Disj(vs[i]) + if err != nil { + return vm.NIL, err + } + } + return t, nil +} + +//lg:native +//lg:name dissoc! +func CoreDissocBang(vs ...vm.Value) (vm.Value, error) { + if len(vs) < 2 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + t, ok := vs[0].(*vm.TransientMap) + if !ok { + return vm.NIL, fmt.Errorf("dissoc! expected TransientMap") + } + var err error + for i := 1; i < len(vs); i++ { + t, err = t.Dissoc(vs[i]) + if err != nil { + return vm.NIL, err + } + } + return t, nil +} + +//lg:native +//lg:name make-record-type +func CoreMakeRecordType(vs ...vm.Value) (vm.Value, error) { + if len(vs) < 1 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + name, ok := vs[0].(vm.String) + if !ok { + return vm.NIL, fmt.Errorf("make-record-type expected String name") + } + fields := make([]vm.Keyword, len(vs)-1) + for i := 1; i < len(vs); i++ { + kw, ok := vs[i].(vm.Keyword) + if !ok { + return vm.NIL, fmt.Errorf("make-record-type expected Keyword fields") + } + fields[i-1] = kw + } + return vm.NewRecordType(string(name), fields), nil +} + +//lg:native +//lg:name make-record +func CoreMakeRecord(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 2 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + rt, ok := vs[0].(*vm.RecordType) + if !ok { + return vm.NIL, fmt.Errorf("make-record expected RecordType") + } + m, ok := vs[1].(*vm.PersistentMap) + if !ok { + return vm.NIL, fmt.Errorf("make-record expected Map") + } + return vm.NewRecord(rt, m), nil +} + +//lg:native +//lg:name record? +func CoreIsRecord(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + _, ok := vs[0].(*vm.Record) + return vm.Boolean(ok), nil +} + +//lg:native +//lg:name make-deftype +func CoreMakeDType(vs ...vm.Value) (vm.Value, error) { + if len(vs) < 1 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + name, ok := vs[0].(vm.String) + if !ok { + return vm.NIL, fmt.Errorf("make-deftype expected String name") + } + fields := make([]vm.Symbol, len(vs)-1) + for i := 1; i < len(vs); i++ { + sym, ok := vs[i].(vm.Symbol) + if !ok { + return vm.NIL, fmt.Errorf("make-deftype expected Symbol fields") + } + fields[i-1] = sym + } + return vm.NewDType(string(name), fields), nil +} + +//lg:native +//lg:name make-deftype-instance +func CoreMakeDTypeInstance(vs ...vm.Value) (vm.Value, error) { + if len(vs) < 1 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + dt, ok := vs[0].(*vm.DType) + if !ok { + return vm.NIL, fmt.Errorf("make-deftype-instance expected DType, got %s", vs[0].Type().Name()) + } + + fields := make([]vm.Value, len(vs)-1) + copy(fields, vs[1:]) + return vm.NewDTypeInstance(dt, fields), nil +} + +//lg:native +//lg:name set-field! +func CoreSetField(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 3 { + return vm.NIL, fmt.Errorf("set-field! expected 3 arguments, got %d", len(vs)) + } + inst, ok := vs[0].(*vm.DTypeInstance) + if !ok { + return vm.NIL, fmt.Errorf("set-field! expected a deftype instance, got %s", vs[0].Type().Name()) + } + name, ok := vs[1].(vm.Symbol) + if !ok { + return vm.NIL, fmt.Errorf("set-field! expected a Symbol field name") + } + if err := inst.SetField(name, vs[2]); err != nil { + return vm.NIL, err + } + return vs[2], nil +} + +//lg:native +//lg:name defprotocol* +func CoreDefProtocol(vs ...vm.Value) (vm.Value, error) { + if len(vs) < 1 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + name, ok := vs[0].(vm.String) + if !ok { + return vm.NIL, fmt.Errorf("defprotocol* expected String name") + } + methods := make([]vm.Symbol, len(vs)-1) + for i := 1; i < len(vs); i++ { + s, ok := vs[i].(vm.Symbol) + if !ok { + return vm.NIL, fmt.Errorf("defprotocol* expected Symbol method names") + } + methods[i-1] = s + } + return vm.NewProtocol(string(name), methods), nil +} + +//lg:native +//lg:name extend-type* +func CoreExtendType(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 3 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + protocol, ok := vs[0].(*vm.Protocol) + if !ok { + return vm.NIL, fmt.Errorf("extend-type* expected Protocol") + } + implMap, ok := vs[2].(*vm.PersistentMap) + if !ok { + return vm.NIL, fmt.Errorf("extend-type* expected map of implementations") + } + + if vs[1] == vm.NIL { + protocol.ExtendNil(implMap) + return vm.NIL, nil + } + if union, ok := vs[1].(*vm.TypeUnion); ok { + + for _, valueType := range union.Types() { + protocol.ExtendViaUnion(valueType, implMap) + } + return vm.NIL, nil + } + vt, ok := vs[1].(vm.ValueType) + if !ok { + return vm.NIL, fmt.Errorf("extend-type* expected a type, got %s", vs[1].Type().Name()) + } + protocol.Extend(vt, implMap) + return vm.NIL, nil +} + +//lg:native +//lg:name make-protocol-fn +func CoreMakeProtocolFn(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 2 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + protocol, ok := vs[0].(*vm.Protocol) + if !ok { + return vm.NIL, fmt.Errorf("make-protocol-fn expected Protocol") + } + methodName, ok := vs[1].(vm.Symbol) + if !ok { + return vm.NIL, fmt.Errorf("make-protocol-fn expected Symbol") + } + return vm.NewProtocolFn(protocol, methodName), nil +} + +//lg:native +//lg:name -set-invokable-protocol! +func CoreSetInvokableProtocol(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 2 { + return vm.NIL, fmt.Errorf("-set-invokable-protocol! expects 2 args") + } + protocol, ok := vs[0].(*vm.Protocol) + if !ok { + return vm.NIL, fmt.Errorf("-set-invokable-protocol! expected a Protocol") + } + invokeFn, ok := vs[1].(vm.Fn) + if !ok { + return vm.NIL, fmt.Errorf("-set-invokable-protocol! expected the -invoke fn") + } + vm.IFnProtocol = protocol + vm.IFnInvoke = invokeFn + return vm.NIL, nil +} + +//lg:native +//lg:name -set-deref-protocol! +func CoreSetDerefProtocol(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 2 { + return vm.NIL, fmt.Errorf("-set-deref-protocol! expects 2 args") + } + protocol, ok := vs[0].(*vm.Protocol) + if !ok { + return vm.NIL, fmt.Errorf("-set-deref-protocol! expected a Protocol") + } + derefFn, ok := vs[1].(vm.Fn) + if !ok { + return vm.NIL, fmt.Errorf("-set-deref-protocol! expected the -deref fn") + } + vm.IDerefProtocol = protocol + vm.IDerefDeref = derefFn + return vm.NIL, nil +} + +//lg:native +//lg:name satisfies? +func CoreSatisfies(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 2 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + protocol, ok := vs[0].(*vm.Protocol) + if !ok { + return vm.NIL, fmt.Errorf("satisfies? expected Protocol") + } + return vm.Boolean(protocol.Satisfies(vs[1])), nil +} + +//lg:native +//lg:name defmulti* +func CoreDefMulti(vs ...vm.Value) (vm.Value, error) { + if len(vs) < 2 || len(vs) > 3 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + name, ok := vs[0].(vm.String) + if !ok { + return vm.NIL, fmt.Errorf("defmulti* expected String name") + } + dispatchFn, ok := vs[1].(vm.Fn) + if !ok { + return vm.NIL, fmt.Errorf("defmulti* expected Fn") + } + var defaultVal vm.Value = vm.Keyword("default") + if len(vs) == 3 { + defaultVal = vs[2] + } + return vm.NewMultiFn(string(name), dispatchFn, defaultVal), nil +} + +//lg:native +//lg:name defmethod* +func CoreDefMethod(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 3 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + mf, ok := vs[0].(*vm.MultiFn) + if !ok { + return vm.NIL, fmt.Errorf("defmethod* expected MultiFn") + } + dispatchVal := vs[1] + method, ok := vs[2].(vm.Fn) + if !ok { + return vm.NIL, fmt.Errorf("defmethod* expected Fn") + } + return mf.AddMethod(dispatchVal, method), nil +} + +//lg:native +//lg:name pr-str +func CorePrStr(vs ...vm.Value) (vm.Value, error) { + return prThroughToString(vs, true) +} + +//lg:native +//lg:name prn-str +func CorePrnStr(vs ...vm.Value) (vm.Value, error) { + s, err := prThroughToString(vs, true) + if err != nil { + return vm.NIL, err + } + return vm.String(string(s.(vm.String)) + "\n"), nil +} + +//lg:native +//lg:name print-str +func CorePrintStr(vs ...vm.Value) (vm.Value, error) { + return prThroughToString(vs, false) +} + +//lg:native +//lg:name println-str +func CorePrintlnStr(vs ...vm.Value) (vm.Value, error) { + s, err := prThroughToString(vs, false) + if err != nil { + return vm.NIL, err + } + return vm.String(string(s.(vm.String)) + "\n"), nil +} + +//lg:native +//lg:name re-find +func CoreReFind(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 2 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + re, ok := vs[0].(*vm.Regex) + if !ok { + return vm.NIL, fmt.Errorf("re-find expected Regex") + } + s, ok := vs[1].(vm.String) + if !ok { + return vm.NIL, fmt.Errorf("re-find expected String") + } + indices := re.FindStringSubmatchIndex(string(s)) + if indices == nil { + return vm.NIL, nil + } + return regexSubmatchValue(string(s), indices), nil +} + +//lg:native +//lg:name re-matches +func CoreReMatches(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 2 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + re, ok := vs[0].(*vm.Regex) + if !ok { + return vm.NIL, fmt.Errorf("re-matches expected Regex") + } + s, ok := vs[1].(vm.String) + if !ok { + return vm.NIL, fmt.Errorf("re-matches expected String") + } + indices := re.FindStringSubmatchIndex(string(s)) + if indices == nil || indices[0] != 0 || indices[1] != len(s) { + return vm.NIL, nil + } + return regexSubmatchValue(string(s), indices), nil +} + +//lg:native +//lg:name re-seq +func CoreReSeq(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 2 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + re, ok := vs[0].(*vm.Regex) + if !ok { + return vm.NIL, fmt.Errorf("re-seq expected Regex") + } + s, ok := vs[1].(vm.String) + if !ok { + return vm.NIL, fmt.Errorf("re-seq expected String") + } + + all := re.FindAllStringSubmatchIndex(string(s), -1) + if all == nil { + return vm.NIL, nil + } + vals := make([]vm.Value, len(all)) + for i, indices := range all { + vals[i] = regexSubmatchValue(string(s), indices) + } + return vm.ListType.Box(vals) +} + +//lg:native +//lg:name require +func CoreRequiref(vs ...vm.Value) (vm.Value, error) { + cns := CurrentNS.Deref().(*vm.Namespace) + for _, v := range vs { + switch arg := v.(type) { + case vm.Symbol: + if _, err := RequireNS(string(arg)); err != nil { + return vm.NIL, err + } + case vm.ArrayVector: + + if arg.RawCount() < 1 { + return vm.NIL, fmt.Errorf("require: empty vector") + } + nsName, ok := arg.ValueAt(vm.Int(0)).(vm.Symbol) + if !ok { + return vm.NIL, fmt.Errorf("require: first element must be a symbol") + } + target, err := RequireNS(string(nsName)) + if err != nil { + return vm.NIL, err + } + + for i := 1; i < arg.RawCount()-1; i += 2 { + opt := arg.ValueAt(vm.Int(int64(i))) + val := arg.ValueAt(vm.Int(int64(i + 1))) + switch opt { + case vm.Keyword("as"): + if alias, ok := val.(vm.Symbol); ok { + cns.Alias(alias, target) + } + case vm.Keyword("refer"): + if val == vm.Keyword("all") { + cns.Refer(target, "", true) + } else if vec, ok := val.(vm.ArrayVector); ok { + syms := make([]vm.Symbol, vec.RawCount()) + for j := 0; j < vec.RawCount(); j++ { + syms[j] = vec.ValueAt(vm.Int(int64(j))).(vm.Symbol) + } + cns.ReferList(target, syms) + } + } + } + default: + return vm.NIL, fmt.Errorf("require expected Symbol or Vector, got %s", v.Type().Name()) + } + } + return vm.NIL, nil +} + +//lg:native +//lg:name find-ns +func CoreFindNs(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + s, ok := vs[0].(vm.Symbol) + if !ok { + return vm.NIL, fmt.Errorf("find-ns expected Symbol") + } + nsMu.RLock() + ns := nsRegistry[string(s)] + nsMu.RUnlock() + if ns == nil { + return vm.NIL, nil + } + return ns, nil +} + +//lg:native +//lg:name resolve +func CoreResolvef(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + sym, ok := vs[0].(vm.Symbol) + if !ok { + return vm.NIL, fmt.Errorf("resolve expected Symbol") + } + cns := CurrentNS.Deref().(*vm.Namespace) + if v := cns.Lookup(sym); v != vm.NIL { + return v, nil + } + return vm.NIL, nil +} + +//lg:native +//lg:name all-ns +func CoreAllNs(vs ...vm.Value) (vm.Value, error) { + nsMu.RLock() + var nss []vm.Value + for _, ns := range nsRegistry { + nss = append(nss, ns) + } + nsMu.RUnlock() + return vm.NewList(nss), nil +} + +//lg:native +//lg:name the-ns +func CoreTheNs(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + s, ok := vs[0].(vm.Symbol) + if !ok { + + if ns, ok := vs[0].(*vm.Namespace); ok { + return ns, nil + } + return vm.NIL, fmt.Errorf("the-ns expected Symbol or Namespace") + } + nsMu.RLock() + ns := nsRegistry[string(s)] + nsMu.RUnlock() + if ns == nil { + return vm.NIL, fmt.Errorf("no namespace: %s found", s) + } + return ns, nil +} + +//lg:native +//lg:name ns-publics +func CoreNsPublics(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + var ns *vm.Namespace + switch a := vs[0].(type) { + case *vm.Namespace: + ns = a + case vm.Symbol: + + nsMu.RLock() + ns = nsRegistry[resolveNSAlias(string(a))] + nsMu.RUnlock() + if ns == nil { + return vm.NIL, fmt.Errorf("no namespace: %s found", a) + } + default: + return vm.NIL, fmt.Errorf("ns-publics expected Symbol or Namespace") + } + pubs := ns.PublicVars() + kvs := make([]vm.Value, 0, len(pubs)*2) + for sym, v := range pubs { + kvs = append(kvs, sym, v) + } + return vm.NewMap(kvs), nil +} + +//lg:native +//lg:name find-var +func CoreFindVar(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + sym, ok := vs[0].(vm.Symbol) + if !ok { + return vm.NIL, fmt.Errorf("find-var expected a symbol") + } + nsV, nameV := sym.Namespaced() + nsSym, ok1 := nsV.(vm.Symbol) + nameSym, ok2 := nameV.(vm.Symbol) + if !ok1 || !ok2 { + return vm.NIL, fmt.Errorf("find-var expects a fully-qualified symbol: %s", sym) + } + nsMu.RLock() + targetNS := nsRegistry[resolveNSAlias(string(nsSym))] + nsMu.RUnlock() + if targetNS == nil { + return vm.NIL, nil + } + if v := targetNS.LookupLocal(nameSym); v != nil { + return v, nil + } + return vm.NIL, nil +} + +//lg:native +//lg:name get-method +func CoreGetMethod(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 2 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + mf, ok := vs[0].(*vm.MultiFn) + if !ok { + return vm.NIL, fmt.Errorf("get-method expected a multimethod") + } + return mf.GetMethod(vs[1]), nil +} + +//lg:native +//lg:name enumeration-seq +func CoreEnumerationSeq(vs ...vm.Value) (vm.Value, error) { + return vm.NIL, fmt.Errorf("enumeration-seq is not supported under let-go (no java.util.Enumeration)") +} + +//lg:native +//lg:name lazy-seq* +func CoreLazySeq(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("lazy-seq* expected 1 argument, got %d", len(vs)) + } + fn, ok := vs[0].(vm.Fn) + if !ok { + return vm.NIL, fmt.Errorf("lazy-seq* expected a function") + } + return vm.NewLazySeq(fn), nil +} + +//lg:native +//lg:name with-meta +func CoreWithMeta(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 2 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + if vs[0] == vm.NIL { + return vm.NIL, nil + } + m, ok := vs[0].(vm.IMeta) + if ok { + return m.WithMeta(vs[1]), nil + } + fn, ok := vs[0].(vm.Fn) + if ok { + return vm.NewMetaFn(fn, vs[1]), nil + } + + return vs[0], nil +} + +//lg:native +//lg:name throw +func CoreThrowf(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + return vm.NIL, vm.NewThrownError(vs[0]) +} + +//lg:native +//lg:name ex-info +func CoreExInfo(vs ...vm.Value) (vm.Value, error) { + if len(vs) < 2 || len(vs) > 3 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + msg, ok := vs[0].(vm.String) + if !ok { + return vm.NIL, fmt.Errorf("ex-info expected String message") + } + data, ok := vs[1].(*vm.PersistentMap) + if !ok { + return vm.NIL, fmt.Errorf("ex-info expected Map data") + } + var cause error + if len(vs) == 3 { + if ei, ok := vs[2].(*vm.ExInfo); ok { + cause = ei + } + } + return vm.NewExInfo(string(msg), data, cause), nil +} + +//lg:native +//lg:name ex-message +func CoreExMessage(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("wrong number of arguments") + } + if ei, ok := vs[0].(*vm.ExInfo); ok { + return vm.String(ei.Message()), nil + } + return vm.NIL, nil +} + +//lg:native +//lg:name ex-data +func CoreExData(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("wrong number of arguments") + } + if ei, ok := vs[0].(*vm.ExInfo); ok { + + if d := ei.Data(); d != nil { + return d, nil + } + } + return vm.NIL, nil +} + +//lg:native +//lg:name ex-cause +func CoreExCause(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("wrong number of arguments") + } + if ei, ok := vs[0].(*vm.ExInfo); ok { + if c := ei.Cause(); c != nil { + if cev, ok := c.(*vm.ExInfo); ok { + return cev, nil + } + } + } + return vm.NIL, nil +} + +//lg:native +//lg:name delay* +func CoreDelayStar(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("delay* expects 1 arg (thunk fn)") + } + fn, ok := vs[0].(vm.Fn) + if !ok { + return vm.NIL, fmt.Errorf("delay* expected Fn") + } + return vm.NewDelay(fn), nil +} + +//lg:native +//lg:name force +func CoreForce(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("force expects 1 arg") + } + if d, ok := vs[0].(*vm.Delay); ok { + return d.Force() + } + return vs[0], nil +} + +//lg:native +//lg:name delay? +func CoreIsDelay(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.FALSE, nil + } + _, ok := vs[0].(*vm.Delay) + return vm.Boolean(ok), nil +} + +//lg:native +//lg:name realized? +func CoreIsRealized(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + if d, ok := vs[0].(*vm.Delay); ok { + return vm.Boolean(d.IsRealized()), nil + } + if p, ok := vs[0].(*vm.Promise); ok { + return vm.Boolean(p.IsRealized()), nil + } + if s, ok := vs[0].(*vm.LazySeq); ok { + return vm.Boolean(s.IsRealized()), nil + } + return vm.NIL, fmt.Errorf("realized? expected delay, promise, future, or lazy seq") +} + +//lg:native +//lg:name volatile! +func CoreVolatilef(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("volatile! expects 1 arg") + } + return vm.NewVolatile(vs[0]), nil +} + +//lg:native +//lg:name vreset! +func CoreVreset(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 2 { + return vm.NIL, fmt.Errorf("vreset! expects 2 args") + } + v, ok := vs[0].(*vm.Volatile) + if !ok { + return vm.NIL, fmt.Errorf("vreset! expected Volatile") + } + return v.Reset(vs[1]), nil +} + +//lg:native +//lg:name reduced +func CoreReducedf(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("reduced expects 1 arg") + } + return vm.NewReduced(vs[0]), nil +} + +//lg:native +//lg:name reduced? +func CoreIsReducedf(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.FALSE, nil + } + return vm.Boolean(vm.IsReduced(vs[0])), nil +} + +//lg:native +//lg:name bit-and +func CoreBitAnd(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 2 { + return vm.NIL, fmt.Errorf("bit-and expects 2 args") + } + a, ok := vs[0].(vm.Int) + if !ok { + return vm.NIL, fmt.Errorf("bit-and expected Int") + } + b, ok := vs[1].(vm.Int) + if !ok { + return vm.NIL, fmt.Errorf("bit-and expected Int") + } + return vm.MakeInt(int(a) & int(b)), nil +} + +//lg:native +//lg:name bit-or +func CoreBitOr(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 2 { + return vm.NIL, fmt.Errorf("bit-or expects 2 args") + } + a, ok := vs[0].(vm.Int) + if !ok { + return vm.NIL, fmt.Errorf("bit-or expected Int") + } + b, ok := vs[1].(vm.Int) + if !ok { + return vm.NIL, fmt.Errorf("bit-or expected Int") + } + return vm.MakeInt(int(a) | int(b)), nil +} + +//lg:native +//lg:name bit-xor +func CoreBitXor(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 2 { + return vm.NIL, fmt.Errorf("bit-xor expects 2 args") + } + a, ok := vs[0].(vm.Int) + if !ok { + return vm.NIL, fmt.Errorf("bit-xor expected Int") + } + b, ok := vs[1].(vm.Int) + if !ok { + return vm.NIL, fmt.Errorf("bit-xor expected Int") + } + return vm.MakeInt(int(a) ^ int(b)), nil +} + +//lg:native +//lg:name bit-not +func CoreBitNot(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("bit-not expects 1 arg") + } + a, ok := vs[0].(vm.Int) + if !ok { + return vm.NIL, fmt.Errorf("bit-not expected Int") + } + return vm.MakeInt(^int(a)), nil +} + +//lg:native +//lg:name bit-shift-left +func CoreBitShiftLeft(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 2 { + return vm.NIL, fmt.Errorf("bit-shift-left expects 2 args") + } + a, ok := vs[0].(vm.Int) + if !ok { + return vm.NIL, fmt.Errorf("bit-shift-left expected Int") + } + b, ok := vs[1].(vm.Int) + if !ok { + return vm.NIL, fmt.Errorf("bit-shift-left expected Int") + } + return vm.MakeInt(int(a) << uint(b)), nil +} + +//lg:native +//lg:name bit-shift-right +func CoreBitShiftRight(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 2 { + return vm.NIL, fmt.Errorf("bit-shift-right expects 2 args") + } + a, ok := vs[0].(vm.Int) + if !ok { + return vm.NIL, fmt.Errorf("bit-shift-right expected Int") + } + b, ok := vs[1].(vm.Int) + if !ok { + return vm.NIL, fmt.Errorf("bit-shift-right expected Int") + } + return vm.MakeInt(int(a) >> uint(b)), nil +} + +//lg:native +//lg:name unsigned-bit-shift-right +func CoreUnsignedBitShiftRight(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 2 { + return vm.NIL, fmt.Errorf("unsigned-bit-shift-right expects 2 args") + } + a, ok := vs[0].(vm.Int) + if !ok { + return vm.NIL, fmt.Errorf("unsigned-bit-shift-right expected Int") + } + b, ok := vs[1].(vm.Int) + if !ok { + return vm.NIL, fmt.Errorf("unsigned-bit-shift-right expected Int") + } + return vm.MakeInt(int(uint(a) >> uint(b))), nil +} + +//lg:native +//lg:name bit-test +func CoreBitTest(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 2 { + return vm.NIL, fmt.Errorf("bit-test expects 2 args") + } + a, ok := vs[0].(vm.Int) + if !ok { + return vm.NIL, fmt.Errorf("bit-test expected Int") + } + b, ok := vs[1].(vm.Int) + if !ok { + return vm.NIL, fmt.Errorf("bit-test expected Int") + } + return vm.Boolean(int(a)&(1< +func CoreTapBang(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("tap> expects 1 arg") + } + tapsMu.Lock() + snap := make([]vm.Fn, len(taps)) + copy(snap, taps) + tapsMu.Unlock() + for _, t := range snap { + _, _ = t.Invoke([]vm.Value{vs[0]}) + } + return vm.TRUE, nil +} + +//lg:native +//lg:name add-watch +func CoreAddWatch(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 3 { + return vm.NIL, fmt.Errorf("add-watch expects 3 args") + } + fn, ok := vm.AsFn(vs[2]) + if !ok { + return vm.NIL, fmt.Errorf("add-watch expected Fn") + } + switch ref := vs[0].(type) { + case *vm.Atom: + ref.AddWatch(vs[1], fn) + case *vm.Var: + ref.AddWatch(vs[1], fn) + default: + return vm.NIL, fmt.Errorf("add-watch expected Atom or Var") + } + return vs[0], nil +} + +//lg:native +//lg:name remove-watch +func CoreRemoveWatch(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 2 { + return vm.NIL, fmt.Errorf("remove-watch expects 2 args") + } + switch ref := vs[0].(type) { + case *vm.Atom: + ref.RemoveWatch(vs[1]) + case *vm.Var: + ref.RemoveWatch(vs[1]) + default: + return vm.NIL, fmt.Errorf("remove-watch expected Atom or Var") + } + return vs[0], nil +} + +//lg:native +//lg:name get-validator +func CoreGetValidator(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("get-validator expects 1 arg") + } + a, ok := vs[0].(*vm.Atom) + if !ok { + return vm.NIL, fmt.Errorf("get-validator expected Atom") + } + return a.Validator(), nil +} + +//lg:native +//lg:name subvec +func CoreSubvecf(vs ...vm.Value) (vm.Value, error) { + if len(vs) < 2 || len(vs) > 3 { + return vm.NIL, fmt.Errorf("subvec expects 2-3 args") + } + s, ok := vm.ToInt(vs[1]) + if !ok { + return vm.NIL, fmt.Errorf("subvec expected Int start") + } + + switch v := vs[0].(type) { + case vm.ArrayVector: + end := len(v) + if len(vs) == 3 { + e, ok := vm.ToInt(vs[2]) + if !ok { + return vm.NIL, fmt.Errorf("subvec expected Int end") + } + end = e + } + if s < 0 || end > len(v) || s > end { + return vm.NIL, fmt.Errorf("subvec: index out of bounds") + } + result := make([]vm.Value, end-s) + copy(result, v[s:end]) + return vm.NewArrayVector(result), nil + case vm.PersistentVector: + end := int(v.Count().(vm.Int)) + if len(vs) == 3 { + e, ok := vm.ToInt(vs[2]) + if !ok { + return vm.NIL, fmt.Errorf("subvec expected Int end") + } + end = e + } + if s < 0 || end > int(v.Count().(vm.Int)) || s > end { + return vm.NIL, fmt.Errorf("subvec: index out of bounds") + } + result := make([]vm.Value, end-s) + for i := s; i < end; i++ { + result[i-s] = v.ValueAt(vm.Int(i)) + } + return vm.NewArrayVector(result), nil + default: + return vm.NIL, fmt.Errorf("subvec expected vector") + } +} + +//lg:native +//lg:name double? +func CoreIsDouble(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.FALSE, nil + } + _, ok := vs[0].(vm.Float) + return vm.Boolean(ok), nil +} + +//lg:native +//lg:name instance? +func CoreInstancep(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 2 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + + if t, ok := vs[0].(vm.ValueType); ok { + if vs[1].Type() == t { + return vm.TRUE, nil + } + + if anc := directTypeAncestors(vs[1].Type()); anc != nil { + return anc.Contains(t), nil + } + return vm.FALSE, nil + } + if union, ok := vs[0].(*vm.TypeUnion); ok { + return vm.Boolean(union.Contains(vs[1].Type())), nil + } + + if marker, ok := vs[0].(vm.Symbol); ok { + if anc := directTypeAncestors(vs[1].Type()); anc != nil { + return vm.Boolean(anc.Contains(marker) == vm.TRUE), nil + } + } + + if p, ok := vs[0].(*vm.Protocol); ok { + return vm.Boolean(p.Satisfies(vs[1])), nil + } + return vm.FALSE, nil +} + +//lg:native +//lg:name ifn? +func CoreIsIFn(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.FALSE, nil + } + switch vs[0].(type) { + case vm.Fn, vm.Keyword, vm.Symbol, *vm.PersistentMap, *vm.PersistentSet, + vm.ArrayVector, vm.PersistentVector, *vm.SortedMap, *vm.SortedSet, *vm.Promise: + return vm.TRUE, nil + } + return vm.FALSE, nil +} + +//lg:native +//lg:name identical? +func CoreIdentical(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 2 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + return vm.Boolean(identicalValue(vs[0], vs[1])), nil +} + +//lg:native +//lg:name any? +func CoreAnyp(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + return vm.TRUE, nil +} + +//lg:native +//lg:name unreduced +func CoreUnreduced(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("unreduced expects 1 arg") + } + if r, ok := vs[0].(*vm.Reduced); ok { + return r.Deref(), nil + } + return vs[0], nil +} + +//lg:native +//lg:name ensure-reduced +func CoreEnsureReduced(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("ensure-reduced expects 1 arg") + } + if _, ok := vs[0].(*vm.Reduced); ok { + return vs[0], nil + } + return vm.NewReduced(vs[0]), nil +} + +//lg:native +//lg:name bigint +func CoreBigintf(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("bigint expects 1 arg") + } + switch v := vs[0].(type) { + case vm.Int: + return vm.NewBigIntFromInt64(int64(v)), nil + case vm.Float: + f := float64(v) + if math.IsNaN(f) || math.IsInf(f, 0) { + return vm.NIL, fmt.Errorf("cannot coerce %s to bigint", vs[0]) + } + decimal := strconv.FormatFloat(f, 'g', -1, 64) + i, _, err := new(big.Float).SetPrec(4096).SetMode(big.ToZero).Parse(decimal, 10) + if err != nil || i == nil { + return vm.NIL, fmt.Errorf("cannot coerce %s to bigint", vs[0]) + } + bi, _ := i.Int(nil) + return vm.NewBigInt(bi), nil + case *vm.BigInt: + return v, nil + case vm.String: + bi, ok := vm.NewBigIntFromString(string(v)) + if !ok { + return vm.NIL, fmt.Errorf("cannot parse bigint: %s", v) + } + return bi, nil + } + return vm.NIL, fmt.Errorf("cannot coerce %s to bigint", vs[0].Type().Name()) +} + +//lg:native +//lg:name ratio? +func CoreIsRatio(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.FALSE, nil + } + return vm.Boolean(vm.IsRatio(vs[0])), nil +} + +//lg:native +//lg:name decimal? +func CoreIsDecimal(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.FALSE, nil + } + return vm.Boolean(vm.IsBigDecimal(vs[0])), nil +} + +//lg:native +//lg:name sorted? +func CoreIsSorted(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.FALSE, nil + } + switch vs[0].(type) { + case *vm.SortedMap, *vm.SortedSet: + return vm.TRUE, nil + } + return vm.FALSE, nil +} + +//lg:native +//lg:name map? +func CoreIsMap(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.FALSE, nil + } + switch vs[0].(type) { + case *vm.PersistentMap, *vm.SortedMap: + return vm.TRUE, nil + } + return vm.FALSE, nil +} + +//lg:native +//lg:name set? +func CoreIsSet(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.FALSE, nil + } + switch vs[0].(type) { + case *vm.PersistentSet, *vm.SortedSet: + return vm.TRUE, nil + } + return vm.FALSE, nil +} + +//lg:native +//lg:name map-entry? +func CoreIsMapEntry(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.FALSE, nil + } + if _, ok := vs[0].(vm.MapEntry); ok { + return vm.TRUE, nil + } + return vm.FALSE, nil +} + +//lg:native +//lg:name lazy-seq? +func CoreIsLazySeq(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.FALSE, nil + } + if _, ok := vs[0].(*vm.LazySeq); ok { + return vm.TRUE, nil + } + return vm.FALSE, nil +} + +//lg:native +//lg:name reversible? +func CoreIsReversible(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.FALSE, nil + } + switch vs[0].(type) { + case vm.ArrayVector, vm.PersistentVector, *vm.SortedMap, *vm.SortedSet: + return vm.TRUE, nil + } + return vm.FALSE, nil +} + +//lg:native +//lg:name rseq +func CoreRseqf(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("wrong number of arguments") + } + switch v := vs[0].(type) { + case *vm.SortedMap: + s := v.RSeq() + if s == vm.EmptyList { + return vm.NIL, nil + } + return s, nil + case *vm.SortedSet: + s := v.RSeq() + if s == vm.EmptyList { + return vm.NIL, nil + } + return s, nil + case vm.ArrayVector: + n := len(v) + if n == 0 { + return vm.NIL, nil + } + var s vm.Seq = vm.EmptyList + for i := range n { + s = vm.NewCons(v[i], s) + } + return s, nil + case vm.PersistentVector: + n := v.RawCount() + if n == 0 { + return vm.NIL, nil + } + var s vm.Seq = vm.EmptyList + for i := range n { + s = vm.NewCons(v.ValueAt(vm.MakeInt(i)), s) + } + return s, nil + } + return vm.NIL, fmt.Errorf("rseq not supported on: %s", vs[0].Type()) +} + +//lg:native +//lg:name numerator +func CoreNumeratorf(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("wrong number of arguments") + } + if r, ok := vs[0].(*vm.Ratio); ok { + num := r.Val().Num() + return vm.MaybeDowngrade(new(big.Int).Set(num)), nil + } + return vm.NIL, fmt.Errorf("numerator expects a Ratio") +} + +//lg:native +//lg:name denominator +func CoreDenominatorf(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("wrong number of arguments") + } + if r, ok := vs[0].(*vm.Ratio); ok { + den := r.Val().Denom() + return vm.MaybeDowngrade(new(big.Int).Set(den)), nil + } + return vm.NIL, fmt.Errorf("denominator expects a Ratio") +} + +//lg:native +//lg:name bigdec +func CoreBigdecf(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("wrong number of arguments") + } + switch v := vs[0].(type) { + case *vm.BigDecimal: + return v, nil + case vm.Int: + return vm.NewBigDecimalFromInt64(int64(v)), nil + case vm.Float: + f := float64(v) + if math.IsInf(f, 0) || math.IsNaN(f) { + return vm.NIL, fmt.Errorf("cannot coerce non-finite float to bigdec") + } + return vm.NewBigDecimalFromFloat64(f), nil + case *vm.BigInt: + return vm.NewBigDecimalFromBigInt(v.Val()), nil + case *vm.Ratio: + f, _ := v.Val().Float64() + return vm.NewBigDecimalFromFloat64(f), nil + case vm.String: + bd, ok := vm.NewBigDecimalFromString(string(v)) + if !ok { + return vm.NIL, fmt.Errorf("cannot parse bigdec: %s", v) + } + return bd, nil + } + return vm.NIL, fmt.Errorf("cannot coerce %s to bigdec", vs[0].Type().Name()) +} + +//lg:native +//lg:name round-bigdec +func CoreRoundBigdec(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 3 { + return vm.NIL, fmt.Errorf("round-bigdec expects precision, rounding mode, and value") + } + precision, ok := vm.ToInt(vs[0]) + if !ok { + return vm.NIL, fmt.Errorf("round-bigdec expected integer precision") + } + var modeName string + switch m := vs[1].(type) { + case vm.Keyword: + modeName = string(m) + case vm.Symbol: + modeName = string(m) + case vm.String: + modeName = string(m) + default: + return vm.NIL, fmt.Errorf("round-bigdec expected rounding mode") + } + modeName = strings.TrimPrefix(strings.ToLower(modeName), ":") + bd, ok := vs[2].(*vm.BigDecimal) + if !ok { + return vs[2], nil + } + return roundBigDecimalValue(bd, precision, modeName) +} + +//lg:native +//lg:name rationalize +func CoreRationalizef(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("wrong number of arguments") + } + switch v := vs[0].(type) { + case *vm.Ratio: + return v, nil + case vm.Int: + return vm.MaybeSimplifyRatio(big.NewRat(int64(v), 1)), nil + case *vm.BigInt: + return vm.MaybeSimplifyRatio(new(big.Rat).SetInt(v.Val())), nil + case vm.Float: + f := float64(v) + if math.IsInf(f, 0) || math.IsNaN(f) { + return vm.NIL, fmt.Errorf("cannot rationalize %s", vs[0].Type().Name()) + } + if r, ok := new(big.Rat).SetString(strconv.FormatFloat(f, 'f', -1, 64)); ok { + return vm.MaybeSimplifyRatio(r), nil + } + return vm.NIL, fmt.Errorf("cannot rationalize %s", vs[0].Type().Name()) + case *vm.BigDecimal: + if r, ok := new(big.Rat).SetString(v.Val().Text('f', -1)); ok { + return vm.MaybeSimplifyRatio(r), nil + } + return vm.NIL, fmt.Errorf("cannot rationalize %s", vs[0].Type().Name()) + } + return vm.NIL, fmt.Errorf("cannot rationalize %s", vs[0].Type().Name()) +} + +//lg:native +//lg:name quot +func CoreQuotf(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 2 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + return vm.NumQuot(vs[0], vs[1]) +} + +//lg:native +//lg:name rem +func CoreRemf(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 2 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + return vm.NumRem(vs[0], vs[1]) +} + +//lg:native +//lg:name hash +func CoreHashf(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + return vm.MakeInt(int(vm.HashValue(vs[0]))), nil +} + +//lg:native +//lg:name parse-double +func CoreParseDouble(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + s, ok := vs[0].(vm.String) + if !ok { + return vm.NIL, fmt.Errorf("parse-double expected String") + } + f, err := strconv.ParseFloat(string(s), 64) + if err != nil { + return vm.NIL, nil + } + return vm.Float(f), nil +} + +//lg:native +//lg:name parse-boolean +func CoreParseBool(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + s, ok := vs[0].(vm.String) + if !ok { + return vm.NIL, fmt.Errorf("parse-boolean expected String") + } + switch string(s) { + case "true": + return vm.TRUE, nil + case "false": + return vm.FALSE, nil + } + return vm.NIL, nil +} + +//lg:native +//lg:name NaN? +func CoreIsNaN(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.FALSE, nil + } + switch v := vs[0].(type) { + case vm.Float: + return vm.Boolean(math.IsNaN(float64(v))), nil + case vm.Float32: + return vm.Boolean(math.IsNaN(float64(v))), nil + case vm.Int, *vm.BigInt, *vm.Ratio, *vm.BigDecimal: + return vm.FALSE, nil + default: + return vm.NIL, fmt.Errorf("NaN? requires a number, got %s", vs[0].Type().Name()) + } +} + +//lg:native +//lg:name infinite? +func CoreIsInfinite(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.FALSE, nil + } + if f, ok := vs[0].(vm.Float); ok { + return vm.Boolean(math.IsInf(float64(f), 0)), nil + } + return vm.FALSE, nil +} + +//lg:native +//lg:name boolean? +func CoreIsBool(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.FALSE, nil + } + _, ok := vs[0].(vm.Boolean) + return vm.Boolean(ok), nil +} + +//lg:native +//lg:name char? +func CoreIsChar(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.FALSE, nil + } + _, ok := vs[0].(vm.Char) + return vm.Boolean(ok), nil +} + +//lg:native +//lg:name var? +func CoreIsVar(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.FALSE, nil + } + _, ok := vs[0].(*vm.Var) + return vm.Boolean(ok), nil +} + +//lg:native +//lg:name byte-array +func CoreByteArrayf(vs ...vm.Value) (vm.Value, error) { + return buildArray(vm.ArrayByte, vs) +} + +//lg:native +//lg:name object-array +func CoreObjectArrayf(vs ...vm.Value) (vm.Value, error) { + return buildArray(vm.ArrayObject, vs) +} + +//lg:native +//lg:name make-array +func CoreMakeArrayf(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 2 { + return vm.NIL, fmt.Errorf("make-array expects 2 args (type, size)") + } + size, ok := vs[1].(vm.Int) + if !ok { + return vm.NIL, fmt.Errorf("make-array size must be Int") + } + n := int(size) + if n < 0 { + return vm.NIL, fmt.Errorf("negative array size: %d", n) + } + switch t := vs[0].(type) { + case vm.Keyword: + switch string(t) { + case "byte": + return vm.NewByteArray(n), nil + case "int", "long": + return vm.NewIntArray(n), nil + case "double", "float": + return vm.NewFloatArray(n), nil + case "object": + return vm.NewObjectArray(n), nil + } + return vm.NIL, fmt.Errorf("unknown array type: %s", t) + default: + + return vm.NewObjectArray(n), nil + } +} + +//lg:native +//lg:name aget +func CoreAgetf(vs ...vm.Value) (vm.Value, error) { + if len(vs) < 2 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + arr, ok := vs[0].(*vm.TypedArray) + if !ok { + return vm.NIL, fmt.Errorf("aget expects array, got %s", vs[0].Type().Name()) + } + idx, ok := vs[1].(vm.Int) + if !ok { + return vm.NIL, fmt.Errorf("aget index must be Int") + } + i := int(idx) + if i < 0 || i >= arr.Len() { + return vm.NIL, fmt.Errorf("array index %d out of bounds for length %d", i, arr.Len()) + } + val := arr.Get(i) + + for _, extra := range vs[2:] { + inner, ok := val.(*vm.TypedArray) + if !ok { + return vm.NIL, fmt.Errorf("aget nested: expected array, got %s", val.Type().Name()) + } + idx, ok := extra.(vm.Int) + if !ok { + return vm.NIL, fmt.Errorf("aget index must be Int") + } + j := int(idx) + if j < 0 || j >= inner.Len() { + return vm.NIL, fmt.Errorf("array index %d out of bounds for length %d", j, inner.Len()) + } + val = inner.Get(j) + } + return val, nil +} + +//lg:native +//lg:name aset +func CoreAsetf(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 3 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + arr, ok := vs[0].(*vm.TypedArray) + if !ok { + return vm.NIL, fmt.Errorf("aset expects array, got %s", vs[0].Type().Name()) + } + idx, ok := vs[1].(vm.Int) + if !ok { + return vm.NIL, fmt.Errorf("aset index must be Int") + } + i := int(idx) + if i < 0 || i >= arr.Len() { + return vm.NIL, fmt.Errorf("array index %d out of bounds for length %d", i, arr.Len()) + } + if err := arr.Set(i, vs[2]); err != nil { + return vm.NIL, err + } + return vs[2], nil +} + +//lg:native +//lg:name alength +func CoreAlengthf(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + arr, ok := vs[0].(*vm.TypedArray) + if !ok { + return vm.NIL, fmt.Errorf("alength expects array, got %s", vs[0].Type().Name()) + } + return vm.MakeInt(arr.Len()), nil +} + +//lg:native +//lg:name aclone +func CoreAclonef(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + arr, ok := vs[0].(*vm.TypedArray) + if !ok { + return vm.NIL, fmt.Errorf("aclone expects array, got %s", vs[0].Type().Name()) + } + return arr.Clone(), nil +} + +//lg:native +//lg:name bytes +func CoreBytesf(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + switch v := vs[0].(type) { + case vm.String: + data := []byte(string(v)) + return vm.NewByteArrayFrom(data), nil + case *vm.TypedArray: + if v.Kind() == vm.ArrayByte { + return v, nil + } + } + return vm.NIL, fmt.Errorf("bytes expects String or byte-array, got %s", vs[0].Type().Name()) +} + +//lg:native +//lg:name doubles +func CoreDoublesf(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) + } + if a, ok := vs[0].(*vm.TypedArray); ok && a.Kind() == vm.ArrayFloat { + return a, nil + } + return buildArray(vm.ArrayFloat, vs) +} + +//lg:native +//lg:name bytes? +func CoreBytesP(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.FALSE, nil + } + a, ok := vs[0].(*vm.TypedArray) + return vm.Boolean(ok && a.Kind() == vm.ArrayByte), nil +} + +//lg:native +//lg:name var-get +func CoreVarGet(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("var-get expects 1 arg") + } + v, ok := vs[0].(*vm.Var) + if !ok { + return vm.NIL, fmt.Errorf("var-get expects a Var") + } + return v.Deref(), nil +} + +//lg:native +//lg:name bound? +func CoreBoundQ(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("bound? expects 1 arg") + } + v, ok := vs[0].(*vm.Var) + if !ok { + return vm.NIL, fmt.Errorf("bound? expects a Var") + } + if v.IsBound() { + return vm.TRUE, nil + } + return vm.FALSE, nil +} + +//lg:native +//lg:name -copy-form-source! +func CoreCopyFormSource(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 2 { + return vm.NIL, fmt.Errorf("-copy-form-source! expects 2 args") + } + if info := vm.FormSource.Get(vs[0]); info != nil { + vm.FormSource.Set(vs[1], *info) + } + return vs[1], nil +} + +//lg:native +//lg:name chunk->fn +func CoreChunkToFnFn(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 3 { + return vm.NIL, fmt.Errorf("chunk->fn expects (arity variadic? chunk), got %d args", len(vs)) + } + arityV, ok := vs[0].(vm.Int) + if !ok { + return vm.NIL, fmt.Errorf("chunk->fn: arity must be Int, got %s", vs[0].Type().Name()) + } + variadic := false + if b, ok := vs[1].(vm.Boolean); ok { + variadic = bool(b) + } else if vs[1] != vm.NIL { + return vm.NIL, fmt.Errorf("chunk->fn: variadic? must be Boolean or nil, got %s", vs[1].Type().Name()) + } + boxed, ok := vs[2].(*vm.Boxed) + if !ok { + return vm.NIL, fmt.Errorf("chunk->fn: third arg must be boxed CodeChunk, got %s", vs[2].Type().Name()) + } + chunk, ok := boxed.Unbox().(*vm.CodeChunk) + if !ok { + return vm.NIL, fmt.Errorf("chunk->fn: boxed value is not a CodeChunk") + } + return vm.MakeFunc(int(arityV), variadic, chunk), nil +} + +//lg:native +//lg:name make-multi-arity +func CoreMakeMultiArityFn(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("make-multi-arity expects 1 arg (list of functions)") + } + list, ok := vs[0].(*vm.List) + if !ok { + return vm.NIL, fmt.Errorf("make-multi-arity expects a list, got %s", vs[0].Type().Name()) + } + var fns []vm.Value + for e := vm.Seq(list); e != nil; e = e.Next() { + fns = append(fns, e.First()) + } + return vm.MakeMultiArity(fns) +} + +//lg:native +//lg:name intern +func CoreInternf(vs ...vm.Value) (vm.Value, error) { + if len(vs) < 2 || len(vs) > 3 { + return vm.NIL, fmt.Errorf("intern expects 2 or 3 args") + } + var targetNS *vm.Namespace + switch n := vs[0].(type) { + case vm.Symbol: + targetNS = nsRegistry[resolveNSAlias(string(n))] + case *vm.Namespace: + targetNS = n + default: + return vm.NIL, fmt.Errorf("intern expects a namespace or symbol") + } + if targetNS == nil { + return vm.NIL, fmt.Errorf("namespace not found") + } + sym, ok := vs[1].(vm.Symbol) + if !ok { + return vm.NIL, fmt.Errorf("intern expects a symbol name") + } + if len(vs) == 2 { + if existing := targetNS.LookupLocal(sym); existing != nil { + return existing, nil + } + return targetNS.Def(string(sym), vm.NIL), nil + } + + if existing := targetNS.LookupLocal(sym); existing != nil { + existing.SetRoot(vs[2]) + return existing, nil + } + v := targetNS.Def(string(sym), vs[2]) + return v, nil +} + +//lg:native +//lg:name apply-def-meta! +func CoreApplyDefMetaf(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 2 { + return vm.NIL, fmt.Errorf("apply-def-meta! expects 2 args") + } + v, ok := vs[0].(*vm.Var) + if !ok { + return vm.NIL, fmt.Errorf("apply-def-meta! expects a Var") + } + ApplyVarMeta(v, vs[1]) + return v, nil +} + +//lg:native +//lg:name create-ns +func CoreCreateNsf(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("create-ns expects 1 arg") + } + sym, ok := vs[0].(vm.Symbol) + if !ok { + return vm.NIL, fmt.Errorf("create-ns expects a symbol") + } + return NS(string(sym)), nil +} + +//lg:native +//lg:name pop! +func CorePopBang(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("pop! expects 1 arg") + } + tv, ok := vs[0].(*vm.TransientVector) + if !ok { + return vm.NIL, fmt.Errorf("pop! expects a transient vector") + } + return tv.Pop() +} + +//lg:native +//lg:name uuid? +func CoreIsUUID(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.FALSE, nil + } + _, ok := vs[0].(*vm.UUID) + return vm.Boolean(ok), nil +} + +//lg:native +//lg:name inst? +func CoreIsInst(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.FALSE, nil + } + _, ok := vs[0].(*vm.Instant) + return vm.Boolean(ok), nil +} + +//lg:native +//lg:name parse-uuid +func CoreParseUUID(vs ...vm.Value) (vm.Value, error) { + if len(vs) != 1 { + return vm.NIL, fmt.Errorf("parse-uuid expects 1 arg") + } + s, ok := vs[0].(vm.String) + if !ok { + return vm.NIL, fmt.Errorf("parse-uuid expects a string, got %s", vs[0].Type().Name()) + } + u := vm.ParseUUID(string(s)) + if u == nil { + return vm.NIL, nil + } + return u, nil +} + +//lg:native +//lg:name == +func CoreNumericEq(vs ...vm.Value) (vm.Value, error) { + if len(vs) < 2 { + return vm.TRUE, nil + } + for i := 1; i < len(vs); i++ { + if !vm.NumEquivalent(vs[0], vs[i]) { + return vm.FALSE, nil + } + } + return vm.TRUE, nil +} diff --git a/pkg/rt/native_prims.go b/pkg/rt/native_prims.go index 824331124..945dbe7b2 100644 --- a/pkg/rt/native_prims.go +++ b/pkg/rt/native_prims.go @@ -439,204 +439,6 @@ func reduceColl(ec *vm.ExecContext, mfn vm.Fn, coll vm.Value, hasInit bool, init return acc, nil } -// symbolToStr accepts the string-like values clojure.core/symbol takes as a -// name or namespace component. -func symbolToStr(v vm.Value) (string, bool) { - switch s := v.(type) { - case vm.String: - return string(s), true - case vm.Symbol: - return string(s), true - case vm.Keyword: - return string(s), true - default: - return "", false - } -} - -// Symbol implements (symbol x): a String/Symbol/Keyword becomes a Symbol of -// the same text, and a Var becomes its qualified name. Lives here rather than -// in pkg/rt/builtins because the Var case needs externalNSName, which reads -// rt's alias table — builtins imports only vm, by design. -// -//lg:native -//lg:name symbol -func Symbol(v vm.Value) (vm.Value, error) { - if v == vm.NIL { - return vm.NIL, fmt.Errorf("symbol expected String, Symbol, Keyword, or Var") - } - if vr, ok := v.(*vm.Var); ok { - return vm.Symbol(externalNSName(vr.NS()) + "/" + vr.VarName()), nil - } - if s, ok := symbolToStr(v); ok { - return vm.Symbol(s), nil - } - return vm.NIL, fmt.Errorf("symbol expected String or Symbol") -} - -// Assoc implements the 3-arity (assoc coll k v). Higher arities stay on the -// trampoline: the variadic form threads pairs left-to-right and is far rarer -// in lowered code than the single-pair case. -// -//lg:native -//lg:name assoc -func Assoc(coll vm.Value, k vm.Value, v vm.Value) (vm.Value, error) { - a, ok := coll.(vm.Associative) - if !ok { - return vm.NIL, fmt.Errorf("assoc expected Associative") - } - ret := a.Assoc(k, v) - if ret == vm.NIL { - return vm.NIL, fmt.Errorf("assoc failed for key %s", k.String()) - } - return ret, nil -} - -// AssocBang implements the 3-arity (assoc! transient k v). The variadic form -// (multiple k/v pairs) stays on the trampoline; the single-pair case is what -// hot loops emit. -// -// Registered as a native because ir.direct's evaluator calls assoc! once per -// INSTRUCTION to store each result into the indexed value table. Without an -// entry here that call lowers to ec.Invoke plus a []vm.Value allocation on -// every instruction executed — the single hottest trampoline in the -// interpreter. -// -//lg:native -//lg:name assoc! -func AssocBang(coll vm.Value, k vm.Value, v vm.Value) (vm.Value, error) { - switch t := coll.(type) { - case *vm.TransientVector: - return t.Assoc(k, v) - case *vm.TransientMap: - return t.Assoc(k, v) - default: - return vm.NIL, fmt.Errorf("assoc! expected a transient, got %s", coll.Type().Name()) - } -} - -// swapAtom is the shared body for the swap! arities: ec.Bind(fn) is what makes -// the atom's retry loop able to re-invoke the user function, which is why this -// lives in rt (with ExecContext) rather than in the vm-only builtins package. -func swapAtom(ec *vm.ExecContext, a vm.Value, f vm.Value, extra []vm.Value) (vm.Value, error) { - at, ok := a.(*vm.Atom) - if !ok { - return vm.NIL, fmt.Errorf("swap expected Atom") - } - fn, ok := vm.AsFn(f) - if !ok { - return vm.NIL, fmt.Errorf("swap expected Fn") - } - return at.Swap(ec.Bind(fn), extra) -} - -// Swap implements (swap! a f). -// -//lg:native -//lg:name swap! -func Swap(ec *vm.ExecContext, a vm.Value, f vm.Value) (vm.Value, error) { - return swapAtom(ec, a, f, nil) -} - -// Swap3 implements (swap! a f x). -// -//lg:native -//lg:name swap! -func Swap3(ec *vm.ExecContext, a vm.Value, f vm.Value, x vm.Value) (vm.Value, error) { - return swapAtom(ec, a, f, []vm.Value{x}) -} - -// NotEq implements the 2-arity (not= a b). It calls rt's own valueEquals — -// NOT vm.ValueEquals / EqValue, which is a different function with different -// nil and numeric handling — so not= stays exactly the negation of =. The NaN -// case mirrors the interpreter path: two NaNs compare not-different here. -// -//lg:native -//lg:name not= -func NotEq(a vm.Value, b vm.Value) (vm.Value, error) { - if isNaNValue(a) && isNaNValue(b) { - return vm.FALSE, nil - } - return vm.Boolean(!valueEquals(a, b)), nil -} - -// assocPairs threads key/value pairs left-to-right, the shared body for the -// fixed assoc arities. -func assocPairs(coll vm.Value, kvs ...vm.Value) (vm.Value, error) { - a, ok := coll.(vm.Associative) - if !ok { - return vm.NIL, fmt.Errorf("assoc expected Associative") - } - ret := a - for i := 0; i+1 < len(kvs); i += 2 { - next := ret.Assoc(kvs[i], kvs[i+1]) - if next == vm.NIL { - return vm.NIL, fmt.Errorf("assoc failed for key %s", kvs[i].String()) - } - // Assoc returns vm.Associative, so next is already that type. - ret = next - } - return ret, nil -} - -// Assoc5 implements (assoc coll k1 v1 k2 v2). -// -//lg:native -//lg:name assoc -func Assoc5(coll, k1, v1, k2, v2 vm.Value) (vm.Value, error) { - return assocPairs(coll, k1, v1, k2, v2) -} - -// Swap4 implements (swap! a f x y). -// -//lg:native -//lg:name swap! -func Swap4(ec *vm.ExecContext, a, f, x, y vm.Value) (vm.Value, error) { - return swapAtom(ec, a, f, []vm.Value{x, y}) -} - -// Swap5 implements (swap! a f x y z). -// -//lg:native -//lg:name swap! -func Swap5(ec *vm.ExecContext, a, f, x, y, z vm.Value) (vm.Value, error) { - return swapAtom(ec, a, f, []vm.Value{x, y, z}) -} - -// IsMap implements (map? x). -// -//lg:native -//lg:name map? -func IsMap(v vm.Value) (vm.Value, error) { - switch v.(type) { - case *vm.PersistentMap, *vm.SortedMap: - return vm.TRUE, nil - } - return vm.FALSE, nil -} - -// Atom implements the 1-arity (atom x). The option-taking arities (:meta, -// :validator) stay on the trampoline — they parse keyword pairs, which the -// fixed-arity direct-call path is not the right shape for. -// -//lg:native -//lg:name atom -func Atom(v vm.Value) (vm.Value, error) { - return vm.NewAtomWithMetaValidator(v, nil, nil) -} - -// Reset implements (reset! a v). -// -//lg:native -//lg:name reset! -func Reset(a vm.Value, v vm.Value) (vm.Value, error) { - at, ok := a.(*vm.Atom) - if !ok { - return vm.NIL, fmt.Errorf("reset expected Atom") - } - return at.Reset(v) -} - // Namespace implements (namespace x) for Named values. // //lg:native @@ -703,27 +505,6 @@ func regexSubmatchValue(s string, indices []int) vm.Value { return regexSubmatchVector(s, indices) } -// ReFind implements (re-find re s), reusing regexSubmatchValue so the -// group-shaped result matches the interpreter path exactly. -// -//lg:native -//lg:name re-find -func ReFind(re vm.Value, s vm.Value) (vm.Value, error) { - r, ok := re.(*vm.Regex) - if !ok { - return vm.NIL, fmt.Errorf("re-find expected Regex") - } - str, ok := s.(vm.String) - if !ok { - return vm.NIL, fmt.Errorf("re-find expected String") - } - indices := r.FindStringSubmatchIndex(string(str)) - if indices == nil { - return vm.NIL, nil - } - return regexSubmatchValue(string(str), indices), nil -} - // Some implements (some pred coll). Body extracted verbatim from lang.go's // closure (including the chunked fast path) rather than retyped, so the // direct-call path cannot drift from the interpreter path. Needs the @@ -839,79 +620,3 @@ func rangeInt(v vm.Value, what string) (vm.Int, error) { return 0, fmt.Errorf("range %s must be an integer, got %s", what, v.Type().Name()) } - -// rangeVals is the shared body of clojure.core/range, extracted verbatim from -// lang.go's closure so the direct-call arities below and the interpreter path -// cannot diverge. -func rangeVals(vs []vm.Value) (vm.Value, error) { - if len(vs) == 0 { - // Infinite range: (range) -> lazy seq 0, 1, 2, ... - return vm.NewInfiniteRange(0, 1), nil - } - if len(vs) > 3 { - return vm.NIL, fmt.Errorf("wrong number of arguments %d", len(vs)) - } - var start, end, step vm.Int - step = 1 - var err error - var endArg vm.Value - switch len(vs) { - case 1: - endArg = vs[0] - case 2: - endArg = vs[1] - if start, err = rangeInt(vs[0], "start"); err != nil { - return vm.NIL, err - } - case 3: - endArg = vs[1] - if start, err = rangeInt(vs[0], "start"); err != nil { - return vm.NIL, err - } - if step, err = rangeInt(vs[2], "step"); err != nil { - return vm.NIL, err - } - } - // A float end still yields integers, like the JVM: infinite - // for ##Inf toward the step, else every int short of the end - // ((range 2 5.29) => 2 3 4 5). - if f, ok := endArg.(vm.Float); ok { - if math.IsInf(float64(f), 0) { - if (f > 0 && step > 0) || (f < 0 && step < 0) { - return vm.NewInfiniteRange(int(start), int(step)), nil - } - return vm.NewRange(0, 0, 1), nil - } - if step > 0 { - endArg = vm.Int(math.Ceil(float64(f))) - } else { - endArg = vm.Int(math.Floor(float64(f))) - } - } - if end, err = rangeInt(endArg, "end"); err != nil { - return vm.NIL, err - } - return vm.NewRange(start, end, step), nil -} - -// Range1 implements (range end). -// -//lg:native -//lg:name range -func Range1(end vm.Value) (vm.Value, error) { return rangeVals([]vm.Value{end}) } - -// Range2 implements (range start end). -// -//lg:native -//lg:name range -func Range2(start, end vm.Value) (vm.Value, error) { - return rangeVals([]vm.Value{start, end}) -} - -// Range3 implements (range start end step). -// -//lg:native -//lg:name range -func Range3(start, end, step vm.Value) (vm.Value, error) { - return rangeVals([]vm.Value{start, end, step}) -} diff --git a/pkg/rt/native_prims_lifecycle.go b/pkg/rt/native_prims_lifecycle.go index 972c51b40..33abefd17 100644 --- a/pkg/rt/native_prims_lifecycle.go +++ b/pkg/rt/native_prims_lifecycle.go @@ -7,12 +7,22 @@ package rt import ( + "fmt" + "os" + "sort" "strings" "sync" "github.com/nooga/let-go/pkg/vm" ) +// regPrimDebug, when LG_REGPRIM_DEBUG is set, logs every generated-primitive +// registration (name, requested ns, resolved canonical ns, whether it landed +// in the canonical ns). It is the per-primitive trace used to root-cause a +// batch of newly hoisted //lg:native primitives without bisecting the whole +// set: grep the run for `landed-canonical=false`. +var regPrimDebug = os.Getenv("LG_REGPRIM_DEBUG") != "" + // Generated-primitive binding lifecycle. // // RegisterGeneratedPrimitives (zz_primitives_generated.go) Defs each native @@ -35,7 +45,45 @@ var ( // emitted for native-module callees consult this before taking the baked // direct call; on false they fall back to the var-dispatch trampoline so the // override is observed across lowered function boundaries. -func NativePrimsIntact() bool { return vm.GuardedRootsIntact() } +func NativePrimsIntact() bool { + if vm.GuardedRootsIntact() { + return true + } + // Off the fast path (a root deviated): under LG_GUARD_DEBUG, name the + // offending native primitive(s) — the diagnostic that pinpoints which + // hoisted primitive is being shadowed instead of a bare intact=false. + if guardDebug { + fmt.Fprintf(os.Stderr, "[GUARD] deviated: %v\n", deviatedGuardedVars()) + } + return false +} + +var guardDebug = os.Getenv("LG_GUARD_DEBUG") != "" + +// deviatedGuardedVars lists every interned var whose guarded root has deviated +// from its canonical native root, "/". Diagnostic only. +func deviatedGuardedVars() []string { + nsMu.RLock() + names := make([]string, 0, len(nsRegistry)) + for k := range nsRegistry { + names = append(names, k) + } + nsMu.RUnlock() + var dev []string + for _, nsName := range names { + ns := LookupNS(nsName) + if ns == nil { + continue + } + for sym, v := range ns.AllVars() { + if v.GuardDeviated() { + dev = append(dev, nsName+"/"+string(sym)) + } + } + } + sort.Strings(dev) + return dev +} // guardModuleVars marks the CURRENT root of every var a native module // direct-calls (corefns seq/first/…, builtins vector/cons/…) as canonical, @@ -85,6 +133,14 @@ func defGeneratedPrimitive(ns *vm.Namespace, nsName, name string, v vm.Value) { // boundaries. setPrimitiveRoot(ns, name, v).GuardRoot() canonical := resolveNSAlias(nsName) + if regPrimDebug { + landed := false + if cns := LookupNS(canonical); cns != nil { + landed = cns.LookupLocal(vm.Symbol(name)) != nil + } + fmt.Fprintf(os.Stderr, "[REGPRIM] %s/%s requested-ns=%s canonical=%s landed-canonical=%v\n", + nsName, name, nsName, canonical, landed) + } genPrimMu.Lock() m := genPrimBindings[canonical] if m == nil { @@ -95,6 +151,67 @@ func defGeneratedPrimitive(ns *vm.Namespace, nsName, name string, v vm.Value) { genPrimMu.Unlock() } +// AuditGeneratedPrimitives verifies that every recorded generated primitive is +// actually bound in its canonical namespace, and returns one human-readable +// line per primitive that is NOT — including where the name IS bound instead, +// if anywhere. It never panics and never stops at the first problem: it is the +// non-terminating diagnostic run around the bootstrap core.lg compile, so a +// batch of newly hoisted //lg:native primitives surfaces ALL its registration +// failures at once (`+ registered under "clojure.core", not canonical "core"`) +// rather than the compile dying on the first `Can't resolve X`. Empty slice = +// every generated primitive resolves in its canonical namespace. +func AuditGeneratedPrimitives() []string { + type binding struct { + ns, name string + } + genPrimMu.RLock() + bindings := make([]binding, 0, len(genPrimBindings)) + for nsName, m := range genPrimBindings { + for name := range m { + bindings = append(bindings, binding{nsName, name}) + } + } + genPrimMu.RUnlock() + + var problems []string + for _, b := range bindings { + ns := LookupNS(b.ns) + if ns == nil { + problems = append(problems, fmt.Sprintf("%s/%s: canonical namespace does not exist", b.ns, b.name)) + continue + } + if v := ns.LookupLocal(vm.Symbol(b.name)); v == nil || !v.IsBound() { + problems = append(problems, fmt.Sprintf("%s/%s: not bound in canonical ns%s", b.ns, b.name, whereNameBound(b.name, resolveNSAlias(b.ns)))) + } + } + sort.Strings(problems) + return problems +} + +// whereNameBound scans the namespace registry for any namespace OTHER than +// exclude that has name bound, returning a " (found bound in: …)" suffix so a +// misregistered primitive points straight at the namespace it landed in (the +// exact signature of the alias-resolution bug: bound in "clojure.core", absent +// from canonical "core"). Empty string when the name is bound nowhere else. +func whereNameBound(name, exclude string) string { + nsMu.RLock() + defer nsMu.RUnlock() + var found []string + for k, ns := range nsRegistry { + if k == exclude { + continue + } + if v := ns.LookupLocal(vm.Symbol(name)); v != nil && v.IsBound() { + found = append(found, k) + } + } + if len(found) == 0 { + return "" + } + sort.Strings(found) + return " (found bound in: " + strings.Join(found, ", ") + ")" +} + // ReapplyGeneratedPrimitives restores the recorded native adapters on a // namespace after one of its chunks executed outside the on-demand loader — // the compiler's eager hybrid-namespace pass (loadPrecompiledBundle) runs diff --git a/pkg/rt/zz_primitives_generated.go b/pkg/rt/zz_primitives_generated.go index 503b9058c..809b12654 100644 --- a/pkg/rt/zz_primitives_generated.go +++ b/pkg/rt/zz_primitives_generated.go @@ -6,9 +6,2450 @@ package rt import ( "fmt" + "github.com/nooga/let-go/pkg/vm" +) + +func _adapt_CorePlus(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CorePlus(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreMul(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreMul(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreSub(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreSub(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreDiv(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreDiv(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CorePlusP(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CorePlusP(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreMulP(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreMulP(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreSubP(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreSubP(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreUncheckedAdd(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreUncheckedAdd(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreUncheckedSubtract(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreUncheckedSubtract(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreUncheckedMultiply(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreUncheckedMultiply(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreUncheckedNegate(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreUncheckedNegate(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreUncheckedDivideInt(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreUncheckedDivideInt(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreUncheckedLong(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreUncheckedLong(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreUncheckedInt(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreUncheckedInt(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreUncheckedShort(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreUncheckedShort(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreUncheckedByte(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreUncheckedByte(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreUncheckedChar(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreUncheckedChar(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreUncheckedDouble(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreUncheckedDouble(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreUncheckedFloat(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreUncheckedFloat(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreMod(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreMod(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreAbs(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreAbs(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreNot(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreNot(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreComplement(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreComplement(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreSetMacro(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreSetMacro(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreGensym(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreGensym(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreVector(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreVector(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreHashMap(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreHashMap(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreArrayMap(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreArrayMap(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreSortedMap(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreSortedMap(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreSortedSet(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreSortedSet(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreSortedMapBy(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreSortedMapBy(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreSortedSetBy(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreSortedSetBy(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreChunkFirst(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreChunkFirst(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreChunkRest(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreChunkRest(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreChunkNext(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreChunkNext(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreChunkConsF(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreChunkConsF(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreChunkedSeqP(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreChunkedSeqP(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreChunkBufferF(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreChunkBufferF(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreChunkAppendF(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreChunkAppendF(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreChunkF(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreChunkF(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreRangef(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreRangef(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreKeyword(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreKeyword(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreSymbolf(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreSymbolf(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreAssoc(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreAssoc(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreDissoc(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreDissoc(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreCons(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreCons(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreDisj(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreDisj(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreContains(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreContains(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreSecond(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreSecond(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreIsList(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreIsList(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreEmpty(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreEmpty(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreKeyf(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreKeyf(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreValf(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreValf(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreCount(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreCount(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreExcludeInCurrentNs(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreExcludeInCurrentNs(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreUse(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreUse(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreAliasf(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreAliasf(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreReferList(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreReferList(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreMethodInvoke(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreMethodInvoke(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreRegisterHostMethod(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreRegisterHostMethod(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreRegisterHostClass(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreRegisterHostClass(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreConcat(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreConcat(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreSlurp(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreSlurp(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreSpit(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreSpit(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreAtom(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreAtom(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreReset(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreReset(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreCompareAndSet(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreCompareAndSet(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreResetVals(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreResetVals(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreChanf(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreChanf(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreScopeClose(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreScopeClose(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreScopeLive(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreScopeLive(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreScopeQmark(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreScopeQmark(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreMax(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreMax(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreMin(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreMin(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreStrReplace(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreStrReplace(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreLongf(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreLongf(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreFloatf(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreFloatf(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreDoublef(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreDoublef(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreIsNumber(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreIsNumber(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreIsFloat(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreIsFloat(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreIsInt(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreIsInt(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreChar(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreChar(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreRegex(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreRegex(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CorePeek(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CorePeek(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CorePop(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CorePop(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreIterate(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreIterate(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreRepeat(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreRepeat(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreRefer(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreRefer(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreFormatf(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreFormatf(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreRandf(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreRandf(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreRandInt(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreRandInt(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreRandNth(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreRandNth(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreShuffle(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreShuffle(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreSetRandSeedFn(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreSetRandSeedFn(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreTransientf(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreTransientf(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CorePersistentf(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CorePersistentf(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreConjBang(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreConjBang(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreAssocBang(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreAssocBang(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreDisjBang(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreDisjBang(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreDissocBang(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreDissocBang(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreMakeRecordType(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreMakeRecordType(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreMakeRecord(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreMakeRecord(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreIsRecord(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreIsRecord(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreMakeDType(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreMakeDType(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreMakeDTypeInstance(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreMakeDTypeInstance(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreSetField(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreSetField(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreDefProtocol(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreDefProtocol(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreExtendType(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreExtendType(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreMakeProtocolFn(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreMakeProtocolFn(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreSetInvokableProtocol(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreSetInvokableProtocol(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreSetDerefProtocol(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreSetDerefProtocol(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreSatisfies(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreSatisfies(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreDefMulti(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreDefMulti(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreDefMethod(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreDefMethod(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CorePrStr(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CorePrStr(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CorePrnStr(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CorePrnStr(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CorePrintStr(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CorePrintStr(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CorePrintlnStr(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CorePrintlnStr(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreReFind(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreReFind(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreReMatches(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreReMatches(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreReSeq(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreReSeq(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreRequiref(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreRequiref(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreFindNs(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreFindNs(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreResolvef(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreResolvef(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreAllNs(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreAllNs(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreTheNs(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreTheNs(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreNsPublics(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreNsPublics(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreFindVar(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreFindVar(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreGetMethod(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreGetMethod(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreEnumerationSeq(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreEnumerationSeq(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreLazySeq(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreLazySeq(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreWithMeta(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreWithMeta(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreThrowf(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreThrowf(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreExInfo(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreExInfo(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreExMessage(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreExMessage(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreExData(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreExData(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreExCause(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreExCause(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreDelayStar(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreDelayStar(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreForce(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreForce(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreIsDelay(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreIsDelay(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreIsRealized(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreIsRealized(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreVolatilef(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreVolatilef(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreVreset(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreVreset(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreReducedf(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreReducedf(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreIsReducedf(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreIsReducedf(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreBitAnd(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreBitAnd(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreBitOr(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreBitOr(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreBitXor(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreBitXor(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreBitNot(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreBitNot(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreBitShiftLeft(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreBitShiftLeft(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreBitShiftRight(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreBitShiftRight(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreUnsignedBitShiftRight(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreUnsignedBitShiftRight(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreBitTest(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreBitTest(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreBitSet(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreBitSet(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreBitClear(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreBitClear(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreBitAndNot(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreBitAndNot(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreBitFlip(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreBitFlip(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreReGroups(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreReGroups(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CorePromisef(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CorePromisef(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreDeliver(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreDeliver(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreAddTap(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreAddTap(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreRemoveTap(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreRemoveTap(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreTapBang(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreTapBang(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreAddWatch(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreAddWatch(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreRemoveWatch(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreRemoveWatch(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreGetValidator(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreGetValidator(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreSubvecf(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreSubvecf(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreIsDouble(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreIsDouble(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreInstancep(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreInstancep(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreIsIFn(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreIsIFn(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreIdentical(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreIdentical(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreAnyp(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreAnyp(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreUnreduced(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreUnreduced(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreEnsureReduced(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreEnsureReduced(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreBigintf(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreBigintf(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreIsRatio(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreIsRatio(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreIsDecimal(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreIsDecimal(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreIsSorted(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreIsSorted(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreIsMap(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreIsMap(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreIsSet(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreIsSet(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreIsMapEntry(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreIsMapEntry(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreIsLazySeq(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreIsLazySeq(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreIsReversible(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreIsReversible(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreRseqf(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreRseqf(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreNumeratorf(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreNumeratorf(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreDenominatorf(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreDenominatorf(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreBigdecf(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreBigdecf(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreRoundBigdec(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreRoundBigdec(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreRationalizef(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreRationalizef(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreQuotf(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreQuotf(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreRemf(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreRemf(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreHashf(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreHashf(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreParseDouble(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreParseDouble(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreParseBool(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreParseBool(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreIsNaN(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreIsNaN(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreIsInfinite(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreIsInfinite(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreIsBool(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreIsBool(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreIsChar(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreIsChar(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreIsVar(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreIsVar(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreByteArrayf(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreByteArrayf(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreObjectArrayf(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreObjectArrayf(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreMakeArrayf(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreMakeArrayf(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreAgetf(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreAgetf(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreAsetf(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreAsetf(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreAlengthf(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreAlengthf(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreAclonef(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreAclonef(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreBytesf(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreBytesf(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreDoublesf(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreDoublesf(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreBytesP(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreBytesP(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreVarGet(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreVarGet(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreBoundQ(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreBoundQ(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreCopyFormSource(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreCopyFormSource(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreChunkToFnFn(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreChunkToFnFn(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} - "github.com/nooga/let-go/pkg/vm" -) +func _adapt_CoreMakeMultiArityFn(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreMakeMultiArityFn(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreInternf(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreInternf(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreApplyDefMetaf(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreApplyDefMetaf(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreCreateNsf(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreCreateNsf(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CorePopBang(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CorePopBang(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreIsUUID(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreIsUUID(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreIsInst(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreIsInst(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreParseUUID(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreParseUUID(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} + +func _adapt_CoreNumericEq(vs []vm.Value) (vm.Value, error) { + if len(vs) < 0 { + return vm.NIL, fmt.Errorf("wrong number of args (%d), expected at least 0", len(vs)) + } + r, err := CoreNumericEq(vs...) + if err != nil { + return vm.NIL, err + } + return r, nil +} func _adapt_Name(vs []vm.Value) (vm.Value, error) { if len(vs) != 1 { @@ -234,176 +2675,6 @@ func _adapt_Reduce3_arity3(ec *vm.ExecContext, vs []vm.Value) (vm.Value, error) return r, nil } -func _adapt_Symbol(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("wrong number of args (%d), expected 1", len(vs)) - } - a0 := vs[0] - r, err := Symbol(a0) - if err != nil { - return vm.NIL, err - } - return r, nil -} - -func _adapt_Assoc(vs []vm.Value) (vm.Value, error) { - switch len(vs) { - case 3: - return _adapt_Assoc_arity3(vs) - case 5: - return _adapt_Assoc5_arity5(vs) - } - return vm.NIL, fmt.Errorf("wrong number of args (%d)", len(vs)) -} - -func _adapt_Assoc_arity3(vs []vm.Value) (vm.Value, error) { - a0 := vs[0] - a1 := vs[1] - a2 := vs[2] - r, err := Assoc(a0, a1, a2) - if err != nil { - return vm.NIL, err - } - return r, nil -} - -func _adapt_Assoc5_arity5(vs []vm.Value) (vm.Value, error) { - a0 := vs[0] - a1 := vs[1] - a2 := vs[2] - a3 := vs[3] - a4 := vs[4] - r, err := Assoc5(a0, a1, a2, a3, a4) - if err != nil { - return vm.NIL, err - } - return r, nil -} - -func _adapt_AssocBang(vs []vm.Value) (vm.Value, error) { - if len(vs) != 3 { - return vm.NIL, fmt.Errorf("wrong number of args (%d), expected 3", len(vs)) - } - a0 := vs[0] - a1 := vs[1] - a2 := vs[2] - r, err := AssocBang(a0, a1, a2) - if err != nil { - return vm.NIL, err - } - return r, nil -} - -func _adapt_Swap(ec *vm.ExecContext, vs []vm.Value) (vm.Value, error) { - switch len(vs) { - case 2: - return _adapt_Swap_arity2(ec, vs) - case 3: - return _adapt_Swap3_arity3(ec, vs) - case 4: - return _adapt_Swap4_arity4(ec, vs) - case 5: - return _adapt_Swap5_arity5(ec, vs) - } - return vm.NIL, fmt.Errorf("wrong number of args (%d)", len(vs)) -} - -func _adapt_Swap_arity2(ec *vm.ExecContext, vs []vm.Value) (vm.Value, error) { - a0 := vs[0] - a1 := vs[1] - r, err := Swap(ec, a0, a1) - if err != nil { - return vm.NIL, err - } - return r, nil -} - -func _adapt_Swap3_arity3(ec *vm.ExecContext, vs []vm.Value) (vm.Value, error) { - a0 := vs[0] - a1 := vs[1] - a2 := vs[2] - r, err := Swap3(ec, a0, a1, a2) - if err != nil { - return vm.NIL, err - } - return r, nil -} - -func _adapt_Swap4_arity4(ec *vm.ExecContext, vs []vm.Value) (vm.Value, error) { - a0 := vs[0] - a1 := vs[1] - a2 := vs[2] - a3 := vs[3] - r, err := Swap4(ec, a0, a1, a2, a3) - if err != nil { - return vm.NIL, err - } - return r, nil -} - -func _adapt_Swap5_arity5(ec *vm.ExecContext, vs []vm.Value) (vm.Value, error) { - a0 := vs[0] - a1 := vs[1] - a2 := vs[2] - a3 := vs[3] - a4 := vs[4] - r, err := Swap5(ec, a0, a1, a2, a3, a4) - if err != nil { - return vm.NIL, err - } - return r, nil -} - -func _adapt_NotEq(vs []vm.Value) (vm.Value, error) { - if len(vs) != 2 { - return vm.NIL, fmt.Errorf("wrong number of args (%d), expected 2", len(vs)) - } - a0 := vs[0] - a1 := vs[1] - r, err := NotEq(a0, a1) - if err != nil { - return vm.NIL, err - } - return r, nil -} - -func _adapt_IsMap(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("wrong number of args (%d), expected 1", len(vs)) - } - a0 := vs[0] - r, err := IsMap(a0) - if err != nil { - return vm.NIL, err - } - return r, nil -} - -func _adapt_Atom(vs []vm.Value) (vm.Value, error) { - if len(vs) != 1 { - return vm.NIL, fmt.Errorf("wrong number of args (%d), expected 1", len(vs)) - } - a0 := vs[0] - r, err := Atom(a0) - if err != nil { - return vm.NIL, err - } - return r, nil -} - -func _adapt_Reset(vs []vm.Value) (vm.Value, error) { - if len(vs) != 2 { - return vm.NIL, fmt.Errorf("wrong number of args (%d), expected 2", len(vs)) - } - a0 := vs[0] - a1 := vs[1] - r, err := Reset(a0, a1) - if err != nil { - return vm.NIL, err - } - return r, nil -} - func _adapt_Namespace(vs []vm.Value) (vm.Value, error) { if len(vs) != 1 { return vm.NIL, fmt.Errorf("wrong number of args (%d), expected 1", len(vs)) @@ -441,19 +2712,6 @@ func _adapt_PopBinding(ec *vm.ExecContext, vs []vm.Value) (vm.Value, error) { return r, nil } -func _adapt_ReFind(vs []vm.Value) (vm.Value, error) { - if len(vs) != 2 { - return vm.NIL, fmt.Errorf("wrong number of args (%d), expected 2", len(vs)) - } - a0 := vs[0] - a1 := vs[1] - r, err := ReFind(a0, a1) - if err != nil { - return vm.NIL, err - } - return r, nil -} - func _adapt_Some(ec *vm.ExecContext, vs []vm.Value) (vm.Value, error) { if len(vs) != 2 { return vm.NIL, fmt.Errorf("wrong number of args (%d), expected 2", len(vs)) @@ -479,132 +2737,721 @@ func _adapt_Int(vs []vm.Value) (vm.Value, error) { return r, nil } -func _adapt_Range1(vs []vm.Value) (vm.Value, error) { - switch len(vs) { - case 1: - return _adapt_Range1_arity1(vs) - case 2: - return _adapt_Range2_arity2(vs) - case 3: - return _adapt_Range3_arity3(vs) - } - return vm.NIL, fmt.Errorf("wrong number of args (%d)", len(vs)) -} - -func _adapt_Range1_arity1(vs []vm.Value) (vm.Value, error) { - a0 := vs[0] - r, err := Range1(a0) - if err != nil { - return vm.NIL, err - } - return r, nil -} - -func _adapt_Range2_arity2(vs []vm.Value) (vm.Value, error) { - a0 := vs[0] - a1 := vs[1] - r, err := Range2(a0, a1) - if err != nil { - return vm.NIL, err - } - return r, nil -} - -func _adapt_Range3_arity3(vs []vm.Value) (vm.Value, error) { - a0 := vs[0] - a1 := vs[1] - a2 := vs[2] - r, err := Range3(a0, a1, a2) - if err != nil { - return vm.NIL, err - } - return r, nil -} - func RegisterGeneratedPrimitives() { RegisterNativeModule(&NativeModule{ GoPkg: "github.com/nooga/let-go/pkg/rt", Namespace: "clojure.core", Fns: map[string]NativeDirectFn{ - "name": {GoIdent: "Name", LgName: "name", Arity: 1, ParamSpecs: []string{"vm.Value"}, ResultSpec: "string", NeedsError: true}, - "subs@2": {GoIdent: "Subs", LgName: "subs", Arity: 2, ParamSpecs: []string{"string", "int"}, ResultSpec: "string", NeedsError: true}, - "subs@3": {GoIdent: "Subs3", LgName: "subs", Arity: 3, ParamSpecs: []string{"string", "int", "int"}, ResultSpec: "string", NeedsError: true}, - "nth@2": {GoIdent: "Nth", LgName: "nth", Arity: 2, ParamSpecs: []string{"vm.Value", "int"}, ResultSpec: "vm.Value", NeedsError: true}, - "nth@3": {GoIdent: "Nth3", LgName: "nth", Arity: 3, ParamSpecs: []string{"vm.Value", "int", "vm.Value"}, ResultSpec: "vm.Value", NeedsError: true}, - "deref@1": {GoIdent: "Deref", LgName: "deref", Arity: 1, ParamSpecs: []string{"vm.Value"}, ResultSpec: "vm.Value", NeedsError: true}, - "deref@3": {GoIdent: "Deref3", LgName: "deref", Arity: 3, ParamSpecs: []string{"vm.Value", "int", "vm.Value"}, ResultSpec: "vm.Value", NeedsError: true}, - "str": {GoIdent: "Str", LgName: "str", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "string", NeedsError: true}, - "get@2": {GoIdent: "Get", LgName: "get", Arity: 2, ParamSpecs: []string{"vm.Value", "vm.Value"}, ResultSpec: "vm.Value", NeedsError: true}, - "get@3": {GoIdent: "Get3", LgName: "get", Arity: 3, ParamSpecs: []string{"vm.Value", "vm.Value", "vm.Value"}, ResultSpec: "vm.Value", NeedsError: true}, - "conj": {GoIdent: "Conj", LgName: "conj", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, - "reduce@2": {GoIdent: "Reduce", LgName: "reduce", Arity: 2, ParamSpecs: []string{"vm.Value", "vm.Value"}, ResultSpec: "vm.Value", NeedsError: true, NeedsEC: true}, - "reduce@3": {GoIdent: "Reduce3", LgName: "reduce", Arity: 3, ParamSpecs: []string{"vm.Value", "vm.Value", "vm.Value"}, ResultSpec: "vm.Value", NeedsError: true, NeedsEC: true}, - "symbol": {GoIdent: "Symbol", LgName: "symbol", Arity: 1, ParamSpecs: []string{"vm.Value"}, ResultSpec: "vm.Value", NeedsError: true}, - "assoc@3": {GoIdent: "Assoc", LgName: "assoc", Arity: 3, ParamSpecs: []string{"vm.Value", "vm.Value", "vm.Value"}, ResultSpec: "vm.Value", NeedsError: true}, - "assoc@5": {GoIdent: "Assoc5", LgName: "assoc", Arity: 5, ParamSpecs: []string{"vm.Value", "vm.Value", "vm.Value", "vm.Value", "vm.Value"}, ResultSpec: "vm.Value", NeedsError: true}, - "assoc!": {GoIdent: "AssocBang", LgName: "assoc!", Arity: 3, ParamSpecs: []string{"vm.Value", "vm.Value", "vm.Value"}, ResultSpec: "vm.Value", NeedsError: true}, - "swap!@2": {GoIdent: "Swap", LgName: "swap!", Arity: 2, ParamSpecs: []string{"vm.Value", "vm.Value"}, ResultSpec: "vm.Value", NeedsError: true, NeedsEC: true}, - "swap!@3": {GoIdent: "Swap3", LgName: "swap!", Arity: 3, ParamSpecs: []string{"vm.Value", "vm.Value", "vm.Value"}, ResultSpec: "vm.Value", NeedsError: true, NeedsEC: true}, - "swap!@4": {GoIdent: "Swap4", LgName: "swap!", Arity: 4, ParamSpecs: []string{"vm.Value", "vm.Value", "vm.Value", "vm.Value"}, ResultSpec: "vm.Value", NeedsError: true, NeedsEC: true}, - "swap!@5": {GoIdent: "Swap5", LgName: "swap!", Arity: 5, ParamSpecs: []string{"vm.Value", "vm.Value", "vm.Value", "vm.Value", "vm.Value"}, ResultSpec: "vm.Value", NeedsError: true, NeedsEC: true}, - "not=": {GoIdent: "NotEq", LgName: "not=", Arity: 2, ParamSpecs: []string{"vm.Value", "vm.Value"}, ResultSpec: "vm.Value", NeedsError: true}, - "map?": {GoIdent: "IsMap", LgName: "map?", Arity: 1, ParamSpecs: []string{"vm.Value"}, ResultSpec: "vm.Value", NeedsError: true}, - "atom": {GoIdent: "Atom", LgName: "atom", Arity: 1, ParamSpecs: []string{"vm.Value"}, ResultSpec: "vm.Value", NeedsError: true}, - "reset!": {GoIdent: "Reset", LgName: "reset!", Arity: 2, ParamSpecs: []string{"vm.Value", "vm.Value"}, ResultSpec: "vm.Value", NeedsError: true}, - "namespace": {GoIdent: "Namespace", LgName: "namespace", Arity: 1, ParamSpecs: []string{"vm.Value"}, ResultSpec: "vm.Value", NeedsError: true}, - "push-binding!": {GoIdent: "PushBinding", LgName: "push-binding!", Arity: 2, ParamSpecs: []string{"vm.Value", "vm.Value"}, ResultSpec: "vm.Value", NeedsError: true, NeedsEC: true}, - "pop-binding!": {GoIdent: "PopBinding", LgName: "pop-binding!", Arity: 1, ParamSpecs: []string{"vm.Value"}, ResultSpec: "vm.Value", NeedsError: true, NeedsEC: true}, - "re-find": {GoIdent: "ReFind", LgName: "re-find", Arity: 2, ParamSpecs: []string{"vm.Value", "vm.Value"}, ResultSpec: "vm.Value", NeedsError: true}, - "some": {GoIdent: "Some", LgName: "some", Arity: 2, ParamSpecs: []string{"vm.Value", "vm.Value"}, ResultSpec: "vm.Value", NeedsError: true, NeedsEC: true}, - "int": {GoIdent: "Int", LgName: "int", Arity: 1, ParamSpecs: []string{"vm.Value"}, ResultSpec: "vm.Value", NeedsError: true}, - "range@1": {GoIdent: "Range1", LgName: "range", Arity: 1, ParamSpecs: []string{"vm.Value"}, ResultSpec: "vm.Value", NeedsError: true}, - "range@2": {GoIdent: "Range2", LgName: "range", Arity: 2, ParamSpecs: []string{"vm.Value", "vm.Value"}, ResultSpec: "vm.Value", NeedsError: true}, - "range@3": {GoIdent: "Range3", LgName: "range", Arity: 3, ParamSpecs: []string{"vm.Value", "vm.Value", "vm.Value"}, ResultSpec: "vm.Value", NeedsError: true}, + "+": {GoIdent: "CorePlus", LgName: "+", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "*": {GoIdent: "CoreMul", LgName: "*", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "-": {GoIdent: "CoreSub", LgName: "-", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "/": {GoIdent: "CoreDiv", LgName: "/", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "+'": {GoIdent: "CorePlusP", LgName: "+'", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "*'": {GoIdent: "CoreMulP", LgName: "*'", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "-'": {GoIdent: "CoreSubP", LgName: "-'", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "unchecked-add": {GoIdent: "CoreUncheckedAdd", LgName: "unchecked-add", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "unchecked-subtract": {GoIdent: "CoreUncheckedSubtract", LgName: "unchecked-subtract", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "unchecked-multiply": {GoIdent: "CoreUncheckedMultiply", LgName: "unchecked-multiply", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "unchecked-negate": {GoIdent: "CoreUncheckedNegate", LgName: "unchecked-negate", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "unchecked-divide-int": {GoIdent: "CoreUncheckedDivideInt", LgName: "unchecked-divide-int", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "unchecked-long": {GoIdent: "CoreUncheckedLong", LgName: "unchecked-long", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "unchecked-int": {GoIdent: "CoreUncheckedInt", LgName: "unchecked-int", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "unchecked-short": {GoIdent: "CoreUncheckedShort", LgName: "unchecked-short", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "unchecked-byte": {GoIdent: "CoreUncheckedByte", LgName: "unchecked-byte", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "unchecked-char": {GoIdent: "CoreUncheckedChar", LgName: "unchecked-char", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "unchecked-double": {GoIdent: "CoreUncheckedDouble", LgName: "unchecked-double", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "unchecked-float": {GoIdent: "CoreUncheckedFloat", LgName: "unchecked-float", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "mod": {GoIdent: "CoreMod", LgName: "mod", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "abs": {GoIdent: "CoreAbs", LgName: "abs", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "not": {GoIdent: "CoreNot", LgName: "not", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "complement": {GoIdent: "CoreComplement", LgName: "complement", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "set-macro!": {GoIdent: "CoreSetMacro", LgName: "set-macro!", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "gensym": {GoIdent: "CoreGensym", LgName: "gensym", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "vector": {GoIdent: "CoreVector", LgName: "vector", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "hash-map": {GoIdent: "CoreHashMap", LgName: "hash-map", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "array-map": {GoIdent: "CoreArrayMap", LgName: "array-map", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "sorted-map": {GoIdent: "CoreSortedMap", LgName: "sorted-map", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "sorted-set": {GoIdent: "CoreSortedSet", LgName: "sorted-set", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "sorted-map-by": {GoIdent: "CoreSortedMapBy", LgName: "sorted-map-by", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "sorted-set-by": {GoIdent: "CoreSortedSetBy", LgName: "sorted-set-by", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "chunk-first": {GoIdent: "CoreChunkFirst", LgName: "chunk-first", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "chunk-rest": {GoIdent: "CoreChunkRest", LgName: "chunk-rest", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "chunk-next": {GoIdent: "CoreChunkNext", LgName: "chunk-next", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "chunk-cons": {GoIdent: "CoreChunkConsF", LgName: "chunk-cons", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "chunked-seq?": {GoIdent: "CoreChunkedSeqP", LgName: "chunked-seq?", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "chunk-buffer": {GoIdent: "CoreChunkBufferF", LgName: "chunk-buffer", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "chunk-append": {GoIdent: "CoreChunkAppendF", LgName: "chunk-append", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "chunk": {GoIdent: "CoreChunkF", LgName: "chunk", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "range": {GoIdent: "CoreRangef", LgName: "range", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "keyword": {GoIdent: "CoreKeyword", LgName: "keyword", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "symbol": {GoIdent: "CoreSymbolf", LgName: "symbol", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "assoc": {GoIdent: "CoreAssoc", LgName: "assoc", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "dissoc": {GoIdent: "CoreDissoc", LgName: "dissoc", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "cons": {GoIdent: "CoreCons", LgName: "cons", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "disj": {GoIdent: "CoreDisj", LgName: "disj", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "contains?": {GoIdent: "CoreContains", LgName: "contains?", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "second": {GoIdent: "CoreSecond", LgName: "second", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "list?": {GoIdent: "CoreIsList", LgName: "list?", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "empty": {GoIdent: "CoreEmpty", LgName: "empty", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "key": {GoIdent: "CoreKeyf", LgName: "key", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "val": {GoIdent: "CoreValf", LgName: "val", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "count": {GoIdent: "CoreCount", LgName: "count", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "exclude-in-current-ns": {GoIdent: "CoreExcludeInCurrentNs", LgName: "exclude-in-current-ns", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "use": {GoIdent: "CoreUse", LgName: "use", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "alias": {GoIdent: "CoreAliasf", LgName: "alias", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "refer-list": {GoIdent: "CoreReferList", LgName: "refer-list", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + ".": {GoIdent: "CoreMethodInvoke", LgName: ".", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "register-host-method!": {GoIdent: "CoreRegisterHostMethod", LgName: "register-host-method!", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "register-host-class!": {GoIdent: "CoreRegisterHostClass", LgName: "register-host-class!", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "concat*": {GoIdent: "CoreConcat", LgName: "concat*", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "slurp": {GoIdent: "CoreSlurp", LgName: "slurp", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "spit": {GoIdent: "CoreSpit", LgName: "spit", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "atom": {GoIdent: "CoreAtom", LgName: "atom", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "reset!": {GoIdent: "CoreReset", LgName: "reset!", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "compare-and-set!": {GoIdent: "CoreCompareAndSet", LgName: "compare-and-set!", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "reset-vals!": {GoIdent: "CoreResetVals", LgName: "reset-vals!", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "chan": {GoIdent: "CoreChanf", LgName: "chan", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "scope-close!": {GoIdent: "CoreScopeClose", LgName: "scope-close!", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "scope-live": {GoIdent: "CoreScopeLive", LgName: "scope-live", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "scope?": {GoIdent: "CoreScopeQmark", LgName: "scope?", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "max": {GoIdent: "CoreMax", LgName: "max", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "min": {GoIdent: "CoreMin", LgName: "min", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "str-replace": {GoIdent: "CoreStrReplace", LgName: "str-replace", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "long": {GoIdent: "CoreLongf", LgName: "long", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "float": {GoIdent: "CoreFloatf", LgName: "float", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "double": {GoIdent: "CoreDoublef", LgName: "double", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "number?": {GoIdent: "CoreIsNumber", LgName: "number?", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "float?": {GoIdent: "CoreIsFloat", LgName: "float?", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "int?": {GoIdent: "CoreIsInt", LgName: "int?", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "char": {GoIdent: "CoreChar", LgName: "char", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "re-pattern": {GoIdent: "CoreRegex", LgName: "re-pattern", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "peek": {GoIdent: "CorePeek", LgName: "peek", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "pop": {GoIdent: "CorePop", LgName: "pop", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "iterate": {GoIdent: "CoreIterate", LgName: "iterate", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "repeat": {GoIdent: "CoreRepeat", LgName: "repeat", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "refer": {GoIdent: "CoreRefer", LgName: "refer", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "format": {GoIdent: "CoreFormatf", LgName: "format", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "rand": {GoIdent: "CoreRandf", LgName: "rand", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "rand-int": {GoIdent: "CoreRandInt", LgName: "rand-int", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "rand-nth": {GoIdent: "CoreRandNth", LgName: "rand-nth", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "shuffle": {GoIdent: "CoreShuffle", LgName: "shuffle", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "set-rand-seed!": {GoIdent: "CoreSetRandSeedFn", LgName: "set-rand-seed!", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "transient": {GoIdent: "CoreTransientf", LgName: "transient", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "persistent!": {GoIdent: "CorePersistentf", LgName: "persistent!", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "conj!": {GoIdent: "CoreConjBang", LgName: "conj!", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "assoc!": {GoIdent: "CoreAssocBang", LgName: "assoc!", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "disj!": {GoIdent: "CoreDisjBang", LgName: "disj!", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "dissoc!": {GoIdent: "CoreDissocBang", LgName: "dissoc!", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "make-record-type": {GoIdent: "CoreMakeRecordType", LgName: "make-record-type", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "make-record": {GoIdent: "CoreMakeRecord", LgName: "make-record", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "record?": {GoIdent: "CoreIsRecord", LgName: "record?", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "make-deftype": {GoIdent: "CoreMakeDType", LgName: "make-deftype", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "make-deftype-instance": {GoIdent: "CoreMakeDTypeInstance", LgName: "make-deftype-instance", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "set-field!": {GoIdent: "CoreSetField", LgName: "set-field!", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "defprotocol*": {GoIdent: "CoreDefProtocol", LgName: "defprotocol*", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "extend-type*": {GoIdent: "CoreExtendType", LgName: "extend-type*", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "make-protocol-fn": {GoIdent: "CoreMakeProtocolFn", LgName: "make-protocol-fn", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "-set-invokable-protocol!": {GoIdent: "CoreSetInvokableProtocol", LgName: "-set-invokable-protocol!", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "-set-deref-protocol!": {GoIdent: "CoreSetDerefProtocol", LgName: "-set-deref-protocol!", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "satisfies?": {GoIdent: "CoreSatisfies", LgName: "satisfies?", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "defmulti*": {GoIdent: "CoreDefMulti", LgName: "defmulti*", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "defmethod*": {GoIdent: "CoreDefMethod", LgName: "defmethod*", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "pr-str": {GoIdent: "CorePrStr", LgName: "pr-str", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "prn-str": {GoIdent: "CorePrnStr", LgName: "prn-str", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "print-str": {GoIdent: "CorePrintStr", LgName: "print-str", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "println-str": {GoIdent: "CorePrintlnStr", LgName: "println-str", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "re-find": {GoIdent: "CoreReFind", LgName: "re-find", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "re-matches": {GoIdent: "CoreReMatches", LgName: "re-matches", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "re-seq": {GoIdent: "CoreReSeq", LgName: "re-seq", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "require": {GoIdent: "CoreRequiref", LgName: "require", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "find-ns": {GoIdent: "CoreFindNs", LgName: "find-ns", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "resolve": {GoIdent: "CoreResolvef", LgName: "resolve", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "all-ns": {GoIdent: "CoreAllNs", LgName: "all-ns", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "the-ns": {GoIdent: "CoreTheNs", LgName: "the-ns", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "ns-publics": {GoIdent: "CoreNsPublics", LgName: "ns-publics", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "find-var": {GoIdent: "CoreFindVar", LgName: "find-var", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "get-method": {GoIdent: "CoreGetMethod", LgName: "get-method", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "enumeration-seq": {GoIdent: "CoreEnumerationSeq", LgName: "enumeration-seq", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "lazy-seq*": {GoIdent: "CoreLazySeq", LgName: "lazy-seq*", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "with-meta": {GoIdent: "CoreWithMeta", LgName: "with-meta", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "throw": {GoIdent: "CoreThrowf", LgName: "throw", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "ex-info": {GoIdent: "CoreExInfo", LgName: "ex-info", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "ex-message": {GoIdent: "CoreExMessage", LgName: "ex-message", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "ex-data": {GoIdent: "CoreExData", LgName: "ex-data", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "ex-cause": {GoIdent: "CoreExCause", LgName: "ex-cause", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "delay*": {GoIdent: "CoreDelayStar", LgName: "delay*", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "force": {GoIdent: "CoreForce", LgName: "force", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "delay?": {GoIdent: "CoreIsDelay", LgName: "delay?", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "realized?": {GoIdent: "CoreIsRealized", LgName: "realized?", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "volatile!": {GoIdent: "CoreVolatilef", LgName: "volatile!", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "vreset!": {GoIdent: "CoreVreset", LgName: "vreset!", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "reduced": {GoIdent: "CoreReducedf", LgName: "reduced", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "reduced?": {GoIdent: "CoreIsReducedf", LgName: "reduced?", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "bit-and": {GoIdent: "CoreBitAnd", LgName: "bit-and", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "bit-or": {GoIdent: "CoreBitOr", LgName: "bit-or", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "bit-xor": {GoIdent: "CoreBitXor", LgName: "bit-xor", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "bit-not": {GoIdent: "CoreBitNot", LgName: "bit-not", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "bit-shift-left": {GoIdent: "CoreBitShiftLeft", LgName: "bit-shift-left", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "bit-shift-right": {GoIdent: "CoreBitShiftRight", LgName: "bit-shift-right", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "unsigned-bit-shift-right": {GoIdent: "CoreUnsignedBitShiftRight", LgName: "unsigned-bit-shift-right", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "bit-test": {GoIdent: "CoreBitTest", LgName: "bit-test", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "bit-set": {GoIdent: "CoreBitSet", LgName: "bit-set", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "bit-clear": {GoIdent: "CoreBitClear", LgName: "bit-clear", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "bit-and-not": {GoIdent: "CoreBitAndNot", LgName: "bit-and-not", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "bit-flip": {GoIdent: "CoreBitFlip", LgName: "bit-flip", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "re-groups": {GoIdent: "CoreReGroups", LgName: "re-groups", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "promise": {GoIdent: "CorePromisef", LgName: "promise", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "deliver": {GoIdent: "CoreDeliver", LgName: "deliver", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "add-tap": {GoIdent: "CoreAddTap", LgName: "add-tap", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "remove-tap": {GoIdent: "CoreRemoveTap", LgName: "remove-tap", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "tap>": {GoIdent: "CoreTapBang", LgName: "tap>", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "add-watch": {GoIdent: "CoreAddWatch", LgName: "add-watch", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "remove-watch": {GoIdent: "CoreRemoveWatch", LgName: "remove-watch", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "get-validator": {GoIdent: "CoreGetValidator", LgName: "get-validator", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "subvec": {GoIdent: "CoreSubvecf", LgName: "subvec", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "double?": {GoIdent: "CoreIsDouble", LgName: "double?", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "instance?": {GoIdent: "CoreInstancep", LgName: "instance?", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "ifn?": {GoIdent: "CoreIsIFn", LgName: "ifn?", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "identical?": {GoIdent: "CoreIdentical", LgName: "identical?", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "any?": {GoIdent: "CoreAnyp", LgName: "any?", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "unreduced": {GoIdent: "CoreUnreduced", LgName: "unreduced", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "ensure-reduced": {GoIdent: "CoreEnsureReduced", LgName: "ensure-reduced", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "bigint": {GoIdent: "CoreBigintf", LgName: "bigint", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "ratio?": {GoIdent: "CoreIsRatio", LgName: "ratio?", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "decimal?": {GoIdent: "CoreIsDecimal", LgName: "decimal?", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "sorted?": {GoIdent: "CoreIsSorted", LgName: "sorted?", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "map?": {GoIdent: "CoreIsMap", LgName: "map?", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "set?": {GoIdent: "CoreIsSet", LgName: "set?", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "map-entry?": {GoIdent: "CoreIsMapEntry", LgName: "map-entry?", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "lazy-seq?": {GoIdent: "CoreIsLazySeq", LgName: "lazy-seq?", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "reversible?": {GoIdent: "CoreIsReversible", LgName: "reversible?", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "rseq": {GoIdent: "CoreRseqf", LgName: "rseq", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "numerator": {GoIdent: "CoreNumeratorf", LgName: "numerator", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "denominator": {GoIdent: "CoreDenominatorf", LgName: "denominator", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "bigdec": {GoIdent: "CoreBigdecf", LgName: "bigdec", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "round-bigdec": {GoIdent: "CoreRoundBigdec", LgName: "round-bigdec", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "rationalize": {GoIdent: "CoreRationalizef", LgName: "rationalize", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "quot": {GoIdent: "CoreQuotf", LgName: "quot", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "rem": {GoIdent: "CoreRemf", LgName: "rem", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "hash": {GoIdent: "CoreHashf", LgName: "hash", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "parse-double": {GoIdent: "CoreParseDouble", LgName: "parse-double", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "parse-boolean": {GoIdent: "CoreParseBool", LgName: "parse-boolean", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "NaN?": {GoIdent: "CoreIsNaN", LgName: "NaN?", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "infinite?": {GoIdent: "CoreIsInfinite", LgName: "infinite?", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "boolean?": {GoIdent: "CoreIsBool", LgName: "boolean?", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "char?": {GoIdent: "CoreIsChar", LgName: "char?", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "var?": {GoIdent: "CoreIsVar", LgName: "var?", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "byte-array": {GoIdent: "CoreByteArrayf", LgName: "byte-array", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "object-array": {GoIdent: "CoreObjectArrayf", LgName: "object-array", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "make-array": {GoIdent: "CoreMakeArrayf", LgName: "make-array", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "aget": {GoIdent: "CoreAgetf", LgName: "aget", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "aset": {GoIdent: "CoreAsetf", LgName: "aset", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "alength": {GoIdent: "CoreAlengthf", LgName: "alength", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "aclone": {GoIdent: "CoreAclonef", LgName: "aclone", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "bytes": {GoIdent: "CoreBytesf", LgName: "bytes", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "doubles": {GoIdent: "CoreDoublesf", LgName: "doubles", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "bytes?": {GoIdent: "CoreBytesP", LgName: "bytes?", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "var-get": {GoIdent: "CoreVarGet", LgName: "var-get", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "bound?": {GoIdent: "CoreBoundQ", LgName: "bound?", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "-copy-form-source!": {GoIdent: "CoreCopyFormSource", LgName: "-copy-form-source!", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "chunk->fn": {GoIdent: "CoreChunkToFnFn", LgName: "chunk->fn", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "make-multi-arity": {GoIdent: "CoreMakeMultiArityFn", LgName: "make-multi-arity", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "intern": {GoIdent: "CoreInternf", LgName: "intern", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "apply-def-meta!": {GoIdent: "CoreApplyDefMetaf", LgName: "apply-def-meta!", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "create-ns": {GoIdent: "CoreCreateNsf", LgName: "create-ns", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "pop!": {GoIdent: "CorePopBang", LgName: "pop!", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "uuid?": {GoIdent: "CoreIsUUID", LgName: "uuid?", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "inst?": {GoIdent: "CoreIsInst", LgName: "inst?", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "parse-uuid": {GoIdent: "CoreParseUUID", LgName: "parse-uuid", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "==": {GoIdent: "CoreNumericEq", LgName: "==", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "name": {GoIdent: "Name", LgName: "name", Arity: 1, ParamSpecs: []string{"vm.Value"}, ResultSpec: "string", NeedsError: true}, + "subs@2": {GoIdent: "Subs", LgName: "subs", Arity: 2, ParamSpecs: []string{"string", "int"}, ResultSpec: "string", NeedsError: true}, + "subs@3": {GoIdent: "Subs3", LgName: "subs", Arity: 3, ParamSpecs: []string{"string", "int", "int"}, ResultSpec: "string", NeedsError: true}, + "nth@2": {GoIdent: "Nth", LgName: "nth", Arity: 2, ParamSpecs: []string{"vm.Value", "int"}, ResultSpec: "vm.Value", NeedsError: true}, + "nth@3": {GoIdent: "Nth3", LgName: "nth", Arity: 3, ParamSpecs: []string{"vm.Value", "int", "vm.Value"}, ResultSpec: "vm.Value", NeedsError: true}, + "deref@1": {GoIdent: "Deref", LgName: "deref", Arity: 1, ParamSpecs: []string{"vm.Value"}, ResultSpec: "vm.Value", NeedsError: true}, + "deref@3": {GoIdent: "Deref3", LgName: "deref", Arity: 3, ParamSpecs: []string{"vm.Value", "int", "vm.Value"}, ResultSpec: "vm.Value", NeedsError: true}, + "str": {GoIdent: "Str", LgName: "str", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "string", NeedsError: true}, + "get@2": {GoIdent: "Get", LgName: "get", Arity: 2, ParamSpecs: []string{"vm.Value", "vm.Value"}, ResultSpec: "vm.Value", NeedsError: true}, + "get@3": {GoIdent: "Get3", LgName: "get", Arity: 3, ParamSpecs: []string{"vm.Value", "vm.Value", "vm.Value"}, ResultSpec: "vm.Value", NeedsError: true}, + "conj": {GoIdent: "Conj", LgName: "conj", Arity: -1, Variadic: true, ParamSpecs: []string{}, ResultSpec: "vm.Value", NeedsError: true}, + "reduce@2": {GoIdent: "Reduce", LgName: "reduce", Arity: 2, ParamSpecs: []string{"vm.Value", "vm.Value"}, ResultSpec: "vm.Value", NeedsError: true, NeedsEC: true}, + "reduce@3": {GoIdent: "Reduce3", LgName: "reduce", Arity: 3, ParamSpecs: []string{"vm.Value", "vm.Value", "vm.Value"}, ResultSpec: "vm.Value", NeedsError: true, NeedsEC: true}, + "namespace": {GoIdent: "Namespace", LgName: "namespace", Arity: 1, ParamSpecs: []string{"vm.Value"}, ResultSpec: "vm.Value", NeedsError: true}, + "push-binding!": {GoIdent: "PushBinding", LgName: "push-binding!", Arity: 2, ParamSpecs: []string{"vm.Value", "vm.Value"}, ResultSpec: "vm.Value", NeedsError: true, NeedsEC: true}, + "pop-binding!": {GoIdent: "PopBinding", LgName: "pop-binding!", Arity: 1, ParamSpecs: []string{"vm.Value"}, ResultSpec: "vm.Value", NeedsError: true, NeedsEC: true}, + "some": {GoIdent: "Some", LgName: "some", Arity: 2, ParamSpecs: []string{"vm.Value", "vm.Value"}, ResultSpec: "vm.Value", NeedsError: true, NeedsEC: true}, + "int": {GoIdent: "Int", LgName: "int", Arity: 1, ParamSpecs: []string{"vm.Value"}, ResultSpec: "vm.Value", NeedsError: true}, }, }) // Bind adapters into namespace if ns := LookupOrRegisterNSNoLoad("clojure.core"); ns != nil { - fn0, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_Name(vs) }) - defGeneratedPrimitive(ns, "clojure.core", "name", fn0) - fn1, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_Subs(vs) }) - defGeneratedPrimitive(ns, "clojure.core", "subs", fn1) - fn2, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_Nth(vs) }) - defGeneratedPrimitive(ns, "clojure.core", "nth", fn2) - fn3, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_Deref(vs) }) - defGeneratedPrimitive(ns, "clojure.core", "deref", fn3) - fn4, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_Str(vs) }) - defGeneratedPrimitive(ns, "clojure.core", "str", fn4) - fn5, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_Get(vs) }) - defGeneratedPrimitive(ns, "clojure.core", "get", fn5) - fn6, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_Conj(vs) }) - defGeneratedPrimitive(ns, "clojure.core", "conj", fn6) + fn0, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CorePlus(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "+", fn0) + fn1, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreMul(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "*", fn1) + fn2, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreSub(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "-", fn2) + fn3, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreDiv(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "/", fn3) + fn4, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CorePlusP(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "+'", fn4) + fn5, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreMulP(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "*'", fn5) + fn6, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreSubP(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "-'", fn6) + fn7, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreUncheckedAdd(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "unchecked-add", fn7) + fn8, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreUncheckedSubtract(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "unchecked-subtract", fn8) + fn9, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreUncheckedMultiply(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "unchecked-multiply", fn9) + fn10, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreUncheckedNegate(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "unchecked-negate", fn10) + fn11, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreUncheckedDivideInt(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "unchecked-divide-int", fn11) + fn12, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreUncheckedLong(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "unchecked-long", fn12) + fn13, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreUncheckedInt(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "unchecked-int", fn13) + fn14, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreUncheckedShort(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "unchecked-short", fn14) + fn15, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreUncheckedByte(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "unchecked-byte", fn15) + fn16, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreUncheckedChar(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "unchecked-char", fn16) + fn17, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreUncheckedDouble(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "unchecked-double", fn17) + fn18, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreUncheckedFloat(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "unchecked-float", fn18) + fn19, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreMod(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "mod", fn19) + fn20, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreAbs(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "abs", fn20) + fn21, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreNot(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "not", fn21) + fn22, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreComplement(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "complement", fn22) + fn23, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreSetMacro(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "set-macro!", fn23) + fn24, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreGensym(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "gensym", fn24) + fn25, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreVector(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "vector", fn25) + fn26, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreHashMap(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "hash-map", fn26) + fn27, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreArrayMap(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "array-map", fn27) + fn28, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreSortedMap(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "sorted-map", fn28) + fn29, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreSortedSet(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "sorted-set", fn29) + fn30, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreSortedMapBy(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "sorted-map-by", fn30) + fn31, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreSortedSetBy(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "sorted-set-by", fn31) + fn32, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreChunkFirst(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "chunk-first", fn32) + fn33, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreChunkRest(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "chunk-rest", fn33) + fn34, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreChunkNext(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "chunk-next", fn34) + fn35, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreChunkConsF(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "chunk-cons", fn35) + fn36, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreChunkedSeqP(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "chunked-seq?", fn36) + fn37, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreChunkBufferF(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "chunk-buffer", fn37) + fn38, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreChunkAppendF(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "chunk-append", fn38) + fn39, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreChunkF(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "chunk", fn39) + fn40, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreRangef(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "range", fn40) + fn41, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreKeyword(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "keyword", fn41) + fn42, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreSymbolf(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "symbol", fn42) + fn43, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreAssoc(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "assoc", fn43) + fn44, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreDissoc(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "dissoc", fn44) + fn45, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreCons(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "cons", fn45) + fn46, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreDisj(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "disj", fn46) + fn47, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreContains(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "contains?", fn47) + fn48, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreSecond(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "second", fn48) + fn49, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreIsList(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "list?", fn49) + fn50, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreEmpty(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "empty", fn50) + fn51, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreKeyf(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "key", fn51) + fn52, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreValf(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "val", fn52) + fn53, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreCount(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "count", fn53) + fn54, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreExcludeInCurrentNs(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "exclude-in-current-ns", fn54) + fn55, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreUse(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "use", fn55) + fn56, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreAliasf(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "alias", fn56) + fn57, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreReferList(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "refer-list", fn57) + fn58, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreMethodInvoke(vs) }) + defGeneratedPrimitive(ns, "clojure.core", ".", fn58) + fn59, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreRegisterHostMethod(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "register-host-method!", fn59) + fn60, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreRegisterHostClass(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "register-host-class!", fn60) + fn61, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreConcat(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "concat*", fn61) + fn62, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreSlurp(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "slurp", fn62) + fn63, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreSpit(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "spit", fn63) + fn64, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreAtom(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "atom", fn64) + fn65, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreReset(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "reset!", fn65) + fn66, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreCompareAndSet(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "compare-and-set!", fn66) + fn67, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreResetVals(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "reset-vals!", fn67) + fn68, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreChanf(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "chan", fn68) + fn69, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreScopeClose(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "scope-close!", fn69) + fn70, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreScopeLive(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "scope-live", fn70) + fn71, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreScopeQmark(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "scope?", fn71) + fn72, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreMax(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "max", fn72) + fn73, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreMin(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "min", fn73) + fn74, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreStrReplace(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "str-replace", fn74) + fn75, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreLongf(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "long", fn75) + fn76, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreFloatf(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "float", fn76) + fn77, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreDoublef(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "double", fn77) + fn78, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreIsNumber(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "number?", fn78) + fn79, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreIsFloat(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "float?", fn79) + fn80, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreIsInt(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "int?", fn80) + fn81, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreChar(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "char", fn81) + fn82, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreRegex(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "re-pattern", fn82) + fn83, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CorePeek(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "peek", fn83) + fn84, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CorePop(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "pop", fn84) + fn85, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreIterate(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "iterate", fn85) + fn86, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreRepeat(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "repeat", fn86) + fn87, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreRefer(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "refer", fn87) + fn88, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreFormatf(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "format", fn88) + fn89, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreRandf(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "rand", fn89) + fn90, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreRandInt(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "rand-int", fn90) + fn91, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreRandNth(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "rand-nth", fn91) + fn92, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreShuffle(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "shuffle", fn92) + fn93, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreSetRandSeedFn(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "set-rand-seed!", fn93) + fn94, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreTransientf(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "transient", fn94) + fn95, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CorePersistentf(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "persistent!", fn95) + fn96, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreConjBang(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "conj!", fn96) + fn97, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreAssocBang(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "assoc!", fn97) + fn98, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreDisjBang(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "disj!", fn98) + fn99, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreDissocBang(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "dissoc!", fn99) + fn100, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreMakeRecordType(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "make-record-type", fn100) + fn101, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreMakeRecord(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "make-record", fn101) + fn102, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreIsRecord(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "record?", fn102) + fn103, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreMakeDType(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "make-deftype", fn103) + fn104, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreMakeDTypeInstance(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "make-deftype-instance", fn104) + fn105, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreSetField(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "set-field!", fn105) + fn106, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreDefProtocol(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "defprotocol*", fn106) + fn107, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreExtendType(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "extend-type*", fn107) + fn108, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreMakeProtocolFn(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "make-protocol-fn", fn108) + fn109, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreSetInvokableProtocol(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "-set-invokable-protocol!", fn109) + fn110, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreSetDerefProtocol(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "-set-deref-protocol!", fn110) + fn111, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreSatisfies(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "satisfies?", fn111) + fn112, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreDefMulti(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "defmulti*", fn112) + fn113, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreDefMethod(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "defmethod*", fn113) + fn114, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CorePrStr(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "pr-str", fn114) + fn115, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CorePrnStr(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "prn-str", fn115) + fn116, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CorePrintStr(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "print-str", fn116) + fn117, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CorePrintlnStr(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "println-str", fn117) + fn118, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreReFind(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "re-find", fn118) + fn119, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreReMatches(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "re-matches", fn119) + fn120, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreReSeq(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "re-seq", fn120) + fn121, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreRequiref(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "require", fn121) + fn122, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreFindNs(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "find-ns", fn122) + fn123, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreResolvef(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "resolve", fn123) + fn124, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreAllNs(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "all-ns", fn124) + fn125, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreTheNs(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "the-ns", fn125) + fn126, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreNsPublics(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "ns-publics", fn126) + fn127, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreFindVar(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "find-var", fn127) + fn128, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreGetMethod(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "get-method", fn128) + fn129, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreEnumerationSeq(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "enumeration-seq", fn129) + fn130, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreLazySeq(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "lazy-seq*", fn130) + fn131, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreWithMeta(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "with-meta", fn131) + fn132, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreThrowf(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "throw", fn132) + fn133, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreExInfo(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "ex-info", fn133) + fn134, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreExMessage(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "ex-message", fn134) + fn135, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreExData(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "ex-data", fn135) + fn136, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreExCause(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "ex-cause", fn136) + fn137, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreDelayStar(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "delay*", fn137) + fn138, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreForce(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "force", fn138) + fn139, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreIsDelay(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "delay?", fn139) + fn140, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreIsRealized(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "realized?", fn140) + fn141, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreVolatilef(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "volatile!", fn141) + fn142, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreVreset(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "vreset!", fn142) + fn143, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreReducedf(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "reduced", fn143) + fn144, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreIsReducedf(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "reduced?", fn144) + fn145, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreBitAnd(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "bit-and", fn145) + fn146, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreBitOr(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "bit-or", fn146) + fn147, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreBitXor(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "bit-xor", fn147) + fn148, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreBitNot(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "bit-not", fn148) + fn149, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreBitShiftLeft(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "bit-shift-left", fn149) + fn150, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreBitShiftRight(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "bit-shift-right", fn150) + fn151, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreUnsignedBitShiftRight(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "unsigned-bit-shift-right", fn151) + fn152, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreBitTest(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "bit-test", fn152) + fn153, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreBitSet(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "bit-set", fn153) + fn154, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreBitClear(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "bit-clear", fn154) + fn155, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreBitAndNot(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "bit-and-not", fn155) + fn156, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreBitFlip(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "bit-flip", fn156) + fn157, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreReGroups(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "re-groups", fn157) + fn158, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CorePromisef(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "promise", fn158) + fn159, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreDeliver(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "deliver", fn159) + fn160, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreAddTap(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "add-tap", fn160) + fn161, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreRemoveTap(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "remove-tap", fn161) + fn162, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreTapBang(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "tap>", fn162) + fn163, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreAddWatch(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "add-watch", fn163) + fn164, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreRemoveWatch(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "remove-watch", fn164) + fn165, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreGetValidator(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "get-validator", fn165) + fn166, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreSubvecf(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "subvec", fn166) + fn167, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreIsDouble(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "double?", fn167) + fn168, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreInstancep(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "instance?", fn168) + fn169, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreIsIFn(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "ifn?", fn169) + fn170, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreIdentical(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "identical?", fn170) + fn171, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreAnyp(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "any?", fn171) + fn172, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreUnreduced(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "unreduced", fn172) + fn173, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreEnsureReduced(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "ensure-reduced", fn173) + fn174, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreBigintf(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "bigint", fn174) + fn175, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreIsRatio(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "ratio?", fn175) + fn176, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreIsDecimal(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "decimal?", fn176) + fn177, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreIsSorted(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "sorted?", fn177) + fn178, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreIsMap(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "map?", fn178) + fn179, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreIsSet(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "set?", fn179) + fn180, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreIsMapEntry(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "map-entry?", fn180) + fn181, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreIsLazySeq(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "lazy-seq?", fn181) + fn182, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreIsReversible(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "reversible?", fn182) + fn183, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreRseqf(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "rseq", fn183) + fn184, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreNumeratorf(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "numerator", fn184) + fn185, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreDenominatorf(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "denominator", fn185) + fn186, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreBigdecf(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "bigdec", fn186) + fn187, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreRoundBigdec(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "round-bigdec", fn187) + fn188, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreRationalizef(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "rationalize", fn188) + fn189, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreQuotf(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "quot", fn189) + fn190, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreRemf(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "rem", fn190) + fn191, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreHashf(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "hash", fn191) + fn192, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreParseDouble(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "parse-double", fn192) + fn193, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreParseBool(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "parse-boolean", fn193) + fn194, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreIsNaN(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "NaN?", fn194) + fn195, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreIsInfinite(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "infinite?", fn195) + fn196, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreIsBool(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "boolean?", fn196) + fn197, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreIsChar(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "char?", fn197) + fn198, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreIsVar(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "var?", fn198) + fn199, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreByteArrayf(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "byte-array", fn199) + fn200, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreObjectArrayf(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "object-array", fn200) + fn201, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreMakeArrayf(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "make-array", fn201) + fn202, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreAgetf(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "aget", fn202) + fn203, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreAsetf(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "aset", fn203) + fn204, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreAlengthf(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "alength", fn204) + fn205, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreAclonef(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "aclone", fn205) + fn206, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreBytesf(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "bytes", fn206) + fn207, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreDoublesf(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "doubles", fn207) + fn208, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreBytesP(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "bytes?", fn208) + fn209, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreVarGet(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "var-get", fn209) + fn210, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreBoundQ(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "bound?", fn210) + fn211, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreCopyFormSource(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "-copy-form-source!", fn211) + fn212, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreChunkToFnFn(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "chunk->fn", fn212) + fn213, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreMakeMultiArityFn(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "make-multi-arity", fn213) + fn214, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreInternf(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "intern", fn214) + fn215, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreApplyDefMetaf(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "apply-def-meta!", fn215) + fn216, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreCreateNsf(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "create-ns", fn216) + fn217, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CorePopBang(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "pop!", fn217) + fn218, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreIsUUID(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "uuid?", fn218) + fn219, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreIsInst(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "inst?", fn219) + fn220, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreParseUUID(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "parse-uuid", fn220) + fn221, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_CoreNumericEq(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "==", fn221) + fn222, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_Name(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "name", fn222) + fn223, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_Subs(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "subs", fn223) + fn224, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_Nth(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "nth", fn224) + fn225, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_Deref(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "deref", fn225) + fn226, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_Str(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "str", fn226) + fn227, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_Get(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "get", fn227) + fn228, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_Conj(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "conj", fn228) defGeneratedPrimitive(ns, "clojure.core", "reduce", vm.NewCtxNativeFn("reduce", _adapt_Reduce)) - fn8, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_Symbol(vs) }) - defGeneratedPrimitive(ns, "clojure.core", "symbol", fn8) - fn9, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_Assoc(vs) }) - defGeneratedPrimitive(ns, "clojure.core", "assoc", fn9) - fn10, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_AssocBang(vs) }) - defGeneratedPrimitive(ns, "clojure.core", "assoc!", fn10) - defGeneratedPrimitive(ns, "clojure.core", "swap!", vm.NewCtxNativeFn("swap!", _adapt_Swap)) - fn12, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_NotEq(vs) }) - defGeneratedPrimitive(ns, "clojure.core", "not=", fn12) - fn13, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_IsMap(vs) }) - defGeneratedPrimitive(ns, "clojure.core", "map?", fn13) - fn14, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_Atom(vs) }) - defGeneratedPrimitive(ns, "clojure.core", "atom", fn14) - fn15, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_Reset(vs) }) - defGeneratedPrimitive(ns, "clojure.core", "reset!", fn15) - fn16, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_Namespace(vs) }) - defGeneratedPrimitive(ns, "clojure.core", "namespace", fn16) + fn230, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_Namespace(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "namespace", fn230) defGeneratedPrimitive(ns, "clojure.core", "push-binding!", vm.NewCtxNativeFn("push-binding!", _adapt_PushBinding)) defGeneratedPrimitive(ns, "clojure.core", "pop-binding!", vm.NewCtxNativeFn("pop-binding!", _adapt_PopBinding)) - fn19, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_ReFind(vs) }) - defGeneratedPrimitive(ns, "clojure.core", "re-find", fn19) defGeneratedPrimitive(ns, "clojure.core", "some", vm.NewCtxNativeFn("some", _adapt_Some)) - fn21, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_Int(vs) }) - defGeneratedPrimitive(ns, "clojure.core", "int", fn21) - fn22, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_Range1(vs) }) - defGeneratedPrimitive(ns, "clojure.core", "range", fn22) + fn234, _ := vm.NativeFnType.Wrap(func(vs []vm.Value) (vm.Value, error) { return _adapt_Int(vs) }) + defGeneratedPrimitive(ns, "clojure.core", "int", fn234) } RegisterNativeModule(&NativeModule{ GoPkg: "github.com/nooga/let-go/pkg/rt", diff --git a/pkg/vm/namespace.go b/pkg/vm/namespace.go index e0ff4c287..5ad4c404c 100644 --- a/pkg/vm/namespace.go +++ b/pkg/vm/namespace.go @@ -518,6 +518,17 @@ func (n *Namespace) PublicVars() map[Symbol]*Var { return out } +// AllVars snapshots every interned var (public and private). Diagnostic use. +func (n *Namespace) AllVars() map[Symbol]*Var { + n.mu.RLock() + defer n.mu.RUnlock() + out := make(map[Symbol]*Var, len(n.registry)) + for k, v := range n.registry { + out[k] = v + } + return out +} + func FuzzySymbolLookup(ns *Namespace, s Symbol, lookupPrivate bool) []Symbol { ret := []Symbol{} for _, r := range ns.refersSnapshot() { diff --git a/pkg/vm/var.go b/pkg/vm/var.go index e89681ccd..770b3e64a 100644 --- a/pkg/vm/var.go +++ b/pkg/vm/var.go @@ -28,6 +28,11 @@ var guardedRootDeviations atomic.Int64 // guards in the lowered tree. func GuardedRootsIntact() bool { return guardedRootDeviations.Load() == 0 } +// GuardDeviated reports whether this guarded var's current root differs from the +// canonical root captured by GuardRoot. Diagnostic use: identify which native +// primitive an intact-check failure attributes to. +func (v *Var) GuardDeviated() bool { return v.guardDeviated.Load() } + type Var struct { // root is atomic so Deref — by far the hottest var operation — is // lock-free. Dynamic (thread-local) bindings no longer live on the Var; diff --git a/scripts/generate.lg b/scripts/generate.lg index 0c2a03e4b..21195eca7 100644 --- a/scripts/generate.lg +++ b/scripts/generate.lg @@ -141,9 +141,15 @@ (gen-go "scripts/gen/ir_bridge_generated.head" "pkg/ir/ir_bridge.lg" "pkg/rt/ir_bridge_generated.go") (gen-lisp "pkg/ir/ir_data.lg" "pkg/rt/core/ir/data/generated.lg") -;; Invoke cmd/lginterop -primitives to generate the primitive registrar. -;; Scans pkg/rt for //lg:native-annotated functions and generates adapters + registrations. -(run! go-bin "run" "./cmd/lginterop" "-primitives" "pkg/rt" "-go-pkg" "github.com/nooga/let-go/pkg/rt" "-primitives-out" "pkg/rt/zz_primitives_generated.go") +;; Invoke cmd/lgprimgen to generate the primitive registrar. +;; Scans pkg/rt for //lg:native-annotated functions and generates adapters + +;; registrations. lgprimgen is a PURE go/ast codegen tool that does NOT import +;; the runtime (pkg/compiler / pkg/rt) — so it runs even mid-migration, when +;; primitives have been moved out of installLangNS but the registrar that +;; replaces them has not been generated yet and the runtime cannot boot. Using +;; the runtime-coupled cmd/lginterop here would make this step depend on the +;; very artifact it produces. +(run! go-bin "run" "./cmd/lgprimgen" "-primitives" "pkg/rt" "-go-pkg" "github.com/nooga/let-go/pkg/rt" "-primitives-out" "pkg/rt/zz_primitives_generated.go") ;; One core compile emits BOTH the .lgb bundle and the gogen_ir Go tree. ;; Hermetic generation (clearing the stale lowered-tree before regen) is