// save writes the state of the workspace to the named file. // The format of the output is ivy source text. func save(c *exec.Context, file string, conf *config.Config) { // "<conf.out>" is a special case for testing. out := conf.Output() if file != "<conf.out>" { fd, err := os.Create(file) if err != nil { value.Errorf("%s", err) } defer fd.Close() buf := bufio.NewWriter(fd) defer buf.Flush() out = buf } // Configuration settings. We will set the base below, // after we have printed all numbers in base 10. fmt.Fprintf(out, ")prec %d\n", conf.FloatPrec()) ibase, obase := conf.Base() fmt.Fprintf(out, ")maxbits %d\n", conf.MaxBits()) fmt.Fprintf(out, ")maxdigits %d\n", conf.MaxDigits()) fmt.Fprintf(out, ")origin %d\n", conf.Origin()) fmt.Fprintf(out, ")prompt %q\n", conf.Prompt()) fmt.Fprintf(out, ")format %q\n", conf.Format()) // Ops. printed := make(map[exec.OpDef]bool) for _, def := range c.Defs { var fn *exec.Function if def.IsBinary { fn = c.BinaryFn[def.Name] } else { fn = c.UnaryFn[def.Name] } for _, ref := range references(c, fn.Body) { if !printed[ref] { if ref.IsBinary { fmt.Fprintf(out, "op _ %s _\n", ref.Name) } else { fmt.Fprintf(out, "op %s _\n", ref.Name) } printed[ref] = true } } printed[def] = true fmt.Fprintln(out, fn) } // Global variables. syms := c.Stack[0] if len(syms) > 0 { // Set the base strictly to 10 for output. fmt.Fprintf(out, "# Set base 10 for parsing numbers.\n)base 10\n") // Sort the names for consistent output. sorted := sortSyms(syms) for _, sym := range sorted { // pi and e are generated if sym.name == "pi" || sym.name == "e" { continue } fmt.Fprintf(out, "%s = ", sym.name) put(out, sym.val) fmt.Fprint(out, "\n") } } // Now we can set the base. fmt.Fprintf(out, ")ibase %d\n", ibase) fmt.Fprintf(out, ")obase %d\n", obase) }