evaldo

package
v0.0.94 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 4, 2026 License: BSD-3-Clause Imports: 101 Imported by: 3

Documentation

Overview

builtins_base_error_utils.go

builtins_error_handling.go

builtins.go

builtins.go

builtins_trees.go

evaldo_rye0.go - A simplified interpreter for the Rye language

evaldo_rye00.go - A highly simplified interpreter for the Rye language This version only handles builtins and integers for performance optimization experiments

evaldo_rye0_no_opt.go - A simplified interpreter for the Rye language without word replacement optimization

Index

Constants

View Source
const MODE_PSQL = 2
View Source
const MODE_SQLITE = 1
View Source
const TYPE_CODE int = 2
View Source
const TYPE_SUBNODE int = 1

Variables

View Source
var BuiltinNames map[string]int // TODO --- this looks like some hanging global ... it should move to ProgramState, it doesn't even really work with contrib and external probably
View Source
var Builtins_bcrypt = map[string]*env.Builtin{

	"bcrypt-hash": {
		Argsn: 1,
		Doc:   "Generate hashing.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return __bcrypt_hash(ps, arg0, arg1, arg2, arg3, arg4)
		},
	},

	"bcrypt-check": {
		Argsn: 2,
		Doc:   "Compare hash and password.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return __bcrypt_check(ps, arg0, arg1, arg2, arg3, arg4)
		},
	},
	"generate-token": {
		Argsn: 1,
		Doc:   "Generate token for hashing.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return __generate_token(ps, arg0, arg1, arg2, arg3, arg4)
		},
	},
}
View Source
var Builtins_bson = map[string]*env.Builtin{

	"from-bson": {
		Argsn: 1,
		Doc:   "Decodes BSON data into Rye values.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			var val map[string]any

			err := bson.Unmarshal(arg0.(env.Native).Value.([]byte), &val)
			if err != nil {
				return MakeBuiltinError(ps, err.Error(), "from-bson")
			}

			return BsonToValue_Map(ps, val["val"], val["typ"].(string), val["met"], true)

		},
	},

	"to-bson": {
		Argsn: 1,
		Doc:   "Encodes a Rye value into BSON format.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			value := ValueToBSON(arg0, true)
			encoded, err := bson.Marshal(value)
			if err != nil {
				return MakeBuiltinError(ps, err.Error(), "to-bson")
			}
			return *env.NewNative(ps.Idx, encoded, "bytes")
		},
	},
}
View Source
var Builtins_cmd = map[string]*env.Builtin{

	"cmd": {
		Argsn: 1,
		Doc:   "Create a command.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			var args []string
			var pipe []*exec.Cmd
			switch input := arg0.(type) {
			case env.List:
				newArgs, err := listToCmdArgs(ps, input.Data...)
				if err != nil {
					return err
				}
				args = append(args, newArgs...)
			case env.Block:
				for _, c := range input.Series.S {
					switch it := c.(type) {
					case env.Word:
						args = append(args, it.Print(*ps.Idx))
					case env.Pipeword:
						word := it.ToWord().Print(*ps.Idx)
						if len(args) == 0 {
							return MakeBuiltinError(ps, "missing command before pipe", "cmd")
						}
						pipecmd := exec.Command(args[0], args[1:]...)
						pipecmd.Stdin = os.Stdin
						pipecmd.Stderr = os.Stderr
						pipe = append(pipe, pipecmd)
						args = []string{word}
					case env.Getword:
						EvalGetword(ps, it, nil, false)
						if ps.ErrorFlag {
							return ps.Res
						}
						newArgs, err := listToCmdArgs(ps, ps.Res)
						if err != nil {
							return err
						}
						args = append(args, newArgs...)
					case env.Block:
						ser := ps.Ser
						ps.Ser = it.Series
						ps.BlockFile = it.FileName
						ps.BlockLine = it.Line
						EvalBlock(ps)
						MaybeDisplayFailureOrError(ps, ps.Idx, "cmd")
						if ps.ErrorFlag {
							ps.Ser = ser
							return ps.Res
						}
						ps.Ser = ser
						newArgs, err := listToCmdArgs(ps, ps.Res)
						if err != nil {

							return err
						}
						args = append(args, newArgs...)
					default:
						newArgs, err := listToCmdArgs(ps, it)
						if err != nil {

							return err
						}
						args = append(args, newArgs...)
					}
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.BlockType, env.ListType}, "cmd")
			}

			if len(args) == 0 {
				return MakeBuiltinError(ps, "missing command", "cmd")
			}
			cmd := exec.Command(args[0], args[1:]...)
			cmd.Stdin = os.Stdin
			cmd.Stdout = os.Stdout
			cmd.Stderr = os.Stderr
			return *env.NewNative(ps.Idx, &command{cmd: cmd, pipe: pipe}, "command")
		},
	},

	"command//Dir!": {
		Argsn: 2,
		Doc:   "Change the working directory of a command.",
		Fn: commandFn("Dir!", func(ps *env.ProgramState, c *command, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch s := arg1.(type) {
			case env.Uri:
				c.cmd.Dir = s.Path
				return arg0
			default:
				return MakeArgError(ps, 2, []env.Type{env.UriType}, "Dir!")
			}
		}),
	},

	"command//Stdin!": {
		Argsn: 2,
		Doc:   "Change the standard input of a command.",
		Fn: commandFn("Stdin!", func(ps *env.ProgramState, c *command, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			out, ret := commandInputFd(ps, c, arg1)
			if ret != nil {
				return ret
			}
			c.cmd.Stdin = out
			return arg0
		}),
	},

	"command//Stdout!": {
		Argsn: 2,
		Doc:   "Change the standard output of a command.",
		Fn: commandFn("Stdout!", func(ps *env.ProgramState, c *command, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			out, ret := commandOutputFd(ps, c, arg1)
			if ret != nil {
				return ret
			}
			c.cmd.Stdout = out
			return arg0
		}),
	},

	"command//Stderr!": {
		Argsn: 2,
		Doc:   "Change the standard error of a command.",
		Fn: commandFn("Stderr!", func(ps *env.ProgramState, c *command, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			out, ret := commandOutputFd(ps, c, arg1)
			if ret != nil {
				return ret
			}
			c.cmd.Stderr = out
			return arg0
		}),
	},

	"command//Pipe": {
		Argsn: 2,
		Doc:   "Pipe the output of the first command to the input of the second command.",
		Fn: commandFn("Pipe", func(ps *env.ProgramState, c *command, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch it := arg1.(type) {
			case env.Native:
				if c2, ok := it.Value.(*command); ok {
					return *env.NewNative(ps.Idx, pipeCommands(c, c2), "command")
				} else {
					return MakeBuiltinError(ps, "arg1 must be of kind command", "Pipe!")
				}
			default:
				return MakeArgError(ps, 2, []env.Type{env.NativeType}, "Pipe")
			}
		}),
	},

	"command//Run": {
		Argsn: 1,
		Doc:   "Start a command and wait for it to finish.",
		Fn: commandFn("Run", func(ps *env.ProgramState, c *command, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			defer c.Close()
			err := c.StartPipe()
			if err != nil {
				ps.FailureFlag = true
				return MakeBuiltinError(ps, err.Error(), "Run")
			}
			err = c.cmd.Run()
			if err != nil {
				ps.FailureFlag = true
				return MakeBuiltinError(ps, err.Error(), "Run")
			}
			return *env.NewBoolean(true)
		}),
	},

	"command//Status": {
		Argsn: 1,
		Doc:   "Start a command, wait for it to finish, and return its exit status.",
		Fn: commandFn("Status", func(ps *env.ProgramState, c *command, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			err := c.StartPipe()
			if err != nil {
				c.Close()
				ps.FailureFlag = true
				return MakeBuiltinError(ps, err.Error(), "Status")
			}
			err = c.cmd.Run()
			c.Close()
			status := c.cmd.ProcessState.ExitCode()
			if err != nil && status == -1 {
				ps.FailureFlag = true
				return MakeBuiltinError(ps, err.Error(), "Status")
			}
			if len(c.pipe) > 0 {
				var statusList []any
				for _, cmd := range c.pipe {
					statusList = append(statusList, *env.NewInteger(int64(cmd.ProcessState.ExitCode())))
				}
				statusList = append(statusList, *env.NewInteger(int64(status)))
				return *env.NewList(statusList)
			}
			return *env.NewInteger(int64(status))
		}),
	},

	"command//Output": {
		Argsn: 1,
		Doc:   "Start a command, wait for it to finish, and return its standard output",
		Fn: commandFn("Output", func(ps *env.ProgramState, c *command, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			defer c.Close()
			err := c.StartPipe()
			if err != nil {
				ps.FailureFlag = true
				return MakeBuiltinError(ps, err.Error(), "Output")
			}
			c.cmd.Stdout = nil
			out, err := c.cmd.Output()
			if err != nil {
				ps.FailureFlag = true
				return MakeBuiltinError(ps, err.Error(), "Output")
			}
			return *env.NewString(string(out))
		}),
	},

	"command//CombinedOutput": {
		Argsn: 1,
		Doc:   "Start a command, wait for it to finish, and return its combined standard output and error",
		Fn: commandFn("CombinedOutput", func(ps *env.ProgramState, c *command, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			defer c.Close()
			err := c.StartPipe()
			if err != nil {
				ps.FailureFlag = true
				return MakeBuiltinError(ps, err.Error(), "CombinedOutput")
			}
			c.cmd.Stdout = nil
			c.cmd.Stderr = nil
			out, err := c.cmd.CombinedOutput()
			if err != nil {
				ps.FailureFlag = true
				return MakeBuiltinError(ps, err.Error(), "CombinedOutput")
			}
			return *env.NewString(string(out))
		}),
	},
}
View Source
var Builtins_console = map[string]*env.Builtin{
	"enter-console": {
		Argsn: 1,
		Doc:   "Stops execution and gives you a Rye console, to test the code inside environment.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch name := arg0.(type) {
			case env.String:
				ser := ps.Ser

				fmt.Println("Welcome to console: \033[1m" + name.Value + "\033[0m")
				fmt.Println("* use \033[1mlc\033[0m to list current context")
				fmt.Println("-------------------------------------------------------------")

				DoRyeRepl(ps, "rye", ShowResults)
				fmt.Println("-------------------------------------------------------------")
				ps.Ser = ser
				return ps.Res
			default:
				return MakeArgError(ps, 1, []env.Type{env.StringType}, "enter-console")
			}
		},
	},
}
View Source
var Builtins_conversion = map[string]*env.Builtin{

	"convert": {
		Argsn: 2,
		Doc:   "Converts value from one kind to another.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return BuiConvert(ps, arg0, arg1)
		},
	},

	"converter": {
		Argsn: 3,
		Doc:   "Sets a converter between two kinds of objects.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {

			switch obj1 := arg0.(type) {
			case env.Kind:
				switch obj2 := arg1.(type) {
				case env.Kind:
					switch spec := arg2.(type) {
					case env.Block:
						obj2.SetConverter(obj1.Kind.Index, spec)
						return obj2
					default:
						return MakeArgError(ps, 3, []env.Type{env.BlockType}, "converter")
					}
				default:
					return MakeArgError(ps, 2, []env.Type{env.KindType, env.BlockType}, "converter")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.KindType}, "converter")
			}
		},
	},
}
View Source
var Builtins_crypto = map[string]*env.Builtin{

	"decode\\hex": {
		Argsn: 1,
		Doc:   "Decodes a hexadecimal string to a bytes native value.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch addr := arg0.(type) {
			case env.String:
				r, err := hex.DecodeString(addr.Value)
				if err != nil {
					ps.FailureFlag = true
					return MakeBuiltinError(ps, "Failure to decode string.", "string//to-bytes")
				}
				return *env.NewNative(ps.Idx, r, "bytes")
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.StringType}, "string//to-bytes")
			}
		},
	},

	"encode-to\\hex": {
		Argsn: 1,
		Doc:   "Encodes a bytes native value to a hexadecimal string.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch addr := arg0.(type) {
			case env.Native:
				return *env.NewString(hex.EncodeToString(addr.Value.([]byte)))
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "bytes//to-string")
			}
		},
	},

	"Ed25519-pub-key//To-string": {
		Argsn: 1,
		Doc:   "Converts an Ed25519 public key to its hexadecimal string representation.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch addr := arg0.(type) {
			case env.Native:
				return *env.NewString(hex.EncodeToString(addr.Value.(ed25519.PublicKey)))
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Ed25519-pub-key//To-string")
			}
		},
	},

	"Ed25519-priv-key//To-string": {
		Argsn: 1,
		Doc:   "Converts an Ed25519 private key to its hexadecimal string representation.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch addr := arg0.(type) {
			case env.Native:
				return *env.NewString(hex.EncodeToString(addr.Value.(ed25519.PrivateKey)))
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Ed25519-priv-key//To-string")
			}
		},
	},

	"ed25519-generate-keys": {
		Argsn: 0,
		Doc:   "Generates a new Ed25519 key pair and returns them in a block with public key first, then private key.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			keys := make([]env.Object, 2)
			puk, pvk, err := ed25519.GenerateKey(nil)
			if err != nil {
				ps.FailureFlag = true
				return MakeBuiltinError(ps, "Failed to generate keys.", "ed25519-generate-keys")
			}
			keys[0] = *env.NewNative(ps.Idx, puk, "Ed25519-pub-key")
			keys[1] = *env.NewNative(ps.Idx, pvk, "Ed25519-priv-key")
			ser := *env.NewTSeries(keys)
			return *env.NewBlock(ser)
		},
	},

	"ed25519-private-key": {
		Argsn: 1,
		Doc:   "Creates an Ed25519 private key from a hexadecimal string or bytes value.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			var pkey []byte
			var err error
			switch server := arg0.(type) {
			case env.Native:
				pkey = server.Value.([]byte)
			case env.String:
				pkey, err = hex.DecodeString(server.Value)
				if err != nil {
					ps.FailureFlag = true
					return MakeBuiltinError(ps, "Error in decoding string.", "ed25519-private-key")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType, env.StringType}, "ed25519-private-key")
			}
			return *env.NewNative(ps.Idx, ed25519.PrivateKey(pkey), "Ed25519-priv-key")

		},
	},

	"ed25519-public-key": {
		Argsn: 1,
		Doc:   "Creates an Ed25519 public key from a hexadecimal string or bytes value.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			var pkey []byte
			var err error
			switch server := arg0.(type) {
			case env.Native:
				pkey = server.Value.([]byte)
			case env.String:
				pkey, err = hex.DecodeString(server.Value)
				if err != nil {
					ps.FailureFlag = true
					return MakeBuiltinError(ps, "Error in decoding string.", "ed25519-public-key")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType, env.StringType}, "ed25519-public-key")
			}
			return *env.NewNative(ps.Idx, ed25519.PublicKey(pkey), "Ed25519-pub-key")

		},
	},

	"Ed25519-priv-key//Sign": {
		Argsn: 2,
		Doc:   "Signs a string message with an Ed25519 private key and returns the signature as bytes.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch pvk := arg0.(type) {
			case env.Native:
				switch buff := arg1.(type) {
				case env.String:
					sigb := ed25519.Sign(pvk.Value.(ed25519.PrivateKey), []byte(buff.Value))
					return *env.NewNative(ps.Idx, sigb, "bytes")
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 1, []env.Type{env.StringType}, "Ed25519-priv-key//Sign")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Ed25519-priv-key//Sign")
			}
		},
	},

	"sha512": {
		Argsn: 1,
		Doc:   "Calculates the SHA-512 hash of a string and returns the result as a hexadecimal string.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch s := arg0.(type) {
			case env.String:
				h := sha512.New()
				h.Write([]byte(s.Value))
				bs := h.Sum(nil)
				return *env.NewString(hex.EncodeToString(bs[:]))
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.StringType}, "sha512")
			}
		},
	},

	"age-generate-keys": {
		Argsn: 0,
		Doc:   "Generates a new age key pair (identity and recipient).",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			identity, err := age.GenerateX25519Identity()
			if err != nil {
				ps.FailureFlag = true
				return MakeBuiltinError(ps, "Failed to generate key pair.", "age-generate-keys")
			}
			keys := make([]env.Object, 2)
			keys[0] = *env.NewNative(ps.Idx, identity, "age-identity")
			keys[1] = *env.NewNative(ps.Idx, identity.Recipient(), "age-recipient")
			ser := *env.NewTSeries(keys)
			return *env.NewBlock(ser)
		},
	},

	"age-identity": {
		Argsn: 1,
		Doc:   "Creates an age identity from a string or bytes.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			var identity *age.X25519Identity
			var err error
			switch ident := arg0.(type) {
			case env.Native:
				if ps.Idx.GetWord(ident.GetKind()) != "bytes" {
					ps.FailureFlag = true
					return MakeArgError(ps, 1, []env.Type{env.NativeType}, "age-identity")
				}
				identity, err = age.ParseX25519Identity(hex.EncodeToString(ident.Value.([]byte)))
				if err != nil {
					ps.FailureFlag = true
					return MakeBuiltinError(ps, "Error in parsing identity: "+err.Error(), "age-identity")
				}
			case env.String:
				identity, err = age.ParseX25519Identity(ident.Value)
				if err != nil {
					ps.FailureFlag = true
					return MakeBuiltinError(ps, "Error in decoding string: "+err.Error(), "age-identity")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType, env.StringType}, "age-identity")
			}
			return *env.NewNative(ps.Idx, identity, "age-identity")
		},
	},

	"age-recipient": {
		Argsn: 1,
		Doc:   "Creates an age recipient from a string or bytes.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			var recipient *age.X25519Recipient
			var err error
			switch rec := arg0.(type) {
			case env.Native:
				if ps.Idx.GetWord(rec.GetKind()) != "bytes" {
					ps.FailureFlag = true
					return MakeArgError(ps, 1, []env.Type{env.NativeType}, "age-recipient")
				}
				recipient, err = age.ParseX25519Recipient(hex.EncodeToString(rec.Value.([]byte)))
				if err != nil {
					ps.FailureFlag = true
					return MakeBuiltinError(ps, "Error in parsing recipient: "+err.Error(), "age-recipient")
				}
			case env.String:
				recipient, err = age.ParseX25519Recipient(rec.Value)
				if err != nil {
					ps.FailureFlag = true
					return MakeBuiltinError(ps, "Error in decoding string: "+err.Error(), "age-recipient")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType, env.StringType}, "age-recipient")
			}
			return *env.NewNative(ps.Idx, recipient, "age-recipient")
		},
	},

	"age-encrypt": {
		Argsn: 2,
		Doc:   "Encrypts a reader with age for the provided age recipient or string password and returns a reader.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch r := arg0.(type) {
			case env.Native:
				if ps.Idx.GetWord(r.GetKind()) != "reader" {
					ps.FailureFlag = true
					return MakeArgError(ps, 1, []env.Type{env.NativeType}, "age-encrypt")
				}
				reader := r.Value.(io.Reader)
				var recipient age.Recipient
				switch rec := arg1.(type) {
				case env.Native:
					if ps.Idx.GetWord(rec.GetKind()) != "age-recipient" {
						ps.FailureFlag = true
						return MakeArgError(ps, 1, []env.Type{env.NativeType}, "age-encrypt")
					}
					recipient = rec.Value.(*age.X25519Recipient)
				case env.String:
					var err error
					recipient, err = age.NewScryptRecipient(rec.Value)
					if err != nil {
						ps.FailureFlag = true
						return MakeBuiltinError(ps, "Error in creating recipient: "+err.Error(), "age-encrypt")
					}
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 1, []env.Type{env.NativeType, env.StringType}, "age-encrypt")
				}
				buf := new(bytes.Buffer)
				w, err := age.Encrypt(buf, recipient)
				if err != nil {
					ps.FailureFlag = true
					return MakeBuiltinError(ps, "Error in encrypting: "+err.Error(), "age-encrypt")
				}

				data, err := io.ReadAll(reader)
				if err != nil {
					ps.FailureFlag = true
					return MakeBuiltinError(ps, "Error reading from reader: "+err.Error(), "age-encrypt")
				}

				if _, err := w.Write(data); err != nil {
					ps.FailureFlag = true
					return MakeBuiltinError(ps, "Error in writing to buffer: "+err.Error(), "age-encrypt")
				}
				w.Close()
				return *env.NewNative(ps.Idx, bytes.NewReader(buf.Bytes()), "reader")
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "age-encrypt")
			}
		},
	},

	"age-decrypt": {
		Argsn: 2,
		Doc:   "Decrypts a reader with age using the provided age identity or string password and returns a reader with the decrypted content.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch r := arg0.(type) {
			case env.Native:
				if ps.Idx.GetWord(r.GetKind()) != "reader" {
					ps.FailureFlag = true
					return MakeArgError(ps, 1, []env.Type{env.NativeType}, "age-decrypt")
				}
				reader := r.Value.(io.Reader)
				var identity age.Identity
				switch ident := arg1.(type) {
				case env.Native:
					if ps.Idx.GetWord(ident.GetKind()) != "age-identity" {
						ps.FailureFlag = true
						return MakeArgError(ps, 1, []env.Type{env.NativeType}, "age-decrypt")
					}
					identity = ident.Value.(*age.X25519Identity)
				case env.String:
					var err error
					identity, err = age.NewScryptIdentity(ident.Value)
					if err != nil {
						ps.FailureFlag = true
						return MakeBuiltinError(ps, "Error in creating identity: "+err.Error(), "age-decrypt")
					}
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 1, []env.Type{env.NativeType, env.StringType}, "age-decrypt")
				}
				decrypted, err := age.Decrypt(reader, identity)
				if err != nil {
					ps.FailureFlag = true
					return MakeBuiltinError(ps, "Error in decrypting: "+err.Error(), "age-decrypt")
				}
				return *env.NewNative(ps.Idx, decrypted, "reader")
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "age-decrypt")
			}
		},
	},

	"pkcs12-to-pem": {
		Argsn: 2,
		Doc:   "Converts a PKCS#12 (.p12) file bytes to PEM blocks using the provided password. Returns a block of pem-block native values.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch p12Data := arg0.(type) {
			case env.Native:
				if ps.Idx.GetWord(p12Data.GetKind()) != "bytes" {
					ps.FailureFlag = true
					return MakeArgError(ps, 1, []env.Type{env.NativeType}, "pkcs12-to-pem")
				}
				switch password := arg1.(type) {
				case env.String:
					blocks, err := pkcs12.ToPEM(p12Data.Value.([]byte), password.Value)
					if err != nil {
						ps.FailureFlag = true
						return MakeBuiltinError(ps, fmt.Sprintf("Failed to convert .p12 to PEM: %v", err), "pkcs12-to-pem")
					}

					objects := make([]env.Object, len(blocks))
					for i, block := range blocks {
						objects[i] = *env.NewNative(ps.Idx, block, "pem-block")
					}
					ser := *env.NewTSeries(objects)
					return *env.NewBlock(ser)
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 2, []env.Type{env.StringType}, "pkcs12-to-pem")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "pkcs12-to-pem")
			}
		},
	},

	"pkcs12-decode": {
		Argsn: 2,
		Doc:   "Decodes a PKCS#12 (.p12) file bytes into private key and certificates using the provided password. Returns a block with [private-key, certificates, ca-certificates].",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch p12Data := arg0.(type) {
			case env.Native:
				if ps.Idx.GetWord(p12Data.GetKind()) != "bytes" {
					ps.FailureFlag = true
					return MakeArgError(ps, 1, []env.Type{env.NativeType}, "pkcs12-decode")
				}
				switch password := arg1.(type) {
				case env.String:
					key, cert, caCerts, err := sslmate.DecodeChain(p12Data.Value.([]byte), password.Value)
					if err != nil {
						ps.FailureFlag = true
						return MakeBuiltinError(ps, fmt.Sprintf("Failed to decode .p12: %v", err), "pkcs12-decode")
					}

					certObjects := make([]env.Object, 0)
					if cert != nil {
						certObjects = append(certObjects, *env.NewNative(ps.Idx, cert, "x509-certificate"))
					}
					certSer := *env.NewTSeries(certObjects)
					certBlock := *env.NewBlock(certSer)

					caCertObjects := make([]env.Object, len(caCerts))
					for i, caCert := range caCerts {
						caCertObjects[i] = *env.NewNative(ps.Idx, caCert, "x509-certificate")
					}
					caCertSer := *env.NewTSeries(caCertObjects)
					caCertBlock := *env.NewBlock(caCertSer)

					objects := make([]env.Object, 3)
					if key != nil {
						objects[0] = *env.NewNative(ps.Idx, key, "private-key")
					} else {
						objects[0] = *env.NewNative(ps.Idx, nil, "private-key")
					}
					objects[1] = certBlock
					objects[2] = caCertBlock
					ser := *env.NewTSeries(objects)
					return *env.NewBlock(ser)
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 2, []env.Type{env.StringType}, "pkcs12-decode")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "pkcs12-decode")
			}
		},
	},

	"pem-block//Block-type?": {
		Argsn: 1,
		Doc:   "Returns the type of a PEM block as a string (e.g., 'CERTIFICATE', 'RSA PRIVATE KEY').",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch certData := arg0.(type) {
			case env.Native:
				if ps.Idx.GetWord(certData.GetKind()) != "pem-block" {
					ps.FailureFlag = true
					return MakeArgError(ps, 1, []env.Type{env.NativeType}, "x509-parse-certificate")
				}
				pb, ok := certData.Value.(*pem.Block)
				if ok {
					return *env.NewString(pb.Type)
				}
				return MakeBuiltinError(ps, fmt.Sprintf("Failed to parse certificate"), "x509-parse-certificate")

			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "x509-parse-certificate")
			}
		},
	},

	"pem-block//Headers?": {
		Argsn: 1,
		Doc:   "Returns the headers of a PEM block as a dictionary.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch certData := arg0.(type) {
			case env.Native:
				if ps.Idx.GetWord(certData.GetKind()) != "pem-block" {
					ps.FailureFlag = true
					return MakeArgError(ps, 1, []env.Type{env.NativeType}, "x509-parse-certificate")
				}
				pb, ok := certData.Value.(*pem.Block)
				if ok {
					headers := make(map[string]interface{}, len(pb.Headers))
					for k, v := range pb.Headers {
						headers[k] = v
					}
					return *env.NewDict(headers)
				}
				return MakeBuiltinError(ps, fmt.Sprintf("Failed to parse certificate"), "x509-parse-certificate")

			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "x509-parse-certificate")
			}
		},
	},

	"x509-parse-certificate": {
		Argsn: 1,
		Doc:   "Parses a PEM block into an X.509 certificate native value.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch certData := arg0.(type) {
			case env.Native:
				if ps.Idx.GetWord(certData.GetKind()) != "pem-block" {
					ps.FailureFlag = true
					return MakeArgError(ps, 1, []env.Type{env.NativeType}, "x509-parse-certificate")
				}
				pb, ok := certData.Value.(*pem.Block)
				if ok {
					cert, err := x509.ParseCertificate(pb.Bytes)
					if err != nil {
						ps.FailureFlag = true
						return MakeBuiltinError(ps, fmt.Sprintf("Failed to parse certificate: %v", err), "x509-parse-certificate")
					}
					return *env.NewNative(ps.Idx, cert, "x509-certificate")
				}
				return MakeBuiltinError(ps, fmt.Sprintf("Failed to parse certificate"), "x509-parse-certificate")

			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "x509-parse-certificate")
			}
		},
	},

	"x509-certificate//Not-after?": {
		Argsn: 1,
		Doc:   "Returns the expiration date (NotAfter) of an X.509 certificate as a time value.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch cert := arg0.(type) {
			case env.Native:
				if ps.Idx.GetWord(cert.GetKind()) != "x509-certificate" {
					ps.FailureFlag = true
					return MakeArgError(ps, 1, []env.Type{env.NativeType}, "x509-certificate//is-expired")
				}
				c := cert.Value.(*x509.Certificate)
				return *env.NewTime(c.NotAfter)
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "x509-certificate//is-expired")
			}
		},
	},

	"x509-certificate//Not-before?": {
		Argsn: 1,
		Doc:   "Returns the start date (NotBefore) of an X.509 certificate as a time value.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch cert := arg0.(type) {
			case env.Native:
				if ps.Idx.GetWord(cert.GetKind()) != "x509-certificate" {
					ps.FailureFlag = true
					return MakeArgError(ps, 1, []env.Type{env.NativeType}, "x509-certificate//is-expired")
				}
				c := cert.Value.(*x509.Certificate)
				return *env.NewTime(c.NotBefore)
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "x509-certificate//is-expired")
			}
		},
	},

	"x509-certificate//Is-expired": {
		Argsn: 1,
		Doc:   "Checks if an X.509 certificate has expired. Returns 1 if expired, 0 otherwise.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch cert := arg0.(type) {
			case env.Native:
				if ps.Idx.GetWord(cert.GetKind()) != "x509-certificate" {
					ps.FailureFlag = true
					return MakeArgError(ps, 1, []env.Type{env.NativeType}, "x509-certificate//is-expired")
				}
				c := cert.Value.(*x509.Certificate)
				if time.Now().After(c.NotAfter) {
					return env.Integer{1}
				}
				return env.Integer{0}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "x509-certificate//is-expired")
			}
		},
	},

	"generate-self-signed-certificate": {
		Argsn: 2,
		Doc:   "Generates a self-signed X.509 certificate with a new RSA key pair.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {

			switch keySize := arg0.(type) {
			case env.Integer:
				if keySize.Value < 2048 {
					ps.FailureFlag = true
					return MakeBuiltinError(ps, "Key size must be at least 2048 bits", "generate-self-signed-certificate")
				}

				switch subjectDict := arg1.(type) {
				case env.Dict:

					privateKey, err := rsa.GenerateKey(rand.Reader, int(keySize.Value))
					if err != nil {
						ps.FailureFlag = true
						return MakeBuiltinError(ps, fmt.Sprintf("Failed to generate RSA key: %v", err), "generate-self-signed-certificate")
					}

					serialNumber, _ := rand.Int(rand.Reader, new(big.Int).Lsh(big.NewInt(1), 128))
					template := x509.Certificate{
						SerialNumber: serialNumber,
						Subject:      pkix.Name{},
						NotBefore:    time.Now(),
						NotAfter:     time.Now().Add(365 * 24 * time.Hour),
						KeyUsage:     x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
						ExtKeyUsage:  []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
						IsCA:         true,
					}

					if cn, ok := subjectDict.Data["CommonName"]; ok {
						if cnStr, ok := cn.(string); ok {
							template.Subject.CommonName = cnStr
						}
					}
					if org, ok := subjectDict.Data["Organization"]; ok {
						if orgStr, ok := org.(string); ok {
							template.Subject.Organization = []string{orgStr}
						}
					}

					certBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &privateKey.PublicKey, privateKey)
					if err != nil {
						ps.FailureFlag = true
						return MakeBuiltinError(ps, fmt.Sprintf("Failed to create certificate: %v", err), "generate-self-signed-certificate")
					}

					objects := []env.Object{
						*env.NewNative(ps.Idx, &x509.Certificate{Raw: certBytes}, "x509-certificate"),
						*env.NewNative(ps.Idx, privateKey, "rsa-private-key"),
					}
					ser := *env.NewTSeries(objects)
					return *env.NewBlock(ser)
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 2, []env.Type{env.DictType}, "generate-self-signed-certificate")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.IntegerType}, "generate-self-signed-certificate")
			}
		},
	},

	"encode-to-pem": {
		Argsn: 2,
		Doc:   "Encodes a certificate and private key as PEM-formatted data.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch certObj := arg0.(type) {
			case env.Native:
				if ps.Idx.GetWord(certObj.GetKind()) != "x509-certificate" {
					ps.FailureFlag = true
					return MakeArgError(ps, 1, []env.Type{env.NativeType}, "encode-to-pem")
				}
				cert := certObj.Value.(*x509.Certificate)
				switch keyObj := arg1.(type) {
				case env.Native:
					if ps.Idx.GetWord(keyObj.GetKind()) != "rsa-private-key" {
						ps.FailureFlag = true
						return MakeArgError(ps, 2, []env.Type{env.NativeType}, "encode-to-pem")
					}
					privateKey := keyObj.Value.(*rsa.PrivateKey)

					certPEM := &bytes.Buffer{}
					err := pem.Encode(certPEM, &pem.Block{
						Type:  "CERTIFICATE",
						Bytes: cert.Raw,
					})
					if err != nil {
						ps.FailureFlag = true
						return MakeBuiltinError(ps, fmt.Sprintf("Failed to encode certificate to PEM: %v", err), "encode-to-pem")
					}

					keyPEM := &bytes.Buffer{}
					err = pem.Encode(keyPEM, &pem.Block{
						Type:  "RSA PRIVATE KEY",
						Bytes: x509.MarshalPKCS1PrivateKey(privateKey),
					})
					if err != nil {
						ps.FailureFlag = true
						return MakeBuiltinError(ps, fmt.Sprintf("Failed to encode private key to PEM: %v", err), "encode-to-pem")
					}

					objects := []env.Object{
						*env.NewNative(ps.Idx, certPEM.Bytes(), "Go-bytes"),
						*env.NewNative(ps.Idx, keyPEM.Bytes(), "Go-bytes"),
					}
					ser := *env.NewTSeries(objects)
					return *env.NewBlock(ser)
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 2, []env.Type{env.NativeType}, "encode-to-pem")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "encode-to-pem")
			}
		},
	},

	"encode-to-p12": {
		Argsn: 3,
		Doc:   "Encodes a certificate and private key into a PKCS#12 (.p12) file with password protection.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch certObj := arg0.(type) {
			case env.Native:
				if ps.Idx.GetWord(certObj.GetKind()) != "x509-certificate" {
					ps.FailureFlag = true
					return MakeArgError(ps, 1, []env.Type{env.NativeType}, "encode-to-p12")
				}
				cert := certObj.Value.(*x509.Certificate)
				switch keyObj := arg1.(type) {
				case env.Native:
					if ps.Idx.GetWord(keyObj.GetKind()) != "rsa-private-key" {
						ps.FailureFlag = true
						return MakeArgError(ps, 2, []env.Type{env.NativeType}, "encode-to-p12")
					}
					privateKey := keyObj.Value.(*rsa.PrivateKey)
					switch password := arg2.(type) {
					case env.String:
						p12Bytes, err := sslmate.Encode(rand.Reader, privateKey, cert, nil, password.Value)
						if err != nil {
							ps.FailureFlag = true
							return MakeBuiltinError(ps, fmt.Sprintf("Failed to encode to .p12: %v", err), "encode-to-p12")
						}
						return *env.NewNative(ps.Idx, p12Bytes, "Go-bytes")
					default:
						ps.FailureFlag = true
						return MakeArgError(ps, 3, []env.Type{env.StringType}, "encode-to-p12")
					}
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 2, []env.Type{env.NativeType}, "encode-to-p12")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "encode-to-p12")
			}
		},
	},

	"x509-certificate//Subject?": {
		Argsn: 1,
		Doc:   "Returns the subject Distinguished Name (DN) of an X.509 certificate as a string.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch cert := arg0.(type) {
			case env.Native:
				if ps.Idx.GetWord(cert.GetKind()) != "x509-certificate" {
					ps.FailureFlag = true
					return MakeArgError(ps, 1, []env.Type{env.NativeType}, "x509-certificate//Subject?")
				}
				c := cert.Value.(*x509.Certificate)
				return *env.NewString(c.Subject.String())
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "x509-certificate//Subject?")
			}
		},
	},

	"x509-certificate//Issuer?": {
		Argsn: 1,
		Doc:   "Returns the issuer Distinguished Name (DN) of an X.509 certificate as a string.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch cert := arg0.(type) {
			case env.Native:
				if ps.Idx.GetWord(cert.GetKind()) != "x509-certificate" {
					ps.FailureFlag = true
					return MakeArgError(ps, 1, []env.Type{env.NativeType}, "x509-certificate//issuer?")
				}
				c := cert.Value.(*x509.Certificate)
				return *env.NewString(c.Issuer.String())
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "x509-certificate//issuer?")
			}
		},
	},

	"x509-certificate//Serial-number?": {
		Argsn: 1,
		Doc:   "Returns the serial number of an X.509 certificate as a string.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch cert := arg0.(type) {
			case env.Native:
				if ps.Idx.GetWord(cert.GetKind()) != "x509-certificate" {
					ps.FailureFlag = true
					return MakeArgError(ps, 1, []env.Type{env.NativeType}, "x509-certificate//serial-number?")
				}
				c := cert.Value.(*x509.Certificate)
				return *env.NewString(c.SerialNumber.String())
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "x509-certificate//serial-number?")
			}
		},
	},

	"x509-certificate//Signature-algorithm?": {
		Argsn: 1,
		Doc:   "Returns the signature algorithm of an X.509 certificate as a string.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch cert := arg0.(type) {
			case env.Native:
				if ps.Idx.GetWord(cert.GetKind()) != "x509-certificate" {
					ps.FailureFlag = true
					return MakeArgError(ps, 1, []env.Type{env.NativeType}, "x509-certificate//signature-algorithm?")
				}
				c := cert.Value.(*x509.Certificate)
				return *env.NewString(c.SignatureAlgorithm.String())
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "x509-certificate//signature-algorithm?")
			}
		},
	},

	"x509-certificate//Public-key-algorithm?": {
		Argsn: 1,
		Doc:   "Returns the public key algorithm of an X.509 certificate as a string.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch cert := arg0.(type) {
			case env.Native:
				if ps.Idx.GetWord(cert.GetKind()) != "x509-certificate" {
					ps.FailureFlag = true
					return MakeArgError(ps, 1, []env.Type{env.NativeType}, "x509-certificate//public-key-algorithm?")
				}
				c := cert.Value.(*x509.Certificate)
				return *env.NewString(c.PublicKeyAlgorithm.String())
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "x509-certificate//public-key-algorithm?")
			}
		},
	},

	"x509-certificate//Key-usage?": {
		Argsn: 1,
		Doc:   "Returns the key usage flags of an X.509 certificate as a block of strings.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch cert := arg0.(type) {
			case env.Native:
				if ps.Idx.GetWord(cert.GetKind()) != "x509-certificate" {
					ps.FailureFlag = true
					return MakeArgError(ps, 1, []env.Type{env.NativeType}, "x509-certificate//key-usage?")
				}
				c := cert.Value.(*x509.Certificate)
				var usages []env.Object
				if c.KeyUsage&x509.KeyUsageDigitalSignature > 0 {
					usages = append(usages, *env.NewString("Digital Signature"))
				}
				if c.KeyUsage&x509.KeyUsageContentCommitment > 0 {
					usages = append(usages, *env.NewString("Content Commitment"))
				}
				if c.KeyUsage&x509.KeyUsageKeyEncipherment > 0 {
					usages = append(usages, *env.NewString("Key Encipherment"))
				}
				if c.KeyUsage&x509.KeyUsageDataEncipherment > 0 {
					usages = append(usages, *env.NewString("Data Encipherment"))
				}
				if c.KeyUsage&x509.KeyUsageKeyAgreement > 0 {
					usages = append(usages, *env.NewString("Key Agreement"))
				}
				if c.KeyUsage&x509.KeyUsageCertSign > 0 {
					usages = append(usages, *env.NewString("Cert Sign"))
				}
				if c.KeyUsage&x509.KeyUsageCRLSign > 0 {
					usages = append(usages, *env.NewString("CRL Sign"))
				}
				if c.KeyUsage&x509.KeyUsageEncipherOnly > 0 {
					usages = append(usages, *env.NewString("Encipher Only"))
				}
				if c.KeyUsage&x509.KeyUsageDecipherOnly > 0 {
					usages = append(usages, *env.NewString("Decipher Only"))
				}
				ser := *env.NewTSeries(usages)
				return *env.NewBlock(ser)
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "x509-certificate//key-usage?")
			}
		},
	},

	"x509-certificate//Extended-key-usage?": {
		Argsn: 1,
		Doc:   "Returns the extended key usage flags of an X.509 certificate as a block of strings.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch cert := arg0.(type) {
			case env.Native:
				if ps.Idx.GetWord(cert.GetKind()) != "x509-certificate" {
					ps.FailureFlag = true
					return MakeArgError(ps, 1, []env.Type{env.NativeType}, "x509-certificate//extended-key-usage?")
				}
				c := cert.Value.(*x509.Certificate)
				usages := make([]env.Object, len(c.ExtKeyUsage))
				for i, extKeyUsage := range c.ExtKeyUsage {
					var usageStr string
					switch extKeyUsage {
					case x509.ExtKeyUsageServerAuth:
						usageStr = "Server Authentication"
					case x509.ExtKeyUsageClientAuth:
						usageStr = "Client Authentication"
					case x509.ExtKeyUsageCodeSigning:
						usageStr = "Code Signing"
					case x509.ExtKeyUsageEmailProtection:
						usageStr = "Email Protection"
					case x509.ExtKeyUsageTimeStamping:
						usageStr = "Time Stamping"
					case x509.ExtKeyUsageOCSPSigning:
						usageStr = "OCSP Signing"
					default:
						usageStr = fmt.Sprintf("Unknown (%d)", int(extKeyUsage))
					}
					usages[i] = *env.NewString(usageStr)
				}
				ser := *env.NewTSeries(usages)
				return *env.NewBlock(ser)
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "x509-certificate//extended-key-usage?")
			}
		},
	},

	"x509-certificate//Dns-names?": {
		Argsn: 1,
		Doc:   "Returns the DNS names from Subject Alternative Names of an X.509 certificate as a block of strings.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch cert := arg0.(type) {
			case env.Native:
				if ps.Idx.GetWord(cert.GetKind()) != "x509-certificate" {
					ps.FailureFlag = true
					return MakeArgError(ps, 1, []env.Type{env.NativeType}, "x509-certificate//dns-names?")
				}
				c := cert.Value.(*x509.Certificate)
				names := make([]env.Object, len(c.DNSNames))
				for i, name := range c.DNSNames {
					names[i] = *env.NewString(name)
				}
				ser := *env.NewTSeries(names)
				return *env.NewBlock(ser)
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "x509-certificate//dns-names?")
			}
		},
	},

	"x509-certificate//Ip-addresses?": {
		Argsn: 1,
		Doc:   "Returns the IP addresses from Subject Alternative Names of an X.509 certificate as a block of strings.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch cert := arg0.(type) {
			case env.Native:
				if ps.Idx.GetWord(cert.GetKind()) != "x509-certificate" {
					ps.FailureFlag = true
					return MakeArgError(ps, 1, []env.Type{env.NativeType}, "x509-certificate//ip-addresses?")
				}
				c := cert.Value.(*x509.Certificate)
				addresses := make([]env.Object, len(c.IPAddresses))
				for i, addr := range c.IPAddresses {
					addresses[i] = *env.NewString(addr.String())
				}
				ser := *env.NewTSeries(addresses)
				return *env.NewBlock(ser)
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "x509-certificate//ip-addresses?")
			}
		},
	},

	"x509-certificate//Email-addresses?": {
		Argsn: 1,
		Doc:   "Returns the email addresses from Subject Alternative Names of an X.509 certificate as a block of strings.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch cert := arg0.(type) {
			case env.Native:
				if ps.Idx.GetWord(cert.GetKind()) != "x509-certificate" {
					ps.FailureFlag = true
					return MakeArgError(ps, 1, []env.Type{env.NativeType}, "x509-certificate//email-addresses?")
				}
				c := cert.Value.(*x509.Certificate)
				emails := make([]env.Object, len(c.EmailAddresses))
				for i, email := range c.EmailAddresses {
					emails[i] = *env.NewString(email)
				}
				ser := *env.NewTSeries(emails)
				return *env.NewBlock(ser)
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "x509-certificate//email-addresses?")
			}
		},
	},

	"x509-certificate//To-pem": {
		Argsn: 1,
		Doc:   "Converts an X.509 certificate to PEM-encoded string format.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch cert := arg0.(type) {
			case env.Native:
				if ps.Idx.GetWord(cert.GetKind()) != "x509-certificate" {
					ps.FailureFlag = true
					return MakeArgError(ps, 1, []env.Type{env.NativeType}, "x509-certificate//to-pem")
				}
				c := cert.Value.(*x509.Certificate)
				pemBlock := &pem.Block{Type: "CERTIFICATE", Bytes: c.Raw}
				pemBytes := pem.EncodeToMemory(pemBlock)
				return *env.NewString(string(pemBytes))
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "x509-certificate//to-pem")
			}
		},
	},

	"private-key//Type?": {
		Argsn: 1,
		Doc:   "Returns the type of a private key as a string.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch key := arg0.(type) {
			case env.Native:
				if ps.Idx.GetWord(key.GetKind()) != "private-key" {
					ps.FailureFlag = true
					return MakeArgError(ps, 1, []env.Type{env.NativeType}, "private-key//type?")
				}
				return *env.NewString(fmt.Sprintf("%T", key.Value))
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "private-key//type?")
			}
		},
	},

	"x509-certificate//To-dict": {
		Argsn: 1,
		Doc:   "Converts an X.509 certificate to a dictionary containing all certificate information for easy display and manipulation.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch cert := arg0.(type) {
			case env.Native:
				if ps.Idx.GetWord(cert.GetKind()) != "x509-certificate" {
					ps.FailureFlag = true
					return MakeArgError(ps, 1, []env.Type{env.NativeType}, "x509-certificate//to-dict")
				}
				c := cert.Value.(*x509.Certificate)

				certDict := make(map[string]interface{})

				certDict["Subject"] = c.Subject.String()
				certDict["Issuer"] = c.Issuer.String()
				certDict["SerialNumber"] = c.SerialNumber.String()
				certDict["NotBefore"] = c.NotBefore.Format("2006-01-02 15:04:05 MST")
				certDict["NotAfter"] = c.NotAfter.Format("2006-01-02 15:04:05 MST")
				certDict["SignatureAlgorithm"] = c.SignatureAlgorithm.String()
				certDict["PublicKeyAlgorithm"] = c.PublicKeyAlgorithm.String()
				certDict["Version"] = int64(c.Version)
				certDict["IsCA"] = c.IsCA

				// Key Usage
				var keyUsages []interface{}
				if c.KeyUsage&x509.KeyUsageDigitalSignature > 0 {
					keyUsages = append(keyUsages, "Digital Signature")
				}
				if c.KeyUsage&x509.KeyUsageContentCommitment > 0 {
					keyUsages = append(keyUsages, "Content Commitment")
				}
				if c.KeyUsage&x509.KeyUsageKeyEncipherment > 0 {
					keyUsages = append(keyUsages, "Key Encipherment")
				}
				if c.KeyUsage&x509.KeyUsageDataEncipherment > 0 {
					keyUsages = append(keyUsages, "Data Encipherment")
				}
				if c.KeyUsage&x509.KeyUsageKeyAgreement > 0 {
					keyUsages = append(keyUsages, "Key Agreement")
				}
				if c.KeyUsage&x509.KeyUsageCertSign > 0 {
					keyUsages = append(keyUsages, "Cert Sign")
				}
				if c.KeyUsage&x509.KeyUsageCRLSign > 0 {
					keyUsages = append(keyUsages, "CRL Sign")
				}
				if c.KeyUsage&x509.KeyUsageEncipherOnly > 0 {
					keyUsages = append(keyUsages, "Encipher Only")
				}
				if c.KeyUsage&x509.KeyUsageDecipherOnly > 0 {
					keyUsages = append(keyUsages, "Decipher Only")
				}
				certDict["KeyUsage"] = keyUsages

				// Extended Key Usage
				var extKeyUsages []interface{}
				for _, extKeyUsage := range c.ExtKeyUsage {
					var usageStr string
					switch extKeyUsage {
					case x509.ExtKeyUsageServerAuth:
						usageStr = "Server Authentication"
					case x509.ExtKeyUsageClientAuth:
						usageStr = "Client Authentication"
					case x509.ExtKeyUsageCodeSigning:
						usageStr = "Code Signing"
					case x509.ExtKeyUsageEmailProtection:
						usageStr = "Email Protection"
					case x509.ExtKeyUsageTimeStamping:
						usageStr = "Time Stamping"
					case x509.ExtKeyUsageOCSPSigning:
						usageStr = "OCSP Signing"
					default:
						usageStr = fmt.Sprintf("Unknown (%d)", int(extKeyUsage))
					}
					extKeyUsages = append(extKeyUsages, usageStr)
				}
				certDict["ExtendedKeyUsage"] = extKeyUsages

				// Subject Alternative Names
				var dnsNames []interface{}
				for _, name := range c.DNSNames {
					dnsNames = append(dnsNames, name)
				}
				certDict["DNSNames"] = dnsNames

				var ipAddresses []interface{}
				for _, addr := range c.IPAddresses {
					ipAddresses = append(ipAddresses, addr.String())
				}
				certDict["IPAddresses"] = ipAddresses

				var emailAddresses []interface{}
				for _, email := range c.EmailAddresses {
					emailAddresses = append(emailAddresses, email)
				}
				certDict["EmailAddresses"] = emailAddresses

				pemBlock := &pem.Block{Type: "CERTIFICATE", Bytes: c.Raw}
				pemBytes := pem.EncodeToMemory(pemBlock)
				certDict["PEM"] = string(pemBytes)

				certDict["IsExpired"] = time.Now().After(c.NotAfter)

				return *env.NewDict(certDict)
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "x509-certificate//to-dict")
			}
		},
	},
}
View Source
var Builtins_echarts = map[string]*env.Builtin{

	"bar-chart": {
		Argsn: 0,
		Doc:   "Creates a new ECharts bar chart instance.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			bar := charts.NewBar()
			return *env.NewNative(ps.Idx, bar, "echarts-bar")
		},
	},

	"bar-data": {
		Argsn: 1,
		Doc:   "Converts a block of numbers into ECharts bar data items.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch blk := arg0.(type) {
			case env.Block:
				items, err := blockToBarData(ps, blk)
				if err != nil {
					return err
				}
				return *env.NewNative(ps.Idx, items, "echarts-bar-data")
			default:
				return MakeArgError(ps, 1, []env.Type{env.BlockType}, "bar-data")
			}
		},
	},

	"title-opts": {
		Argsn: 2,
		Doc:   "Creates ECharts title options with title and subtitle.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			title, ok := arg0.(env.String)
			if !ok {
				return MakeArgError(ps, 1, []env.Type{env.StringType}, "title-opts")
			}
			subtitle, ok := arg1.(env.String)
			if !ok {
				return MakeArgError(ps, 2, []env.Type{env.StringType}, "title-opts")
			}
			titleOpts := opts.Title{
				Title:    title.Value,
				Subtitle: subtitle.Value,
			}
			return *env.NewNative(ps.Idx, titleOpts, "echarts-title-opts")
		},
	},

	"with-title-opts": {
		Argsn: 1,
		Doc:   "Wraps title options into a chart global option.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch nat := arg0.(type) {
			case env.Native:
				titleOpts, ok := nat.Value.(opts.Title)
				if !ok {
					return MakeNativeArgError(ps, 1, []string{"echarts-title-opts"}, "with-title-opts")
				}
				opt := charts.WithTitleOpts(titleOpts)
				return *env.NewNative(ps.Idx, opt, "echarts-global-opts")
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "with-title-opts")
			}
		},
	},

	"echarts-bar//Global-options!": {
		Argsn: 2,
		Doc:   "Sets global options on an ECharts bar chart. Accepts a single option or a block of options.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			barNat, ok := arg0.(env.Native)
			if !ok {
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "echarts-bar//Global-options!")
			}
			bar, ok := barNat.Value.(*charts.Bar)
			if !ok {
				return MakeNativeArgError(ps, 1, []string{"echarts-bar"}, "echarts-bar//Global-options!")
			}

			// Collect options
			var gopts []charts.GlobalOpts
			switch opt := arg1.(type) {
			case env.Native:
				gopt, ok := opt.Value.(charts.GlobalOpts)
				if !ok {
					return MakeNativeArgError(ps, 2, []string{"echarts-global-opts"}, "echarts-bar//Global-options!")
				}
				gopts = append(gopts, gopt)
			case env.Block:
				for i := 0; i < opt.Series.Len(); i++ {
					obj := opt.Series.Get(i)
					nat, ok := obj.(env.Native)
					if !ok {
						return MakeBuiltinError(ps, "block must contain native echarts-global-opts", "echarts-bar//Global-options!")
					}
					gopt, ok := nat.Value.(charts.GlobalOpts)
					if !ok {
						return MakeBuiltinError(ps, "block must contain echarts-global-opts natives", "echarts-bar//Global-options!")
					}
					gopts = append(gopts, gopt)
				}
			default:
				return MakeArgError(ps, 2, []env.Type{env.NativeType, env.BlockType}, "echarts-bar//Global-options!")
			}

			bar.SetGlobalOptions(gopts...)
			return barNat
		},
	},

	"echarts-bar//X-axis!": {
		Argsn: 2,
		Doc:   "Sets the x-axis labels on an ECharts bar chart.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			barNat, ok := arg0.(env.Native)
			if !ok {
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "echarts-bar//X-axis!")
			}
			bar, ok := barNat.Value.(*charts.Bar)
			if !ok {
				return MakeNativeArgError(ps, 1, []string{"echarts-bar"}, "echarts-bar//X-axis!")
			}
			switch blk := arg1.(type) {
			case env.Block:
				labels, err := blockToStringSlice(ps, blk)
				if err != nil {
					return err
				}
				bar.SetXAxis(labels)
				return barNat
			default:
				return MakeArgError(ps, 2, []env.Type{env.BlockType}, "echarts-bar//X-axis!")
			}
		},
	},

	"echarts-bar//Add-series": {
		Argsn: 3,
		Doc:   "Adds a data series to an ECharts bar chart.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			barNat, ok := arg0.(env.Native)
			if !ok {
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "echarts-bar//Add-series")
			}
			bar, ok := barNat.Value.(*charts.Bar)
			if !ok {
				return MakeNativeArgError(ps, 1, []string{"echarts-bar"}, "echarts-bar//Add-series")
			}
			name, ok := arg1.(env.String)
			if !ok {
				return MakeArgError(ps, 2, []env.Type{env.StringType}, "echarts-bar//Add-series")
			}
			dataNat, ok := arg2.(env.Native)
			if !ok {
				return MakeArgError(ps, 3, []env.Type{env.NativeType}, "echarts-bar//Add-series")
			}
			data, ok := dataNat.Value.([]opts.BarData)
			if !ok {
				return MakeNativeArgError(ps, 3, []string{"echarts-bar-data"}, "echarts-bar//Add-series")
			}
			bar.AddSeries(name.Value, data)
			return barNat
		},
	},

	"echarts-bar//Render": {
		Argsn: 2,
		Doc:   "Renders an ECharts bar chart to a writer (file, etc.).",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			barNat, ok := arg0.(env.Native)
			if !ok {
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "echarts-bar//Render")
			}
			bar, ok := barNat.Value.(*charts.Bar)
			if !ok {
				return MakeNativeArgError(ps, 1, []string{"echarts-bar"}, "echarts-bar//Render")
			}
			writerNat, ok := arg1.(env.Native)
			if !ok {
				return MakeArgError(ps, 2, []env.Type{env.NativeType}, "echarts-bar//Render")
			}
			writer, ok := writerNat.Value.(io.Writer)
			if !ok {
				return MakeNativeArgError(ps, 2, []string{"io.Writer (e.g., file)"}, "echarts-bar//Render")
			}
			err := bar.Render(writer)
			if err != nil {
				return MakeBuiltinError(ps, err.Error(), "echarts-bar//Render")
			}
			return barNat
		},
	},

	"line-chart": {
		Argsn: 0,
		Doc:   "Creates a new ECharts line chart instance.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			line := charts.NewLine()
			return *env.NewNative(ps.Idx, line, "echarts-line")
		},
	},

	"line-data": {
		Argsn: 1,
		Doc:   "Converts a block of numbers into ECharts line data items.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch blk := arg0.(type) {
			case env.Block:
				items, err := blockToLineData(ps, blk)
				if err != nil {
					return err
				}
				return *env.NewNative(ps.Idx, items, "echarts-line-data")
			default:
				return MakeArgError(ps, 1, []env.Type{env.BlockType}, "line-data")
			}
		},
	},

	"echarts-line//Global-options!": {
		Argsn: 2,
		Doc:   "Sets global options on an ECharts line chart.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			lineNat, ok := arg0.(env.Native)
			if !ok {
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "echarts-line//Global-options!")
			}
			line, ok := lineNat.Value.(*charts.Line)
			if !ok {
				return MakeNativeArgError(ps, 1, []string{"echarts-line"}, "echarts-line//Global-options!")
			}

			var gopts []charts.GlobalOpts
			switch opt := arg1.(type) {
			case env.Native:
				gopt, ok := opt.Value.(charts.GlobalOpts)
				if !ok {
					return MakeNativeArgError(ps, 2, []string{"echarts-global-opts"}, "echarts-line//Global-options!")
				}
				gopts = append(gopts, gopt)
			case env.Block:
				for i := 0; i < opt.Series.Len(); i++ {
					obj := opt.Series.Get(i)
					nat, ok := obj.(env.Native)
					if !ok {
						return MakeBuiltinError(ps, "block must contain native echarts-global-opts", "echarts-line//Global-options!")
					}
					gopt, ok := nat.Value.(charts.GlobalOpts)
					if !ok {
						return MakeBuiltinError(ps, "block must contain echarts-global-opts natives", "echarts-line//Global-options!")
					}
					gopts = append(gopts, gopt)
				}
			default:
				return MakeArgError(ps, 2, []env.Type{env.NativeType, env.BlockType}, "echarts-line//Global-options!")
			}

			line.SetGlobalOptions(gopts...)
			return lineNat
		},
	},

	"echarts-line//X-axis!": {
		Argsn: 2,
		Doc:   "Sets the x-axis labels on an ECharts line chart.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			lineNat, ok := arg0.(env.Native)
			if !ok {
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "echarts-line//X-axis!")
			}
			line, ok := lineNat.Value.(*charts.Line)
			if !ok {
				return MakeNativeArgError(ps, 1, []string{"echarts-line"}, "echarts-line//X-axis!")
			}
			switch blk := arg1.(type) {
			case env.Block:
				labels, err := blockToStringSlice(ps, blk)
				if err != nil {
					return err
				}
				line.SetXAxis(labels)
				return lineNat
			default:
				return MakeArgError(ps, 2, []env.Type{env.BlockType}, "echarts-line//X-axis!")
			}
		},
	},

	"echarts-line//Add-series": {
		Argsn: 3,
		Doc:   "Adds a data series to an ECharts line chart.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			lineNat, ok := arg0.(env.Native)
			if !ok {
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "echarts-line//Add-series")
			}
			line, ok := lineNat.Value.(*charts.Line)
			if !ok {
				return MakeNativeArgError(ps, 1, []string{"echarts-line"}, "echarts-line//Add-series")
			}
			name, ok := arg1.(env.String)
			if !ok {
				return MakeArgError(ps, 2, []env.Type{env.StringType}, "echarts-line//Add-series")
			}
			dataNat, ok := arg2.(env.Native)
			if !ok {
				return MakeArgError(ps, 3, []env.Type{env.NativeType}, "echarts-line//Add-series")
			}
			data, ok := dataNat.Value.([]opts.LineData)
			if !ok {
				return MakeNativeArgError(ps, 3, []string{"echarts-line-data"}, "echarts-line//Add-series")
			}
			line.AddSeries(name.Value, data)
			return lineNat
		},
	},

	"echarts-line//Render": {
		Argsn: 2,
		Doc:   "Renders an ECharts line chart to a writer (file, etc.).",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			lineNat, ok := arg0.(env.Native)
			if !ok {
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "echarts-line//Render")
			}
			line, ok := lineNat.Value.(*charts.Line)
			if !ok {
				return MakeNativeArgError(ps, 1, []string{"echarts-line"}, "echarts-line//Render")
			}
			writerNat, ok := arg1.(env.Native)
			if !ok {
				return MakeArgError(ps, 2, []env.Type{env.NativeType}, "echarts-line//Render")
			}
			writer, ok := writerNat.Value.(io.Writer)
			if !ok {
				return MakeNativeArgError(ps, 2, []string{"io.Writer"}, "echarts-line//Render")
			}
			err := line.Render(writer)
			if err != nil {
				return MakeBuiltinError(ps, err.Error(), "echarts-line//Render")
			}
			return lineNat
		},
	},

	"pie-chart": {
		Argsn: 0,
		Doc:   "Creates a new ECharts pie chart instance.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			pie := charts.NewPie()
			return *env.NewNative(ps.Idx, pie, "echarts-pie")
		},
	},

	"pie-data": {
		Argsn: 1,
		Doc:   "Converts a block of name-value pairs into ECharts pie data items.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch blk := arg0.(type) {
			case env.Block:
				items, err := blockToPieData(ps, blk)
				if err != nil {
					return err
				}
				return *env.NewNative(ps.Idx, items, "echarts-pie-data")
			default:
				return MakeArgError(ps, 1, []env.Type{env.BlockType}, "pie-data")
			}
		},
	},

	"echarts-pie//Global-options!": {
		Argsn: 2,
		Doc:   "Sets global options on an ECharts pie chart.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			pieNat, ok := arg0.(env.Native)
			if !ok {
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "echarts-pie//Global-options!")
			}
			pie, ok := pieNat.Value.(*charts.Pie)
			if !ok {
				return MakeNativeArgError(ps, 1, []string{"echarts-pie"}, "echarts-pie//Global-options!")
			}

			var gopts []charts.GlobalOpts
			switch opt := arg1.(type) {
			case env.Native:
				gopt, ok := opt.Value.(charts.GlobalOpts)
				if !ok {
					return MakeNativeArgError(ps, 2, []string{"echarts-global-opts"}, "echarts-pie//Global-options!")
				}
				gopts = append(gopts, gopt)
			case env.Block:
				for i := 0; i < opt.Series.Len(); i++ {
					obj := opt.Series.Get(i)
					nat, ok := obj.(env.Native)
					if !ok {
						return MakeBuiltinError(ps, "block must contain native echarts-global-opts", "echarts-pie//Global-options!")
					}
					gopt, ok := nat.Value.(charts.GlobalOpts)
					if !ok {
						return MakeBuiltinError(ps, "block must contain echarts-global-opts natives", "echarts-pie//Global-options!")
					}
					gopts = append(gopts, gopt)
				}
			default:
				return MakeArgError(ps, 2, []env.Type{env.NativeType, env.BlockType}, "echarts-pie//Global-options!")
			}

			pie.SetGlobalOptions(gopts...)
			return pieNat
		},
	},

	"echarts-pie//Add-series": {
		Argsn: 2,
		Doc:   "Adds a data series to an ECharts pie chart.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			pieNat, ok := arg0.(env.Native)
			if !ok {
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "echarts-pie//Add-series")
			}
			pie, ok := pieNat.Value.(*charts.Pie)
			if !ok {
				return MakeNativeArgError(ps, 1, []string{"echarts-pie"}, "echarts-pie//Add-series")
			}
			dataNat, ok := arg1.(env.Native)
			if !ok {
				return MakeArgError(ps, 2, []env.Type{env.NativeType}, "echarts-pie//Add-series")
			}
			data, ok := dataNat.Value.([]opts.PieData)
			if !ok {
				return MakeNativeArgError(ps, 2, []string{"echarts-pie-data"}, "echarts-pie//Add-series")
			}
			pie.AddSeries("pie", data)
			return pieNat
		},
	},

	"echarts-pie//Render": {
		Argsn: 2,
		Doc:   "Renders an ECharts pie chart to a writer (file, etc.).",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			pieNat, ok := arg0.(env.Native)
			if !ok {
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "echarts-pie//Render")
			}
			pie, ok := pieNat.Value.(*charts.Pie)
			if !ok {
				return MakeNativeArgError(ps, 1, []string{"echarts-pie"}, "echarts-pie//Render")
			}
			writerNat, ok := arg1.(env.Native)
			if !ok {
				return MakeArgError(ps, 2, []env.Type{env.NativeType}, "echarts-pie//Render")
			}
			writer, ok := writerNat.Value.(io.Writer)
			if !ok {
				return MakeNativeArgError(ps, 2, []string{"io.Writer"}, "echarts-pie//Render")
			}
			err := pie.Render(writer)
			if err != nil {
				return MakeBuiltinError(ps, err.Error(), "echarts-pie//Render")
			}
			return pieNat
		},
	},

	"scatter-chart": {
		Argsn: 0,
		Doc:   "Creates a new ECharts scatter chart instance.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			scatter := charts.NewScatter()
			return *env.NewNative(ps.Idx, scatter, "echarts-scatter")
		},
	},

	"scatter-data": {
		Argsn: 1,
		Doc:   "Converts a block of [x y] pairs into ECharts scatter data items.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch blk := arg0.(type) {
			case env.Block:
				items, err := blockToScatterData(ps, blk)
				if err != nil {
					return err
				}
				return *env.NewNative(ps.Idx, items, "echarts-scatter-data")
			default:
				return MakeArgError(ps, 1, []env.Type{env.BlockType}, "scatter-data")
			}
		},
	},

	"echarts-scatter//Global-options!": {
		Argsn: 2,
		Doc:   "Sets global options on an ECharts scatter chart.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			scatterNat, ok := arg0.(env.Native)
			if !ok {
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "echarts-scatter//Global-options!")
			}
			scatter, ok := scatterNat.Value.(*charts.Scatter)
			if !ok {
				return MakeNativeArgError(ps, 1, []string{"echarts-scatter"}, "echarts-scatter//Global-options!")
			}

			var gopts []charts.GlobalOpts
			switch opt := arg1.(type) {
			case env.Native:
				gopt, ok := opt.Value.(charts.GlobalOpts)
				if !ok {
					return MakeNativeArgError(ps, 2, []string{"echarts-global-opts"}, "echarts-scatter//Global-options!")
				}
				gopts = append(gopts, gopt)
			case env.Block:
				for i := 0; i < opt.Series.Len(); i++ {
					obj := opt.Series.Get(i)
					nat, ok := obj.(env.Native)
					if !ok {
						return MakeBuiltinError(ps, "block must contain native echarts-global-opts", "echarts-scatter//Global-options!")
					}
					gopt, ok := nat.Value.(charts.GlobalOpts)
					if !ok {
						return MakeBuiltinError(ps, "block must contain echarts-global-opts natives", "echarts-scatter//Global-options!")
					}
					gopts = append(gopts, gopt)
				}
			default:
				return MakeArgError(ps, 2, []env.Type{env.NativeType, env.BlockType}, "echarts-scatter//Global-options!")
			}

			scatter.SetGlobalOptions(gopts...)
			return scatterNat
		},
	},

	"echarts-scatter//X-axis!": {
		Argsn: 2,
		Doc:   "Sets the x-axis labels on an ECharts scatter chart.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			scatterNat, ok := arg0.(env.Native)
			if !ok {
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "echarts-scatter//X-axis!")
			}
			scatter, ok := scatterNat.Value.(*charts.Scatter)
			if !ok {
				return MakeNativeArgError(ps, 1, []string{"echarts-scatter"}, "echarts-scatter//X-axis!")
			}
			switch blk := arg1.(type) {
			case env.Block:
				labels, err := blockToStringSlice(ps, blk)
				if err != nil {
					return err
				}
				scatter.SetXAxis(labels)
				return scatterNat
			default:
				return MakeArgError(ps, 2, []env.Type{env.BlockType}, "echarts-scatter//X-axis!")
			}
		},
	},

	"echarts-scatter//Add-series": {
		Argsn: 3,
		Doc:   "Adds a data series to an ECharts scatter chart.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			scatterNat, ok := arg0.(env.Native)
			if !ok {
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "echarts-scatter//Add-series")
			}
			scatter, ok := scatterNat.Value.(*charts.Scatter)
			if !ok {
				return MakeNativeArgError(ps, 1, []string{"echarts-scatter"}, "echarts-scatter//Add-series")
			}
			name, ok := arg1.(env.String)
			if !ok {
				return MakeArgError(ps, 2, []env.Type{env.StringType}, "echarts-scatter//Add-series")
			}
			dataNat, ok := arg2.(env.Native)
			if !ok {
				return MakeArgError(ps, 3, []env.Type{env.NativeType}, "echarts-scatter//Add-series")
			}
			data, ok := dataNat.Value.([]opts.ScatterData)
			if !ok {
				return MakeNativeArgError(ps, 3, []string{"echarts-scatter-data"}, "echarts-scatter//Add-series")
			}
			scatter.AddSeries(name.Value, data)
			return scatterNat
		},
	},

	"echarts-scatter//Render": {
		Argsn: 2,
		Doc:   "Renders an ECharts scatter chart to a writer (file, etc.).",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			scatterNat, ok := arg0.(env.Native)
			if !ok {
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "echarts-scatter//Render")
			}
			scatter, ok := scatterNat.Value.(*charts.Scatter)
			if !ok {
				return MakeNativeArgError(ps, 1, []string{"echarts-scatter"}, "echarts-scatter//Render")
			}
			writerNat, ok := arg1.(env.Native)
			if !ok {
				return MakeArgError(ps, 2, []env.Type{env.NativeType}, "echarts-scatter//Render")
			}
			writer, ok := writerNat.Value.(io.Writer)
			if !ok {
				return MakeNativeArgError(ps, 2, []string{"io.Writer"}, "echarts-scatter//Render")
			}
			err := scatter.Render(writer)
			if err != nil {
				return MakeBuiltinError(ps, err.Error(), "echarts-scatter//Render")
			}
			return scatterNat
		},
	},

	"legend-opts": {
		Argsn: 0,
		Doc:   "Creates ECharts legend options.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			legendOpts := opts.Legend{}
			return *env.NewNative(ps.Idx, legendOpts, "echarts-legend-opts")
		},
	},

	"with-legend-opts": {
		Argsn: 1,
		Doc:   "Wraps legend options into a chart global option.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch nat := arg0.(type) {
			case env.Native:
				legendOpts, ok := nat.Value.(opts.Legend)
				if !ok {
					return MakeNativeArgError(ps, 1, []string{"echarts-legend-opts"}, "with-legend-opts")
				}
				opt := charts.WithLegendOpts(legendOpts)
				return *env.NewNative(ps.Idx, opt, "echarts-global-opts")
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "with-legend-opts")
			}
		},
	},

	"tooltip-opts": {
		Argsn: 0,
		Doc:   "Creates ECharts tooltip options.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			tooltipOpts := opts.Tooltip{}
			return *env.NewNative(ps.Idx, tooltipOpts, "echarts-tooltip-opts")
		},
	},

	"with-tooltip-opts": {
		Argsn: 1,
		Doc:   "Wraps tooltip options into a chart global option.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch nat := arg0.(type) {
			case env.Native:
				tooltipOpts, ok := nat.Value.(opts.Tooltip)
				if !ok {
					return MakeNativeArgError(ps, 1, []string{"echarts-tooltip-opts"}, "with-tooltip-opts")
				}
				opt := charts.WithTooltipOpts(tooltipOpts)
				return *env.NewNative(ps.Idx, opt, "echarts-global-opts")
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "with-tooltip-opts")
			}
		},
	},
}
View Source
var Builtins_email = map[string]*env.Builtin{

	"email-message": {
		Argsn: 0,
		Doc:   "Creates a new empty email message object that can be configured with headers, body, and attachments.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return __newMessage(ps, arg0, arg1, arg2, arg3, arg4)
		},
	},

	"gomail-message//Set-header": {
		Argsn: 3,
		Doc:   "Sets a standard email header field such as Subject, To, From, Cc, or Bcc with the specified value.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return __setHeader(ps, arg0, arg1, arg2, arg3, arg4)
		},
	},

	"gomail-message//Set-address-header": {
		Argsn: 4,
		Doc:   "Sets an email address header with both email address and display name, commonly used for From, To, Cc, and Bcc fields.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return __setAddressHeader(ps, arg0, arg1, arg2, arg3, arg4)
		},
	},

	"gomail-message//Set-body": {
		Argsn: 3,
		Doc:   "Sets the main body content of the email with the specified MIME content type, supporting plain text and HTML formats.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return __setBody(ps, arg0, arg1, arg2, arg3, arg4)
		},
	},

	"gomail-message//Attach": {
		Argsn: 2,
		Doc:   "Attaches a file to the email message using a file URI, making the file available as an email attachment.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return __attach(ps, arg0, arg1, arg2, arg3, arg4)
		},
	},

	"gomail-message//Add-alternative": {
		Argsn: 3,
		Doc:   "Adds alternative content to the email (e.g., HTML version alongside plain text), allowing email clients to choose their preferred format.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return __addAlternative(ps, arg0, arg1, arg2, arg3, arg4)
		},
	},

	"new-email-dialer": {
		Argsn: 4,
		Doc:   "Creates a new SMTP dialer configured with server details and authentication credentials for sending emails.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return __newDialer(ps, arg0, arg1, arg2, arg3, arg4)
		},
	},

	"gomail-dialer//Dial-and-send": {
		Argsn: 2,
		Doc:   "Connects to the SMTP server and sends the specified email message, handling authentication and delivery.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return __dialAndSend(ps, arg0, arg1, arg2, arg3, arg4)
		},
	},
}
View Source
var Builtins_error_creation = ErrorCreationBuiltins

Export the error handling builtins for registration

View Source
var Builtins_error_handling = ErrorHandlingBuiltins
View Source
var Builtins_error_inspection = ErrorInspectionBuiltins
View Source
var Builtins_error_utils = map[string]*env.Builtin{

	"is-error": {
		AcceptFailure: true,
		Argsn:         1,
		Doc:           "Returns true if the value is an error, false otherwise.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			ps.FailureFlag = false
			switch arg0.(type) {
			case env.Error, *env.Error:
				return *env.NewBoolean(true)
			}
			return *env.NewBoolean(false)
		},
	},

	"error-kind?": {
		AcceptFailure: true,
		Argsn:         1,
		Doc:           "Returns the kind of an error, or void if not an error.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			ps.FailureFlag = false
			switch err := arg0.(type) {
			case env.Error:
				return *env.NewWord(err.Kind.Index)
			case *env.Error:
				return *env.NewWord(err.Kind.Index)
			}
			return *env.NewVoid()
		},
	},

	"is-error-of-kind": {
		AcceptFailure: true,
		Argsn:         2,
		Doc:           "Returns true if the value is an error of the specified kind, false otherwise.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			ps.FailureFlag = false

			// Get the kind to check
			var kindIndex int
			switch kind := arg1.(type) {
			case env.Word:
				kindIndex = kind.Index
			case env.Tagword:
				kindIndex = kind.Index
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 2, []env.Type{env.WordType, env.TagwordType}, "error-of-kind?")
			}

			switch err := arg0.(type) {
			case env.Error:
				return *env.NewBoolean(err.Kind.Index == kindIndex)
			case *env.Error:
				return *env.NewBoolean(err.Kind.Index == kindIndex)
			}

			return *env.NewBoolean(false)
		},
	},

	"try-all": {
		Argsn: 1,
		Doc:   "Executes a block and returns a result tuple [success, result], where success is true if no error occurred.",
		Pure:  true,
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch bloc := arg0.(type) {
			case env.Block:

				oldSer := ps.Ser
				oldFailureFlag := ps.FailureFlag
				oldErrorFlag := ps.ErrorFlag

				ps.Ser = bloc.Series
				EvalBlock(ps)

				result := ps.Res
				success := !ps.FailureFlag && !ps.ErrorFlag

				ps.Ser = oldSer
				ps.FailureFlag = oldFailureFlag
				ps.ErrorFlag = oldErrorFlag

				return *env.NewBlock(*env.NewTSeries([]env.Object{
					*env.NewBoolean(success),
					result,
				}))
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.BlockType}, "try-all")
			}
		},
	},

	"finally": {
		Argsn: 2,
		Doc:   "Executes a block and ensures another block is executed afterward, regardless of errors.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch mainBlock := arg0.(type) {
			case env.Block:
				switch finallyBlock := arg1.(type) {
				case env.Block:

					oldSer := ps.Ser

					ps.Ser = mainBlock.Series
					EvalBlock(ps)
					if ps.ErrorFlag {
						ps.Ser = oldSer
						return ps.Res
					}

					result := ps.Res
					hasFailure := ps.FailureFlag
					hasError := ps.ErrorFlag

					ps.Ser = finallyBlock.Series
					ps.FailureFlag = false
					ps.ErrorFlag = false
					EvalBlock(ps)
					if ps.ErrorFlag {
						ps.Ser = oldSer
						return ps.Res
					}

					ps.Res = result
					ps.FailureFlag = hasFailure
					ps.ErrorFlag = hasError

					ps.Ser = oldSer

					return ps.Res
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 2, []env.Type{env.BlockType}, "finally")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.BlockType}, "finally")
			}
		},
	},
}
View Source
var Builtins_eyr = map[string]*env.Builtin{

	"eyr": {
		Argsn: 1,
		Doc:   "Evaluates Rye block as Eyr (postfix) stack based code.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch bloc := arg0.(type) {
			case env.Block:
				ser := ps.Ser
				ps.Ser = bloc.Series
				dialect := ps.Dialect
				ps.Dialect = env.EyrDialect

				if ps.Stack == nil {
					ps.Stack = env.NewEyrStack()
				} else {
					ps.ResetStack()
				}
				Eyr_EvalBlock(ps, false)
				ps.Dialect = dialect
				ps.Ser = ser
				return ps.Res
			default:
				return MakeArgError(ps, 1, []env.Type{env.BlockType}, "eyr")
			}
		},
	},

	"rye0": {
		Argsn: 1,
		Doc:   "Evaluates Rye block as Rye0 dialect.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch bloc := arg0.(type) {
			case env.Block:
				ser := ps.Ser
				ps.Ser = bloc.Series
				dialect := ps.Dialect
				ps.Dialect = env.Rye0Dialect
				Rye0_EvalBlockInj(ps, nil, false)
				ps.Dialect = dialect
				ps.Ser = ser
				return ps.Res
			default:
				return MakeArgError(ps, 1, []env.Type{env.BlockType}, "rye0")
			}
		},
	},

	"rye00": {
		Argsn: 1,
		Doc:   "Evaluates Rye block as Rye00 dialect (builtins and integers only).",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch bloc := arg0.(type) {
			case env.Block:
				ser := ps.Ser
				ps.Ser = bloc.Series
				dialect := ps.Dialect
				ps.Dialect = env.Rye00Dialect
				Rye00_EvalBlockInj(ps, nil, false)
				ps.Dialect = dialect
				ps.Ser = ser
				return ps.Res
			default:
				return MakeArgError(ps, 1, []env.Type{env.BlockType}, "rye00")
			}
		},
	},

	"eyr\\clear": {
		Argsn: 0,
		Doc:   "Clears the EYR stack.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			ps.ResetStack()
			return env.NewBoolean(false)
		},
	},

	"eyr\\full": {
		Argsn: 1,
		Doc:   "Evaluates Rye block as Eyr (postfix) stack based code.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch bloc := arg0.(type) {
			case env.Block:
				ser := ps.Ser
				ps.Ser = bloc.Series
				dialect := ps.Dialect
				ps.Dialect = env.EyrDialect
				Eyr_EvalBlock(ps, true)
				ps.Dialect = dialect
				ps.Ser = ser
				return ps.Res
			default:
				return MakeArgError(ps, 1, []env.Type{env.BlockType}, "eyr\\full")
			}
		},
	},

	"eyr\\loop": {
		Argsn: 2,
		Doc:   "Evaluates Rye block in loop as Eyr code (postfix stack based) N times.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch cond := arg0.(type) {
			case env.Integer:
				switch bloc := arg1.(type) {
				case env.Block:
					ps.Dialect = env.EyrDialect
					ser := ps.Ser
					ps.Ser = bloc.Series
					for i := 0; int64(i) < cond.Value; i++ {
						ps = Eyr_EvalBlock(ps, false)
						ps.Ser.Reset()
					}
					ps.Ser = ser
					return ps.Res
				default:
					return MakeArgError(ps, 2, []env.Type{env.BlockType}, "eyr\\loop")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.IntegerType}, "eyr\\loop")
			}
		},
	},

	"to-eyr": {
		Argsn: 1,
		Doc:   "Evaluates Rye block as Eyr (postfix) stack based code.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch bloc := arg0.(type) {
			case env.Block:
				eBlock := env.NewBlock(*env.NewTSeries(make([]env.Object, 0)))
				CompileRyeToEyr(&bloc, ps, eBlock)
				return *eBlock
			default:
				return MakeArgError(ps, 1, []env.Type{env.BlockType}, "eyr")
			}
		},
	},
}
View Source
var Builtins_gin = map[string]*env.Builtin{

	"router": {
		Argsn: 0,
		Doc:   "Create new Gin router with default middleware.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			router := gin.Default()
			return *env.NewNative(ps.Idx, router, "Gin-router")
		},
	},

	"router\\new": {
		Argsn: 0,
		Doc:   "Create new Gin router without default middleware.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			router := gin.New()
			return *env.NewNative(ps.Idx, router, "Gin-router")
		},
	},

	"Gin-router//Use": {
		Argsn: 2,
		Doc:   "Add middleware function to Gin router.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch router := arg0.(type) {
			case env.Native:
				switch middleware := arg1.(type) {
				case env.Function:
					router.Value.(*gin.Engine).Use(func(c *gin.Context) {
						ps.FailureFlag = false
						ps.ErrorFlag = false
						ps.ReturnFlag = false
						psTemp := env.ProgramState{}
						err := copier.Copy(&psTemp, &ps)
						if err != nil {
							c.String(http.StatusInternalServerError, "Middleware error")
							return
						}
						CallFunction_CollectArgs(middleware, &psTemp, *env.NewNative(ps.Idx, c, "Gin-context"), false, nil)
						if psTemp.FailureFlag || psTemp.ErrorFlag {
							c.Abort()
							return
						}
					})
					return arg0
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 2, []env.Type{env.FunctionType}, "Gin-router//Use")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Gin-router//Use")
			}
		},
	},

	"Gin-group//Use": {
		Argsn: 2,
		Doc:   "Add middleware function to Gin route group.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch group := arg0.(type) {
			case env.Native:
				switch middleware := arg1.(type) {
				case env.Function:
					group.Value.(*gin.RouterGroup).Use(func(c *gin.Context) {
						ps.FailureFlag = false
						ps.ErrorFlag = false
						ps.ReturnFlag = false
						psTemp := env.ProgramState{}
						err := copier.Copy(&psTemp, &ps)
						if err != nil {
							c.String(http.StatusInternalServerError, "Middleware error")
							return
						}
						CallFunction_CollectArgs(middleware, &psTemp, *env.NewNative(ps.Idx, c, "Gin-context"), false, nil)
						if psTemp.FailureFlag || psTemp.ErrorFlag {
							c.Abort()
							return
						}
					})
					return arg0
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 2, []env.Type{env.FunctionType}, "Gin-group//Use")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Gin-group//Use")
			}
		},
	},

	"Gin-context//Next": {
		Argsn: 1,
		Doc:   "Continue to next middleware/handler in chain.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch ctx := arg0.(type) {
			case env.Native:
				ctx.Value.(*gin.Context).Next()
				return arg0
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Gin-context//Next")
			}
		},
	},

	"Gin-context//Abort": {
		Argsn: 1,
		Doc:   "Abort the middleware chain and prevent further handlers from executing.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch ctx := arg0.(type) {
			case env.Native:
				ctx.Value.(*gin.Context).Abort()
				return arg0
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Gin-context//Abort")
			}
		},
	},

	"Gin-context//AbortWithStatus": {
		Argsn: 2,
		Doc:   "Abort with HTTP status code.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch ctx := arg0.(type) {
			case env.Native:
				switch code := arg1.(type) {
				case env.Integer:
					ctx.Value.(*gin.Context).AbortWithStatus(int(code.Value))
					return arg0
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 2, []env.Type{env.IntegerType}, "Gin-context//AbortWithStatus")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Gin-context//AbortWithStatus")
			}
		},
	},

	"Gin-context//IsAborted": {
		Argsn: 1,
		Doc:   "Check if context has been aborted.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch ctx := arg0.(type) {
			case env.Native:
				aborted := ctx.Value.(*gin.Context).IsAborted()
				if aborted {
					return *env.NewInteger(1)
				}
				return *env.NewInteger(0)
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Gin-context//IsAborted")
			}
		},
	},

	"middleware\\CORS": {
		Argsn: 0,
		Doc:   "Create basic CORS middleware function.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {

			return *env.NewString("{ ctx | ctx//Header ctx \"Access-Control-Allow-Origin\" \"*\" ctx//Header ctx \"Access-Control-Allow-Methods\" \"GET, POST, PUT, DELETE, OPTIONS\" ctx//Header ctx \"Access-Control-Allow-Headers\" \"Content-Type, Authorization\" ctx//Next ctx }")
		},
	},

	"middleware\\Logger": {
		Argsn: 0,
		Doc:   "Create basic logging middleware function.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {

			return *env.NewString("{ ctx | print [ \"Request from:\" ctx//ClientIP ctx ] ctx//Next ctx }")
		},
	},

	"middleware\\Auth": {
		Argsn: 1,
		Doc:   "Create authentication middleware with secret key.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch secret := arg0.(type) {
			case env.String:

				authCode := "{ ctx | auth-header: ctx//GetHeader ctx \"Authorization\" either [ equals? auth-header \"Bearer " + secret.Value + "\" ] [ ctx//Next ctx ] [ ctx//AbortWithStatus ctx status\\unauthorized ] }"
				return *env.NewString(authCode)
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.StringType}, "middleware\\Auth")
			}
		},
	},

	"Gin-router//GET": {
		Argsn: 3,
		Doc:   "Add GET route handler to Gin router.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch router := arg0.(type) {
			case env.Native:
				switch path := arg1.(type) {
				case env.String:
					switch handler := arg2.(type) {
					case env.Function:
						router.Value.(*gin.Engine).GET(path.Value, func(c *gin.Context) {
							ps.FailureFlag = false
							ps.ErrorFlag = false
							ps.ReturnFlag = false
							psTemp := env.ProgramState{}
							err := copier.Copy(&psTemp, &ps)
							if err != nil {
								c.String(http.StatusInternalServerError, "Internal error")
								return
							}
							CallFunction_CollectArgs(handler, &psTemp, *env.NewNative(ps.Idx, c, "Gin-context"), false, nil)

							if psTemp.FailureFlag {
								c.String(http.StatusInternalServerError, psTemp.Res.Inspect(*ps.Idx))
								return
							}
							if psTemp.ErrorFlag {
								c.String(http.StatusInternalServerError, psTemp.Res.Inspect(*ps.Idx))
								return
							}
						})
						return arg0
					default:
						ps.FailureFlag = true
						return MakeArgError(ps, 3, []env.Type{env.FunctionType}, "Gin-router//GET")
					}
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 2, []env.Type{env.StringType}, "Gin-router//GET")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Gin-router//GET")
			}
		},
	},

	"Gin-router//POST": {
		Argsn: 3,
		Doc:   "Add POST route handler to Gin router.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch router := arg0.(type) {
			case env.Native:
				switch path := arg1.(type) {
				case env.String:
					switch handler := arg2.(type) {
					case env.Function:
						router.Value.(*gin.Engine).POST(path.Value, func(c *gin.Context) {
							ps.FailureFlag = false
							ps.ErrorFlag = false
							ps.ReturnFlag = false
							psTemp := env.ProgramState{}
							err := copier.Copy(&psTemp, &ps)
							if err != nil {
								c.String(http.StatusInternalServerError, "Internal error")
								return
							}
							CallFunction_CollectArgs(handler, &psTemp, *env.NewNative(ps.Idx, c, "Gin-context"), false, nil)
						})
						return arg0
					default:
						ps.FailureFlag = true
						return MakeArgError(ps, 3, []env.Type{env.FunctionType}, "Gin-router//POST")
					}
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 2, []env.Type{env.StringType}, "Gin-router//POST")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Gin-router//POST")
			}
		},
	},

	"Gin-router//PUT": {
		Argsn: 3,
		Doc:   "Add PUT route handler to Gin router.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch router := arg0.(type) {
			case env.Native:
				switch path := arg1.(type) {
				case env.String:
					switch handler := arg2.(type) {
					case env.Function:
						router.Value.(*gin.Engine).PUT(path.Value, func(c *gin.Context) {
							ps.FailureFlag = false
							ps.ErrorFlag = false
							ps.ReturnFlag = false
							psTemp := env.ProgramState{}
							err := copier.Copy(&psTemp, &ps)
							if err != nil {
								c.String(http.StatusInternalServerError, "Internal error")
								return
							}
							CallFunction_CollectArgs(handler, &psTemp, *env.NewNative(ps.Idx, c, "Gin-context"), false, nil)
						})
						return arg0
					default:
						ps.FailureFlag = true
						return MakeArgError(ps, 3, []env.Type{env.FunctionType}, "Gin-router//PUT")
					}
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 2, []env.Type{env.StringType}, "Gin-router//PUT")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Gin-router//PUT")
			}
		},
	},

	"Gin-router//DELETE": {
		Argsn: 3,
		Doc:   "Add DELETE route handler to Gin router.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch router := arg0.(type) {
			case env.Native:
				switch path := arg1.(type) {
				case env.String:
					switch handler := arg2.(type) {
					case env.Function:
						router.Value.(*gin.Engine).DELETE(path.Value, func(c *gin.Context) {
							ps.FailureFlag = false
							ps.ErrorFlag = false
							ps.ReturnFlag = false
							psTemp := env.ProgramState{}
							err := copier.Copy(&psTemp, &ps)
							if err != nil {
								c.String(http.StatusInternalServerError, "Internal error")
								return
							}
							CallFunction_CollectArgs(handler, &psTemp, *env.NewNative(ps.Idx, c, "Gin-context"), false, nil)
						})
						return arg0
					default:
						ps.FailureFlag = true
						return MakeArgError(ps, 3, []env.Type{env.FunctionType}, "Gin-router//DELETE")
					}
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 2, []env.Type{env.StringType}, "Gin-router//DELETE")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Gin-router//DELETE")
			}
		},
	},

	"Gin-router//Run": {
		Argsn: 2,
		Doc:   "Start the Gin server listening on specified address.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch router := arg0.(type) {
			case env.Native:
				switch addr := arg1.(type) {
				case env.String:
					err := router.Value.(*gin.Engine).Run(addr.Value)
					if err != nil {
						ps.FailureFlag = true
						return MakeBuiltinError(ps, err.Error(), "Gin-router//Run")
					}
					return arg0
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 2, []env.Type{env.StringType}, "Gin-router//Run")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Gin-router//Run")
			}
		},
	},

	"Gin-router//LoadHTMLGlob": {
		Argsn: 2,
		Doc:   "Load HTML templates from a glob pattern.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch router := arg0.(type) {
			case env.Native:
				switch pattern := arg1.(type) {
				case env.String:
					router.Value.(*gin.Engine).LoadHTMLGlob(pattern.Value)
					return arg0
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 2, []env.Type{env.StringType}, "Gin-router//LoadHTMLGlob")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Gin-router//LoadHTMLGlob")
			}
		},
	},

	"Gin-router//Group": {
		Argsn: 2,
		Doc:   "Create route group with prefix.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch router := arg0.(type) {
			case env.Native:
				switch prefix := arg1.(type) {
				case env.String:
					group := router.Value.(*gin.Engine).Group(prefix.Value)
					return *env.NewNative(ps.Idx, group, "Gin-group")
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 2, []env.Type{env.StringType}, "Gin-router//Group")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Gin-router//Group")
			}
		},
	},

	"Gin-group//GET": {
		Argsn: 3,
		Doc:   "Add GET route handler to Gin route group.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch group := arg0.(type) {
			case env.Native:
				switch path := arg1.(type) {
				case env.String:
					switch handler := arg2.(type) {
					case env.Function:
						group.Value.(*gin.RouterGroup).GET(path.Value, func(c *gin.Context) {
							ps.FailureFlag = false
							ps.ErrorFlag = false
							ps.ReturnFlag = false
							psTemp := env.ProgramState{}
							err := copier.Copy(&psTemp, &ps)
							if err != nil {
								c.String(http.StatusInternalServerError, "Internal error")
								return
							}
							CallFunction_CollectArgs(handler, &psTemp, *env.NewNative(ps.Idx, c, "Gin-context"), false, nil)
						})
						return arg0
					default:
						ps.FailureFlag = true
						return MakeArgError(ps, 3, []env.Type{env.FunctionType}, "Gin-group//GET")
					}
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 2, []env.Type{env.StringType}, "Gin-group//GET")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Gin-group//GET")
			}
		},
	},

	"Gin-group//POST": {
		Argsn: 3,
		Doc:   "Add POST route handler to Gin route group.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch group := arg0.(type) {
			case env.Native:
				switch path := arg1.(type) {
				case env.String:
					switch handler := arg2.(type) {
					case env.Function:
						group.Value.(*gin.RouterGroup).POST(path.Value, func(c *gin.Context) {
							ps.FailureFlag = false
							ps.ErrorFlag = false
							ps.ReturnFlag = false
							psTemp := env.ProgramState{}
							err := copier.Copy(&psTemp, &ps)
							if err != nil {
								c.String(http.StatusInternalServerError, "Internal error")
								return
							}
							CallFunction_CollectArgs(handler, &psTemp, *env.NewNative(ps.Idx, c, "Gin-context"), false, nil)
						})
						return arg0
					default:
						ps.FailureFlag = true
						return MakeArgError(ps, 3, []env.Type{env.FunctionType}, "Gin-group//POST")
					}
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 2, []env.Type{env.StringType}, "Gin-group//POST")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Gin-group//POST")
			}
		},
	},

	"Gin-context//Param": {
		Argsn: 2,
		Doc:   "Get URL parameter from Gin context.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch ctx := arg0.(type) {
			case env.Native:
				switch key := arg1.(type) {
				case env.String:
					value := ctx.Value.(*gin.Context).Param(key.Value)
					return *env.NewString(value)
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 2, []env.Type{env.StringType}, "Gin-context//Param")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Gin-context//Param")
			}
		},
	},

	"Gin-context//Query": {
		Argsn: 2,
		Doc:   "Get query parameter from Gin context.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch ctx := arg0.(type) {
			case env.Native:
				switch key := arg1.(type) {
				case env.String:
					value := ctx.Value.(*gin.Context).Query(key.Value)
					return *env.NewString(value)
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 2, []env.Type{env.StringType}, "Gin-context//Query")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Gin-context//Query")
			}
		},
	},

	"Gin-context//PostForm": {
		Argsn: 2,
		Doc:   "Get form parameter from Gin context.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch ctx := arg0.(type) {
			case env.Native:
				switch key := arg1.(type) {
				case env.String:
					value := ctx.Value.(*gin.Context).PostForm(key.Value)
					return *env.NewString(value)
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 2, []env.Type{env.StringType}, "Gin-context//PostForm")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Gin-context//PostForm")
			}
		},
	},

	"Gin-context//String": {
		Argsn: 3,
		Doc:   "Send string response with status code.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch ctx := arg0.(type) {
			case env.Native:
				switch code := arg1.(type) {
				case env.Integer:
					switch message := arg2.(type) {
					case env.String:
						ctx.Value.(*gin.Context).String(int(code.Value), message.Value)
						return arg0
					default:
						ps.FailureFlag = true
						return MakeArgError(ps, 3, []env.Type{env.StringType}, "Gin-context//String")
					}
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 2, []env.Type{env.IntegerType}, "Gin-context//String")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Gin-context//String")
			}
		},
	},

	"Gin-context//JSON": {
		Argsn: 3,
		Doc:   "Send JSON response with status code.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch ctx := arg0.(type) {
			case env.Native:
				switch code := arg1.(type) {
				case env.Integer:
					switch data := arg2.(type) {
					case env.Dict:
						ctx.Value.(*gin.Context).JSON(int(code.Value), data.Data)
						return arg0
					case env.List:
						ctx.Value.(*gin.Context).JSON(int(code.Value), data.Data)
						return arg0
					case env.Block:

						items := make([]interface{}, data.Series.Len())
						for i := 0; i < data.Series.Len(); i++ {
							items[i] = data.Series.Get(i)
						}
						ctx.Value.(*gin.Context).JSON(int(code.Value), items)
						return arg0
					default:
						ps.FailureFlag = true
						return MakeArgError(ps, 3, []env.Type{env.DictType, env.ListType, env.BlockType}, "Gin-context//JSON")
					}
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 2, []env.Type{env.IntegerType}, "Gin-context//JSON")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Gin-context//JSON")
			}
		},
	},

	"Gin-context//HTML": {
		Argsn: 4,
		Doc:   "Render HTML template with data.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch ctx := arg0.(type) {
			case env.Native:
				switch code := arg1.(type) {
				case env.Integer:
					switch tmplName := arg2.(type) {
					case env.String:
						switch data := arg3.(type) {
						case env.Dict:

							ginH := make(gin.H)
							for k, v := range data.Data {
								ginH[k] = v
							}
							ctx.Value.(*gin.Context).HTML(int(code.Value), tmplName.Value, ginH)
							return arg0
						default:
							ps.FailureFlag = true
							return MakeArgError(ps, 4, []env.Type{env.DictType}, "Gin-context//HTML")
						}
					default:
						ps.FailureFlag = true
						return MakeArgError(ps, 3, []env.Type{env.StringType}, "Gin-context//HTML")
					}
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 2, []env.Type{env.IntegerType}, "Gin-context//HTML")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Gin-context//HTML")
			}
		},
	},

	"Gin-context//ShouldBindJSON": {
		Argsn: 1,
		Doc:   "Bind request JSON to Rye dict.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch ctx := arg0.(type) {
			case env.Native:
				var jsonData map[string]interface{}
				err := ctx.Value.(*gin.Context).ShouldBindJSON(&jsonData)
				if err != nil {
					ps.FailureFlag = true
					return MakeBuiltinError(ps, err.Error(), "Gin-context//ShouldBindJSON")
				}

				ryeDict := env.NewDict(jsonData)
				return *ryeDict
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Gin-context//ShouldBindJSON")
			}
		},
	},

	"Gin-context//Header": {
		Argsn: 3,
		Doc:   "Set response header in Gin context.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch ctx := arg0.(type) {
			case env.Native:
				switch name := arg1.(type) {
				case env.String:
					switch value := arg2.(type) {
					case env.String:
						ctx.Value.(*gin.Context).Header(name.Value, value.Value)
						return arg0
					default:
						ps.FailureFlag = true
						return MakeArgError(ps, 3, []env.Type{env.StringType}, "Gin-context//Header")
					}
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 2, []env.Type{env.StringType}, "Gin-context//Header")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Gin-context//Header")
			}
		},
	},

	"Gin-context//Status": {
		Argsn: 2,
		Doc:   "Set response status code.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch ctx := arg0.(type) {
			case env.Native:
				switch code := arg1.(type) {
				case env.Integer:
					ctx.Value.(*gin.Context).Status(int(code.Value))
					return arg0
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 2, []env.Type{env.IntegerType}, "Gin-context//Status")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Gin-context//Status")
			}
		},
	},

	"Gin-context//FullPath": {
		Argsn: 1,
		Doc:   "Get the full path of the matched route.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch ctx := arg0.(type) {
			case env.Native:
				fullPath := ctx.Value.(*gin.Context).FullPath()
				return *env.NewString(fullPath)
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Gin-context//FullPath")
			}
		},
	},

	"Gin-context//ClientIP": {
		Argsn: 1,
		Doc:   "Get client IP address from Gin context.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch ctx := arg0.(type) {
			case env.Native:
				clientIP := ctx.Value.(*gin.Context).ClientIP()
				return *env.NewString(clientIP)
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Gin-context//ClientIP")
			}
		},
	},

	"Gin-context//GetHeader": {
		Argsn: 2,
		Doc:   "Get request header value from Gin context.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch ctx := arg0.(type) {
			case env.Native:
				switch name := arg1.(type) {
				case env.String:
					value := ctx.Value.(*gin.Context).GetHeader(name.Value)
					return *env.NewString(value)
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 2, []env.Type{env.StringType}, "Gin-context//GetHeader")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Gin-context//GetHeader")
			}
		},
	},

	"status\\OK": {
		Argsn: 0,
		Doc:   "HTTP 200 OK status code constant.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return *env.NewInteger(http.StatusOK)
		},
	},

	"status\\created": {
		Argsn: 0,
		Doc:   "HTTP 201 Created status code constant.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return *env.NewInteger(http.StatusCreated)
		},
	},

	"status\\bad-request": {
		Argsn: 0,
		Doc:   "HTTP 400 Bad Request status code constant.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return *env.NewInteger(http.StatusBadRequest)
		},
	},

	"status\\not-found": {
		Argsn: 0,
		Doc:   "HTTP 404 Not Found status code constant.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return *env.NewInteger(http.StatusNotFound)
		},
	},

	"status\\unauthorized": {
		Argsn: 0,
		Doc:   "HTTP 401 Unauthorized status code constant.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return *env.NewInteger(http.StatusUnauthorized)
		},
	},

	"status\\internal-server-error": {
		Argsn: 0,
		Doc:   "HTTP 500 Internal Server Error status code constant.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return *env.NewInteger(http.StatusInternalServerError)
		},
	},

	"status\\conflict": {
		Argsn: 0,
		Doc:   "HTTP 409 Conflict status code constant.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return *env.NewInteger(http.StatusConflict)
		},
	},

	"Gin-context//SetCookie": {
		Argsn: 8,
		Doc:   "Set HTTP cookie with name, value, maxAge, path, domain, secure, httpOnly.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch ctx := arg0.(type) {
			case env.Native:
				switch name := arg1.(type) {
				case env.String:
					switch value := arg2.(type) {
					case env.String:
						switch maxAge := arg3.(type) {
						case env.Integer:
							switch path := arg4.(type) {
							case env.String:

								ctx.Value.(*gin.Context).SetCookie(name.Value, value.Value, int(maxAge.Value), path.Value, "", false, false)
								return arg0
							default:
								ps.FailureFlag = true
								return MakeArgError(ps, 5, []env.Type{env.StringType}, "Gin-context//SetCookie")
							}
						default:
							ps.FailureFlag = true
							return MakeArgError(ps, 4, []env.Type{env.IntegerType}, "Gin-context//SetCookie")
						}
					default:
						ps.FailureFlag = true
						return MakeArgError(ps, 3, []env.Type{env.StringType}, "Gin-context//SetCookie")
					}
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 2, []env.Type{env.StringType}, "Gin-context//SetCookie")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Gin-context//SetCookie")
			}
		},
	},

	"Gin-context//Cookie": {
		Argsn: 2,
		Doc:   "Get cookie value by name from request.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch ctx := arg0.(type) {
			case env.Native:
				switch name := arg1.(type) {
				case env.String:
					value, err := ctx.Value.(*gin.Context).Cookie(name.Value)
					if err != nil {

						return *env.NewString("")
					}
					return *env.NewString(value)
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 2, []env.Type{env.StringType}, "Gin-context//Cookie")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Gin-context//Cookie")
			}
		},
	},

	"Gin-context//SetSession": {
		Argsn: 3,
		Doc:   "Set session value by key (stored in context).",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch ctx := arg0.(type) {
			case env.Native:
				switch key := arg1.(type) {
				case env.String:

					ctx.Value.(*gin.Context).Set("session_"+key.Value, arg2)
					return arg0
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 2, []env.Type{env.StringType}, "Gin-context//SetSession")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Gin-context//SetSession")
			}
		},
	},

	"Gin-context//GetSession": {
		Argsn: 2,
		Doc:   "Get session value by key from context.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch ctx := arg0.(type) {
			case env.Native:
				switch key := arg1.(type) {
				case env.String:
					value, exists := ctx.Value.(*gin.Context).Get("session_" + key.Value)
					if !exists {
						return *env.NewString("")
					}

					switch v := value.(type) {
					case string:
						return *env.NewString(v)
					case int64:
						return *env.NewInteger(v)
					case env.Object:
						return v
					default:
						return *env.NewString("")
					}
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 2, []env.Type{env.StringType}, "Gin-context//GetSession")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Gin-context//GetSession")
			}
		},
	},

	"Gin-context//ClearSession": {
		Argsn: 2,
		Doc:   "Clear/remove session value by key.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch ctx := arg0.(type) {
			case env.Native:
				switch key := arg1.(type) {
				case env.String:

					ctx.Value.(*gin.Context).Set("session_"+key.Value, nil)
					return arg0
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 2, []env.Type{env.StringType}, "Gin-context//ClearSession")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Gin-context//ClearSession")
			}
		},
	},

	"session\\login": {
		Argsn: 3,
		Doc:   "Helper function to create user login session.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch ctx := arg0.(type) {
			case env.Native:
				switch userID := arg1.(type) {
				case env.String:
					switch username := arg2.(type) {
					case env.String:

						ctx.Value.(*gin.Context).Set("session_user_id", userID.Value)
						ctx.Value.(*gin.Context).Set("session_username", username.Value)
						ctx.Value.(*gin.Context).Set("session_logged_in", true)

						ctx.Value.(*gin.Context).SetCookie("session_id", userID.Value, 3600, "/", "", false, true)

						return arg0
					default:
						ps.FailureFlag = true
						return MakeArgError(ps, 3, []env.Type{env.StringType}, "session\\login")
					}
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 2, []env.Type{env.StringType}, "session\\login")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "session\\login")
			}
		},
	},

	"session\\logout": {
		Argsn: 1,
		Doc:   "Helper function to destroy user session.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch ctx := arg0.(type) {
			case env.Native:

				ctx.Value.(*gin.Context).Set("session_user_id", nil)
				ctx.Value.(*gin.Context).Set("session_username", nil)
				ctx.Value.(*gin.Context).Set("session_logged_in", false)

				ctx.Value.(*gin.Context).SetCookie("session_id", "", -1, "/", "", false, true)

				return arg0
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "session\\logout")
			}
		},
	},

	"session\\is-logged-in": {
		Argsn: 1,
		Doc:   "Check if user is logged in.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch ctx := arg0.(type) {
			case env.Native:
				loggedIn, exists := ctx.Value.(*gin.Context).Get("session_logged_in")
				if exists && loggedIn == true {
					return *env.NewInteger(1)
				}
				return *env.NewInteger(0)
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "session\\is-logged-in")
			}
		},
	},

	"session\\get-user": {
		Argsn: 1,
		Doc:   "Get current logged in user info as dict.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch ctx := arg0.(type) {
			case env.Native:
				userID, _ := ctx.Value.(*gin.Context).Get("session_user_id")
				username, _ := ctx.Value.(*gin.Context).Get("session_username")
				loggedIn, _ := ctx.Value.(*gin.Context).Get("session_logged_in")

				userData := make(map[string]interface{})
				if userID != nil {
					userData["user_id"] = userID
				}
				if username != nil {
					userData["username"] = username
				}
				userData["logged_in"] = loggedIn == true

				return *env.NewDict(userData)
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "session\\get-user")
			}
		},
	},
}
View Source
var Builtins_git = map[string]*env.Builtin{

	"init": {
		Argsn: 1,
		Doc:   "Initializes a new Git repository at the specified path.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch path := arg0.(type) {
			case env.String:
				repo, err := git.PlainInit(path.Value, false)
				if err != nil {
					return MakeBuiltinError(ps, fmt.Sprintf("failed to initialize repository: %v", err), "git-init")
				}
				return *env.NewNative(ps.Idx, repo, "git-repo")
			case env.Uri:
				repo, err := git.PlainInit(path.GetPath(), false)
				if err != nil {
					return MakeBuiltinError(ps, fmt.Sprintf("failed to initialize repository: %v", err), "git-init")
				}
				return *env.NewNative(ps.Idx, repo, "git-repo")
			default:
				return MakeArgError(ps, 1, []env.Type{env.StringType, env.UriType}, "git-init")
			}
		},
	},

	"open": {
		Argsn: 1,
		Doc:   "Opens a Git repository at the specified path.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch path := arg0.(type) {
			case env.String:
				repo, err := git.PlainOpen(path.Value)
				if err != nil {
					return MakeBuiltinError(ps, fmt.Sprintf("failed to open repository: %v", err), "git-repo//open")
				}
				return *env.NewNative(ps.Idx, repo, "git-repo")
			case env.Uri:
				repo, err := git.PlainOpen(path.GetPath())
				if err != nil {
					return MakeBuiltinError(ps, fmt.Sprintf("failed to open repository: %v", err), "git-repo//open")
				}
				return *env.NewNative(ps.Idx, repo, "git-repo")
			default:
				return MakeArgError(ps, 1, []env.Type{env.StringType, env.UriType}, "git-repo//open")
			}
		},
	},

	"clone": {
		Argsn: 2,
		Doc:   "Clones a Git repository from the specified URL to the specified path.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch url := arg0.(type) {
			case env.String:
				switch path := arg1.(type) {
				case env.String:
					repo, err := git.PlainClone(path.Value, &git.CloneOptions{
						URL: url.Value,
					})
					if err != nil {
						return MakeBuiltinError(ps, fmt.Sprintf("failed to clone repository: %v", err), "git-repo//clone")
					}
					return *env.NewNative(ps.Idx, repo, "git-repo")
				case env.Uri:
					repo, err := git.PlainClone(path.GetPath(), &git.CloneOptions{
						URL: url.Value,
					})
					if err != nil {
						return MakeBuiltinError(ps, fmt.Sprintf("failed to clone repository: %v", err), "git-repo//clone")
					}
					return *env.NewNative(ps.Idx, repo, "git-repo")
				default:
					return MakeArgError(ps, 2, []env.Type{env.StringType, env.UriType}, "git-repo//clone")
				}
			case env.Uri:
				switch path := arg1.(type) {
				case env.String:
					repo, err := git.PlainClone(path.Value, &git.CloneOptions{
						URL: url.GetPath(),
					})
					if err != nil {
						return MakeBuiltinError(ps, fmt.Sprintf("failed to clone repository: %v", err), "git-repo//clone")
					}
					return *env.NewNative(ps.Idx, repo, "git-repo")
				case env.Uri:
					repo, err := git.PlainClone(path.GetPath(), &git.CloneOptions{
						URL: url.GetPath(),
					})
					if err != nil {
						return MakeBuiltinError(ps, fmt.Sprintf("failed to clone repository: %v", err), "git-repo//clone")
					}
					return *env.NewNative(ps.Idx, repo, "git-repo")
				default:
					return MakeArgError(ps, 2, []env.Type{env.StringType, env.UriType}, "git-repo//clone")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.StringType, env.UriType}, "git-repo//clone")
			}
		},
	},

	"git-repo//Worktree?": {
		Argsn: 1,
		Doc:   "Gets the worktree for a Git repository.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch repo := arg0.(type) {
			case env.Native:
				if ps.Idx.GetWord(repo.Kind.Index) != "git-repo" {
					return MakeBuiltinError(ps, "expected a Git repository object", "git-repo//Worktree?")
				}

				worktree, err := repo.Value.(*git.Repository).Worktree()
				if err != nil {
					return MakeBuiltinError(ps, fmt.Sprintf("failed to get worktree: %v", err), "git-repo//Worktree?")
				}
				return *env.NewNative(ps.Idx, worktree, "git-worktree")
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "git-repo//Worktree?")
			}
		},
	},

	"git-worktree//Status?": {
		Argsn: 1,
		Doc:   "Gets the status of a Git worktree.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch wt := arg0.(type) {
			case env.Native:
				if ps.Idx.GetWord(wt.Kind.Index) != "git-worktree" {
					return MakeBuiltinError(ps, "expected a Git worktree object", "git-worktree//Status?")
				}

				status, err := wt.Value.(*git.Worktree).Status()
				if err != nil {
					return MakeBuiltinError(ps, fmt.Sprintf("failed to get status: %v", err), "git-worktree//Status?")
				}

				dict := env.NewDict(make(map[string]any))
				for filePath, fileStatus := range status {
					fileDict := env.NewDict(make(map[string]any))
					fileDict.Data["staging"] = string(fileStatus.Staging)
					fileDict.Data["worktree"] = string(fileStatus.Worktree)
					dict.Data[filePath] = fileDict
				}

				return *dict
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "git-worktree//Status?")
			}
		},
	},

	"git-repo//Untracked-files?": {
		Argsn: 1,
		Doc:   "Lists all untracked files in the repository sorted by last modification time (newest first).",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch repo := arg0.(type) {
			case env.Native:
				if ps.Idx.GetWord(repo.Kind.Index) != "git-repo" {
					return MakeBuiltinError(ps, "expected a Git repository object", "git-repo//Untracked-files?")
				}

				gitRepo := repo.Value.(*git.Repository)

				worktree, err := gitRepo.Worktree()
				if err != nil {
					return MakeBuiltinError(ps, fmt.Sprintf("failed to get worktree: %v", err), "git-repo//Untracked-files?")
				}

				status, err := worktree.Status()
				if err != nil {
					return MakeBuiltinError(ps, fmt.Sprintf("failed to get status: %v", err), "git-repo//Untracked-files?")
				}

				repoPath := "."

				if wt, err := gitRepo.Worktree(); err == nil {
					path := wt.Filesystem.Root()
					if path != "" {
						repoPath = path
					}
				}

				// Collect untracked files
				var untrackedFiles []fileInfo
				for filePath, fileStatus := range status {

					if string(fileStatus.Worktree) == "?" && string(fileStatus.Staging) == "?" {

						fullPath := filepath.Join(repoPath, filePath)

						info, err := os.Stat(fullPath)
						if err != nil {
							fmt.Fprintf(os.Stderr, "warning: could not stat file %s: %v\n", fullPath, err)
							continue
						}

						if info.IsDir() {
							continue
						}

						untrackedFiles = append(untrackedFiles, fileInfo{
							path:  filePath,
							mtime: info.ModTime(),
						})
					}
				}

				sort.Slice(untrackedFiles, func(i, j int) bool {
					return untrackedFiles[i].mtime.After(untrackedFiles[j].mtime)
				})

				result := make([]env.Object, 0, len(untrackedFiles))
				for _, file := range untrackedFiles {
					fileDict := env.NewDict(make(map[string]any))
					fileDict.Data["path"] = file.path
					fileDict.Data["mtime"] = file.mtime.Format(time.RFC3339)
					result = append(result, *fileDict)
				}

				return *env.NewBlock(*env.NewTSeries(result))
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "git-repo//Untracked-files?")
			}
		},
	},

	"git-repo//Commits?": {
		Argsn: 1,
		Doc:   "Gets the commit history for a Git repository.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch repo := arg0.(type) {
			case env.Native:
				if ps.Idx.GetWord(repo.Kind.Index) != "git-repo" {
					return MakeBuiltinError(ps, "expected a Git repository object", "git-repo//Commits?")
				}

				gitRepo := repo.Value.(*git.Repository)

				ref, err := gitRepo.Head()
				if err != nil {
					return MakeBuiltinError(ps, fmt.Sprintf("failed to get HEAD reference: %v", err), "git-repo//Commits?")
				}

				commitIter, err := gitRepo.Log(&git.LogOptions{From: ref.Hash()})
				if err != nil {
					return MakeBuiltinError(ps, fmt.Sprintf("failed to get commit history: %v", err), "git-repo//Commits?")
				}

				commits := make([]env.Object, 0)
				err = commitIter.ForEach(func(c *object.Commit) error {
					commitDict := env.NewDict(make(map[string]any))
					commitDict.Data["hash"] = c.Hash.String()
					commitDict.Data["author"] = c.Author.Name
					commitDict.Data["email"] = c.Author.Email
					commitDict.Data["message"] = c.Message
					commitDict.Data["date"] = c.Author.When.Format(time.RFC3339)

					commits = append(commits, *commitDict)
					return nil
				})

				if err != nil {
					return MakeBuiltinError(ps, fmt.Sprintf("failed to iterate commits: %v", err), "git-repo//Commits?")
				}

				return *env.NewBlock(*env.NewTSeries(commits))
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "git-repo//Commits?")
			}
		},
	},

	"git-repo//Branches?": {
		Argsn: 1,
		Doc:   "Gets the list of branches in a Git repository.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch repo := arg0.(type) {
			case env.Native:
				if ps.Idx.GetWord(repo.Kind.Index) != "git-repo" {
					return MakeBuiltinError(ps, "expected a Git repository object", "git-repo//Branches?")
				}

				gitRepo := repo.Value.(*git.Repository)

				branchIter, err := gitRepo.Branches()
				if err != nil {
					return MakeBuiltinError(ps, fmt.Sprintf("failed to get branches: %v", err), "git-repo//Branches?")
				}

				branches := make([]env.Object, 0)
				err = branchIter.ForEach(func(ref *plumbing.Reference) error {
					branchDict := env.NewDict(make(map[string]any))
					branchDict.Data["name"] = ref.Name().Short()
					branchDict.Data["hash"] = ref.Hash().String()

					branches = append(branches, *branchDict)
					return nil
				})

				if err != nil {
					return MakeBuiltinError(ps, fmt.Sprintf("failed to iterate branches: %v", err), "git-repo//Branches?")
				}

				return *env.NewBlock(*env.NewTSeries(branches))
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "git-repo//Branches?")
			}
		},
	},

	"git-repo//Remotes?": {
		Argsn: 1,
		Doc:   "Gets the list of remotes in a Git repository.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch repo := arg0.(type) {
			case env.Native:
				if ps.Idx.GetWord(repo.Kind.Index) != "git-repo" {
					return MakeBuiltinError(ps, "expected a Git repository object", "git-repo//Remotes?")
				}

				gitRepo := repo.Value.(*git.Repository)

				remotes, err := gitRepo.Remotes()
				if err != nil {
					return MakeBuiltinError(ps, fmt.Sprintf("failed to get remotes: %v", err), "git-repo//Remotes?")
				}

				remotesBlock := make([]env.Object, 0, len(remotes))
				for _, remote := range remotes {
					remoteDict := env.NewDict(make(map[string]any))
					remoteDict.Data["name"] = remote.Config().Name

					urls := make([]env.Object, 0, len(remote.Config().URLs))
					for _, url := range remote.Config().URLs {
						urls = append(urls, *env.NewString(url))
					}

					remoteDict.Data["urls"] = *env.NewBlock(*env.NewTSeries(urls))
					remotesBlock = append(remotesBlock, *remoteDict)
				}

				return *env.NewBlock(*env.NewTSeries(remotesBlock))
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "git-repo//Remotes?")
			}
		},
	},

	"git-repo//Tags?": {
		Argsn: 1,
		Doc:   "Gets the list of tags in a Git repository.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch repo := arg0.(type) {
			case env.Native:
				if ps.Idx.GetWord(repo.Kind.Index) != "git-repo" {
					return MakeBuiltinError(ps, "expected a Git repository object", "git-repo//Tags?")
				}

				gitRepo := repo.Value.(*git.Repository)

				tagIter, err := gitRepo.Tags()
				if err != nil {
					return MakeBuiltinError(ps, fmt.Sprintf("failed to get tags: %v", err), "git-repo//Tags?")
				}

				tags := make([]env.Object, 0)
				err = tagIter.ForEach(func(ref *plumbing.Reference) error {
					tagDict := env.NewDict(make(map[string]any))
					tagDict.Data["name"] = ref.Name().Short()
					tagDict.Data["hash"] = ref.Hash().String()

					tags = append(tags, *tagDict)
					return nil
				})

				if err != nil {
					return MakeBuiltinError(ps, fmt.Sprintf("failed to iterate tags: %v", err), "git-repo//Tags?")
				}

				return *env.NewBlock(*env.NewTSeries(tags))
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "git-repo//Tags?")
			}
		},
	},

	"git-repo//Checkout": {
		Argsn: 2,
		Doc:   "Checks out a branch in a Git repository.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch repo := arg0.(type) {
			case env.Native:
				if ps.Idx.GetWord(repo.Kind.Index) != "git-repo" {
					return MakeBuiltinError(ps, "expected a Git repository object", "git-repo//checkout")
				}

				gitRepo := repo.Value.(*git.Repository)

				worktree, err := gitRepo.Worktree()
				if err != nil {
					return MakeBuiltinError(ps, fmt.Sprintf("failed to get worktree: %v", err), "git-repo//checkout")
				}

				// Get the branch name
				var branchName string
				switch branch := arg1.(type) {
				case env.String:
					branchName = branch.Value
				default:
					return MakeArgError(ps, 2, []env.Type{env.StringType}, "git-repo//checkout")
				}

				err = worktree.Checkout(&git.CheckoutOptions{
					Branch: plumbing.NewBranchReferenceName(branchName),
				})
				if err != nil {
					return MakeBuiltinError(ps, fmt.Sprintf("failed to checkout branch: %v", err), "git-repo//checkout")
				}

				return arg0
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "git-repo//checkout")
			}
		},
	},

	"git-repo//Create-branch": {
		Argsn: 2,
		Doc:   "Creates a new branch in a Git repository.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch repo := arg0.(type) {
			case env.Native:
				if ps.Idx.GetWord(repo.Kind.Index) != "git-repo" {
					return MakeBuiltinError(ps, "expected a Git repository object", "git-repo//create-branch")
				}

				gitRepo := repo.Value.(*git.Repository)

				worktree, err := gitRepo.Worktree()
				if err != nil {
					return MakeBuiltinError(ps, fmt.Sprintf("failed to get worktree: %v", err), "git-repo//create-branch")
				}

				// Get the branch name
				var branchName string
				switch branch := arg1.(type) {
				case env.String:
					branchName = branch.Value
				default:
					return MakeArgError(ps, 2, []env.Type{env.StringType}, "git-repo//create-branch")
				}

				headRef, err := gitRepo.Head()
				if err != nil {
					return MakeBuiltinError(ps, fmt.Sprintf("failed to get HEAD reference: %v", err), "git-repo//create-branch")
				}

				branchRef := plumbing.NewBranchReferenceName(branchName)

				err = gitRepo.Storer.SetReference(plumbing.NewHashReference(branchRef, headRef.Hash()))
				if err != nil {
					return MakeBuiltinError(ps, fmt.Sprintf("failed to create branch: %v", err), "git-repo//create-branch")
				}

				err = worktree.Checkout(&git.CheckoutOptions{
					Branch: branchRef,
				})
				if err != nil {
					return MakeBuiltinError(ps, fmt.Sprintf("failed to checkout branch: %v", err), "git-repo//create-branch")
				}

				return arg0
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "git-repo//create-branch")
			}
		},
	},

	"git-worktree//Add": {
		Argsn: 2,
		Doc:   "Adds a file to the Git index.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch wt := arg0.(type) {
			case env.Native:
				if ps.Idx.GetWord(wt.Kind.Index) != "git-worktree" {
					return MakeBuiltinError(ps, "expected a Git worktree object", "git-worktree//add")
				}

				worktree := wt.Value.(*git.Worktree)

				// Get the file path
				var filePath string
				switch path := arg1.(type) {
				case env.String:
					filePath = path.Value
				case env.Uri:
					filePath = path.GetPath()
				default:
					return MakeArgError(ps, 2, []env.Type{env.StringType, env.UriType}, "git-worktree//add")
				}

				_, err := worktree.Add(filePath)
				if err != nil {
					return MakeBuiltinError(ps, fmt.Sprintf("failed to add file: %v", err), "git-worktree//add")
				}

				return arg0
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "git-worktree//add")
			}
		},
	},

	"git-worktree//Commit": {
		Argsn: 2,
		Doc:   "Commits changes to the Git repository.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch wt := arg0.(type) {
			case env.Native:
				if ps.Idx.GetWord(wt.Kind.Index) != "git-worktree" {
					return MakeBuiltinError(ps, "expected a Git worktree object", "git-worktree//commit")
				}

				worktree := wt.Value.(*git.Worktree)

				// Get the commit message
				var message string
				switch msg := arg1.(type) {
				case env.String:
					message = msg.Value
				default:
					return MakeArgError(ps, 2, []env.Type{env.StringType}, "git-worktree//commit")
				}

				authorName := "Rye User"
				authorEmail := "rye@example.com"

				if arg2 != nil {
					switch author := arg2.(type) {
					case env.String:
						authorName = author.Value
					default:
						return MakeArgError(ps, 3, []env.Type{env.StringType}, "git-worktree//commit")
					}
				}

				if arg3 != nil {
					switch email := arg3.(type) {
					case env.String:
						authorEmail = email.Value
					default:
						return MakeArgError(ps, 4, []env.Type{env.StringType}, "git-worktree//commit")
					}
				}

				_, err := worktree.Commit(message, &git.CommitOptions{
					Author: &object.Signature{
						Name:  authorName,
						Email: authorEmail,
						When:  time.Now(),
					},
				})
				if err != nil {
					return MakeBuiltinError(ps, fmt.Sprintf("failed to commit changes: %v", err), "git-worktree//commit")
				}

				return arg0
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "git-worktree//commit")
			}
		},
	},
}
View Source
var Builtins_goroutines = map[string]*env.Builtin{

	"go-with": {
		Argsn: 2,
		Doc:   "Executes a function in a separate goroutine, passing the specified value as an argument.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch arg := arg0.(type) {
			case env.Object:
				switch handler := arg1.(type) {
				case env.Function:

					psTemp := env.ProgramState{}
					err := copier.Copy(&psTemp, &ps)
					if err != nil {
						return MakeBuiltinError(ps, fmt.Sprintf("failed to copy program state: %s", err), "go-with")
					}

					psTemp.FailureFlag = false
					psTemp.ErrorFlag = false
					psTemp.ReturnFlag = false

					go func() {
						defer func() {
							if r := recover(); r != nil {

								fmt.Printf("Goroutine panic in go-with: %v\n", r)
							}
						}()
						CallFunction_CollectArgs(handler, &psTemp, arg, false, nil)
					}()

					return arg0
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 2, []env.Type{env.FunctionType}, "go-with")
				}
			default:
				ps.FailureFlag = true
				return MakeBuiltinError(ps, "First argument should be object type.", "go-with")
			}
		},
	},

	"go": {
		Argsn: 1,
		Doc:   "Executes a function in a separate goroutine without passing any arguments.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch handler := arg0.(type) {
			case env.Function:

				psTemp := env.ProgramState{}
				err := copier.Copy(&psTemp, &ps)
				if err != nil {
					return MakeBuiltinError(ps, fmt.Sprintf("failed to copy program state: %s", err), "go")
				}

				psTemp.FailureFlag = false
				psTemp.ErrorFlag = false
				psTemp.ReturnFlag = false

				go func() {
					defer func() {
						if r := recover(); r != nil {

							fmt.Printf("Goroutine panic in go: %v\n", r)
						}
					}()
					CallFunction_CollectArgs(handler, &psTemp, nil, false, nil)
				}()

				return arg0
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.FunctionType}, "go")
			}
		},
	},

	"channel": {
		Argsn: 1,
		Doc:   "Creates a new channel with the specified buffer size for goroutine communication.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch buflen := arg0.(type) {
			case env.Integer:

				ch := make(chan *env.Object, int(buflen.Value))
				return *env.NewNative(ps.Idx, ch, "Rye-channel")
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.IntegerType}, "channel")
			}
		},
	},

	"Rye-channel//Read": {
		Argsn: 1,
		Doc:   "Reads the next value from a channel, blocking until a value is available or the channel is closed.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch chn := arg0.(type) {
			case env.Native:

				ch, ok := chn.Value.(chan *env.Object)
				if !ok {
					ps.FailureFlag = true
					return MakeBuiltinError(ps, "Invalid channel type", "Rye-channel//Read")
				}

				msg, ok := <-ch
				if ok {
					return *msg
				} else {
					return *env.NewError("channel closed")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Rye-channel//Read")
			}
		},
	},

	"Rye-channel//Send": {
		Argsn: 2,
		Doc:   "Sends a value through a channel, blocking if the channel is unbuffered or full.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch chn := arg0.(type) {
			case env.Native:
				chn.Value.(chan *env.Object) <- &arg1
				return arg0
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Rye-channel//Send")
			}
		},
	},

	"Rye-channel//Close": {
		Argsn: 1,
		Doc:   "Closes a channel, preventing further sends and causing pending/future reads to return an error.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch chn := arg0.(type) {
			case env.Native:
				close(chn.Value.(chan *env.Object))
				return arg0
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Rye-channel//Close")
			}
		},
	},

	"mutex": {
		Argsn: 0,
		Doc:   "Creates a new mutex for synchronizing access to shared resources between goroutines.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			var mtx sync.Mutex
			return *env.NewNative(ps.Idx, &mtx, "Rye-mutex")
		},
	},

	"waitgroup": {
		Argsn: 0,
		Doc:   "Creates a new waitgroup for coordinating multiple goroutines to wait for completion.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			var wg sync.WaitGroup
			return *env.NewNative(ps.Idx, &wg, "Rye-waitgroup")
		},
	},

	"Rye-mutex//Lock": {
		Argsn: 1,
		Doc:   "Acquires the lock on a mutex, blocking until the lock becomes available.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch mtx := arg0.(type) {
			case env.Native:
				mtx.Value.(*sync.Mutex).Lock()
				return arg0
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Rye-mutex//Lock")
			}
		},
	},

	"Rye-mutex//Unlock": {
		Argsn: 1,
		Doc:   "Releases the lock on a mutex, allowing other goroutines to acquire it.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch mtx := arg0.(type) {
			case env.Native:
				mtx.Value.(*sync.Mutex).Unlock()
				return arg0
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Rye-mutex//Unlock")
			}
		},
	},

	"Rye-waitgroup//Add": {
		Argsn: 2,
		Doc:   "Adds the specified count to the waitgroup counter, indicating how many goroutines to wait for.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch wg := arg0.(type) {
			case env.Native:
				switch count := arg1.(type) {
				case env.Integer:
					wg.Value.(*sync.WaitGroup).Add(int(count.Value))
					return arg0
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 2, []env.Type{env.IntegerType}, "Rye-waitgroup//Add")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Rye-waitgroup//Add")
			}
		},
	},

	"Rye-waitgroup//Done": {
		Argsn: 1,
		Doc:   "Decrements the waitgroup counter by one, indicating that a goroutine has completed.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch wg := arg0.(type) {
			case env.Native:
				wg.Value.(*sync.WaitGroup).Done()
				return arg0
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Rye-waitgroup//Done")
			}
		},
	},

	"Rye-waitgroup//Wait": {
		Argsn: 1,
		Doc:   "Blocks until the waitgroup counter reaches zero, meaning all goroutines have completed.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch wg := arg0.(type) {
			case env.Native:
				wg.Value.(*sync.WaitGroup).Wait()
				return arg0
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Rye-waitgroup//Wait")
			}
		},
	},

	"select\\fn": {
		Argsn: 1,
		Doc:   "Performs a select operation on multiple channels, executing functions when channels are ready or a default function.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch block := arg0.(type) {
			case env.Block:
				ser := ps.Ser
				ps.Ser = block.Series

				var hasDeafult bool
				var cases []reflect.SelectCase
				var funcs []env.Function
				for ps.Ser.Pos() < ps.Ser.Len() {
					EvalExpression_CollectArg(ps, false)
					defaultFn, ok := ps.Res.(env.Function)

					if ok {
						if hasDeafult {
							ps.FailureFlag = true
							return MakeBuiltinError(ps, "select can only have one default case", "select\\fn")
						}
						if defaultFn.Argsn != 0 {
							ps.FailureFlag = true
							return MakeBuiltinError(ps, "function with 0 args required", "select\\fn")
						}
						defaultCase := make(chan struct{})
						close(defaultCase)
						cases = append(cases, reflect.SelectCase{
							Dir:  reflect.SelectRecv,
							Chan: reflect.ValueOf(defaultCase),
						})
						funcs = append(funcs, defaultFn)
						hasDeafult = true
						continue
					}

					native, ok := ps.Res.(env.Native)
					if !ok {
						ps.FailureFlag = true
						return MakeBuiltinError(ps, "first argument of a case must be a channel", "select\\fn")
					}
					ch, ok := native.Value.(chan *env.Object)
					if !ok {
						ps.FailureFlag = true
						return MakeBuiltinError(ps, "first argument of a case must be a channel", "select\\fn")
					}
					cases = append(cases, reflect.SelectCase{Dir: reflect.SelectRecv, Chan: reflect.ValueOf(ch)})

					EvalExpression_CollectArg(ps, false)
					fn, ok := ps.Res.(env.Function)
					if !ok {
						ps.FailureFlag = true
						return MakeBuiltinError(ps, "second argument of a case must be a function", "select\\fn")
					}
					if fn.Argsn > 1 {
						ps.FailureFlag = true
						return MakeBuiltinError(ps, "function with 0 or 1 arg required", "select\\fn")
					}
					funcs = append(funcs, fn)
				}
				ps.Ser = ser

				chosen, value, recvOK := reflect.Select(cases)
				fn := funcs[chosen]

				psTemp := env.ProgramState{}
				err := copier.Copy(&psTemp, &ps)
				if err != nil {
					ps.FailureFlag = true
					return MakeBuiltinError(ps, fmt.Sprintf("failed to copy ps: %s", err), "select\\fn")
				}
				var arg env.Object = nil
				if recvOK {
					val, ok := value.Interface().(*env.Object)
					if !ok {
						ps.FailureFlag = true
						return MakeBuiltinError(ps, "value from channel is not an object", "select\\fn")
					}
					arg = *val
				}
				if fn.Argsn == 0 {
					arg = nil
				}
				CallFunction_CollectArgs(fn, &psTemp, arg, false, nil)

			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.BlockType}, "select\\fn")
			}
			return arg0
		},
	},

	"select": {
		Argsn: 1,
		Doc:   "Select on a message on multiple channels or default.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch block := arg0.(type) {
			case env.Block:
				ser := ps.Ser
				ps.Ser = block.Series

				var hasDeafult bool
				var cases []reflect.SelectCase
				var funcs []env.Block
				for ps.Ser.Pos() < ps.Ser.Len() {
					EvalExpression_CollectArg(ps, false)

					switch maybeChan := ps.Res.(type) {
					case env.Native:
						ch, ok := maybeChan.Value.(chan *env.Object)
						if !ok {
							ps.FailureFlag = true
							return MakeBuiltinError(ps, "first argument of a case must be a channel", "select")
						}
						cases = append(cases, reflect.SelectCase{Dir: reflect.SelectRecv, Chan: reflect.ValueOf(ch)})

						EvalExpression_CollectArg(ps, false)
						fn, ok := ps.Res.(env.Block)
						if !ok {
							ps.FailureFlag = true
							return MakeBuiltinError(ps, "second argument of a case must be a block", "select")
						}

						funcs = append(funcs, fn)

					case env.Void:
						if hasDeafult {
							ps.FailureFlag = true
							return MakeBuiltinError(ps, "select can only have one default case", "select")
						}

						defaultCase := make(chan struct{})
						close(defaultCase)
						cases = append(cases, reflect.SelectCase{
							Dir:  reflect.SelectRecv,
							Chan: reflect.ValueOf(defaultCase),
						})
						EvalExpression_CollectArg(ps, false)
						fn, ok := ps.Res.(env.Block)
						if !ok {
							ps.FailureFlag = true
							return MakeBuiltinError(ps, "second argument of a case must be a block", "select")
						}
						funcs = append(funcs, fn)
						hasDeafult = true
					}
				}
				ps.Ser = ser

				chosen, value, recvOK := reflect.Select(cases)
				fn := funcs[chosen]

				psTemp := env.ProgramState{}
				err := copier.Copy(&psTemp, &ps)
				if err != nil {
					ps.FailureFlag = true
					return MakeBuiltinError(ps, fmt.Sprintf("failed to copy ps: %s", err), "select")
				}
				var arg env.Object = nil
				if recvOK {
					val, ok := value.Interface().(*env.Object)
					if !ok {
						ps.FailureFlag = true
						return MakeBuiltinError(ps, "value from channel is not an object", "select")
					}
					arg = *val
				}

				psTemp.Ser = fn.Series
				EvalBlockInj(&psTemp, arg, true)
				MaybeDisplayFailureOrError(ps, ps.Idx, "select")

				if psTemp.ErrorFlag {
					return psTemp.Res
				}

			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.BlockType}, "select")
			}
			return arg0
		},
	},
}
View Source
var Builtins_html = map[string]*env.Builtin{

	"unescape\\html": {
		Argsn: 1,
		Doc:   "Converts HTML entities to their character equivalents.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			text, ok := arg0.(env.String)
			if !ok {
				return MakeArgError(ps, 1, []env.Type{env.StringType}, "unescape\\html")
			}
			mkd := html.UnescapeString(text.Value)
			return *env.NewString(mkd)
		},
	},

	"escape\\html": {
		Argsn: 1,
		Doc:   "Converts special characters to HTML entities.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			text, ok := arg0.(env.String)
			if !ok {
				return MakeArgError(ps, 1, []env.Type{env.StringType}, "unescape\\html")
			}
			mkd := html.EscapeString(text.Value)
			return *env.NewString(mkd)
		},
	},

	"html->markdown": {
		Argsn: 1,
		Doc:   "Converts HTML text to markdown format.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			text, ok := arg0.(env.String)
			if !ok {
				return MakeArgError(ps, 1, []env.Type{env.StringType}, "html->markdown")
			}
			mkd, err := htmltomarkdown.ConvertString(text.Value)
			if err != nil {
				return MakeBuiltinError(ps, err.Error(), "html->markdown")
			}
			return *env.NewString(mkd)
		},
	},

	"reader//Parse-html": {
		Argsn: 2,
		Doc:   "Parses HTML using a streaming approach with tag handlers.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			rm, err := load_html_Dict(ps, arg1.(env.Block))
			trace8("*** _--- GOT RM ++**")

			if err != nil {
				ps.FailureFlag = true
				return MakeBuiltinError(ps, "Error to load html dict.", "reader//parse-html")
			}
			return do_html(ps, arg0.(env.Native).Value.(io.Reader), rm)
		},
	},

	"rye-html-start//Attr?": {
		Argsn: 2,
		Doc:   "Retrieves an attribute value by name or index from an HTML element.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch tok1 := arg0.(type) {
			case env.Native:
				switch tok := tok1.Value.(type) {
				case html.Token:
					switch n := arg1.(type) {
					case env.Integer:
						if int(n.Value) < len(tok.Attr) {
							return *env.NewString(tok.Attr[int(n.Value)].Val)
						} else {
							return MakeBuiltinError(ps, "Attribute index out of bounds.", "rye-html-start//Attr?")
						}
					case env.Word:
						attrName := ps.Idx.GetWord(n.Index)
						for _, a := range tok.Attr {
							if a.Key == attrName {
								return *env.NewString(a.Val)
							}
						}
						return MakeBuiltinError(ps, "Attribute '"+attrName+"' not found.", "rye-html-start//Attr?")
					case env.String:
						attrName := n.Value
						for _, a := range tok.Attr {
							if a.Key == attrName {
								return *env.NewString(a.Val)
							}
						}
						return MakeBuiltinError(ps, "Attribute '"+attrName+"' not found.", "rye-html-start//Attr?")
					default:
						return MakeArgError(ps, 2, []env.Type{env.IntegerType, env.WordType, env.StringType}, "rye-html-start//Attr?")
					}
				default:
					return MakeBuiltinError(ps, "Token value is not matching.", "rye-html-start//Attr?")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "rye-html-start//Attr?")
			}
		},
	},

	"rye-html-start//Attrs?": {
		Argsn: 1,
		Doc:   "Returns a dict of all attributes from an HTML element.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch tok1 := arg0.(type) {
			case env.Native:
				switch tok := tok1.Value.(type) {
				case html.Token:
					data := make(map[string]any)
					for _, attr := range tok.Attr {
						data[attr.Key] = *env.NewString(attr.Val)
					}
					return *env.NewDict(data)
				default:
					return MakeBuiltinError(ps, "Token value is not matching.", "rye-html-start//Attrs?")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "rye-html-start//Attrs?")
			}
		},
	},

	"rye-html-start//Name?": {
		Argsn: 1,
		Doc:   "Returns the name of an HTML element.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch tok1 := arg0.(type) {
			case env.Native:
				switch tok := tok1.Value.(type) {
				case html.Token:
					return *env.NewString(tok.Data)
				default:
					return MakeBuiltinError(ps, "Not xml-start element.", "rye-html-start//Name?")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "rye-html-start//Name?")
			}
		},
	},
}
View Source
var Builtins_http = map[string]*env.Builtin{

	"http-server": {
		Argsn: 1,
		Doc:   "Creates a new HTTP server that listens on the specified address with a 10-second read header timeout.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch addr := arg0.(type) {
			case env.String:

				server := &http.Server{Addr: addr.Value, ReadHeaderTimeout: 10 * time.Second}
				return *env.NewNative(ps.Idx, server, "Go-server")
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.StringType}, "http-server")
			}
		},
	},

	"Go-server//Serve": {
		Argsn: 1,
		Doc:   "Starts the HTTP server listening and serving requests on the configured address (blocking call).",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch server := arg0.(type) {
			case env.Native:

				err := server.Value.(*http.Server).ListenAndServe()
				if err != nil {
					return makeError(ps, err.Error())
				}
				return arg0
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Go-server//Serve")
			}
		},
	},

	"Go-server//Handle": {
		Argsn: 3,
		Doc:   "Registers an HTTP handler for a specific path pattern on the server, accepting string responses, Rye functions, or native Go handlers.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch path := arg1.(type) {
			case env.String:
				switch handler := arg2.(type) {
				case env.String:

					http.HandleFunc(path.Value, func(w http.ResponseWriter, r *http.Request) {
						fmt.Fprintf(w, handler.Value)
					})
					return arg0
				case env.Function:

					http.HandleFunc(path.Value, func(w http.ResponseWriter, r *http.Request) {

						ps.FailureFlag = false
						ps.ErrorFlag = false
						ps.ReturnFlag = false

						psTemp := env.ProgramState{}
						err := copier.Copy(&psTemp, &ps)
						if err != nil {
							fmt.Println(err.Error())

						}

						CallFunctionArgs2(handler, ps, *env.NewNative(ps.Idx, w, "Go-server-response-writer"), *env.NewNative(ps.Idx, r, "Go-server-request"), nil)

						if ps.FailureFlag || ps.ErrorFlag {
							fmt.Println("Error in HTTP handler: " + ps.Res.Inspect(*ps.Idx))
						}
					})
					return arg0
				case env.Native:

					http.Handle(path.Value, handler.Value.(http.Handler))
					return arg0
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 3, []env.Type{env.StringType, env.FunctionType, env.NativeType}, "Go-server//Handle")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 2, []env.Type{env.StringType}, "Go-server//Handle")
			}
		},
	},

	"Go-server-response-writer//Write": {
		Argsn: 2,
		Doc:   "Writes string content to the HTTP response body, used within HTTP request handlers to send response data to clients.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch path := arg0.(type) {
			case env.Native:
				switch handler := arg1.(type) {
				case env.String:

					fmt.Fprintf(path.Value.(http.ResponseWriter), handler.Value)
					return arg0
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 2, []env.Type{env.StringType}, "Go-server-response-writer//Write")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Go-server-response-writer//Write")
			}
		},
	},

	"Go-server-response-writer//Set-content-type": {
		Argsn: 2,
		Doc:   "Sets the Content-Type header for the HTTP response, determining how the browser interprets the response data.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch path := arg0.(type) {
			case env.Native:
				switch handler := arg1.(type) {
				case env.String:

					path.Value.(http.ResponseWriter).Header().Set("Content-Type", handler.Value)
					return arg0
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 2, []env.Type{env.StringType}, "Go-server-response-writer//Set-content-type")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Go-server-response-writer//Set-content-type")
			}
		},
	},

	"Go-server-response-writer//Set-header": {
		Argsn: 3,
		Doc:   "Sets a custom HTTP header in the response, allowing control over caching, security, and other HTTP behaviors.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch writer := arg0.(type) {
			case env.Native:
				switch name := arg1.(type) {
				case env.Word:

					name_ := ps.Idx.GetWord(name.Index)
					switch value := arg2.(type) {
					case env.String:

						writer.Value.(http.ResponseWriter).Header().Set(name_, value.Value)
						return arg0
					default:
						ps.FailureFlag = true
						return MakeArgError(ps, 3, []env.Type{env.StringType}, "Go-server-response-writer//Set-header")
					}
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 2, []env.Type{env.WordType}, "Go-server-response-writer//Set-header")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Go-server-response-writer//Set-header")
			}
		},
	},

	"Go-server-response-writer//Write-header": {
		Argsn: 2,
		Doc:   "Sets the HTTP status code for the response (must be called before writing response body).",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch w := arg0.(type) {
			case env.Native:
				switch code := arg1.(type) {
				case env.Integer:

					w.Value.(http.ResponseWriter).WriteHeader(int(code.Value))
					return arg0
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 2, []env.Type{env.IntegerType}, "Go-server-response-writer//Write-header")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Go-server-response-writer//Write-header")
			}
		},
	},

	"Go-server//Handle-ws": {
		Argsn: 3,
		Doc:   "Define handler for websockets",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch path := arg1.(type) {
			case env.String:
				switch handler := arg2.(type) {
				case env.Function:
					http.HandleFunc(path.Value, func(w http.ResponseWriter, r *http.Request) {
						conn, _, _, err := ws.UpgradeHTTP(r, w)
						if err != nil {
							fmt.Println("< upgrade http error >")

						}
						go func() {
							defer conn.Close()
							ps.FailureFlag = false
							ps.ErrorFlag = false
							ps.ReturnFlag = false
							fmt.Println("<< Call Function Args 2 >>")
							fmt.Println(ps.Ser.PositionAndSurroundingElements(*ps.Idx))
							psTemp := env.ProgramState{}
							err := copier.Copy(&psTemp, &ps)
							if err != nil {
								fmt.Println(err.Error())

							}
							CallFunctionArgs2(handler, &psTemp, *env.NewNative(psTemp.Idx, conn, "Go-server-websocket"), *env.NewNative(psTemp.Idx, "asd", "Go-server-context"), nil)

						}()
					})
					return arg0
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 1, []env.Type{env.FunctionType}, "Go-server//Handle-ws")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.StringType}, "Go-server//Handle-ws")
			}
		},
	},

	"Go-server-websocket//Read": {
		Argsn: 1,
		Doc:   "Reading websocket.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch conn := arg0.(type) {
			case env.Native:
				fmt.Println("BEFORE READ")

				msg, op, err := wsutil.ReadClientData(conn.Value.(io.ReadWriter))
				fmt.Println("AFTER READ")
				fmt.Println(op)
				if err != nil {
					fmt.Println(err.Error())
					fmt.Println("READ ERROR !!!!")
					ps.ReturnFlag = true
					ps.FailureFlag = true
					ps.ErrorFlag = true
					return MakeBuiltinError(ps, "Error in reading client data.", "Go-server-websocket//Read")
				}

				return env.NewString(string(msg))
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Go-server-websocket//Read")
			}
		},
	},

	"Go-server-websocket//Write": {
		Argsn: 2,
		Doc:   "Writing websocket.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch sock := arg0.(type) {
			case env.Native:
				switch message := arg1.(type) {
				case env.String:
					err := wsutil.WriteServerMessage(sock.Value.(io.Writer), ws.OpText, []byte(message.Value))

					if err != nil {
						fmt.Println("YYOOYOYOYOYOYOYYOYOYOOY")
						ps.FailureFlag = true
						return MakeBuiltinError(ps, "Failed to write server message.", "Go-server-websocket//Write")
					}
					return arg1
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 2, []env.Type{env.NativeType}, "Go-server-websocket//Write")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Go-server-websocket//Write")
			}
		},
	},

	"Go-server-request//Query?": {
		Argsn: 2,
		Doc:   "Retrieves a query parameter value from the HTTP request URL (e.g., from ?name=value&other=data).",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch req := arg0.(type) {
			case env.Native:
				switch key := arg1.(type) {
				case env.String:

					vals, ok := req.Value.(*http.Request).URL.Query()[key.Value]

					if !ok || len(vals[0]) < 1 {
						ps.FailureFlag = true
						return MakeBuiltinError(ps, "Key is missing.", "Go-server-request//query?")
					}

					return *env.NewString(vals[0])
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 2, []env.Type{env.StringType}, "Go-server-request//query?")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Go-server-request//query?")
			}
		},
	},

	"Go-server-request//Url?": {
		Argsn: 1,
		Doc:   "Extracts the URL object from an HTTP request, providing access to path, query parameters, and other URL components.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch req := arg0.(type) {
			case env.Native:

				vals := req.Value.(*http.Request).URL
				return *env.NewNative(ps.Idx, vals, "Go-server-url")
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Go-server-request//url?")
			}
		},
	},

	"Go-server-url//Path?": {
		Argsn: 1,
		Doc:   "Extracts the path component from a URL object (the part after the domain and before query parameters).",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch req := arg0.(type) {
			case env.Native:

				val := req.Value.(*url.URL).Path
				return *env.NewString(val)
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Go-server-url//path?")
			}
		},
	},

	"Go-server-request//Cookie-val?": {
		Argsn: 2,
		Doc:   "Get cookie value from server request.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch req := arg0.(type) {
			case env.Native:
				switch key := arg1.(type) {
				case env.String:
					cookie, err := req.Value.(*http.Request).Cookie(key.Value)
					if err != nil {
						ps.FailureFlag = true
						return MakeBuiltinError(ps, "Cookie key is missing.", "Go-server-request//cookie-val?")
					}
					return *env.NewString(cookie.Value)
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 2, []env.Type{env.StringType}, "Go-server-request//cookie-val?")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Go-server-request//cookie-val?")
			}
		},
	},

	"Go-server-request//Form?": {
		Argsn: 2,
		Doc:   "Get form field from server request.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch req := arg0.(type) {
			case env.Native:
				switch key := arg1.(type) {
				case env.String:
					r := req.Value.(*http.Request)
					err := r.ParseForm()
					if err != nil {
						return makeError(ps, err.Error())
					}
					val := r.FormValue(key.Value)
					if len(val) < 1 {
						ps.FailureFlag = true
						return MakeBuiltinError(ps, "Value is missing.", "Go-server-request//form?")
					}
					return *env.NewString(val)
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 2, []env.Type{env.StringType}, "Go-server-request//form?")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Go-server-request//form?")
			}
		},
	},

	"Go-server-request//Full-form?": {
		Argsn: 1,
		Doc:   "Get full form data as Dict from server request.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch req := arg0.(type) {
			case env.Native:
				r := req.Value.(*http.Request)
				err := r.ParseForm()
				if err != nil {
					return makeError(ps, err.Error())
				}
				dict := make(map[string]any)
				for key, val := range r.Form {
					dict[key] = val[0]
				}
				return *env.NewDict(dict)
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Go-server-request//full-form?")
			}
		},
	},

	"Go-server-request//Parse-multipart-form!": {
		Argsn: 1,
		Doc:   "Parse multipart form from server request.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch req := arg0.(type) {
			case env.Native:
				r := req.Value.(*http.Request)

				err := r.ParseMultipartForm(10 << 20)
				if err != nil {
					return makeError(ps, err.Error())
				}
				return arg0
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Go-server-request//parse-multipart-form!")
			}
		},
	},

	"Go-server-request//Form-file?": {
		Argsn: 2,
		Doc:   "Get form file from server request as block with reader and multipart header.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch req := arg0.(type) {
			case env.Native:
				switch key := arg1.(type) {
				case env.String:
					r := req.Value.(*http.Request)
					file, handler, err := r.FormFile(key.Value)
					if err != nil {
						ps.FailureFlag = true
						return MakeBuiltinError(ps, fmt.Sprintf("Failed to read from file: '%v'", err.Error()), "Go-server-request//form-file?")
					}
					pair := make([]env.Object, 2)
					pair[0] = *env.NewNative(ps.Idx, file, "reader")
					pair[1] = *env.NewNative(ps.Idx, handler, "rye-multipart-header")
					return *env.NewBlock(*env.NewTSeries(pair))
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 2, []env.Type{env.StringType}, "Go-server-request//form-file?")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Go-server-request//form-file?")
			}
		},
	},

	"rye-multipart-header//Filename?": {
		Argsn: 1,
		Doc:   "Get filename from multipart header.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch req := arg0.(type) {
			case env.Native:
				r := req.Value.(*multipart.FileHeader)
				return *env.NewString(r.Filename)
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "rye-multipart-header//filename?")
			}
		},
	},

	"cookie-store": {
		Argsn: 1,
		Doc:   "Create new cookie store.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch addr := arg0.(type) {
			case env.String:
				return *env.NewNative(ps.Idx, sessions.NewCookieStore([]byte(addr.Value)), "Http-cookie-store")
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.StringType}, "new-cookie-store")
			}
		},
	},

	"Http-cookie-store//Get": {
		Argsn: 3,
		Doc:   "Get http cookie store.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {

			switch store := arg0.(type) {
			case env.Native:
				switch r := arg1.(type) {
				case env.Native:
					switch name := arg2.(type) {
					case env.String:

						session, err := store.Value.(*sessions.CookieStore).Get(r.Value.(*http.Request), name.Value)
						if err != nil {
							ps.FailureFlag = true
							errMsg := fmt.Sprintf("Can't get session: %v", err.Error())
							return MakeBuiltinError(ps, errMsg, "Http-cookie-store//get")
						}

						return *env.NewNative(ps.Idx, session, "Http-session")
					default:

						ps.FailureFlag = true
						return *env.NewError("arg 0 should be String")

					}
				default:

					ps.FailureFlag = true
					return *env.NewError("arg 0 should be String")

				}
			default:

				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Http-cookie-store//get")
			}
		},
	},

	"Http-session//Set": {
		Argsn: 3,
		Doc:   "Set http session.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {

			switch session := arg0.(type) {
			case env.Native:
				switch key := arg1.(type) {
				case env.String:
					switch val := arg2.(type) {
					case env.String:

						session.Value.(*sessions.Session).Values[key.Value] = val.Value
						return arg0
					case env.Integer:
						session.Value.(*sessions.Session).Values[key.Value] = int(val.Value)
						return arg0
					default:
						return MakeArgError(ps, 3, []env.Type{env.StringType, env.IntegerType}, "Http-session//set")
					}

				default:
					return MakeArgError(ps, 2, []env.Type{env.StringType}, "Http-session//set")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Http-session//set")
			}
		},
	},

	"Http-session//Get": {
		Argsn: 2,
		Doc:   "Get http session.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {

			switch session := arg0.(type) {
			case env.Native:
				switch key := arg1.(type) {
				case env.String:
					val := session.Value.(*sessions.Session).Values[key.Value]
					if val != nil {
						switch val2 := val.(type) {
						case int:
							return env.NewInteger(int64(val2))
						case string:
							return env.NewString(val2)
						case env.Object:
							return val2
						default:
							ps.FailureFlag = true
							return MakeBuiltinError(ps, "Unknown type.", "Http-session//get")
						}
					} else {
						ps.FailureFlag = true
						return MakeBuiltinError(ps, "Value is empty.", "Http-session//get")
					}
				default:
					return MakeArgError(ps, 2, []env.Type{env.StringType}, "Http-session//get")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Http-session//get")
			}
		},
	},

	"Http-session//Save": {
		Argsn: 3,
		Doc:   "Save http session.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch session := arg0.(type) {
			case env.Native:
				switch r := arg1.(type) {
				case env.Native:
					switch w := arg2.(type) {
					case env.Native:
						err := session.Value.(*sessions.Session).Save(r.Value.(*http.Request), w.Value.(http.ResponseWriter))
						if err != nil {
							ps.FailureFlag = true
							errMsg := fmt.Sprintf("Can't save: %v", err.Error())
							return MakeBuiltinError(ps, errMsg, "Http-session//save")
						}
						return *env.NewInteger(1)
					default:
						return MakeArgError(ps, 3, []env.Type{env.NativeType}, "Http-session//save")
					}
				default:
					return MakeArgError(ps, 2, []env.Type{env.NativeType}, "Http-session//save")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Http-session//save")
			}
		},
	},

	"http-dir": {
		Argsn: 1,
		Doc:   "Create new http directory.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch addr := arg0.(type) {
			case env.Uri:
				return *env.NewNative(ps.Idx, http.Dir(addr.Path), "Go-http-dir")
			default:
				return MakeArgError(ps, 1, []env.Type{env.UriType}, "http-dir")
			}
		},
	},
	"new-static-handler": {
		Argsn: 1,
		Doc:   "Create new static handler.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch addr := arg0.(type) {
			case env.Uri:
				return *env.NewNative(ps.Idx, http.FileServer(http.Dir(addr.Path)), "Http-handler")
			default:
				return MakeArgError(ps, 1, []env.Type{env.UriType}, "new-static-handler")
			}

		},
	},
	"Http-handler//Strip-prefix": {
		Argsn: 2,
		Doc:   "TODODOC.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch prefix := arg1.(type) {
			case env.String:
				switch servr := arg0.(type) {
				case env.Native:
					return *env.NewNative(ps.Idx, http.StripPrefix(prefix.Value, servr.Value.(http.Handler)), "Http-handler")
				default:
					return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Http-handler//strip-prefix")
				}
			default:
				return MakeArgError(ps, 2, []env.Type{env.StringType}, "Http-handler//strip-prefix")
			}

		},
	},

	"https-response//Header?": {
		Argsn: 2,
		Doc:   "Get header value from HTTP response.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch resp := arg0.(type) {
			case env.Native:
				switch headerName := arg1.(type) {
				case env.String:
					response := resp.Value.(*http.Response)
					headerValue := response.Header.Get(headerName.Value)
					return *env.NewString(headerValue)
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 2, []env.Type{env.StringType}, "https-response//Header?")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "https-response//Header?")
			}
		},
	},

	"https-response//Status?": {
		Argsn: 1,
		Doc:   "Gets the HTTP status code from a response object.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch resp := arg0.(type) {
			case env.Native:
				response := resp.Value.(*http.Response)
				return *env.NewInteger(int64(response.StatusCode))
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "https-response//Status?")
			}
		},
	},

	"https-response//Status-text?": {
		Argsn: 1,
		Doc:   "Gets the HTTP status text from a response object.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch resp := arg0.(type) {
			case env.Native:
				response := resp.Value.(*http.Response)
				return *env.NewString(response.Status)
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "https-response//Status-text?")
			}
		},
	},
}
View Source
var Builtins_imap = map[string]*env.Builtin{

	"imap-client": {
		Argsn: 4,
		Doc:   "Create new IMAP client connection with username, password, server, and port.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch username := arg0.(type) {
			case env.String:
				switch password := arg1.(type) {
				case env.String:
					switch server := arg2.(type) {
					case env.String:
						switch port := arg3.(type) {
						case env.Integer:
							client, err := imap.New(username.Value, password.Value, server.Value, int(port.Value))
							if err != nil {
								ps.FailureFlag = true
								return env.NewError(fmt.Sprintf("IMAP connection failed: %s", err.Error()))
							}
							return *env.NewNative(ps.Idx, client, "imap-client")
						default:
							return MakeArgError(ps, 4, []env.Type{env.IntegerType}, "new-imap-client")
						}
					default:
						return MakeArgError(ps, 3, []env.Type{env.StringType}, "new-imap-client")
					}
				default:
					return MakeArgError(ps, 2, []env.Type{env.StringType}, "new-imap-client")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.StringType}, "new-imap-client")
			}
		},
	},

	"imap-client\\oauth2": {
		Argsn: 4,
		Doc:   "Create new IMAP client connection with OAuth2 authentication (email, access_token, server, port).",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch email := arg0.(type) {
			case env.String:
				switch token := arg1.(type) {
				case env.String:
					switch server := arg2.(type) {
					case env.String:
						switch port := arg3.(type) {
						case env.Integer:
							client, err := imap.NewWithOAuth2(email.Value, token.Value, server.Value, int(port.Value))
							if err != nil {
								ps.FailureFlag = true
								return env.NewError(fmt.Sprintf("IMAP OAuth2 connection failed: %s", err.Error()))
							}
							return *env.NewNative(ps.Idx, client, "imap-client")
						default:
							return MakeArgError(ps, 4, []env.Type{env.IntegerType}, "new-imap-client-oauth2")
						}
					default:
						return MakeArgError(ps, 3, []env.Type{env.StringType}, "new-imap-client-oauth2")
					}
				default:
					return MakeArgError(ps, 2, []env.Type{env.StringType}, "new-imap-client-oauth2")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.StringType}, "new-imap-client-oauth2")
			}
		},
	},

	"imap-client//Select-folder": {
		Argsn: 2,
		Doc:   "Select a folder for operations (e.g., 'INBOX').",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch client := arg0.(type) {
			case env.Native:
				if imapClient, ok := client.Value.(*imap.Dialer); ok {
					switch folder := arg1.(type) {
					case env.String:
						err := imapClient.SelectFolder(folder.Value)
						if err != nil {
							ps.FailureFlag = true
							return env.NewError(fmt.Sprintf("Failed to select folder: %s", err.Error()))
						}
						return arg0
					default:
						return MakeArgError(ps, 2, []env.Type{env.StringType}, "imap-client//select-folder")
					}
				} else {
					return MakeBuiltinError(ps, "Expected imap-client", "imap-client//select-folder")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "imap-client//select-folder")
			}
		},
	},

	"imap-client//Get-folders": {
		Argsn: 1,
		Doc:   "Get list of available folders.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch client := arg0.(type) {
			case env.Native:
				if imapClient, ok := client.Value.(*imap.Dialer); ok {
					folders, err := imapClient.GetFolders()
					if err != nil {
						ps.FailureFlag = true
						return env.NewError(fmt.Sprintf("Failed to get folders: %s", err.Error()))
					}

					result := make([]env.Object, len(folders))
					for i, folder := range folders {
						result[i] = env.String{Value: folder}
					}
					return *env.NewBlock(*env.NewTSeries(result))
				} else {
					return MakeBuiltinError(ps, "Expected imap-client", "imap-client//get-folders")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "imap-client//get-folders")
			}
		},
	},

	"imap-client//Search-emails": {
		Argsn: 2,
		Doc:   "Search for emails using IMAP search criteria (e.g., 'UNSEEN', 'FROM \"user@domain.com\"', 'SUBJECT \"test\"').",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch client := arg0.(type) {
			case env.Native:
				if imapClient, ok := client.Value.(*imap.Dialer); ok {
					switch searchCriteria := arg1.(type) {
					case env.String:
						uids, err := imapClient.GetUIDs(searchCriteria.Value)
						if err != nil {
							ps.FailureFlag = true
							return env.NewError(fmt.Sprintf("Search failed: %s", err.Error()))
						}

						result := make([]env.Object, len(uids))
						for i, uid := range uids {
							result[i] = env.Integer{Value: int64(uid)}
						}
						return *env.NewBlock(*env.NewTSeries(result))
					default:
						return MakeArgError(ps, 2, []env.Type{env.StringType}, "imap-client//search-emails")
					}
				} else {
					return MakeBuiltinError(ps, "Expected imap-client", "imap-client//search-emails")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "imap-client//search-emails")
			}
		},
	},

	"imap-client//Get-overviews": {
		Argsn: 2,
		Doc:   "Get email overviews (headers only, fast) for given UIDs block.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch client := arg0.(type) {
			case env.Native:
				if imapClient, ok := client.Value.(*imap.Dialer); ok {
					switch uidsBlock := arg1.(type) {
					case env.Block:
						var uids []int
						for _, uidObj := range uidsBlock.Series.S {
							switch uid := uidObj.(type) {
							case env.Integer:
								uids = append(uids, int(uid.Value))
							default:
								return MakeBuiltinError(ps, "All UIDs must be integers", "imap-client//get-overviews")
							}
						}

						if len(uids) == 0 {
							return *env.NewBlock(*env.NewTSeries([]env.Object{}))
						}

						overviews, err := imapClient.GetOverviews(uids...)
						if err != nil {
							ps.FailureFlag = true
							return env.NewError(fmt.Sprintf("Failed to get overviews: %s", err.Error()))
						}

						result := make([]env.Object, 0, len(overviews))
						for uid, email := range overviews {
							emailDict := env.NewDict(make(map[string]any))
							emailDict.Data["uid"] = *env.NewInteger(int64(uid))
							emailDict.Data["subject"] = *env.NewString(email.Subject)

							fromStr := ""
							if email.From != nil && len(email.From) > 0 {
								var fromParts []string
								for emailAddr, name := range email.From {
									if name != "" {
										fromParts = append(fromParts, fmt.Sprintf("%s <%s>", name, emailAddr))
									} else {
										fromParts = append(fromParts, emailAddr)
									}
								}
								fromStr = strings.Join(fromParts, ", ")
							}
							emailDict.Data["from"] = *env.NewString(fromStr)

							toStr := ""
							if email.To != nil && len(email.To) > 0 {
								var toParts []string
								for emailAddr, name := range email.To {
									if name != "" {
										toParts = append(toParts, fmt.Sprintf("%s <%s>", name, emailAddr))
									} else {
										toParts = append(toParts, emailAddr)
									}
								}
								toStr = strings.Join(toParts, ", ")
							}
							emailDict.Data["to"] = *env.NewString(toStr)

							emailDict.Data["date"] = *env.NewString(email.Sent.Format(time.RFC3339))
							emailDict.Data["size"] = *env.NewInteger(int64(email.Size))

							flagObjs := make([]env.Object, len(email.Flags))
							for i, flag := range email.Flags {
								flagObjs[i] = *env.NewString(flag)
							}
							emailDict.Data["flags"] = *env.NewBlock(*env.NewTSeries(flagObjs))

							result = append(result, *emailDict)
						}

						return *env.NewBlock(*env.NewTSeries(result))
					default:
						return MakeArgError(ps, 2, []env.Type{env.BlockType}, "imap-client//get-overviews")
					}
				} else {
					return MakeBuiltinError(ps, "Expected imap-client", "imap-client//get-overviews")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "imap-client//get-overviews")
			}
		},
	},

	"imap-client//Get-emails": {
		Argsn: 2,
		Doc:   "Get full emails with bodies and attachments (slower) for given UIDs block.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch client := arg0.(type) {
			case env.Native:
				if imapClient, ok := client.Value.(*imap.Dialer); ok {
					switch uidsBlock := arg1.(type) {
					case env.Block:
						var uids []int
						for _, uidObj := range uidsBlock.Series.S {
							switch uid := uidObj.(type) {
							case env.Integer:
								uids = append(uids, int(uid.Value))
							default:
								return MakeBuiltinError(ps, "All UIDs must be integers", "imap-client//get-emails")
							}
						}

						if len(uids) == 0 {
							return *env.NewBlock(*env.NewTSeries([]env.Object{}))
						}

						emails, err := imapClient.GetEmails(uids...)
						if err != nil {
							ps.FailureFlag = true
							return env.NewError(fmt.Sprintf("Failed to get emails: %s", err.Error()))
						}

						result := make([]env.Object, 0, len(emails))
						for uid, email := range emails {
							emailDict := env.NewDict(make(map[string]any))
							emailDict.Data["uid"] = *env.NewInteger(int64(uid))
							emailDict.Data["subject"] = *env.NewString(email.Subject)

							fromStr := ""
							if email.From != nil && len(email.From) > 0 {
								var fromParts []string
								for emailAddr, name := range email.From {
									if name != "" {
										fromParts = append(fromParts, fmt.Sprintf("%s <%s>", name, emailAddr))
									} else {
										fromParts = append(fromParts, emailAddr)
									}
								}
								fromStr = strings.Join(fromParts, ", ")
							}
							emailDict.Data["from"] = *env.NewString(fromStr)

							toStr := ""
							if email.To != nil && len(email.To) > 0 {
								var toParts []string
								for emailAddr, name := range email.To {
									if name != "" {
										toParts = append(toParts, fmt.Sprintf("%s <%s>", name, emailAddr))
									} else {
										toParts = append(toParts, emailAddr)
									}
								}
								toStr = strings.Join(toParts, ", ")
							}
							emailDict.Data["to"] = *env.NewString(toStr)

							ccStr := ""
							if email.CC != nil && len(email.CC) > 0 {
								var ccParts []string
								for emailAddr, name := range email.CC {
									if name != "" {
										ccParts = append(ccParts, fmt.Sprintf("%s <%s>", name, emailAddr))
									} else {
										ccParts = append(ccParts, emailAddr)
									}
								}
								ccStr = strings.Join(ccParts, ", ")
							}
							emailDict.Data["cc"] = *env.NewString(ccStr)

							bccStr := ""
							if email.BCC != nil && len(email.BCC) > 0 {
								var bccParts []string
								for emailAddr, name := range email.BCC {
									if name != "" {
										bccParts = append(bccParts, fmt.Sprintf("%s <%s>", name, emailAddr))
									} else {
										bccParts = append(bccParts, emailAddr)
									}
								}
								bccStr = strings.Join(bccParts, ", ")
							}
							emailDict.Data["bcc"] = *env.NewString(bccStr)

							emailDict.Data["date"] = *env.NewString(email.Sent.Format(time.RFC3339))
							emailDict.Data["received"] = *env.NewString(email.Received.Format(time.RFC3339))
							emailDict.Data["message-id"] = *env.NewString(email.MessageID)
							emailDict.Data["size"] = *env.NewInteger(int64(email.Size))
							emailDict.Data["text"] = *env.NewString(email.Text)
							emailDict.Data["html"] = *env.NewString(email.HTML)

							flagObjs := make([]env.Object, len(email.Flags))
							for i, flag := range email.Flags {
								flagObjs[i] = *env.NewString(flag)
							}
							emailDict.Data["flags"] = *env.NewBlock(*env.NewTSeries(flagObjs))

							if len(email.Attachments) > 0 {
								attachObjs := make([]env.Object, len(email.Attachments))
								for i, att := range email.Attachments {
									attDict := env.NewDict(make(map[string]any))
									attDict.Data["name"] = *env.NewString(att.Name)
									attDict.Data["mime-type"] = *env.NewString(att.MimeType)
									attDict.Data["size"] = *env.NewInteger(int64(len(att.Content)))

									attDict.Data["content"] = string(att.Content)
									attachObjs[i] = *attDict
								}
								emailDict.Data["attachments"] = *env.NewBlock(*env.NewTSeries(attachObjs))
							} else {
								emailDict.Data["attachments"] = *env.NewBlock(*env.NewTSeries([]env.Object{}))
							}

							result = append(result, *emailDict)
						}

						return *env.NewBlock(*env.NewTSeries(result))
					default:
						return MakeArgError(ps, 2, []env.Type{env.BlockType}, "imap-client//get-emails")
					}
				} else {
					return MakeBuiltinError(ps, "Expected imap-client", "imap-client//get-emails")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "imap-client//get-emails")
			}
		},
	},

	"imap-client//Mark-seen": {
		Argsn: 2,
		Doc:   "Mark an email as read/seen by UID.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch client := arg0.(type) {
			case env.Native:
				if imapClient, ok := client.Value.(*imap.Dialer); ok {
					switch uid := arg1.(type) {
					case env.Integer:
						err := imapClient.MarkSeen(int(uid.Value))
						if err != nil {
							ps.FailureFlag = true
							return env.NewError(fmt.Sprintf("Failed to mark email as seen: %s", err.Error()))
						}
						return arg0
					default:
						return MakeArgError(ps, 2, []env.Type{env.IntegerType}, "imap-client//mark-seen")
					}
				} else {
					return MakeBuiltinError(ps, "Expected imap-client", "imap-client//mark-seen")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "imap-client//mark-seen")
			}
		},
	},

	"imap-client//Move-email": {
		Argsn: 3,
		Doc:   "Move an email to another folder by UID.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch client := arg0.(type) {
			case env.Native:
				if imapClient, ok := client.Value.(*imap.Dialer); ok {
					switch uid := arg1.(type) {
					case env.Integer:
						switch folder := arg2.(type) {
						case env.String:
							err := imapClient.MoveEmail(int(uid.Value), folder.Value)
							if err != nil {
								ps.FailureFlag = true
								return env.NewError(fmt.Sprintf("Failed to move email: %s", err.Error()))
							}
							return arg0
						default:
							return MakeArgError(ps, 3, []env.Type{env.StringType}, "imap-client//move-email")
						}
					default:
						return MakeArgError(ps, 2, []env.Type{env.IntegerType}, "imap-client//move-email")
					}
				} else {
					return MakeBuiltinError(ps, "Expected imap-client", "imap-client//move-email")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "imap-client//move-email")
			}
		},
	},

	"imap-client//Delete-email": {
		Argsn: 2,
		Doc:   "Mark an email for deletion by UID (use expunge to permanently delete).",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch client := arg0.(type) {
			case env.Native:
				if imapClient, ok := client.Value.(*imap.Dialer); ok {
					switch uid := arg1.(type) {
					case env.Integer:
						err := imapClient.DeleteEmail(int(uid.Value))
						if err != nil {
							ps.FailureFlag = true
							return env.NewError(fmt.Sprintf("Failed to delete email: %s", err.Error()))
						}
						return arg0
					default:
						return MakeArgError(ps, 2, []env.Type{env.IntegerType}, "imap-client//delete-email")
					}
				} else {
					return MakeBuiltinError(ps, "Expected imap-client", "imap-client//delete-email")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "imap-client//delete-email")
			}
		},
	},

	"imap-client//Expunge": {
		Argsn: 1,
		Doc:   "Permanently remove emails marked for deletion.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch client := arg0.(type) {
			case env.Native:
				if imapClient, ok := client.Value.(*imap.Dialer); ok {
					err := imapClient.Expunge()
					if err != nil {
						ps.FailureFlag = true
						return env.NewError(fmt.Sprintf("Failed to expunge: %s", err.Error()))
					}
					return arg0
				} else {
					return MakeBuiltinError(ps, "Expected imap-client", "imap-client//expunge")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "imap-client//expunge")
			}
		},
	},

	"imap-client//Close": {
		Argsn: 1,
		Doc:   "Close the IMAP client connection.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch client := arg0.(type) {
			case env.Native:
				if imapClient, ok := client.Value.(*imap.Dialer); ok {
					err := imapClient.Close()
					if err != nil {
						ps.FailureFlag = true
						return env.NewError(fmt.Sprintf("Failed to close connection: %s", err.Error()))
					}
					return env.Void{}
				} else {
					return MakeBuiltinError(ps, "Expected imap-client", "imap-client//close")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "imap-client//close")
			}
		},
	},
}
View Source
var Builtins_io = map[string]*env.Builtin{

	"input": {
		Argsn: 1,
		Doc:   "Prompts for and reads user input from the console.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch str := arg0.(type) {
			case env.String:
				fmt.Print("" + str.Value)
				var input string
				fmt.Scanln(&input)

				return *env.NewString(input)
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.StringType}, "input")
			}
		},
	},

	"file-uri//Open": {
		Argsn: 1,
		Doc:   "Opens a file for reading.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch s := arg0.(type) {
			case env.Uri:
				file, err := os.Open(s.Path)
				if err != nil {
					return makeError(ps, err.Error())
				}
				return *env.NewNative(ps.Idx, file, "file")
			default:
				return MakeArgError(ps, 1, []env.Type{env.UriType}, "file-uri//Open")
			}
		},
	},

	"file-uri//Open\\append": {
		Argsn: 1,
		Doc:   "Opens a file for appending.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {

			profile, exists := os.LookupEnv("RYE_SECCOMP_PROFILE")
			if exists && profile == "readonly" {
				ps.FailureFlag = true
				return MakeBuiltinError(ps, "file append operation blocked by readonly seccomp profile", "file-uri//Open\\append")
			}

			switch s := arg0.(type) {
			case env.Uri:
				file, err := os.OpenFile(s.Path, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644)
				if err != nil {
					return MakeBuiltinError(ps, err.Error(), "__openFile")
				}
				return *env.NewNative(ps.Idx, file, "file")
			default:
				return MakeArgError(ps, 1, []env.Type{env.UriType}, "__openFile")
			}
		},
	},

	"file-uri//Create": {
		Argsn: 1,
		Doc:   "Creates a new file.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {

			profile, exists := os.LookupEnv("RYE_SECCOMP_PROFILE")
			if exists && profile == "readonly" {
				ps.FailureFlag = true
				return MakeBuiltinError(ps, "file creation blocked by readonly seccomp profile", "file-uri//Create")
			}

			switch s := arg0.(type) {
			case env.Uri:

				file, err := os.Create(s.Path)
				if err != nil {
					ps.ReturnFlag = true
					ps.FailureFlag = true
					return MakeBuiltinError(ps, err.Error(), "__create")
				}
				return *env.NewNative(ps.Idx, file, "file")
			default:
				ps.ReturnFlag = true
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.UriType}, "__create")
			}
		},
	},

	"file-uri//File-ext?": {
		Argsn: 1,
		Doc:   "Gets the extension of a file.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch s := arg0.(type) {
			case env.Uri:
				ext := filepath.Ext(s.Path)
				return *env.NewString(ext)

			default:
				return MakeArgError(ps, 1, []env.Type{env.UriType, env.StringType}, "file-ext?")
			}
		},
	},

	"file-uri//Filename?": {
		Argsn: 1,
		Doc:   "Gets the filename with extension from a file path.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch s := arg0.(type) {
			case env.Uri:
				filename := filepath.Base(s.Path)
				return *env.NewString(filename)
			default:
				return MakeArgError(ps, 1, []env.Type{env.UriType}, "file-uri//Filename?")
			}
		},
	},

	"file-uri//Stem?": {
		Argsn: 1,
		Doc:   "Gets the filename without extension from a file path.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch s := arg0.(type) {
			case env.Uri:
				base := filepath.Base(s.Path)
				stem := strings.TrimSuffix(base, filepath.Ext(base))
				return *env.NewString(stem)
			default:
				return MakeArgError(ps, 1, []env.Type{env.UriType}, "file-uri//Stem?")
			}
		},
	},

	"file-uri//Dir?": {
		Argsn: 1,
		Doc:   "Gets the directory path from a file path.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch s := arg0.(type) {
			case env.Uri:
				dir := filepath.Dir(s.Path)
				return *env.NewString(dir)
			default:
				return MakeArgError(ps, 1, []env.Type{env.UriType}, "file-uri//Dir?")
			}
		},
	},

	"file-uri//Split": {
		Argsn: 1,
		Doc:   "Splits a file path into its components.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch s := arg0.(type) {
			case env.Uri:
				pathStr := s.Path
				var components []env.Object

				parts := strings.Split(pathStr, string(filepath.Separator))
				for _, part := range parts {
					if part != "" {
						components = append(components, *env.NewString(part))
					}
				}

				if filepath.IsAbs(pathStr) && len(components) > 0 {
					components = append([]env.Object{*env.NewString(string(filepath.Separator))}, components...)
				}

				return *env.NewBlock(*env.NewTSeries(components))
			default:
				return MakeArgError(ps, 1, []env.Type{env.UriType}, "file-uri//Split")
			}
		},
	},

	"file-uri//Is-absolute": {
		Argsn: 1,
		Doc:   "Checks if a file path is absolute.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch s := arg0.(type) {
			case env.Uri:
				isAbs := filepath.IsAbs(s.Path)
				return *env.NewBoolean(isAbs)
			default:
				return MakeArgError(ps, 1, []env.Type{env.UriType}, "file-uri//Is-absolute")
			}
		},
	},

	"file-uri//Does-exist": {
		Argsn: 1,
		Doc:   "Checks if a file exists.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch s := arg0.(type) {
			case env.Uri:
				_, err := os.Stat(s.Path)
				if err == nil {
					return *env.NewBoolean(true)
				}
				if os.IsNotExist(err) {
					return *env.NewBoolean(false)
				}

				return *env.NewBoolean(false)
			default:
				return MakeArgError(ps, 1, []env.Type{env.UriType}, "file-uri//Does-exist")
			}
		},
	},

	"file-uri//Delete": {
		Argsn: 1,
		Doc:   "Deletes a file.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {

			profile, exists := os.LookupEnv("RYE_SECCOMP_PROFILE")
			if exists && profile == "readonly" {
				ps.FailureFlag = true
				return MakeBuiltinError(ps, "delete operation blocked by readonly seccomp profile", "file-uri//Delete")
			}

			switch s := arg0.(type) {
			case env.Uri:
				err := os.Remove(s.Path)
				if err != nil {
					ps.FailureFlag = true
					return MakeBuiltinError(ps, err.Error(), "file-uri//Delete")
				}
				return *env.NewBoolean(true)
			default:
				return MakeArgError(ps, 1, []env.Type{env.UriType}, "file-uri//Delete")
			}
		},
	},

	"file//Reader": {
		Argsn: 1,
		Doc:   "Creates a new reader from file object.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {

			switch s := arg0.(type) {
			case env.Native:
				file, ok := s.Value.(*os.File)
				if !ok {
					ps.FailureFlag = true
					return MakeBuiltinError(ps, "Error opening file.", "file//Reader")
				}
				return *env.NewNative(ps.Idx, bufio.NewReader(file), "reader")
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "file//Reader")
			}
		},
	},

	"file//Writer": {
		Argsn: 1,
		Doc:   "Creates a new reader from file object.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {

			switch s := arg0.(type) {
			case env.Native:
				file, ok := s.Value.(*os.File)
				if !ok {
					ps.FailureFlag = true
					return MakeBuiltinError(ps, "Error opening file.", "file//Reader")
				}
				return *env.NewNative(ps.Idx, bufio.NewWriter(file), "writer")
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "file//Reader")
			}
		},
	},

	"file-uri//Reader": {
		Argsn: 1,
		Doc:   "Creates a new reader from a file uri/path.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch s := arg0.(type) {
			case env.Uri:
				file, err := os.Open(s.Path)

				if err != nil {
					ps.FailureFlag = true
					return MakeBuiltinError(ps, "Error opening file.", "file-uri//Reader")
				}
				return *env.NewNative(ps.Idx, bufio.NewReader(file), "reader")
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.UriType}, "file-uri//Read")
			}
		},
	},

	"reader": {
		Argsn: 1,
		Doc:   "Creates a new reader from a string.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch s := arg0.(type) {
			case env.String:
				return *env.NewNative(ps.Idx, bufio.NewReader(strings.NewReader(s.Value)), "reader")
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.StringType}, "reader")
			}
		},
	},

	"stdin": {
		Argsn: 0,
		Doc:   "Gets a reader for standard input.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return *env.NewNative(ps.Idx, os.Stdin, "reader")
		},
	},

	"stdout": {
		Argsn: 0,
		Doc:   "Gets a writer for standard output.",
		Fn: func(env1 *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return *env.NewNative(env1.Idx, os.Stdout, "writer")
		},
	},

	"stderr": {
		Argsn: 0,
		Doc:   "Gets a writer for standard error.",
		Fn: func(env1 *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return *env.NewNative(env1.Idx, os.Stderr, "writer")
		},
	},

	"reader//Read\\string": {
		Argsn: 1,
		Doc:   "Reads all content from a reader as a string.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch r := arg0.(type) {
			case env.Native:
				reader, ok := r.Value.(io.Reader)
				if !ok {
					ps.FailureFlag = true
					return MakeBuiltinError(ps, "Not Reader", "__read\\string")
				}
				buf := new(strings.Builder)
				_, err := io.Copy(buf, reader)
				if err != nil {
					ps.FailureFlag = true
					return MakeBuiltinError(ps, err.Error(), "__read\\string")
				}
				return *env.NewString(buf.String())
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "__read\\string")
			}

		},
	},

	"reader//Close": {
		Argsn: 1,
		Doc:   "Closes a reader if it implements io.Closer.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch r := arg0.(type) {
			case env.Native:

				if closer, ok := r.Value.(io.Closer); ok {
					err := closer.Close()
					if err != nil {
						ps.FailureFlag = true
						return MakeBuiltinError(ps, err.Error(), "reader//Close")
					}
					return *env.NewString("")
				}

				return *env.NewString("")
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "reader//Close")
			}
		},
	},

	"reader//Copy": {
		Argsn: 2,
		Doc:   "Copies all content from a reader to a writer.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch r := arg0.(type) {
			case env.Native:
				switch w := arg1.(type) {
				case env.Native:

					_, err := io.Copy(w.Value.(io.Writer), r.Value.(io.Reader))
					if err != nil {
						ps.FailureFlag = true
						return MakeBuiltinError(ps, err.Error(), "__copy")
					}
					return arg0
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 2, []env.Type{env.NativeType}, "__copy")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "__copy")
			}

		},
	},

	"file//Copy": {
		Argsn: 2,
		Doc:   "Copies content from a file to a writer.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch r := arg0.(type) {
			case env.Native:
				switch w := arg1.(type) {
				case env.Native:

					_, err := io.Copy(w.Value.(io.Writer), r.Value.(io.Reader))
					if err != nil {
						ps.FailureFlag = true
						return MakeBuiltinError(ps, err.Error(), "__copy")
					}
					return arg0
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 2, []env.Type{env.NativeType}, "__copy")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "__copy")
			}

		},
	},

	"file//Stat": {
		Argsn: 1,
		Doc:   "Gets file information (stat) for a file.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch r := arg0.(type) {
			case env.Native:
				info, err := r.Value.(*os.File).Stat()
				if err != nil {
					ps.FailureFlag = true
					return MakeBuiltinError(ps, err.Error(), "file//Stat")
				}
				return *env.NewNative(ps.Idx, info, "file-info")
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "file//Stat")
			}
		},
	},

	"file-info//Size?": {
		Argsn: 1,
		Doc:   "Gets the size of a file in bytes.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch s := arg0.(type) {
			case env.Native:
				size := s.Value.(os.FileInfo).Size()
				return *env.NewInteger(size)
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "file-info//Size?")
			}
		},
	},

	"file//Read-all": {
		Argsn: 1,
		Doc:   "Reads the entire content of a file as a string.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch s := arg0.(type) {
			case env.Native:
				data, err := io.ReadAll(s.Value.(io.Reader))
				if err != nil {
					ps.FailureFlag = true
					return MakeBuiltinError(ps, "Error reading file.", "__read_all")
				}
				return *env.NewString(string(data))
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "__read_all")
			}
		},
	},

	"file//Seek\\end": {
		Argsn: 1,
		Doc:   "Seeks to the end of a file.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch s := arg0.(type) {
			case env.Native:
				reader, ok := s.Value.(*os.File)
				if !ok {
					return MakeBuiltinError(ps, "Native not io.Reader", "file//Seek\\end")
				}
				reader.Seek(0, os.SEEK_END)
				return arg0
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "file//Seek\\end")
			}
		},
	},

	"file//Write": {
		Argsn: 2,
		Doc:   "Writes a string directly to a file object.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {

			profile, exists := os.LookupEnv("RYE_SECCOMP_PROFILE")
			if exists && profile == "readonly" {
				ps.FailureFlag = true
				return MakeBuiltinError(ps, "write operation blocked by readonly seccomp profile", "file//Write")
			}

			switch s := arg0.(type) {
			case env.Native:
				file, ok := s.Value.(*os.File)
				if !ok {
					ps.FailureFlag = true
					return MakeBuiltinError(ps, "Native not os.File", "file//Write")
				}
				switch content := arg1.(type) {
				case env.String:
					_, err := file.WriteString(content.Value)
					if err != nil {
						ps.FailureFlag = true
						return MakeBuiltinError(ps, err.Error(), "file//Write")
					}
					return arg0
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 2, []env.Type{env.StringType}, "file//Write")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "file//Write")
			}
		},
	},

	"file//Close": {
		Argsn: 1,
		Doc:   "Closes an open file.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch s := arg0.(type) {
			case env.Native:
				err := s.Value.(*os.File).Close()
				if err != nil {
					ps.FailureFlag = true
					return MakeBuiltinError(ps, err.Error(), "__close")
				}
				return *env.NewString("")
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "__close")
			}

		},
	},

	"file-uri//Read": {
		Argsn: 1,
		Doc:   "Reads the entire content of a file as a string.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch f := arg0.(type) {
			case env.Uri:
				data, err := os.ReadFile(f.GetPath())
				if err != nil {
					return MakeBuiltinError(ps, err.Error(), "file-uri//Read")
				}
				return *env.NewString(string(data))
			default:
				return MakeArgError(ps, 1, []env.Type{env.UriType}, "file-uri//Read")
			}
		},
	},

	"file-uri//Read\\bytes": {
		Argsn: 1,
		Doc:   "Reads the entire content of a file as bytes.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch f := arg0.(type) {
			case env.Uri:
				data, err := os.ReadFile(f.GetPath())
				if err != nil {
					return MakeBuiltinError(ps, err.Error(), "__fs_read_bytes")
				}
				return *env.NewNative(ps.Idx, data, "bytes")
			default:
				return MakeArgError(ps, 1, []env.Type{env.UriType}, "__fs_read_bytes")
			}
		},
	},

	"file-uri//Read\\lines": {
		Argsn: 1,
		Doc:   "Reads a file and returns its content as a block of lines.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch f := arg0.(type) {
			case env.Uri:
				file, err := os.OpenFile(f.GetPath(), os.O_RDONLY, os.ModePerm)
				if err != nil {
					return MakeBuiltinError(ps, err.Error(), "file-uri//Read\\lines")
				}
				defer file.Close()

				lines := make([]env.Object, 0)
				sc := bufio.NewScanner(file)
				for sc.Scan() {
					lines = append(lines, *env.NewString(sc.Text()))
				}
				if err := sc.Err(); err != nil {
					return MakeBuiltinError(ps, err.Error(), "file-uri//Read\\lines")
				}
				return *env.NewBlock(*env.NewTSeries(lines))
			default:
				return MakeArgError(ps, 1, []env.Type{env.UriType}, "file-uri//Read\\lines")
			}
		},
	},

	"file-uri//Write": {
		Argsn: 2,
		Doc:   "Writes content to a file.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {

			profile, exists := os.LookupEnv("RYE_SECCOMP_PROFILE")
			if exists && profile == "readonly" {
				ps.FailureFlag = true
				return MakeBuiltinError(ps, "write operation blocked by readonly seccomp profile", "file-uri//Write")
			}

			switch f := arg0.(type) {
			case env.Uri:
				switch s := arg1.(type) {
				case env.String:
					err := os.WriteFile(f.GetPath(), []byte(s.Value), 0600)
					if err != nil {
						ps.FailureFlag = true
						return MakeBuiltinError(ps, err.Error(), "__fs_write")
					}
					return arg1
				case env.Native:
					err := os.WriteFile(f.GetPath(), s.Value.([]byte), 0600)
					if err != nil {
						ps.FailureFlag = true
						return MakeBuiltinError(ps, err.Error(), "__fs_write")
					}
					return arg1
				default:
					return MakeArgError(ps, 2, []env.Type{env.StringType, env.NativeType}, "__fs_write")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.UriType}, "__fs_write")
			}
		},
	},

	"write\\bytes": {
		Argsn: 2,
		Doc:   "Writes bytes to a file.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch bytesObj := arg0.(type) {
			case env.Native:
				if ps.Idx.GetWord(bytesObj.GetKind()) != "Go-bytes" {
					ps.FailureFlag = true
					return MakeArgError(ps, 1, []env.Type{env.NativeType}, "write-file")
				}
				switch path := arg1.(type) {
				case env.String:
					err := os.WriteFile(path.Value, bytesObj.Value.([]byte), 0644)
					if err != nil {
						ps.FailureFlag = true
						return MakeBuiltinError(ps, fmt.Sprintf("Failed to write file: %v", err), "write-file")
					}
					return env.Integer{1}
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 2, []env.Type{env.StringType}, "write-file")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "write-file")
			}
		},
	},

	"append\\bytes": {
		Argsn: 2,
		Doc:   "Appends two byte arrays into one.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch bytes1 := arg0.(type) {
			case env.Native:
				if ps.Idx.GetWord(bytes1.GetKind()) != "bytes" {
					ps.FailureFlag = true
					return MakeArgError(ps, 1, []env.Type{env.NativeType}, "append-bytes")
				}
				switch bytes2 := arg1.(type) {
				case env.Native:
					if ps.Idx.GetWord(bytes2.GetKind()) != "bytes" {
						ps.FailureFlag = true
						return MakeArgError(ps, 2, []env.Type{env.NativeType}, "append-bytes")
					}
					combined := append(bytes1.Value.([]byte), bytes2.Value.([]byte)...)
					return *env.NewNative(ps.Idx, combined, "bytes")
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 2, []env.Type{env.NativeType}, "append-bytes")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "append-bytes")
			}
		},
	},

	"writer//Write": {
		Argsn: 2,
		Doc:   "Writes a string to a writer.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {

			profile, exists := os.LookupEnv("RYE_SECCOMP_PROFILE")
			if exists && profile == "readonly" {

				switch ww := arg0.(type) {
				case env.Native:
					_, ok := ww.Value.(*bufio.Writer)
					if !ok {
						return MakeBuiltinError(ps, "Native not io.File", "writer//Write\\string")
					}

				}
			}

			switch s := arg1.(type) {
			case env.String:
				switch ww := arg0.(type) {
				case env.Native:
					writer, ok := ww.Value.(*bufio.Writer)
					if !ok {
						return MakeBuiltinError(ps, "Native not io.File", "writer//Write\\string")
					}
					_, err := writer.WriteString(s.Value)
					if err != nil {
						return MakeBuiltinError(ps, "Error at write: "+err.Error(), "writer//Write\\string")
					}
					return arg0
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 1, []env.Type{env.NativeType}, "writer//Write\\string")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.StringType}, "writer//Write\\string")
			}
		},
	},

	"https-uri//Open": {
		Argsn: 1,
		Doc:   "Opens a HTTPS GET request and returns a reader for the response body.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch f := arg0.(type) {
			case env.Uri:

				proto := ps.Idx.GetWord(f.GetProtocol().Index)

				req, err := http.NewRequest(http.MethodGet, proto+"://"+f.GetPath(), nil)
				if err != nil {
					ps.FailureFlag = true
					return *env.NewError(err.Error())
				}
				resp, err := http.DefaultClient.Do(req)
				if err != nil {
					ps.FailureFlag = true
					return *env.NewError(err.Error())
				}

				if resp.StatusCode >= 200 && resp.StatusCode <= 299 {
					return *env.NewNative(ps.Idx, resp.Body, "https-uri://open")
				} else {
					ps.FailureFlag = true
					errMsg := fmt.Sprintf("Status Code: %v", resp.StatusCode)
					return MakeBuiltinError(ps, errMsg, "https-uri://Open")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "https-uri://Open")
			}
		},
	},

	"https-uri//Get": {
		Argsn: 1,
		Doc:   "Makes a HTTPS GET request and returns the response body as a string.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch f := arg0.(type) {
			case env.Uri:
				proto := ps.Idx.GetWord(f.GetProtocol().Index)
				req, err := http.NewRequest(http.MethodGet, proto+"://"+f.GetPath(), nil)
				if err != nil {
					ps.FailureFlag = true
					return *env.NewError(err.Error())
				}
				resp, err := http.DefaultClient.Do(req)
				if err != nil {
					ps.FailureFlag = true
					return *env.NewError(err.Error())
				}
				defer resp.Body.Close()
				body, _ := io.ReadAll(resp.Body)

				if resp.StatusCode >= 200 && resp.StatusCode <= 299 {
					return *env.NewString(string(body))
				} else {
					ps.FailureFlag = true
					errMsg := fmt.Sprintf("Status Code: %v", resp.StatusCode)
					return MakeBuiltinError(ps, errMsg, "https-uri//Get")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.UriType}, "https-uri//Get")
			}
		},
	},

	"https-uri//Post": {
		Argsn: 3,
		Doc:   "Makes a HTTPS POST request and returns the response body as a string.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch f := arg0.(type) {
			case env.Uri:
				switch d := arg1.(type) {
				case env.String:
					var tt string

					switch t := arg2.(type) {
					case env.Word:

						tidx, terr := ps.Idx.GetIndex("json")
						tidx2, terr2 := ps.Idx.GetIndex("text")
						tidx3, terr3 := ps.Idx.GetIndex("urlencoded")
						tidx4, terr4 := ps.Idx.GetIndex("multipart")
						if terr && t.Index == tidx {
							tt = "application/json"
						} else if terr2 && t.Index == tidx2 {
							tt = "text/plain"
						} else if terr3 && t.Index == tidx3 {
							tt = "application/x-www-form-urlencoded"
						} else if terr4 && t.Index == tidx4 {
							tt = "multipart/form-data"
						} else {
							ps.FailureFlag = true
							return MakeBuiltinError(ps, "Wrong content type.", "https-uri//Post")
						}
					case env.String:

						tt = t.Value
					default:
						ps.FailureFlag = true
						return MakeArgError(ps, 3, []env.Type{env.WordType, env.StringType}, "https-uri//Post")
					}

					proto := ps.Idx.GetWord(f.GetProtocol().Index)
					req, err := http.NewRequest(http.MethodPost, proto+"://"+f.GetPath(), strings.NewReader(d.Value))
					if err != nil {
						ps.FailureFlag = true
						return *env.NewError(err.Error())
					}
					req.Header.Set("Content-Type", tt)
					resp, err := http.DefaultClient.Do(req)
					if err != nil {
						ps.FailureFlag = true
						return *env.NewError(err.Error())
					}
					defer resp.Body.Close()
					body, err := io.ReadAll(resp.Body)
					if err != nil {
						ps.FailureFlag = true
						return MakeBuiltinError(ps, err.Error(), "https-uri//Post")
					}

					if resp.StatusCode >= 200 && resp.StatusCode <= 299 {
						return *env.NewString(string(body))
					} else {
						ps.FailureFlag = true
						return env.NewError2(resp.StatusCode, string(body))
					}
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 2, []env.Type{env.StringType}, "https-uri//Post")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.UriType}, "https-uri//Post")
			}
		},
	},

	"http-uri//Get": {
		Argsn: 1,
		Doc:   "Makes a HTTP GET request and returns the response body as a string.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch f := arg0.(type) {
			case env.Uri:
				proto := ps.Idx.GetWord(f.GetProtocol().Index)
				req, err := http.NewRequest(http.MethodGet, proto+"://"+f.GetPath(), nil)
				if err != nil {
					ps.FailureFlag = true
					return *env.NewError(err.Error())
				}
				resp, err := http.DefaultClient.Do(req)
				if err != nil {
					ps.FailureFlag = true
					return *env.NewError(err.Error())
				}
				defer resp.Body.Close()
				body, _ := io.ReadAll(resp.Body)

				if resp.StatusCode >= 200 && resp.StatusCode <= 299 {
					return *env.NewString(string(body))
				} else {
					ps.FailureFlag = true
					errMsg := fmt.Sprintf("Status Code: %v", resp.StatusCode)
					return MakeBuiltinError(ps, errMsg, "http-uri//Get")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.UriType}, "http-uri//Get")
			}
		},
	},

	"http-uri//Post": {
		Argsn: 3,
		Doc:   "Makes a HTTP POST request and returns the response body as a string.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch f := arg0.(type) {
			case env.Uri:
				switch t := arg2.(type) {
				case env.Word:
					switch d := arg1.(type) {
					case env.String:
						var tt string
						tidx, terr := ps.Idx.GetIndex("json")
						tidx2, terr2 := ps.Idx.GetIndex("text")
						if terr && t.Index == tidx {
							tt = "application/json"
						} else if terr2 && t.Index == tidx2 {
							tt = "text/plain"
						} else {
							ps.FailureFlag = true
							return MakeBuiltinError(ps, "Wrong content type.", "http-uri//Post")
						}

						proto := ps.Idx.GetWord(f.GetProtocol().Index)
						req, err := http.NewRequest(http.MethodPost, proto+"://"+f.GetPath(), strings.NewReader(d.Value))
						if err != nil {
							ps.FailureFlag = true
							return *env.NewError(err.Error())
						}
						req.Header.Set("Content-Type", tt)
						resp, err := http.DefaultClient.Do(req)
						if err != nil {
							ps.FailureFlag = true
							return *env.NewError(err.Error())
						}
						defer resp.Body.Close()
						body, err := io.ReadAll(resp.Body)
						if err != nil {
							ps.FailureFlag = true
							return MakeBuiltinError(ps, err.Error(), "http-uri//Post")
						}

						if resp.StatusCode >= 200 && resp.StatusCode <= 299 {
							return *env.NewString(string(body))
						} else {
							ps.FailureFlag = true
							return env.NewError2(resp.StatusCode, string(body))
						}
					default:
						ps.FailureFlag = true
						return MakeArgError(ps, 2, []env.Type{env.StringType}, "http-uri//Post")
					}
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 3, []env.Type{env.WordType}, "http-uri//Post")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.UriType}, "http-uri//Post")
			}
		},
	},

	"https-uri//Request": {
		Argsn: 3,
		Doc:   "Creates a new HTTPS request object.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch uri := arg0.(type) {
			case env.Uri:
				switch method := arg1.(type) {
				case env.Word:
					method1 := ps.Idx.GetWord(method.Index)
					if !(method1 == "GET" || method1 == "POST" || method1 == "PUT" || method1 == "DELETE") {
						ps.FailureFlag = true
						return MakeBuiltinError(ps, "Wrong method.", "https-uri//Request")
					}
					switch data := arg2.(type) {
					case env.String:
						data1 := strings.NewReader(data.Value)
						proto := ps.Idx.GetWord(uri.GetProtocol().Index)
						req, err := http.NewRequest(method1, proto+"://"+uri.GetPath(), data1)
						if err != nil {
							ps.FailureFlag = true
							return MakeBuiltinError(ps, err.Error(), "https-uri//Request")
						}
						return *env.NewNative(ps.Idx, req, "https-request")
					default:
						ps.FailureFlag = true
						return MakeArgError(ps, 3, []env.Type{env.StringType}, "https-uri//Request")
					}
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 2, []env.Type{env.WordType}, "https-uri//Request")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.UriType}, "https-uri//Request")
			}
		},
	},

	"https-request//Header!": {
		Argsn: 3,
		Doc:   "Sets a header on a HTTPS request.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch req := arg0.(type) {
			case env.Native:
				switch method := arg1.(type) {
				case env.Word:
					name := ps.Idx.GetWord(method.Index)
					switch data := arg2.(type) {
					case env.String:
						req.Value.(*http.Request).Header.Set(name, data.Value)
						return arg0
					default:
						return MakeArgError(ps, 3, []env.Type{env.StringType}, "https-request//Header!")
					}
				default:
					return MakeArgError(ps, 2, []env.Type{env.WordType}, "https-request//Header!")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "https-request//Header!")
			}
		},
	},

	"https-request//Basic-auth!": {
		Argsn: 3,
		Doc:   "Sets Basic Authentication on a HTTPS request.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch req := arg0.(type) {
			case env.Native:
				switch username := arg1.(type) {
				case env.String:
					switch password := arg2.(type) {
					case env.String:
						req.Value.(*http.Request).SetBasicAuth(username.Value, password.Value)
						return arg0
					default:
						return MakeArgError(ps, 3, []env.Type{env.StringType}, "https-request//Basic-auth!")
					}
				default:
					return MakeArgError(ps, 2, []env.Type{env.StringType}, "https-request//Basic-auth!")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "https-request//Basic-auth!")
			}
		},
	},

	"https-request//Call": {
		Argsn: 1,
		Doc:   "Executes a HTTPS request and returns the response object. Always returns the response regardless of status code (200, 404, 500, etc.) - use Status? to check the code.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch req := arg0.(type) {
			case env.Native:
				client := &http.Client{}
				resp, err := client.Do(req.Value.(*http.Request))

				if err != nil {
					return MakeBuiltinError(ps, err.Error(), "https-request//Call")
				}

				return *env.NewNative(ps.Idx, resp, "https-response")
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "https-request//Call")
			}
		},
	},

	"https-response//Reader": {
		Argsn: 1,
		Doc:   "Gets a reader for the HTTPS response body that can be used with io.Copy.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch resp := arg0.(type) {
			case env.Native:

				return *env.NewNative(ps.Idx, resp.Value.(*http.Response).Body, "reader")
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "https-response//Reader")
			}
		},
	},

	"https-response//Read-body": {
		Argsn: 1,
		Doc:   "Reads the body of a HTTPS response as a string.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch resp := arg0.(type) {
			case env.Native:
				data, err := io.ReadAll(resp.Value.(*http.Response).Body)
				if err != nil {
					return MakeBuiltinError(ps, err.Error(), "https-response//Read-body")
				}
				return *env.NewString(string(data))
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "https-response//Read-body")
			}
		},
	},

	"email//Send": {
		Argsn: 2,
		Doc:   "Sends an email to the specified address.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch to_ := arg0.(type) {
			case env.Email:
				switch msg := arg1.(type) {
				case env.String:
					idx, _ := ps.Idx.GetIndex("user-profile")
					uctx_, _ := ps.Ctx.Get(idx)
					uctx := uctx_.(env.RyeCtx)
					fmt.Println(to_)
					fmt.Println(msg)
					fmt.Println(uctx)

					return *env.NewInteger(1)
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 2, []env.Type{env.StringType}, "email//Send")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.EmailType}, "email//Send")
			}
		},
	},

	"ftp-uri//Open": {
		Argsn: 1,
		Doc:   "Opens a connection to an FTP server.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {

			switch s := arg0.(type) {
			case env.Uri:
				conn, err := ftp.Dial(s.Path)
				if err != nil {
					fmt.Println("Error connecting to FTP server:", err)
					return MakeBuiltinError(ps, "Error connecting to FTP server: "+err.Error(), "ftp-uri//Open")
				}

				if err != nil {
					ps.FailureFlag = true
					return MakeBuiltinError(ps, "Error opening file.", "ftp-uri//Open")
				}
				return *env.NewNative(ps.Idx, conn, "ftp-connection")
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.UriType, env.StringType}, "ftp-uri//Open")
			}
		},
	},

	"ftp-connection//Login": {
		Argsn: 3,
		Doc:   "Logs in to an FTP server connection.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {

			switch s := arg0.(type) {
			case env.Native:
				username, ok := arg1.(env.String)
				if !ok {

					return nil
				}
				pwd, ok := arg2.(env.String)
				if !ok {

					return nil
				}
				err := s.Value.(*ftp.ServerConn).Login(username.Value, pwd.Value)
				if err != nil {

					fmt.Println("Error logging in:", err)
					return nil
				}
				return s
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.UriType, env.StringType}, "ftp-connection//Login")
			}
		},
	},

	"ftp-connection//Retrieve": {
		Argsn: 2,
		Doc:   "Retrieves a file from an FTP server.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {

			switch s := arg0.(type) {
			case env.Native:
				path, ok := arg1.(env.String)
				if !ok {

				}
				resp, err := s.Value.(*ftp.ServerConn).Retr(path.Value)
				if err != nil {
					fmt.Println("Error retrieving:", err)
					return nil
				}
				return *env.NewNative(ps.Idx, resp, "reader")
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.UriType, env.StringType}, "ftp-connection//Retrieve")
			}
		},
	},

	"tail-file": {
		Argsn: 3,
		Doc:   "Tails a file, following it for new content. Used for monitoring log files.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			var filePath string

			switch path := arg0.(type) {
			case env.Uri:
				filePath = path.GetPath()
			case env.String:
				filePath = path.Value
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.UriType, env.StringType}, "tail-file")
			}

			follow := true
			if arg1 != nil {
				switch f := arg1.(type) {
				case env.Boolean:
					follow = f.Value
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 2, []env.Type{env.BooleanType}, "tail-file")
				}
			}

			reopen := true
			if arg2 != nil {
				switch r := arg2.(type) {
				case env.Boolean:
					reopen = r.Value
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 3, []env.Type{env.BooleanType}, "tail-file")
				}
			}

			config := tail.Config{
				Follow: follow,
				ReOpen: reopen,
			}

			t, err := tail.TailFile(filePath, config)
			if err != nil {
				ps.FailureFlag = true
				return MakeBuiltinError(ps, err.Error(), "tail-file")
			}

			return *env.NewNative(ps.Idx, t, "tail-file")
		},
	},

	"tail-file//Read-line": {
		Argsn: 1,
		Doc:   "Reads the next line from a tailed file. Blocks until a line is available.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch t := arg0.(type) {
			case env.Native:
				if ps.Idx.GetWord(t.GetKind()) != "tail-file" {
					ps.FailureFlag = true
					return MakeBuiltinError(ps, "Expected tail-file object", "tail-file//Read-line")
				}

				line, ok := <-t.Value.(*tail.Tail).Lines
				if !ok {

					return *env.NewVoid()
				}

				return *env.NewString(line.Text)
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "tail-file//Read-line")
			}
		},
	},

	"tail-file//Close": {
		Argsn: 1,
		Doc:   "Closes a tailed file, stopping the monitoring.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch t := arg0.(type) {
			case env.Native:
				if ps.Idx.GetWord(t.GetKind()) != "tail-file" {
					ps.FailureFlag = true
					return MakeBuiltinError(ps, "Expected tail-file object", "tail-file//Close")
				}

				err := t.Value.(*tail.Tail).Stop()
				if err != nil {
					ps.FailureFlag = true
					return MakeBuiltinError(ps, err.Error(), "tail-file//Close")
				}

				return *env.NewString("")
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "tail-file//Close")
			}
		},
	},
}
View Source
var Builtins_json = map[string]*env.Builtin{

	"parse-json": {
		Argsn: 1,
		Doc:   "Parses JSON string into Rye values.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch input := arg0.(type) {
			case env.String:
				var m any
				err := json.Unmarshal([]byte(input.Value), &m)
				if err != nil {
					return MakeBuiltinError(ps, "Failed to Unmarshal.", "_parse_json")

				}
				return env.ToRyeValue(m)
			default:
				return MakeArgError(ps, 1, []env.Type{env.StringType}, "_parse_json")
			}
		},
	},

	"parse-json\\lines": {
		Argsn: 1,
		Doc:   "Parses JSON string into Rye values.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch input := arg0.(type) {
			case env.String:
				var vals []any
				decoder := json.NewDecoder(strings.NewReader(input.Value))
				for decoder.More() {
					var m any
					err := decoder.Decode(&m)
					if err != nil {
						return MakeBuiltinError(ps, "Failed to Unmarshal.", "_parse_json\\lines")
					}
					vals = append(vals, env.ToRyeValue(m))
				}
				return *env.NewList(vals)
			default:
				return MakeArgError(ps, 1, []env.Type{env.StringType}, "_parse_json\\lines")
			}
		},
	},

	"to-json": {
		Argsn: 1,
		Doc:   "Converts a Rye value to a JSON string.",
		Fn: func(es *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return *env.NewString(RyeToJSON(arg0))
		},
	},

	"to-json\\lines": {
		Argsn: 1,
		Doc:   "Converts a table to JSON with each row on a separate line.",
		Fn: func(es *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return *env.NewString(RyeToJSONLines(arg0))
		},
	},
}
View Source
var Builtins_mail = map[string]*env.Builtin{

	"reader//Parse-email": {
		Argsn: 1,
		Doc:   "Parses email data from a reader.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch reader := arg0.(type) {
			case env.Native:
				email, err := parsemail.Parse(reader.Value.(io.Reader))
				if err != nil {
					return MakeBuiltinError(ps, err.Error(), "reader//parse-email")
				}
				return *env.NewNative(ps.Idx, email, "parsed-email")
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "reader//parse-email")
			}
		},
	},

	"parsed-email//Subject?": {
		Argsn: 1,
		Doc:   "Gets the subject from a parsed email.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch email := arg0.(type) {
			case env.Native:
				return *env.NewString(email.Value.(parsemail.Email).Subject)
			default:
				return *MakeArgError(ps, 1, []env.Type{env.NativeType}, "parsed-email//Subject?")
			}
		},
	},

	"parsed-email//Message-id?": {
		Argsn: 1,
		Doc:   "Gets the message ID from a parsed email.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch email := arg0.(type) {
			case env.Native:
				return *env.NewString(email.Value.(parsemail.Email).MessageID)
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "parsed-email//message-id?")
			}
		},
	},

	"parsed-email//Html-body?": {
		Argsn: 1,
		Doc:   "Gets the HTML body from a parsed email.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch email := arg0.(type) {
			case env.Native:
				return *env.NewString(email.Value.(parsemail.Email).HTMLBody)
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "parsed-email//html-body?")
			}
		},
	},

	"parsed-email//Text-body?": {
		Argsn: 1,
		Doc:   "Gets the plain text body from a parsed email.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch email := arg0.(type) {
			case env.Native:
				return *env.NewString(email.Value.(parsemail.Email).TextBody)
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "parsed-email//text-body?")
			}
		},
	},

	"parsed-email//Attachments?": {
		Argsn: 1,
		Doc:   "Gets the attachments from a parsed email.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return *env.NewNative(ps.Idx, arg0, "smtpd")
		},
	},

	"parsed-email//Embedded-files?": {
		Argsn: 1,
		Doc:   "Gets the embedded files from a parsed email.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return *env.NewNative(ps.Idx, arg0, "smtpd")
		},
	},
}
View Source
var Builtins_markdown = map[string]*env.Builtin{

	"reader//do-markdown": {
		Argsn: 2,
		Doc:   "Processes Markdown using a streaming approach with section handlers.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			rm, err := load_markdown_Dict(ps, arg1.(env.Block))
			if err != nil {
				ps.FailureFlag = true
				return err
			}
			return do_markdown(ps, arg0, rm)
		},
	},

	"markdown->html": {
		Argsn: 1,
		Doc:   "Converts Markdown text to HTML.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			text, ok := arg0.(env.String)
			if !ok {
				return MakeArgError(ps, 1, []env.Type{env.StringType}, "markdown->html")
			}

			html, err := markdown_to_html(ps, text.Value)
			if err != nil {
				return MakeBuiltinError(ps, err.Error(), "markdown->html")
			}

			return *env.NewString(html)
		},
	},

	"markdown": {
		Argsn: 1,
		Doc:   "Creates a Markdown value from a string.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch text := arg0.(type) {
			case env.String:
				return *env.NewMarkdown(text.Value)
			case env.Markdown:
				return text
			default:
				return MakeArgError(ps, 1, []env.Type{env.StringType, env.MarkdownType}, "markdown")
			}
		},
	},

	"markdown//text": {
		Argsn: 1,
		Doc:   "Gets the raw markdown text from a Markdown value.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			md, ok := arg0.(env.Markdown)
			if !ok {
				return MakeArgError(ps, 1, []env.Type{env.MarkdownType}, "markdown//text")
			}
			return *env.NewString(md.Value)
		},
	},

	"markdown//length": {
		Argsn: 1,
		Doc:   "Gets the length of the markdown text in characters.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			md, ok := arg0.(env.Markdown)
			if !ok {
				return MakeArgError(ps, 1, []env.Type{env.MarkdownType}, "markdown//length")
			}
			return *env.NewInteger(int64(len(md.Value)))
		},
	},

	"markdown//to-html": {
		Argsn: 1,
		Doc:   "Converts a Markdown value to HTML.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			md, ok := arg0.(env.Markdown)
			if !ok {
				return MakeArgError(ps, 1, []env.Type{env.MarkdownType}, "markdown//to-html")
			}

			html, err := markdown_to_html(ps, md.Value)
			if err != nil {
				return MakeBuiltinError(ps, err.Error(), "markdown//to-html")
			}

			return *env.NewString(html)
		},
	},

	"markdown//headings": {
		Argsn: 1,
		Doc:   "Extracts all headings from markdown text as a list of strings.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			md, ok := arg0.(env.Markdown)
			if !ok {
				return MakeArgError(ps, 1, []env.Type{env.MarkdownType}, "markdown//headings")
			}

			headings := extractHeadings(md.Value)
			result := make([]any, len(headings))
			for i, heading := range headings {
				result[i] = heading
			}
			return *env.NewList(result)
		},
	},

	"markdown//paragraphs": {
		Argsn: 1,
		Doc:   "Extracts all paragraphs from markdown text as a list of strings.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			md, ok := arg0.(env.Markdown)
			if !ok {
				return MakeArgError(ps, 1, []env.Type{env.MarkdownType}, "markdown//paragraphs")
			}

			paragraphs := extractParagraphs(md.Value)
			result := make([]any, len(paragraphs))
			for i, paragraph := range paragraphs {
				result[i] = paragraph
			}
			return *env.NewList(result)
		},
	},

	"markdown//links": {
		Argsn: 1,
		Doc:   "Extracts all links from markdown text as a list of dictionaries with 'text' and 'url' keys.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			md, ok := arg0.(env.Markdown)
			if !ok {
				return MakeArgError(ps, 1, []env.Type{env.MarkdownType}, "markdown//links")
			}

			links := extractLinks(md.Value)
			result := make([]any, len(links))
			for i, link := range links {
				linkDict := make(map[string]any)
				linkDict["text"] = link["text"]
				linkDict["url"] = link["url"]
				result[i] = linkDict
			}
			return *env.NewList(result)
		},
	},
}
View Source
var Builtins_match = map[string]*env.Builtin{

	"match-block": {
		Argsn: 2,
		Doc:   "Tries to match and deconstruct a value into multiple values, with support for literal values, type checking, get-words, code evaluation, and nested blocks. First argument can be any value. If it doesn't match, returns failure.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			value := arg0

			// Convert value to a block if it's not already
			var valueBlock env.Block
			switch v := value.(type) {
			case env.Block:
				valueBlock = v
			default:

				valueBlock = env.Block{
					Series: *env.NewTSeries([]env.Object{value}),
				}
			}

			switch pattern := arg1.(type) {
			case env.Block:
				return matchBlock(ps, valueBlock, pattern)
			default:
				return MakeArgError(ps, 2, []env.Type{env.BlockType}, "match-block")
			}
		},
	},

	"match": {
		Argsn: 2,
		Doc:   "Matches a value against a series of pattern/action pairs. Pattern can be a single element or block. Returns the result of the first matching action, or failure if none match.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			value := arg0

			switch patternsBlock := arg1.(type) {
			case env.Block:

				if patternsBlock.Series.Len()%2 != 0 {
					return MakeBuiltinError(ps, "Patterns block must contain an even number of elements (pairs)", "match")
				}

				for i := 0; i < patternsBlock.Series.Len(); i += 2 {
					pattern := patternsBlock.Series.Get(i)
					action := patternsBlock.Series.Get(i + 1)

					actionBlock, actionOk := action.(env.Block)
					if !actionOk {
						return MakeBuiltinError(ps, "Action must be a block", "match")
					}

					oldFailureFlag := ps.FailureFlag
					ps.FailureFlag = false

					matchResult, _ := matchValue(ps, value, pattern, matchMode{0})

					if !ps.FailureFlag {

						ps.FailureFlag = oldFailureFlag

						ser := ps.Ser
						ps.Ser = actionBlock.Series
						EvalBlockInj(ps, value, true)
						ps.Ser = ser
						return ps.Res
					}

					ps.FailureFlag = oldFailureFlag
					_ = matchResult
				}

				ps.FailureFlag = true
				return MakeBuiltinError(ps, "No pattern matched the value", "match")
			default:
				return MakeArgError(ps, 2, []env.Type{env.BlockType}, "match")
			}
		},
	},
}
View Source
var Builtins_math = map[string]*env.Builtin{

	"mod": {
		Argsn: 2,
		Doc:   "Returns the remainder of dividing x by y.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			fa, fb, errPos := assureFloats(arg0, arg1)
			if errPos > 0 {
				return MakeArgError(ps, errPos, []env.Type{env.IntegerType, env.BlockType}, "mod")
			}
			return *env.NewDecimal(math.Mod(fa, fb))
		},
	},

	"pow": {
		Argsn: 2,
		Doc:   "Returns base raised to the power of exponent.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch base := arg0.(type) {
			case env.Complex:
				switch exp := arg1.(type) {
				case env.Complex:
					return *env.NewComplex(cmplx.Pow(base.Value, exp.Value))
				case env.Integer:
					return *env.NewComplex(cmplx.Pow(base.Value, complex(float64(exp.Value), 0)))
				case env.Decimal:
					return *env.NewComplex(cmplx.Pow(base.Value, complex(exp.Value, 0)))
				default:
					return MakeArgError(ps, 2, []env.Type{env.IntegerType, env.DecimalType, env.ComplexType}, "pow")
				}
			case env.Integer:
				switch exp := arg1.(type) {
				case env.Complex:
					return *env.NewComplex(cmplx.Pow(complex(float64(base.Value), 0), exp.Value))
				case env.Integer:
					return *env.NewDecimal(math.Pow(float64(base.Value), float64(exp.Value)))
				case env.Decimal:
					return *env.NewDecimal(math.Pow(float64(base.Value), exp.Value))
				default:
					return MakeArgError(ps, 2, []env.Type{env.IntegerType, env.DecimalType, env.ComplexType}, "pow")
				}
			case env.Decimal:
				switch exp := arg1.(type) {
				case env.Complex:
					return *env.NewComplex(cmplx.Pow(complex(base.Value, 0), exp.Value))
				case env.Integer:
					return *env.NewDecimal(math.Pow(base.Value, float64(exp.Value)))
				case env.Decimal:
					return *env.NewDecimal(math.Pow(base.Value, exp.Value))
				default:
					return MakeArgError(ps, 2, []env.Type{env.IntegerType, env.DecimalType, env.ComplexType}, "pow")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.IntegerType, env.DecimalType, env.ComplexType}, "pow")
			}
		},
	},

	"log2": {
		Argsn: 1,
		Doc:   "Returns the binary logarithm (base-2) of x.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch val := arg0.(type) {
			case env.Integer:
				return *env.NewDecimal(math.Log2(float64(val.Value)))
			case env.Decimal:
				return *env.NewDecimal(math.Log2(val.Value))
			default:
				return MakeArgError(ps, 2, []env.Type{env.IntegerType, env.BlockType}, "log2")
			}
		},
	},

	"log10": {
		Argsn: 1,
		Doc:   "Returns the decimal logarithm (base-10) of x.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch val := arg0.(type) {
			case env.Integer:
				return *env.NewDecimal(math.Log10(float64(val.Value)))
			case env.Decimal:
				return *env.NewDecimal(math.Log10(val.Value))
			default:
				return MakeArgError(ps, 2, []env.Type{env.IntegerType, env.DecimalType}, "log10")
			}
		},
	},

	"log": {
		Argsn: 1,
		Doc:   "Returns the natural logarithm of x.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch val := arg0.(type) {
			case env.Integer:
				if val.Value <= 0 {
					ps.FailureFlag = true
					return MakeBuiltinError(ps, "Can't compute logarithm of zero or negative number.", "log")
				}
				return *env.NewDecimal(math.Log(float64(val.Value)))
			case env.Decimal:
				if val.Value <= 0 {
					ps.FailureFlag = true
					return MakeBuiltinError(ps, "Can't compute logarithm of zero or negative number.", "log")
				}
				return *env.NewDecimal(math.Log(val.Value))
			case env.Complex:
				if val.Value == complex(0, 0) {
					ps.FailureFlag = true
					return MakeBuiltinError(ps, "Can't compute logarithm of zero.", "log")
				}
				return *env.NewComplex(cmplx.Log(val.Value))
			default:
				return MakeArgError(ps, 1, []env.Type{env.IntegerType, env.DecimalType, env.ComplexType}, "log")
			}
		},
	},

	"log1p": {
		Argsn: 1,
		Doc:   "Returns the natural logarithm of 1 plus its argument x.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch val := arg0.(type) {
			case env.Integer:
				return *env.NewDecimal(math.Log1p(float64(val.Value)))
			case env.Decimal:
				return *env.NewDecimal(math.Log1p(val.Value))
			default:
				return MakeArgError(ps, 2, []env.Type{env.IntegerType, env.DecimalType}, "log1p")
			}
		},
	},

	"logb": {
		Argsn: 1,
		Doc:   "Returns the binary exponent of x.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch val := arg0.(type) {
			case env.Integer:
				return *env.NewDecimal(math.Logb(float64(val.Value)))
			case env.Decimal:
				return *env.NewDecimal(math.Logb(val.Value))
			default:
				return MakeArgError(ps, 2, []env.Type{env.IntegerType, env.DecimalType}, "logb")
			}
		},
	},

	"sq": {
		Argsn: 1,
		Doc:   "Returns the square of x.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch val := arg0.(type) {
			case env.Integer:
				return *env.NewDecimal(math.Pow(float64(val.Value), 2.0))
			case env.Decimal:
				return *env.NewDecimal(math.Pow(val.Value, 2.0))
			default:
				return MakeArgError(ps, 2, []env.Type{env.IntegerType, env.BlockType}, "sq")
			}
		},
	},

	"sin": {
		Argsn: 1,
		Doc:   "Returns the sine of the radian argument.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch val := arg0.(type) {
			case env.Integer:
				return *env.NewDecimal(math.Sin(float64(val.Value)))
			case env.Decimal:
				return *env.NewDecimal(math.Sin(val.Value))
			case env.Complex:
				return *env.NewComplex(cmplx.Sin(val.Value))
			default:
				return MakeArgError(ps, 2, []env.Type{env.IntegerType, env.DecimalType, env.ComplexType}, "sin")
			}
		},
	},

	"cos": {
		Argsn: 1,
		Doc:   "Returns the cosine of the radian argument.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch val := arg0.(type) {
			case env.Integer:
				return *env.NewDecimal(math.Cos(float64(val.Value)))
			case env.Decimal:
				return *env.NewDecimal(math.Cos(val.Value))
			case env.Complex:
				return *env.NewComplex(cmplx.Cos(val.Value))
			default:
				return MakeArgError(ps, 2, []env.Type{env.IntegerType, env.DecimalType, env.ComplexType}, "cos")
			}
		},
	},

	"tan": {
		Argsn: 1,
		Doc:   "Returns the tangent of the radian argument.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch val := arg0.(type) {
			case env.Integer:
				return *env.NewDecimal(math.Tan(float64(val.Value)))
			case env.Decimal:
				return *env.NewDecimal(math.Tan(val.Value))
			case env.Complex:
				return *env.NewComplex(cmplx.Tan(val.Value))
			default:
				return MakeArgError(ps, 2, []env.Type{env.IntegerType, env.DecimalType, env.ComplexType}, "tan")
			}
		},
	},

	"sqrt": {
		Argsn: 1,
		Doc:   "Returns the square root of x.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch val := arg0.(type) {
			case env.Integer:
				return *env.NewDecimal(math.Sqrt(float64(val.Value)))
			case env.Decimal:
				return *env.NewDecimal(math.Sqrt(val.Value))
			case env.Complex:
				return *env.NewComplex(cmplx.Sqrt(val.Value))
			default:
				return MakeArgError(ps, 2, []env.Type{env.IntegerType, env.DecimalType, env.ComplexType}, "sqrt")
			}
		},
	},

	"abs": {
		Argsn: 1,
		Doc:   "Returns the absolute value of a number.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch val := arg0.(type) {
			case env.Integer:
				return *env.NewInteger(int64(math.Abs(float64(val.Value))))
			case env.Decimal:
				return *env.NewDecimal(math.Abs(val.Value))
			case env.Complex:
				return *env.NewDecimal(cmplx.Abs(val.Value))
			default:
				return MakeArgError(ps, 2, []env.Type{env.IntegerType, env.DecimalType, env.ComplexType}, "abs")
			}
		},
	},

	"acos": {
		Argsn: 1,
		Doc:   "Returns the arccosine (inverse cosine) in radians.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch val := arg0.(type) {
			case env.Integer:
				if val.Value < -1.0 || val.Value > 1.0 {
					return MakeBuiltinError(ps, "Invalid input: Acos is only defined for -1 <= x <= 1.", "acos")
				}
				return *env.NewDecimal(math.Acos(float64(val.Value)))
			case env.Decimal:
				if val.Value < -1.0 || val.Value > 1.0 {
					return MakeBuiltinError(ps, "Invalid input: Acos is only defined for -1 <= x <= 1.", "acos")
				}
				return *env.NewDecimal(math.Acos(val.Value))
			default:
				return MakeArgError(ps, 2, []env.Type{env.IntegerType, env.DecimalType}, "acos")
			}
		},
	},

	"acosh": {
		Argsn: 1,
		Doc:   "Returns the inverse hyperbolic cosine.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch val := arg0.(type) {
			case env.Integer:
				if val.Value < 1.0 {
					return MakeBuiltinError(ps, " Acosh is only defined for x >= 1.", "acosh")
				}
				return *env.NewDecimal(math.Log(float64(val.Value) + math.Sqrt(float64(val.Value)*float64(val.Value)-1)))
			case env.Decimal:
				if val.Value < 1.0 {
					return MakeBuiltinError(ps, " Acosh is only defined for x >= 1.", "acosh")
				}
				return *env.NewDecimal(math.Log(val.Value + math.Sqrt(val.Value*val.Value-1)))
			default:
				return MakeArgError(ps, 2, []env.Type{env.IntegerType, env.DecimalType}, "acosh")
			}
		},
	},

	"asin": {
		Argsn: 1,
		Doc:   "Returns the arcsine (inverse sine) in radians.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch val := arg0.(type) {
			case env.Integer:
				if val.Value < -1.0 || val.Value > 1.0 {
					return MakeBuiltinError(ps, "Invalid input: Asin is only defined for -1 <= x <= 1.", "asin")
				}
				return *env.NewDecimal(math.Asin(float64(val.Value)))
			case env.Decimal:
				if val.Value < -1.0 || val.Value > 1.0 {
					return MakeBuiltinError(ps, "Invalid input: Asin is only defined for -1 <= x <= 1.", "asin")
				}
				return *env.NewDecimal(math.Asin(val.Value))
			default:
				return MakeArgError(ps, 2, []env.Type{env.IntegerType, env.DecimalType}, "asin")
			}
		},
	},

	"asinh": {
		Argsn: 1,
		Doc:   "Returns the inverse hyperbolic sine.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch val := arg0.(type) {
			case env.Integer:
				return *env.NewDecimal(math.Log(float64(val.Value) + math.Sqrt(float64(val.Value)*float64(val.Value)+1)))
			case env.Decimal:
				return *env.NewDecimal(math.Log(val.Value + math.Sqrt(val.Value*val.Value+1)))
			default:
				return MakeArgError(ps, 2, []env.Type{env.IntegerType, env.DecimalType}, "asinh")
			}
		},
	},

	"atan": {
		Argsn: 1,
		Doc:   "Returns the arctangent (inverse tangent) in radians.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch val := arg0.(type) {
			case env.Integer:
				return *env.NewDecimal(math.Atan(float64(val.Value)))
			case env.Decimal:
				return *env.NewDecimal(math.Atan(val.Value))
			default:
				return MakeArgError(ps, 2, []env.Type{env.IntegerType, env.DecimalType}, "atan")
			}
		},
	},

	"atan2": {
		Argsn: 2,
		Doc:   "Returns the arc tangent of y/x, using the signs of the two to determine the quadrant of the return value.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch val := arg0.(type) {
			case env.Integer:
				switch val2 := arg1.(type) {
				case env.Integer:
					return *env.NewDecimal(math.Atan2(float64(val.Value), float64(val2.Value)))
				case env.Decimal:
					return *env.NewDecimal(math.Atan2(float64(val.Value), val2.Value))
				default:
					return MakeArgError(ps, 2, []env.Type{env.IntegerType, env.DecimalType}, "atan2")
				}
			case env.Decimal:
				switch val2 := arg1.(type) {
				case env.Integer:
					return *env.NewDecimal(math.Atan2(val.Value, float64(val2.Value)))
				case env.Decimal:
					return *env.NewDecimal(math.Atan2(val.Value, val2.Value))
				default:
					return MakeArgError(ps, 2, []env.Type{env.IntegerType, env.DecimalType}, "atan2")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.IntegerType, env.DecimalType}, "atan2")
			}
		},
	},

	"atanh": {
		Argsn: 1,
		Doc:   "Returns the inverse hyperbolic tangent.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch val := arg0.(type) {
			case env.Integer:
				return *env.NewDecimal(math.Atanh(float64(val.Value)))
			case env.Decimal:
				return *env.NewDecimal(math.Atanh(val.Value))
			default:
				return MakeArgError(ps, 1, []env.Type{env.IntegerType, env.DecimalType}, "atanh")
			}
		},
	},

	"ceil": {
		Argsn: 1,
		Doc:   "Returns the least integer value greater than or equal to x.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch val := arg0.(type) {
			case env.Integer:
				return *env.NewDecimal(float64(val.Value))
			case env.Decimal:
				return *env.NewDecimal(math.Ceil(val.Value))
			default:
				return MakeArgError(ps, 1, []env.Type{env.IntegerType, env.DecimalType}, "ceil")
			}
		},
	},

	"cbrt": {
		Argsn: 1,
		Doc:   "Returns the cube root of x.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch val := arg0.(type) {
			case env.Integer:
				return *env.NewDecimal(math.Cbrt(float64(val.Value)))
			case env.Decimal:
				return *env.NewDecimal(math.Cbrt(val.Value))
			default:
				return MakeArgError(ps, 1, []env.Type{env.IntegerType, env.DecimalType}, "cbrt")
			}
		},
	},

	"copysign": {
		Argsn: 2,
		Doc:   "Returns a value with the magnitude of x and the sign of y.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch val := arg0.(type) {
			case env.Integer:
				switch val2 := arg1.(type) {
				case env.Integer:
					return *env.NewDecimal(math.Copysign(float64(val.Value), float64(val2.Value)))
				case env.Decimal:
					return *env.NewDecimal(math.Copysign(float64(val.Value), val2.Value))
				default:
					return MakeArgError(ps, 2, []env.Type{env.IntegerType, env.DecimalType}, "copysign")
				}
			case env.Decimal:
				switch val2 := arg1.(type) {
				case env.Integer:
					return *env.NewDecimal(math.Copysign(val.Value, float64(val2.Value)))
				case env.Decimal:
					return *env.NewDecimal(math.Copysign(val.Value, val2.Value))
				default:
					return MakeArgError(ps, 2, []env.Type{env.IntegerType, env.DecimalType}, "copysign")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.IntegerType, env.DecimalType}, "copysign")
			}
		},
	},

	"dim": {
		Argsn: 2,
		Doc:   "Returns the maximum of x-y or 0.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch val := arg0.(type) {
			case env.Integer:
				switch val2 := arg1.(type) {
				case env.Integer:
					return *env.NewDecimal(util.GetDimValue(float64(val.Value), float64(val2.Value)))
				case env.Decimal:
					return *env.NewDecimal(util.GetDimValue(float64(val.Value), val2.Value))
				default:
					return MakeArgError(ps, 2, []env.Type{env.IntegerType, env.DecimalType}, "dim")
				}
			case env.Decimal:
				switch val2 := arg1.(type) {
				case env.Integer:
					return *env.NewDecimal(util.GetDimValue(val.Value, float64(val2.Value)))
				case env.Decimal:
					return *env.NewDecimal(util.GetDimValue(val.Value, val2.Value))
				default:
					return MakeArgError(ps, 2, []env.Type{env.IntegerType, env.DecimalType}, "dim")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.IntegerType, env.DecimalType}, "dim")
			}
		},
	},

	"round\\to": {
		Argsn: 2,
		Doc:   "Rounds a decimal to the specified number of decimal places.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch val := arg0.(type) {
			case env.Decimal:
				switch precision := arg1.(type) {
				case env.Integer:
					ratio := math.Pow(10, float64(precision.Value))
					return *env.NewDecimal(math.Round(val.Value*ratio) / ratio)
				default:
					return MakeArgError(ps, 2, []env.Type{env.IntegerType, env.DecimalType}, "round\\to")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.DecimalType}, "round\\to")
			}
		},
	},

	"round": {
		Argsn: 1,
		Doc:   "Rounds a decimal to the nearest integer.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch val := arg0.(type) {
			case env.Decimal:
				return *env.NewDecimal(math.Round(val.Value))
			default:
				return MakeArgError(ps, 1, []env.Type{env.DecimalType}, "round\\to")
			}
		},
	},

	"roundtoeven": {
		Argsn: 1,
		Doc:   "Returns the nearest integer, rounding ties to even.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch val := arg0.(type) {
			case env.Decimal:
				return *env.NewDecimal(math.RoundToEven(val.Value))
			case env.Integer:
				return *env.NewDecimal(math.RoundToEven(float64(val.Value)))
			default:
				return MakeArgError(ps, 1, []env.Type{env.DecimalType, env.IntegerType}, "roundtoeven")
			}
		},
	},

	"erf": {
		Argsn: 1,
		Doc:   "Returns the error function of value.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch val := arg0.(type) {
			case env.Integer:
				return *env.NewDecimal(math.Erf(float64(val.Value)))
			case env.Decimal:
				return *env.NewDecimal(math.Erf(val.Value))
			default:
				return MakeArgError(ps, 1, []env.Type{env.IntegerType, env.DecimalType}, "erf")
			}
		},
	},

	"erfc": {
		Argsn: 1,
		Doc:   "Returns the complementary error function of value.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch val := arg0.(type) {
			case env.Integer:
				return *env.NewDecimal(math.Erfc(float64(val.Value)))
			case env.Decimal:
				return *env.NewDecimal(math.Erfc(val.Value))
			default:
				return MakeArgError(ps, 1, []env.Type{env.IntegerType, env.DecimalType}, "erfc")
			}
		},
	},

	"erfcinv": {
		Argsn: 1,
		Doc:   "Returns the inverse of erfc(x) function.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch val := arg0.(type) {
			case env.Integer:
				return *env.NewDecimal(math.Erfcinv(float64(val.Value)))
			case env.Decimal:
				return *env.NewDecimal(math.Erfcinv(val.Value))
			default:
				return MakeArgError(ps, 1, []env.Type{env.IntegerType, env.DecimalType}, "erfcinv")
			}
		},
	},

	"erfinv": {
		Argsn: 1,
		Doc:   "Returns the inverse error function of value.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch val := arg0.(type) {
			case env.Integer:
				return *env.NewDecimal(math.Erfinv(float64(val.Value)))
			case env.Decimal:
				return *env.NewDecimal(math.Erfinv(val.Value))
			default:
				return MakeArgError(ps, 1, []env.Type{env.IntegerType, env.DecimalType}, "erfinv")
			}
		},
	},

	"exp": {
		Argsn: 1,
		Doc:   "Returns e**x, the base-e exponential of x.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch val := arg0.(type) {
			case env.Integer:
				return *env.NewDecimal(math.Exp(float64(val.Value)))
			case env.Decimal:
				return *env.NewDecimal(math.Exp(val.Value))
			case env.Complex:
				return *env.NewComplex(cmplx.Exp(val.Value))
			default:
				return MakeArgError(ps, 1, []env.Type{env.IntegerType, env.DecimalType, env.ComplexType}, "exp")
			}
		},
	},

	"exp2": {
		Argsn: 1,
		Doc:   "Returns 2**x, the base-2 exponential of x.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch val := arg0.(type) {
			case env.Integer:
				return *env.NewDecimal(math.Exp2(float64(val.Value)))
			case env.Decimal:
				return *env.NewDecimal(math.Exp2(val.Value))
			default:
				return MakeArgError(ps, 1, []env.Type{env.IntegerType, env.DecimalType}, "exp2")
			}
		},
	},

	"expm1": {
		Argsn: 1,
		Doc:   "Returns e**x - 1, the base-e exponential of x minus 1. It is more accurate than exp(x) - 1 when x is near zero.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch val := arg0.(type) {
			case env.Integer:
				return *env.NewDecimal(math.Expm1(float64(val.Value)))
			case env.Decimal:
				return *env.NewDecimal(math.Expm1(val.Value))
			default:
				return MakeArgError(ps, 1, []env.Type{env.IntegerType, env.DecimalType}, "expm1")
			}
		},
	},

	"fma": {
		Argsn: 3,
		Doc:   "Returns x * y + z, computed with only one rounding. (That is, FMA returns the fused multiply-add of x, y, and z.)",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch val1 := arg0.(type) {
			case env.Integer:
				switch val2 := arg1.(type) {
				case env.Integer:
					switch val3 := arg2.(type) {
					case env.Integer:
						return *env.NewDecimal(math.FMA(float64(val1.Value), float64(val2.Value), float64(val3.Value)))
					case env.Decimal:
						return *env.NewDecimal(math.FMA(float64(val1.Value), float64(val2.Value), val3.Value))
					default:
						return MakeArgError(ps, 3, []env.Type{env.IntegerType, env.DecimalType}, "fma")
					}
				case env.Decimal:
					switch val3 := arg2.(type) {
					case env.Integer:
						return *env.NewDecimal(math.FMA(float64(val1.Value), val2.Value, float64(val3.Value)))
					case env.Decimal:
						return *env.NewDecimal(math.FMA(float64(val1.Value), val2.Value, val3.Value))
					default:
						return MakeArgError(ps, 3, []env.Type{env.IntegerType, env.DecimalType}, "fma")
					}
				default:
					return MakeArgError(ps, 2, []env.Type{env.IntegerType, env.DecimalType}, "fma")
				}
			case env.Decimal:
				switch val2 := arg1.(type) {
				case env.Integer:
					switch val3 := arg2.(type) {
					case env.Integer:
						return *env.NewDecimal(math.FMA(val1.Value, float64(val2.Value), float64(val3.Value)))
					case env.Decimal:
						return *env.NewDecimal(math.FMA(val1.Value, float64(val2.Value), val3.Value))
					default:
						return MakeArgError(ps, 3, []env.Type{env.IntegerType, env.DecimalType}, "fma")
					}
				case env.Decimal:
					switch val3 := arg2.(type) {
					case env.Integer:
						return *env.NewDecimal(math.FMA(val1.Value, val2.Value, float64(val3.Value)))
					case env.Decimal:
						return *env.NewDecimal(math.FMA(val1.Value, val2.Value, val3.Value))
					default:
						return MakeArgError(ps, 3, []env.Type{env.IntegerType, env.DecimalType}, "fma")
					}
				default:
					return MakeArgError(ps, 2, []env.Type{env.IntegerType, env.DecimalType}, "fma")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.IntegerType, env.DecimalType}, "fma")
			}
		},
	},

	"j0": {
		Argsn: 1,
		Doc:   "Returns the order-zero Bessel function of the first kind.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch val := arg0.(type) {
			case env.Integer:
				return *env.NewDecimal(math.J0(float64(val.Value)))
			case env.Decimal:
				return *env.NewDecimal(math.J0(val.Value))
			default:
				return MakeArgError(ps, 1, []env.Type{env.IntegerType, env.DecimalType}, "j0")
			}
		},
	},

	"j1": {
		Argsn: 1,
		Doc:   "Returns the order-one Bessel function of the first kind.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch val := arg0.(type) {
			case env.Integer:
				return *env.NewDecimal(math.J1(float64(val.Value)))
			case env.Decimal:
				return *env.NewDecimal(math.J1(val.Value))
			default:
				return MakeArgError(ps, 1, []env.Type{env.IntegerType, env.DecimalType}, "j1")
			}
		},
	},

	"y0": {
		Argsn: 1,
		Doc:   "Returns the order-zero Bessel function of the second kind.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch val := arg0.(type) {
			case env.Integer:
				return *env.NewDecimal(math.Y0(float64(val.Value)))
			case env.Decimal:
				return *env.NewDecimal(math.Y0(val.Value))
			default:
				return MakeArgError(ps, 1, []env.Type{env.IntegerType, env.DecimalType}, "y0")
			}
		},
	},

	"y1": {
		Argsn: 1,
		Doc:   "Returns the order-one Bessel function of the second kind.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch val := arg0.(type) {
			case env.Integer:
				return *env.NewDecimal(math.Y1(float64(val.Value)))
			case env.Decimal:
				return *env.NewDecimal(math.Y1(val.Value))
			default:
				return MakeArgError(ps, 1, []env.Type{env.IntegerType, env.DecimalType}, "y1")
			}
		},
	},

	"yn": {
		Argsn: 2,
		Doc:   "Returns the order-n Bessel function of the second kind.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch v1 := arg0.(type) {
			case env.Integer:
				switch v2 := arg1.(type) {
				case env.Integer:
					return *env.NewDecimal(math.Yn(int(v1.Value), float64(v2.Value)))
				case env.Decimal:
					return *env.NewDecimal(math.Yn(int(v1.Value), v2.Value))
				default:
					return MakeArgError(ps, 2, []env.Type{env.IntegerType, env.DecimalType}, "yn")
				}
			case env.Decimal:
				switch v2 := arg1.(type) {
				case env.Integer:
					return *env.NewDecimal(math.Yn(int(v1.Value), float64(v2.Value)))
				case env.Decimal:
					return *env.NewDecimal(math.Yn(int(v1.Value), v2.Value))
				default:
					return MakeArgError(ps, 2, []env.Type{env.IntegerType, env.DecimalType}, "yn")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.IntegerType, env.DecimalType}, "yn")
			}
		},
	},

	"jn": {
		Argsn: 2,
		Doc:   "Returns the order-n Bessel function of the first kind.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch v1 := arg0.(type) {
			case env.Integer:
				switch v2 := arg1.(type) {
				case env.Integer:
					return *env.NewDecimal(math.Jn(int(v1.Value), float64(v2.Value)))
				case env.Decimal:
					return *env.NewDecimal(math.Jn(int(v1.Value), v2.Value))
				default:
					return MakeArgError(ps, 2, []env.Type{env.IntegerType, env.DecimalType}, "jn")
				}
			case env.Decimal:
				switch v2 := arg1.(type) {
				case env.Integer:
					return *env.NewDecimal(math.Jn(int(v1.Value), float64(v2.Value)))
				case env.Decimal:
					return *env.NewDecimal(math.Jn(int(v1.Value), v2.Value))
				default:
					return MakeArgError(ps, 2, []env.Type{env.IntegerType, env.DecimalType}, "jn")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.IntegerType, env.DecimalType}, "jn")
			}
		},
	},

	"trunc": {
		Argsn: 1,
		Doc:   "Returns the integer value of input.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch val := arg0.(type) {
			case env.Integer:
				return *env.NewDecimal(float64(val.Value))
			case env.Decimal:
				return *env.NewDecimal(math.Trunc(val.Value))
			default:
				return MakeArgError(ps, 1, []env.Type{env.IntegerType, env.DecimalType}, "trunc")
			}
		},
	},

	"pi": {
		Argsn: 0,
		Doc:   "Returns the mathematical constant π (pi).",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return *env.NewDecimal(float64(math.Pi))
		},
	},

	"deg->rad": {
		Argsn: 1,
		Doc:   "Converts degrees to radians.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			var fa float64
			switch a := arg0.(type) {
			case env.Decimal:
				fa = a.Value
			case env.Integer:
				fa = float64(a.Value)
			default:
				return MakeArgError(ps, 1, []env.Type{env.IntegerType, env.DecimalType}, "deg->rad")
			}
			return *env.NewDecimal(fa * float64(math.Pi) / 180.0)
		},
	},

	"is-near": {
		Argsn: 2,
		Doc:   "Returns true if two decimals are close.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			fa, fb, errPos := assureFloats(arg0, arg1)
			if errPos > 0 {
				return MakeArgError(ps, errPos, []env.Type{env.IntegerType, env.BlockType}, "is-near")
			}
			const epsilon = 0.0000000000001 // math.SmallestNonzeroFloat64
			if math.Abs(fa-fb) <= (epsilon) {
				return env.NewBoolean(true)
			} else {
				return env.NewBoolean(false)
			}
		},
	},

	"near-zero": {
		Argsn: 1,
		Doc:   "Returns true if a decimal is close to zero.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			var fa float64
			switch a := arg0.(type) {
			case env.Decimal:
				fa = a.Value
			case env.Integer:
				fa = float64(a.Value)
			default:
				return MakeArgError(ps, 1, []env.Type{env.IntegerType, env.BlockType}, "near-zero")
			}
			// const epsilon = math.SmallestNonzeroFloat64
			const epsilon = 0.0000000000001 // math.SmallestNonzeroFloat64
			if math.Abs(fa) <= epsilon {
				return env.NewBoolean(true)
			} else {
				return env.NewBoolean(false)
			}
		},
	},

	"is-prime": {
		Argsn: 1,
		Doc:   "Returns true if the integer is a prime number.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch val := arg0.(type) {
			case env.Integer:
				if val.Value <= 1 {
					return *env.NewBoolean(false)
				}
				if primes.IsPrime(int(val.Value)) {
					return *env.NewBoolean(true)
				} else {
					return *env.NewBoolean(false)
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.IntegerType}, "is-prime")
			}
		},
	},

	"to-eyr": {
		Argsn: 1,
		Doc:   "Converts math dialect to Eyr dialect.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return DialectMath(ps, arg0)
		},
	},

	"calc": {
		Argsn: 1,
		Doc:   "Evaluates expressions in math dialect.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			res := DialectMath(ps, arg0)
			switch block := res.(type) {
			case env.Block:

				ps.ResetStack()
				ser := ps.Ser
				ps.Ser = block.Series
				Eyr_EvalBlock(ps, false)
				ps.Ser = ser
				return ps.Res
			default:
				return res
			}
		},
	},

	"gcd": {
		Argsn: 2,
		Doc:   "Returns the greatest common divisor of two integers using Euclidean algorithm.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch val1 := arg0.(type) {
			case env.Integer:
				switch val2 := arg1.(type) {
				case env.Integer:
					a := val1.Value
					b := val2.Value

					if a < 0 {
						a = -a
					}
					if b < 0 {
						b = -b
					}

					for b != 0 {
						temp := b
						b = a % b
						a = temp
					}

					return *env.NewInteger(a)
				default:
					return MakeArgError(ps, 2, []env.Type{env.IntegerType}, "gcd")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.IntegerType}, "gcd")
			}
		},
	},

	"outer-product": {
		Argsn: 2,
		Doc:   "Computes the outer product of two vectors (blocks), returning a matrix (block of blocks) where each element [i,j] = a[i] * b[j]. Similar to numpy.outer().",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch vec1 := arg0.(type) {
			case env.Block:
				switch vec2 := arg1.(type) {
				case env.Block:

					result := make([]env.Object, vec1.Series.Len())

					for i := 0; i < vec1.Series.Len(); i++ {

						val1 := vec1.Series.Get(i)
						var f1 float64
						var isDecimal1 bool

						switch v1 := val1.(type) {
						case env.Integer:
							f1 = float64(v1.Value)
							isDecimal1 = false
						case env.Decimal:
							f1 = v1.Value
							isDecimal1 = true
						default:
							return MakeBuiltinError(ps, fmt.Sprintf("Element at position %d in first block must be integer or decimal", i), "outer-product")
						}

						row := make([]env.Object, vec2.Series.Len())

						for j := 0; j < vec2.Series.Len(); j++ {

							val2 := vec2.Series.Get(j)
							var f2 float64
							var isDecimal2 bool

							switch v2 := val2.(type) {
							case env.Integer:
								f2 = float64(v2.Value)
								isDecimal2 = false
							case env.Decimal:
								f2 = v2.Value
								isDecimal2 = true
							default:
								return MakeBuiltinError(ps, fmt.Sprintf("Element at position %d in second block must be integer or decimal", j), "outer-product")
							}

							product := f1 * f2

							if isDecimal1 || isDecimal2 {
								row[j] = *env.NewDecimal(product)
							} else {
								row[j] = *env.NewInteger(int64(product))
							}
						}

						result[i] = *env.NewBlock(*env.NewTSeries(row))
					}

					return *env.NewBlock(*env.NewTSeries(result))
				default:
					return MakeArgError(ps, 2, []env.Type{env.BlockType}, "outer-product")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.BlockType}, "outer-product")
			}
		},
	},
}
View Source
var Builtins_mcp = map[string]*env.Builtin{

	"mcp-server//Create": {
		Argsn: 2,
		Doc:   "Creates a new MCP server with the given name and version.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch name := arg0.(type) {
			case env.String:
				switch version := arg1.(type) {
				case env.String:
					mcpServerMutex.Lock()
					defer mcpServerMutex.Unlock()

					serverInfo := struct {
						Name    string
						Version string
					}{
						Name:    name.Value,
						Version: version.Value,
					}

					return *env.NewNative(ps.Idx, serverInfo, "Rye-mcp-server")
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 2, []env.Type{env.StringType}, "mcp-server//create")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.StringType}, "mcp-server//create")
			}
		},
	},

	"mcp//Create-resource": {
		Argsn: 3,
		Doc:   "Creates a new MCP resource with the given URI, name, and MIME type.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch uri := arg0.(type) {
			case env.String:
				switch name := arg1.(type) {
				case env.String:
					switch mimeType := arg2.(type) {
					case env.String:

						resourceInfo := struct {
							URI      string
							Name     string
							MIMEType string
						}{
							URI:      uri.Value,
							Name:     name.Value,
							MIMEType: mimeType.Value,
						}

						return *env.NewNative(ps.Idx, resourceInfo, "Rye-mcp-resource")
					default:
						ps.FailureFlag = true
						return MakeArgError(ps, 3, []env.Type{env.StringType}, "mcp-resource//create")
					}
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 2, []env.Type{env.StringType}, "mcp-resource//create")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.StringType}, "mcp-resource//create")
			}
		},
	},

	"mcp//Create-tool": {
		Argsn: 2,
		Doc:   "Creates a new MCP tool with the given name and description.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch name := arg0.(type) {
			case env.String:
				switch desc := arg1.(type) {
				case env.String:

					toolInfo := struct {
						Name        string
						Description string
					}{
						Name:        name.Value,
						Description: desc.Value,
					}

					return *env.NewNative(ps.Idx, toolInfo, "Rye-mcp-tool")
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 2, []env.Type{env.StringType}, "mcp-tool//create")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.StringType}, "mcp-tool//create")
			}
		},
	},

	"mcp//Create-prompt": {
		Argsn: 2,
		Doc:   "Creates a new MCP prompt with the given name and description.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch name := arg0.(type) {
			case env.String:
				switch desc := arg1.(type) {
				case env.String:

					promptInfo := struct {
						Name        string
						Description string
					}{
						Name:        name.Value,
						Description: desc.Value,
					}

					return *env.NewNative(ps.Idx, promptInfo, "Rye-mcp-prompt")
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 2, []env.Type{env.StringType}, "mcp-prompt//create")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.StringType}, "mcp-prompt//create")
			}
		},
	},

	"mcp//Protocol-version": {
		Argsn: 0,
		Doc:   "Returns the latest MCP protocol version.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return env.String{Value: "2024-11-05"}
		},
	},

	"Rye-mcp-server//Get-name": {
		Argsn: 1,
		Doc:   "Gets the name of the MCP server.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch srv := arg0.(type) {
			case env.Native:
				if srv.Type() != env.NativeType {
					ps.FailureFlag = true
					return MakeBuiltinError(ps, "Expected native type", "Rye-mcp-server//get-name")
				}

				serverInfo, ok := srv.Value.(struct {
					Name    string
					Version string
				})
				if !ok {
					ps.FailureFlag = true
					return MakeBuiltinError(ps, "Failed to cast to server info", "Rye-mcp-server//get-name")
				}

				return env.String{Value: serverInfo.Name}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Rye-mcp-server//get-name")
			}
		},
	},

	"Rye-mcp-server//Get-version": {
		Argsn: 1,
		Doc:   "Gets the version of the MCP server.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch srv := arg0.(type) {
			case env.Native:
				if srv.Type() != env.NativeType {
					ps.FailureFlag = true
					return MakeBuiltinError(ps, "Expected native type", "Rye-mcp-server//get-version")
				}

				serverInfo, ok := srv.Value.(struct {
					Name    string
					Version string
				})
				if !ok {
					ps.FailureFlag = true
					return MakeBuiltinError(ps, "Failed to cast to server info", "Rye-mcp-server//get-version")
				}

				return env.String{Value: serverInfo.Version}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Rye-mcp-server//get-version")
			}
		},
	},

	"Rye-mcp-resource//Get-uri": {
		Argsn: 1,
		Doc:   "Gets the URI of the MCP resource.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch res := arg0.(type) {
			case env.Native:
				if res.Type() != env.NativeType {
					ps.FailureFlag = true
					return MakeBuiltinError(ps, "Expected native type", "Rye-mcp-resource//get-uri")
				}

				resourceInfo, ok := res.Value.(struct {
					URI      string
					Name     string
					MIMEType string
				})
				if !ok {
					ps.FailureFlag = true
					return MakeBuiltinError(ps, "Failed to cast to resource info", "Rye-mcp-resource//get-uri")
				}

				return env.String{Value: resourceInfo.URI}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Rye-mcp-resource//get-uri")
			}
		},
	},

	"Rye-mcp-resource//Get-name": {
		Argsn: 1,
		Doc:   "Gets the name of the MCP resource.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch res := arg0.(type) {
			case env.Native:
				if res.Type() != env.NativeType {
					ps.FailureFlag = true
					return MakeBuiltinError(ps, "Expected native type", "Rye-mcp-resource//get-name")
				}

				resourceInfo, ok := res.Value.(struct {
					URI      string
					Name     string
					MIMEType string
				})
				if !ok {
					ps.FailureFlag = true
					return MakeBuiltinError(ps, "Failed to cast to resource info", "Rye-mcp-resource//get-name")
				}

				return env.String{Value: resourceInfo.Name}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Rye-mcp-resource//get-name")
			}
		},
	},

	"Rye-mcp-resource//Get-mime-type": {
		Argsn: 1,
		Doc:   "Gets the MIME type of the MCP resource.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch res := arg0.(type) {
			case env.Native:
				if res.Type() != env.NativeType {
					ps.FailureFlag = true
					return MakeBuiltinError(ps, "Expected native type", "Rye-mcp-resource//get-mime-type")
				}

				resourceInfo, ok := res.Value.(struct {
					URI      string
					Name     string
					MIMEType string
				})
				if !ok {
					ps.FailureFlag = true
					return MakeBuiltinError(ps, "Failed to cast to resource info", "Rye-mcp-resource//get-mime-type")
				}

				return env.String{Value: resourceInfo.MIMEType}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Rye-mcp-resource//get-mime-type")
			}
		},
	},

	"Rye-mcp-tool//Get-name": {
		Argsn: 1,
		Doc:   "Gets the name of the MCP tool.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch tool := arg0.(type) {
			case env.Native:
				if tool.Type() != env.NativeType {
					ps.FailureFlag = true
					return MakeBuiltinError(ps, "Expected native type", "Rye-mcp-tool//get-name")
				}

				toolInfo, ok := tool.Value.(struct {
					Name        string
					Description string
				})
				if !ok {
					ps.FailureFlag = true
					return MakeBuiltinError(ps, "Failed to cast to tool info", "Rye-mcp-tool//get-name")
				}

				return env.String{Value: toolInfo.Name}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Rye-mcp-tool//get-name")
			}
		},
	},

	"Rye-mcp-tool//Get-description": {
		Argsn: 1,
		Doc:   "Gets the description of the MCP tool.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch tool := arg0.(type) {
			case env.Native:
				if tool.Type() != env.NativeType {
					ps.FailureFlag = true
					return MakeBuiltinError(ps, "Expected native type", "Rye-mcp-tool//get-description")
				}

				toolInfo, ok := tool.Value.(struct {
					Name        string
					Description string
				})
				if !ok {
					ps.FailureFlag = true
					return MakeBuiltinError(ps, "Failed to cast to tool info", "Rye-mcp-tool//get-description")
				}

				return env.String{Value: toolInfo.Description}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Rye-mcp-tool//get-description")
			}
		},
	},

	"Rye-mcp-prompt//Get-name": {
		Argsn: 1,
		Doc:   "Gets the name of the MCP prompt.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch prompt := arg0.(type) {
			case env.Native:
				if prompt.Type() != env.NativeType {
					ps.FailureFlag = true
					return MakeBuiltinError(ps, "Expected native type", "Rye-mcp-prompt//get-name")
				}

				promptInfo, ok := prompt.Value.(struct {
					Name        string
					Description string
				})
				if !ok {
					ps.FailureFlag = true
					return MakeBuiltinError(ps, "Failed to cast to prompt info", "Rye-mcp-prompt//get-name")
				}

				return env.String{Value: promptInfo.Name}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Rye-mcp-prompt//get-name")
			}
		},
	},

	"Rye-mcp-prompt//Get-description": {
		Argsn: 1,
		Doc:   "Gets the description of the MCP prompt.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch prompt := arg0.(type) {
			case env.Native:
				if prompt.Type() != env.NativeType {
					ps.FailureFlag = true
					return MakeBuiltinError(ps, "Expected native type", "Rye-mcp-prompt//get-description")
				}

				promptInfo, ok := prompt.Value.(struct {
					Name        string
					Description string
				})
				if !ok {
					ps.FailureFlag = true
					return MakeBuiltinError(ps, "Failed to cast to prompt info", "Rye-mcp-prompt//get-description")
				}

				return env.String{Value: promptInfo.Description}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Rye-mcp-prompt//get-description")
			}
		},
	},
}
View Source
var Builtins_mqtt = map[string]*env.Builtin{

	"mqtt-uri//Open": {
		Argsn: 1,
		Doc:   "Opens a connection to an MQTT broker.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch uri := arg0.(type) {
			case env.Uri:

				scheme := ps.Idx.GetWord(uri.Scheme.Index)
				if scheme != "mqtt" && scheme != "mqtts" {
					ps.FailureFlag = true
					return MakeBuiltinError(ps, "URI scheme must be 'mqtt' or 'mqtts'", "mqtt-uri//Open")
				}

				// Construct broker URL
				var brokerURL string
				if scheme == "mqtts" {
					brokerURL = "ssl://" + uri.Path
				} else {
					brokerURL = "tcp://" + uri.Path
				}

				clientID := "mqtt-client"
				if len(uri.Path) > 0 {

					parts := strings.Split(uri.Path, "/")
					if len(parts) > 1 && parts[1] != "" {
						clientID = parts[1]

						brokerURL = strings.Replace(brokerURL, "/"+clientID, "", 1)
					}
				}

				opts := mqtt.NewClientOptions()
				opts.AddBroker(brokerURL)
				opts.SetClientID(clientID)
				opts.SetDefaultPublishHandler(func(client mqtt.Client, msg mqtt.Message) {

				})

				client := mqtt.NewClient(opts)
				if token := client.Connect(); token.Wait() && token.Error() != nil {
					ps.FailureFlag = true
					return MakeBuiltinError(ps, fmt.Sprintf("Failed to connect to MQTT broker: %v", token.Error()), "mqtt-uri//Open")
				}

				return *env.NewNative(ps.Idx, client, "mqtt-client")
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.UriType}, "mqtt-uri//Open")
			}
		},
	},

	"mqtt-client//Disconnect": {
		Argsn: 1,
		Doc:   "Disconnects from the MQTT broker.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch client := arg0.(type) {
			case env.Native:
				mqttClient := client.Value.(mqtt.Client)
				mqttClient.Disconnect(250)
				return *env.NewInteger(1)
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "mqtt-client//Disconnect")
			}
		},
	},

	"mqtt-client//Publish": {
		Argsn: 5,
		Doc:   "Publishes a message to an MQTT topic with specified QoS and retain flag.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch client := arg0.(type) {
			case env.Native:
				switch topic := arg1.(type) {
				case env.String:
					switch payload := arg2.(type) {
					case env.String:
						switch qos := arg3.(type) {
						case env.Integer:
							switch retain := arg4.(type) {
							case env.Integer:
								mqttClient := client.Value.(mqtt.Client)
								retainBool := retain.Value != 0

								if qos.Value < 0 || qos.Value > 2 {
									ps.FailureFlag = true
									return MakeBuiltinError(ps, "QoS must be 0, 1, or 2", "mqtt-client//Publish")
								}

								token := mqttClient.Publish(topic.Value, byte(qos.Value), retainBool, payload.Value)
								if token.Wait() && token.Error() != nil {
									ps.FailureFlag = true
									return MakeBuiltinError(ps, fmt.Sprintf("Failed to publish message: %v", token.Error()), "mqtt-client//Publish")
								}

								return *env.NewInteger(1)
							default:
								ps.FailureFlag = true
								return MakeArgError(ps, 5, []env.Type{env.IntegerType}, "mqtt-client//Publish")
							}
						default:
							ps.FailureFlag = true
							return MakeArgError(ps, 4, []env.Type{env.IntegerType}, "mqtt-client//Publish")
						}
					default:
						ps.FailureFlag = true
						return MakeArgError(ps, 3, []env.Type{env.StringType}, "mqtt-client//Publish")
					}
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 2, []env.Type{env.StringType}, "mqtt-client//Publish")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "mqtt-client//Publish")
			}
		},
	},

	"mqtt-client//Publish-simple": {
		Argsn: 3,
		Doc:   "Publishes a message to an MQTT topic with default settings (QoS 0, no retain).",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch client := arg0.(type) {
			case env.Native:
				switch topic := arg1.(type) {
				case env.String:
					switch payload := arg2.(type) {
					case env.String:
						mqttClient := client.Value.(mqtt.Client)

						token := mqttClient.Publish(topic.Value, 0, false, payload.Value)
						if token.Wait() && token.Error() != nil {
							ps.FailureFlag = true
							return MakeBuiltinError(ps, fmt.Sprintf("Failed to publish message: %v", token.Error()), "mqtt-client//Publish-simple")
						}

						return *env.NewInteger(1)
					default:
						ps.FailureFlag = true
						return MakeArgError(ps, 3, []env.Type{env.StringType}, "mqtt-client//Publish-simple")
					}
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 2, []env.Type{env.StringType}, "mqtt-client//Publish-simple")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "mqtt-client//Publish-simple")
			}
		},
	},

	"mqtt-client//Subscribe": {
		Argsn: 4,
		Doc:   "Subscribes to an MQTT topic with a message handler function.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch client := arg0.(type) {
			case env.Native:
				switch topic := arg1.(type) {
				case env.String:
					switch qos := arg2.(type) {
					case env.Integer:
						switch handler := arg3.(type) {
						case env.Function:
							mqttClient := client.Value.(mqtt.Client)

							if qos.Value < 0 || qos.Value > 2 {
								ps.FailureFlag = true
								return MakeBuiltinError(ps, "QoS must be 0, 1, or 2", "mqtt-client//Subscribe")
							}

							callback := func(client mqtt.Client, msg mqtt.Message) {

								psCallback := *ps
								psCallback.FailureFlag = false
								psCallback.ErrorFlag = false
								psCallback.ReturnFlag = false

								msgDict := make(map[string]any)
								msgDict["topic"] = *env.NewString(msg.Topic())

								msgDict["qos"] = *env.NewInteger(int64(msg.Qos()))
								msgDict["retained"] = *env.NewBoolean(msg.Retained())
								msgDict["duplicate"] = *env.NewBoolean(msg.Duplicate())
								msgDict["message-id"] = *env.NewInteger(int64(msg.MessageID()))

								CallFunctionArgs2(handler,
									&psCallback,
									*env.NewString(string(msg.Payload())),
									*env.NewDict(msgDict),
									nil)
								if psCallback.FailureFlag || psCallback.ErrorFlag {
									fmt.Println("********* CALLBACK ERROR MQTT")
								}
								MaybeDisplayFailureOrError(&psCallback, psCallback.Idx, "on-mqtt-message")
							}

							token := mqttClient.Subscribe(topic.Value, byte(qos.Value), callback)
							if token.Wait() && token.Error() != nil {
								ps.FailureFlag = true
								return MakeBuiltinError(ps, fmt.Sprintf("Failed to subscribe: %v", token.Error()), "mqtt-client//Subscribe")
							}

							return *env.NewInteger(1)
						default:
							fmt.Println(arg3.Inspect(*ps.Idx))
							ps.FailureFlag = true
							return MakeArgError(ps, 4, []env.Type{env.FunctionType}, "mqtt-client//Subscribe")
						}
					default:
						ps.FailureFlag = true
						return MakeArgError(ps, 3, []env.Type{env.IntegerType}, "mqtt-client//Subscribe")
					}
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 2, []env.Type{env.StringType}, "mqtt-client//Subscribe")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "mqtt-client//Subscribe")
			}
		},
	},

	"mqtt-client//Subscribe-simple": {
		Argsn: 3,
		Doc:   "Subscribes to an MQTT topic with default QoS 0 and a message handler function.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch client := arg0.(type) {
			case env.Native:
				switch topic := arg1.(type) {
				case env.String:
					switch handler := arg2.(type) {
					case env.Function:
						mqttClient := client.Value.(mqtt.Client)

						callback := func(client mqtt.Client, msg mqtt.Message) {

							psCallback := *ps
							psCallback.FailureFlag = false
							psCallback.ErrorFlag = false
							psCallback.ReturnFlag = false

							msgDict := make(map[string]any)
							msgDict["topic"] = *env.NewString(msg.Topic())
							msgDict["qos"] = *env.NewInteger(int64(msg.Qos()))
							msgDict["retained"] = *env.NewBoolean(msg.Retained())

							CallFunctionArgs2(handler, &psCallback, *env.NewDict(msgDict), env.Void{}, nil)
						}

						token := mqttClient.Subscribe(topic.Value, 0, callback)
						if token.Wait() && token.Error() != nil {
							ps.FailureFlag = true
							return MakeBuiltinError(ps, fmt.Sprintf("Failed to subscribe: %v", token.Error()), "mqtt-client//Subscribe-simple")
						}

						return *env.NewInteger(1)
					default:
						ps.FailureFlag = true
						return MakeArgError(ps, 3, []env.Type{env.FunctionType}, "mqtt-client//Subscribe-simple")
					}
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 2, []env.Type{env.StringType}, "mqtt-client//Subscribe-simple")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "mqtt-client//Subscribe-simple")
			}
		},
	},

	"mqtt-client//Unsubscribe": {
		Argsn: 2,
		Doc:   "Unsubscribes from an MQTT topic.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch client := arg0.(type) {
			case env.Native:
				switch topic := arg1.(type) {
				case env.String:
					mqttClient := client.Value.(mqtt.Client)

					token := mqttClient.Unsubscribe(topic.Value)
					if token.Wait() && token.Error() != nil {
						ps.FailureFlag = true
						return MakeBuiltinError(ps, fmt.Sprintf("Failed to unsubscribe: %v", token.Error()), "mqtt-client//Unsubscribe")
					}

					return *env.NewInteger(1)
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 2, []env.Type{env.StringType}, "mqtt-client//Unsubscribe")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "mqtt-client//Unsubscribe")
			}
		},
	},

	"mqtt-client//Is-connected": {
		Argsn: 1,
		Doc:   "Checks if the MQTT client is currently connected to the broker.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch client := arg0.(type) {
			case env.Native:
				mqttClient := client.Value.(mqtt.Client)
				if mqttClient.IsConnected() {
					return *env.NewInteger(1)
				} else {
					return *env.NewInteger(0)
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "mqtt-client//Connected?")
			}
		},
	},

	"mqtt-options": {
		Argsn: 0,
		Doc:   "Creates a new MQTT client options object for advanced configuration.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			opts := mqtt.NewClientOptions()
			return *env.NewNative(ps.Idx, opts, "mqtt-options")
		},
	},

	"mqtt-options//Set-broker": {
		Argsn: 2,
		Doc:   "Sets the MQTT broker address in the options.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch opts := arg0.(type) {
			case env.Native:
				switch broker := arg1.(type) {
				case env.String:
					options := opts.Value.(*mqtt.ClientOptions)
					options.AddBroker(broker.Value)
					return arg0
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 2, []env.Type{env.StringType}, "mqtt-options//Set-broker")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "mqtt-options//Set-broker")
			}
		},
	},

	"mqtt-options//Set-client-id": {
		Argsn: 2,
		Doc:   "Sets the client ID in the MQTT options.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch opts := arg0.(type) {
			case env.Native:
				switch clientID := arg1.(type) {
				case env.String:
					options := opts.Value.(*mqtt.ClientOptions)
					options.SetClientID(clientID.Value)
					return arg0
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 2, []env.Type{env.StringType}, "mqtt-options//Set-client-id")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "mqtt-options//Set-client-id")
			}
		},
	},

	"mqtt-options//Set-keep-alive": {
		Argsn: 2,
		Doc:   "Sets the keep alive interval in seconds.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch opts := arg0.(type) {
			case env.Native:
				switch keepAlive := arg1.(type) {
				case env.Integer:
					options := opts.Value.(*mqtt.ClientOptions)
					options.SetKeepAlive(time.Duration(keepAlive.Value) * time.Second)
					return arg0
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 2, []env.Type{env.IntegerType}, "mqtt-options//Set-keep-alive")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "mqtt-options//Set-keep-alive")
			}
		},
	},

	"mqtt-options//Set-username": {
		Argsn: 2,
		Doc:   "Sets the username for MQTT authentication.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch opts := arg0.(type) {
			case env.Native:
				switch username := arg1.(type) {
				case env.String:
					options := opts.Value.(*mqtt.ClientOptions)
					options.SetUsername(username.Value)
					return arg0
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 2, []env.Type{env.StringType}, "mqtt-options//Set-username")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "mqtt-options//Set-username")
			}
		},
	},

	"mqtt-options//Set-password": {
		Argsn: 2,
		Doc:   "Sets the password for MQTT authentication.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch opts := arg0.(type) {
			case env.Native:
				switch password := arg1.(type) {
				case env.String:
					options := opts.Value.(*mqtt.ClientOptions)
					options.SetPassword(password.Value)
					return arg0
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 2, []env.Type{env.StringType}, "mqtt-options//Set-password")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "mqtt-options//Set-password")
			}
		},
	},

	"mqtt-options//Set-will": {
		Argsn: 5,
		Doc:   "Sets the Last Will and Testament message with QoS and retain flag.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch opts := arg0.(type) {
			case env.Native:
				switch topic := arg1.(type) {
				case env.String:
					switch payload := arg2.(type) {
					case env.String:
						switch qos := arg3.(type) {
						case env.Integer:
							switch retain := arg4.(type) {
							case env.Integer:
								if qos.Value < 0 || qos.Value > 2 {
									ps.FailureFlag = true
									return MakeBuiltinError(ps, "QoS must be 0, 1, or 2", "mqtt-options//Set-will")
								}

								options := opts.Value.(*mqtt.ClientOptions)
								retainBool := retain.Value != 0
								options.SetWill(topic.Value, payload.Value, byte(qos.Value), retainBool)
								return arg0
							default:
								ps.FailureFlag = true
								return MakeArgError(ps, 5, []env.Type{env.IntegerType}, "mqtt-options//Set-will")
							}
						default:
							ps.FailureFlag = true
							return MakeArgError(ps, 4, []env.Type{env.IntegerType}, "mqtt-options//Set-will")
						}
					default:
						ps.FailureFlag = true
						return MakeArgError(ps, 3, []env.Type{env.StringType}, "mqtt-options//Set-will")
					}
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 2, []env.Type{env.StringType}, "mqtt-options//Set-will")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "mqtt-options//Set-will")
			}
		},
	},

	"mqtt-options//Connect-with-options": {
		Argsn: 1,
		Doc:   "Creates and connects an MQTT client using the configured options.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch opts := arg0.(type) {
			case env.Native:
				options := opts.Value.(*mqtt.ClientOptions)
				client := mqtt.NewClient(options)

				if token := client.Connect(); token.Wait() && token.Error() != nil {
					ps.FailureFlag = true
					return MakeBuiltinError(ps, fmt.Sprintf("Failed to connect to MQTT broker: %v", token.Error()), "mqtt-options//Connect-with-options")
				}

				return *env.NewNative(ps.Idx, client, "mqtt-client")
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "mqtt-options//Connect-with-options")
			}
		},
	},
}
View Source
var Builtins_msgdispatcher = map[string]*env.Builtin{

	"msg-dispatcher": {
		Argsn: 2,
		Doc:   "Creates a new message dispatcher with specified buffer size and initial state.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch bufSize := arg0.(type) {
			case env.Integer:
				switch initialState := arg1.(type) {
				case env.Dict:
					dispatcher := NewMessageDispatcher(int(bufSize.Value), initialState)
					return *env.NewNative(ps.Idx, dispatcher, "msg-dispatcher")
				default:
					return MakeArgError(ps, 2, []env.Type{env.DictType}, "msg-dispatcher")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.IntegerType}, "msg-dispatcher")
			}
		},
	},

	"msg-dispatcher//Register": {
		Argsn: 3,
		Doc:   "Registers a message handler function for a specific message type.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch native := arg0.(type) {
			case env.Native:
				dispatcher, ok := native.Value.(*MessageDispatcher)
				if !ok {
					return MakeBuiltinError(ps, "Expected MessageDispatcher", "Rye-msg-dispatcher//Register")
				}

				switch msgType := arg1.(type) {
				case env.String:
					switch handler := arg2.(type) {
					case env.Function:
						if handler.Argsn != 2 {
							return MakeBuiltinError(ps, "Handler must accept 2 arguments (message, state)", "Rye-msg-dispatcher//Register")
						}
						dispatcher.RegisterHandler(msgType.Value, handler)
						return arg0
					default:
						return MakeArgError(ps, 3, []env.Type{env.FunctionType}, "Rye-msg-dispatcher//Register")
					}
				default:
					return MakeArgError(ps, 2, []env.Type{env.StringType}, "Rye-msg-dispatcher//Register")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Rye-msg-dispatcher//Register")
			}
		},
	},

	"msg-dispatcher//Unregister": {
		Argsn: 2,
		Doc:   "Unregisters a message handler for a specific message type.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch native := arg0.(type) {
			case env.Native:
				dispatcher, ok := native.Value.(*MessageDispatcher)
				if !ok {
					return MakeBuiltinError(ps, "Expected MessageDispatcher", "Rye-msg-dispatcher//Unregister")
				}

				switch msgType := arg1.(type) {
				case env.String:
					dispatcher.UnregisterHandler(msgType.Value)
					return arg0
				default:
					return MakeArgError(ps, 2, []env.Type{env.StringType}, "Rye-msg-dispatcher//Unregister")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Rye-msg-dispatcher//Unregister")
			}
		},
	},

	"msg-dispatcher//Send": {
		Argsn: 2,
		Doc:   "Sends a message to the dispatcher for processing.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch native := arg0.(type) {
			case env.Native:
				dispatcher, ok := native.Value.(*MessageDispatcher)
				if !ok {
					return MakeBuiltinError(ps, "Expected MessageDispatcher", "Rye-msg-dispatcher//Send")
				}

				err := dispatcher.Send(arg1)
				if err != nil {
					return MakeBuiltinError(ps, fmt.Sprintf("Send failed: %v", err), "Rye-msg-dispatcher//Send")
				}
				return arg0
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Rye-msg-dispatcher//Send")
			}
		},
	},

	"msg-dispatcher//State": {
		Argsn: 1,
		Doc:   "Gets the current state from the dispatcher.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch native := arg0.(type) {
			case env.Native:
				dispatcher, ok := native.Value.(*MessageDispatcher)
				if !ok {
					return MakeBuiltinError(ps, "Expected MessageDispatcher", "Rye-msg-dispatcher//State")
				}
				return dispatcher.GetState()
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Rye-msg-dispatcher//State")
			}
		},
	},

	"msg-dispatcher//Set-state": {
		Argsn: 2,
		Doc:   "Sets the current state in the dispatcher.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch native := arg0.(type) {
			case env.Native:
				dispatcher, ok := native.Value.(*MessageDispatcher)
				if !ok {
					return MakeBuiltinError(ps, "Expected MessageDispatcher", "Rye-msg-dispatcher//Set-state")
				}

				switch newState := arg1.(type) {
				case env.Dict:
					dispatcher.SetState(newState)
					return arg0
				default:
					return MakeArgError(ps, 2, []env.Type{env.DictType}, "Rye-msg-dispatcher//Set-state")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Rye-msg-dispatcher//Set-state")
			}
		},
	},

	"msg-dispatcher//Start": {
		Argsn: 2,
		Doc:   "Starts the message dispatcher loop in a goroutine. Optionally takes an update callback function.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch native := arg0.(type) {
			case env.Native:
				dispatcher, ok := native.Value.(*MessageDispatcher)
				if !ok {
					return MakeBuiltinError(ps, "Expected MessageDispatcher", "Rye-msg-dispatcher//Start")
				}

				var updateCallback env.Function
				switch cb := arg1.(type) {
				case env.Function:
					if cb.Argsn != 1 {
						return MakeBuiltinError(ps, "Update callback must accept 1 argument (state)", "Rye-msg-dispatcher//Start")
					}
					updateCallback = cb
				case env.Void:

					updateCallback = env.Function{Argsn: -1}
				default:
					return MakeArgError(ps, 2, []env.Type{env.FunctionType, env.VoidType}, "Rye-msg-dispatcher//Start")
				}

				dispatcher.Start(ps, updateCallback)
				return arg0
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Rye-msg-dispatcher//Start")
			}
		},
	},

	"msg-dispatcher//Stop": {
		Argsn: 1,
		Doc:   "Stops the message dispatcher loop and waits for it to finish.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch native := arg0.(type) {
			case env.Native:
				dispatcher, ok := native.Value.(*MessageDispatcher)
				if !ok {
					return MakeBuiltinError(ps, "Expected MessageDispatcher", "Rye-msg-dispatcher//Stop")
				}
				dispatcher.Stop()
				return arg0
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Rye-msg-dispatcher//Stop")
			}
		},
	},
}

Builtins for message dispatcher

View Source
var Builtins_mysql = map[string]*env.Builtin{

	"mysql-uri//Open": {
		Argsn: 1,
		Doc:   "Opens a connection to a MySQL database.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch str := arg0.(type) {
			case env.Uri:
				fmt.Println(str.Path)
				fmt.Println(str.GetPath())
				fmt.Println(str.GetFullUri(*ps.Idx))
				db, err := sql.Open("mysql", str.Path)
				if err != nil {

					ps.FailureFlag = true
					errMsg := fmt.Sprintf("Error opening SQL: %v", err.Error())
					return MakeBuiltinError(ps, errMsg, "mysql-uri//Open")
				} else {

					return *env.NewNative(ps.Idx, db, "Rye-mysql")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.UriType}, "mysql-uri//Open")
			}

		},
	},

	"mysql-uri//Open\\pwd": {
		Argsn: 2,
		Doc:   "Opens a connection to a MySQL database with separate password parameter.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch str := arg0.(type) {
			case env.Uri:
				switch pwd := arg1.(type) {
				case env.String:
					path := strings.Replace(str.Path, "@", ":"+pwd.Value+"@", 1)
					fmt.Println(path)
					db, err := sql.Open("mysql", path)
					if err != nil {

						ps.FailureFlag = true
						errMsg := fmt.Sprintf("Error opening SQL: %v", err.Error())
						return MakeBuiltinError(ps, errMsg, "mysql-uri//Open\\pwd")
					} else {

						return *env.NewNative(ps.Idx, db, "Rye-mysql")
					}
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 2, []env.Type{env.StringType}, "mysql-uri//Open\\pwd")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.UriType}, "mysql-uri//Open\\pwd")
			}
		},
	},

	"Rye-mysql//Exec": {
		Argsn: 2,
		Doc:   "Executes a SQL statement that modifies data (INSERT, UPDATE, DELETE).",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			var sqlstr string
			var vals []any
			switch db1 := arg0.(type) {
			case env.Native:
				switch str := arg1.(type) {
				case env.Block:
					ser := ps.Ser
					ps.Ser = str.Series
					values := make([]any, 0, 2)
					_, vals = SQL_EvalBlock(ps, MODE_SQLITE, values)
					sqlstr = ps.Res.(env.String).Value
					ps.Ser = ser
				case env.String:
					sqlstr = str.Value
				default:
					ps.ErrorFlag = true
					return MakeArgError(ps, 2, []env.Type{env.BlockType, env.StringType}, "Rye-mysql//Exec")
				}
				if sqlstr != "" {

					db2 := db1.Value.(*sql.DB)
					res, err := db2.Exec(sqlstr, vals...)
					if err != nil {
						ps.FailureFlag = true
						return MakeBuiltinError(ps, err.Error(), "Rye-mysql//Exec")
					} else {
						num, _ := res.RowsAffected()
						if num > 0 {
							return env.NewInteger(1)
						} else {
							ps.FailureFlag = true
							return MakeBuiltinError(ps, "No rows affected.", "Rye-mysql//Exec")
						}
					}
				} else {
					return MakeBuiltinError(ps, "SQL string is blank.", "Rye-mysql//Exec")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Rye-mysql//Exec")
			}
		},
	},

	"Rye-mysql//Query": {
		Argsn: 2,
		Doc:   "Executes a SQL query and returns results as a table.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			var sqlstr string
			var vals []any
			switch db1 := arg0.(type) {
			case env.Native:
				switch str := arg1.(type) {
				case env.Block:

					ser := ps.Ser
					ps.Ser = str.Series
					values := make([]any, 0, 2)
					_, vals = SQL_EvalBlock(ps, MODE_SQLITE, values)
					sqlstr = ps.Res.(env.String).Value
					ps.Ser = ser
				case env.String:
					sqlstr = str.Value
				default:
					ps.ErrorFlag = true
					return MakeArgError(ps, 2, []env.Type{env.BlockType, env.StringType}, "Rye-mysql//Query")
				}
				if sqlstr != "" {

					rows, err := db1.Value.(*sql.DB).Query(sqlstr, vals...)

					if err != nil {
						ps.FailureFlag = true
						return MakeBuiltinError(ps, err.Error(), "Rye-mysql//Query")
					} else {
						cols, _ := rows.Columns()
						spr := env.NewTable(cols)
						i := 0
						for rows.Next() {

							var sr env.TableRow

							columns := make([]any, len(cols))
							columnPointers := make([]any, len(cols))
							for i := range columns {
								columnPointers[i] = &columns[i]
							}

							if err := rows.Scan(columnPointers...); err != nil {
								ps.FailureFlag = true
								return MakeBuiltinError(ps, err.Error(), "Rye-mysql//Query")
							}

							m := make(map[string]any)
							for i, colName := range cols {
								val := *columnPointers[i].(*any)
								switch vval := val.(type) {
								case []uint8:

									m[colName] = env.ToRyeValue(string(vval))
									sr.Values = append(sr.Values, env.ToRyeValue(string(vval)))
								default:
									m[colName] = env.ToRyeValue(vval)
									sr.Values = append(sr.Values, env.ToRyeValue(vval))
								}
							}
							spr.AddRow(sr)

							i++
						}
						rows.Close()

						if i == 0 {
							ps.FailureFlag = true
							return MakeBuiltinError(ps, "No data.", "Rye-mysql//Query")
						}
						return *spr

					}
				} else {
					return MakeBuiltinError(ps, "Empty SQL.", "Rye-mysql//Query")
				}

			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Rye-mysql//Query")
			}
		},
	},
}
View Source
var Builtins_os = map[string]*env.Builtin{

	"cwd?": {
		Argsn: 0,
		Doc:   "Gets the current working directory.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			path, err := os.Getwd()
			if err != nil {
				return MakeBuiltinError(ps, err.Error(), "cwd")
			}
			return *env.NewUri1(ps.Idx, "file://"+path)
		},
	},

	"does-exist": {
		Argsn: 1,
		Doc:   "Checks if a file or directory exists.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch path := arg0.(type) {
			case env.Uri:
				filePath := filepath.Join(ps.WorkingPath, path.GetPath())
				res := FileExists(filePath)
				if res == -1 {
					return MakeBuiltinError(ps, "Error checking if path exists", "exists?")
				}
				if res == 1 {
					return *env.NewBoolean(true)
				} else {
					return *env.NewBoolean(false)
				}
			case env.String:
				filePath := filepath.Join(ps.WorkingPath, path.Value)
				res := FileExists(filePath)
				if res == -1 {
					return MakeBuiltinError(ps, "Error checking if path exists", "exists?")
				}
				if res == 1 {
					return *env.NewBoolean(true)
				} else {
					return *env.NewBoolean(false)
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.UriType, env.StringType}, "exists?")
			}
		},
	},

	"cd": {
		Argsn: 1,
		Doc:   "Changes the current working directory.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch path := arg0.(type) {
			case env.Uri:

				err := os.Chdir(path.GetPath())
				if err != nil {
					return MakeBuiltinError(ps, err.Error(), "cd")
				}
				return arg0
			default:
				return MakeArgError(ps, 1, []env.Type{env.UriType}, "cd")
			}
		},
	},

	"env?": {
		Argsn: 1,
		Doc:   "Gets the value of an environment variable.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch variable_name := arg0.(type) {
			case env.String:

				val, ok := os.LookupEnv(variable_name.Value)
				if !ok {
					return MakeBuiltinError(ps, "Variable couldn't be read", "env?")
				}
				return *env.NewString(val)
			default:
				return MakeArgError(ps, 1, []env.Type{env.StringType}, "env?")
			}
		},
	},

	"mkdir": {
		Argsn: 1,
		Doc:   "Creates a new directory.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch path := arg0.(type) {
			case env.Uri:
				newDir := filepath.Join(ps.WorkingPath, path.GetPath())

				err := os.Mkdir(newDir, 0755)
				if err != nil {
					return MakeBuiltinError(ps, "Error creating directory: "+err.Error(), "mkdir")
				} else {
					return arg0
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.UriType}, "mkdir")
			}
		},
	},

	"mktmp": {
		Argsn: 0,
		Doc:   "Creates a new temporary directory.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			dir, err := os.MkdirTemp("", "rye-tmp-")
			if err != nil {
				return MakeBuiltinError(ps, "Error creating temporary directory: "+err.Error(), "mktmp")
			}
			return *env.NewUri1(ps.Idx, "file://"+dir)
		},
	},

	"mv": {
		Argsn: 2,
		Doc:   "Moves or renames a file or directory.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch path := arg0.(type) {
			case env.Uri:
				switch path2 := arg1.(type) {
				case env.Uri:
					old := filepath.Join(ps.WorkingPath, path.GetPath())
					new := filepath.Join(ps.WorkingPath, path2.GetPath())
					err := os.Rename(old, new)
					if err != nil {
						fmt.Println("Error renaming file:", err)
						return MakeBuiltinError(ps, "Error renaming file: "+err.Error(), "mv")
					} else {
						return arg1
					}
				default:
					return MakeArgError(ps, 1, []env.Type{env.UriType}, "mv")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.UriType}, "mv")
			}
		},
	},

	"ls": {
		Argsn: 0,
		Doc:   "Lists files and directories in the current directory.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {

			files, err := os.ReadDir(".")
			if err != nil {
				return MakeBuiltinError(ps, "Error reading directory:"+err.Error(), "ls")
			}

			items := make([]env.Object, len(files))

			for i, file := range files {

				items[i] = *env.NewUri1(ps.Idx, "file://"+file.Name())
			}
			return *env.NewBlock(*env.NewTSeries(items))
		},
	},

	"ls\\": {
		Argsn: 1,
		Doc:   "Lists files or directories in the current directory based on filter. Use 'dirs' for directories only, 'files' for files only, a string for partial name matching, or a regexp to match names.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			files, err := os.ReadDir(".")
			if err != nil {
				return MakeBuiltinError(ps, "Error reading directory:"+err.Error(), "ls\\")
			}

			var items []env.Object

			switch filterArg := arg0.(type) {
			case env.Word:
				filter := ps.Idx.GetWord(filterArg.Index)
				if filter != "dirs" && filter != "files" {
					return MakeBuiltinError(ps, "Word filter must be 'dirs' or 'files'", "ls\\")
				}

				for _, file := range files {
					include := false
					if filter == "dirs" {
						include = file.IsDir()
					} else if filter == "files" {
						include = !file.IsDir()
					}

					if include {
						items = append(items, *env.NewUri1(ps.Idx, "file://"+file.Name()))
					}
				}

			case env.String:

				pattern := filterArg.Value
				for _, file := range files {
					if strings.Contains(file.Name(), pattern) {
						items = append(items, *env.NewUri1(ps.Idx, "file://"+file.Name()))
					}
				}

			case env.Native:

				if ps.Idx.GetWord(filterArg.Kind.Index) != "regexp" {
					return MakeBuiltinError(ps, "Native object must be a regexp", "ls\\")
				}

				regex := filterArg.Value.(*regexp.Regexp)
				for _, file := range files {
					if regex.MatchString(file.Name()) {
						items = append(items, *env.NewUri1(ps.Idx, "file://"+file.Name()))
					}
				}

			default:
				return MakeArgError(ps, 1, []env.Type{env.WordType, env.StringType, env.NativeType}, "ls\\")
			}

			return *env.NewBlock(*env.NewTSeries(items))
		},
	},

	"host-info?": {
		Argsn: 0,
		Doc:   "Gets information about the host system.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			v, err := host.Info()
			if err != nil {
				return MakeBuiltinError(ps, err.Error(), "host-info?")
			}
			r := env.NewDict(make(map[string]any, 10))
			r.Data["hostname"] = *env.NewString(v.Hostname)
			r.Data["uptime"] = *env.NewInteger(int64(v.Uptime))
			r.Data["boot-time"] = *env.NewInteger(int64(v.BootTime))
			r.Data["procs"] = *env.NewInteger(int64(v.Procs))
			r.Data["os"] = *env.NewString(v.OS)
			r.Data["platform"] = *env.NewString(v.Platform)
			r.Data["platform-family"] = *env.NewString(v.PlatformFamily)
			r.Data["platform-version"] = *env.NewString(v.PlatformVersion)
			r.Data["kernel-version"] = *env.NewString(v.KernelVersion)
			r.Data["virtualization-system"] = *env.NewString(v.VirtualizationSystem)
			return *r
		},
	},

	"users?": {
		Argsn: 0,
		Doc:   "Gets information about users currently logged into the system.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			users, err := host.Users()
			if err != nil {
				return MakeBuiltinError(ps, err.Error(), "users?")
			}
			fmt.Println(users)
			s := env.NewTable([]string{"User", "Terminal", "Host", "Started"})
			for _, user := range users {
				vals := []any{
					*env.NewString(user.User),
					*env.NewString(user.Terminal),
					*env.NewString(user.Host),
					*env.NewInteger(int64(user.Started)),
				}
				s.AddRow(*env.NewTableRow(vals, s))
			}
			return *s
		},
	},

	"load-avg?": {
		Argsn: 0,
		Doc:   "Gets the system load average over the last 1, 5, and 15 minutes.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			v, err := load.Avg()
			if err != nil {
				return MakeBuiltinError(ps, err.Error(), "load-avg?")
			}
			r := env.NewDict(make(map[string]any, 3))
			r.Data["1"] = *env.NewDecimal(v.Load1)
			r.Data["5"] = *env.NewDecimal(v.Load5)
			r.Data["15"] = *env.NewDecimal(v.Load15)
			return *r
		},
	},

	"virtual-memory?": {
		Argsn: 0,
		Doc:   "Gets information about virtual memory usage.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			v, err := mem.VirtualMemory()
			if err != nil {
				return MakeBuiltinError(ps, err.Error(), "virtual-memory?")
			}
			r := env.NewDict(make(map[string]any, 3))
			r.Data["total"] = *env.NewInteger(int64(v.Total))
			r.Data["free"] = *env.NewInteger(int64(v.Free))
			r.Data["used-percent"] = *env.NewDecimal(v.UsedPercent)
			return *r
		},
	},

	"disk-usage?": {
		Argsn: 0,
		Doc:   "Gets disk usage information for all partitions.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			partitions, err := disk.Partitions(true)
			if err != nil {
				return MakeBuiltinError(ps, err.Error(), "disk-usage?")
			}
			s := env.NewTable([]string{"Filesystem", "Size", "Used", "Available", "Capacity", "iused", "ifree", "%iused", "Mounted on"})
			for _, partition := range partitions {
				usage, err := disk.Usage(partition.Mountpoint)
				if err != nil {
					return MakeBuiltinError(ps, err.Error(), "disk-usage?")
				}
				vals := []any{
					*env.NewString(partition.Device),
					*env.NewInteger(int64(usage.Total)),
					*env.NewInteger(int64(usage.Used)),
					*env.NewInteger(int64(usage.Free)),
					*env.NewDecimal(usage.UsedPercent),
					*env.NewInteger(int64(usage.InodesUsed)),
					*env.NewInteger(int64(usage.InodesFree)),
					*env.NewInteger(int64(usage.InodesUsedPercent)),
					*env.NewString(usage.Path),
				}
				s.AddRow(*env.NewTableRow(vals, s))
			}
			return *s
		},
	},

	"pids?": {
		Argsn: 0,
		Doc:   "Gets a list of all process IDs currently running.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			pids, err := process.Pids()
			if err != nil {
				return MakeBuiltinError(ps, err.Error(), "pids?")
			}

			pids2 := make([]env.Object, len(pids))
			for i, p := range pids {
				pids2[i] = env.NewInteger(int64(p))
			}
			return *env.NewBlock(*env.NewTSeries(pids2))
		},
	},

	"processes?": {
		Argsn: 0,
		Doc:   "Gets detailed information about all running processes.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			processes, err := process.Processes()
			if err != nil {
				return MakeBuiltinError(ps, err.Error(), "processes?")
			}
			s := proccesTableBase()
			for _, process := range processes {
				processTableAdd(s, process)
			}
			return *s
		},
	},

	"process": {
		Argsn: 1,
		Doc:   "Gets detailed information about a specific process by PID.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch pid := arg0.(type) {
			case env.Integer:
				process, err := process.NewProcess(int32(pid.Value))
				if err != nil {
					return MakeBuiltinError(ps, err.Error(), "process")
				}
				s := proccesTableBase()
				processTableAdd(s, process)
				return s.Rows[0].ToDict()
			default:
				return *MakeArgError(ps, 1, []env.Type{env.IntegerType}, "process")
			}
		},
	},

	"lookup-address": {
		Argsn: 1,
		Doc:   "Performs a reverse DNS lookup to get hostnames for an IP address.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch ip := arg0.(type) {
			case env.String:
				names, err := net.LookupAddr(ip.Value)
				if err != nil {
					return MakeBuiltinError(ps, err.Error(), "ip-lookup")
				}

				items := make([]env.Object, len(names))

				for i, name := range names {
					items[i] = *env.NewString(name)
				}
				return *env.NewBlock(*env.NewTSeries(items))
			default:
				return *MakeArgError(ps, 1, []env.Type{env.StringType}, "ip-lookup")
			}
		},
	},

	"lookup-ip": {
		Argsn: 1,
		Doc:   "Performs a DNS lookup to get IP addresses for a hostname.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch ip := arg0.(type) {
			case env.String:
				names, err := net.LookupIP(ip.Value)
				if err != nil {
					return MakeBuiltinError(ps, err.Error(), "ip-lookup")
				}

				items := make([]env.Object, len(names))

				for i, name := range names {
					items[i] = *env.NewString(name.String())
				}
				return *env.NewBlock(*env.NewTSeries(items))
			default:
				return *MakeArgError(ps, 1, []env.Type{env.StringType}, "ip-lookup")
			}
		},
	},

	"write\\clipboard": {
		Argsn: 1,
		Doc:   "Writes a string value to the system clipboard.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch val := arg0.(type) {
			case env.String:
				err := clipboard.WriteAll(val.Value)
				if err != nil {
					return MakeBuiltinError(ps, err.Error(), "write\\clipboard")
				}
				return arg0
			default:
				return *MakeArgError(ps, 1, []env.Type{env.StringType}, "write\\clipboard")
			}
		},
	},

	"read\\clipboard": {
		Argsn: 0,
		Doc:   "Reads the current contents of the system clipboard.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			val, err := clipboard.ReadAll()
			if err != nil {
				return MakeBuiltinError(ps, err.Error(), "read\\clipboard")
			}
			return *env.NewString(val)
		},
	},
}
View Source
var Builtins_pipes = map[string]*env.Builtin{

	"cat": {
		Argsn: 1,
		Doc:   "Creates a new pipe object from a file.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch path := arg0.(type) {
			case env.Uri:
				p := script.File(path.GetPath())
				return *env.NewNative(ps.Idx, p, "script-pipe")
			default:
				return MakeArgError(ps, 1, []env.Type{env.UriType}, "p-new-file")
			}
		},
	},

	"find": {
		Argsn: 1,
		Doc:   "Creates a pipe object listing all the files in the directory and its subdirectories recursively, one per line.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch path := arg0.(type) {
			case env.Uri:
				p := script.FindFiles(path.GetPath())
				return *env.NewNative(ps.Idx, p, "script-pipe")
			default:
				return MakeArgError(ps, 1, []env.Type{env.UriType}, "p-new-find-files")
			}
		},
	},

	"list": {
		Argsn: 1,
		Doc:   "Creates a pipe object listing all the files in the directory, one per line. Accepts and URI or glob pattern.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch path := arg0.(type) {
			case env.Uri:
				p := script.ListFiles(path.GetPath())
				return *env.NewNative(ps.Idx, p, "script-pipe")
			case env.String:
				p := script.ListFiles(path.Value)
				return *env.NewNative(ps.Idx, p, "script-pipe")
			default:
				return MakeArgError(ps, 1, []env.Type{env.UriType}, "p-new-list-files")
			}
		},
	},

	"from-block": {
		Argsn: 1,
		Doc:   "Creates a pipe object from a block of strings, one per line.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch block := arg0.(type) {
			case env.Block:
				strs := make([]string, len(block.Series.S))
				for i, item := range block.Series.S {
					switch s := item.(type) {
					case env.String:
						strs[i] = s.Value
					default:
						return MakeBuiltinError(ps, "Block must contain only strings", "p-new-block")
					}
				}
				p := script.Slice(strs)
				return *env.NewNative(ps.Idx, p, "script-pipe")
			default:
				return MakeArgError(ps, 1, []env.Type{env.BlockType}, "p-new-block")
			}
		},
	},

	"echo": {
		Argsn: 1,
		Doc:   "Creates a pipe object from a string.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch s := arg0.(type) {
			case env.String:
				p := script.Echo(s.Value)
				return *env.NewNative(ps.Idx, p, "script-pipe")
			default:
				return MakeArgError(ps, 1, []env.Type{env.StringType}, "p-new-echo")
			}
		},
	},

	"cat\\opt": {
		Argsn: 1,
		Doc:   "Creates a pipe object from a file if it exists, otherwise returns an empty pipe object.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch path := arg0.(type) {
			case env.Uri:
				p := script.IfExists(path.GetPath())
				return *env.NewNative(ps.Idx, p, "script-pipe")
			default:
				return MakeArgError(ps, 1, []env.Type{env.UriType}, "p-new-if-exists")
			}
		},
	},

	"exec": {
		Argsn: 1,
		Doc:   "Creates a pipe object from a command that is executed.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch cmd := arg0.(type) {
			case env.String:
				p := script.Exec(cmd.Value)
				return *env.NewNative(ps.Idx, p, "script-pipe")
			default:
				return MakeArgError(ps, 1, []env.Type{env.StringType}, "p-new-exec")
			}
		},
	},

	"exec\\in": {
		Argsn: 2,
		Doc:   "Executes a command by sending it the contents of the pipe as input and returns a pipe object.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch p := arg0.(type) {
			case env.Native:
				switch pipe := p.Value.(type) {
				case *script.Pipe:
					switch cmd := arg1.(type) {
					case env.String:
						newPipe := pipe.Exec(cmd.Value)
						return *env.NewNative(ps.Idx, newPipe, "script-pipe")
					default:
						return MakeArgError(ps, 2, []env.Type{env.StringType}, "p-exec")
					}
				default:
					return MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-exec")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "p-exec")
			}
		},
	},

	"exec\\each": {
		Argsn: 2,
		Doc:   "Executes a command from a Go template for each line in the pipe and returns a pipe object with the output of each command.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch p := arg0.(type) {
			case env.Native:
				switch pipe := p.Value.(type) {
				case *script.Pipe:
					switch cmd := arg1.(type) {
					case env.String:
						newPipe := pipe.ExecForEach(cmd.Value)
						return *env.NewNative(ps.Idx, newPipe, "script-pipe")
					default:
						return MakeArgError(ps, 2, []env.Type{env.StringType}, "p-exec-for-each")
					}
				default:
					return MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-exec-for-each")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "p-exec-for-each")
			}
		},
	},

	"into-string": {
		Argsn: 1,
		Doc:   "Returns pipe contents as a string.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch p := arg0.(type) {
			case env.Native:
				switch pipe := p.Value.(type) {
				case *script.Pipe:
					str, err := pipe.String()
					if err != nil {
						return MakeBuiltinError(ps, err.Error(), "p-string")
					}
					return *env.NewString(str)
				default:
					return MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-string")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "p-string")
			}
		},
	},

	"into-file": {
		Argsn: 2,
		Doc:   "Writes pipe contents to a file and returns the number of bytes written.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch p := arg0.(type) {
			case env.Native:
				switch pipe := p.Value.(type) {
				case *script.Pipe:
					switch path := arg1.(type) {
					case env.Uri:
						i, err := pipe.WriteFile(path.GetPath())
						if err != nil {
							return MakeBuiltinError(ps, err.Error(), "p-write-file")
						}
						return *env.NewInteger(i)
					default:
						return MakeArgError(ps, 2, []env.Type{env.UriType}, "p-write-file")
					}
				default:
					return MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-write-file")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "p-write-file")
			}
		},
	},

	"out": {
		Argsn: 1,
		Doc:   "Prints pipe contents to stdout and returns the number of bytes written.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch p := arg0.(type) {
			case env.Native:
				switch pipe := p.Value.(type) {
				case *script.Pipe:
					i, err := pipe.Stdout()
					if err != nil {
						return MakeBuiltinError(ps, err.Error(), "p-stdout")
					}
					return *env.NewInteger(int64(i))
				default:
					return MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-stdout")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "p-stdout")
			}
		},
	},

	"head": {
		Argsn: 2,
		Doc:   "Returns a pipe with the first n lines from the pipe.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch p := arg0.(type) {
			case env.Native:
				switch pipe := p.Value.(type) {
				case *script.Pipe:
					switch n := arg1.(type) {
					case env.Integer:
						newPipe := pipe.First(int(n.Value))
						return *env.NewNative(ps.Idx, newPipe, "script-pipe")
					default:
						return MakeArgError(ps, 2, []env.Type{env.IntegerType}, "p-first-n")
					}
				default:
					return MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-first-n")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "p-first-n")
			}
		},
	},

	"tail": {
		Argsn: 2,
		Doc:   "Returns a pipe with the last n lines from the pipe.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch p := arg0.(type) {
			case env.Native:
				switch pipe := p.Value.(type) {
				case *script.Pipe:
					switch n := arg1.(type) {
					case env.Integer:
						newPipe := pipe.Last(int(n.Value))
						return *env.NewNative(ps.Idx, newPipe, "script-pipe")
					default:
						return MakeArgError(ps, 2, []env.Type{env.IntegerType}, "p-last-n")
					}
				default:
					return MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-last-n")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "p-last-n")
			}
		},
	},

	"dirname": {
		Argsn: 1,
		Doc:   "Reads paths from the pipe, one per line, and returns the directory component of each.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch p := arg0.(type) {
			case env.Native:
				switch pipe := p.Value.(type) {
				case *script.Pipe:
					newPipe := pipe.Dirname()
					return *env.NewNative(ps.Idx, newPipe, "script-pipe")
				default:
					return MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-dirname")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "p-dirname")
			}
		},
	},

	"basename": {
		Argsn: 1,
		Doc:   "Reads paths from the pipe, one per line, and removes any leading directory components from each.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch p := arg0.(type) {
			case env.Native:
				switch pipe := p.Value.(type) {
				case *script.Pipe:
					newPipe := pipe.Basename()
					return *env.NewNative(ps.Idx, newPipe, "script-pipe")
				default:
					return MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-basename")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "p-basename")
			}
		},
	},

	"wcl": {
		Argsn: 1,
		Doc:   "Returns the number of lines in a pipe.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch p := arg0.(type) {
			case env.Native:
				switch pipe := p.Value.(type) {
				case *script.Pipe:
					n, err := pipe.CountLines()
					if err != nil {
						return MakeBuiltinError(ps, err.Error(), "p-count-lines")
					}
					return *env.NewInteger(int64(n))
				default:
					return MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-count-lines")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "p-count-lines")
			}
		},
	},

	"freq": {
		Argsn: 1,
		Doc:   "Returns a pipe object with the frequency of each line in a pipe in descending order.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch p := arg0.(type) {
			case env.Native:
				switch pipe := p.Value.(type) {
				case *script.Pipe:
					newPipe := pipe.Freq()
					return *env.NewNative(ps.Idx, newPipe, "script-pipe")
				default:
					return MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-freq")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "p-freq")
			}
		},
	},

	"column": {
		Argsn: 2,
		Doc:   "Returns a pipe object with the column of each line of input, where the first column is column 1, and columns are delimited by Unicode whitespace.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch p := arg0.(type) {
			case env.Native:
				switch pipe := p.Value.(type) {
				case *script.Pipe:
					switch n := arg1.(type) {
					case env.Integer:
						newPipe := pipe.Column(int(n.Value))
						return *env.NewNative(ps.Idx, newPipe, "script-pipe")
					default:
						return MakeArgError(ps, 2, []env.Type{env.IntegerType}, "p-column")
					}
				default:
					return MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-column")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "p-column")
			}
		},
	},

	"jq": {
		Argsn: 2,
		Doc:   "Executes the jq command on the pipe whose contents are presumed to be JSON and returns a new pipe object with the output.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch p := arg0.(type) {
			case env.Native:
				switch pipe := p.Value.(type) {
				case *script.Pipe:
					switch jq := arg1.(type) {
					case env.String:
						newPipe := pipe.JQ(jq.Value)
						return *env.NewNative(ps.Idx, newPipe, "script-pipe")
					default:
						return MakeArgError(ps, 2, []env.Type{env.StringType}, "p-jq")
					}
				default:
					return MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-jq")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "p-jq")
			}
		},
	},

	"match": {
		Argsn: 2,
		Doc:   "Returns a pipe object with lines that match the string.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch p := arg0.(type) {
			case env.Native:
				switch pipe := p.Value.(type) {
				case *script.Pipe:
					switch s := arg1.(type) {
					case env.String:
						newPipe := pipe.Match(s.Value)
						return *env.NewNative(ps.Idx, newPipe, "script-pipe")
					default:
						return MakeArgError(ps, 2, []env.Type{env.StringType}, "p-match")
					}
				default:
					return MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-match")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "p-match")
			}
		},
	},

	"match\\regexp": {
		Argsn: 2,
		Doc:   "Returns a pipe object with lines that match the regular expression.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch p := arg0.(type) {
			case env.Native:
				switch pipe := p.Value.(type) {
				case *script.Pipe:
					switch r := arg1.(type) {
					case env.Native:
						switch regxp := r.Value.(type) {
						case *regexp.Regexp:
							newPipe := pipe.MatchRegexp(regxp)
							return *env.NewNative(ps.Idx, newPipe, "script-pipe")
						default:
							return MakeNativeArgError(ps, 2, []string{"regexp"}, "p-match-regexp")
						}
					default:
						return MakeArgError(ps, 2, []env.Type{env.NativeType}, "p-match-regexp")
					}
				default:
					return MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-match-regexp")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "p-match-regexp")
			}
		},
	},

	"not-match": {
		Argsn: 2,
		Doc:   "Returns a pipe object with lines that do not match the string.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch p := arg0.(type) {
			case env.Native:
				switch pipe := p.Value.(type) {
				case *script.Pipe:
					switch s := arg1.(type) {
					case env.String:
						newPipe := pipe.Reject(s.Value)
						return *env.NewNative(ps.Idx, newPipe, "script-pipe")
					default:
						return MakeArgError(ps, 2, []env.Type{env.StringType}, "p-not-match")
					}
				default:
					return MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-not-match")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "p-not-match")
			}
		},
	},

	"not-match\\regexp": {
		Argsn: 2,
		Doc:   "Returns a pipe object with lines that do not match the regular expression.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch p := arg0.(type) {
			case env.Native:
				switch pipe := p.Value.(type) {
				case *script.Pipe:
					switch r := arg1.(type) {
					case env.Native:
						switch regxp := r.Value.(type) {
						case *regexp.Regexp:
							newPipe := pipe.RejectRegexp(regxp)
							return *env.NewNative(ps.Idx, newPipe, "script-pipe")
						default:
							return MakeNativeArgError(ps, 2, []string{"regexp"}, "p-not-match-regexp")
						}
					default:
						return MakeArgError(ps, 2, []env.Type{env.NativeType}, "p-not-match-regexp")
					}
				default:
					return MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-not-match-regexp")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "p-not-match-regexp")
			}
		},
	},

	"replace": {
		Argsn: 3,
		Doc:   "Replaces all occurrences of a string with another string in the pipe and returns a new pipe object.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch p := arg0.(type) {
			case env.Native:
				switch pipe := p.Value.(type) {
				case *script.Pipe:
					switch search := arg1.(type) {
					case env.String:
						switch replace := arg2.(type) {
						case env.String:
							newPipe := pipe.Replace(search.Value, replace.Value)
							return *env.NewNative(ps.Idx, newPipe, "script-pipe")
						default:
							return MakeArgError(ps, 3, []env.Type{env.StringType}, "p-replace")
						}
					default:
						return MakeArgError(ps, 2, []env.Type{env.StringType}, "p-replace")
					}
				default:
					return MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-replace")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "p-replace")
			}
		},
	},

	"replace\\regexp": {
		Argsn: 3,
		Doc:   "Replaces all occurrences of strings that match the regexp pattern with a string in the pipe and returns a new pipe object.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch p := arg0.(type) {
			case env.Native:
				switch pipe := p.Value.(type) {
				case *script.Pipe:
					switch searchR := arg1.(type) {
					case env.Native:
						switch searchRegexp := searchR.Value.(type) {
						case *regexp.Regexp:
							switch replace := arg2.(type) {
							case env.String:
								newPipe := pipe.ReplaceRegexp(searchRegexp, replace.Value)
								return *env.NewNative(ps.Idx, newPipe, "script-pipe")
							default:
								return MakeArgError(ps, 3, []env.Type{env.StringType}, "p-replace-regexp")
							}
						default:
							return MakeNativeArgError(ps, 2, []string{"regexp"}, "p-replace-regexp")
						}
					default:
						return MakeArgError(ps, 2, []env.Type{env.NativeType}, "p-replace-regexp")
					}
				default:
					return MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-replace-regexp")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "p-replace-regexp")
			}
		},
	},

	"into-block": {
		Argsn: 1,
		Doc:   "Returns a block of strings with the contents of the pipe, one per line.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch p := arg0.(type) {
			case env.Native:
				switch pipe := p.Value.(type) {
				case *script.Pipe:
					lines, err := pipe.Slice()
					if err != nil {
						return MakeBuiltinError(ps, err.Error(), "p-block")
					}
					items := make([]env.Object, len(lines))
					for i, line := range lines {
						items[i] = *env.NewString(line)
					}
					return *env.NewBlock(*env.NewTSeries(items))
				default:
					return MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-block")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "p-block")
			}
		},
	},

	"error\\opt": {
		Argsn: 1,
		Doc:   "Returns the error from the pipe, if any.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch p := arg0.(type) {
			case env.Native:
				switch pipe := p.Value.(type) {
				case *script.Pipe:
					err := pipe.Error()
					if err != nil {
						return *env.NewError(err.Error())
					}
					return env.Void{}
				default:
					return MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-error")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "p-error")
			}
		},
	},

	"sha256sum": {
		Argsn: 1,
		Doc:   "Returns the hex-encoded SHA-256 hash of the entire contents of the pipe.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch p := arg0.(type) {
			case env.Native:
				switch pipe := p.Value.(type) {
				case *script.Pipe:
					sha256, err := pipe.SHA256Sum()
					if err != nil {
						return MakeBuiltinError(ps, err.Error(), "pipes/sha256sum")
					}
					return *env.NewString(sha256)
				default:
					return MakeNativeArgError(ps, 1, []string{"script-pipe"}, "pipes/sha256sum")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "pipes/sha256sum")
			}
		},
	},

	"sha256sums": {
		Argsn: 1,
		Doc:   "Reads paths from the pipe, one per line, and produces the hex-encoded SHA-256 hash of each corresponding file, one per line.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch p := arg0.(type) {
			case env.Native:
				switch pipe := p.Value.(type) {
				case *script.Pipe:
					newPipe := pipe.SHA256Sums()
					return *env.NewNative(ps.Idx, newPipe, "script-pipe")
				default:
					return MakeNativeArgError(ps, 1, []string{"script-pipe"}, "pipes/sha256sums")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "pipes/sha256sums")
			}
		},
	},

	"decodeBase64": {
		Argsn: 1,
		Doc:   "decodeBase64 produces the string represented by the base64 encoded input.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch p := arg0.(type) {
			case env.Native:
				switch pipe := p.Value.(type) {
				case *script.Pipe:
					newPipe := pipe.DecodeBase64()
					return *env.NewNative(ps.Idx, newPipe, "script-pipe")
				default:
					return MakeNativeArgError(ps, 1, []string{"script-pipe"}, "decodeBase64")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "decodeBase64")
			}
		},
	},

	"encodeBase64": {
		Argsn: 1,
		Doc:   "encodeBase64 produces the base64 encoding of the input.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch p := arg0.(type) {
			case env.Native:
				switch pipe := p.Value.(type) {
				case *script.Pipe:
					newPipe := pipe.EncodeBase64()
					return *env.NewNative(ps.Idx, newPipe, "script-pipe")
				default:
					return MakeNativeArgError(ps, 1, []string{"script-pipe"}, "encodeBase64")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "encodeBase64")
			}
		},
	},

	"join": {
		Argsn: 1,
		Doc:   "joins all the lines in the pipe's contents into a single space-separated string, which will always end with a newline.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch p := arg0.(type) {
			case env.Native:
				switch pipe := p.Value.(type) {
				case *script.Pipe:
					newPipe := pipe.Join()
					return *env.NewNative(ps.Idx, newPipe, "script-pipe")
				default:
					return MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-join")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "p-join")
			}
		},
	},

	"exit-status": {
		Argsn: 1,
		Doc:   "Returns the integer exit status of a previous command. This will be zero unless the pipe's error status is set and the error matches the pattern.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch p := arg0.(type) {
			case env.Native:
				switch pipe := p.Value.(type) {
				case *script.Pipe:
					status := pipe.ExitStatus()
					return *env.NewInteger(int64(status))
				default:
					return MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-exit-status")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "p-exit-status")
			}
		},
	},

	"args": {
		Argsn: 0,
		Doc:   "Creates a pipe containing the program's command-line arguments from os.Args, excluding the program name, one per line.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			newPipe := script.Args()
			return *env.NewNative(ps.Idx, newPipe, "script-pipe")
		},
	},

	"concat": {
		Argsn: 1,
		Doc:   "concat reads paths from the pipe, one per line, and produces the contents of all the corresponding files in sequence. If there are any errors (for example, non-existent files), these will be ignored, execution will continue, and the pipe's error status will not be set.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch p := arg0.(type) {
			case env.Native:
				switch pipe := p.Value.(type) {
				case *script.Pipe:
					newPipe := pipe.Concat()
					return *env.NewNative(ps.Idx, newPipe, "script-pipe")
				default:
					return MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-concat")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "p-concat")
			}
		},
	},

	"close": {
		Argsn: 1,
		Doc:   "Closes the pipe's associated reader.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch p := arg0.(type) {
			case env.Native:
				switch pipe := p.Value.(type) {
				case *script.Pipe:
					closeErr := pipe.Close()
					if closeErr != nil {
						return *env.NewError("Error closing pipe")
					}
					return *env.NewInteger(0)
				default:
					return MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-close")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "p-close")
			}
		},
	},

	"get": {
		Argsn: 2,
		Doc:   "Get makes an HTTP GET request to url, sending the contents of the pipe as the request body, and produces the server's response.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch p := arg0.(type) {
			case env.Native:
				switch pipe := p.Value.(type) {
				case *script.Pipe:
					switch s := arg1.(type) {
					case env.String:
						newPipe := pipe.Get(s.Value)
						return *env.NewNative(ps.Idx, newPipe, "script-pipe")
					default:
						return MakeArgError(ps, 2, []env.Type{env.StringType}, "p-get")
					}
				default:
					return MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-get")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "p-get")
			}
		},
	},

	"post": {
		Argsn: 2,
		Doc:   "Post makes an HTTP POST request to url, using the contents of the pipe as the request body, and produces the server's response.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch p := arg0.(type) {
			case env.Native:
				switch pipe := p.Value.(type) {
				case *script.Pipe:
					switch s := arg1.(type) {
					case env.String:
						newPipe := pipe.Post(s.Value)
						return *env.NewNative(ps.Idx, newPipe, "script-pipe")
					default:
						return MakeArgError(ps, 2, []env.Type{env.StringType}, "p-post")
					}
				default:
					return MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-post")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "p-post")
			}
		},
	},

	"new": {
		Argsn: 0,
		Doc:   "new creates a new pipe with an empty reader.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			newPipe := script.NewPipe()
			return *env.NewNative(ps.Idx, newPipe, "script-pipe")
		},
	},

	"wait": {
		Argsn: 1,
		Doc:   "Wait reads the pipe to completion and returns any error present on the pipe, or 0 otherwise..",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch p := arg0.(type) {
			case env.Native:
				switch pipe := p.Value.(type) {
				case *script.Pipe:
					waitErr := pipe.Wait()
					if waitErr != nil {
						return *env.NewError("Error in pipe during waiting")
					}
					return *env.NewInteger(0)
				default:
					return MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-wait")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "p-wait")
			}
		},
	},

	"append-to-file": {
		Argsn: 2,
		Doc:   "append-to-file appends the contents of the pipe to the file path, creating it if necessary, and returns the number of bytes successfully written, or an error.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch p := arg0.(type) {
			case env.Native:
				switch pipe := p.Value.(type) {
				case *script.Pipe:
					switch s := arg1.(type) {
					case env.String:
						writtenBytes, err := pipe.AppendFile(s.Value)
						if err != nil {
							return *env.NewError("Error while appending data to files.")
						}
						return *env.NewInteger(writtenBytes)
					case env.Uri:
						writtenBytes, err := pipe.AppendFile(s.Path)
						if err != nil {
							return *env.NewError("Error while appending data to rey-file.")
						}
						return *env.NewInteger(writtenBytes)
					default:
						return MakeArgError(ps, 2, []env.Type{env.StringType, env.UriType}, "p-append-to-file")
					}
				default:
					return MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-append-to-file")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "p-append-to-file")
			}
		},
	},

	"stdin": {
		Argsn: 0,
		Doc:   "Stdin creates a pipe that reads from os.Stdin.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			newPipe := script.Stdin()
			return *env.NewNative(ps.Idx, newPipe, "script-pipe")
		},
	},

	"error": {
		Argsn: 1,
		Doc:   "error - returns any error present on the pipe, or 0 otherwise.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch p := arg0.(type) {
			case env.Native:
				switch pipe := p.Value.(type) {
				case *script.Pipe:
					waitErr := pipe.Error()
					if waitErr != nil {
						return *env.NewError("Error in pipe: " + waitErr.Error())
					}
					return *env.NewInteger(0)
				default:
					return MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-error")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "p-error")
			}
		},
	},

	"set-error": {
		Argsn: 2,
		Doc:   "set-error sets the error err on the pipe and return it.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch p := arg0.(type) {
			case env.Native:
				switch pipe := p.Value.(type) {
				case *script.Pipe:
					switch errStr := arg1.(type) {
					case env.String:
						err := errors.New(errStr.Value)
						pipe.SetError(err)
						return *env.NewNative(ps.Idx, pipe, "script-pipe")
					default:
						return MakeArgError(ps, 2, []env.Type{env.StringType}, "p-set-error")
					}
				default:
					return MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-set-error")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "p-set-error")
			}
		},
	},
}
View Source
var Builtins_prometheus = map[string]*env.Builtin{

	"new-counter": {
		Argsn: 3,
		Doc:   "Creates a new Prometheus counter with the given name, help text, and optional labels.",
		Fn:    __prometheus_new_counter,
	},
	"prometheus-counter//Inc": {
		Argsn: 1,
		Doc:   "Increments a Prometheus counter by 1.",
		Fn:    __prometheus_counter_inc,
	},
	"prometheus-counter//Add": {
		Argsn: 2,
		Doc:   "Adds the given value to a Prometheus counter.",
		Fn:    __prometheus_counter_add,
	},

	"new-gauge": {
		Argsn: 3,
		Doc:   "Creates a new Prometheus gauge with the given name, help text, and optional labels.",
		Fn:    __prometheus_new_gauge,
	},
	"prometheus-gauge//Set": {
		Argsn: 2,
		Doc:   "Sets a Prometheus gauge to the given value.",
		Fn:    __prometheus_gauge_set,
	},
	"prometheus-gauge//Inc": {
		Argsn: 1,
		Doc:   "Increments a Prometheus gauge by 1.",
		Fn:    __prometheus_gauge_inc,
	},
	"prometheus-gauge//Dec": {
		Argsn: 1,
		Doc:   "Decrements a Prometheus gauge by 1.",
		Fn:    __prometheus_gauge_dec,
	},
	"prometheus-gauge//Add": {
		Argsn: 2,
		Doc:   "Adds the given value to a Prometheus gauge.",
		Fn:    __prometheus_gauge_add,
	},
	"prometheus-gauge//Sub": {
		Argsn: 2,
		Doc:   "Subtracts the given value from a Prometheus gauge.",
		Fn:    __prometheus_gauge_sub,
	},

	"new-histogram": {
		Argsn: 4,
		Doc:   "Creates a new Prometheus histogram with the given name, help text, optional buckets, and optional labels.",
		Fn:    __prometheus_new_histogram,
	},
	"prometheus-histogram//Observe": {
		Argsn: 2,
		Doc:   "Observes the given value in a Prometheus histogram.",
		Fn:    __prometheus_histogram_observe,
	},

	"new-summary": {
		Argsn: 4,
		Doc:   "Creates a new Prometheus summary with the given name, help text, optional objectives, and optional labels.",
		Fn:    __prometheus_new_summary,
	},
	"prometheus-summary//Observe": {
		Argsn: 2,
		Doc:   "Observes the given value in a Prometheus summary.",
		Fn:    __prometheus_summary_observe,
	},

	"start-http-server": {
		Argsn: 1,
		Doc:   "Starts a Prometheus HTTP server on the given address (e.g., ':8080').",
		Fn:    __prometheus_start_http_server,
	},

	"new-mutex": {
		Argsn: 0,
		Doc:   "Creates a new mutex for protecting metrics from concurrent access.",
		Fn:    __prometheus_new_mutex,
	},
	"prometheus-mutex//Lock": {
		Argsn: 1,
		Doc:   "Locks a mutex.",
		Fn:    __prometheus_mutex_lock,
	},
	"prometheus-mutex//Unlock": {
		Argsn: 1,
		Doc:   "Unlocks a mutex.",
		Fn:    __prometheus_mutex_unlock,
	},

	"must-register": {
		Argsn: 1,
		Doc:   "Registers a Prometheus collector using MustRegister. Will panic if registration fails.",
		Fn:    __prometheus_must_register,
	},
	"handler": {
		Argsn: 0,
		Doc:   "Returns a Prometheus HTTP handler for custom HTTP server setups.",
		Fn:    __prometheus_handler,
	},
}

Map of Prometheus builtins

View Source
var Builtins_psql = map[string]*env.Builtin{

	"postgres-uri//Open": {
		Argsn: 1,
		Doc:   "Opens a connection to a PostgreSQL database.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch str := arg0.(type) {
			case env.Uri:
				db, err := sql.Open("postgres", "postgresql://"+str.Path)
				if err != nil {

					ps.FailureFlag = true
					errMsg := fmt.Sprintf("Error opening SQL: %v" + err.Error())
					return MakeBuiltinError(ps, errMsg, "postgres-uri//Open")
				} else {

					return *env.NewNative(ps.Idx, db, "Rye-psql")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.UriType}, "postgres-uri//Open")
			}

		},
	},

	"Rye-psql//Exec": {
		Argsn: 2,
		Doc:   "Executes a SQL statement that modifies data (INSERT, UPDATE, DELETE).",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			var sqlstr string
			var vals []any
			switch db1 := arg0.(type) {
			case env.Native:
				switch str := arg1.(type) {
				case env.Block:
					ser := ps.Ser
					ps.Ser = str.Series
					values := make([]any, 0, 2)
					_, vals = SQL_EvalBlock(ps, MODE_PSQL, values)
					sqlstr = ps.Res.(env.String).Value
					ps.Ser = ser
				case env.String:
					sqlstr = str.Value
				default:
					ps.ErrorFlag = true
					return MakeArgError(ps, 2, []env.Type{env.BlockType, env.StringType}, "Rye-psql//Exec")
				}
				if sqlstr != "" {

					db2 := db1.Value.(*sql.DB)
					res, err := db2.Exec(sqlstr, vals...)
					if err != nil {
						ps.FailureFlag = true
						return env.NewError("Error" + err.Error())
					} else {
						num, _ := res.RowsAffected()
						return *env.NewInteger(num)

					}
				} else {
					return MakeBuiltinError(ps, "Sql string is empty.", "Rye-psql//Exec")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Rye-psql//Exec")
			}
		},
	},

	"Rye-psql//Query": {
		Argsn: 2,
		Doc:   "Executes a SQL query and returns results as a table.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			var sqlstr string
			var vals []any
			switch db1 := arg0.(type) {
			case env.Native:
				switch str := arg1.(type) {
				case env.Block:

					ser := ps.Ser
					ps.Ser = str.Series
					values := make([]any, 0, 2)
					_, vals = SQL_EvalBlock(ps, MODE_PSQL, values)
					sqlstr = ps.Res.(env.String).Value
					ps.Ser = ser
				case env.String:
					sqlstr = str.Value
				default:
					ps.ErrorFlag = true
					return MakeArgError(ps, 2, []env.Type{env.BlockType, env.StringType}, "Rye-psql//Query")
				}
				if sqlstr != "" {

					rows, err := db1.Value.(*sql.DB).Query(sqlstr, vals...)

					if err != nil {
						ps.FailureFlag = true
						return MakeBuiltinError(ps, err.Error(), "Rye-psql//Query")
					} else {
						cols, _ := rows.Columns()
						spr := env.NewTable(cols)
						i := 0
						for rows.Next() {

							var sr env.TableRow

							columns := make([]any, len(cols))
							columnPointers := make([]any, len(cols))
							for i := range columns {
								columnPointers[i] = &columns[i]
							}

							if err := rows.Scan(columnPointers...); err != nil {
								ps.FailureFlag = true
								return MakeBuiltinError(ps, "Error scanning row: "+err.Error(), "Rye-psql//Query")
							}

							m := make(map[string]any)
							for i, colName := range cols {
								val := columnPointers[i].(*any)
								// Convert nil (SQL NULL) values to Void{} for proper Rye handling
								var ryeVal env.Object
								if *val == nil {
									ryeVal = env.Void{}
								} else {
									ryeVal = env.ToRyeValue(*val)
								}
								m[colName] = ryeVal
								sr.Values = append(sr.Values, ryeVal)
							}
							spr.AddRow(sr)

							i++
						}
						rows.Close()

						if i == 0 {
							ps.FailureFlag = true
							return MakeBuiltinError(ps, "No data.", "Rye-psql//Query")
						}
						return *spr

					}
				} else {
					return MakeBuiltinError(ps, "Empty SQL.", "Rye-psql//Query")
				}

			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Rye-psql//Query")
			}
		},
	},

	"Rye-psql//Show-SQL": {
		Argsn: 2,
		Doc:   "Generates and returns the SQL string without executing it.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			var sqlstr string
			var vals []any
			switch arg0.(type) {
			case env.Native:
				switch str := arg1.(type) {
				case env.Block:
					ser := ps.Ser
					ps.Ser = str.Series
					values := make([]any, 0, 2)
					_, vals = SQL_EvalBlock(ps, MODE_PSQL, values)
					sqlstr = ps.Res.(env.String).Value
					ps.Ser = ser
				case env.String:
					sqlstr = str.Value
				default:
					ps.ErrorFlag = true
					return MakeArgError(ps, 2, []env.Type{env.BlockType, env.StringType}, "Rye-psql//Show-SQL")
				}
				if sqlstr != "" {

					if len(vals) > 0 {
						result := sqlstr + "\n-- Parameters: "
						for i, val := range vals {
							if i > 0 {
								result += ", "
							}
							result += fmt.Sprintf("$%d = %v", i+1, val)
						}
						return *env.NewString(result)
					}
					return *env.NewString(sqlstr)
				} else {
					return MakeBuiltinError(ps, "Empty SQL.", "Rye-psql//Show-SQL")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Rye-psql//Show-SQL")
			}
		},
	},
}
View Source
var Builtins_regexp = map[string]*env.Builtin{

	"regexp": {
		Argsn: 1,
		Doc:   "Creates a compiled regular expression object from a pattern string.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch s := arg0.(type) {
			case env.String:
				val, err := regexp.Compile(s.Value)
				if err != nil {
					return MakeError(ps, err.Error())
				}
				return *env.NewNative(ps.Idx, val, "regexp")
			default:
				return MakeArgError(ps, 1, []env.Type{env.StringType}, "regexp")
			}
		},
	},

	"re": {
		Argsn: 1,
		Doc:   "Creates a compiled regular expression object from a pattern string.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch s := arg0.(type) {
			case env.String:
				val, err := regexp.Compile(s.Value)
				if err != nil {
					return MakeError(ps, err.Error())
				}
				return *env.NewNative(ps.Idx, val, "regexp")
			default:
				return MakeArgError(ps, 1, []env.Type{env.StringType}, "regexp")
			}
		},
	},

	"regexp//Is-match": {
		Argsn: 2,
		Doc:   "Tests if a string matches the regular expression pattern.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch val := arg1.(type) {
			case env.String:
				switch s := arg0.(type) {
				case env.Native:
					res := s.Value.(*regexp.Regexp).MatchString(val.Value)
					if res {
						return *env.NewBoolean(true)
					} else {
						return *env.NewBoolean(false)
					}
				default:
					return MakeArgError(ps, 1, []env.Type{env.NativeType}, "regexp//Is-match")
				}
			default:
				return MakeArgError(ps, 2, []env.Type{env.StringType}, "regexp//Is-match")
			}
		},
	},

	"regexp//Submatch?": {
		Argsn: 2,
		Doc:   "Extracts the first captured group from a string using the regular expression.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch val := arg1.(type) {
			case env.String:
				switch s := arg0.(type) {
				case env.Native:
					res := s.Value.(*regexp.Regexp).FindStringSubmatch(val.Value)
					if len(res) > 1 {
						return *env.NewString(res[1])
					} else {
						return MakeBuiltinError(ps, "No submatch.", "regexp//Submatch?")
					}
				default:
					return MakeArgError(ps, 1, []env.Type{env.NativeType}, "regexp//Submatch?")
				}
			default:
				return MakeArgError(ps, 2, []env.Type{env.StringType}, "regexp//Submatch?")
			}
		},
	},

	"regexp//Submatches?": {
		Argsn: 2,
		Doc:   "Extracts all captured groups from the first match as a block of strings.",
		Fn: func(env1 *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch val := arg1.(type) {
			case env.String:
				switch s := arg0.(type) {
				case env.Native:
					res := s.Value.(*regexp.Regexp).FindStringSubmatch(val.Value)
					if len(res) > 0 {
						col1 := make([]env.Object, len(res)-1)
						for i, row := range res {
							if i > 0 {
								col1[i-1] = *env.NewString(row)
							}
						}
						return *env.NewBlock(*env.NewTSeries(col1))
					}
					return MakeBuiltinError(env1, "No results", "Submatches?")
				default:
					return MakeError(env1, "Arg2 not Native")
				}
			default:
				return MakeError(env1, "Arg1 not String")
			}
		},
	},

	"regexp//Submatches\\all?": {
		Argsn: 2,
		Doc:   "Extracts all captured groups from all matches as a nested block structure.",
		Fn: func(env1 *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch val := arg1.(type) {
			case env.String:
				switch s := arg0.(type) {
				case env.Native:
					res := s.Value.(*regexp.Regexp).FindAllStringSubmatch(val.Value, -1)
					if len(res) > 0 {
						blks := make([]env.Object, len(res))
						for i, mtch := range res {
							strs := make([]env.Object, len(mtch)-1)
							for j, row := range mtch {
								if j > 0 {
									strs[j-1] = *env.NewString(row)
								}
							}
							blks[i] = *env.NewBlock(*env.NewTSeries(strs))
						}
						return *env.NewBlock(*env.NewTSeries(blks))
					}
					return MakeBuiltinError(env1, "No results", "Submatches?")
				default:
					return MakeError(env1, "Arg2 not Native")
				}
			default:
				return MakeError(env1, "Arg1 not String")
			}
		},
	},

	"regexp//Find-all": {
		Argsn: 2,
		Doc:   "Finds all substrings matching the regular expression and returns them as a block.",
		Fn: func(env1 *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch val := arg1.(type) {
			case env.String:
				switch s := arg0.(type) {
				case env.Native:
					res := s.Value.(*regexp.Regexp).FindAllString(val.Value, -1)
					if len(res) > 0 {
						col1 := make([]env.Object, len(res))
						for i, row := range res {
							col1[i] = *env.NewString(row)
						}
						return *env.NewBlock(*env.NewTSeries(col1))
					}
					return MakeBuiltinError(env1, "No results", "Find-all")
				default:
					return MakeError(env1, "Arg2 not Native")
				}
			default:
				return MakeError(env1, "Arg1 not String")
			}
		},
	},

	"regexp//Match?": {
		Argsn: 2,
		Doc:   "Finds the first substring matching the regular expression.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch val := arg1.(type) {
			case env.String:
				switch s := arg0.(type) {
				case env.Native:
					res := s.Value.(*regexp.Regexp).FindString(val.Value)
					if len(res) > 0 {
						return *env.NewString(res)
					}
					return MakeBuiltinError(ps, "No result", "Match?")
				default:
					return MakeArgError(ps, 1, []env.Type{env.NativeType}, "regexp//Match?")
				}
			default:
				return MakeArgError(ps, 2, []env.Type{env.StringType}, "regexp//Match?")
			}
		},
	},

	"regexp//Replace-all": {
		Argsn: 3,
		Doc:   "Replaces all occurrences of the regular expression pattern with the specified replacement string.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch re := arg0.(type) {
			case env.Native:
				switch val := arg1.(type) {
				case env.String:
					switch replac := arg2.(type) {
					case env.String:
						res := re.Value.(*regexp.Regexp).ReplaceAllString(val.Value, replac.Value)
						return *env.NewString(res)
					default:
						return MakeArgError(ps, 3, []env.Type{env.StringType}, "regexp//Replace-all")
					}
				default:
					return MakeArgError(ps, 2, []env.Type{env.StringType}, "regexp//Replace-all")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "regexp//Replace-all")
			}
		},
	},
}
View Source
var Builtins_smtpd = map[string]*env.Builtin{

	"smtp-server": {
		Argsn: 1,
		Doc:   "Creates a new SMTP server that can receive incoming email messages on the specified address.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {

			return *env.NewNative(ps.Idx, arg0, "smtpd")
		},
	},

	"smtpd//Serve": {
		Argsn: 4,
		Doc:   "Starts the SMTP server listening for incoming emails and calls the handler function for each received message.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch server := arg0.(type) {
			case env.Native:
				switch handler := arg1.(type) {
				case env.Function:
					switch name := arg2.(type) {
					case env.String:

						err := smtpd.ListenAndServe(server.Value.(env.String).Value,
							func(origin net.Addr, from string, to []string, data []byte) error {

								ps.FailureFlag = false
								ps.ErrorFlag = false
								ps.ReturnFlag = false

								psTemp := env.ProgramState{}
								err := copier.Copy(&psTemp, &ps)
								if err != nil {
									fmt.Println(err.Error())
								}

								lstTo := make([]any, len(to))
								for i, v := range to {
									lstTo[i] = v
								}

								CallFunctionArgs4(handler, ps,
									*env.NewNative(ps.Idx, bytes.NewReader(data), "reader"),
									env.NewString(from),
									*env.NewList(lstTo),
									*env.NewNative(ps.Idx, origin, "new-addr"), nil)
								return nil
							}, name.Value, "")
						if err != nil {
							return makeError(ps, err.Error())
						}
						return arg0
					default:
						return MakeArgError(ps, 3, []env.Type{env.StringType}, "smtpd//serve")
					}
				default:
					return MakeArgError(ps, 2, []env.Type{env.FunctionType}, "smtpd//serve")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.StringType}, "smtpd//serve")
			}
		},
	},
}
View Source
var Builtins_sqlite = map[string]*env.Builtin{

	"sqlite-uri//Open": {
		Argsn: 1,
		Doc:   "Opens a connection to a SQLite database file.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {

			switch str := arg0.(type) {
			case env.Uri:

				db, _ := sql.Open("sqlite", str.GetPath())
				return *env.NewNative(ps.Idx, db, "Rye-sqlite")
			default:
				return MakeArgError(ps, 1, []env.Type{env.UriType}, "sqlite-uri//Open")
			}

		},
	},

	"htmlize": {
		Argsn: 1,
		Doc:   "Converts a table to HTML format.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch str := arg0.(type) {
			case env.Table:
				return *env.NewString(str.ToHtml())
			default:
				return MakeArgError(ps, 1, []env.Type{env.TableType}, "htmlize")
			}

		},
	},

	"Rye-sqlite//Exec": {
		Argsn: 2,
		Doc:   "Executes a SQL statement that doesn't return rows.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			var sqlstr string
			var vals []any
			switch db1 := arg0.(type) {
			case env.Native:
				switch str := arg1.(type) {
				case env.Block:

					ser := ps.Ser
					ps.Ser = str.Series
					values := make([]any, 0)
					_, vals = SQL_EvalBlock(ps, MODE_SQLITE, values)
					sqlstr = ps.Res.(env.String).Value
					ps.Ser = ser
				case env.String:
					sqlstr = str.Value
				default:
					return MakeArgError(ps, 2, []env.Type{env.BlockType, env.StringType}, "Rye-sqlite//Exec")
				}
				if sqlstr != "" {
					db2 := db1.Value.(*sql.DB)
					_, err := db2.Exec(sqlstr, vals...)
					if err != nil {
						return MakeBuiltinError(ps, err.Error(), "Rye-sqlite//Exec")
					}

					return arg0
				} else {
					return MakeBuiltinError(ps, "sql string not found.", "Rye-sqlite//Exec")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Rye-sqlite//Exec")
			}
		},
	},

	"Rye-sqlite//Query": {
		Argsn: 2,
		Doc:   "Executes a SQL query and returns results as a table.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			var sqlstr string
			var vals []any
			switch db1 := arg0.(type) {
			case env.Native:
				switch str := arg1.(type) {
				case env.Block:

					ser := ps.Ser
					ps.Ser = str.Series
					values := make([]any, 0)
					_, vals = SQL_EvalBlock(ps, MODE_SQLITE, values)
					sqlstr = ps.Res.(env.String).Value
					ps.Ser = ser
				case env.String:
					sqlstr = str.Value
				default:
					return MakeArgError(ps, 2, []env.Type{env.BlockType, env.StringType}, "Rye-sqlite//Query")
				}
				if sqlstr != "" {
					rows, err := db1.Value.(*sql.DB).Query(sqlstr, vals...)
					if err != nil {
						return MakeBuiltinError(ps, err.Error(), "Rye-sqlite//Query")
					}
					columns, _ := rows.Columns()
					spr := env.NewTable(columns)

					if err != nil {
						fmt.Println(err.Error())
					} else {
						cols, _ := rows.Columns()
						for rows.Next() {
							var sr env.TableRow
							columns := make([]any, len(cols))
							columnPointers := make([]any, len(cols))
							for i := range columns {
								columnPointers[i] = &columns[i]
							}

							if err := rows.Scan(columnPointers...); err != nil {
								return env.NewError(err.Error())
							}

							m := make(map[string]any)
							for i, colName := range cols {
								val := columnPointers[i].(*any)
								// Convert nil (SQL NULL) values to Void{} for proper Rye handling
								var ryeVal env.Object
								if *val == nil {
									ryeVal = env.Void{}
								} else {
									ryeVal = env.ToRyeValue(*val)
								}
								m[colName] = ryeVal
								sr.Values = append(sr.Values, ryeVal)
								sr.Uplink = spr
							}
							spr.AddRow(sr)

						}
						rows.Close()

						return *spr
					}
					return MakeBuiltinError(ps, "Empty SQL.", "Rye-sqlite//Query")
				} else {
					return MakeBuiltinError(ps, "Sql string not found.", "Rye-sqlite//Query")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Rye-sqlite//Query")
			}
		},
	},

	"Rye-sqlite//Show-SQL": {
		Argsn: 2,
		Doc:   "Generates and returns the SQL string without executing it.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			var sqlstr string
			var vals []any
			switch arg0.(type) {
			case env.Native:
				switch str := arg1.(type) {
				case env.Block:
					ser := ps.Ser
					ps.Ser = str.Series
					values := make([]any, 0)
					_, vals = SQL_EvalBlock(ps, MODE_SQLITE, values)
					sqlstr = ps.Res.(env.String).Value
					ps.Ser = ser
				case env.String:
					sqlstr = str.Value
				default:
					return MakeArgError(ps, 2, []env.Type{env.BlockType, env.StringType}, "Rye-sqlite//Show-SQL")
				}
				if sqlstr != "" {

					if len(vals) > 0 {
						result := sqlstr + "\n-- Parameters: "
						for i, val := range vals {
							if i > 0 {
								result += ", "
							}
							result += fmt.Sprintf("? = %v", val)
						}
						return *env.NewString(result)
					}
					return *env.NewString(sqlstr)
				} else {
					return MakeBuiltinError(ps, "Empty SQL.", "Rye-sqlite//Show-SQL")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "Rye-sqlite//Show-SQL")
			}
		},
	},
}
View Source
var Builtins_ssh = map[string]*env.Builtin{}
View Source
var Builtins_stackless = map[string]*env.Builtin{

	"ry0": {
		Argsn: 1,
		Doc:   "TODODOC",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch bloc := arg0.(type) {
			case env.Block:
				ser := ps.Ser
				ps.Ser = bloc.Series
				Stck_EvalBlock(ps)
				ps.Ser = ser
				return ps.Res
			default:
				return MakeArgError(ps, 1, []env.Type{env.BlockType}, "ry0")
			}
		},
	},

	"ry0-loop": {
		Argsn: 2,
		Doc:   "TODODOC",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch cond := arg0.(type) {
			case env.Integer:
				switch bloc := arg1.(type) {
				case env.Block:
					ser := ps.Ser
					ps.Ser = bloc.Series
					for i := 0; int64(i) < cond.Value; i++ {
						ps = Stck_EvalBlock(ps)
						ps.Ser.Reset()
					}
					ps.Ser = ser
					return ps.Res
				default:
					return MakeArgError(ps, 1, []env.Type{env.BlockType}, "ry0-loop")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.IntegerType}, "ry0-loop")
			}
		},
	},
}
View Source
var Builtins_structures = map[string]*env.Builtin{

	"dict->struct": {
		Argsn: 2,
		Doc:   "Converts a Rye Dict to a Go struct using reflection. Takes a Dict and a Native containing a pointer to a struct.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {

			switch dict := arg0.(type) {
			case env.Dict:

				switch native := arg1.(type) {
				case env.Native:

					return dictToStruct(ps, dict, native.Value)
				default:
					return MakeArgError(ps, 2, []env.Type{env.NativeType}, "dict->struct")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.DictType}, "dict->struct")
			}
		},
	},

	"dict->new-struct": {
		Argsn: 2,
		Doc:   "Creates a new Go struct type at runtime based on a Rye Dict and populates it with values. Takes a Dict and a string for the struct name.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {

			switch dict := arg0.(type) {
			case env.Dict:

				switch nameObj := arg1.(type) {
				case env.String:

					structPtr, err := dictToNewStruct(ps, dict, nameObj.Value)
					if err != nil {
						return MakeBuiltinError(ps, err.Error(), "dict->new-struct")
					}

					return *env.NewNative(ps.Idx, structPtr, nameObj.Value)
				default:
					return MakeArgError(ps, 2, []env.Type{env.StringType}, "dict->new-struct")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.DictType}, "dict->new-struct")
			}
		},
	},

	"struct->dict": {
		Argsn: 1,
		Doc:   "Converts a Go struct to a Rye Dict using reflection. Takes a Native containing a struct or pointer to a struct.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {

			switch native := arg0.(type) {
			case env.Native:

				return structToDict(ps, native.Value)
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "struct->dict")
			}
		},
	},

	"process": {
		Argsn: 2,
		Doc:   "TODODOC",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			rm, err := load_structures_Dict(ps, arg1.(env.Block))

			if err != nil {
				ps.FailureFlag = true
				return err
			}
			switch data := arg0.(type) {
			case env.Dict:
				return do_structures(ps, data, rm)
			}
			return nil
		},
	},
}
View Source
var Builtins_sxml = map[string]*env.Builtin{

	"reader//do-sxml": {
		Argsn: 2,
		Doc:   "Processes XML using a streaming SAX-like approach with tag handlers.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			rm, err := load_saxml_Dict(ps, arg1.(env.Block))

			if err != nil {
				ps.FailureFlag = true
				return err
			}
			return do_sxml(ps, arg0.(env.Native).Value.(io.Reader), rm)
		},
	},

	"rye-sxml-start//Attr?": {
		Argsn: 2,
		Doc:   "Retrieves an attribute by index or name from an XML start element.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch obj := arg0.(type) {
			case env.Native:
				switch obj1 := obj.Value.(type) {
				case xml.StartElement:
					switch n := arg1.(type) {
					case env.Integer:
						if int(n.Value) < len(obj1.Attr) {
							attr := obj1.Attr[int(n.Value)]
							return *env.NewList([]any{
								*env.NewString(attr.Name.Space),
								*env.NewString(attr.Name.Local),
								*env.NewString(attr.Value),
							})
						} else {
							return MakeBuiltinError(ps, "Attribute index out of bounds.", "rye-sxml-start//Attr?")
						}
					case env.Word:
						attrName := ps.Idx.GetWord(n.Index)
						for _, attr := range obj1.Attr {
							if attr.Name.Local == attrName {

								return *env.NewString(attr.Value)
							}
						}
						return MakeBuiltinError(ps, "Attribute '"+attrName+"' not found.", "rye-sxml-start//Attr?")
					case env.String:
						attrName := n.Value

						namespaceAndName := strings.Split(attrName, ":")
						if len(namespaceAndName) == 2 {

							targetNS := namespaceAndName[0]
							targetLocal := namespaceAndName[1]
							for _, attr := range obj1.Attr {
								if attr.Name.Space == targetNS && attr.Name.Local == targetLocal {
									return *env.NewString(attr.Value)
								}
							}
						} else {

							for _, attr := range obj1.Attr {
								if attr.Name.Local == attrName {
									return *env.NewString(attr.Value)
								}
							}
						}
						return MakeBuiltinError(ps, "Attribute '"+attrName+"' not found.", "rye-sxml-start//Attr?")
					default:
						return MakeArgError(ps, 2, []env.Type{env.IntegerType, env.WordType, env.StringType}, "rye-sxml-start//Attr?")
					}
				default:
					return MakeBuiltinError(ps, "Not xml-start element.", "rye-sxml-start//Attr?")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "rye-sxml-start//Attr?")
			}
		},
	},

	"rye-sxml-start//Attrs?": {
		Argsn: 1,
		Doc:   "Returns a dict of all attributes from an XML start element.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch obj := arg0.(type) {
			case env.Native:
				switch obj1 := obj.Value.(type) {
				case xml.StartElement:
					data := make(map[string]any)
					for _, attr := range obj1.Attr {
						var key string
						if attr.Name.Space != "" {
							key = attr.Name.Space + ":" + attr.Name.Local
						} else {
							key = attr.Name.Local
						}
						data[key] = *env.NewString(attr.Value)
					}
					return *env.NewDict(data)
				default:
					return MakeBuiltinError(ps, "Not xml-start element.", "rye-sxml-start//Attrs?")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "rye-sxml-start//Attrs?")
			}
		},
	},

	"rye-sxml-start//Name?": {
		Argsn: 1,
		Doc:   "Returns the name of an XML start element.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch obj := arg0.(type) {
			case env.Native:
				switch obj1 := obj.Value.(type) {
				case xml.StartElement:
					return *env.NewString(obj1.Name.Local)
				default:
					return MakeBuiltinError(ps, "Not xml-start element.", "rye-sxml-start//Name?")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "rye-sxml-start//Name?")
			}
		},
	},
}
View Source
var Builtins_table = map[string]*env.Builtin{

	"table": {
		Argsn: 2,
		Doc:   "Creates a table by accepting block of column names and flat block of values",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch header1 := arg0.(type) {
			case env.Block:
				hlen := header1.Series.Len()
				cols, err := ColNames(ps, header1, "table")
				if err != nil {
					return err
				}
				spr := env.NewTable(cols)
				switch data1 := arg1.(type) {
				case env.Block:
					rdata := data1.Series.S

					if hlen > 0 {
						for i := 0; i < len(rdata)/hlen; i++ {
							rowd := make([]any, hlen)
							for ii := 0; ii < hlen; ii++ {
								rowd[ii] = rdata[i*hlen+ii]
							}
							spr.AddRow(*env.NewTableRow(rowd, spr))
						}
					}
					return *spr
				case env.List:
					rdata := data1.Data
					for i := 0; i < len(rdata)/hlen; i++ {
						rowd := make([]any, hlen)
						for ii := 0; ii < hlen; ii++ {
							rowd[ii] = rdata[i*hlen+ii]
						}
						spr.AddRow(*env.NewTableRow(rowd, spr))
					}
					return *spr
				default:
					return MakeArgError(ps, 2, []env.Type{env.BlockType}, "table")
				}

			default:
				return MakeArgError(ps, 1, []env.Type{env.BlockType}, "table")
			}
		},
	},

	"table\\columns": {
		Argsn: 2,
		Doc:   "Creats a table by accepting a block of columns",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) (res env.Object) {
			return SheetFromColumns(ps, arg0, arg1)
		},
	},

	"table\\rows": {
		Argsn: 2,
		Doc:   "Creates a table by accepting a block or list of rows",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) (res env.Object) {
			cols, err := ColNames(ps, arg0, "table\\rows	")
			if err != nil {
				return err
			}
			spr := env.NewTable(cols)
			switch rows := arg1.(type) {
			case env.Block:
				for _, objRow := range rows.Series.S {
					row, err := TableRowsFromBlockOrList(ps, spr, len(cols), objRow)
					if err != nil {
						return err
					}
					spr.AddRow(*row)
				}
				return *spr
			case env.List:
				for _, listRow := range rows.Data {
					row, err := TableRowsFromBlockOrList(ps, spr, len(cols), listRow)
					if err != nil {
						return err
					}
					spr.AddRow(*row)
				}
				return *spr
			default:
				return MakeArgError(ps, 2, []env.Type{env.BlockType, env.ListType}, "table\\rows")
			}
		},
	},

	"to-table": {
		Argsn: 1,
		Doc:   "Creates a table by accepting block or list of dicts",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) (res env.Object) {
			switch block := arg0.(type) {
			case env.Block:
				data := block.Series
				if data.Len() == 0 {
					return MakeBuiltinError(ps, "Block is empty", "to-table")
				}
				k := make(map[string]struct{})
				for _, obj := range data.S {
					switch dict := obj.(type) {
					case env.Dict:
						for key := range dict.Data {
							k[key] = struct{}{}
						}
					default:
						return MakeBuiltinError(ps, "Block must contain only dicts", "to-table")
					}
				}
				var keys []string
				for key := range k {
					keys = append(keys, key)
				}
				spr := env.NewTable(keys)
				for _, obj := range data.S {
					switch dict := obj.(type) {
					case env.Dict:
						row := make([]any, len(keys))
						for i, key := range keys {
							data, ok := dict.Data[key]
							if !ok {
								data = env.Void{}
							}
							row[i] = data
						}
						spr.AddRow(*env.NewTableRow(row, spr))
					}
				}
				return *spr

			case env.List:
				data := block.Data
				if len(data) == 0 {
					return MakeBuiltinError(ps, "List is empty", "to-table")
				}
				k := make(map[string]struct{})
				for _, obj := range data {
					switch dict := obj.(type) {
					case map[string]any:
						for key := range dict {
							k[key] = struct{}{}
						}
					case env.Dict:
						for key := range dict.Data {
							k[key] = struct{}{}
						}
					default:
						return MakeBuiltinError(ps, "List must contain only dicts", "to-table")
					}
				}
				var keys []string
				for key := range k {
					keys = append(keys, key)
				}
				spr := env.NewTable(keys)
				for _, obj := range data {
					row := make([]any, len(keys))
					switch dict := obj.(type) {
					case map[string]any:
						for i, key := range keys {
							data, ok := dict[key]
							if !ok {
								data = env.Void{}
							}
							row[i] = env.ToRyeValue(data)
						}
						spr.AddRow(*env.NewTableRow(row, spr))
					case env.Dict:
						row := make([]any, len(keys))
						for i, key := range keys {
							data, ok := dict.Data[key]
							if !ok {
								data = env.Void{}
							}
							row[i] = env.ToRyeValue(data)
						}
						spr.AddRow(*env.NewTableRow(row, spr))
					}
				}
				return *spr

			default:
				return MakeArgError(ps, 1, []env.Type{env.BlockType, env.ListType}, "to-table")
			}
		},
	},

	"where-equal": {
		Argsn: 3,
		Doc:   "Returns table of rows where specific colum is equal to given value.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch spr := arg0.(type) {
			case *env.Table:
				switch col := arg1.(type) {
				case env.Word:
					return WhereEquals(ps, *spr, ps.Idx.GetWord(col.Index), arg2)
				case env.String:
					return WhereEquals(ps, *spr, col.Value, arg2)
				default:
					return MakeArgError(ps, 2, []env.Type{env.WordType, env.StringType}, "where-equal")
				}
			case env.Table:
				switch col := arg1.(type) {
				case env.Word:
					return WhereEquals(ps, spr, ps.Idx.GetWord(col.Index), arg2)
				case env.String:
					return WhereEquals(ps, spr, col.Value, arg2)
				default:
					return MakeArgError(ps, 2, []env.Type{env.WordType, env.StringType}, "where-equal")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.TableType}, "where-equal")
			}
		},
	},

	"where-not-equal": {
		Argsn: 3,
		Doc:   "Returns table of rows where specific colum is not equal to given value.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch spr := arg0.(type) {
			case *env.Table:
				switch col := arg1.(type) {
				case env.Word:
					return WhereNotEquals(ps, *spr, ps.Idx.GetWord(col.Index), arg2)
				case env.String:
					return WhereNotEquals(ps, *spr, col.Value, arg2)
				default:
					return MakeArgError(ps, 2, []env.Type{env.WordType, env.StringType}, "where-not-equal")
				}
			case env.Table:
				switch col := arg1.(type) {
				case env.Word:
					return WhereNotEquals(ps, spr, ps.Idx.GetWord(col.Index), arg2)
				case env.String:
					return WhereNotEquals(ps, spr, col.Value, arg2)
				default:
					return MakeArgError(ps, 2, []env.Type{env.WordType, env.StringType}, "where-not-equal")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.TableType}, "where-not-equal")
			}
		},
	},

	"where-void": {
		Argsn: 2,
		Doc:   "Returns table of rows where specific colum is equal to given value.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch spr := arg0.(type) {
			case *env.Table:
				switch col := arg1.(type) {
				case env.Word:
					return WhereEquals(ps, *spr, ps.Idx.GetWord(col.Index), env.NewVoid())
				case env.String:
					return WhereEquals(ps, *spr, col.Value, env.NewVoid())
				default:
					return MakeArgError(ps, 2, []env.Type{env.WordType, env.StringType}, "where-equal")
				}
			case env.Table:
				switch col := arg1.(type) {
				case env.Word:
					return WhereEquals(ps, spr, ps.Idx.GetWord(col.Index), env.NewVoid())
				case env.String:
					return WhereEquals(ps, spr, col.Value, env.NewVoid())
				default:
					return MakeArgError(ps, 2, []env.Type{env.WordType, env.StringType}, "where-equal")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.TableType}, "where-equal")
			}
		},
	},

	"where-match": {
		Argsn: 3,
		Doc:   "Returns table of rows where a specific colum matches a regex.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) (res env.Object) {
			var spr *env.Table
			switch sheet := arg0.(type) {
			case env.Table:
				spr = &sheet
			case *env.Table:
				spr = sheet
			default:
				return MakeArgError(ps, 1, []env.Type{env.TableType}, "where-match")
			}
			switch reNative := arg2.(type) {
			case env.Native:
				re, ok := reNative.Value.(*regexp.Regexp)
				if !ok {
					return MakeArgError(ps, 2, []env.Type{env.NativeType}, "where-match")
				}
				switch col := arg1.(type) {
				case env.Word:
					return WhereMatch(ps, spr, ps.Idx.GetWord(col.Index), re)
				case env.String:
					return WhereMatch(ps, spr, col.Value, re)
				default:
					return MakeArgError(ps, 2, []env.Type{env.WordType, env.StringType}, "where-match")
				}
			default:
				return MakeArgError(ps, 3, []env.Type{env.NativeType}, "where-match")
			}
		},
	},

	"where-contains": {
		Argsn: 3,
		Doc:   "Returns table of rows where specific colum contains a given string value.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) (res env.Object) {
			var spr *env.Table
			switch sheet := arg0.(type) {
			case env.Table:
				spr = &sheet
			case *env.Table:
				spr = sheet
			default:
				return MakeArgError(ps, 1, []env.Type{env.TableType}, "where-match")
			}
			switch s := arg2.(type) {
			case env.String:
				switch col := arg1.(type) {
				case env.Word:
					return WhereContains(ps, spr, ps.Idx.GetWord(col.Index), s.Value, false)
				case env.String:
					return WhereContains(ps, spr, col.Value, s.Value, false)
				default:
					return MakeArgError(ps, 2, []env.Type{env.WordType, env.StringType}, "where-contains")
				}
			default:
				return MakeArgError(ps, 3, []env.Type{env.StringType}, "where-contains")
			}
		},
	},

	"where-not-contains": {
		Argsn: 3,
		Doc:   "Returns table of rows where specific colum contains a given string value.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) (res env.Object) {
			var spr *env.Table
			switch sheet := arg0.(type) {
			case env.Table:
				spr = &sheet
			case *env.Table:
				spr = sheet
			default:
				return MakeArgError(ps, 1, []env.Type{env.TableType}, "where-match")
			}
			switch s := arg2.(type) {
			case env.String:
				switch col := arg1.(type) {
				case env.Word:
					return WhereContains(ps, spr, ps.Idx.GetWord(col.Index), s.Value, true)
				case env.String:
					return WhereContains(ps, spr, col.Value, s.Value, true)
				default:
					return MakeArgError(ps, 2, []env.Type{env.WordType, env.StringType}, "where-not-contains")
				}
			default:
				return MakeArgError(ps, 3, []env.Type{env.StringType}, "where-not-contains")
			}
		},
	},

	"where-greater": {
		Argsn: 3,
		Doc:   "Returns table of rows where specific colum is greater than given value.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			var spr *env.Table
			switch sheet := arg0.(type) {
			case env.Table:
				spr = &sheet
			case *env.Table:
				spr = sheet
			default:
				return MakeArgError(ps, 1, []env.Type{env.TableType}, "where-match")
			}
			switch col := arg1.(type) {
			case env.Word:
				return WhereGreater(ps, spr, ps.Idx.GetWord(col.Index), arg2)
			case env.String:
				return WhereGreater(ps, spr, col.Value, arg2)
			default:
				return MakeArgError(ps, 2, []env.Type{env.WordType, env.StringType}, "where-greater")
			}
		},
	},

	"where-lesser": {
		Argsn: 3,
		Doc:   "Returns table of rows where specific colum is lesser than given value.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			var spr *env.Table
			switch sheet := arg0.(type) {
			case env.Table:
				spr = &sheet
			case *env.Table:
				spr = sheet
			default:
				return MakeArgError(ps, 1, []env.Type{env.TableType}, "where-match")
			}
			switch col := arg1.(type) {
			case env.Word:
				return WhereLesser(ps, spr, ps.Idx.GetWord(col.Index), arg2)
			case env.String:
				return WhereLesser(ps, spr, col.Value, arg2)
			default:
				return MakeArgError(ps, 2, []env.Type{env.WordType, env.StringType}, "where-lesser")
			}
		},
	},

	"where-between": {
		Argsn: 4,
		Doc:   "Returns table of rows where specific colum is between given values.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) (res env.Object) {
			var spr *env.Table
			switch sheet := arg0.(type) {
			case env.Table:
				spr = &sheet
			case *env.Table:
				spr = sheet
			default:
				return MakeArgError(ps, 1, []env.Type{env.TableType}, "where-match")
			}
			switch col := arg1.(type) {
			case env.Word:
				return WhereBetween(ps, spr, ps.Idx.GetWord(col.Index), arg2, arg3, false)
			case env.String:
				return WhereBetween(ps, spr, col.Value, arg2, arg3, false)
			default:
				return MakeArgError(ps, 2, []env.Type{env.WordType, env.StringType}, "where-between")
			}
		},
	},

	"where-between\\inclusive": {
		Argsn: 4,
		Doc:   "Returns table of rows where specific colum is between given values.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) (res env.Object) {
			var spr *env.Table
			switch sheet := arg0.(type) {
			case env.Table:
				spr = &sheet
			case *env.Table:
				spr = sheet
			default:
				return MakeArgError(ps, 1, []env.Type{env.TableType}, "where-match")
			}
			switch col := arg1.(type) {
			case env.Word:
				return WhereBetween(ps, spr, ps.Idx.GetWord(col.Index), arg2, arg3, true)
			case env.String:
				return WhereBetween(ps, spr, col.Value, arg2, arg3, true)
			default:
				return MakeArgError(ps, 2, []env.Type{env.WordType, env.StringType}, "where-between")
			}
		},
	},

	"where-in": {
		Argsn: 3,
		Doc:   "Returns table of rows where specific colum value if found in block of values.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) (res env.Object) {
			switch spr := arg0.(type) {
			case env.Table:
				switch s := arg2.(type) {
				case env.Block:
					switch col := arg1.(type) {
					case env.Word:
						return WhereIn(ps, spr, ps.Idx.GetWord(col.Index), s.Series.S)
					case env.String:
						return WhereIn(ps, spr, col.Value, s.Series.S)
					default:
						return MakeArgError(ps, 2, []env.Type{env.WordType, env.StringType}, "where-in")
					}
				default:
					return MakeArgError(ps, 3, []env.Type{env.StringType}, "where-in")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.TableType}, "where-in")
			}
		},
	},

	"where-not-in": {
		Argsn: 3,
		Doc:   "Returns table of rows where specific colum value if found in block of values.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) (res env.Object) {
			switch spr := arg0.(type) {
			case env.Table:
				switch s := arg2.(type) {
				case env.Block:
					switch col := arg1.(type) {
					case env.Word:
						return WhereNotIn(ps, spr, ps.Idx.GetWord(col.Index), s.Series.S)
					case env.String:
						return WhereNotIn(ps, spr, col.Value, s.Series.S)
					default:
						return MakeArgError(ps, 2, []env.Type{env.WordType, env.StringType}, "where-in")
					}
				default:
					return MakeArgError(ps, 3, []env.Type{env.StringType}, "where-in")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.TableType}, "where-in")
			}
		},
	},

	"add-row": {
		Argsn: 2,
		Doc:   "Returns a table with new-row added to it",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch table := arg0.(type) {
			case env.Table:
				switch bloc := arg1.(type) {
				case env.Block:
					vals := make([]any, bloc.Series.Len())
					for i := 0; i < bloc.Series.Len(); i++ {
						vals[i] = bloc.Series.Get(i)
					}
					table.AddRow(*env.NewTableRow(vals, &table))
					return table
				case env.List:
					vals := make([]any, len(bloc.Data))
					for i, v := range bloc.Data {
						vals[i] = env.ToRyeValue(v)
					}
					table.AddRow(*env.NewTableRow(vals, &table))
					return table
				default:
					return MakeArgError(ps, 2, []env.Type{env.BlockType, env.ListType}, "add-row")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.TableType}, "add-row")
			}
		},
	},

	"get-rows": {
		Argsn: 1,
		Doc:   "Get rows as a native. This value can be used in `add-rows` and `add-rows!`",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch spr := arg0.(type) {
			case env.Table:
				rows := spr.GetRows()
				return *env.NewNative(ps.Idx, rows, "table-rows")
			default:
				return MakeArgError(ps, 1, []env.Type{env.TableType}, "get-rows")
			}
		},
	},

	"add-rows": {
		Argsn: 2,
		Doc:   "Add one or more rows to a table",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch spr := arg0.(type) {
			case env.Table:
				switch data1 := arg1.(type) {
				case env.Block:
					data := data1.Series
					for data.Pos() < data.Len() {
						rowd := make([]any, len(spr.Cols))
						for ii := 0; ii < len(spr.Cols); ii++ {
							k1 := data.Pop()
							rowd[ii] = k1
						}
						spr.AddRow(*env.NewTableRow(rowd, &spr))
					}
					return spr
				case env.List:
					data := data1.Data
					for item := range data {
						rowd := make([]any, len(spr.Cols))
						for ii := 0; ii < len(spr.Cols); ii++ {
							k1 := item
							rowd[ii] = k1
						}
						spr.AddRow(*env.NewTableRow(rowd, &spr))
					}
					return spr
				case env.Native:
					spr.Rows = append(spr.Rows, data1.Value.([]env.TableRow)...)
					return spr
				default:
					fmt.Println(data1.Inspect(*ps.Idx))
					return MakeArgError(ps, 2, []env.Type{env.BlockType, env.NativeType}, "add-rows")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.TableType}, "add-rows")
			}
		},
	},

	"add-rows!": {
		Argsn: 2,
		Doc:   "Add one or more rows to a table ref",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch spr := arg0.(type) {
			case *env.Table:
				switch data1 := arg1.(type) {
				case env.Block:
					data := data1.Series
					for data.Pos() < data.Len() {
						rowd := make([]any, len(spr.Cols))
						for ii := 0; ii < len(spr.Cols); ii++ {
							k1 := data.Pop()
							rowd[ii] = k1
						}
						spr.AddRow(*env.NewTableRow(rowd, spr))
					}
					return spr
				case env.Native:
					spr.Rows = append(spr.Rows, data1.Value.([]env.TableRow)...)
					return spr
				default:
					return MakeArgError(ps, 2, []env.Type{env.BlockType, env.NativeType}, "add-rows!")
				}
			case *env.PersistentTable:
				switch data1 := arg1.(type) {
				case env.Block:
					data := data1.Series
					for data.Pos() < data.Len() {
						rowd := make([]any, len(spr.Cols))
						for ii := 0; ii < len(spr.Cols); ii++ {
							k1 := data.Pop()
							rowd[ii] = k1
						}
						spr.AddRow(*env.NewTableRow(rowd, spr))
					}
					return spr
				default:
					return MakeArgError(ps, 2, []env.Type{env.BlockType}, "add-rows!")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.TableType, env.PersistentTableType}, "add-rows!")
			}
		},
	},

	"update-row!": {
		Argsn: 3,
		Doc:   `Update the row at the given index.`,
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch spr := arg0.(type) {
			case *env.Table:
				switch idx := arg1.(type) {
				case env.Integer:
					if idx.Value < 1 || (idx.Value-1) > int64(len(spr.Rows)) {
						errMsg := fmt.Sprintf("update-row! called with row index %d, but table only has %d rows", idx.Value, len(spr.Rows))
						return makeError(ps, errMsg)
					}
					switch updater := arg2.(type) {
					case env.Function:
						CallFunction_CollectArgs(updater, ps, spr.Rows[idx.Value-1], false, ps.Ctx)
						ret := ps.Res
						if ok, err, row := RyeValueToTableRow(spr, ret); ok {
							spr.Rows[idx.Value-1] = *row
							return spr
						} else if len(err) > 0 {
							return makeError(ps, err)
						} else {
							return makeError(ps, fmt.Sprintf(
								"Function given to update-row! should have returned a Dict or a TableRow, but returned a %s %#v instead",
								NameOfRyeType(ret.Type()), ret,
							))
						}
					case env.Dict:

						row := spr.Rows[idx.Value-1]

						for keyStr, val := range updater.Data {
							index := spr.GetColumnIndex(keyStr)
							if index < 0 {
								return makeError(ps, "Column "+keyStr+" was not found")
							}
							row.Values[index] = val
						}
						return spr
					case env.TableRow:
						spr.Rows[idx.Value-1] = updater
						return spr
					default:
						return MakeArgError(ps, 3, []env.Type{env.FunctionType, env.DictType, env.TableRowType}, "update-row!")
					}
				default:
					return MakeArgError(ps, 2, []env.Type{env.IntegerType}, "update-row!")
				}
			default:
				return MakeNeedsThawedArgError(ps, "update-row!")
			}

		},
	},

	"remove-row!": {
		Argsn: 2,
		Doc:   "Remove a row from a table by index",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch spr := arg0.(type) {
			case *env.Table:
				switch data1 := arg1.(type) {
				case env.Integer:
					if data1.Value > 0 && data1.Value <= int64(len(spr.Rows)) {
						spr.RemoveRowByIndex(data1.Value - 1)
						return spr
					} else {
						return makeError(ps, fmt.Sprintf("Table had less then %d rows", data1.Value))
					}
				default:
					return MakeArgError(ps, 2, []env.Type{env.BlockType, env.NativeType}, "remove-row!")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.TableType}, "remove-row!")
			}
		},
	},

	"columns?": {
		Argsn: 2,
		Doc:   "Returns table with just given columns. Use lsetwords (:newName) to rename the previous column.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch spr := arg0.(type) {
			case env.Table:
				switch col := arg1.(type) {
				case env.Block:
					cols := make([]string, 0)
					colNames := make([]string, 0)

					for _, obj := range col.Series.S {
						switch ww := obj.(type) {
						case env.String:
							cols = append(cols, ww.Value)
							colNames = append(colNames, ww.Value)
						case env.Tagword:
							colName := ps.Idx.GetWord(ww.Index)
							cols = append(cols, colName)
							colNames = append(colNames, colName)
						case env.LSetword:

							if len(colNames) == 0 {
								return MakeBuiltinError(ps, "LSetword :"+ps.Idx.GetWord(ww.Index)+" found but no previous column to rename", "columns?")
							}

							newName := ps.Idx.GetWord(ww.Index)
							colNames[len(colNames)-1] = newName
						default:
							return MakeBuiltinError(ps, "Expected string, tagword, or lsetword in columns specification", "columns?")
						}
					}
					return spr.ColumnsRenamed(ps, cols, colNames)
				default:
					return MakeArgError(ps, 1, []env.Type{env.BlockType}, "columns?")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.TableType}, "columns?")
			}
		},
	},

	"header?": {
		Argsn: 1,
		Doc:   "Gets the column names (header) as block.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch spr := arg0.(type) {
			case *env.Table:
				return spr.GetColumns()
			case env.Table:
				return spr.GetColumns()
			default:
				return MakeArgError(ps, 1, []env.Type{env.TableType}, "headers?")
			}
		},
	},

	"column?": {
		Argsn: 2,
		Doc:   "Gets all values of a column as a block.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) (res env.Object) {
			switch spr := arg0.(type) {
			case env.Table:
				switch col := arg1.(type) {
				case env.Word:
					res := spr.GetColumn(ps.Idx.GetWord(col.Index))
					if _, isErr := res.(*env.Error); isErr {
						ps.FailureFlag = true
					}
					return res
				case env.String:
					res := spr.GetColumn(col.Value)
					if _, isErr := res.(*env.Error); isErr {
						ps.FailureFlag = true
					}
					return res
				default:
					return MakeArgError(ps, 2, []env.Type{env.WordType, env.StringType}, "column?")
				}
			case env.Block:
				switch col := arg1.(type) {
				case env.Integer:
					col1 := make([]env.Object, len(spr.Series.S))
					if col.Value < 0 {
						return MakeBuiltinError(ps, "Index can't be negative", "column?")
					}
					for i, item_ := range spr.Series.S {
						switch item := item_.(type) {
						case env.Block:
							if len(item.Series.S) < int(col.Value) {
								return MakeBuiltinError(ps, "index out of bounds for item: "+strconv.Itoa(i), "column?")
							}
							col1[i] = item.Series.S[col.Value]
						}
					}
					return *env.NewBlock(*env.NewTSeries(col1))
				default:
					return MakeArgError(ps, 2, []env.Type{env.WordType, env.StringType}, "column?")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.TableType}, "column?")
			}
		},
	},

	"drop-column": {
		Argsn: 2,
		Doc:   "Remove a column from a table. Returns new table",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch spr := arg0.(type) {
			case env.Table:
				switch rmCol := arg1.(type) {
				case env.Word:
					return DropColumn(ps, spr, *env.NewString(ps.Idx.GetWord(rmCol.Index)))
				case env.String:
					return DropColumn(ps, spr, rmCol)
				case env.Block:
					return DropColumnBlock(ps, spr, rmCol)
				default:
					return MakeArgError(ps, 2, []env.Type{env.WordType, env.StringType, env.BlockType}, "drop-column")
				}
			}
			return MakeArgError(ps, 1, []env.Type{env.TableType}, "drop-column")
		},
	},

	"rename-column!": {
		Argsn: 3,
		Doc:   "Remove a column from a table. Returns new table",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch spr := arg0.(type) {
			case *env.Table:
				switch oldName := arg1.(type) {
				case env.String:
					switch newName := arg2.(type) {
					case env.String:
						return RenameColumn(ps, spr, oldName, newName)
					default:
						return MakeArgError(ps, 2, []env.Type{env.WordType, env.BlockType}, "rename-column")
					}
				default:
					return MakeArgError(ps, 2, []env.Type{env.WordType, env.BlockType}, "rename-column")
				}
			}
			return MakeArgError(ps, 1, []env.Type{env.TableType}, "rename-column")
		},
	},

	"gen-column": {
		Argsn: 4,
		Doc:   "Adds a new column to table. Changes in-place and returns the new table.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch spr := arg0.(type) {
			case env.Table:
				switch newCol := arg1.(type) {
				case env.Word:
					switch fromCols := arg2.(type) {
					case env.Block:
						switch code := arg3.(type) {
						case env.Block:
							return GenerateColumn(ps, spr, newCol, fromCols, code)
						default:
							return MakeArgError(ps, 4, []env.Type{env.BlockType}, "gen-column")
						}
					case env.Word:
						switch replaceBlock := arg3.(type) {
						case env.Block:
							if replaceBlock.Series.Len() != 2 {
								return MakeBuiltinError(ps, "Replacement block must contain a regex object and replacement string.", "genadd-umn")
							}
							regexNative, ok := replaceBlock.Series.S[0].(env.Native)
							if !ok {
								return MakeBuiltinError(ps, "First element of replacement block must be a regex object.", "genaddumn")
							}
							regex, ok := regexNative.Value.(*regexp.Regexp)
							if !ok {
								return MakeBuiltinError(ps, "First element of replacement block must be a regex object.", "gen-column")
							}
							replaceStr, ok := replaceBlock.Series.S[1].(env.String)
							if !ok {
								return MakeBuiltinError(ps, "Second element of replacement block must be a string.", "gen-column")
							}
							err := GenerateColumnRegexReplace(ps, &spr, newCol, fromCols, regex, replaceStr.Value)
							if err != nil {
								return err
							}
							return spr
						default:
							return MakeArgError(ps, 3, []env.Type{env.BlockType}, "gen-column")
						}
					default:
						return MakeArgError(ps, 3, []env.Type{env.BlockType}, "gen-column")
					}
				default:
					return MakeArgError(ps, 2, []env.Type{env.WordType}, "gen-column")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.TableType}, "gen-column")
			}
		},
	},

	"add-column": {
		Argsn: 3,
		Doc:   "Adds a new column to table with the given data. Returns the modified table.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch spr := arg0.(type) {
			case env.Table:
				var colName string
				switch col := arg1.(type) {
				case env.Word:
					colName = ps.Idx.GetWord(col.Index)
				case env.String:
					colName = col.Value
				default:
					return MakeArgError(ps, 2, []env.Type{env.WordType, env.StringType}, "add-column")
				}

				numRows := len(spr.Rows)

				switch data := arg2.(type) {
				case env.Block:

					if data.Series.Len() != numRows {
						return MakeBuiltinError(ps, fmt.Sprintf("Column data has %d values but table has %d rows", data.Series.Len(), numRows), "add-column")
					}

					spr.Cols = append(spr.Cols, colName)

					for i, row := range spr.Rows {
						row.Values = append(row.Values, data.Series.S[i])
						spr.Rows[i] = row
					}
					return spr
				case env.List:
					if len(data.Data) != numRows {
						return MakeBuiltinError(ps, fmt.Sprintf("Column data has %d values but table has %d rows", len(data.Data), numRows), "add-column")
					}

					spr.Cols = append(spr.Cols, colName)

					for i, row := range spr.Rows {
						row.Values = append(row.Values, env.ToRyeValue(data.Data[i]))
						spr.Rows[i] = row
					}
					return spr
				default:
					return MakeArgError(ps, 3, []env.Type{env.BlockType, env.ListType}, "add-column")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.TableType}, "add-column")
			}
		},
	},

	"order-by!": {
		Argsn: 3,
		Doc:   "Sorts row by given column, changes table in place.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			dir, ok := arg2.(env.Word)
			if !ok {
				return MakeArgError(ps, 3, []env.Type{env.WordType}, "sort-by!")
			}
			var dirAsc bool
			if dir.Index == ps.Idx.IndexWord("asc") {
				dirAsc = true
			} else if dir.Index == ps.Idx.IndexWord("desc") {
				dirAsc = false
			} else {
				return MakeBuiltinError(ps, "Direction can be just asc or desc.", "sort-by!")
			}
			switch spr := arg0.(type) {
			case env.Table:
				switch col := arg1.(type) {
				case env.String:
					if dirAsc {
						SortByColumn(ps, &spr, col.Value)
					} else {
						SortByColumnDesc(ps, &spr, col.Value)
					}
					return spr
				case env.Word:
					if dirAsc {
						SortByColumn(ps, &spr, ps.Idx.GetWord(col.Index))
					} else {
						SortByColumnDesc(ps, &spr, ps.Idx.GetWord(col.Index))
					}
					return spr
				default:
					return MakeArgError(ps, 2, []env.Type{env.WordType}, "sort-by!")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.TableType}, "sort-by!")
			}
		},
	},

	"order-by": {
		Argsn: 3,
		Doc:   "Sorts row by given column, changes table in place.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			dir, ok := arg2.(env.Word)
			if !ok {
				return MakeArgError(ps, 3, []env.Type{env.WordType}, "sort-by!")
			}
			var dirAsc bool
			if dir.Index == ps.Idx.IndexWord("asc") {
				dirAsc = true
			} else if dir.Index == ps.Idx.IndexWord("desc") {
				dirAsc = false
			} else {
				return MakeBuiltinError(ps, "Direction can be just asc or desc.", "sort-by!")
			}
			switch spr := arg0.(type) {
			case env.Table:
				copied := make([]env.TableRow, len(spr.Rows))
				copy(copied, spr.Rows)
				newSpr := env.NewTable(spr.Cols)
				newSpr.Rows = copied
				switch col := arg1.(type) {
				case env.String:
					if dirAsc {
						SortByColumn(ps, newSpr, col.Value)
					} else {
						SortByColumnDesc(ps, newSpr, col.Value)
					}
					return *newSpr
				case env.Word:
					if dirAsc {
						SortByColumn(ps, newSpr, ps.Idx.GetWord(col.Index))
					} else {
						SortByColumnDesc(ps, newSpr, ps.Idx.GetWord(col.Index))
					}
					return *newSpr
				default:
					return MakeArgError(ps, 2, []env.Type{env.WordType}, "sort-by!")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.TableType}, "sort-by!")
			}
		},
	},

	"add-indexes!": {
		Argsn: 2,
		Doc:   "Creates an index for all values in the provided columns. Changes in-place and returns the new table.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch spr := arg0.(type) {
			case env.Table:
				switch col := arg1.(type) {
				case env.Block:
					colWords := make([]env.Word, col.Series.Len())
					for c := range col.Series.S {
						switch ww := col.Series.S[c].(type) {
						case env.Word:
							colWords[c] = ww
						default:
							return MakeError(ps, "Block of tagwords needed")
						}
					}
					err := AddIndexes(ps, &spr, colWords)
					if err != nil {
						return err
					}
					return spr
				default:
					return MakeArgError(ps, 2, []env.Type{env.BlockType}, "add-indexes!")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.TableType}, "add-indexes!")
			}
		},
	},

	"indexes?": {
		Argsn: 1,
		Doc:   "Returns the columns that are indexed in a table.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) (res env.Object) {
			switch spr := arg0.(type) {
			case env.Table:
				res := make([]env.Object, 0)
				for col := range spr.Indexes {
					res = append(res, *env.NewString(col))
				}
				return *env.NewBlock(*env.NewTSeries(res))
			default:
				return MakeArgError(ps, 1, []env.Type{env.TableType}, "indexes?")
			}
		},
	},

	"autotype": {
		Argsn: 2,
		Doc:   "Takes a table and tries to determine and change the types of columns.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) (res env.Object) {
			switch spr := arg0.(type) {
			case env.Table:
				switch percent := arg1.(type) {
				case env.Decimal:
					return AutoType(ps, &spr, percent.Value)
				default:
					return MakeArgError(ps, 2, []env.Type{env.DecimalType}, "autotype")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.TableType}, "autotype")
			}
		},
	},

	"left-join": {
		Argsn: 4,
		Doc:   "Left joins two tables on the given columns.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) (res env.Object) {
			switch spr1 := arg0.(type) {
			case env.Table:
				switch spr2 := arg1.(type) {
				case env.Table:
					switch col1 := arg2.(type) {
					case env.Word:
						col2, ok := arg3.(env.Word)
						if !ok {
							return MakeArgError(ps, 4, []env.Type{env.WordType}, "left-join")
						}
						return LeftJoin(ps, spr1, spr2, ps.Idx.GetWord(col1.Index), ps.Idx.GetWord(col2.Index), false)
					case env.String:
						col2, ok := arg3.(env.String)
						if !ok {
							MakeArgError(ps, 4, []env.Type{env.StringType}, "left-join")
						}
						return LeftJoin(ps, spr1, spr2, col1.Value, col2.Value, false)
					default:
						return MakeArgError(ps, 3, []env.Type{env.WordType, env.StringType}, "left-join")
					}
				default:
					return MakeArgError(ps, 2, []env.Type{env.TableType}, "left-join")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.TableType}, "left-join")
			}
		},
	},

	"inner-join": {
		Argsn: 4,
		Doc:   "Inner joins two tables on the given columns.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) (res env.Object) {
			switch spr1 := arg0.(type) {
			case env.Table:
				switch spr2 := arg1.(type) {
				case env.Table:
					switch col1 := arg2.(type) {
					case env.Word:
						col2, ok := arg3.(env.Word)
						if !ok {
							return MakeArgError(ps, 4, []env.Type{env.WordType}, "inner-join")
						}
						return LeftJoin(ps, spr1, spr2, ps.Idx.GetWord(col1.Index), ps.Idx.GetWord(col2.Index), true)
					case env.String:
						col2, ok := arg3.(env.String)
						if !ok {
							MakeArgError(ps, 4, []env.Type{env.StringType}, "inner-join")
						}
						return LeftJoin(ps, spr1, spr2, col1.Value, col2.Value, true)
					default:
						return MakeArgError(ps, 3, []env.Type{env.WordType, env.StringType}, "inner-join")
					}
				default:
					return MakeArgError(ps, 2, []env.Type{env.TableType}, "inner-join")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.TableType}, "inner-join")
			}
		},
	},

	"group-by": {
		Argsn: 3,
		Doc:   "Groups a table by the given column(s) and (optional) aggregations.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) (res env.Object) {
			switch spr := arg0.(type) {
			case env.Table:
				switch aggBlock := arg2.(type) {
				case env.Block:
					if len(aggBlock.Series.S)%2 != 0 {
						return MakeBuiltinError(ps, "Aggregation block must contain pairs of column name and function for each aggregation.", "group-by")
					}
					aggregations := make(map[string][]string)
					for i := 0; i < len(aggBlock.Series.S); i += 2 {
						col := aggBlock.Series.S[i]
						fun, ok := aggBlock.Series.S[i+1].(env.Word)
						if !ok {
							return MakeBuiltinError(ps, "Aggregation function must be a word", "group-by")
						}
						colStr := ""
						switch col := col.(type) {
						case env.Tagword:
							colStr = ps.Idx.GetWord(col.Index)
						case env.String:
							colStr = col.Value
						default:
							return MakeBuiltinError(ps, "Aggregation column must be a word or string", "group-by")
						}
						funStr := ps.Idx.GetWord(fun.Index)
						aggregations[colStr] = append(aggregations[colStr], funStr)
					}
					switch col := arg1.(type) {
					case env.Word:
						return GroupBy(ps, spr, []string{ps.Idx.GetWord(col.Index)}, aggregations)
					case env.String:
						return GroupBy(ps, spr, []string{col.Value}, aggregations)
					case env.Block:
						cols := make([]string, col.Series.Len())
						for c := range col.Series.S {
							switch ww := col.Series.S[c].(type) {
							case env.String:
								cols[c] = ww.Value
							case env.Tagword:
								cols[c] = ps.Idx.GetWord(ww.Index)
							case env.Word:
								cols[c] = ps.Idx.GetWord(ww.Index)
							default:
								return MakeBuiltinError(ps, "Block must contain only strings or words for column names", "group-by")
							}
						}
						return GroupBy(ps, spr, cols, aggregations)
					default:
						return MakeArgError(ps, 2, []env.Type{env.WordType, env.StringType, env.BlockType}, "group-by")
					}
				default:
					return MakeArgError(ps, 3, []env.Type{env.BlockType}, "group-by")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.TableType}, "group-by")
			}
		},
	},

	"A1": {
		Argsn: 1,
		Doc:   "Accepts a Table and returns the first row first column cell.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch s0 := arg0.(type) {
			case env.Table:
				r := s0.Rows[0].Values[0]
				return env.ToRyeValue(r)

			default:
				ps.ErrorFlag = true
				return env.NewError("first arg not table")
			}
		},
	},

	"B1": {
		Argsn: 1,
		Doc:   "Accepts a Table and returns the first row second column cell.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch s0 := arg0.(type) {
			case env.Table:
				r := s0.Rows[0].Values[1]
				return env.ToRyeValue(r)

			default:
				ps.ErrorFlag = true
				return env.NewError("first arg not table")
			}
		},
	},

	"A2": {
		Argsn: 1,
		Doc:   "Accepts a Table and returns the second row first column cell.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch s0 := arg0.(type) {
			case env.Table:
				r := s0.Rows[1].Values[0]
				return env.ToRyeValue(r)

			default:
				ps.ErrorFlag = true
				return env.NewError("first arg not table")
			}
		},
	},

	"B2": {
		Argsn: 1,
		Doc:   "Accepts a Table and returns the second row second column cell.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch s0 := arg0.(type) {
			case env.Table:
				r := s0.Rows[1].Values[1]
				return env.ToRyeValue(r)

			default:
				ps.ErrorFlag = true
				return env.NewError("first arg not table")
			}
		},
	},

	"file-uri//Load\\csv": {

		Argsn: 1,
		Doc:   "Loads a .csv file to a table datatype.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch file := arg0.(type) {
			case env.Uri:

				f, err := os.Open(file.GetPath())
				if err != nil {

					return MakeBuiltinError(ps, "Unable to read input file:"+err.Error(), "Load\\csv")
				}
				defer f.Close()

				csvReader := csv.NewReader(f)
				rows, err := csvReader.ReadAll()
				if err != nil {

					return MakeBuiltinError(ps, "Unable to parse file as CSV: "+err.Error(), "Load\\csv")
				}
				if len(rows) == 0 {
					return MakeBuiltinError(ps, "File is empty", "Load\\csv")
				}
				spr := env.NewTable(rows[0])

				if len(rows) > 1 {
					for _, row := range rows[1:] {
						anyRow := make([]any, len(row))
						for i, v := range row {
							anyRow[i] = *env.NewString(v)
						}
						spr.AddRow(*env.NewTableRow(anyRow, spr))
					}
				}
				return *spr
			default:
				return MakeArgError(ps, 1, []env.Type{env.UriType}, "Load\\csv")
			}
		},
	},

	"file-uri//Load\\csv\\": {

		Argsn: 2,
		Doc:   "Loads a .csv file to a table datatype.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch file := arg0.(type) {
			case env.Uri:
				switch separator := arg1.(type) {
				case env.String:

					f, err := os.Open(file.GetPath())
					if err != nil {

						return MakeBuiltinError(ps, "Unable to read input file:"+err.Error(), "Load\\csv")
					}
					defer f.Close()

					csvReader := csv.NewReader(f)
					if len(separator.Value) != 1 {
						return MakeBuiltinError(ps, "Separator must be exactly 1 character long", "Load\\csv\\")
					}
					csvReader.Comma = rune(separator.Value[0])
					rows, err := csvReader.ReadAll()
					if err != nil {

						return MakeBuiltinError(ps, "Unable to parse file as CSV: "+err.Error(), "Load\\csv")
					}
					if len(rows) == 0 {
						return MakeBuiltinError(ps, "File is empty", "Load\\csv")
					}
					spr := env.NewTable(rows[0])

					if len(rows) > 1 {
						for _, row := range rows[1:] {
							anyRow := make([]any, len(row))
							for i, v := range row {
								anyRow[i] = *env.NewString(v)
							}
							spr.AddRow(*env.NewTableRow(anyRow, spr))
						}
					}
					return *spr
				default:
					return MakeArgError(ps, 2, []env.Type{env.StringType}, "Load\\csv\\")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.UriType}, "Load\\csv\\")
			}
		},
	},

	"file-uri//Load\\tsv": {

		Argsn: 1,
		Doc:   "Loads a .csv file to a table datatype.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch file := arg0.(type) {
			case env.Uri:

				f, err := os.Open(file.GetPath())
				if err != nil {

					return MakeBuiltinError(ps, "Unable to read input file:"+err.Error(), "Load\\csv")
				}
				defer f.Close()

				csvReader := csv.NewReader(f)
				csvReader.Comma = '\t'
				rows, err := csvReader.ReadAll()
				if err != nil {

					return MakeBuiltinError(ps, "Unable to parse file as CSV: "+err.Error(), "Load\\csv")
				}
				if len(rows) == 0 {
					return MakeBuiltinError(ps, "File is empty", "Load\\csv")
				}
				spr := env.NewTable(rows[0])

				if len(rows) > 1 {
					for _, row := range rows[1:] {
						anyRow := make([]any, len(row))
						for i, v := range row {
							anyRow[i] = *env.NewString(v)
						}
						spr.AddRow(*env.NewTableRow(anyRow, spr))
					}
				}
				return *spr
			default:
				return MakeArgError(ps, 1, []env.Type{env.UriType}, "Load\\csv")
			}
		},
	},

	"save\\csv": {
		Argsn: 2,
		Doc:   "Saves a table to a .csv file.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch spr := arg0.(type) {
			case env.Table:
				switch file := arg1.(type) {
				case env.Uri:

					f, err := os.Create(file.GetPath())
					if err != nil {

						return MakeBuiltinError(ps, "Unable to create input file.", "save\\csv")
					}
					defer f.Close()

					cLen := len(spr.Cols)

					csvWriter := csv.NewWriter(f)

					err1 := csvWriter.Write(spr.Cols)
					if err1 != nil {
						return MakeBuiltinError(ps, "Unable to create write header.", "save\\csv")
					}

					for ir, row := range spr.Rows {
						strVals := make([]string, cLen)

						for i, v := range row.Values {
							var sv string
							switch tv := v.(type) {
							case string:
								sv = tv
							case int64:
								sv = strconv.Itoa(int(tv))
							case float64:
								sv = strconv.FormatFloat(tv, 'f', -1, 64)
							case env.String:
								sv = tv.Value
							case env.Integer:
								sv = strconv.Itoa(int(tv.Value))
							case env.Decimal:
								sv = fmt.Sprintf("%f", tv.Value)
							}
							if i < cLen {
								strVals[i] = sv
							}
						}
						err := csvWriter.Write(strVals)
						if err != nil {
							return MakeBuiltinError(ps, "Unable to write line: "+strconv.Itoa(ir), "save\\csv")
						}
					}
					csvWriter.Flush()
					f.Close()
					return spr
				default:
					return MakeArgError(ps, 1, []env.Type{env.UriType}, "save\\csv")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.UriType}, "save\\csv")
			}
		},
	},

	"save\\tsv": {
		Argsn: 2,
		Doc:   "Saves a table to a .csv file.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch spr := arg0.(type) {
			case env.Table:
				switch file := arg1.(type) {
				case env.Uri:

					f, err := os.Create(file.GetPath())
					if err != nil {

						return MakeBuiltinError(ps, "Unable to create input file.", "save\\csv")
					}
					defer f.Close()

					cLen := len(spr.Cols)

					csvWriter := csv.NewWriter(f)
					csvWriter.Comma = '\t'
					err1 := csvWriter.Write(spr.Cols)
					if err1 != nil {
						return MakeBuiltinError(ps, "Unable to create write header.", "save\\csv")
					}

					for ir, row := range spr.Rows {
						strVals := make([]string, cLen)

						for i, v := range row.Values {
							var sv string
							switch tv := v.(type) {
							case string:
								sv = tv
							case int64:
								sv = strconv.Itoa(int(tv))
							case float64:
								sv = strconv.FormatFloat(tv, 'f', -1, 64)
							case env.String:
								sv = tv.Value
							case env.Integer:
								sv = strconv.Itoa(int(tv.Value))
							case env.Decimal:
								sv = fmt.Sprintf("%f", tv.Value)
							}
							if i < cLen {
								strVals[i] = sv
							}
						}
						err := csvWriter.Write(strVals)
						if err != nil {
							return MakeBuiltinError(ps, "Unable to write line: "+strconv.Itoa(ir), "save\\csv")
						}
					}
					csvWriter.Flush()
					f.Close()
					return spr
				default:
					return MakeArgError(ps, 1, []env.Type{env.UriType}, "save\\csv")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.UriType}, "save\\csv")
			}
		},
	},

	"file-uri//Load\\xlsx": {
		Argsn: 1,
		Doc:   "Loads the first sheet in an .xlsx file to a Table.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch file := arg0.(type) {
			case env.Uri:
				f, err := excelize.OpenFile(file.GetPath())
				if err != nil {
					return MakeBuiltinError(ps, fmt.Sprintf("Unable to open file: %s", err), "Load\\xlsx")
				}
				defer f.Close()

				sheetMap := f.GetSheetMap()
				if len(sheetMap) == 0 {
					return MakeBuiltinError(ps, "No sheets found in file", "Load\\xlsx")
				}

				sheetName := sheetMap[1]
				rows, err := f.Rows(sheetName)
				if err != nil {
					return MakeBuiltinError(ps, fmt.Sprintf("Unable to get rows from sheet: %s", err), "Load\\xlsx")
				}
				rows.Next()
				header, err := rows.Columns()
				if err != nil {
					return MakeBuiltinError(ps, fmt.Sprintf("Unable to get columns from sheet: %s", err), "Load\\xlsx")
				}
				if len(header) == 0 {
					return MakeBuiltinError(ps, "Header row is empty", "Load\\xlsx")
				}
				spr := env.NewTable(header)
				for rows.Next() {
					row, err := rows.Columns()
					if err != nil {
						return MakeBuiltinError(ps, fmt.Sprintf("Unable to get row: %s", err), "Load\\xlsx")
					}
					anyRow := make([]any, len(row))
					for i, v := range row {
						anyRow[i] = *env.NewString(v)
					}

					for i := len(row); i < len(spr.Cols); i++ {
						anyRow[i] = *env.NewString("")
					}
					spr.AddRow(*env.NewTableRow(anyRow, spr))
				}
				return *spr
			default:
				return MakeArgError(ps, 1, []env.Type{env.UriType}, "Load\\xlsx")
			}
		},
	},

	"save\\xlsx": {
		Argsn: 2,
		Doc:   "Saves a Table to a .xlsx file.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch spr := arg0.(type) {
			case env.Table:
				switch file := arg1.(type) {
				case env.Uri:
					sheetName := "Sheet1"
					f := excelize.NewFile()
					index, err := f.NewSheet(sheetName)
					if err != nil {
						return MakeBuiltinError(ps, fmt.Sprintf("Unable to create new sheet: %s", err), "save\\xlsx")
					}
					err = f.SetSheetRow(sheetName, "A1", &spr.Cols)
					if err != nil {
						return MakeBuiltinError(ps, fmt.Sprintf("Unable to set header row: %s", err), "save\\xlsx")
					}
					for i, row := range spr.Rows {

						rowIndex := i + 2
						vals := make([]any, len(row.Values))
						for j, v := range row.Values {
							switch val := v.(type) {
							case env.String:
								vals[j] = val.Value
							case string:
								vals[j] = val
							case env.Integer:
								vals[j] = val.Value
							case int64:
								vals[j] = val
							case env.Decimal:
								vals[j] = val.Value
							case float64:
								vals[j] = val
							default:
								return MakeBuiltinError(ps, fmt.Sprintf("Unable to save table: unsupported type %T", val), "save\\xlsx")
							}
						}
						err = f.SetSheetRow(sheetName, fmt.Sprintf("A%d", rowIndex), &vals)
						if err != nil {
							return MakeBuiltinError(ps, fmt.Sprintf("Unable to set row %d: %s", rowIndex, err), "save\\xlsx")
						}
					}
					f.SetActiveSheet(index)
					err = f.SaveAs(file.GetPath())
					if err != nil {
						return MakeBuiltinError(ps, fmt.Sprintf("Unable to save table: %s", err), "save\\xlsx")
					}
					return spr
				default:
					return MakeArgError(ps, 1, []env.Type{env.UriType}, "save\\xlsx")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.TableType}, "save\\xlsx")
			}
		},
	},

	"persistent-table": {
		Argsn: 3,
		Doc:   "Creates a persistent table using BadgerDB for storage",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			cols, err := ColNames(ps, arg0, "persistent-table")
			if err != nil {
				return err
			}

			switch dbPath := arg1.(type) {
			case env.String:
				switch tableName := arg2.(type) {
				case env.String:
					pt, err := env.NewPersistentTable(cols, dbPath.Value, tableName.Value)
					if err != nil {
						return MakeBuiltinError(ps, fmt.Sprintf("Failed to create persistent table: %v", err), "persistent-table")
					}
					return pt
				default:
					return MakeArgError(ps, 3, []env.Type{env.StringType}, "persistent-table")
				}
			default:
				return MakeArgError(ps, 2, []env.Type{env.StringType}, "persistent-table")
			}
		},
	},

	"close-persistent-table!": {
		Argsn: 1,
		Doc:   "Closes the BadgerDB connection for a persistent table",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch pt := arg0.(type) {
			case *env.PersistentTable:
				err := pt.Close()
				if err != nil {
					return MakeBuiltinError(ps, fmt.Sprintf("Failed to close persistent table: %v", err), "close-persistent-table!")
				}
				return pt
			default:
				return MakeArgError(ps, 1, []env.Type{env.PersistentTableType}, "close-persistent-table!")
			}
		},
	},
}
View Source
var Builtins_telegrambot = map[string]*env.Builtin{

	"bot": {
		Argsn: 1,
		Doc:   "Create new telegram bot using API value.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch arg := arg0.(type) {
			case env.String:
				bot, err := tgm.NewBotAPI(arg.Value)
				if err != nil {
					return MakeBuiltinError(ps, "Error in NewBotAPI function.", "new-telegram-bot")
				}
				return *env.NewNative(ps.Idx, bot, "telegram-bot")
			default:
				return MakeArgError(ps, 1, []env.Type{env.StringType}, "new-telegram-bot")
			}
		},
	},

	"telegram-bot//on-update": {
		Argsn: 2,
		Doc:   "Get telegram update and add to Rye dictionary",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch bot := arg0.(type) {
			case env.Native:
				switch code := arg1.(type) {
				case env.Block:
					u := tgm.NewUpdate(0)
					u.Timeout = 60

					updates, _ := bot.Value.(*tgm.BotAPI).GetUpdatesChan(u)
					ser := ps.Ser
					ps.Ser = code.Series

					for update := range updates {
						dict := TelegramUpdateToRyeDict(update)
						EvalBlockInj(ps, dict, true)
						if ps.ErrorFlag {
							ps.Ser = ser
							return ps.Res
						}
						ps.Ser.Reset()
					}
					ps.Ser = ser
					return env.NewInteger(1)
				case env.Function:
					u := tgm.NewUpdate(0)
					u.Timeout = 60

					updates, _ := bot.Value.(*tgm.BotAPI).GetUpdatesChan(u)

					for update := range updates {
						dict := TelegramUpdateToRyeDict(update)
						ps.FailureFlag = false
						ps.ErrorFlag = false
						ps.ReturnFlag = false
						psTemp := env.ProgramState{}
						err := copier.Copy(&psTemp, &ps)
						if err != nil {
							fmt.Println(err.Error())

						}
						CallFunctionArgsN(code, ps, nil, dict)
					}
					return env.NewInteger(1)

				default:
					return MakeArgError(ps, 2, []env.Type{env.BlockType}, "telegram-bot//on-update")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "telegram-bot//on-update")
			}
		},
	},

	"telegram-message//send": {
		Argsn: 2,
		Doc:   "Send message in telegram bot.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch msg := arg0.(type) {
			case env.Native:
				switch bot := arg1.(type) {
				case env.Native:
					_, err := bot.Value.(*tgm.BotAPI).Send(msg.Value.(*tgm.MessageConfig))
					if err != nil {
						return makeError(ps, err.Error())
					}
					return arg0
				default:
					return MakeArgError(ps, 2, []env.Type{env.NativeType}, "telegram-message//send")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "telegram-message//send")
			}

		},
	},

	"telegram-message//parse-mode!": {
		Argsn: 2,
		Doc:   "Set the parse mode of the message",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch msg := arg0.(type) {
			case env.Native:
				switch mode := arg1.(type) {
				case env.String:
					message, _ := msg.Value.(tgm.MessageConfig)
					message.ParseMode = mode.Value
					return msg
				default:
					return MakeArgError(ps, 2, []env.Type{env.NativeType}, "telegram-message//send")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.NativeType}, "telegram-message//send")
			}

		},
	},

	"message": {
		Argsn: 2,
		Doc:   "Create new telegram bot message.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch cid := arg0.(type) {
			case env.Integer:
				switch txt := arg1.(type) {
				case env.String:
					msg := tgm.NewMessage(cid.Value, txt.Value)
					msg.ParseMode = "HTML"
					return *env.NewNative(ps.Idx, &msg, "telegram-message")
				default:
					return MakeArgError(ps, 2, []env.Type{env.StringType}, "new-telegram-message")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.IntegerType}, "new-telegram-message")
			}
		},
	},
}
View Source
var Builtins_term = map[string]*env.Builtin{

	"wrap": {
		Argsn: 2,
		Doc:   "Wraps a string to a specified width by inserting newlines.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			text, ok := arg0.(env.String)
			if !ok {
				return MakeArgError(ps, 1, []env.Type{env.StringType}, "wrap")
			}
			wdth, ok := arg1.(env.Integer)
			if !ok {
				return MakeArgError(ps, 1, []env.Type{env.IntegerType}, "wrap")
			}
			mkd := wrap.String(text.Value, int(wdth.Value))
			return *env.NewString(mkd)
		},
	},

	"wrap\\words": {
		Argsn: 2,
		Doc:   "Wraps a string to a specified width, preserving word boundaries.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			text, ok := arg0.(env.String)
			if !ok {
				return MakeArgError(ps, 1, []env.Type{env.StringType}, "wrap\\words")
			}
			wdth, ok := arg1.(env.Integer)
			if !ok {
				return MakeArgError(ps, 1, []env.Type{env.IntegerType}, "wrap\\words")
			}
			mkd := wordwrap.String(text.Value, int(wdth.Value))
			return *env.NewString(mkd)
		},
	},

	"indent": {
		Argsn: 2,
		Doc:   "Indents each line of a string by a specified number of spaces.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			text, ok := arg0.(env.String)
			if !ok {
				return MakeArgError(ps, 1, []env.Type{env.StringType}, "indent")
			}
			wdth, ok := arg1.(env.Integer)
			if !ok {
				return MakeArgError(ps, 1, []env.Type{env.IntegerType}, "indent")
			}
			mkd := indent.String(text.Value, uint(wdth.Value))
			return *env.NewString(mkd)
		},
	},

	"width?": {
		Argsn: 0,
		Doc:   "Returns the current width of the terminal in characters.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			fd := int(os.Stdout.Fd())
			width, _, err := goterm.GetSize(fd)
			if err != nil {
				return MakeBuiltinError(ps, err.Error(), "width?")
			}
			return env.NewInteger(int64(width))
		},
	},

	"black": {
		Argsn: 0,
		Doc:   "Sets terminal text color to black.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			term.ColorBlack()
			return env.NewInteger(1)
		},
	},

	"red": {
		Argsn: 0,
		Doc:   "Sets terminal text color to red.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			term.ColorRed()
			return env.NewInteger(1)
		},
	},

	"blue": {
		Argsn: 0,
		Doc:   "Sets terminal text color to blue.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			term.ColorBlue()
			return env.NewInteger(1)
		},
	},

	"green": {
		Argsn: 0,
		Doc:   "Sets terminal text color to green.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			term.ColorGreen()
			return env.NewInteger(1)
		},
	},

	"yellow": {
		Argsn: 0,
		Doc:   "Sets terminal text color to yellow.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			term.ColorYellow()
			return env.NewInteger(1)
		},
	},

	"magenta": {
		Argsn: 0,
		Doc:   "Sets terminal text color to magenta.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			term.ColorMagenta()
			return env.NewInteger(1)
		},
	},

	"cyan": {
		Argsn: 0,
		Doc:   "Sets terminal text color to cyan.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			term.ColorBlue()
			return env.NewInteger(1)
		},
	},

	"white": {
		Argsn: 0,
		Doc:   "Sets terminal text color to white.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			term.ColorWhite()
			return env.NewInteger(1)
		},
	},

	"str\\black": {
		Argsn: 0,
		Doc:   "Returns ANSI escape code string for black text color.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return *env.NewString(term.StrColorBlack())
		},
	},

	"str\\red": {
		Argsn: 0,
		Doc:   "Returns ANSI escape code string for red text color.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return *env.NewString(term.StrColorRed())
		},
	},

	"str\\blue": {
		Argsn: 0,
		Doc:   "Returns ANSI escape code string for blue text color.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return *env.NewString(term.StrColorBlue())
		},
	},

	"str\\green": {
		Argsn: 0,
		Doc:   "Returns ANSI escape code string for green text color.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return *env.NewString(term.StrColorGreen())
		},
	},

	"str\\yellow": {
		Argsn: 0,
		Doc:   "Returns ANSI escape code string for yellow text color.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return *env.NewString(term.StrColorYellow())
		},
	},

	"str\\magenta": {
		Argsn: 0,
		Doc:   "Returns ANSI escape code string for magenta text color.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return *env.NewString(term.StrColorMagenta())
		},
	},

	"str\\cyan": {
		Argsn: 0,
		Doc:   "Returns ANSI escape code string for cyan text color.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return *env.NewString(term.StrColorCyan())
		},
	},

	"str\\white": {
		Argsn: 0,
		Doc:   "Returns ANSI escape code string for white text color.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return *env.NewString(term.StrColorWhite())
		},
	},

	"br-black": {
		Argsn: 0,
		Doc:   "Sets terminal text color to bright black (gray).",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			term.ColorBrBlack()
			return env.NewInteger(1)
		},
	},

	"str\\br-black": {
		Argsn: 0,
		Doc:   "Returns ANSI escape code string for bright black (gray) text color.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return *env.NewString(term.StrColorBrBlack())
		},
	},

	"br-red": {
		Argsn: 0,
		Doc:   "Sets terminal text color to bright red.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			term.ColorBrRed()
			return env.NewInteger(1)
		},
	},

	"br-blue": {
		Argsn: 0,
		Doc:   "Sets terminal text color to bright blue.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			term.ColorBrBlue()
			return env.NewInteger(1)
		},
	},

	"br-green": {
		Argsn: 0,
		Doc:   "Sets terminal text color to bright green.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			term.ColorBrGreen()
			return env.NewInteger(1)
		},
	},

	"br-yellow": {
		Argsn: 0,
		Doc:   "Sets terminal text color to bright yellow.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			term.ColorBrYellow()
			return env.NewInteger(1)
		},
	},

	"br-magenta": {
		Argsn: 0,
		Doc:   "Sets terminal text color to bright magenta.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			term.ColorBrMagenta()
			return env.NewInteger(1)
		},
	},

	"br-cyan": {
		Argsn: 0,
		Doc:   "Sets terminal text color to bright cyan.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			term.ColorBrBlue()
			return env.NewInteger(1)
		},
	},

	"br-white": {
		Argsn: 0,
		Doc:   "Sets terminal text color to bright white.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			term.ColorBrWhite()
			return env.NewInteger(1)
		},
	},

	"bg-black": {
		Argsn: 0,
		Doc:   "Sets terminal background color to black.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			term.ColorBgBlack()
			return env.NewInteger(1)
		},
	},

	"bg-red": {
		Argsn: 0,
		Doc:   "Sets terminal background color to red.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			term.ColorBgRed()
			return env.NewInteger(1)
		},
	},

	"bg-blue": {
		Argsn: 0,
		Doc:   "Sets terminal background color to blue.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			term.ColorBgBlue()
			return env.NewInteger(1)
		},
	},

	"bg-green": {
		Argsn: 0,
		Doc:   "Sets terminal background color to green.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			term.ColorBgGreen()
			return env.NewInteger(1)
		},
	},

	"bg-yellow": {
		Argsn: 0,
		Doc:   "Sets terminal background color to yellow.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			term.ColorBgYellow()
			return env.NewInteger(1)
		},
	},

	"bg-magenta": {
		Argsn: 0,
		Doc:   "Sets terminal background color to magenta.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			term.ColorBgMagenta()
			return env.NewInteger(1)
		},
	},

	"bg-cyan": {
		Argsn: 0,
		Doc:   "Sets terminal background color to cyan.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			term.ColorBgBlue()
			return env.NewInteger(1)
		},
	},

	"bg-white": {
		Argsn: 0,
		Doc:   "Sets terminal background color to white.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			term.ColorBgWhite()
			return env.NewInteger(1)
		},
	},

	"bold": {
		Argsn: 0,
		Doc:   "Sets terminal text style to bold.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			term.Bold()
			return env.NewInteger(1)
		},
	},

	"underline": {
		Argsn: 0,
		Doc:   "Sets terminal text style to underlined.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			term.Underline()
			return env.NewInteger(1)
		},
	},

	"reset\\bold": {
		Argsn: 0,
		Doc:   "Resets terminal text bold style.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			term.ResetBold()
			return env.NewInteger(1)

		},
	},

	"reset": {
		Argsn: 0,
		Doc:   "Resets all terminal text styles and colors.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			term.CloseProps()
			return env.NewInteger(1)
		},
	},

	"str\\reset": {
		Argsn: 0,
		Doc:   "Returns ANSI escape code string to reset all terminal text styles and colors.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return *env.NewString(term.StrCloseProps())
		},
	},

	"spin-it": {
		Argsn: 2,
		Doc:   "Takes a block of code and a message string, shows a spinner with the message while evaluating",
		Pure:  true,
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch bloc := arg1.(type) {
			case env.Block:
				switch msg := arg0.(type) {
				case env.String:

					done := make(chan bool)
					spinnerDone := make(chan bool)

					go func() {
						ser := ps.Ser
						ps.Ser = bloc.Series
						ps.BlockFile = bloc.FileName
						ps.BlockLine = bloc.Line
						EvalBlock(ps)
						MaybeDisplayFailureOrError(ps, ps.Idx, "spin-it")
						ps.Ser = ser
						done <- true
					}()

					spinner := []rune{'|', '/', '-', '\\'}
					i := 0

					go func() {
						for {
							select {
							case <-done:
								fmt.Printf("\r")
								spinnerDone <- true
								return
							default:
								fmt.Printf("\r%s %c", msg.Value, spinner[i%len(spinner)])
								i++
								time.Sleep(120 * time.Millisecond)
							}
						}
					}()

					<-spinnerDone
					fmt.Println("")
					return ps.Res
				default:
					return MakeArgError(ps, 1, []env.Type{env.StringType}, "spin-it")
				}
			default:
				return MakeArgError(ps, 2, []env.Type{env.BlockType}, "spin-it")
			}
		},
	},
}
View Source
var Builtins_termstr = map[string]*env.Builtin{

	"black": {
		Argsn: 0,
		Doc:   "Returns ANSI escape code string for black text color.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return *env.NewString(term.StrColorBlack())
		},
	},

	"red": {
		Argsn: 0,
		Doc:   "Returns ANSI escape code string for red text color.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return *env.NewString(term.StrColorRed())
		},
	},

	"blue": {
		Argsn: 0,
		Doc:   "Returns ANSI escape code string for blue text color.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return *env.NewString(term.StrColorBlue())
		},
	},

	"green": {
		Argsn: 0,
		Doc:   "Returns ANSI escape code string for green text color.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return *env.NewString(term.StrColorGreen())
		},
	},

	"yellow": {
		Argsn: 0,
		Doc:   "Returns ANSI escape code string for yellow text color.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return *env.NewString(term.StrColorYellow())
		},
	},

	"magenta": {
		Argsn: 0,
		Doc:   "Returns ANSI escape code string for magenta text color.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return *env.NewString(term.StrColorMagenta())
		},
	},

	"cyan": {
		Argsn: 0,
		Doc:   "Returns ANSI escape code string for cyan text color.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return *env.NewString(term.StrColorCyan())
		},
	},

	"white": {
		Argsn: 0,
		Doc:   "Returns ANSI escape code string for white text color.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return *env.NewString(term.StrColorWhite())
		},
	},

	"br-black": {
		Argsn: 0,
		Doc:   "Returns ANSI escape code string for bright black (gray) text color.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return *env.NewString(term.StrColorBrBlack())
		},
	},

	"br-red": {
		Argsn: 0,
		Doc:   "Returns ANSI escape code string for bright red text color.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return *env.NewString(term.StrColorBrRed())
		},
	},

	"br-blue": {
		Argsn: 0,
		Doc:   "Returns ANSI escape code string for bright blue text color.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return *env.NewString(term.StrColorBrBlue())
		},
	},

	"br-green": {
		Argsn: 0,
		Doc:   "Returns ANSI escape code string for bright green text color.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return *env.NewString(term.StrColorBrGreen())
		},
	},

	"br-yellow": {
		Argsn: 0,
		Doc:   "Returns ANSI escape code string for bright yellow text color.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return *env.NewString(term.StrColorBrYellow())
		},
	},

	"br-magenta": {
		Argsn: 0,
		Doc:   "Returns ANSI escape code string for bright magenta text color.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return *env.NewString(term.StrColorBrMagenta())
		},
	},

	"br-cyan": {
		Argsn: 0,
		Doc:   "Returns ANSI escape code string for bright cyan text color.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return *env.NewString(term.StrColorBrCyan())
		},
	},

	"br-white": {
		Argsn: 0,
		Doc:   "Returns ANSI escape code string for bright white text color.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return *env.NewString(term.StrColorBrWhite())
		},
	},

	"bg-black": {
		Argsn: 0,
		Doc:   "Returns ANSI escape code string for black background color.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return *env.NewString(term.StrColorBgBlack())
		},
	},

	"bg-red": {
		Argsn: 0,
		Doc:   "Returns ANSI escape code string for red background color.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return *env.NewString(term.StrColorBgRed())
		},
	},

	"bg-blue": {
		Argsn: 0,
		Doc:   "Returns ANSI escape code string for blue background color.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return *env.NewString(term.StrColorBgBlue())
		},
	},

	"bg-green": {
		Argsn: 0,
		Doc:   "Returns ANSI escape code string for green background color.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return *env.NewString(term.StrColorBgGreen())
		},
	},

	"bg-yellow": {
		Argsn: 0,
		Doc:   "Returns ANSI escape code string for yellow background color.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return *env.NewString(term.StrColorBgYellow())
		},
	},

	"bg-magenta": {
		Argsn: 0,
		Doc:   "Returns ANSI escape code string for magenta background color.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return *env.NewString(term.StrColorBgMagenta())
		},
	},

	"bg-cyan": {
		Argsn: 0,
		Doc:   "Returns ANSI escape code string for cyan background color.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return *env.NewString(term.StrColorBgCyan())
		},
	},

	"bg-white": {
		Argsn: 0,
		Doc:   "Returns ANSI escape code string for white background color.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return *env.NewString(term.StrColorBgWhite())
		},
	},

	"bold": {
		Argsn: 0,
		Doc:   "Returns ANSI escape code string for bold text style.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return *env.NewString(term.StrBold())
		},
	},

	"underline": {
		Argsn: 0,
		Doc:   "Returns ANSI escape code string for underlined text style.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return *env.NewString(term.StrUnderline())
		},
	},

	"reset\\bold": {
		Argsn: 0,
		Doc:   "Returns ANSI escape code string to reset bold text style.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return *env.NewString(term.StrResetBold())
		},
	},

	"reset": {
		Argsn: 0,
		Doc:   "Returns ANSI escape code string to reset all terminal text styles and colors.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return *env.NewString(term.StrCloseProps())
		},
	},
}
View Source
var Builtins_validation = map[string]*env.Builtin{

	"validate": {
		Argsn: 2,
		Doc:   "Validates and transforms data according to specified rules, returning a dictionary with converted values or an error.",
		Fn: func(env1 *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return BuiValidate(env1, arg0, arg1)
		},
	},

	"validate>ctx": {
		Argsn: 2,
		Doc:   "Validates and transforms data according to specified rules, returning a context object for easy field access.",
		Fn: func(env1 *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			obj := BuiValidate(env1, arg0, arg1)
			if env1.FailureFlag {
				return obj
			}
			switch obj1 := obj.(type) {
			case env.Dict:
				return util.Dict2Context(env1, obj1)
			default:
				return obj1
			}
		},
	},
}
View Source
var Builtins_vector = map[string]*env.Builtin{

	"vector": {
		Argsn: 1,
		Doc:   "Creates a vector from a block of numbers.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch s := arg0.(type) {
			case env.Block:
				data := ArrayFloat32FromSeries(s.Series)
				val, err := govector.AsVector(data)
				if err != nil {
					return MakeError(ps, err.Error())
				}
				return *env.NewVector(val)
			default:
				return MakeArgError(ps, 1, []env.Type{env.BlockType}, "vector")
			}
		},
	},

	"normalize": {
		Argsn: 1,
		Doc:   "Calculates the L2 norm (Euclidean length) of a vector.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch val := arg0.(type) {
			case env.Vector:
				return *env.NewDecimal(govector.Norm(val.Value, 2.0))
			default:
				return MakeArgError(ps, 1, []env.Type{env.VectorType}, "normalize")
			}
		},
	},

	"std-deviation?": {
		Argsn: 1,
		Doc:   "Calculates the standard deviation of a vector's elements.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch val := arg0.(type) {
			case env.Vector:
				return *env.NewDecimal(val.Value.Sd())
			default:
				return MakeArgError(ps, 1, []env.Type{env.VectorType}, "std-deviation?")
			}
		},
	},

	"cosine-similarity?": {
		Argsn: 2,
		Doc:   "Calculates the cosine similarity between two vectors.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch v1 := arg0.(type) {
			case env.Vector:
				switch v2 := arg1.(type) {
				case env.Vector:
					res, err := govector.Cosine(v1.Value, v2.Value)
					if err != nil {
						return MakeBuiltinError(ps, err.Error(), "cosine-similarity?")
					}
					return *env.NewDecimal(res)
				default:
					return MakeArgError(ps, 2, []env.Type{env.VectorType}, "cosine-similarity?")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.VectorType}, "cosine-similarity?")
			}
		},
	},

	"correlation": {
		Argsn: 2,
		Doc:   "Calculates the correlation coefficient between two vectors.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch v1 := arg0.(type) {
			case env.Vector:
				switch v2 := arg1.(type) {
				case env.Vector:
					res, err := govector.Cor(v1.Value, v2.Value)
					if err != nil {
						return MakeError(ps, err.Error())
					}
					return *env.NewDecimal(res)
				default:
					return MakeArgError(ps, 2, []env.Type{env.VectorType}, "correlation")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.VectorType}, "correlation")
			}
		},
	},

	"dot-product": {
		Argsn: 2,
		Doc:   "Calculates the dot product between two vectors.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch v1 := arg0.(type) {
			case env.Vector:
				switch v2 := arg1.(type) {
				case env.Vector:
					res, err := govector.DotProduct(v1.Value, v2.Value)
					if err != nil {
						return MakeError(ps, err.Error())
					}
					return *env.NewDecimal(res)
				default:
					return MakeArgError(ps, 2, []env.Type{env.VectorType}, "dot-product")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.VectorType}, "dot-product")
			}
		},
	},
}
View Source
var Builtins_web = map[string]*env.Builtin{}
View Source
var ErrorCreationBuiltins = map[string]*env.Builtin{

	"fail": {
		Argsn: 1,
		Doc:   "Creates an error and sets the failure flag, but continues execution (unlike ^fail).",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			ps.FailureFlag = true
			return MakeRyeError(ps, arg0, nil)
		},
	},

	"^fail": {
		Argsn: 1,
		Doc:   "Creates an error and immediately returns from the current function with failure state.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			ps.FailureFlag = true
			ps.ReturnFlag = true
			return MakeRyeError(ps, arg0, nil)
		},
	},

	"refail": {
		Argsn: 2,
		Doc:   "Re-raises an existing error with additional context.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch er := arg0.(type) {
			case *env.Error:
				ps.FailureFlag = true
				return MakeRyeError(ps, arg1, er)
			default:
				return MakeArgError(ps, 1, []env.Type{env.ErrorType}, "reraise")
			}
		},
	},

	"failure": {
		Argsn: 1,
		Doc:   "Creates an error object without setting any flags (unlike fail and ^fail).",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return MakeRyeError(ps, arg0, nil)
		},
	},

	"failure\\wrap": {
		Argsn: 2,
		Doc:   "Creates a new error that wraps an existing error, allowing for error chaining.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch er := arg1.(type) {
			case *env.Error:
				return MakeRyeError(ps, arg0, er)
			default:
				return MakeArgError(ps, 2, []env.Type{env.ErrorType}, "wrap\\failure")
			}
		},
	},
}

Error Creation Functions

View Source
var ErrorHandlingBuiltins = map[string]*env.Builtin{

	"disarm": {
		AcceptFailure: true,
		Argsn:         1,
		Doc:           "Clears the failure flag while preserving the error object, allowing error inspection without propagation.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			ps.FailureFlag = false
			return arg0
		},
	},

	"check": {
		AcceptFailure: true,
		Argsn:         2,
		Doc:           "Checks if a value is in failure state and wraps it with a new error if so, otherwise returns the original value.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			if ps.FailureFlag || arg0.Type() == env.ErrorType {
				ps.FailureFlag = false
				switch er := arg0.(type) {
				case *env.Error:
					if er.Status == 0 && er.Message == "" {
						er = nil
					}
					return MakeRyeError(ps, arg1, er)
				}
			}
			return arg0
		},
	},

	"^check": {
		AcceptFailure: true,
		Argsn:         2,
		Doc:           "Like 'check' but also sets the return flag to immediately exit the current function.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			if ps.FailureFlag {
				ps.ReturnFlag = true
				switch er := arg0.(type) {
				case *env.Error:
					if er.Status == 0 && er.Message == "" {
						er = nil
					}
					return MakeRyeError(ps, arg1, er)
				case env.Error:

					return MakeRyeError(ps, arg1, &er)
				}
				return env.NewError("error 12221")
			}
			return arg0
		},
	},

	"^ensure": {
		AcceptFailure: true,
		Argsn:         2,
		Doc:           "Checks if a value is truthy and returns it if so, otherwise creates an error and immediately returns from the function.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch cond := arg0.(type) {
			case env.Object:
				if !util.IsTruthy(cond) {
					ps.FailureFlag = true
					ps.ReturnFlag = true
					return MakeRyeError(ps, arg1, nil)
				} else {
					return arg0
				}
			}
			return arg0
		},
	},

	"ensure": {
		AcceptFailure: true,
		Argsn:         2,
		Doc:           "Checks if a value is truthy and returns it if so, otherwise creates an error with the failure flag set.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch cond := arg0.(type) {
			case env.Object:
				if !util.IsTruthy(cond) {
					ps.FailureFlag = true
					return MakeRyeError(ps, arg1, nil)
				} else {
					return arg0
				}
			}
			return arg0
		},
	},

	"requires-one-of": {
		AcceptFailure: true,
		Argsn:         2,
		Doc:           "Validates that a value matches one of the provided options, failing with a descriptive error if not.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch optionsBlock := arg1.(type) {
			case env.Block:

				options := optionsBlock.Series.GetAll()
				for _, option := range options {

					if arg0.GetKind() == option.GetKind() && arg0.Inspect(*ps.Idx) == option.Inspect(*ps.Idx) {
						return arg0
					}
				}

				ps.FailureFlag = true

				valueStr := arg0.Inspect(*ps.Idx)

				// Build error message with options
				var errorMsg string
				if len(options) > 0 {
					optionsStr := "{ "
					for i, opt := range options {
						if i > 0 {
							optionsStr += " "
						}
						optionsStr += opt.Inspect(*ps.Idx)
					}
					optionsStr += " }"
					errorMsg = fmt.Sprintf("Value %s must be one of %s", valueStr, optionsStr)
				} else {
					errorMsg = fmt.Sprintf("Value %s does not match any valid option", valueStr)
				}

				return MakeRyeError(ps, *env.NewString(errorMsg), nil)
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 2, []env.Type{env.BlockType}, "requires-one-of")
			}
		},
	},

	"^requires-one-of": {
		AcceptFailure: true,
		Argsn:         2,
		Doc:           "Validates that a value matches one of the provided options, failing with a descriptive error if not.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch optionsBlock := arg1.(type) {
			case env.Block:

				options := optionsBlock.Series.GetAll()
				for _, option := range options {

					if arg0.GetKind() == option.GetKind() && arg0.Inspect(*ps.Idx) == option.Inspect(*ps.Idx) {
						return arg0
					}
				}

				ps.FailureFlag = true

				valueStr := arg0.Inspect(*ps.Idx)

				// Build error message with options
				var errorMsg string
				if len(options) > 0 {
					optionsStr := "{ "
					for i, opt := range options {
						if i > 0 {
							optionsStr += " "
						}
						optionsStr += opt.Inspect(*ps.Idx)
					}
					optionsStr += " }"
					errorMsg = fmt.Sprintf("Value %s must be one of %s", valueStr, optionsStr)
				} else {
					errorMsg = fmt.Sprintf("Value %s does not match any valid option", valueStr)
				}
				ps.ReturnFlag = true
				return MakeRyeError(ps, *env.NewString(errorMsg), nil)
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 2, []env.Type{env.BlockType}, "requires-one-of")
			}
		},
	},

	"fix": {
		AcceptFailure: true,
		Argsn:         2,
		Doc:           "Handles errors by executing a block if the value is in failure state, clearing the failure flag.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			if ps.FailureFlag || arg0.Type() == env.ErrorType {
				ps.FailureFlag = false

				switch bloc := arg1.(type) {
				case env.Block:
					ser := ps.Ser
					ps.Ser = bloc.Series
					EvalBlockInjMultiDialect(ps, arg0, true)
					MaybeDisplayFailureOrError(ps, ps.Idx, "fix")
					if ps.ErrorFlag {
						ps.Ser = ser
						return ps.Res
					}
					ps.Ser = ser
					return ps.Res
				default:
					ps.FailureFlag = true
					return env.NewError("expecting block")
				}
			} else {
				return arg0
			}
		},
	},

	"^fix": {
		AcceptFailure: true,
		Argsn:         2,
		Doc:           "Like 'fix' but also sets the return flag to immediately exit the current function with the handler result.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			if ps.FailureFlag || arg0.Type() == env.ErrorType {
				ps.FailureFlag = false

				switch bloc := arg1.(type) {
				case env.Block:
					ser := ps.Ser
					ps.Ser = bloc.Series
					EvalBlockInjMultiDialect(ps, arg0, true)
					MaybeDisplayFailureOrError(ps, ps.Idx, "^fix")
					ps.Ser = ser
					ps.ReturnFlag = true
					return ps.Res
				default:
					ps.FailureFlag = true
					return env.NewError("expecting block")
				}
			} else {
				return arg0
			}
		},
	},

	"fix\\either": {
		AcceptFailure: true,
		Argsn:         3,
		Doc:           "Executes one of two blocks depending on whether the value is in failure state.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			if ps.FailureFlag || arg0.Type() == env.ErrorType {
				ps.FailureFlag = false

				switch bloc := arg1.(type) {
				case env.Block:
					ser := ps.Ser
					ps.Ser = bloc.Series
					EvalBlockInjMultiDialect(ps, arg0, true)
					MaybeDisplayFailureOrError(ps, ps.Idx, "fix\\either")
					ps.Ser = ser
					return ps.Res
				default:
					ps.FailureFlag = true
					return env.NewError("expecting block")
				}
			} else {
				switch bloc := arg2.(type) {
				case env.Block:
					ser := ps.Ser
					ps.Ser = bloc.Series
					EvalBlockInjMultiDialect(ps, arg0, true)
					MaybeDisplayFailureOrError(ps, ps.Idx, "fix\\either")
					ps.Ser = ser
					return ps.Res
				default:
					ps.FailureFlag = true
					return env.NewError("expecting block")
				}
			}
		},
	},

	"fix\\else": {
		AcceptFailure: true,
		Argsn:         2,
		Doc:           "Executes a block if the value is not in failure state, otherwise returns the original value.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			if !(ps.FailureFlag || arg0.Type() == env.ErrorType) {
				ps.FailureFlag = false

				switch bloc := arg1.(type) {
				case env.Block:
					ser := ps.Ser
					ps.Ser = bloc.Series
					EvalBlockInjMultiDialect(ps, arg0, true)
					MaybeDisplayFailureOrError(ps, ps.Idx, "fix\\else")
					ps.Ser = ser
					return ps.Res
				default:
					ps.FailureFlag = true
					return env.NewError("expecting block")
				}
			} else {
				return arg0
			}
		},
	},

	"fix\\continue": {
		AcceptFailure: true,
		Argsn:         3,
		Doc:           "Executes one of two blocks depending on whether the value is in failure state, like an error-handling if/else.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			if ps.FailureFlag || arg0.Type() == env.ErrorType {
				ps.FailureFlag = false

				switch bloc := arg1.(type) {
				case env.Block:
					ser := ps.Ser
					ps.Ser = bloc.Series
					EvalBlockInjMultiDialect(ps, arg0, true)
					ps.Ser = ser
					return ps.Res
				default:
					ps.FailureFlag = true
					return env.NewError("expecting block")
				}
			} else {
				switch bloc := arg2.(type) {
				case env.Block:
					ser := ps.Ser
					ps.Ser = bloc.Series
					EvalBlockInjMultiDialect(ps, arg0, true)
					ps.Ser = ser
					return ps.Res
				default:
					ps.FailureFlag = true
					return env.NewError("expecting block")
				}
			}
		},
	},

	"continue": {
		AcceptFailure: true,
		Argsn:         2,
		Doc:           "Executes a block only if the value is not in failure state, opposite of 'fix'.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			if !(ps.FailureFlag || arg0.Type() == env.ErrorType) {
				ps.FailureFlag = false

				switch bloc := arg1.(type) {
				case env.Block:
					ser := ps.Ser
					ps.Ser = bloc.Series
					EvalBlockInjMultiDialect(ps, arg0, true)
					MaybeDisplayFailureOrError(ps, ps.Idx, "continue")
					ps.Ser = ser
					return ps.Res
				default:
					ps.FailureFlag = true
					return env.NewError("expecting block")
				}
			} else {
				ps.FailureFlag = false
				return arg0
			}
		},
	},

	"^fix\\match": {
		Argsn:         2,
		Doc:           "Error handling switch that matches error codes with handler blocks and sets the return flag.",
		AcceptFailure: true,
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			ps.FailureFlag = false

			switch er := arg0.(type) {
			case env.Error, *env.Error:
				switch bloc := arg1.(type) {
				case env.Block:
					var code env.Object
					any_found := false

					for i := 0; i < bloc.Series.Len(); i += 2 {
						if i > bloc.Series.Len()-2 {
							return MakeBuiltinError(ps, "Switch block malformed.", "^fix\\match")
						}

						switch ev := bloc.Series.Get(i).(type) {
						case env.Integer:
							var status int
							if err, ok := er.(env.Error); ok {
								status = err.Status
							} else if errPtr, ok := er.(*env.Error); ok {
								status = errPtr.Status
							}

							if status == int(ev.Value) {
								any_found = true
								code = bloc.Series.Get(i + 1)
							}
						case env.Void:
							if !any_found {
								code = bloc.Series.Get(i + 1)
								any_found = true
							}
						default:
							return MakeBuiltinError(ps, "Invalid type in block series.", "^fix\\match")
						}
					}

					switch cc := code.(type) {
					case env.Block:

						ser := ps.Ser

						ps.Ser = cc.Series

						EvalBlockInjMultiDialect(ps, arg0, true)

						MaybeDisplayFailureOrError(ps, ps.Idx, "fix\\match")

						ps.Ser = ser

						ps.ReturnFlag = true
						return ps.Res
					default:

						ps.FailureFlag = true
						return MakeBuiltinError(ps, "Malformed switch block.", "^fix\\match")
					}
				default:

					ps.FailureFlag = true
					return MakeArgError(ps, 2, []env.Type{env.BlockType}, "^fix\\match")
				}
			default:
				return arg0
			}
		},
	},

	"try": {
		Argsn: 1,
		Doc:   "Takes a block of code and does (runs) it.",
		Pure:  true,
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch bloc := arg0.(type) {
			case env.Block:
				ser := ps.Ser
				ps.Ser = bloc.Series
				ps.InErrHandler = true
				EvalBlock(ps)

				ps.InErrHandler = false
				ps.ReturnFlag = false
				ps.ErrorFlag = false
				ps.FailureFlag = false

				ps.Ser = ser
				return ps.Res
			default:
				return MakeArgError(ps, 1, []env.Type{env.BlockType}, "try")
			}
		},
	},

	"try-all": {
		Argsn: 1,
		Doc:   "Executes a block and returns a result tuple [success, result], where success is true if no error occurred.",
		Pure:  true,
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch bloc := arg0.(type) {
			case env.Block:

				oldSer := ps.Ser
				oldFailureFlag := ps.FailureFlag
				oldErrorFlag := ps.ErrorFlag

				ps.Ser = bloc.Series
				EvalBlock(ps)
				MaybeDisplayFailureOrError(ps, ps.Idx, "try-all")

				result := ps.Res
				success := !ps.FailureFlag && !ps.ErrorFlag

				ps.Ser = oldSer
				ps.FailureFlag = oldFailureFlag
				ps.ErrorFlag = oldErrorFlag

				return *env.NewBlock(*env.NewTSeries([]env.Object{
					*env.NewBoolean(success),
					result,
				}))
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.BlockType}, "try-all")
			}
		},
	},

	"try\\in": {
		Argsn: 2,
		Doc:   "Takes a Context and a Block. It Does a block inside a given Context.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch ctx := arg0.(type) {
			case env.RyeCtx:
				switch bloc := arg1.(type) {
				case env.Block:
					ser := ps.Ser
					ps.Ser = bloc.Series
					EvalBlockInCtxInj(ps, &ctx, nil, false)
					MaybeDisplayFailureOrError(ps, ps.Idx, "try\\in")

					ps.ReturnFlag = false
					ps.ErrorFlag = false
					ps.FailureFlag = false

					ps.Ser = ser
					return ps.Res
				default:
					ps.ErrorFlag = true
					return MakeArgError(ps, 2, []env.Type{env.BlockType}, "try\\in")
				}
			default:
				ps.ErrorFlag = true
				return MakeArgError(ps, 1, []env.Type{env.ContextType}, "try\\in")
			}
		},
	},

	"finally": {
		Argsn: 2,
		Doc:   "Executes a block and ensures another block is executed afterward, regardless of errors.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch mainBlock := arg0.(type) {
			case env.Block:
				switch finallyBlock := arg1.(type) {
				case env.Block:

					oldSer := ps.Ser

					ps.Ser = mainBlock.Series
					EvalBlock(ps)
					MaybeDisplayFailureOrError(ps, ps.Idx, "finally")

					result := ps.Res
					hasFailure := ps.FailureFlag
					hasError := ps.ErrorFlag

					ps.Ser = finallyBlock.Series
					ps.FailureFlag = false
					ps.ErrorFlag = false
					EvalBlock(ps)
					MaybeDisplayFailureOrError(ps, ps.Idx, "finally")

					ps.Res = result
					ps.FailureFlag = hasFailure
					ps.ErrorFlag = hasError

					ps.Ser = oldSer

					return ps.Res
				default:
					ps.FailureFlag = true
					return MakeArgError(ps, 2, []env.Type{env.BlockType}, "finally")
				}
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 1, []env.Type{env.BlockType}, "finally")
			}
		},
	},

	"retry": {
		Argsn:         2,
		Doc:           "Executes a block and retries it up to N times if it results in a failure.",
		AcceptFailure: true,
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch retries := arg0.(type) {
			case env.Integer:
				switch bloc := arg1.(type) {
				case env.Block:

					ser := ps.Ser

					ps.Ser = bloc.Series
					EvalBlock(ps)
					MaybeDisplayFailureOrError(ps, ps.Idx, "retry")

					if !ps.FailureFlag {
						ps.Ser = ser
						return ps.Res
					}

					result := ps.Res

					for i := int64(1); i < retries.Value; i++ {

						ps.Ser.Reset()
						ps.FailureFlag = false
						ps.ErrorFlag = false

						EvalBlock(ps)
						MaybeDisplayFailureOrError(ps, ps.Idx, "retry")

						if !ps.FailureFlag {
							ps.Ser = ser
							return ps.Res
						}

						result = ps.Res
					}

					ps.Ser = ser
					ps.FailureFlag = true
					return result
				default:
					return MakeArgError(ps, 2, []env.Type{env.BlockType}, "retry")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.IntegerType}, "retry")
			}
		},
	},

	"persist": {
		Argsn:         1,
		Doc:           "Executes a block repeatedly until it succeeds (no failure), then returns the successful result. Gives up after 1000 attempts.",
		AcceptFailure: true,
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch bloc := arg0.(type) {
			case env.Block:

				ser := ps.Ser

				for attempt := 1; attempt <= 1000; attempt++ {

					ps.Ser = bloc.Series
					ps.Ser.Reset()
					ps.FailureFlag = false
					ps.ErrorFlag = false

					EvalBlock(ps)
					MaybeDisplayFailureOrError(ps, ps.Idx, "persist")

					if !ps.FailureFlag {
						ps.Ser = ser
						return ps.Res
					}

				}

				ps.Ser = ser
				ps.FailureFlag = true
				return MakeRyeError(ps, *env.NewString("Persist failed: Block did not succeed after 1000 attempts"), nil)
			default:
				return MakeArgError(ps, 1, []env.Type{env.BlockType}, "persist")
			}
		},
	},

	"timeout": {
		AcceptFailure: true,
		Argsn:         2,
		Doc:           "Executes a block of code with a timeout, failing if execution exceeds the specified duration in milliseconds.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch ms := arg0.(type) {
			case env.Integer:
				switch bloc := arg1.(type) {
				case env.Block:

					ser := ps.Ser

					resultChan := make(chan env.Object, 1)
					doneChan := make(chan bool, 1)

					psCopy := env.NewProgramState(bloc.Series, ps.Idx)
					psCopy.Ctx = ps.Ctx
					psCopy.PCtx = ps.PCtx
					psCopy.Gen = ps.Gen

					go func() {
						EvalBlock(psCopy)
						MaybeDisplayFailureOrError(ps, ps.Idx, "timeout")

						resultChan <- psCopy.Res
						doneChan <- psCopy.FailureFlag
					}()

					timeoutDuration := time.Duration(ms.Value) * time.Millisecond

					select {
					case result := <-resultChan:
						ps.FailureFlag = <-doneChan
						ps.Ser = ser
						return result

					case <-time.After(timeoutDuration):
						ps.FailureFlag = true
						ps.Ser = ser
						return MakeRyeError(ps, *env.NewString(fmt.Sprintf("Execution timed out after %d ms", ms.Value)), nil)
					}
				default:
					return MakeArgError(ps, 2, []env.Type{env.BlockType}, "timeout")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.IntegerType}, "timeout")
			}
		},
	},
}

Error Handling Functions

View Source
var ErrorInspectionBuiltins = map[string]*env.Builtin{

	"is-error": {
		AcceptFailure: true,
		Argsn:         1,
		Doc:           "Returns true if the value is an error, false otherwise.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			ps.FailureFlag = false
			switch arg0.(type) {
			case env.Error, *env.Error:
				return *env.NewBoolean(true)
			}
			return *env.NewBoolean(false)
		},
	},

	"error-kind?": {
		AcceptFailure: true,
		Argsn:         1,
		Doc:           "Returns the kind of an error, or void if not an error.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			ps.FailureFlag = false
			switch err := arg0.(type) {
			case env.Error:
				return *env.NewWord(err.Kind.Index)
			case *env.Error:
				return *env.NewWord(err.Kind.Index)
			}
			return *env.NewVoid()
		},
	},

	"is-error-of-kind": {
		AcceptFailure: true,
		Argsn:         2,
		Doc:           "Returns true if the value is an error of the specified kind, false otherwise.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			ps.FailureFlag = false

			// Get the kind to check
			var kindIndex int
			switch kind := arg1.(type) {
			case env.Word:
				kindIndex = kind.Index
			case env.Tagword:
				kindIndex = kind.Index
			default:
				ps.FailureFlag = true
				return MakeArgError(ps, 2, []env.Type{env.WordType, env.TagwordType}, "is-error-of-kind")
			}

			switch err := arg0.(type) {
			case env.Error:
				return *env.NewBoolean(err.Kind.Index == kindIndex)
			case *env.Error:
				return *env.NewBoolean(err.Kind.Index == kindIndex)
			}

			return *env.NewBoolean(false)
		},
	},

	"cause?": {
		AcceptFailure: true,
		Argsn:         1,
		Doc:           "Extracts the root cause from an error chain by traversing the Parent references.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch er := arg0.(type) {
			case env.Error:

				current := &er
				for current.Parent != nil {
					current = current.Parent
				}
				return *current
			case *env.Error:

				current := er
				for current.Parent != nil {
					current = current.Parent
				}
				return *current
			default:
				ps.FailureFlag = true
				return env.NewError("arg 0 not error")
			}
		},
	},

	"status?": {
		AcceptFailure: true,
		Argsn:         1,
		Doc:           "Extracts the numeric status code from an error object.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch er := arg0.(type) {
			case env.Error:
				return *env.NewInteger(int64(er.Status))
			case *env.Error:
				return *env.NewInteger(int64(er.Status))
			default:
				ps.FailureFlag = true
				return env.NewError("arg 0 not error")
			}
		},
	},

	"message?": {
		AcceptFailure: true,
		Argsn:         1,
		Doc:           "Extracts the message string from an error object.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch er := arg0.(type) {
			case env.Error:
				return *env.NewString(er.Message)
			case *env.Error:
				return *env.NewString(er.Message)
			default:
				ps.FailureFlag = true
				return env.NewError("arg 0 not error")
			}
		},
	},

	"details?": {
		AcceptFailure: true,
		Argsn:         1,
		Doc:           "Extracts additional details from an error object as a dictionary.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			var originalMap map[string]env.Object
			switch er := arg0.(type) {
			case env.Error:
				originalMap = er.Values
			case *env.Error:
				originalMap = er.Values
			default:
				ps.FailureFlag = true
				return env.NewError("arg 0 not error")
			}

			convertedMap := make(map[string]any)
			for key, value := range originalMap {
				convertedMap[key] = value
			}
			return env.NewDict(convertedMap)
		},
	},

	"has-failed": {
		AcceptFailure: true,
		Argsn:         1,
		Doc:           "Tests if a value is an error object, returning true for errors and false for non-errors.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			ps.FailureFlag = false
			switch arg0.(type) {
			case env.Error, *env.Error:
				return *env.NewBoolean(true)
			}
			return *env.NewBoolean(false)
		},
	},

	"is-failure": {
		Argsn: 1,
		Doc:   "Checks if a value is a failure/error type. Unlike has-failed, this doesn't accept failures - the value must already be disarmed.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch arg0.(type) {
			case env.Error, *env.Error:
				return *env.NewBoolean(true)
			}
			return *env.NewBoolean(false)
		},
	},

	"is-success": {
		Argsn: 1,
		Doc:   "Returns true for any value that is not a failure/error type. The opposite of is-failure.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch arg0.(type) {
			case env.Error, *env.Error:
				return *env.NewBoolean(false)
			}
			return *env.NewBoolean(true)
		},
	},
}

Error Inspection Functions

View Source
var NoInspectMode bool

NoInspectMode controls whether to exit immediately on error without showing debugging options

View Source
var OutBuffer = "" // how does this work with multiple threads / ... in server use ... probably we would need some per environment variable, not global / global?
View Source
var ShowResults bool
View Source
var VarBuiltins_demo = map[string]*env.VarBuiltin{

	"var-not": {
		Argsn: 1,
		Doc:   "Performs logical negation on boolean values only.",
		Pure:  true,
		Fn: func(env1 *env.ProgramState, args ...env.Object) env.Object {
			switch b := args[0].(type) {
			case env.Boolean:
				return *env.NewBoolean(!b.Value)
			default:
				return MakeArgError(env1, 1, []env.Type{env.BooleanType}, "not")
			}
		},
	},

	"var-and": {
		Argsn: 2,
		Doc:   "Performs a logical AND operation between two boolean values, or a bitwise AND operation between two integer values.",
		Pure:  true,
		Fn: func(ps *env.ProgramState, args ...env.Object) env.Object {
			switch s1 := args[0].(type) {
			case env.Boolean:
				switch s2 := args[1].(type) {
				case env.Boolean:
					return *env.NewBoolean(s1.Value && s2.Value)
				default:
					return MakeArgError(ps, 2, []env.Type{env.BooleanType}, "and")
				}
			case env.Integer:
				switch s2 := args[1].(type) {
				case env.Integer:
					return *env.NewInteger(s1.Value & s2.Value)
				default:
					return MakeArgError(ps, 2, []env.Type{env.IntegerType}, "and")
				}
			default:
				return MakeArgError(ps, 1, []env.Type{env.BooleanType, env.IntegerType}, "and")
			}
		},
	},
}

Functions

func AddIndexes

func AddIndexes(ps *env.ProgramState, s *env.Table, columns []env.Word) env.Object

func ArrayFloat32FromSeries

func ArrayFloat32FromSeries(block env.TSeries) []float32

func AutoType

func AutoType(ps *env.ProgramState, s *env.Table, percent float64) env.Object

func BsonToValue_Map added in v0.0.21

func BsonToValue_Map(ps *env.ProgramState, val any, typ string, meta any, topLevel bool) env.Object

func BsonToValue_Val added in v0.0.21

func BsonToValue_Val(ps *env.ProgramState, val any, topLevel bool) env.Object

func BuiConvert

func BuiConvert(ps *env.ProgramState, arg0 env.Object, arg1 env.Object) env.Object

func BuiValidate

func BuiValidate(env1 *env.ProgramState, arg0 env.Object, arg1 env.Object) env.Object

func CallBuiltin_CollectArgs added in v0.0.90

func CallBuiltin_CollectArgs(bi env.Builtin, ps *env.ProgramState, arg0_ env.Object, toLeft bool, pipeSecond bool, firstVal env.Object)

CallBuiltin_CollectArgs calls a builtin by collecting up to 5 arguments from the code stream. Called from: EvalExpression_DispatchType, EvalObject Purpose: Main builtin caller - collects arguments, handles failure flags, calls builtin function

func CallCurriedCaller added in v0.0.82

func CallCurriedCaller(cc env.CurriedCaller, ps *env.ProgramState, arg0_ env.Object, toLeft bool, pipeSecond bool, firstVal env.Object)

CallCurriedCaller handles calling a curried caller (partially applied function or builtin). Called from: EvalExpression_DispatchType, EvalObject Purpose: Executes curried callers by filling in remaining arguments and calling the underlying builtin/function

func CallFunctionArgs2

func CallFunctionArgs2(fn env.Function, ps *env.ProgramState, arg0 env.Object, arg1 env.Object, ctx *env.RyeCtx)

CallFunctionArgs2 calls a function with exactly 2 arguments provided. Called from: CallFunctionWithArgs, builtins needing to call 2-arg functions Purpose: Optimized path for 2-argument function calls from builtins

func CallFunctionArgs4

func CallFunctionArgs4(fn env.Function, ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, ctx *env.RyeCtx)

CallFunctionArgs4 calls a function with exactly 4 arguments provided. Called from: CallFunctionWithArgs, builtins needing to call 4-arg functions Purpose: Optimized path for 4-argument function calls from builtins

func CallFunctionArgsN added in v0.0.21

func CallFunctionArgsN(fn env.Function, ps *env.ProgramState, ctx *env.RyeCtx, args ...env.Object)

CallFunctionArgsN calls a function with a variable number of arguments (N arguments). Called from: CallFunctionWithArgs, CallCurriedCaller, builtins with variable args Purpose: Generic function caller for any number of arguments provided as a slice

func CallFunctionWithArgs added in v0.0.81

func CallFunctionWithArgs(fn env.Function, ps *env.ProgramState, ctx *env.RyeCtx, args ...env.Object)

CallFunctionWithArgs is a consolidated function caller that dispatches based on argument count. Called from: Various builtins that need to call user functions Purpose: Dispatcher that routes to specialized function callers based on number of arguments (0,1,2,4,N)

func CallFunction_CollectArgs added in v0.0.90

func CallFunction_CollectArgs(fn env.Function, ps *env.ProgramState, arg0_ env.Object, toLeft bool, ctx *env.RyeCtx, pipeSecond ...interface{})

CallFunction_CollectArgs calls a function by collecting arguments from the code stream. Called from: EvalObject, CallFunctionWithArgs (0 or 1 arg case) Purpose: Main function caller in evaluator - collects args from code, sets up context, executes function body

func CallVarBuiltin added in v0.0.40

func CallVarBuiltin(bi env.VarBuiltin, ps *env.ProgramState, arg0_ env.Object, toLeft bool, pipeSecond bool, firstVal env.Object)

CallVarBuiltin calls a variadic builtin by collecting all required arguments into a slice. Called from: EvalExpression_DispatchType, EvalObject Purpose: Handles builtins with variable number of arguments, collecting them into a slice

func Clear

func Clear()

Clear screen

func ColNames added in v0.0.31

func ColNames(ps *env.ProgramState, from env.Object, fnName string) ([]string, env.Object)

func CompileRyeToEyr added in v0.0.21

func CompileRyeToEyr(block *env.Block, ps *env.ProgramState, eyrBlock *env.Block) *env.Block

func CompileStepRyeToEyr added in v0.0.21

func CompileStepRyeToEyr(block *env.Block, ps *env.ProgramState, eyrBlock *env.Block) *env.Block

func CompileWord added in v0.0.21

func CompileWord(block *env.Block, ps *env.ProgramState, word env.Word, eyrBlock *env.Block)

func Conversion_EvalBlockCtx

func Conversion_EvalBlockCtx(ps *env.ProgramState, vals env.RyeCtx) env.Object

func Conversion_EvalBlockDict

func Conversion_EvalBlockDict(ps *env.ProgramState, vals env.Dict) env.Object

func CopyMap

func CopyMap(m map[string]any) map[string]any

func DELETE_ME_getCurrentBlock added in v0.0.86

func DELETE_ME_getCurrentBlock(es *env.ProgramState) *env.Block

DELETE_ME_getCurrentBlock is deprecated and marked for deletion. Called from: Nowhere (deprecated) Purpose: Was used to get current executing block, now replaced by better location tracking

func DetermineContext added in v0.0.22

func DetermineContext(fn env.Function, ps *env.ProgramState, ctx *env.RyeCtx) *env.RyeCtx

DetermineContext determines the appropriate context for a function call. Called from: CallFunctionWithArgs, CallFunctionArgsN Purpose: Sets up function execution context based on pure/impure, defined context, and parent context

func DialectMath added in v0.0.11

func DialectMath(env1 *env.ProgramState, arg0 env.Object) env.Object

func DictToJSON added in v0.0.20

func DictToJSON(dict env.Dict) string

Inspect returns a string representation of the Integer.

func DirectlyCallBuiltin

func DirectlyCallBuiltin(ps *env.ProgramState, bi env.Builtin, a0 env.Object, a1 env.Object) env.Object

DirectlyCallBuiltin directly calls a builtin with provided arguments (no collection from code). Called from: Builtins that need to call other builtins directly Purpose: Direct builtin invocation helper for inter-builtin calls

func DisableFastEvaluator added in v0.0.40

func DisableFastEvaluator()

DisableFastEvaluator disables the fast evaluator for Rye0 dialect. Called from: Command-line flags or configuration code Purpose: Switches back to standard evaluation mode for Rye0 dialect code

func DisplayEnhancedError added in v0.0.86

func DisplayEnhancedError(es *env.ProgramState, genv *env.Idxs, tag string, topLevel bool)

DisplayEnhancedError displays a formatted error with source location and block context. Called from: MaybeDisplayFailureOrError2 Purpose: Main error display - shows red banner, error message, block location, and <here> marker

func DoRyeDualRepl added in v0.0.40

func DoRyeDualRepl(leftPs, rightPs *env.ProgramState, dialect string, showResults bool)

DoRyeDualRepl is the entry point for the dual REPL mode

func DoRyeRepl

func DoRyeRepl(es *env.ProgramState, dialect string, showResults bool)

func DropColumn added in v0.0.24

func DropColumn(ps *env.ProgramState, s env.Table, name env.String) env.Object

func DropColumnBlock added in v0.0.24

func DropColumnBlock(ps *env.ProgramState, s env.Table, names env.Block) env.Object

func DropColumns added in v0.0.24

func DropColumns(ps *env.ProgramState, s env.Table, names []env.String) env.Object

Drop one or more columns from a table, returning a new table

func EmptyRM added in v0.0.40

func EmptyRM() env.Dict

EmptyRM creates an empty Dict

func EnableFastEvaluator added in v0.0.40

func EnableFastEvaluator()

EnableFastEvaluator enables the fast evaluator for Rye0 dialect. Called from: Command-line flags or configuration code Purpose: Switches to optimized evaluation mode for Rye0 dialect code

func EscapeJson added in v0.0.20

func EscapeJson(val string) string

func EvalBlock

func EvalBlock(ps *env.ProgramState)

EvalBlock is the main entry point for evaluating a block of code. Called from: Throughout the codebase - main evaluation loops, builtins, function calls Purpose: Dispatches to the appropriate dialect-specific evaluator (Rye2, Eyr, Rye0, Rye00) HOTCODE: Performance-critical function called frequently during execution

func EvalBlockInCtxInj

func EvalBlockInCtxInj(ps *env.ProgramState, ctx *env.RyeCtx, inj env.Object, injnow bool)

EvalBlockInCtxInj evaluates a block in a specific context with value injection. Called from: Builtins that need to evaluate code in a different context Purpose: Temporarily switches to specified context, evaluates block, then restores original context

func EvalBlockInPersistentCtx added in v0.0.82

func EvalBlockInPersistentCtx(ps *env.ProgramState, pctx *PersistentCtx)

EvalBlockInPersistentCtx evaluates a block within a PersistentCtx, ensuring persistence

func EvalBlockInj

func EvalBlockInj(ps *env.ProgramState, inj env.Object, injnow bool)

EvalBlockInj evaluates a block of code with optional value injection for Rye2 dialect. Called from: EvalBlock, CallFunction_CollectArgs, ExecuteDeferredBlocks, observer execution, init() Purpose: Core Rye2 evaluator - loops through expressions, handling injection, commas, and error/failure flags

func EvalBlockInjMultiDialect added in v0.0.22

func EvalBlockInjMultiDialect(ps *env.ProgramState, inj env.Object, injnow bool)

EvalBlockInjMultiDialect evaluates a block with value injection support across multiple dialects. Called from: EvalExpression_DispatchType (for OPGROUP/OPBLOCK modes), observer execution Purpose: Provides multi-dialect block evaluation with the ability to inject values into the first expression

func EvalExpression added in v0.0.81

func EvalExpression(ps *env.ProgramState, inj env.Object, injnow bool, limited bool) bool

EvalExpression is the consolidated expression evaluator handling both regular and injected evaluation. Called from: EvalExpressionInj, EvalExpression_CollectArg, EvalExpressionInjLimited (wrapper functions) Purpose: Evaluates left side via DispatchType, then optionally evaluates right side (opwords/pipewords)

func EvalExpressionInj

func EvalExpressionInj(ps *env.ProgramState, inj env.Object, injnow bool) bool

EvalExpressionInj evaluates an expression with optional value injection. Called from: EvalBlockInj, EvalExpression_DispatchType (OPBBLOCK mode), EvalSetword, EvalModword Purpose: Wrapper for EvalExpression that allows injecting a value into the expression

func EvalExpressionInjLimited

func EvalExpressionInjLimited(ps *env.ProgramState, inj env.Object, injnow bool) bool

EvalExpressionInjLimited evaluates an expression with injection in limited mode (stops at setwords/pipewords). Called from: Various places where expression evaluation should not consume setwords or pipewords Purpose: Limited expression evaluation that prevents consuming certain right-side constructs

func EvalExpression_CollectArg added in v0.0.90

func EvalExpression_CollectArg(ps *env.ProgramState, limited bool)

EvalExpression_CollectArg evaluates an expression without injection (for collecting function arguments). Called from: CallFunction_CollectArgs, CallBuiltin_CollectArgs, CallVarBuiltin, EvalWord Purpose: Wrapper for EvalExpression used when collecting arguments from code

func EvalExpression_DispatchType added in v0.0.90

func EvalExpression_DispatchType(ps *env.ProgramState)

EvalExpression_DispatchType is the core type dispatcher that evaluates individual Rye values. Called from: EvalExpression, EvalWord, EvalGenword Purpose: Main type switch - handles all Rye value types and dispatches to appropriate handlers Note: This is the heart of the evaluator - if Rye were fully Polish notation, this would be most of it

func EvalGenword

func EvalGenword(ps *env.ProgramState, word env.Genword, leftVal env.Object, toLeft bool)

EvalGenword evaluates a generic word (explicitly declared generic). Called from: EvalExpression_DispatchType Purpose: Handles words explicitly marked as generic - evaluates next expression and dispatches on its type

func EvalGetword

func EvalGetword(ps *env.ProgramState, word env.Getword, leftVal env.Object, toLeft bool)

EvalGetword evaluates a get-word (prefixed with ?) which retrieves a value without calling it. Called from: EvalExpression_DispatchType Purpose: Returns the raw value associated with a word without evaluating it (like quoting)

func EvalModword added in v0.0.20

func EvalModword(ps *env.ProgramState, word env.Modword)

EvalModword evaluates a mod-word (word::) which modifies an existing word in the context. Called from: EvalExpression_DispatchType Purpose: Evaluates the expression to the right and modifies an existing word's value, triggers observers

func EvalObject

func EvalObject(ps *env.ProgramState, object env.Object, leftVal env.Object, toLeft bool, ctx *env.RyeCtx, pipeSecond bool, firstVal env.Object)

EvalObject evaluates a Rye object, particularly handling callable types (builtins, functions). Called from: EvalWord, EvalGenword Purpose: Evaluates found objects - dispatches builtins/functions/cpaths to their callers, returns other types

func EvalSetword

func EvalSetword(ps *env.ProgramState, word env.Setword)

EvalSetword evaluates a set-word (word:) which sets a new word in the context. Called from: EvalExpression_DispatchType Purpose: Evaluates the expression to the right and binds the result to a word (creating new binding)

func EvalWord

func EvalWord(ps *env.ProgramState, word env.Object, leftVal env.Object, toLeft bool, pipeSecond bool)

EvalWord evaluates a word by looking up its value and potentially dispatching to generic words. Called from: EvalExpression_DispatchType, OptionallyEvalExpressionRight, EvalObject Purpose: Main word evaluator - looks up in context, tries generic words if not found, handles getcpath mode

func EvaluateLoadedValue added in v0.0.20

func EvaluateLoadedValue(ps *env.ProgramState, block_ env.Object, script_ string, allowMod bool) env.Object

func ExecuteDeferredBlocks added in v0.0.40

func ExecuteDeferredBlocks(ps *env.ProgramState)

ExecuteDeferredBlocks executes all deferred blocks in LIFO order (last in, first out). Called from: CallFunction_CollectArgs, CallFunctionArgs2, CallFunctionArgs4, CallFunctionArgsN (via defer) Purpose: Executes cleanup blocks registered with defer, similar to Go's defer statement

func ExtractFunctionName added in v0.0.93

func ExtractFunctionName(doc string) (name string, found bool)

ExtractFunctionName extracts the function name from a docstring that ends with "(name)" If the pattern is found, returns the name; otherwise returns the full docstring

func Eyr_CallBuiltin

func Eyr_CallBuiltin(bi env.Builtin, ps *env.ProgramState, arg0_ env.Object, toLeft bool) *env.ProgramState

func Eyr_CallBuiltinPipe added in v0.0.22

func Eyr_CallBuiltinPipe(bi env.Builtin, ps *env.ProgramState, arg0_ env.Object) *env.ProgramState

func Eyr_CallFunction added in v0.0.22

func Eyr_CallFunction(fn env.Function, es *env.ProgramState, leftVal env.Object, toLeft bool, session *env.RyeCtx) *env.ProgramState

This is separate from CallFuncitonArgsN so it can manage pulling args directly off of the eyr stack

func Eyr_EvalBlock

func Eyr_EvalBlock(ps *env.ProgramState, full bool) *env.ProgramState

func Eyr_EvalBlockInside added in v0.0.22

func Eyr_EvalBlockInside(ps *env.ProgramState, inj env.Object, injnow bool) *env.ProgramState

func Eyr_EvalExpression

func Eyr_EvalExpression(ps *env.ProgramState) *env.ProgramState

func Eyr_EvalLSetword added in v0.0.20

func Eyr_EvalLSetword(ps *env.ProgramState, word env.LSetword, leftVal env.Object, toLeft bool) *env.ProgramState

func Eyr_EvalObject

func Eyr_EvalObject(es *env.ProgramState, object env.Object, leftVal env.Object, pipeWord bool, session *env.RyeCtx, bakein bool) *env.ProgramState

func Eyr_EvalWord

func Eyr_EvalWord(ps *env.ProgramState, word env.Object, leftVal env.Object, pipeWord bool) *env.ProgramState

func FastCallBuiltin added in v0.0.44

func FastCallBuiltin(ps *env.ProgramState, bi env.Builtin, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object

FastCallBuiltin is an optimized version of CallBuiltin for the common case where all arguments are already available. It skips the argument evaluation, error checking, and currying logic that makes CallBuiltin slower.

This function should be used when: 1. All arguments are already available (no need to evaluate from program state) 2. No currying is needed 3. The builtin function has a fixed number of arguments

func FastCallFunction added in v0.0.80

func FastCallFunction(fn env.Function, ps *env.ProgramState, args []env.Object, ctx *env.RyeCtx) *env.ProgramState

FastCallFunction is an optimized version of Rye0_CallFunction for the common case where all arguments are already available. It skips the complex context determination, argument evaluation, and error checking that makes Rye0_CallFunction slower.

This function should be used when: 1. All arguments are already available (no need to evaluate from program state) 2. The function has a fixed number of arguments (typically small, like 0-3) 3. No complex context path resolution is needed

func FastCallFunctionWithArgs added in v0.0.80

func FastCallFunctionWithArgs(fn env.Function, ps *env.ProgramState, ctx *env.RyeCtx, args ...env.Object) *env.ProgramState

FastCallFunctionWithArgs is an optimized version of Rye0_CallFunctionWithArgs It's similar to FastCallFunction but follows the signature of Rye0_CallFunctionWithArgs

func FileExists added in v0.0.23

func FileExists(filePath string) int

func FormatBacktickQuotes added in v0.0.93

func FormatBacktickQuotes(message string) string

FormatBacktickQuotes processes an error message and highlights text within backticks with a special background color for terminal display. Called from: DisplayEnhancedError Purpose: Converts `word` to highlighted word for better error readability

func FormatBuiltinReference added in v0.0.93

func FormatBuiltinReference(doc string) string

FormatBuiltinReference formats a builtin reference for error display If a name can be extracted from the docstring, it returns the emphasized name Otherwise returns the full docstring Uses backticks to quote the name - the display function will highlight them

func GenerateColumn

func GenerateColumn(ps *env.ProgramState, s env.Table, name env.Word, extractCols env.Block, code env.Block) env.Object

func GenerateColumnRegexReplace added in v0.0.17

func GenerateColumnRegexReplace(ps *env.ProgramState, s *env.Table, name env.Word, fromColName env.Word, re *regexp.Regexp, pattern string) env.Object

func GetNumRowsFrom added in v0.0.31

func GetNumRowsFrom(ps *env.ProgramState, data any) (int, *env.Error)

func GroupBy added in v0.0.17

func GroupBy(ps *env.ProgramState, s env.Table, cols []string, aggregations map[string][]string) env.Object

func HandleEnterConsoleOption added in v0.0.86

func HandleEnterConsoleOption(es *env.ProgramState, genv *env.Idxs)

HandleEnterConsoleOption enters the REPL console for debugging

func HandleListContextOption added in v0.0.86

func HandleListContextOption(es *env.ProgramState, genv *env.Idxs)

HandleListContextOption lists the current context

func HandleNvimOption added in v0.0.86

func HandleNvimOption(fileName string, lineNumber int)

HandleNvimOption opens Neovim at the specified file and line

func HandleVSCodeOption added in v0.0.86

func HandleVSCodeOption(fileName string, lineNumber int)

HandleVSCodeOption opens VSCode at the specified file and line

func IntersectBlocksCustom added in v0.0.34

func IntersectBlocksCustom(a env.Block, b env.Block, ps *env.ProgramState, fn env.Function) []env.Object

func IntersectStringsCustom added in v0.0.34

func IntersectStringsCustom(a env.String, b env.String, ps *env.ProgramState, fn env.Function) string

func LeftJoin added in v0.0.17

func LeftJoin(ps *env.ProgramState, s1 env.Table, s2 env.Table, col1 string, col2 string, innerJoin bool) env.Object

func ListToJSON added in v0.0.20

func ListToJSON(list env.List) string

Inspect returns a string representation of the Integer.

func LoadColumnData added in v0.0.31

func LoadColumnData(ps *env.ProgramState, data any, colIdx int, numRows int, colData []env.TableRow, cols []string) *env.Error

func LoadScriptLocalFile added in v0.0.20

func LoadScriptLocalFile(ps *env.ProgramState, s1 env.Uri) (env.Object, string)

func MakeArgError

func MakeArgError(env1 *env.ProgramState, N int, typ []env.Type, fn string) *env.Error

func MakeArgErrorMessage added in v0.0.25

func MakeArgErrorMessage(N int, allowedTypes []env.Type, fn string) string

func MakeBuiltinError

func MakeBuiltinError(env1 *env.ProgramState, msg string, fn string) *env.Error

func MakeColError added in v0.0.31

func MakeColError(ps *env.ProgramState, builtinName string, colName string, expectedRowCount int, actualRowCount int) *env.Error

func MakeError

func MakeError(env1 *env.ProgramState, msg string) *env.Error

func MakeNativeArgError added in v0.0.19

func MakeNativeArgError(env1 *env.ProgramState, N int, knd []string, fn string) *env.Error

func MakeNeedsThawedArgError added in v0.0.25

func MakeNeedsThawedArgError(env1 *env.ProgramState, fn string) *env.Error

func MakeRyeError

func MakeRyeError(env1 *env.ProgramState, val env.Object, er *env.Error) *env.Error

func Math_EvalBlock added in v0.0.11

func Math_EvalBlock(es *env.ProgramState) []env.Object

func MaybeAcceptComma

func MaybeAcceptComma(ps *env.ProgramState, inj env.Object, injnow bool) bool

MaybeAcceptComma handles comma expression guards between block-level expressions. Called from: EvalBlockInj, EvalExpression_DispatchType (OPBBLOCK mode) Purpose: Checks for and consumes comma separators; re-enables injection if comma found HOTPATH: Called frequently during block evaluation

func MaybeDisplayFailureOrError

func MaybeDisplayFailureOrError(es *env.ProgramState, genv *env.Idxs, tag string)

MaybeDisplayFailureOrError displays errors/failures if error flag is set (wrapper). Called from: Throughout the codebase after evaluation operations Purpose: Wrapper that calls MaybeDisplayFailureOrError2 with default parameters

func MaybeDisplayFailureOrError2 added in v0.0.87

func MaybeDisplayFailureOrError2(es *env.ProgramState, genv *env.Idxs, tag string, topLevel bool, fileMode bool)

MaybeDisplayFailureOrError2 displays errors/failures and optionally offers debugging options. Called from: MaybeDisplayFailureOrError, main REPL/file execution code Purpose: Main error display coordinator - shows enhanced errors and offers debugging in file mode

func MaybeDisplayFailureOrErrorWASM added in v0.0.13

func MaybeDisplayFailureOrErrorWASM(es *env.ProgramState, genv *env.Idxs, printfn func(string), tag string)

MaybeDisplayFailureOrErrorWASM displays errors/failures in WASM environment using custom print function. Called from: WASM build code (main_wasm.go) Purpose: WASM-specific error display that uses provided print function instead of fmt.Println

func MoveCursor

func MoveCursor(x int, y int)

Move cursor to given position

func MoveCursorBackward

func MoveCursorBackward(bias int)

Move cursor backward relative the current position

func MoveCursorDown

func MoveCursorDown(bias int)

Move cursor down relative the current position

func MoveCursorForward

func MoveCursorForward(bias int)

Move cursor forward relative the current position

func MoveCursorUp

func MoveCursorUp(bias int)

Move cursor up relative the current position

func NameOfRyeType added in v0.0.25

func NameOfRyeType(t env.Type) string

func OfferDebuggingOptions added in v0.0.86

func OfferDebuggingOptions(es *env.ProgramState, genv *env.Idxs, tag string)

OfferDebuggingOptions presents debugging options to the user when an error occurs Loops to offer options repeatedly until user chooses to continue or times out

func OptionallyEvalExpressionRight added in v0.0.90

func OptionallyEvalExpressionRight(nextObj env.Object, ps *env.ProgramState, limited bool)

OptionallyEvalExpressionRight evaluates right-side constructs like opwords, pipewords, and setwords. Called from: EvalExpression, recursively from itself Purpose: Handles operator precedence by evaluating opwords/pipewords/setwords/modwords to the right

func PopOutBuffer

func PopOutBuffer() string

func RegisterBuiltins

func RegisterBuiltins(ps *env.ProgramState)

func RegisterBuiltins2

func RegisterBuiltins2(builtins map[string]*env.Builtin, ps *env.ProgramState, name string)

func RegisterBuiltinsInContext added in v0.0.16

func RegisterBuiltinsInContext(builtins map[string]*env.Builtin, ps *env.ProgramState, name string) *env.RyeCtx

func RegisterBuiltinsInSubContext added in v0.0.23

func RegisterBuiltinsInSubContext(builtins map[string]*env.Builtin, ps *env.ProgramState, parent *env.RyeCtx, name string) *env.RyeCtx

func RegisterErrorUtilsBuiltins added in v0.0.82

func RegisterErrorUtilsBuiltins(ps *env.ProgramState)

RegisterErrorUtilsBuiltins registers the error utility builtins

func RegisterVarBuiltins added in v0.0.40

func RegisterVarBuiltins(ps *env.ProgramState)

func RegisterVarBuiltins2 added in v0.0.40

func RegisterVarBuiltins2(builtins map[string]*env.VarBuiltin, ps *env.ProgramState, name string)

func RenameColumn added in v0.0.32

func RenameColumn(ps *env.ProgramState, s *env.Table, oldName env.String, newName env.String) env.Object

Drop one or more columns from a table, returning a new table

func RunDualRepl added in v0.0.40

func RunDualRepl(leftPs, rightPs *env.ProgramState, dialect string, showResults bool)

RunDualRepl runs the dual REPL

func Rye00_CallBuiltin added in v0.0.81

func Rye00_CallBuiltin(bi env.Builtin, ps *env.ProgramState, arg0_ env.Object, toLeft bool, pipeSecond bool, firstVal env.Object)

Rye00_CallBuiltin calls a builtin function. Optimized version that focuses on performance.

func Rye00_EvalBlockInj added in v0.0.81

func Rye00_EvalBlockInj(ps *env.ProgramState, inj env.Object, injnow bool) *env.ProgramState

Rye00_EvalBlockInj evaluates a block with an optional injected value.

func Rye00_EvalExpression_DispatchType added in v0.0.90

func Rye00_EvalExpression_DispatchType(ps *env.ProgramState)

Rye00_EvalExpression_DispatchType evaluates a concrete expression. This is the main part of the evaluator that handles only integers and builtins.

func Rye00_EvalObject added in v0.0.81

func Rye00_EvalObject(ps *env.ProgramState, object env.Object, leftVal env.Object, toLeft bool, ctx *env.RyeCtx, pipeSecond bool, firstVal env.Object)

Rye00_EvalObject evaluates a Rye object. Simplified version that only handles builtins.

func Rye00_EvalWord added in v0.0.81

func Rye00_EvalWord(ps *env.ProgramState, word env.Object, leftVal env.Object, toLeft bool, pipeSecond bool)

Rye00_EvalWord evaluates a word in the current context. Simplified version that only handles builtins.

func Rye00_MaybeDisplayFailureOrError added in v0.0.81

func Rye00_MaybeDisplayFailureOrError(es *env.ProgramState, genv *env.Idxs, tag string)

Rye00_MaybeDisplayFailureOrError displays failure or error information if present.

func Rye00_checkFlagsAfterExpression added in v0.0.81

func Rye00_checkFlagsAfterExpression(ps *env.ProgramState) bool

Rye00_checkFlagsAfterExpression checks if there are failure flags after evaluating a block.

func Rye00_checkForFailureWithBuiltin added in v0.0.81

func Rye00_checkForFailureWithBuiltin(bi env.Builtin, ps *env.ProgramState, n int) bool

Rye00_checkForFailureWithBuiltin checks if there are failure flags and handles them appropriately.

func Rye00_findWordValue added in v0.0.81

func Rye00_findWordValue(ps *env.ProgramState, word1 env.Object) (bool, env.Object, *env.RyeCtx)

Rye00_findWordValue returns the value associated with a word in the current context. Simplified version that only looks for builtins.

func Rye0_CallBuiltin added in v0.0.36

func Rye0_CallBuiltin(bi env.Builtin, ps *env.ProgramState, arg0_ env.Object, toLeft bool, pipeSecond bool, firstVal env.Object) *env.ProgramState

Rye0_CallBuiltin calls a builtin function. Parameters:

  • bi: The builtin to call
  • ps: The program state
  • arg0_: The first argument (if any)
  • toLeft: Whether the call is to the left
  • pipeSecond: Whether this is a pipe second call
  • firstVal: The first value (if any)

Returns:

  • The updated program state

func Rye0_CallFunction added in v0.0.36

func Rye0_CallFunction(fn env.Function, ps *env.ProgramState, arg0 env.Object, toLeft bool, ctx *env.RyeCtx) *env.ProgramState

Rye0_CallFunction calls a function. Parameters:

  • fn: The function to call
  • ps: The program state
  • arg0: The first argument (if any)
  • toLeft: Whether the call is to the left
  • ctx: The context (if any)

Returns:

  • The updated program state

func Rye0_CallFunctionWithArgs added in v0.0.37

func Rye0_CallFunctionWithArgs(fn env.Function, ps *env.ProgramState, ctx *env.RyeCtx, args ...env.Object) *env.ProgramState

Rye0_CallFunctionWithArgs calls a function with the given arguments. This consolidates the functionality of Rye0_CallFunctionArgs2, Rye0_CallFunctionArgs4, and Rye0_CallFunctionArgsN. Parameters:

  • fn: The function to call
  • ps: The program state
  • ctx: The context (if any)
  • args: The arguments to pass to the function

Returns:

  • The updated program state

func Rye0_CallFunction_Optimized added in v0.0.80

func Rye0_CallFunction_Optimized(fn env.Function, ps *env.ProgramState, arg0 env.Object, toLeft bool, ctx *env.RyeCtx) *env.ProgramState

Modified version of Rye0_CallFunction that uses FastCallFunction for common cases

func Rye0_DetermineContext added in v0.0.36

func Rye0_DetermineContext(fn env.Function, ps *env.ProgramState, ctx *env.RyeCtx) *env.RyeCtx

Rye0_DetermineContext determines the appropriate context for a function call. Parameters:

  • fn: The function
  • ps: The program state
  • ctx: The context (if any)

Returns:

  • The determined context

func Rye0_EvalBlockInj added in v0.0.36

func Rye0_EvalBlockInj(ps *env.ProgramState, inj env.Object, injnow bool) *env.ProgramState

Rye0_EvalBlockInj evaluates a block with an optional injected value.

func Rye0_EvalExpressionInj added in v0.0.36

func Rye0_EvalExpressionInj(ps *env.ProgramState, inj env.Object, injnow bool) (*env.ProgramState, bool)

Rye0_EvalExpressionInj evaluates an expression with an optional injected value.

func Rye0_EvalExpression_CollectArg added in v0.0.90

func Rye0_EvalExpression_CollectArg(ps *env.ProgramState, limited bool) *env.ProgramState

Rye0_EvalExpression_CollectArg evaluates an expression with optional limitations.

func Rye0_EvalExpression_DispatchType added in v0.0.90

func Rye0_EvalExpression_DispatchType(ps *env.ProgramState) *env.ProgramState

Rye0_EvalExpression_DispatchType evaluates a concrete expression. This is the main part of the evaluator that handles all Rye value types.

func Rye0_EvalGenword added in v0.0.36

func Rye0_EvalGenword(ps *env.ProgramState, word env.Genword, leftVal env.Object, toLeft bool) *env.ProgramState

Rye0_EvalGenword evaluates a generic word.

func Rye0_EvalGetword added in v0.0.36

func Rye0_EvalGetword(ps *env.ProgramState, word env.Getword, leftVal env.Object, toLeft bool) *env.ProgramState

Rye0_EvalGetword evaluates a get-word.

func Rye0_EvalModword added in v0.0.36

func Rye0_EvalModword(ps *env.ProgramState, word env.Modword) *env.ProgramState

Rye0_EvalModword evaluates a mod-word.

func Rye0_EvalObject added in v0.0.36

func Rye0_EvalObject(ps *env.ProgramState, object env.Object, leftVal env.Object, toLeft bool, ctx *env.RyeCtx, pipeSecond bool, firstVal env.Object) *env.ProgramState

Rye0_EvalObject evaluates a Rye object.

func Rye0_EvalSetword added in v0.0.36

func Rye0_EvalSetword(ps *env.ProgramState, word env.Setword) *env.ProgramState

Rye0_EvalSetword evaluates a set-word.

func Rye0_EvalWord added in v0.0.36

func Rye0_EvalWord(ps *env.ProgramState, word env.Object, leftVal env.Object, toLeft bool, pipeSecond bool) *env.ProgramState

Rye0_EvalWord evaluates a word in the current context.

func Rye0_EvaluateBlock added in v0.0.37

func Rye0_EvaluateBlock(ps *env.ProgramState, block env.Block) *env.ProgramState

Rye0_EvaluateBlock handles the evaluation of a block object.

func Rye0_FastEvalBlock added in v0.0.43

func Rye0_FastEvalBlock(ps *env.ProgramState) *env.ProgramState

Rye0_FastEvalBlock evaluates a block of code using the fast evaluator

func Rye0_MaybeDisplayFailureOrError added in v0.0.36

func Rye0_MaybeDisplayFailureOrError(es *env.ProgramState, genv *env.Idxs, tag string)

Rye0_MaybeDisplayFailureOrError displays failure or error information if present. Parameters:

  • es: The program state
  • genv: The index environment
  • tag: A tag for the error message

func Rye0_MaybeDisplayFailureOrErrorWASM added in v0.0.36

func Rye0_MaybeDisplayFailureOrErrorWASM(es *env.ProgramState, genv *env.Idxs, printfn func(string), tag string)

Rye0_MaybeDisplayFailureOrErrorWASM displays failure or error information for WASM environment. Parameters:

  • es: The program state
  • genv: The index environment
  • printfn: The print function to use
  • tag: A tag for the error message

func Rye0_checkContextErrorHandler added in v0.0.36

func Rye0_checkContextErrorHandler(ps *env.ProgramState) bool

Rye0_checkContextErrorHandler checks if there is an error handler defined in the context. Parameters:

  • ps: The program state

Returns:

  • Whether an error handler was found and executed

func Rye0_checkErrorFlag added in v0.0.81

func Rye0_checkErrorFlag(ps *env.ProgramState) bool

Rye0_checkErrorFlag checks if there are error or return flags.

func Rye0_checkFlagsAfterExpression added in v0.0.81

func Rye0_checkFlagsAfterExpression(ps *env.ProgramState) bool

Rye00_checkFlagsAfterExpression checks if there are failure flags after evaluating a block.

func Rye0_checkForFailureWithBuiltin added in v0.0.81

func Rye0_checkForFailureWithBuiltin(bi env.Builtin, ps *env.ProgramState, n int) bool

Rye0_checkForFailureWithBuiltin checks if there are failure flags and handles them appropriately.

func Rye0_findCPathValue added in v0.0.37

func Rye0_findCPathValue(ps *env.ProgramState, word env.CPath) (bool, env.Object, *env.RyeCtx)

Rye0_findCPathValue handles the lookup of context path values.

func Rye0_findWordValue added in v0.0.36

func Rye0_findWordValue(ps *env.ProgramState, word1 env.Object) (bool, env.Object, *env.RyeCtx)

Rye0_findWordValue returns the value associated with a word in the current context. It also checks if the word refers to a builtin in a parent context, and if so, it can replace the word with the builtin directly in the series for faster future lookups.

func RyeToJSON

func RyeToJSON(res any) string

func RyeToJSONLines added in v0.0.20

func RyeToJSONLines(res any) string

func RyeValueToTableRow added in v0.0.33

func RyeValueToTableRow(spr *env.Table, obj env.Object) (bool, string, *env.TableRow)

func SQL_EvalBlock added in v0.0.21

func SQL_EvalBlock(es *env.ProgramState, mode int, values []any) (*env.ProgramState, []any)

func SQL_EvalExpression added in v0.0.21

func SQL_EvalExpression(es *env.ProgramState, vals []any, mode int) (*env.ProgramState, string, []any)

func SheetFromColumns added in v0.0.31

func SheetFromColumns(ps *env.ProgramState, arg0 env.Object, arg1 env.Object) (res env.Object)

func SheetFromColumnsMapData added in v0.0.31

func SheetFromColumnsMapData(ps *env.ProgramState, cols []string, arg1 env.Object) env.Object

func SortByColumn

func SortByColumn(ps *env.ProgramState, s *env.Table, name string)

func SortByColumnDesc

func SortByColumnDesc(ps *env.ProgramState, s *env.Table, name string)

func Stck_CallBuiltin

func Stck_CallBuiltin(bi env.Builtin, ps *env.ProgramState, arg0_ env.Object, toLeft bool) *env.ProgramState

func Stck_EvalBlock

func Stck_EvalBlock(ps *env.ProgramState) *env.ProgramState

func Stck_EvalExpression

func Stck_EvalExpression(ps *env.ProgramState) *env.ProgramState

func Stck_EvalObject

func Stck_EvalObject(ps *env.ProgramState, object env.Object, leftVal env.Object, toLeft bool, ctx *env.RyeCtx) *env.ProgramState

func Stck_EvalWord

func Stck_EvalWord(ps *env.ProgramState, word env.Object, leftVal env.Object, toLeft bool) *env.ProgramState

func TableRowToJSON added in v0.0.33

func TableRowToJSON(row env.TableRow) string

Inspect returns a string representation of the Integer.

func TableRowsFromBlockOrList added in v0.0.33

func TableRowsFromBlockOrList(ps *env.ProgramState, spr *env.Table, numCols int, arg1 any) (*env.TableRow, *env.Error)

func TableToJSON added in v0.0.33

func TableToJSON(s env.Table) string

Inspect returns a string representation of the Integer.

func TableToJSONLines added in v0.0.33

func TableToJSONLines(s env.Table) string

func TelegramUpdateToRyeDict added in v0.0.21

func TelegramUpdateToRyeDict(update_ tgm.Update) env.Dict

func TriggerObservers added in v0.0.88

func TriggerObservers(ps *env.ProgramState, ctx *env.RyeCtx, wordIndex int, oldValue, newValue env.Object)

TriggerObservers triggers all observers watching a variable that has changed. Called from: EvalModword, OptionallyEvalExpressionRight (LModword case) Purpose: Notifies observers when a variable's value changes, executing their observer blocks

func Validation_EvalBlock

func Validation_EvalBlock(es *env.ProgramState, vals env.Dict) (env.Dict, map[string]env.Object)

func Validation_EvalBlock_Context added in v0.0.85

func Validation_EvalBlock_Context(es *env.ProgramState, vals env.RyeCtx) (env.RyeCtx, map[string]env.Object)

func Validation_EvalBlock_List

func Validation_EvalBlock_List(es *env.ProgramState, vals env.List) (env.Object, []env.Object)

func Validation_EvalBlock_Value added in v0.0.85

func Validation_EvalBlock_Value(es *env.ProgramState, val env.Object) (env.Object, env.Object)

func ValueToBSON added in v0.0.21

func ValueToBSON(arg0 env.Object, topLevel bool) any

func VectorToJSON added in v0.0.24

func VectorToJSON(vector env.Vector) string

func WhereBetween added in v0.0.17

func WhereBetween(ps *env.ProgramState, s *env.Table, name string, val1 env.Object, val2 env.Object, inclusiveMode bool) env.Object

func WhereContains added in v0.0.17

func WhereContains(ps *env.ProgramState, s *env.Table, name string, val string, not bool) env.Object

func WhereEquals

func WhereEquals(ps *env.ProgramState, s env.Table, name string, val env.Object) env.Object

func WhereGreater

func WhereGreater(ps *env.ProgramState, s *env.Table, name string, val env.Object) env.Object

func WhereIn added in v0.0.17

func WhereIn(ps *env.ProgramState, s env.Table, name string, b []env.Object) env.Object

func WhereLesser

func WhereLesser(ps *env.ProgramState, s *env.Table, name string, val env.Object) env.Object

func WhereMatch added in v0.0.17

func WhereMatch(ps *env.ProgramState, s *env.Table, name string, r *regexp.Regexp) env.Object

func WhereNotEquals added in v0.0.82

func WhereNotEquals(ps *env.ProgramState, s env.Table, name string, val env.Object) env.Object

func WhereNotIn added in v0.0.87

func WhereNotIn(ps *env.ProgramState, s env.Table, name string, b []env.Object) env.Object

Types

type ConversionError

type ConversionError struct {
	// contains filtered or unexported fields
}

Integer represents an integer.

type DualReplState added in v0.0.40

type DualReplState struct {
	// contains filtered or unexported fields
}

DualReplState represents the state of the dual REPL

func NewDualReplState added in v0.0.40

func NewDualReplState(leftPs, rightPs *env.ProgramState, dialect string, showResults bool, leftChan chan term.KeyEvent, rightChan chan term.KeyEvent) (*DualReplState, error)

NewDualReplState creates a new dual REPL state

func (*DualReplState) Draw added in v0.0.40

func (d *DualReplState) Draw()

Draw draws the dual REPL UI

func (*DualReplState) HandleInput added in v0.0.40

func (d *DualReplState) HandleInput(ev *tcell.EventKey) bool

HandleInput handles keyboard input for the dual REPL

type HtmlDialectNode added in v0.0.21

type HtmlDialectNode struct {
	Condition *HtmlNavigCondition
	Code      *env.Block
	SubNode   *env.Dict
	Type      int // 1 - node , 2 - code , 3 - direct_descendant (later)
}

type HtmlNavigCondition added in v0.0.21

type HtmlNavigCondition struct {
	Class string
	Id    string
}

type Instruction added in v0.0.43

type Instruction func(vm *Rye0VM) int

Instruction is a function that executes a single instruction in the VM

func Rye0_CompileExpression added in v0.0.43

func Rye0_CompileExpression(ps *env.ProgramState) Instruction

Rye0_CompileExpression compiles a single expression into an Instruction

type MessageDispatcher added in v0.0.90

type MessageDispatcher struct {
	// contains filtered or unexported fields
}

MessageDispatcher provides a high-performance message routing system

func NewMessageDispatcher added in v0.0.90

func NewMessageDispatcher(bufferSize int, initialState env.Dict) *MessageDispatcher

NewMessageDispatcher creates a new message dispatcher

func (*MessageDispatcher) GetState added in v0.0.90

func (md *MessageDispatcher) GetState() env.Dict

GetState returns a copy of the current state

func (*MessageDispatcher) RegisterHandler added in v0.0.90

func (md *MessageDispatcher) RegisterHandler(msgType string, handler env.Function)

RegisterHandler registers a message handler function

func (*MessageDispatcher) Send added in v0.0.90

func (md *MessageDispatcher) Send(msg env.Object) error

Send sends a message to the dispatcher

func (*MessageDispatcher) SetState added in v0.0.90

func (md *MessageDispatcher) SetState(state env.Dict)

SetState updates the state

func (*MessageDispatcher) Start added in v0.0.90

func (md *MessageDispatcher) Start(ps *env.ProgramState, updateCallback env.Function)

Start begins processing messages in a goroutine

func (*MessageDispatcher) Stop added in v0.0.90

func (md *MessageDispatcher) Stop()

Stop stops the message processing loop

func (*MessageDispatcher) UnregisterHandler added in v0.0.90

func (md *MessageDispatcher) UnregisterHandler(msgType string)

UnregisterHandler removes a message handler

type PersistentCtx added in v0.0.82

type PersistentCtx struct {
	env.RyeCtx // Minimal in-memory context for interface compatibility only

	Idxs *env.Idxs
	// contains filtered or unexported fields
}

PersistentCtx wraps a RyeCtx with a BadgerDB backend for persistence. It operates in database-first mode for ACID compliance.

func NewPersistentCtx added in v0.0.82

func NewPersistentCtx(dbPath string, ps *env.ProgramState) (*PersistentCtx, error)

NewPersistentCtx creates a new persistent context or loads an existing one.

func (*PersistentCtx) AsRyeCtx added in v0.0.82

func (pc *PersistentCtx) AsRyeCtx() *env.RyeCtx

AsRyeCtx returns the underlying RyeCtx for backward compatibility

func (*PersistentCtx) Copy added in v0.0.82

func (pc *PersistentCtx) Copy() env.Context

Copy creates a copy of the persistent context (note: copy won't be persistent)

func (*PersistentCtx) Get added in v0.0.88

func (pc *PersistentCtx) Get(word int) (env.Object, bool)

Get overrides the embedded Get method to read from database.

func (*PersistentCtx) GetDoc added in v0.0.82

func (pc *PersistentCtx) GetDoc() string

GetDoc returns the documentation string

func (*PersistentCtx) GetKindWord added in v0.0.82

func (pc *PersistentCtx) GetKindWord() env.Word

GetKindWord returns the Kind as a Word

func (*PersistentCtx) GetParent added in v0.0.82

func (pc *PersistentCtx) GetParent() env.Context

GetParent returns the parent context

func (*PersistentCtx) IsVariable added in v0.0.88

func (pc *PersistentCtx) IsVariable(word int) bool

IsVariable checks if a word is a variable by reading from database

func (*PersistentCtx) MarkAsVariable added in v0.0.88

func (pc *PersistentCtx) MarkAsVariable(word int)

MarkAsVariable marks a word as a variable in the database

func (*PersistentCtx) Mod added in v0.0.82

func (pc *PersistentCtx) Mod(word int, val env.Object) bool

Mod overrides the embedded Mod method to add ACID persistence.

func (*PersistentCtx) Set added in v0.0.82

func (pc *PersistentCtx) Set(word int, val env.Object) env.Object

Set overrides the embedded Set method to add ACID persistence.

func (*PersistentCtx) SetDoc added in v0.0.82

func (pc *PersistentCtx) SetDoc(doc string)

SetDoc sets the documentation string

func (*PersistentCtx) SetKindWord added in v0.0.82

func (pc *PersistentCtx) SetKindWord(kind env.Word)

SetKindWord sets the Kind

func (*PersistentCtx) SetNew added in v0.0.82

func (pc *PersistentCtx) SetNew(word int, val env.Object, idxs *env.Idxs) bool

SetNew overrides the embedded SetNew method to add ACID persistence.

func (*PersistentCtx) SetParent added in v0.0.82

func (pc *PersistentCtx) SetParent(parent env.Context)

SetParent sets the parent context

func (PersistentCtx) Type added in v0.0.82

func (pc PersistentCtx) Type() env.Type

func (*PersistentCtx) Unset added in v0.0.82

func (pc *PersistentCtx) Unset(word int, idxs *env.Idxs) env.Object

Unset overrides the embedded Unset method to add ACID persistence.

type PersistentCtxEvaluator added in v0.0.82

type PersistentCtxEvaluator struct {
	// contains filtered or unexported fields
}

PersistentCtxEvaluator intercepts evaluation to ensure persistence operations go through PersistentCtx

func (*PersistentCtxEvaluator) EvalBlock added in v0.0.82

func (pce *PersistentCtxEvaluator) EvalBlock()

EvalBlock evaluates the current series while intercepting persistence operations

type PersistentRyeCtx added in v0.0.82

type PersistentRyeCtx struct {
	env.RyeCtx
	// contains filtered or unexported fields
}

PersistentRyeCtx is a RyeCtx with persistence methods injected

func CreatePersistentRyeCtx added in v0.0.82

func CreatePersistentRyeCtx(pctx *PersistentCtx) *PersistentRyeCtx

CreatePersistentRyeCtx creates a RyeCtx that has persistent behavior by injecting persistence functions

func (*PersistentRyeCtx) Mod added in v0.0.82

func (w *PersistentRyeCtx) Mod(word int, val env.Object) bool

Override Mod to use PersistentCtx persistence

func (*PersistentRyeCtx) Set added in v0.0.82

func (w *PersistentRyeCtx) Set(word int, val env.Object) env.Object

Override Set to use PersistentCtx persistence

func (*PersistentRyeCtx) SetNew added in v0.0.82

func (w *PersistentRyeCtx) SetNew(word int, val env.Object, idxs *env.Idxs) bool

Override SetNew to use PersistentCtx persistence

func (*PersistentRyeCtx) Unset added in v0.0.82

func (w *PersistentRyeCtx) Unset(word int, idxs *env.Idxs) env.Object

Override Unset to use PersistentCtx persistence

type Program added in v0.0.43

type Program struct {
	// contains filtered or unexported fields
}

Program represents a compiled Rye0 program

func Rye0_CompileBlock added in v0.0.43

func Rye0_CompileBlock(ps *env.ProgramState) *Program

Rye0_CompileBlock compiles a block of code into a Program

type Repl added in v0.0.21

type Repl struct {
	// contains filtered or unexported fields
}

type Rye0VM added in v0.0.43

type Rye0VM struct {
	Sp int // Exported for use in benchmarks
	// contains filtered or unexported fields
}

Rye0VM represents a virtual machine for executing compiled Rye0 code

func NewRye0VM added in v0.0.43

func NewRye0VM(ctx *env.RyeCtx, pctx *env.RyeCtx, gen *env.Gen, idx *env.Idxs) *Rye0VM

NewRye0VM creates a new virtual machine for executing compiled Rye0 code

func (*Rye0VM) Execute added in v0.0.43

func (vm *Rye0VM) Execute(p *Program) (env.Object, error)

Execute executes a compiled program

func (*Rye0VM) Pop added in v0.0.43

func (vm *Rye0VM) Pop() env.Object

Pop pops a value from the stack

func (*Rye0VM) Push added in v0.0.43

func (vm *Rye0VM) Push(val env.Object)

Push pushes a value onto the stack

type RyeBlockCustomSort added in v0.0.34

type RyeBlockCustomSort struct {
	// contains filtered or unexported fields
}

Custom Sort object interface

func (RyeBlockCustomSort) Len added in v0.0.34

func (s RyeBlockCustomSort) Len() int

func (RyeBlockCustomSort) Less added in v0.0.34

func (s RyeBlockCustomSort) Less(i, j int) bool

func (RyeBlockCustomSort) Swap added in v0.0.34

func (s RyeBlockCustomSort) Swap(i, j int)

type RyeBlockSort

type RyeBlockSort []env.Object

Sort object interface

func (RyeBlockSort) Len

func (s RyeBlockSort) Len() int

func (RyeBlockSort) Less

func (s RyeBlockSort) Less(i, j int) bool

func (RyeBlockSort) Swap

func (s RyeBlockSort) Swap(i, j int)

type RyeListCustomSort added in v0.0.34

type RyeListCustomSort struct {
	// contains filtered or unexported fields
}

Custom Sort object interface

func (RyeListCustomSort) Len added in v0.0.34

func (s RyeListCustomSort) Len() int

func (RyeListCustomSort) Less added in v0.0.34

func (s RyeListCustomSort) Less(i, j int) bool

func (RyeListCustomSort) Swap added in v0.0.34

func (s RyeListCustomSort) Swap(i, j int)

type RyeListSort

type RyeListSort []any

Sort list interface

func (RyeListSort) Len

func (s RyeListSort) Len() int

func (RyeListSort) Less

func (s RyeListSort) Less(i, j int) bool

func (RyeListSort) Swap

func (s RyeListSort) Swap(i, j int)

type RyeStringSort added in v0.0.35

type RyeStringSort []rune

Sort list interface

func (RyeStringSort) Len added in v0.0.35

func (s RyeStringSort) Len() int

func (RyeStringSort) Less added in v0.0.35

func (s RyeStringSort) Less(i, j int) bool

func (RyeStringSort) Swap added in v0.0.35

func (s RyeStringSort) Swap(i, j int)

type ShellEd

type ShellEd struct {
	CurrObj env.Function
	Pause   bool
	Askfor  []string
	Mode    string
	Return  env.Object
}

type ValidationError

type ValidationError struct {
	// contains filtered or unexported fields
}

Integer represents an integer.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL