diff --git a/Makefile b/Makefile index 040dd37..b8ba616 100644 --- a/Makefile +++ b/Makefile @@ -28,7 +28,7 @@ gocmd: generate: @go generate ./... -pkg/gen/gljimports/gljimports_%.go: ./scripts/gen-gljimports.sh ./cmd/gen-import-interop/main.go \ +pkg/gen/gljimports/gljimports_%.go: ./scripts/gen-gljimports.sh ./cmd/gen-import-interop/main.go ./internal/genpkg/genpkg.go \ $(wildcard ./pkg/lang/*.go) $(wildcard ./pkg/runtime/*.go) @echo "Generating $@" @./scripts/gen-gljimports.sh $@ $* $(GO_CMD) diff --git a/README.md b/README.md index 6abef21..96794dc 100644 --- a/README.md +++ b/README.md @@ -137,14 +137,11 @@ Then, in your own program: package main import ( - "your.package/gljimports" - - "github.com/glojurelang/glojure/pkg/runtime" + // Add your packages' exports to the pkgmap. + _ "your.package/gljimports" ) -func init() { - gljimports.RegisterImports(pkgmap.Set) -} +// ... ``` ## Comparisons to other Go ports of Clojure diff --git a/cmd/gen-import-interop/main.go b/cmd/gen-import-interop/main.go index c24b6d6..49098b1 100644 --- a/cmd/gen-import-interop/main.go +++ b/cmd/gen-import-interop/main.go @@ -2,17 +2,9 @@ package main import ( "flag" - "fmt" - "go/constant" - "go/format" - "go/importer" - "go/token" - "go/types" - "math" - "os" - "sort" - "strconv" "strings" + + "github.com/glojurelang/glojure/internal/genpkg" ) var defaultPackages = []string{ @@ -179,11 +171,6 @@ var packagesFlag = flag.String( "comma separated list of packages to import", ) -type export struct { - name string - obj types.Object -} - func main() { flag.Parse() @@ -192,198 +179,5 @@ func main() { packages = strings.Split(*packagesFlag, ",") } - sortedPackageNames, packageExports := collectExportedObjects(packages) - printGeneratedCode(sortedPackageNames, packageExports) -} - -func collectExportedObjects(packages []string) ([]string, map[string][]export) { - var packageNames []string - packageExports := map[string][]export{} - - fileSet := token.NewFileSet() - sourceImporter := importer.ForCompiler(fileSet, "source", nil) - - for _, packageName := range packages { - packageData, err := sourceImporter.Import(packageName) - if err != nil { - panic(err) - } - - var exportedObjects []export - for _, exportedObjectName := range packageData.Scope().Names() { - object := packageData.Scope().Lookup(exportedObjectName) - if isEligibleForExport(object, packageName) { - exportedObjects = append(exportedObjects, export{ - name: exportedObjectName, - obj: object, - }) - } - } - - if len(exportedObjects) > 0 { - packageExports[packageName] = exportedObjects - packageNames = append(packageNames, packageName) - } - } - - sort.Strings(packageNames) - - return packageNames, packageExports -} - -func isEligibleForExport(object types.Object, packageName string) bool { - if !object.Exported() { - return false - } - - if _, isIllegalType := object.(*types.Builtin); isIllegalType { - return false - } - - return true -} - -func printGeneratedCode(packageNames []string, packageExports map[string][]export) { - builder := createHeaderBuilder(packageNames) - createFunctionBuilder(builder, packageNames, packageExports) - - formattedCode, err := format.Source([]byte(builder.String())) - if err != nil { - panic(err) - } - - os.Stdout.Write(formattedCode) - os.Stdout.Sync() -} - -func createHeaderBuilder(packageNames []string) *strings.Builder { - builder := &strings.Builder{} - - builder.WriteString("// GENERATED FILE. DO NOT EDIT.\n") - builder.WriteString("package gljimports\n\n") - builder.WriteString("import (\n") - - for _, packageName := range packageNames { - aliasName := strings.NewReplacer(".", "_", "/", "_", "-", "_").Replace(packageName) - builder.WriteString(fmt.Sprintf("\t%s \"%s\"\n", aliasName, packageName)) - } - - builder.WriteString(")\n\n") - - return builder -} - -func createFunctionBuilder(builder *strings.Builder, packageNames []string, packageExports map[string][]export) { - builder.WriteString("func RegisterImports(_register func(string, interface{})) {\n") - - first := true - for _, packageName := range packageNames { - if !first { - builder.WriteString("\n") - } - first = false - addPackageSection(builder, packageName, packageExports[packageName]) - } - - builder.WriteString("}\n") -} - -func addPackageSection(builder *strings.Builder, packageName string, packageExports []export) { - builder.WriteString(fmt.Sprintf("\t// package %s\n", packageName)) - builder.WriteString("\t////////////////////////////////////////\n") - - packageAlias := replaceSpecChars(packageName) - - for _, exportedObject := range packageExports { - declareExportedObject(builder, exportedObject, packageName, packageAlias) - } -} - -func replaceSpecChars(value string) string { - return strings.NewReplacer(".", "_", "/", "_", "-", "_").Replace(value) -} - -func declareExportedObject(builder *strings.Builder, exportedObject export, packageName string, packageAlias string) { - globalName := fmt.Sprintf("%s.%s", packageName, exportedObject.name) - aliasName := fmt.Sprintf("%s.%s", packageAlias, exportedObject.name) - - decl := getDeclaration(exportedObject.obj, globalName, aliasName) - - for _, line := range strings.Split(decl, "\n") { - builder.WriteRune('\t') - builder.WriteString(line) - builder.WriteRune('\n') - } -} - -func getDeclaration(object types.Object, globalName string, aliasName string) string { - switch concreteObject := object.(type) { - case *types.Const: - return getConstDeclaration(concreteObject, globalName, aliasName) - case *types.Func: - return fmt.Sprintf("_register(%q, %s)", globalName, aliasName) - case *types.Var: - return getVarDeclaration(concreteObject, globalName, aliasName) - case *types.TypeName: - return getTypeNameDeclaration(concreteObject, globalName, aliasName) - default: - panic(fmt.Errorf("unknown type %T (%v)", object, object)) - } -} - -func getConstDeclaration(object *types.Const, globalName string, aliasName string) string { - value := object.Val() - - switch value.Kind() { - case constant.Bool, constant.String, constant.Complex: - return fmt.Sprintf("_register(%q, %s)", globalName, aliasName) - case constant.Int: - val := aliasName - if intType := getTypedInt(value.ExactString()); intType != "" { - val = fmt.Sprintf("%s(%s)", intType, val) - } - return fmt.Sprintf("_register(%q, %s)", globalName, val) - case constant.Float: - return fmt.Sprintf("_register(%q, float64(%s))", globalName, aliasName) - default: - panic(fmt.Errorf("unknown constant type: %s", value.Kind())) - } -} - -func getVarDeclaration(object *types.Var, globalName string, aliasName string) string { - typeName := object.Type().String() - - if typeName == "sync.Mutex" || typeName == "sync.RWMutex" { - return fmt.Sprintf("_register(%q, &%s)", globalName, aliasName) - } - - return fmt.Sprintf("_register(%q, %s)", globalName, aliasName) -} - -func getTypeNameDeclaration(object *types.TypeName, globalName string, aliasName string) string { - isGeneric := strings.HasSuffix(object.Type().String(), "]") - - if isGeneric { - return "" - } - - return fmt.Sprintf("_register(%q, reflect.TypeOf((*%s)(nil)).Elem())", globalName, aliasName) -} - -// getTypedInt derives the type of the integer literal from its string -// representation. Use the smallest type >= int that can represent the value. -func getTypedInt(value string) string { - if v, err := strconv.ParseInt(value, 10, 0); err == nil && v >= math.MinInt && v <= math.MaxInt { - return "" - } else if v, err := strconv.ParseInt(value, 10, 32); err == nil && v >= -2147483648 && v <= 2147483647 { - return "int32" - } else if v, err := strconv.ParseUint(value, 10, 32); err == nil && v <= 4294967295 { - return "uint32" - } else if v, err := strconv.ParseInt(value, 10, 64); err == nil && v >= -9223372036854775808 && v <= 9223372036854775807 { - return "int64" - } else if _, err := strconv.ParseUint(value, 10, 64); err == nil { - return "uint64" - } else { - panic(fmt.Errorf("cannot determine type of integer literal %s", value)) - } + genpkg.GenPkgs(packages) } diff --git a/cmd/glj/main.go b/cmd/glj/main.go index 9ed8b50..fc56bad 100644 --- a/cmd/glj/main.go +++ b/cmd/glj/main.go @@ -1,51 +1,40 @@ package main import ( - "bufio" + "fmt" "log" "os" + "os/exec" + "syscall" - "github.com/glojurelang/glojure/pkg/lang" - "github.com/glojurelang/glojure/pkg/reader" - "github.com/glojurelang/glojure/pkg/repl" - "github.com/glojurelang/glojure/pkg/runtime" + "github.com/glojurelang/glojure/internal/deps" // Bootstrap the runtime _ "github.com/glojurelang/glojure/pkg/glj" + "github.com/glojurelang/glojure/pkg/gljmain" ) func main() { - args := os.Args[1:] - - runtime.AddLoadPath(os.DirFS(".")) + dps, err := deps.Load() + if err != nil { + log.Fatal(err) + } + if dps != nil { + if err := dps.Gen(); err != nil { + panic(err) + } - if len(args) == 0 { - repl.Start() - } else { - file, err := os.Open(os.Args[1]) + exe, err := exec.LookPath("go") if err != nil { - log.Fatal(err) + panic(fmt.Errorf("failed to find `go` executable: %v", err)) } - env := lang.GlobalEnv - core := lang.FindNamespace(lang.NewSymbol("glojure.core")) - core.FindInternedVar(lang.NewSymbol("*command-line-args*")).BindRoot(lang.Seq(os.Args[2:])) - - rdr := reader.New(bufio.NewReader(file), reader.WithGetCurrentNS(func() *lang.Namespace { - return env.CurrentNamespace() - })) - for { - val, err := rdr.ReadOne() - if err == reader.ErrEOF { - break - } - if err != nil { - log.Fatal(err) - } - _, err = env.Eval(val) - if err != nil { - log.Fatal(err) - } + argv := append([]string{"go", "run", "./glj/cmd/glj"}, os.Args[1:]...) + if err := syscall.Exec(exe, argv, os.Environ()); err != nil { + log.Fatalf("failed to run %v: %v", exe, err) } + panic("a successful exec syscall should replace this process") } + + gljmain.Main(os.Args[1:]) } diff --git a/internal/deps/deps.go b/internal/deps/deps.go new file mode 100644 index 0000000..e9be115 --- /dev/null +++ b/internal/deps/deps.go @@ -0,0 +1,27 @@ +package deps + +import "fmt" + +// Deps is a struct that contains all the dependencies for the +// Glojure application. +type Deps struct { + goModName string + goModDir string + + Pkgs []string + Deps map[string]map[string]string +} + +func (d *Deps) Gen() error { + if err := d.Get(); err != nil { + return fmt.Errorf("failed to fetch dependencies: %w", err) + } + if err := d.Embed(); err != nil { + return fmt.Errorf("failed to generate embed for packages: %w", err) + } + if err := d.GLJ(); err != nil { + return fmt.Errorf("failed to generate glj main: %w", err) + } + + return nil +} diff --git a/internal/deps/embed.go b/internal/deps/embed.go new file mode 100644 index 0000000..efe1f7f --- /dev/null +++ b/internal/deps/embed.go @@ -0,0 +1,85 @@ +package deps + +import ( + "bytes" + "fmt" + "go/format" + "os" + "path/filepath" + "sort" + "strings" +) + +// Embed generates an gljembed.go file that embeds the directories +// from gljdeps.edn's pkgs and adds them to the Glojure load path when +// imported. +func (d *Deps) Embed() error { + sort.Strings(d.Pkgs) + + // if goModRootDir (an absolute path) is not the current directory, + // return an error. + currentDir, err := os.Getwd() + if err != nil { + return err + } + if d.goModDir != currentDir { + return fmt.Errorf("gljdeps.edn must be in the root directory of the go module") + } + + f, err := os.Create(filepath.Join(d.goModDir, "gljembed.go")) + if err != nil { + return err + } + defer f.Close() + + b := bytes.NewBuffer(nil) + + fmt.Fprintf(b, "// Code generated by glj. DO NOT EDIT.\n\n") + fmt.Fprintf(b, "package %s\n\n", filepath.Base(d.goModName)) + + fmt.Fprintf(b, `import ( + "embed" + "io/fs" + + "github.com/glojurelang/glojure/pkg/runtime" +) + +`) + + fmt.Fprintf(b, "var (\n") + for _, pkg := range d.Pkgs { + fsName := mungePath(pkg) + "FS" + fmt.Fprintf(b, "\t//go:embed %s/*\n", pkg) + fmt.Fprintf(b, "\t%s embed.FS\n", fsName) + } + fmt.Fprintf(b, ")\n\n") + + fmt.Fprintf(b, `func subfs(efs embed.FS, dir string) fs.FS { + d, err := fs.Sub(efs, dir) + if err != nil { + panic(err) + } + return d +} + +`) + + fmt.Fprintf(b, "func init() {\n") + for _, pkg := range d.Pkgs { + fsName := mungePath(pkg) + "FS" + fmt.Fprintf(b, "\truntime.AddLoadPath(subfs(%s, %q))\n", fsName, pkg) + } + fmt.Fprintf(b, "}\n") + + src, err := format.Source(b.Bytes()) + if err != nil { + return err + } + f.Write(src) + + return nil +} + +func mungePath(path string) string { + return strings.Replace(path, "/", "__", -1) +} diff --git a/internal/deps/get.go b/internal/deps/get.go new file mode 100644 index 0000000..463a36e --- /dev/null +++ b/internal/deps/get.go @@ -0,0 +1,64 @@ +package deps + +import ( + "fmt" + "os" + "os/exec" + "strings" + + "github.com/glojurelang/glojure/internal/genpkg" +) + +// Get gets the dependencies for the given package and generates a +// package map for any go dependencies. +func (d *Deps) Get() error { + packages := make([]string, 0, len(d.Deps)) + + for dep, depMap := range d.Deps { + version, ok := depMap["version"] + if !ok { + version = "latest" + } + + if err := getDep(dep, version); err != nil { + return err + } + + packages = append(packages, dep) + } + + if err := os.MkdirAll("./glj/gljimports", 0755); err != nil { + return err + } + + f, err := os.Create("./glj/gljimports/gljimports.go") + if err != nil { + return err + } + + genpkg.GenPkgs(packages, genpkg.WithWriter(f)) + + return nil +} + +func getDep(dep, version string) error { + out, err := exec.Command("go", "list", "-f", "{{.Module}}", dep).Output() + if err == nil { + // do we already have the right version? + parts := strings.Split(string(out), " ") + if len(parts) == 2 { + curVersion := strings.TrimSpace(parts[1]) + if curVersion == version { + // already installed with desired version + return nil + } + } + } + + // go get @ + cmd := exec.Command("go", "get", dep+"@"+version) + if out, err := cmd.CombinedOutput(); err != nil { + return fmt.Errorf("failed to `go get %s@%s`: %w\n%s", dep, version, err, out) + } + return nil +} diff --git a/internal/deps/glj.go b/internal/deps/glj.go new file mode 100644 index 0000000..8052042 --- /dev/null +++ b/internal/deps/glj.go @@ -0,0 +1,55 @@ +package deps + +import ( + "fmt" + "go/format" + "os" +) + +// GLJ generates a Go main package in glj/cmd/glj/main.go that +// implements the glj command with the project's dependencies and +// packages available. +func (d *Deps) GLJ() error { + main := fmt.Sprintf(mainTemplate, d.goModName, d.goModName) + src, err := format.Source([]byte(main)) + if err != nil { + return err + } + + if err := os.MkdirAll("./glj/cmd/glj", 0755); err != nil { + return err + } + + f, err := os.Create("./glj/cmd/glj/main.go") + if err != nil { + return err + } + defer f.Close() + + if _, err := f.Write(src); err != nil { + return err + } + + return nil +} + +const ( + mainTemplate = ` +// Code generated by glj. DO NOT EDIT. + +package main + +import ( + "os" + + "github.com/glojurelang/glojure/pkg/gljmain" + + _ %q + _ "%s/glj/gljimports" +) + +func main() { + gljmain.Main(os.Args[1:]) +} +` +) diff --git a/internal/deps/load.go b/internal/deps/load.go new file mode 100644 index 0000000..cba425c --- /dev/null +++ b/internal/deps/load.go @@ -0,0 +1,130 @@ +package deps + +import ( + "bufio" + "fmt" + "os" + "os/exec" + "path/filepath" + "strings" + + "github.com/glojurelang/glojure/pkg/lang" + "github.com/glojurelang/glojure/pkg/pkgmap" + "github.com/glojurelang/glojure/pkg/reader" +) + +func Load() (*Deps, error) { + const filename = "./gljdeps.edn" + + _, err := os.Stat(filename) + if err != nil { + if os.IsNotExist(err) { + return nil, nil + } + return nil, err + } + + modRootDir, err := goModRootDir() + if err != nil { + return nil, fmt.Errorf("failed to find go mod dir: %w", err) + } + + modName, err := goModName() + if err != nil { + return nil, fmt.Errorf("failed to find go mod name: %w", err) + } + + f, err := os.Open(filename) + if err != nil { + return nil, err + } + defer f.Close() + + rdr := reader.New(bufio.NewReader(f)) + d, err := rdr.ReadOne() + if err != nil { + return nil, err + } + + dmap, ok := d.(lang.IPersistentMap) + if !ok { + return nil, fmt.Errorf("expected map, got %T", d) + } + + deps := &Deps{ + Deps: make(map[string]map[string]string), + goModName: modName, + goModDir: modRootDir, + } + { // paths + for s := lang.Seq(dmap.ValAt(lang.NewKeyword("paths"))); s != nil; s = s.Next() { + first := s.First() + str, ok := first.(string) + if !ok { + return nil, fmt.Errorf("expected strings in :paths vector, got %T", first) + } + deps.Pkgs = append(deps.Pkgs, str) + } + } + + { // deps + var depsMap lang.IPersistentMap + if dm := dmap.ValAt(lang.NewKeyword("deps")); dm != nil { + if dm, ok := dm.(lang.IPersistentMap); !ok { + return nil, fmt.Errorf("expected map for :deps, got %T", dm) + } else { + depsMap = dm + } + } + for s := lang.Seq(depsMap); s != nil; s = s.Next() { + entry := s.First().(lang.IMapEntry) + k := entry.Key() + sym, ok := k.(*lang.Symbol) + if !ok { + return nil, fmt.Errorf("expected symbol for :deps key, got %T", k) + } + + v := entry.Val() + valMap, ok := v.(lang.IPersistentMap) + if !ok { + return nil, fmt.Errorf("expected map for :deps value, got %T", v) + } + + depMap := make(map[string]string) + for s := lang.Seq(valMap); s != nil; s = s.Next() { + entry := s.First().(lang.IMapEntry) + k := entry.Key() + kw, ok := k.(lang.Keyword) + if !ok { + return nil, fmt.Errorf("expected keyword for :deps key, got %T", k) + } + + v := entry.Val() + str, ok := v.(string) + if !ok { + return nil, fmt.Errorf("expected string for :deps value, got %T", v) + } + depMap[kw.Name()] = str + } + deps.Deps[pkgmap.UnmungePkg(sym.FullName())] = depMap + } + } + + return deps, nil +} + +func goModRootDir() (string, error) { + out, err := exec.Command("go", "env", "GOMOD").CombinedOutput() + if err != nil { + return "", fmt.Errorf("%w\n%s", err, string(out)) + } + return filepath.Dir(string(out)), nil +} + +func goModName() (string, error) { + out, err := exec.Command("go", "list", "-m").CombinedOutput() + if err != nil { + return "", fmt.Errorf("%w\n%s", err, string(out)) + } + return strings.TrimSpace(string(out)), nil +} diff --git a/internal/deps/pull.go b/internal/deps/pull.go new file mode 100644 index 0000000..594830d --- /dev/null +++ b/internal/deps/pull.go @@ -0,0 +1,3 @@ +package deps + + diff --git a/internal/genpkg/genpkg.go b/internal/genpkg/genpkg.go new file mode 100644 index 0000000..093653c --- /dev/null +++ b/internal/genpkg/genpkg.go @@ -0,0 +1,266 @@ +package genpkg + +import ( + "fmt" + "go/constant" + "go/format" + "go/importer" + "go/token" + "go/types" + "io" + "math" + "os" + "sort" + "strconv" + "strings" +) + +type ( + Options struct { + writer io.Writer + } + + Option func(*Options) + + export struct { + name string + obj types.Object + } +) + +func WithWriter(w io.Writer) Option { + return func(o *Options) { + o.writer = w + } +} + +func GenPkgs(packages []string, options ...Option) { + opts := &Options{ + writer: os.Stdout, + } + for _, opt := range options { + opt(opts) + } + + sortedPackageNames, packageExports := collectExportedObjects(packages) + printGeneratedCode(opts.writer, sortedPackageNames, packageExports) +} + +func collectExportedObjects(packages []string) ([]string, map[string][]export) { + var packageNames []string + packageExports := map[string][]export{} + + fileSet := token.NewFileSet() + sourceImporter := importer.ForCompiler(fileSet, "source", nil) + + for _, packageName := range packages { + packageData, err := sourceImporter.Import(packageName) + if err != nil { + panic(err) + } + + var exportedObjects []export + for _, exportedObjectName := range packageData.Scope().Names() { + object := packageData.Scope().Lookup(exportedObjectName) + if isEligibleForExport(object, packageName) { + exportedObjects = append(exportedObjects, export{ + name: exportedObjectName, + obj: object, + }) + } + } + + if len(exportedObjects) > 0 { + packageExports[packageName] = exportedObjects + packageNames = append(packageNames, packageName) + } + } + + sort.Strings(packageNames) + + return packageNames, packageExports +} + +func isEligibleForExport(object types.Object, packageName string) bool { + if !object.Exported() { + return false + } + + if _, isIllegalType := object.(*types.Builtin); isIllegalType { + return false + } + + return true +} + +func printGeneratedCode(w io.Writer, packageNames []string, packageExports map[string][]export) { + builder := createHeaderBuilder(packageNames) + createFunctionBuilder(builder, packageNames, packageExports) + + formattedCode, err := format.Source([]byte(builder.String())) + if err != nil { + panic(err) + } + + if _, err := w.Write(formattedCode); err != nil { + panic(err) + } + if wc, ok := w.(io.Closer); ok { + if err := wc.Close(); err != nil { + panic(err) + } + } +} + +func createHeaderBuilder(packageNames []string) *strings.Builder { + builder := &strings.Builder{} + + builder.WriteString("// GENERATED FILE. DO NOT EDIT.\n") + builder.WriteString("package gljimports\n\n") + builder.WriteString("import (\n") + + reflectImported := false + pkgMapImported := false + + for _, packageName := range packageNames { + if packageName == "reflect" { + reflectImported = true + } + if packageName == "github.com/glojurelang/glojure/pkg/pkgmap" { + pkgMapImported = true + } + aliasName := strings.NewReplacer(".", "_", "/", "_", "-", "_").Replace(packageName) + builder.WriteString(fmt.Sprintf("\t%s \"%s\"\n", aliasName, packageName)) + } + if !reflectImported { + builder.WriteString("\t\"reflect\"\n") + } + if !pkgMapImported { + builder.WriteString("\t\"github.com/glojurelang/glojure/pkg/pkgmap\"\n") + } + + builder.WriteString(")\n\n") + + builder.WriteString(`func init() { + RegisterImports(pkgmap.Set) +} + +`) + + return builder +} + +func createFunctionBuilder(builder *strings.Builder, packageNames []string, packageExports map[string][]export) { + builder.WriteString("func RegisterImports(_register func(string, interface{})) {\n") + + first := true + for _, packageName := range packageNames { + if !first { + builder.WriteString("\n") + } + first = false + addPackageSection(builder, packageName, packageExports[packageName]) + } + + builder.WriteString("}\n") +} + +func addPackageSection(builder *strings.Builder, packageName string, packageExports []export) { + builder.WriteString(fmt.Sprintf("\t// package %s\n", packageName)) + builder.WriteString("\t////////////////////////////////////////\n") + + packageAlias := replaceSpecChars(packageName) + + for _, exportedObject := range packageExports { + declareExportedObject(builder, exportedObject, packageName, packageAlias) + } +} + +func replaceSpecChars(value string) string { + return strings.NewReplacer(".", "_", "/", "_", "-", "_").Replace(value) +} + +func declareExportedObject(builder *strings.Builder, exportedObject export, packageName string, packageAlias string) { + globalName := fmt.Sprintf("%s.%s", packageName, exportedObject.name) + aliasName := fmt.Sprintf("%s.%s", packageAlias, exportedObject.name) + + decl := getDeclaration(exportedObject.obj, globalName, aliasName) + + for _, line := range strings.Split(decl, "\n") { + builder.WriteRune('\t') + builder.WriteString(line) + builder.WriteRune('\n') + } +} + +func getDeclaration(object types.Object, globalName string, aliasName string) string { + switch concreteObject := object.(type) { + case *types.Const: + return getConstDeclaration(concreteObject, globalName, aliasName) + case *types.Func: + return fmt.Sprintf("_register(%q, %s)", globalName, aliasName) + case *types.Var: + return getVarDeclaration(concreteObject, globalName, aliasName) + case *types.TypeName: + return getTypeNameDeclaration(concreteObject, globalName, aliasName) + default: + panic(fmt.Errorf("unknown type %T (%v)", object, object)) + } +} + +func getConstDeclaration(object *types.Const, globalName string, aliasName string) string { + value := object.Val() + + switch value.Kind() { + case constant.Bool, constant.String, constant.Complex: + return fmt.Sprintf("_register(%q, %s)", globalName, aliasName) + case constant.Int: + val := aliasName + if intType := getTypedInt(value.ExactString()); intType != "" { + val = fmt.Sprintf("%s(%s)", intType, val) + } + return fmt.Sprintf("_register(%q, %s)", globalName, val) + case constant.Float: + return fmt.Sprintf("_register(%q, float64(%s))", globalName, aliasName) + default: + panic(fmt.Errorf("unknown constant type: %s", value.Kind())) + } +} + +func getVarDeclaration(object *types.Var, globalName string, aliasName string) string { + typeName := object.Type().String() + + if typeName == "sync.Mutex" || typeName == "sync.RWMutex" { + return fmt.Sprintf("_register(%q, &%s)", globalName, aliasName) + } + + return fmt.Sprintf("_register(%q, %s)", globalName, aliasName) +} + +func getTypeNameDeclaration(object *types.TypeName, globalName string, aliasName string) string { + isGeneric := strings.HasSuffix(object.Type().String(), "]") + + if isGeneric { + return "" + } + + return fmt.Sprintf("_register(%q, reflect.TypeOf((*%s)(nil)).Elem())", globalName, aliasName) +} + +// getTypedInt derives the type of the integer literal from its string +// representation. Use the smallest type >= int that can represent the value. +func getTypedInt(value string) string { + if v, err := strconv.ParseInt(value, 10, 0); err == nil && v >= math.MinInt && v <= math.MaxInt { + return "" + } else if v, err := strconv.ParseInt(value, 10, 32); err == nil && v >= -2147483648 && v <= 2147483647 { + return "int32" + } else if v, err := strconv.ParseUint(value, 10, 32); err == nil && v <= 4294967295 { + return "uint32" + } else if v, err := strconv.ParseInt(value, 10, 64); err == nil && v >= -9223372036854775808 && v <= 9223372036854775807 { + return "int64" + } else if _, err := strconv.ParseUint(value, 10, 64); err == nil { + return "uint64" + } else { + panic(fmt.Errorf("cannot determine type of integer literal %s", value)) + } +} diff --git a/pkg/gen/gljimports/gljimports_darwin_amd64.go b/pkg/gen/gljimports/gljimports_darwin_amd64.go index bbed971..11f87ec 100644 --- a/pkg/gen/gljimports/gljimports_darwin_amd64.go +++ b/pkg/gen/gljimports/gljimports_darwin_amd64.go @@ -64,6 +64,7 @@ import ( flag "flag" fmt "fmt" github_com_glojurelang_glojure_pkg_lang "github.com/glojurelang/glojure/pkg/lang" + "github.com/glojurelang/glojure/pkg/pkgmap" github_com_glojurelang_glojure_pkg_runtime "github.com/glojurelang/glojure/pkg/runtime" go_ast "go/ast" go_build "go/build" @@ -157,6 +158,10 @@ import ( unsafe "unsafe" ) +func init() { + RegisterImports(pkgmap.Set) +} + func RegisterImports(_register func(string, interface{})) { // package archive/tar //////////////////////////////////////// @@ -3182,6 +3187,8 @@ func RegisterImports(_register func(string, interface{})) { _register("github.com/glojurelang/glojure/pkg/lang.Char", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.Char)(nil)).Elem()) _register("github.com/glojurelang/glojure/pkg/lang.CharAt", github_com_glojurelang_glojure_pkg_lang.CharAt) _register("github.com/glojurelang/glojure/pkg/lang.CharLiteralFromRune", github_com_glojurelang_glojure_pkg_lang.CharLiteralFromRune) + _register("github.com/glojurelang/glojure/pkg/lang.ChunkBuffer", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.ChunkBuffer)(nil)).Elem()) + _register("github.com/glojurelang/glojure/pkg/lang.ChunkedCons", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.ChunkedCons)(nil)).Elem()) _register("github.com/glojurelang/glojure/pkg/lang.CloneThreadBindingFrame", github_com_glojurelang_glojure_pkg_lang.CloneThreadBindingFrame) _register("github.com/glojurelang/glojure/pkg/lang.Comparer", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.Comparer)(nil)).Elem()) _register("github.com/glojurelang/glojure/pkg/lang.ConcatStrings", github_com_glojurelang_glojure_pkg_lang.ConcatStrings) @@ -3227,6 +3234,7 @@ func RegisterImports(_register func(string, interface{})) { _register("github.com/glojurelang/glojure/pkg/lang.GoIndex", github_com_glojurelang_glojure_pkg_lang.GoIndex) _register("github.com/glojurelang/glojure/pkg/lang.GoLen", github_com_glojurelang_glojure_pkg_lang.GoLen) _register("github.com/glojurelang/glojure/pkg/lang.GoMake", github_com_glojurelang_glojure_pkg_lang.GoMake) + _register("github.com/glojurelang/glojure/pkg/lang.GoMapIndex", github_com_glojurelang_glojure_pkg_lang.GoMapIndex) _register("github.com/glojurelang/glojure/pkg/lang.GoNew", github_com_glojurelang_glojure_pkg_lang.GoNew) _register("github.com/glojurelang/glojure/pkg/lang.GoPanic", github_com_glojurelang_glojure_pkg_lang.GoPanic) _register("github.com/glojurelang/glojure/pkg/lang.GoReal", github_com_glojurelang_glojure_pkg_lang.GoReal) @@ -3234,6 +3242,7 @@ func RegisterImports(_register func(string, interface{})) { _register("github.com/glojurelang/glojure/pkg/lang.GoRecvChanOf", github_com_glojurelang_glojure_pkg_lang.GoRecvChanOf) _register("github.com/glojurelang/glojure/pkg/lang.GoSend", github_com_glojurelang_glojure_pkg_lang.GoSend) _register("github.com/glojurelang/glojure/pkg/lang.GoSendChanOf", github_com_glojurelang_glojure_pkg_lang.GoSendChanOf) + _register("github.com/glojurelang/glojure/pkg/lang.GoSetMapIndex", github_com_glojurelang_glojure_pkg_lang.GoSetMapIndex) _register("github.com/glojurelang/glojure/pkg/lang.GoSlice", github_com_glojurelang_glojure_pkg_lang.GoSlice) _register("github.com/glojurelang/glojure/pkg/lang.HasType", github_com_glojurelang_glojure_pkg_lang.HasType) _register("github.com/glojurelang/glojure/pkg/lang.Hash", github_com_glojurelang_glojure_pkg_lang.Hash) @@ -3274,6 +3283,7 @@ func RegisterImports(_register func(string, interface{})) { _register("github.com/glojurelang/glojure/pkg/lang.Import", github_com_glojurelang_glojure_pkg_lang.Import) _register("github.com/glojurelang/glojure/pkg/lang.Inc", github_com_glojurelang_glojure_pkg_lang.Inc) _register("github.com/glojurelang/glojure/pkg/lang.IncP", github_com_glojurelang_glojure_pkg_lang.IncP) + _register("github.com/glojurelang/glojure/pkg/lang.IndexOutOfBoundsError", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.IndexOutOfBoundsError)(nil)).Elem()) _register("github.com/glojurelang/glojure/pkg/lang.Indexed", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.Indexed)(nil)).Elem()) _register("github.com/glojurelang/glojure/pkg/lang.InternKeyword", github_com_glojurelang_glojure_pkg_lang.InternKeyword) _register("github.com/glojurelang/glojure/pkg/lang.InternKeywordString", github_com_glojurelang_glojure_pkg_lang.InternKeywordString) @@ -3289,6 +3299,7 @@ func RegisterImports(_register func(string, interface{})) { _register("github.com/glojurelang/glojure/pkg/lang.IsSeq", github_com_glojurelang_glojure_pkg_lang.IsSeq) _register("github.com/glojurelang/glojure/pkg/lang.IsSeqEqual", github_com_glojurelang_glojure_pkg_lang.IsSeqEqual) _register("github.com/glojurelang/glojure/pkg/lang.IsTruthy", github_com_glojurelang_glojure_pkg_lang.IsTruthy) + _register("github.com/glojurelang/glojure/pkg/lang.IsZero", github_com_glojurelang_glojure_pkg_lang.IsZero) _register("github.com/glojurelang/glojure/pkg/lang.KWAliases", github_com_glojurelang_glojure_pkg_lang.KWAliases) _register("github.com/glojurelang/glojure/pkg/lang.KWArg", github_com_glojurelang_glojure_pkg_lang.KWArg) _register("github.com/glojurelang/glojure/pkg/lang.KWArgId", github_com_glojurelang_glojure_pkg_lang.KWArgId) @@ -3438,10 +3449,14 @@ func RegisterImports(_register func(string, interface{})) { _register("github.com/glojurelang/glojure/pkg/lang.NewBigIntFromInt64", github_com_glojurelang_glojure_pkg_lang.NewBigIntFromInt64) _register("github.com/glojurelang/glojure/pkg/lang.NewBox", github_com_glojurelang_glojure_pkg_lang.NewBox) _register("github.com/glojurelang/glojure/pkg/lang.NewChar", github_com_glojurelang_glojure_pkg_lang.NewChar) + _register("github.com/glojurelang/glojure/pkg/lang.NewChunkBuffer", github_com_glojurelang_glojure_pkg_lang.NewChunkBuffer) + _register("github.com/glojurelang/glojure/pkg/lang.NewChunkedCons", github_com_glojurelang_glojure_pkg_lang.NewChunkedCons) _register("github.com/glojurelang/glojure/pkg/lang.NewConcatIterator", github_com_glojurelang_glojure_pkg_lang.NewConcatIterator) _register("github.com/glojurelang/glojure/pkg/lang.NewCons", github_com_glojurelang_glojure_pkg_lang.NewCons) _register("github.com/glojurelang/glojure/pkg/lang.NewCycle", github_com_glojurelang_glojure_pkg_lang.NewCycle) _register("github.com/glojurelang/glojure/pkg/lang.NewError", github_com_glojurelang_glojure_pkg_lang.NewError) + _register("github.com/glojurelang/glojure/pkg/lang.NewGoMapSeq", github_com_glojurelang_glojure_pkg_lang.NewGoMapSeq) + _register("github.com/glojurelang/glojure/pkg/lang.NewIndexOutOfBoundsError", github_com_glojurelang_glojure_pkg_lang.NewIndexOutOfBoundsError) _register("github.com/glojurelang/glojure/pkg/lang.NewIterator", github_com_glojurelang_glojure_pkg_lang.NewIterator) _register("github.com/glojurelang/glojure/pkg/lang.NewKeyword", github_com_glojurelang_glojure_pkg_lang.NewKeyword) _register("github.com/glojurelang/glojure/pkg/lang.NewLazilyPersistentVector", github_com_glojurelang_glojure_pkg_lang.NewLazilyPersistentVector) @@ -3465,6 +3480,7 @@ func RegisterImports(_register func(string, interface{})) { _register("github.com/glojurelang/glojure/pkg/lang.NewRepeat", github_com_glojurelang_glojure_pkg_lang.NewRepeat) _register("github.com/glojurelang/glojure/pkg/lang.NewRepeatN", github_com_glojurelang_glojure_pkg_lang.NewRepeatN) _register("github.com/glojurelang/glojure/pkg/lang.NewSet", github_com_glojurelang_glojure_pkg_lang.NewSet) + _register("github.com/glojurelang/glojure/pkg/lang.NewSliceChunk", github_com_glojurelang_glojure_pkg_lang.NewSliceChunk) _register("github.com/glojurelang/glojure/pkg/lang.NewSliceIterator", github_com_glojurelang_glojure_pkg_lang.NewSliceIterator) _register("github.com/glojurelang/glojure/pkg/lang.NewSubVector", github_com_glojurelang_glojure_pkg_lang.NewSubVector) _register("github.com/glojurelang/glojure/pkg/lang.NewSymbol", github_com_glojurelang_glojure_pkg_lang.NewSymbol) @@ -3520,6 +3536,7 @@ func RegisterImports(_register func(string, interface{})) { _register("github.com/glojurelang/glojure/pkg/lang.Set", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.Set)(nil)).Elem()) _register("github.com/glojurelang/glojure/pkg/lang.SetField", github_com_glojurelang_glojure_pkg_lang.SetField) _register("github.com/glojurelang/glojure/pkg/lang.ShutdownAgents", github_com_glojurelang_glojure_pkg_lang.ShutdownAgents) + _register("github.com/glojurelang/glojure/pkg/lang.SliceChunk", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.SliceChunk)(nil)).Elem()) _register("github.com/glojurelang/glojure/pkg/lang.SliceSet", github_com_glojurelang_glojure_pkg_lang.SliceSet) _register("github.com/glojurelang/glojure/pkg/lang.StackFrame", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.StackFrame)(nil)).Elem()) _register("github.com/glojurelang/glojure/pkg/lang.Stacker", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.Stacker)(nil)).Elem()) diff --git a/pkg/gen/gljimports/gljimports_darwin_arm64.go b/pkg/gen/gljimports/gljimports_darwin_arm64.go index a99dcbe..46aeaf1 100644 --- a/pkg/gen/gljimports/gljimports_darwin_arm64.go +++ b/pkg/gen/gljimports/gljimports_darwin_arm64.go @@ -64,6 +64,7 @@ import ( flag "flag" fmt "fmt" github_com_glojurelang_glojure_pkg_lang "github.com/glojurelang/glojure/pkg/lang" + "github.com/glojurelang/glojure/pkg/pkgmap" github_com_glojurelang_glojure_pkg_runtime "github.com/glojurelang/glojure/pkg/runtime" go_ast "go/ast" go_build "go/build" @@ -157,6 +158,10 @@ import ( unsafe "unsafe" ) +func init() { + RegisterImports(pkgmap.Set) +} + func RegisterImports(_register func(string, interface{})) { // package archive/tar //////////////////////////////////////// @@ -3182,6 +3187,8 @@ func RegisterImports(_register func(string, interface{})) { _register("github.com/glojurelang/glojure/pkg/lang.Char", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.Char)(nil)).Elem()) _register("github.com/glojurelang/glojure/pkg/lang.CharAt", github_com_glojurelang_glojure_pkg_lang.CharAt) _register("github.com/glojurelang/glojure/pkg/lang.CharLiteralFromRune", github_com_glojurelang_glojure_pkg_lang.CharLiteralFromRune) + _register("github.com/glojurelang/glojure/pkg/lang.ChunkBuffer", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.ChunkBuffer)(nil)).Elem()) + _register("github.com/glojurelang/glojure/pkg/lang.ChunkedCons", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.ChunkedCons)(nil)).Elem()) _register("github.com/glojurelang/glojure/pkg/lang.CloneThreadBindingFrame", github_com_glojurelang_glojure_pkg_lang.CloneThreadBindingFrame) _register("github.com/glojurelang/glojure/pkg/lang.Comparer", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.Comparer)(nil)).Elem()) _register("github.com/glojurelang/glojure/pkg/lang.ConcatStrings", github_com_glojurelang_glojure_pkg_lang.ConcatStrings) @@ -3227,6 +3234,7 @@ func RegisterImports(_register func(string, interface{})) { _register("github.com/glojurelang/glojure/pkg/lang.GoIndex", github_com_glojurelang_glojure_pkg_lang.GoIndex) _register("github.com/glojurelang/glojure/pkg/lang.GoLen", github_com_glojurelang_glojure_pkg_lang.GoLen) _register("github.com/glojurelang/glojure/pkg/lang.GoMake", github_com_glojurelang_glojure_pkg_lang.GoMake) + _register("github.com/glojurelang/glojure/pkg/lang.GoMapIndex", github_com_glojurelang_glojure_pkg_lang.GoMapIndex) _register("github.com/glojurelang/glojure/pkg/lang.GoNew", github_com_glojurelang_glojure_pkg_lang.GoNew) _register("github.com/glojurelang/glojure/pkg/lang.GoPanic", github_com_glojurelang_glojure_pkg_lang.GoPanic) _register("github.com/glojurelang/glojure/pkg/lang.GoReal", github_com_glojurelang_glojure_pkg_lang.GoReal) @@ -3234,6 +3242,7 @@ func RegisterImports(_register func(string, interface{})) { _register("github.com/glojurelang/glojure/pkg/lang.GoRecvChanOf", github_com_glojurelang_glojure_pkg_lang.GoRecvChanOf) _register("github.com/glojurelang/glojure/pkg/lang.GoSend", github_com_glojurelang_glojure_pkg_lang.GoSend) _register("github.com/glojurelang/glojure/pkg/lang.GoSendChanOf", github_com_glojurelang_glojure_pkg_lang.GoSendChanOf) + _register("github.com/glojurelang/glojure/pkg/lang.GoSetMapIndex", github_com_glojurelang_glojure_pkg_lang.GoSetMapIndex) _register("github.com/glojurelang/glojure/pkg/lang.GoSlice", github_com_glojurelang_glojure_pkg_lang.GoSlice) _register("github.com/glojurelang/glojure/pkg/lang.HasType", github_com_glojurelang_glojure_pkg_lang.HasType) _register("github.com/glojurelang/glojure/pkg/lang.Hash", github_com_glojurelang_glojure_pkg_lang.Hash) @@ -3274,6 +3283,7 @@ func RegisterImports(_register func(string, interface{})) { _register("github.com/glojurelang/glojure/pkg/lang.Import", github_com_glojurelang_glojure_pkg_lang.Import) _register("github.com/glojurelang/glojure/pkg/lang.Inc", github_com_glojurelang_glojure_pkg_lang.Inc) _register("github.com/glojurelang/glojure/pkg/lang.IncP", github_com_glojurelang_glojure_pkg_lang.IncP) + _register("github.com/glojurelang/glojure/pkg/lang.IndexOutOfBoundsError", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.IndexOutOfBoundsError)(nil)).Elem()) _register("github.com/glojurelang/glojure/pkg/lang.Indexed", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.Indexed)(nil)).Elem()) _register("github.com/glojurelang/glojure/pkg/lang.InternKeyword", github_com_glojurelang_glojure_pkg_lang.InternKeyword) _register("github.com/glojurelang/glojure/pkg/lang.InternKeywordString", github_com_glojurelang_glojure_pkg_lang.InternKeywordString) @@ -3289,6 +3299,7 @@ func RegisterImports(_register func(string, interface{})) { _register("github.com/glojurelang/glojure/pkg/lang.IsSeq", github_com_glojurelang_glojure_pkg_lang.IsSeq) _register("github.com/glojurelang/glojure/pkg/lang.IsSeqEqual", github_com_glojurelang_glojure_pkg_lang.IsSeqEqual) _register("github.com/glojurelang/glojure/pkg/lang.IsTruthy", github_com_glojurelang_glojure_pkg_lang.IsTruthy) + _register("github.com/glojurelang/glojure/pkg/lang.IsZero", github_com_glojurelang_glojure_pkg_lang.IsZero) _register("github.com/glojurelang/glojure/pkg/lang.KWAliases", github_com_glojurelang_glojure_pkg_lang.KWAliases) _register("github.com/glojurelang/glojure/pkg/lang.KWArg", github_com_glojurelang_glojure_pkg_lang.KWArg) _register("github.com/glojurelang/glojure/pkg/lang.KWArgId", github_com_glojurelang_glojure_pkg_lang.KWArgId) @@ -3438,10 +3449,14 @@ func RegisterImports(_register func(string, interface{})) { _register("github.com/glojurelang/glojure/pkg/lang.NewBigIntFromInt64", github_com_glojurelang_glojure_pkg_lang.NewBigIntFromInt64) _register("github.com/glojurelang/glojure/pkg/lang.NewBox", github_com_glojurelang_glojure_pkg_lang.NewBox) _register("github.com/glojurelang/glojure/pkg/lang.NewChar", github_com_glojurelang_glojure_pkg_lang.NewChar) + _register("github.com/glojurelang/glojure/pkg/lang.NewChunkBuffer", github_com_glojurelang_glojure_pkg_lang.NewChunkBuffer) + _register("github.com/glojurelang/glojure/pkg/lang.NewChunkedCons", github_com_glojurelang_glojure_pkg_lang.NewChunkedCons) _register("github.com/glojurelang/glojure/pkg/lang.NewConcatIterator", github_com_glojurelang_glojure_pkg_lang.NewConcatIterator) _register("github.com/glojurelang/glojure/pkg/lang.NewCons", github_com_glojurelang_glojure_pkg_lang.NewCons) _register("github.com/glojurelang/glojure/pkg/lang.NewCycle", github_com_glojurelang_glojure_pkg_lang.NewCycle) _register("github.com/glojurelang/glojure/pkg/lang.NewError", github_com_glojurelang_glojure_pkg_lang.NewError) + _register("github.com/glojurelang/glojure/pkg/lang.NewGoMapSeq", github_com_glojurelang_glojure_pkg_lang.NewGoMapSeq) + _register("github.com/glojurelang/glojure/pkg/lang.NewIndexOutOfBoundsError", github_com_glojurelang_glojure_pkg_lang.NewIndexOutOfBoundsError) _register("github.com/glojurelang/glojure/pkg/lang.NewIterator", github_com_glojurelang_glojure_pkg_lang.NewIterator) _register("github.com/glojurelang/glojure/pkg/lang.NewKeyword", github_com_glojurelang_glojure_pkg_lang.NewKeyword) _register("github.com/glojurelang/glojure/pkg/lang.NewLazilyPersistentVector", github_com_glojurelang_glojure_pkg_lang.NewLazilyPersistentVector) @@ -3465,6 +3480,7 @@ func RegisterImports(_register func(string, interface{})) { _register("github.com/glojurelang/glojure/pkg/lang.NewRepeat", github_com_glojurelang_glojure_pkg_lang.NewRepeat) _register("github.com/glojurelang/glojure/pkg/lang.NewRepeatN", github_com_glojurelang_glojure_pkg_lang.NewRepeatN) _register("github.com/glojurelang/glojure/pkg/lang.NewSet", github_com_glojurelang_glojure_pkg_lang.NewSet) + _register("github.com/glojurelang/glojure/pkg/lang.NewSliceChunk", github_com_glojurelang_glojure_pkg_lang.NewSliceChunk) _register("github.com/glojurelang/glojure/pkg/lang.NewSliceIterator", github_com_glojurelang_glojure_pkg_lang.NewSliceIterator) _register("github.com/glojurelang/glojure/pkg/lang.NewSubVector", github_com_glojurelang_glojure_pkg_lang.NewSubVector) _register("github.com/glojurelang/glojure/pkg/lang.NewSymbol", github_com_glojurelang_glojure_pkg_lang.NewSymbol) @@ -3520,6 +3536,7 @@ func RegisterImports(_register func(string, interface{})) { _register("github.com/glojurelang/glojure/pkg/lang.Set", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.Set)(nil)).Elem()) _register("github.com/glojurelang/glojure/pkg/lang.SetField", github_com_glojurelang_glojure_pkg_lang.SetField) _register("github.com/glojurelang/glojure/pkg/lang.ShutdownAgents", github_com_glojurelang_glojure_pkg_lang.ShutdownAgents) + _register("github.com/glojurelang/glojure/pkg/lang.SliceChunk", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.SliceChunk)(nil)).Elem()) _register("github.com/glojurelang/glojure/pkg/lang.SliceSet", github_com_glojurelang_glojure_pkg_lang.SliceSet) _register("github.com/glojurelang/glojure/pkg/lang.StackFrame", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.StackFrame)(nil)).Elem()) _register("github.com/glojurelang/glojure/pkg/lang.Stacker", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.Stacker)(nil)).Elem()) diff --git a/pkg/gen/gljimports/gljimports_linux_amd64.go b/pkg/gen/gljimports/gljimports_linux_amd64.go index 8ced82f..2f7a2bd 100644 --- a/pkg/gen/gljimports/gljimports_linux_amd64.go +++ b/pkg/gen/gljimports/gljimports_linux_amd64.go @@ -64,6 +64,7 @@ import ( flag "flag" fmt "fmt" github_com_glojurelang_glojure_pkg_lang "github.com/glojurelang/glojure/pkg/lang" + "github.com/glojurelang/glojure/pkg/pkgmap" github_com_glojurelang_glojure_pkg_runtime "github.com/glojurelang/glojure/pkg/runtime" go_ast "go/ast" go_build "go/build" @@ -157,6 +158,10 @@ import ( unsafe "unsafe" ) +func init() { + RegisterImports(pkgmap.Set) +} + func RegisterImports(_register func(string, interface{})) { // package archive/tar //////////////////////////////////////// @@ -3182,6 +3187,8 @@ func RegisterImports(_register func(string, interface{})) { _register("github.com/glojurelang/glojure/pkg/lang.Char", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.Char)(nil)).Elem()) _register("github.com/glojurelang/glojure/pkg/lang.CharAt", github_com_glojurelang_glojure_pkg_lang.CharAt) _register("github.com/glojurelang/glojure/pkg/lang.CharLiteralFromRune", github_com_glojurelang_glojure_pkg_lang.CharLiteralFromRune) + _register("github.com/glojurelang/glojure/pkg/lang.ChunkBuffer", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.ChunkBuffer)(nil)).Elem()) + _register("github.com/glojurelang/glojure/pkg/lang.ChunkedCons", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.ChunkedCons)(nil)).Elem()) _register("github.com/glojurelang/glojure/pkg/lang.CloneThreadBindingFrame", github_com_glojurelang_glojure_pkg_lang.CloneThreadBindingFrame) _register("github.com/glojurelang/glojure/pkg/lang.Comparer", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.Comparer)(nil)).Elem()) _register("github.com/glojurelang/glojure/pkg/lang.ConcatStrings", github_com_glojurelang_glojure_pkg_lang.ConcatStrings) @@ -3227,6 +3234,7 @@ func RegisterImports(_register func(string, interface{})) { _register("github.com/glojurelang/glojure/pkg/lang.GoIndex", github_com_glojurelang_glojure_pkg_lang.GoIndex) _register("github.com/glojurelang/glojure/pkg/lang.GoLen", github_com_glojurelang_glojure_pkg_lang.GoLen) _register("github.com/glojurelang/glojure/pkg/lang.GoMake", github_com_glojurelang_glojure_pkg_lang.GoMake) + _register("github.com/glojurelang/glojure/pkg/lang.GoMapIndex", github_com_glojurelang_glojure_pkg_lang.GoMapIndex) _register("github.com/glojurelang/glojure/pkg/lang.GoNew", github_com_glojurelang_glojure_pkg_lang.GoNew) _register("github.com/glojurelang/glojure/pkg/lang.GoPanic", github_com_glojurelang_glojure_pkg_lang.GoPanic) _register("github.com/glojurelang/glojure/pkg/lang.GoReal", github_com_glojurelang_glojure_pkg_lang.GoReal) @@ -3234,6 +3242,7 @@ func RegisterImports(_register func(string, interface{})) { _register("github.com/glojurelang/glojure/pkg/lang.GoRecvChanOf", github_com_glojurelang_glojure_pkg_lang.GoRecvChanOf) _register("github.com/glojurelang/glojure/pkg/lang.GoSend", github_com_glojurelang_glojure_pkg_lang.GoSend) _register("github.com/glojurelang/glojure/pkg/lang.GoSendChanOf", github_com_glojurelang_glojure_pkg_lang.GoSendChanOf) + _register("github.com/glojurelang/glojure/pkg/lang.GoSetMapIndex", github_com_glojurelang_glojure_pkg_lang.GoSetMapIndex) _register("github.com/glojurelang/glojure/pkg/lang.GoSlice", github_com_glojurelang_glojure_pkg_lang.GoSlice) _register("github.com/glojurelang/glojure/pkg/lang.HasType", github_com_glojurelang_glojure_pkg_lang.HasType) _register("github.com/glojurelang/glojure/pkg/lang.Hash", github_com_glojurelang_glojure_pkg_lang.Hash) @@ -3274,6 +3283,7 @@ func RegisterImports(_register func(string, interface{})) { _register("github.com/glojurelang/glojure/pkg/lang.Import", github_com_glojurelang_glojure_pkg_lang.Import) _register("github.com/glojurelang/glojure/pkg/lang.Inc", github_com_glojurelang_glojure_pkg_lang.Inc) _register("github.com/glojurelang/glojure/pkg/lang.IncP", github_com_glojurelang_glojure_pkg_lang.IncP) + _register("github.com/glojurelang/glojure/pkg/lang.IndexOutOfBoundsError", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.IndexOutOfBoundsError)(nil)).Elem()) _register("github.com/glojurelang/glojure/pkg/lang.Indexed", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.Indexed)(nil)).Elem()) _register("github.com/glojurelang/glojure/pkg/lang.InternKeyword", github_com_glojurelang_glojure_pkg_lang.InternKeyword) _register("github.com/glojurelang/glojure/pkg/lang.InternKeywordString", github_com_glojurelang_glojure_pkg_lang.InternKeywordString) @@ -3289,6 +3299,7 @@ func RegisterImports(_register func(string, interface{})) { _register("github.com/glojurelang/glojure/pkg/lang.IsSeq", github_com_glojurelang_glojure_pkg_lang.IsSeq) _register("github.com/glojurelang/glojure/pkg/lang.IsSeqEqual", github_com_glojurelang_glojure_pkg_lang.IsSeqEqual) _register("github.com/glojurelang/glojure/pkg/lang.IsTruthy", github_com_glojurelang_glojure_pkg_lang.IsTruthy) + _register("github.com/glojurelang/glojure/pkg/lang.IsZero", github_com_glojurelang_glojure_pkg_lang.IsZero) _register("github.com/glojurelang/glojure/pkg/lang.KWAliases", github_com_glojurelang_glojure_pkg_lang.KWAliases) _register("github.com/glojurelang/glojure/pkg/lang.KWArg", github_com_glojurelang_glojure_pkg_lang.KWArg) _register("github.com/glojurelang/glojure/pkg/lang.KWArgId", github_com_glojurelang_glojure_pkg_lang.KWArgId) @@ -3438,10 +3449,14 @@ func RegisterImports(_register func(string, interface{})) { _register("github.com/glojurelang/glojure/pkg/lang.NewBigIntFromInt64", github_com_glojurelang_glojure_pkg_lang.NewBigIntFromInt64) _register("github.com/glojurelang/glojure/pkg/lang.NewBox", github_com_glojurelang_glojure_pkg_lang.NewBox) _register("github.com/glojurelang/glojure/pkg/lang.NewChar", github_com_glojurelang_glojure_pkg_lang.NewChar) + _register("github.com/glojurelang/glojure/pkg/lang.NewChunkBuffer", github_com_glojurelang_glojure_pkg_lang.NewChunkBuffer) + _register("github.com/glojurelang/glojure/pkg/lang.NewChunkedCons", github_com_glojurelang_glojure_pkg_lang.NewChunkedCons) _register("github.com/glojurelang/glojure/pkg/lang.NewConcatIterator", github_com_glojurelang_glojure_pkg_lang.NewConcatIterator) _register("github.com/glojurelang/glojure/pkg/lang.NewCons", github_com_glojurelang_glojure_pkg_lang.NewCons) _register("github.com/glojurelang/glojure/pkg/lang.NewCycle", github_com_glojurelang_glojure_pkg_lang.NewCycle) _register("github.com/glojurelang/glojure/pkg/lang.NewError", github_com_glojurelang_glojure_pkg_lang.NewError) + _register("github.com/glojurelang/glojure/pkg/lang.NewGoMapSeq", github_com_glojurelang_glojure_pkg_lang.NewGoMapSeq) + _register("github.com/glojurelang/glojure/pkg/lang.NewIndexOutOfBoundsError", github_com_glojurelang_glojure_pkg_lang.NewIndexOutOfBoundsError) _register("github.com/glojurelang/glojure/pkg/lang.NewIterator", github_com_glojurelang_glojure_pkg_lang.NewIterator) _register("github.com/glojurelang/glojure/pkg/lang.NewKeyword", github_com_glojurelang_glojure_pkg_lang.NewKeyword) _register("github.com/glojurelang/glojure/pkg/lang.NewLazilyPersistentVector", github_com_glojurelang_glojure_pkg_lang.NewLazilyPersistentVector) @@ -3465,6 +3480,7 @@ func RegisterImports(_register func(string, interface{})) { _register("github.com/glojurelang/glojure/pkg/lang.NewRepeat", github_com_glojurelang_glojure_pkg_lang.NewRepeat) _register("github.com/glojurelang/glojure/pkg/lang.NewRepeatN", github_com_glojurelang_glojure_pkg_lang.NewRepeatN) _register("github.com/glojurelang/glojure/pkg/lang.NewSet", github_com_glojurelang_glojure_pkg_lang.NewSet) + _register("github.com/glojurelang/glojure/pkg/lang.NewSliceChunk", github_com_glojurelang_glojure_pkg_lang.NewSliceChunk) _register("github.com/glojurelang/glojure/pkg/lang.NewSliceIterator", github_com_glojurelang_glojure_pkg_lang.NewSliceIterator) _register("github.com/glojurelang/glojure/pkg/lang.NewSubVector", github_com_glojurelang_glojure_pkg_lang.NewSubVector) _register("github.com/glojurelang/glojure/pkg/lang.NewSymbol", github_com_glojurelang_glojure_pkg_lang.NewSymbol) @@ -3520,6 +3536,7 @@ func RegisterImports(_register func(string, interface{})) { _register("github.com/glojurelang/glojure/pkg/lang.Set", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.Set)(nil)).Elem()) _register("github.com/glojurelang/glojure/pkg/lang.SetField", github_com_glojurelang_glojure_pkg_lang.SetField) _register("github.com/glojurelang/glojure/pkg/lang.ShutdownAgents", github_com_glojurelang_glojure_pkg_lang.ShutdownAgents) + _register("github.com/glojurelang/glojure/pkg/lang.SliceChunk", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.SliceChunk)(nil)).Elem()) _register("github.com/glojurelang/glojure/pkg/lang.SliceSet", github_com_glojurelang_glojure_pkg_lang.SliceSet) _register("github.com/glojurelang/glojure/pkg/lang.StackFrame", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.StackFrame)(nil)).Elem()) _register("github.com/glojurelang/glojure/pkg/lang.Stacker", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.Stacker)(nil)).Elem()) diff --git a/pkg/gen/gljimports/gljimports_linux_arm64.go b/pkg/gen/gljimports/gljimports_linux_arm64.go index 241e196..ce8c415 100644 --- a/pkg/gen/gljimports/gljimports_linux_arm64.go +++ b/pkg/gen/gljimports/gljimports_linux_arm64.go @@ -64,6 +64,7 @@ import ( flag "flag" fmt "fmt" github_com_glojurelang_glojure_pkg_lang "github.com/glojurelang/glojure/pkg/lang" + "github.com/glojurelang/glojure/pkg/pkgmap" github_com_glojurelang_glojure_pkg_runtime "github.com/glojurelang/glojure/pkg/runtime" go_ast "go/ast" go_build "go/build" @@ -157,6 +158,10 @@ import ( unsafe "unsafe" ) +func init() { + RegisterImports(pkgmap.Set) +} + func RegisterImports(_register func(string, interface{})) { // package archive/tar //////////////////////////////////////// @@ -3182,6 +3187,8 @@ func RegisterImports(_register func(string, interface{})) { _register("github.com/glojurelang/glojure/pkg/lang.Char", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.Char)(nil)).Elem()) _register("github.com/glojurelang/glojure/pkg/lang.CharAt", github_com_glojurelang_glojure_pkg_lang.CharAt) _register("github.com/glojurelang/glojure/pkg/lang.CharLiteralFromRune", github_com_glojurelang_glojure_pkg_lang.CharLiteralFromRune) + _register("github.com/glojurelang/glojure/pkg/lang.ChunkBuffer", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.ChunkBuffer)(nil)).Elem()) + _register("github.com/glojurelang/glojure/pkg/lang.ChunkedCons", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.ChunkedCons)(nil)).Elem()) _register("github.com/glojurelang/glojure/pkg/lang.CloneThreadBindingFrame", github_com_glojurelang_glojure_pkg_lang.CloneThreadBindingFrame) _register("github.com/glojurelang/glojure/pkg/lang.Comparer", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.Comparer)(nil)).Elem()) _register("github.com/glojurelang/glojure/pkg/lang.ConcatStrings", github_com_glojurelang_glojure_pkg_lang.ConcatStrings) @@ -3227,6 +3234,7 @@ func RegisterImports(_register func(string, interface{})) { _register("github.com/glojurelang/glojure/pkg/lang.GoIndex", github_com_glojurelang_glojure_pkg_lang.GoIndex) _register("github.com/glojurelang/glojure/pkg/lang.GoLen", github_com_glojurelang_glojure_pkg_lang.GoLen) _register("github.com/glojurelang/glojure/pkg/lang.GoMake", github_com_glojurelang_glojure_pkg_lang.GoMake) + _register("github.com/glojurelang/glojure/pkg/lang.GoMapIndex", github_com_glojurelang_glojure_pkg_lang.GoMapIndex) _register("github.com/glojurelang/glojure/pkg/lang.GoNew", github_com_glojurelang_glojure_pkg_lang.GoNew) _register("github.com/glojurelang/glojure/pkg/lang.GoPanic", github_com_glojurelang_glojure_pkg_lang.GoPanic) _register("github.com/glojurelang/glojure/pkg/lang.GoReal", github_com_glojurelang_glojure_pkg_lang.GoReal) @@ -3234,6 +3242,7 @@ func RegisterImports(_register func(string, interface{})) { _register("github.com/glojurelang/glojure/pkg/lang.GoRecvChanOf", github_com_glojurelang_glojure_pkg_lang.GoRecvChanOf) _register("github.com/glojurelang/glojure/pkg/lang.GoSend", github_com_glojurelang_glojure_pkg_lang.GoSend) _register("github.com/glojurelang/glojure/pkg/lang.GoSendChanOf", github_com_glojurelang_glojure_pkg_lang.GoSendChanOf) + _register("github.com/glojurelang/glojure/pkg/lang.GoSetMapIndex", github_com_glojurelang_glojure_pkg_lang.GoSetMapIndex) _register("github.com/glojurelang/glojure/pkg/lang.GoSlice", github_com_glojurelang_glojure_pkg_lang.GoSlice) _register("github.com/glojurelang/glojure/pkg/lang.HasType", github_com_glojurelang_glojure_pkg_lang.HasType) _register("github.com/glojurelang/glojure/pkg/lang.Hash", github_com_glojurelang_glojure_pkg_lang.Hash) @@ -3274,6 +3283,7 @@ func RegisterImports(_register func(string, interface{})) { _register("github.com/glojurelang/glojure/pkg/lang.Import", github_com_glojurelang_glojure_pkg_lang.Import) _register("github.com/glojurelang/glojure/pkg/lang.Inc", github_com_glojurelang_glojure_pkg_lang.Inc) _register("github.com/glojurelang/glojure/pkg/lang.IncP", github_com_glojurelang_glojure_pkg_lang.IncP) + _register("github.com/glojurelang/glojure/pkg/lang.IndexOutOfBoundsError", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.IndexOutOfBoundsError)(nil)).Elem()) _register("github.com/glojurelang/glojure/pkg/lang.Indexed", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.Indexed)(nil)).Elem()) _register("github.com/glojurelang/glojure/pkg/lang.InternKeyword", github_com_glojurelang_glojure_pkg_lang.InternKeyword) _register("github.com/glojurelang/glojure/pkg/lang.InternKeywordString", github_com_glojurelang_glojure_pkg_lang.InternKeywordString) @@ -3289,6 +3299,7 @@ func RegisterImports(_register func(string, interface{})) { _register("github.com/glojurelang/glojure/pkg/lang.IsSeq", github_com_glojurelang_glojure_pkg_lang.IsSeq) _register("github.com/glojurelang/glojure/pkg/lang.IsSeqEqual", github_com_glojurelang_glojure_pkg_lang.IsSeqEqual) _register("github.com/glojurelang/glojure/pkg/lang.IsTruthy", github_com_glojurelang_glojure_pkg_lang.IsTruthy) + _register("github.com/glojurelang/glojure/pkg/lang.IsZero", github_com_glojurelang_glojure_pkg_lang.IsZero) _register("github.com/glojurelang/glojure/pkg/lang.KWAliases", github_com_glojurelang_glojure_pkg_lang.KWAliases) _register("github.com/glojurelang/glojure/pkg/lang.KWArg", github_com_glojurelang_glojure_pkg_lang.KWArg) _register("github.com/glojurelang/glojure/pkg/lang.KWArgId", github_com_glojurelang_glojure_pkg_lang.KWArgId) @@ -3438,10 +3449,14 @@ func RegisterImports(_register func(string, interface{})) { _register("github.com/glojurelang/glojure/pkg/lang.NewBigIntFromInt64", github_com_glojurelang_glojure_pkg_lang.NewBigIntFromInt64) _register("github.com/glojurelang/glojure/pkg/lang.NewBox", github_com_glojurelang_glojure_pkg_lang.NewBox) _register("github.com/glojurelang/glojure/pkg/lang.NewChar", github_com_glojurelang_glojure_pkg_lang.NewChar) + _register("github.com/glojurelang/glojure/pkg/lang.NewChunkBuffer", github_com_glojurelang_glojure_pkg_lang.NewChunkBuffer) + _register("github.com/glojurelang/glojure/pkg/lang.NewChunkedCons", github_com_glojurelang_glojure_pkg_lang.NewChunkedCons) _register("github.com/glojurelang/glojure/pkg/lang.NewConcatIterator", github_com_glojurelang_glojure_pkg_lang.NewConcatIterator) _register("github.com/glojurelang/glojure/pkg/lang.NewCons", github_com_glojurelang_glojure_pkg_lang.NewCons) _register("github.com/glojurelang/glojure/pkg/lang.NewCycle", github_com_glojurelang_glojure_pkg_lang.NewCycle) _register("github.com/glojurelang/glojure/pkg/lang.NewError", github_com_glojurelang_glojure_pkg_lang.NewError) + _register("github.com/glojurelang/glojure/pkg/lang.NewGoMapSeq", github_com_glojurelang_glojure_pkg_lang.NewGoMapSeq) + _register("github.com/glojurelang/glojure/pkg/lang.NewIndexOutOfBoundsError", github_com_glojurelang_glojure_pkg_lang.NewIndexOutOfBoundsError) _register("github.com/glojurelang/glojure/pkg/lang.NewIterator", github_com_glojurelang_glojure_pkg_lang.NewIterator) _register("github.com/glojurelang/glojure/pkg/lang.NewKeyword", github_com_glojurelang_glojure_pkg_lang.NewKeyword) _register("github.com/glojurelang/glojure/pkg/lang.NewLazilyPersistentVector", github_com_glojurelang_glojure_pkg_lang.NewLazilyPersistentVector) @@ -3465,6 +3480,7 @@ func RegisterImports(_register func(string, interface{})) { _register("github.com/glojurelang/glojure/pkg/lang.NewRepeat", github_com_glojurelang_glojure_pkg_lang.NewRepeat) _register("github.com/glojurelang/glojure/pkg/lang.NewRepeatN", github_com_glojurelang_glojure_pkg_lang.NewRepeatN) _register("github.com/glojurelang/glojure/pkg/lang.NewSet", github_com_glojurelang_glojure_pkg_lang.NewSet) + _register("github.com/glojurelang/glojure/pkg/lang.NewSliceChunk", github_com_glojurelang_glojure_pkg_lang.NewSliceChunk) _register("github.com/glojurelang/glojure/pkg/lang.NewSliceIterator", github_com_glojurelang_glojure_pkg_lang.NewSliceIterator) _register("github.com/glojurelang/glojure/pkg/lang.NewSubVector", github_com_glojurelang_glojure_pkg_lang.NewSubVector) _register("github.com/glojurelang/glojure/pkg/lang.NewSymbol", github_com_glojurelang_glojure_pkg_lang.NewSymbol) @@ -3520,6 +3536,7 @@ func RegisterImports(_register func(string, interface{})) { _register("github.com/glojurelang/glojure/pkg/lang.Set", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.Set)(nil)).Elem()) _register("github.com/glojurelang/glojure/pkg/lang.SetField", github_com_glojurelang_glojure_pkg_lang.SetField) _register("github.com/glojurelang/glojure/pkg/lang.ShutdownAgents", github_com_glojurelang_glojure_pkg_lang.ShutdownAgents) + _register("github.com/glojurelang/glojure/pkg/lang.SliceChunk", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.SliceChunk)(nil)).Elem()) _register("github.com/glojurelang/glojure/pkg/lang.SliceSet", github_com_glojurelang_glojure_pkg_lang.SliceSet) _register("github.com/glojurelang/glojure/pkg/lang.StackFrame", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.StackFrame)(nil)).Elem()) _register("github.com/glojurelang/glojure/pkg/lang.Stacker", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.Stacker)(nil)).Elem()) diff --git a/pkg/gen/gljimports/gljimports_windows.go b/pkg/gen/gljimports/gljimports_windows.go index 5f38592..9eb3674 100644 --- a/pkg/gen/gljimports/gljimports_windows.go +++ b/pkg/gen/gljimports/gljimports_windows.go @@ -64,6 +64,7 @@ import ( flag "flag" fmt "fmt" github_com_glojurelang_glojure_pkg_lang "github.com/glojurelang/glojure/pkg/lang" + "github.com/glojurelang/glojure/pkg/pkgmap" github_com_glojurelang_glojure_pkg_runtime "github.com/glojurelang/glojure/pkg/runtime" go_ast "go/ast" go_build "go/build" @@ -157,6 +158,10 @@ import ( unsafe "unsafe" ) +func init() { + RegisterImports(pkgmap.Set) +} + func RegisterImports(_register func(string, interface{})) { // package archive/tar //////////////////////////////////////// @@ -3182,6 +3187,8 @@ func RegisterImports(_register func(string, interface{})) { _register("github.com/glojurelang/glojure/pkg/lang.Char", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.Char)(nil)).Elem()) _register("github.com/glojurelang/glojure/pkg/lang.CharAt", github_com_glojurelang_glojure_pkg_lang.CharAt) _register("github.com/glojurelang/glojure/pkg/lang.CharLiteralFromRune", github_com_glojurelang_glojure_pkg_lang.CharLiteralFromRune) + _register("github.com/glojurelang/glojure/pkg/lang.ChunkBuffer", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.ChunkBuffer)(nil)).Elem()) + _register("github.com/glojurelang/glojure/pkg/lang.ChunkedCons", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.ChunkedCons)(nil)).Elem()) _register("github.com/glojurelang/glojure/pkg/lang.CloneThreadBindingFrame", github_com_glojurelang_glojure_pkg_lang.CloneThreadBindingFrame) _register("github.com/glojurelang/glojure/pkg/lang.Comparer", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.Comparer)(nil)).Elem()) _register("github.com/glojurelang/glojure/pkg/lang.ConcatStrings", github_com_glojurelang_glojure_pkg_lang.ConcatStrings) @@ -3227,6 +3234,7 @@ func RegisterImports(_register func(string, interface{})) { _register("github.com/glojurelang/glojure/pkg/lang.GoIndex", github_com_glojurelang_glojure_pkg_lang.GoIndex) _register("github.com/glojurelang/glojure/pkg/lang.GoLen", github_com_glojurelang_glojure_pkg_lang.GoLen) _register("github.com/glojurelang/glojure/pkg/lang.GoMake", github_com_glojurelang_glojure_pkg_lang.GoMake) + _register("github.com/glojurelang/glojure/pkg/lang.GoMapIndex", github_com_glojurelang_glojure_pkg_lang.GoMapIndex) _register("github.com/glojurelang/glojure/pkg/lang.GoNew", github_com_glojurelang_glojure_pkg_lang.GoNew) _register("github.com/glojurelang/glojure/pkg/lang.GoPanic", github_com_glojurelang_glojure_pkg_lang.GoPanic) _register("github.com/glojurelang/glojure/pkg/lang.GoReal", github_com_glojurelang_glojure_pkg_lang.GoReal) @@ -3234,6 +3242,7 @@ func RegisterImports(_register func(string, interface{})) { _register("github.com/glojurelang/glojure/pkg/lang.GoRecvChanOf", github_com_glojurelang_glojure_pkg_lang.GoRecvChanOf) _register("github.com/glojurelang/glojure/pkg/lang.GoSend", github_com_glojurelang_glojure_pkg_lang.GoSend) _register("github.com/glojurelang/glojure/pkg/lang.GoSendChanOf", github_com_glojurelang_glojure_pkg_lang.GoSendChanOf) + _register("github.com/glojurelang/glojure/pkg/lang.GoSetMapIndex", github_com_glojurelang_glojure_pkg_lang.GoSetMapIndex) _register("github.com/glojurelang/glojure/pkg/lang.GoSlice", github_com_glojurelang_glojure_pkg_lang.GoSlice) _register("github.com/glojurelang/glojure/pkg/lang.HasType", github_com_glojurelang_glojure_pkg_lang.HasType) _register("github.com/glojurelang/glojure/pkg/lang.Hash", github_com_glojurelang_glojure_pkg_lang.Hash) @@ -3274,6 +3283,7 @@ func RegisterImports(_register func(string, interface{})) { _register("github.com/glojurelang/glojure/pkg/lang.Import", github_com_glojurelang_glojure_pkg_lang.Import) _register("github.com/glojurelang/glojure/pkg/lang.Inc", github_com_glojurelang_glojure_pkg_lang.Inc) _register("github.com/glojurelang/glojure/pkg/lang.IncP", github_com_glojurelang_glojure_pkg_lang.IncP) + _register("github.com/glojurelang/glojure/pkg/lang.IndexOutOfBoundsError", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.IndexOutOfBoundsError)(nil)).Elem()) _register("github.com/glojurelang/glojure/pkg/lang.Indexed", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.Indexed)(nil)).Elem()) _register("github.com/glojurelang/glojure/pkg/lang.InternKeyword", github_com_glojurelang_glojure_pkg_lang.InternKeyword) _register("github.com/glojurelang/glojure/pkg/lang.InternKeywordString", github_com_glojurelang_glojure_pkg_lang.InternKeywordString) @@ -3289,6 +3299,7 @@ func RegisterImports(_register func(string, interface{})) { _register("github.com/glojurelang/glojure/pkg/lang.IsSeq", github_com_glojurelang_glojure_pkg_lang.IsSeq) _register("github.com/glojurelang/glojure/pkg/lang.IsSeqEqual", github_com_glojurelang_glojure_pkg_lang.IsSeqEqual) _register("github.com/glojurelang/glojure/pkg/lang.IsTruthy", github_com_glojurelang_glojure_pkg_lang.IsTruthy) + _register("github.com/glojurelang/glojure/pkg/lang.IsZero", github_com_glojurelang_glojure_pkg_lang.IsZero) _register("github.com/glojurelang/glojure/pkg/lang.KWAliases", github_com_glojurelang_glojure_pkg_lang.KWAliases) _register("github.com/glojurelang/glojure/pkg/lang.KWArg", github_com_glojurelang_glojure_pkg_lang.KWArg) _register("github.com/glojurelang/glojure/pkg/lang.KWArgId", github_com_glojurelang_glojure_pkg_lang.KWArgId) @@ -3438,10 +3449,14 @@ func RegisterImports(_register func(string, interface{})) { _register("github.com/glojurelang/glojure/pkg/lang.NewBigIntFromInt64", github_com_glojurelang_glojure_pkg_lang.NewBigIntFromInt64) _register("github.com/glojurelang/glojure/pkg/lang.NewBox", github_com_glojurelang_glojure_pkg_lang.NewBox) _register("github.com/glojurelang/glojure/pkg/lang.NewChar", github_com_glojurelang_glojure_pkg_lang.NewChar) + _register("github.com/glojurelang/glojure/pkg/lang.NewChunkBuffer", github_com_glojurelang_glojure_pkg_lang.NewChunkBuffer) + _register("github.com/glojurelang/glojure/pkg/lang.NewChunkedCons", github_com_glojurelang_glojure_pkg_lang.NewChunkedCons) _register("github.com/glojurelang/glojure/pkg/lang.NewConcatIterator", github_com_glojurelang_glojure_pkg_lang.NewConcatIterator) _register("github.com/glojurelang/glojure/pkg/lang.NewCons", github_com_glojurelang_glojure_pkg_lang.NewCons) _register("github.com/glojurelang/glojure/pkg/lang.NewCycle", github_com_glojurelang_glojure_pkg_lang.NewCycle) _register("github.com/glojurelang/glojure/pkg/lang.NewError", github_com_glojurelang_glojure_pkg_lang.NewError) + _register("github.com/glojurelang/glojure/pkg/lang.NewGoMapSeq", github_com_glojurelang_glojure_pkg_lang.NewGoMapSeq) + _register("github.com/glojurelang/glojure/pkg/lang.NewIndexOutOfBoundsError", github_com_glojurelang_glojure_pkg_lang.NewIndexOutOfBoundsError) _register("github.com/glojurelang/glojure/pkg/lang.NewIterator", github_com_glojurelang_glojure_pkg_lang.NewIterator) _register("github.com/glojurelang/glojure/pkg/lang.NewKeyword", github_com_glojurelang_glojure_pkg_lang.NewKeyword) _register("github.com/glojurelang/glojure/pkg/lang.NewLazilyPersistentVector", github_com_glojurelang_glojure_pkg_lang.NewLazilyPersistentVector) @@ -3465,6 +3480,7 @@ func RegisterImports(_register func(string, interface{})) { _register("github.com/glojurelang/glojure/pkg/lang.NewRepeat", github_com_glojurelang_glojure_pkg_lang.NewRepeat) _register("github.com/glojurelang/glojure/pkg/lang.NewRepeatN", github_com_glojurelang_glojure_pkg_lang.NewRepeatN) _register("github.com/glojurelang/glojure/pkg/lang.NewSet", github_com_glojurelang_glojure_pkg_lang.NewSet) + _register("github.com/glojurelang/glojure/pkg/lang.NewSliceChunk", github_com_glojurelang_glojure_pkg_lang.NewSliceChunk) _register("github.com/glojurelang/glojure/pkg/lang.NewSliceIterator", github_com_glojurelang_glojure_pkg_lang.NewSliceIterator) _register("github.com/glojurelang/glojure/pkg/lang.NewSubVector", github_com_glojurelang_glojure_pkg_lang.NewSubVector) _register("github.com/glojurelang/glojure/pkg/lang.NewSymbol", github_com_glojurelang_glojure_pkg_lang.NewSymbol) @@ -3520,6 +3536,7 @@ func RegisterImports(_register func(string, interface{})) { _register("github.com/glojurelang/glojure/pkg/lang.Set", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.Set)(nil)).Elem()) _register("github.com/glojurelang/glojure/pkg/lang.SetField", github_com_glojurelang_glojure_pkg_lang.SetField) _register("github.com/glojurelang/glojure/pkg/lang.ShutdownAgents", github_com_glojurelang_glojure_pkg_lang.ShutdownAgents) + _register("github.com/glojurelang/glojure/pkg/lang.SliceChunk", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.SliceChunk)(nil)).Elem()) _register("github.com/glojurelang/glojure/pkg/lang.SliceSet", github_com_glojurelang_glojure_pkg_lang.SliceSet) _register("github.com/glojurelang/glojure/pkg/lang.StackFrame", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.StackFrame)(nil)).Elem()) _register("github.com/glojurelang/glojure/pkg/lang.Stacker", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.Stacker)(nil)).Elem()) diff --git a/pkg/glj/init.go b/pkg/glj/init.go index 523d077..3cafee3 100644 --- a/pkg/glj/init.go +++ b/pkg/glj/init.go @@ -4,9 +4,10 @@ import ( "io" "os" - "github.com/glojurelang/glojure/pkg/gen/gljimports" + // Add the Go standard library to the pkgmap. + _ "github.com/glojurelang/glojure/pkg/gen/gljimports" + value "github.com/glojurelang/glojure/pkg/lang" - "github.com/glojurelang/glojure/pkg/pkgmap" "github.com/glojurelang/glojure/pkg/runtime" ) @@ -15,8 +16,6 @@ func init() { } func initEnv(stdout io.Writer) value.Environment { - gljimports.RegisterImports(pkgmap.Set) - // TODO: clean up this code. copied from rtcompat.go. kvs := make([]interface{}, 0, 3) for _, vr := range []*value.Var{value.VarCurrentNS, value.VarWarnOnReflection, value.VarUncheckedMath, value.VarDataReaders} { diff --git a/pkg/gljmain/gljmain.go b/pkg/gljmain/gljmain.go new file mode 100644 index 0000000..5f56197 --- /dev/null +++ b/pkg/gljmain/gljmain.go @@ -0,0 +1,49 @@ +package gljmain + +import ( + "bufio" + "log" + "os" + + // bootstrap the runtime + _ "github.com/glojurelang/glojure/pkg/glj" + + "github.com/glojurelang/glojure/pkg/lang" + "github.com/glojurelang/glojure/pkg/reader" + "github.com/glojurelang/glojure/pkg/repl" + "github.com/glojurelang/glojure/pkg/runtime" +) + +func Main(args []string) { + runtime.AddLoadPath(os.DirFS(".")) + + if len(args) == 0 { + repl.Start() + } else { + file, err := os.Open(os.Args[1]) + if err != nil { + log.Fatal(err) + } + env := lang.GlobalEnv + + core := lang.FindNamespace(lang.NewSymbol("glojure.core")) + core.FindInternedVar(lang.NewSymbol("*command-line-args*")).BindRoot(lang.Seq(os.Args[2:])) + + rdr := reader.New(bufio.NewReader(file), reader.WithGetCurrentNS(func() *lang.Namespace { + return env.CurrentNamespace() + })) + for { + val, err := rdr.ReadOne() + if err == reader.ErrEOF { + break + } + if err != nil { + log.Fatal(err) + } + _, err = env.Eval(val) + if err != nil { + log.Fatal(err) + } + } + } +} diff --git a/pkg/lang/apply.go b/pkg/lang/apply.go index 9e0560d..a3fcb61 100644 --- a/pkg/lang/apply.go +++ b/pkg/lang/apply.go @@ -207,13 +207,34 @@ func reflectFuncFromIFn(targetType reflect.Type, applyer IFn) func(args []reflec } return zeroValues } - // convert return value to expected type of target type - coerced, err := coerceGoValue(targetType.Out(0), res) - if err != nil { - panic(err) + + if targetType.NumOut() == 0 { + return nil + } + + ret := make([]reflect.Value, targetType.NumOut()) + if targetType.NumOut() == 1 { + // convert return value to expected type of target type + coerced, err := coerceGoValue(targetType.Out(0), res) + if err != nil { + panic(err) + } + ret[0] = coerced + } else { + i := 0 + for s := Seq(res); s != nil && i < len(ret); s = s.Next() { + coerced, err := coerceGoValue(targetType.Out(i), s.First()) + if err != nil { + panic(err) + } + ret[i] = coerced + i++ + } + for ; i < len(ret); i++ { + ret[i] = reflect.Zero(targetType.Out(i)) + } } - res = coerced.Interface() - return []reflect.Value{reflect.ValueOf(res)} + return ret } } diff --git a/pkg/lang/builtins.go b/pkg/lang/builtins.go index 139bda9..a3f4da5 100644 --- a/pkg/lang/builtins.go +++ b/pkg/lang/builtins.go @@ -62,10 +62,12 @@ var ( // function; it can only be applied to lvalues, which are not // first-class in clojure. we'll need a special form to take the // address of slice elements and struct fields. - "index": GoIndex, // index(slc, i) -> val - "slice": GoSlice, // slice(slc, i, j) -> slc[i:j] - "send": GoSend, // send(ch, val) -> ch <- val - "recv": GoRecv, // recv(ch) -> val, ok <- ch + "index": GoIndex, // index(slc, i) -> val + "slice": GoSlice, // slice(slc, i, j) -> slc[i:j] + "map-index": GoMapIndex, // mapindex(m, key) -> val + "set-map-index": GoSetMapIndex, // setmapindex(m, key, val) -> m[key] = val + "send": GoSend, // send(ch, val) -> ch <- val + "recv": GoRecv, // recv(ch) -> val, ok <- ch } ) @@ -179,10 +181,18 @@ func GoDeref(ptr interface{}) interface{} { return reflect.Indirect(reflect.ValueOf(ptr)).Interface() } -func GoIndex(slc interface{}, i interface{}) interface{} { +func GoIndex(slc, i interface{}) interface{} { return reflect.ValueOf(slc).Index(MustAsInt(i)).Interface() } +func GoMapIndex(m, k interface{}) interface{} { + return reflect.ValueOf(m).MapIndex(reflect.ValueOf(k)).Interface() +} + +func GoSetMapIndex(m, k, v interface{}) { + reflect.ValueOf(m).SetMapIndex(reflect.ValueOf(k), reflect.ValueOf(v)) +} + func GoSlice(slc interface{}, indices ...interface{}) interface{} { slcVal := reflect.ValueOf(slc) i := 0 diff --git a/pkg/lang/chunkbuffer.go b/pkg/lang/chunkbuffer.go new file mode 100644 index 0000000..611a14b --- /dev/null +++ b/pkg/lang/chunkbuffer.go @@ -0,0 +1,37 @@ +package lang + +type ( + ChunkBuffer struct { + buffer []interface{} + end int + } +) + +var ( + _ Counted = (*ChunkBuffer)(nil) +) + +func NewChunkBuffer(capacity int) *ChunkBuffer { + return &ChunkBuffer{ + buffer: make([]interface{}, capacity), + end: 0, + } +} + +func (cb *ChunkBuffer) Add(item interface{}) { + // following Clojure's implementation, we pre-allocate the + // buffer. additions beyond the initial capacity will cause a + // runtime error. + cb.buffer[cb.end] = item + cb.end++ +} + +func (cb *ChunkBuffer) Chunk() IChunk { + ret := NewSliceChunk(cb.buffer) + cb.buffer = nil + return ret +} + +func (cb *ChunkBuffer) Count() int { + return cb.end +} diff --git a/pkg/lang/chunkedcons.go b/pkg/lang/chunkedcons.go new file mode 100644 index 0000000..898f314 --- /dev/null +++ b/pkg/lang/chunkedcons.go @@ -0,0 +1,64 @@ +package lang + +type ( + ChunkedCons struct { + meta IPersistentMap + + chunk IChunk + more ISeq + } +) + +var ( + _ IChunkedSeq = (*ChunkedCons)(nil) + _ ISeq = (*ChunkedCons)(nil) +) + +func NewChunkedCons(chunk IChunk, more ISeq) *ChunkedCons { + return &ChunkedCons{ + chunk: chunk, + more: more, + } +} + +func (c *ChunkedCons) ChunkedFirst() IChunk { + return c.chunk +} + +func (c *ChunkedCons) ChunkedNext() ISeq { + return c.ChunkedMore().Seq() +} + +func (c *ChunkedCons) ChunkedMore() ISeq { + if c.more == nil { + return emptyList + } + return c.more +} + +func (c *ChunkedCons) First() interface{} { + return c.chunk.Nth(0) +} + +func (c *ChunkedCons) Next() ISeq { + if c.chunk.Count() > 1 { + return NewChunkedCons(c.chunk.DropFirst(), c.more) + } + return c.ChunkedNext() +} + +func (c *ChunkedCons) More() ISeq { + if c.chunk.Count() > 1 { + return NewChunkedCons(c.chunk.DropFirst(), c.more) + } + if c.more == nil { + return emptyList + } + return c.more +} + +func (c *ChunkedCons) Seq() ISeq { + return c +} + +func (c *ChunkedCons) xxx_sequential() {} diff --git a/pkg/lang/error.go b/pkg/lang/error.go index 0a1f376..2830023 100644 --- a/pkg/lang/error.go +++ b/pkg/lang/error.go @@ -11,6 +11,8 @@ type ( msg string } + IndexOutOfBoundsError struct{} + // Stacker is an interface for retrieving stack traces. Stacker interface { Stack() []StackFrame @@ -40,6 +42,17 @@ func (e *TimeoutError) Error() string { return e.msg } +func NewIndexOutOfBoundsError() error { + return &IndexOutOfBoundsError{} +} + +func (e *IndexOutOfBoundsError) Error() string { + return "index out of bounds" +} + +//////////////////////////////////////////////////////////////////////////////// +// TODO: Revisit + // NewError creates a new error value. func NewError(frame StackFrame, err error) *Error { return &Error{ diff --git a/pkg/lang/interfaces.go b/pkg/lang/interfaces.go index e3c84cb..656af23 100644 --- a/pkg/lang/interfaces.go +++ b/pkg/lang/interfaces.go @@ -114,7 +114,9 @@ type ( } Indexed interface { - Nth(int) (interface{}, bool) + Counted + + Nth(int) interface{} NthDefault(int, interface{}) interface{} } @@ -234,7 +236,7 @@ type ( Indexed DropFirst() IChunk - Reduce(fn IFn, init interface{}) interface{} + ReduceInit(fn IFn, init interface{}) interface{} } IChunkedSeq interface { @@ -285,6 +287,13 @@ type ( } + //////////////////////////////////////////////////////////////////////////// + // Abstract classes + // + // TODO: represent Clojure's abstract classes as interfaces to + // provide compile-time checks for implementations of required + // methods. + // Java Future interface Future interface { Get() interface{} @@ -295,6 +304,11 @@ type ( } ) +var ( + // sentinel value for "not found" + notFound = &struct{}{} +) + func Conj(coll Conjer, x interface{}) Conjer { if coll == nil { return emptyList.Conj(x) diff --git a/pkg/lang/iteration.go b/pkg/lang/iteration.go index 6396d7a..10fa1a3 100644 --- a/pkg/lang/iteration.go +++ b/pkg/lang/iteration.go @@ -84,7 +84,11 @@ func (i iterator) Next() ISeq { } func (i iterator) More() ISeq { - return i.Next() + nxt := i.Next() + if nxt == nil { + return emptyList + } + return nxt } // NewRangeIterator returns a lazy sequence of start, start + step, start + 2*step, ... @@ -177,8 +181,7 @@ func (it vectorIterator) Seq() ISeq { } func (it vectorIterator) First() interface{} { - v, _ := it.v.Nth(it.start) - return v + return it.v.Nth(it.start) } func (it vectorIterator) Next() ISeq { @@ -335,3 +338,33 @@ func (i sliceIterator) ReduceInit(f IFn, start interface{}) interface{} { } return ret } + +//////////////////////////////////////////////////////////////////////////////// + +func chunkIteratorSeq(iter *reflect.MapIter) ISeq { + const chunkSize = 32 + + return NewLazySeq(func() interface{} { + chunk := make([]interface{}, 0, chunkSize) + exhausted := false + for n := 0; n < chunkSize; n++ { + chunk = append(chunk, NewMapEntry(iter.Key().Interface(), iter.Value().Interface())) + if !iter.Next() { + exhausted = true + break + } + } + if exhausted { + return NewChunkedCons(NewSliceChunk(chunk), nil) + } + return NewChunkedCons(NewSliceChunk(chunk), chunkIteratorSeq(iter)) + }) +} + +func NewGoMapSeq(x interface{}) ISeq { + rng := reflect.ValueOf(x).MapRange() + if !rng.Next() { + return nil + } + return chunkIteratorSeq(rng) +} diff --git a/pkg/lang/mapentry.go b/pkg/lang/mapentry.go index 4c7accf..631abae 100644 --- a/pkg/lang/mapentry.go +++ b/pkg/lang/mapentry.go @@ -47,20 +47,20 @@ func (me *MapEntry) Length() int { return me.Count() } -func (me *MapEntry) Nth(i int) (interface{}, bool) { +func (me *MapEntry) Nth(i int) interface{} { switch i { case 0: - return me.Key(), true + return me.Key() case 1: - return me.Val(), true + return me.Val() default: - return nil, false + panic(NewIndexOutOfBoundsError()) } } func (me *MapEntry) NthDefault(i int, d interface{}) interface{} { - if v, ok := me.Nth(i); ok { - return v + if i >= 0 && i < 2 { + return me.Nth(i) } return d } diff --git a/pkg/lang/numbers.go b/pkg/lang/numbers.go index 653cda9..7add7e3 100644 --- a/pkg/lang/numbers.go +++ b/pkg/lang/numbers.go @@ -68,10 +68,14 @@ func (nm *NumberMethods) And(x, y interface{}) interface{} { return bitOpsCast(x) & bitOpsCast(y) } -func (nm *NumberMethods) IsZero(x interface{}) bool { +func IsZero(x interface{}) bool { return Ops(x).IsZero(x) } +func (nm *NumberMethods) IsZero(x interface{}) bool { + return IsZero(x) +} + func (nm *NumberMethods) IsPos(x interface{}) bool { return Ops(x).IsPos(x) } diff --git a/pkg/lang/seq.go b/pkg/lang/seq.go index 7736ecc..988c963 100644 --- a/pkg/lang/seq.go +++ b/pkg/lang/seq.go @@ -63,6 +63,8 @@ func Seq(x interface{}) ISeq { switch t.Kind() { case reflect.Slice, reflect.Array: return NewSliceIterator(x) + case reflect.Map: + return NewGoMapSeq(x) } panic(fmt.Errorf("can't convert %T to ISeq", x)) diff --git a/pkg/lang/slicechunk.go b/pkg/lang/slicechunk.go new file mode 100644 index 0000000..4f495e3 --- /dev/null +++ b/pkg/lang/slicechunk.go @@ -0,0 +1,55 @@ +package lang + +import "errors" + +type ( + SliceChunk struct { + slc []interface{} + } +) + +var ( + _ IChunk = (*SliceChunk)(nil) +) + +func NewSliceChunk(slc []interface{}) *SliceChunk { + return &SliceChunk{ + slc: slc, + } +} + +func (sc *SliceChunk) Count() int { + return len(sc.slc) +} + +func (sc *SliceChunk) DropFirst() IChunk { + if len(sc.slc) == 0 { + panic(errors.New("DropFirst of empty chunk")) + } + return NewSliceChunk(sc.slc[1:]) +} + +func (sc *SliceChunk) Nth(i int) interface{} { + return sc.slc[i] +} + +func (sc *SliceChunk) NthDefault(i int, def interface{}) interface{} { + if i >= 0 && i < len(sc.slc) { + return sc.Nth(i) + } + return def +} + +func (sc *SliceChunk) ReduceInit(fn IFn, init interface{}) interface{} { + ret := fn.Invoke(init, sc.slc[0]) + if IsReduced(ret) { + return ret + } + for i := 1; i < len(sc.slc); i++ { + ret = fn.Invoke(ret, sc.slc[i]) + if IsReduced(ret) { + return ret + } + } + return ret +} diff --git a/pkg/lang/subvector.go b/pkg/lang/subvector.go index 55ac3c8..86210f5 100644 --- a/pkg/lang/subvector.go +++ b/pkg/lang/subvector.go @@ -84,7 +84,7 @@ func (v *SubVector) EntryAt(key interface{}) IMapEntry { return nil } if kInt >= 0 && kInt < v.end-v.start { - val, _ := v.v.Nth(v.start + kInt) + val := v.v.Nth(v.start + kInt) return &MapEntry{key: kInt, val: val} } return nil @@ -96,9 +96,7 @@ func (v *SubVector) ValAt(i interface{}) interface{} { func (v *SubVector) ValAtDefault(k, def interface{}) interface{} { if i, ok := AsInt(k); ok { - if val, ok := v.Nth(i); ok { - return val - } + return v.NthDefault(i, def) } return def } @@ -123,16 +121,18 @@ func (v *SubVector) Equal(v2 interface{}) bool { return true } -func (v *SubVector) Nth(i int) (val interface{}, ok bool) { +func (v *SubVector) Nth(i int) interface{} { + if v.start+i >= v.end || i < 0 { + panic(NewIndexOutOfBoundsError()) + } return v.v.Nth(v.start + i) } func (v *SubVector) NthDefault(i int, def interface{}) interface{} { - val, ok := v.Nth(i) - if !ok { - return def + if i >= 0 && i < v.Count() { + return v.Nth(i) } - return val + return def } func (v *SubVector) Peek() interface{} { diff --git a/pkg/lang/vector.go b/pkg/lang/vector.go index 4d5f896..91f40dd 100644 --- a/pkg/lang/vector.go +++ b/pkg/lang/vector.go @@ -104,8 +104,8 @@ func (v *Vector) EntryAt(key interface{}) IMapEntry { if !ok { return nil } - val, ok := v.Nth(kInt) - if !ok { + val := v.NthDefault(kInt, notFound) + if val == notFound { return nil } return &MapEntry{ @@ -128,23 +128,24 @@ func (v *Vector) ValAt(i interface{}) interface{} { func (v *Vector) ValAtDefault(k, def interface{}) interface{} { if i, ok := AsInt(k); ok { - if val, ok := v.Nth(i); ok { - return val - } + return v.NthDefault(i, def) } return def } -func (v *Vector) Nth(i int) (val interface{}, ok bool) { - return v.vec.Index(i) +func (v *Vector) Nth(i int) interface{} { + res, ok := v.vec.Index(i) + if !ok { + panic(NewIndexOutOfBoundsError()) + } + return res } func (v *Vector) NthDefault(i int, def interface{}) interface{} { - val, ok := v.Nth(i) - if !ok { - return def + if i >= 0 && i < v.Count() { + return v.Nth(i) } - return val + return def } func (v *Vector) String() string { @@ -275,8 +276,7 @@ func toSlice(x interface{}) []interface{} { count := Count(x) res := make([]interface{}, count) for i := 0; i < count; i++ { - val, _ := idxd.Nth(i) - res = append(res, val) + res = append(res, idxd.Nth(i)) } return res } diff --git a/pkg/pkgmap/pkgmap.go b/pkg/pkgmap/pkgmap.go index a07a02d..74ab4f9 100644 --- a/pkg/pkgmap/pkgmap.go +++ b/pkg/pkgmap/pkgmap.go @@ -46,3 +46,7 @@ func SplitExport(export string) (string, string) { func mungePkg(pkg string) string { return strings.Replace(pkg, "/", "$", -1) } + +func UnmungePkg(pkg string) string { + return strings.Replace(pkg, "$", "/", -1) +} diff --git a/pkg/stdlib/glojure/core.glj b/pkg/stdlib/glojure/core.glj index e7edc08..316c46d 100644 --- a/pkg/stdlib/glojure/core.glj +++ b/pkg/stdlib/glojure/core.glj @@ -683,7 +683,7 @@ (list (quote github.com$glojurelang$glojure$pkg$lang.NewLazySeq) (list* (quote ^{:once true} fn*) [] body))) (defn ^:static ^glojure.lang.ChunkBuffer chunk-buffer ^glojure.lang.ChunkBuffer [capacity] - (glojure.lang.ChunkBuffer. capacity)) + (github.com$glojurelang$glojure$pkg$lang.NewChunkBuffer capacity)) (defn ^:static chunk-append [^glojure.lang.ChunkBuffer b x] (.add b x)) @@ -701,9 +701,9 @@ (.chunkedNext s)) (defn ^:static chunk-cons [chunk rest] - (if (glojure.lang.Numbers/isZero (github.com$glojurelang$glojure$pkg$lang.Count chunk)) + (if (github.com$glojurelang$glojure$pkg$lang.IsZero (github.com$glojurelang$glojure$pkg$lang.Count chunk)) rest - (glojure.lang.ChunkedCons. chunk rest))) + (github.com$glojurelang$glojure$pkg$lang.NewChunkedCons chunk rest))) (defn ^:static chunked-seq? [s] (instance? github.com$glojurelang$glojure$pkg$lang.IChunkedSeq s)) diff --git a/scripts/rewrite-core/rewrite.clj b/scripts/rewrite-core/rewrite.clj index 7dab34c..8fe90c3 100644 --- a/scripts/rewrite-core/rewrite.clj +++ b/scripts/rewrite-core/rewrite.clj @@ -367,7 +367,12 @@ (sexpr-replace '(list 'new 'clojure.lang.LazySeq (list* '^{:once true} fn* [] body)) '(list 'github.com$glojurelang$glojure$pkg$lang.NewLazySeq (list* '^{:once true} fn* [] body))) (sexpr-replace 'clojure.lang.RT/count 'github.com$glojurelang$glojure$pkg$lang.Count) + (sexpr-replace 'clojure.lang.IChunkedSeq 'github.com$glojurelang$glojure$pkg$lang.IChunkedSeq) + (sexpr-replace 'clojure.lang.ChunkBuffer. + 'github.com$glojurelang$glojure$pkg$lang.NewChunkBuffer) + (sexpr-replace 'clojure.lang.ChunkedCons. + 'github.com$glojurelang$glojure$pkg$lang.NewChunkedCons) ;; replace (. (applyTo )) with (glojure.lang.Apply ) [(fn select [zloc] (and (z/list? zloc) @@ -490,9 +495,11 @@ (sexpr-replace '(cast Number x) '(github.com$glojurelang$glojure$pkg$lang.AsNumber x)) (sexpr-replace '(. clojure.lang.Numbers (minus x)) - '(* -1 x)) + '(* -1 x)) ;; TODO: unary minus (sexpr-replace '(. clojure.lang.Numbers (minusP x)) - '(* -1 x)) + '(* -1 x)) ;; TODO: promoting ops + (sexpr-replace 'clojure.lang.Numbers/isZero + 'github.com$glojurelang$glojure$pkg$lang.IsZero) (sexpr-replace 'Unchecked_add 'UncheckedAdd) (sexpr-replace 'Unchecked_dec 'UncheckedDec) diff --git a/test/glojure/test_glojure/builtins.glj b/test/glojure/test_glojure/builtins.glj index 16ffee6..8a1a795 100644 --- a/test/glojure/test_glojure/builtins.glj +++ b/test/glojure/test_glojure/builtins.glj @@ -43,4 +43,10 @@ (recur (+ sum n)) sum))))))) +(deftest maps + (let [mp (go/make (go/map-of go/string go/any))] + (go/set-map-index mp "foo" 42) + (is (= 42 (go/map-index mp "foo"))) + (is (= ["foo" 42] (first (seq mp)))))) + (run-tests)