batteries

package
v0.2.61 Latest Latest
Warning

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

Go to latest
Published: Sep 15, 2026 License: BSD-3-Clause Imports: 98 Imported by: 0

Documentation

Overview

moved to evaldo/builtins_error_handling.go

builtins.go

builtins.go

builtins_trees.go

Index

Constants

View Source
const MODE_PSQL = 2 // Uses $1, $2, etc. placeholders
View Source
const MODE_SQLITE = 1 // Uses ? placeholders

SQL mode constants for different database parameter styles

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

Variables

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

	"bcrypt-hash": {
		Argsn: 1,
		Doc:   "Generates a bcrypt hash from a password string.",
		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:   "Compares a bcrypt hash with a plain text 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:   "Generates a cryptographically secure random token of the specified length in bytes.",
		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.Bytes).Value, &val)
			if err != nil {
				return evaldo.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 evaldo.MakeBuiltinError(ps, err.Error(), "to-bson")
			}
			return *env.NewBytes(encoded)
		},
	},
}
View Source
var Builtins_chitosocket = map[string]*env.Builtin{

	"chitosocket": {
		Argsn: 1,
		Doc:   "Creates a new ChitoSocket WebSocket server with the specified number of CPU cores.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch cores := arg0.(type) {
			case env.Integer:
				socket, err := chitosocket.StartUp(int(cores.Value))
				if err != nil {
					ps.FailureFlag = true
					return evaldo.MakeBuiltinError(ps, err.Error(), "chitosocket")
				}
				return *env.NewNative(ps.Idx, socket, "Chitosocket-server")
			default:
				ps.FailureFlag = true
				return evaldo.MakeArgError(ps, 1, []env.Type{env.IntegerType}, "chitosocket")
			}
		},
	},

	"Chitosocket-server//close": {
		Argsn: 1,
		Doc:   "Closes the ChitoSocket server and releases resources.",
		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:
				sock := server.Value.(*chitosocket.Socket)
				err := sock.Close()
				if err != nil {
					ps.FailureFlag = true
					return evaldo.MakeBuiltinError(ps, err.Error(), "Chitosocket-server//close")
				}
				return *env.NewInteger(1)
			default:
				ps.FailureFlag = true
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "Chitosocket-server//close")
			}
		},
	},

	"Chitosocket-server//on": {
		Argsn: 3,
		Doc:   "Registers an event handler for the specified event name. Handler receives subscriber and data as arguments.",
		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 eventName := arg1.(type) {
				case env.String:
					switch handler := arg2.(type) {
					case env.Function:
						sock := server.Value.(*chitosocket.Socket)
						sock.On[eventName.Value] = func(sub *chitosocket.Subscriber, data []byte) {

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

							subNative := *env.NewNative(ps.Idx, sub, "Chitosocket-subscriber")
							dataStr := *env.NewString(string(data))

							evaldo.CallFunctionArgs2(handler, ps, subNative, dataStr, nil)
						}
						return arg0
					default:
						ps.FailureFlag = true
						return evaldo.MakeArgError(ps, 3, []env.Type{env.FunctionType}, "Chitosocket-server//on")
					}
				case env.Word:
					switch handler := arg2.(type) {
					case env.Function:
						sock := server.Value.(*chitosocket.Socket)
						eventNameStr := ps.Idx.GetWord(eventName.Index)
						sock.On[eventNameStr] = func(sub *chitosocket.Subscriber, data []byte) {
							ps.FailureFlag = false
							ps.ErrorFlag = false
							ps.ReturnFlag = false

							subNative := *env.NewNative(ps.Idx, sub, "Chitosocket-subscriber")
							dataStr := *env.NewString(string(data))

							evaldo.CallFunctionArgs2(handler, ps, subNative, dataStr, nil)
						}
						return arg0
					default:
						ps.FailureFlag = true
						return evaldo.MakeArgError(ps, 3, []env.Type{env.FunctionType}, "Chitosocket-server//on")
					}
				default:
					ps.FailureFlag = true
					return evaldo.MakeArgError(ps, 2, []env.Type{env.StringType, env.WordType}, "Chitosocket-server//on")
				}
			default:
				ps.FailureFlag = true
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "Chitosocket-server//on")
			}
		},
	},

	"Chitosocket-server//upgrade-connection": {
		Argsn: 3,
		Doc:   "Upgrades an HTTP connection to WebSocket. Returns a block with connection, response writer, and subscriber.",
		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 req := arg1.(type) {
				case env.Native:
					switch w := arg2.(type) {
					case env.Native:
						sock := server.Value.(*chitosocket.Socket)

						httpReq, ok1 := req.Value.(*http.Request)
						httpWriter, ok2 := w.Value.(http.ResponseWriter)

						if !ok1 || !ok2 {
							ps.FailureFlag = true
							return evaldo.MakeBuiltinError(ps, "Invalid HTTP request or response writer types", "Chitosocket-server//upgrade-connection")
						}

						conn, rw, sub, err := sock.UpgradeConnection(httpReq, httpWriter)
						if err != nil {
							ps.FailureFlag = true
							return evaldo.MakeBuiltinError(ps, err.Error(), "Chitosocket-server//upgrade-connection")
						}

						result := make([]env.Object, 3)
						result[0] = *env.NewNative(ps.Idx, conn, "Chitosocket-connection")
						result[1] = *env.NewNative(ps.Idx, rw, "Chitosocket-response-writer")
						result[2] = *env.NewNative(ps.Idx, sub, "Chitosocket-subscriber")

						return *env.NewBlock(*env.NewTSeries(result))
					default:
						ps.FailureFlag = true
						return evaldo.MakeArgError(ps, 3, []env.Type{env.NativeType}, "Chitosocket-server//upgrade-connection")
					}
				default:
					ps.FailureFlag = true
					return evaldo.MakeArgError(ps, 2, []env.Type{env.NativeType}, "Chitosocket-server//upgrade-connection")
				}
			default:
				ps.FailureFlag = true
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "Chitosocket-server//upgrade-connection")
			}
		},
	},

	"Chitosocket-server//emit-direct": {
		Argsn: 4,
		Doc:   "Emits an event directly to a specific subscriber with the given data.",
		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 sub := arg1.(type) {
				case env.Native:
					switch eventName := arg2.(type) {
					case env.String:
						sock := server.Value.(*chitosocket.Socket)
						subscriber := sub.Value.(*chitosocket.Subscriber)

						var dataBytes []byte
						switch data := arg3.(type) {
						case env.String:
							dataBytes = []byte(data.Value)
						case env.Dict:
							jsonData, err := json.Marshal(data.Data)
							if err != nil {
								ps.FailureFlag = true
								return evaldo.MakeBuiltinError(ps, err.Error(), "Chitosocket-server//emit-direct")
							}
							dataBytes = jsonData
						default:
							dataBytes = []byte(arg3.Inspect(*ps.Idx))
						}

						sock.EmitDirect(subscriber, eventName.Value, dataBytes)
						return *env.NewInteger(1)
					default:
						ps.FailureFlag = true
						return evaldo.MakeArgError(ps, 3, []env.Type{env.StringType}, "Chitosocket-server//emit-direct")
					}
				default:
					ps.FailureFlag = true
					return evaldo.MakeArgError(ps, 2, []env.Type{env.NativeType}, "Chitosocket-server//emit-direct")
				}
			default:
				ps.FailureFlag = true
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "Chitosocket-server//emit-direct")
			}
		},
	},

	"Chitosocket-server//emit": {
		Argsn: 4,
		Doc:   "Emits an event to all subscribers in a specific room (excluding none).",
		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 eventName := arg1.(type) {
				case env.String:
					switch room := arg3.(type) {
					case env.String:
						sock := server.Value.(*chitosocket.Socket)

						var dataBytes []byte
						switch data := arg2.(type) {
						case env.String:
							dataBytes = []byte(data.Value)
						case env.Dict:
							jsonData, err := json.Marshal(data.Data)
							if err != nil {
								ps.FailureFlag = true
								return evaldo.MakeBuiltinError(ps, err.Error(), "Chitosocket-server//emit")
							}
							dataBytes = jsonData
						default:
							dataBytes = []byte(arg2.Inspect(*ps.Idx))
						}

						sock.Emit(eventName.Value, nil, dataBytes, room.Value)
						return *env.NewInteger(1)
					default:
						ps.FailureFlag = true
						return evaldo.MakeArgError(ps, 4, []env.Type{env.StringType}, "Chitosocket-server//emit")
					}
				default:
					ps.FailureFlag = true
					return evaldo.MakeArgError(ps, 2, []env.Type{env.StringType}, "Chitosocket-server//emit")
				}
			default:
				ps.FailureFlag = true
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "Chitosocket-server//emit")
			}
		},
	},

	"Chitosocket-server//broadcast": {
		Argsn: 3,
		Doc:   "Broadcasts an event to all connected subscribers.",
		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 eventName := arg1.(type) {
				case env.String:
					sock := server.Value.(*chitosocket.Socket)

					var dataBytes []byte
					switch data := arg2.(type) {
					case env.String:
						dataBytes = []byte(data.Value)
					case env.Dict:
						jsonData, err := json.Marshal(data.Data)
						if err != nil {
							ps.FailureFlag = true
							return evaldo.MakeBuiltinError(ps, err.Error(), "Chitosocket-server//broadcast")
						}
						dataBytes = jsonData
					default:
						dataBytes = []byte(arg2.Inspect(*ps.Idx))
					}

					sock.Broadcast(eventName.Value, dataBytes)
					return *env.NewInteger(1)
				default:
					ps.FailureFlag = true
					return evaldo.MakeArgError(ps, 2, []env.Type{env.StringType}, "Chitosocket-server//broadcast")
				}
			default:
				ps.FailureFlag = true
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "Chitosocket-server//broadcast")
			}
		},
	},

	"Chitosocket-server//add-to-room": {
		Argsn: 3,
		Doc:   "Adds a subscriber to a room.",
		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 sub := arg1.(type) {
				case env.Native:
					switch room := arg2.(type) {
					case env.String:
						sock := server.Value.(*chitosocket.Socket)
						subscriber := sub.Value.(*chitosocket.Subscriber)
						sock.AddToRoom(subscriber, room.Value)
						return *env.NewInteger(1)
					default:
						ps.FailureFlag = true
						return evaldo.MakeArgError(ps, 3, []env.Type{env.StringType}, "Chitosocket-server//add-to-room")
					}
				default:
					ps.FailureFlag = true
					return evaldo.MakeArgError(ps, 2, []env.Type{env.NativeType}, "Chitosocket-server//add-to-room")
				}
			default:
				ps.FailureFlag = true
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "Chitosocket-server//add-to-room")
			}
		},
	},

	"Chitosocket-server//remove-from-room": {
		Argsn: 3,
		Doc:   "Removes a subscriber from a room.",
		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 sub := arg1.(type) {
				case env.Native:
					switch room := arg2.(type) {
					case env.String:
						sock := server.Value.(*chitosocket.Socket)
						subscriber := sub.Value.(*chitosocket.Subscriber)
						sock.RemoveFromRoom(subscriber, room.Value)
						return *env.NewInteger(1)
					default:
						ps.FailureFlag = true
						return evaldo.MakeArgError(ps, 3, []env.Type{env.StringType}, "Chitosocket-server//remove-from-room")
					}
				default:
					ps.FailureFlag = true
					return evaldo.MakeArgError(ps, 2, []env.Type{env.NativeType}, "Chitosocket-server//remove-from-room")
				}
			default:
				ps.FailureFlag = true
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "Chitosocket-server//remove-from-room")
			}
		},
	},

	"Chitosocket-server//room-count?": {
		Argsn: 2,
		Doc:   "Returns the number of subscribers in a room.",
		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 room := arg1.(type) {
				case env.String:
					sock := server.Value.(*chitosocket.Socket)
					count := sock.GetRoomCount(room.Value)
					return *env.NewInteger(int64(count))
				default:
					ps.FailureFlag = true
					return evaldo.MakeArgError(ps, 2, []env.Type{env.StringType}, "Chitosocket-server//room-count?")
				}
			default:
				ps.FailureFlag = true
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "Chitosocket-server//room-count?")
			}
		},
	},

	"Chitosocket-subscriber//id?": {
		Argsn: 1,
		Doc:   "Returns the unique ID of the subscriber.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch sub := arg0.(type) {
			case env.Native:
				subscriber := sub.Value.(*chitosocket.Subscriber)
				return *env.NewString(subscriber.ID)
			default:
				ps.FailureFlag = true
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "Chitosocket-subscriber//id?")
			}
		},
	},

	"Chitosocket-server//handler?": {
		Argsn: 2,
		Doc:   "Returns the handler function for a specific event, or void if not set.",
		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 eventName := arg1.(type) {
				case env.String:
					sock := server.Value.(*chitosocket.Socket)
					if handler, ok := sock.On[eventName.Value]; ok {
						return *env.NewNative(ps.Idx, handler, "Chitosocket-handler")
					}
					return env.Void{}
				default:
					ps.FailureFlag = true
					return evaldo.MakeArgError(ps, 2, []env.Type{env.StringType}, "Chitosocket-server//handler?")
				}
			default:
				ps.FailureFlag = true
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "Chitosocket-server//handler?")
			}
		},
	},

	"Chitosocket-handler//call": {
		Argsn: 3,
		Doc:   "Calls a handler function with the given subscriber and data.",
		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.Native:
				switch sub := arg1.(type) {
				case env.Native:
					handlerFn := handler.Value.(chitosocket.HandlerFunc)
					subscriber := sub.Value.(*chitosocket.Subscriber)

					var dataBytes []byte
					switch data := arg2.(type) {
					case env.String:
						dataBytes = []byte(data.Value)
					case env.Void:
						dataBytes = nil
					default:
						dataBytes = []byte(arg2.Inspect(*ps.Idx))
					}

					handlerFn(subscriber, dataBytes)
					return *env.NewInteger(1)
				default:
					ps.FailureFlag = true
					return evaldo.MakeArgError(ps, 2, []env.Type{env.NativeType}, "Chitosocket-handler//call")
				}
			default:
				ps.FailureFlag = true
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "Chitosocket-handler//call")
			}
		},
	},

	"Chitosocket-server//remove": {
		Argsn: 2,
		Doc:   "Removes a subscriber from the server.",
		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 sub := arg1.(type) {
				case env.Native:
					sock := server.Value.(*chitosocket.Socket)
					subscriber := sub.Value.(*chitosocket.Subscriber)
					err := sock.Remove(subscriber)
					if err != nil {
						ps.FailureFlag = true
						return evaldo.MakeBuiltinError(ps, err.Error(), "Chitosocket-server//remove")
					}
					return *env.NewInteger(1)
				default:
					ps.FailureFlag = true
					return evaldo.MakeArgError(ps, 2, []env.Type{env.NativeType}, "Chitosocket-server//remove")
				}
			default:
				ps.FailureFlag = true
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "Chitosocket-server//remove")
			}
		},
	},
}

Builtins_chitosocket provides WebSocket server functionality with room support

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

	"parse-args": {
		Argsn: 2,
		Doc:   "Parses command line arguments according to a specification block, returning a dictionary with the parsed values.",
		Fn: func(es *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return BuiParseArgs(es, arg0, arg1)
		},
	},

	"parse-args\\ctx": {
		Argsn: 2,
		Doc:   "Parses command line arguments according to a specification block, returning a context for easy field access.",
		Fn: func(es *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			result := BuiParseArgs(es, arg0, arg1)
			if es.FailureFlag {
				return result
			}
			switch dict := result.(type) {
			case env.Dict:

				ctx := env.NewEnv(nil)
				for k, v := range dict.Data {
					idx := es.Idx.IndexWord(k)
					if obj, ok := v.(env.Object); ok {
						ctx.Set(idx, obj)
					} else {
						ctx.Set(idx, env.ToRyeValue(v))
					}
				}
				return ctx
			default:
				return result
			}
		},
	},

	"generate-help": {
		Argsn: 1,
		Doc:   "Generates help text from a CLI specification block.",
		Fn: func(es *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			spec, ok := arg0.(env.Block)
			if !ok {
				es.FailureFlag = true
				return evaldo.MakeArgError(es, 1, []env.Type{env.BlockType}, "generate-help")
			}

			cliSpec, err := CLI_ParseSpec(es, spec)
			if err != nil {
				es.FailureFlag = true
				return env.NewError2(400, "spec error: "+err.Error())
			}

			helpText := generateHelpText(es, cliSpec, nil)
			return *env.NewString(helpText)
		},
	},

	"generate-help\\command": {
		Argsn: 2,
		Doc:   "Generates help text for a specific subcommand.",
		Fn: func(es *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			spec, ok := arg0.(env.Block)
			if !ok {
				es.FailureFlag = true
				return evaldo.MakeArgError(es, 1, []env.Type{env.BlockType}, "generate-help\\command")
			}

			cmdPath := make([]string, 0)
			switch cmd := arg1.(type) {
			case env.String:
				if cmd.Value != "" {
					cmdPath = strings.Split(cmd.Value, " ")
				}
			case env.Block:
				ser := cmd.Series
				ser.Reset()
				for ser.Pos() < ser.Len() {
					obj := ser.Pop()
					if s, ok := obj.(env.String); ok {
						cmdPath = append(cmdPath, s.Value)
					} else if w, ok := obj.(env.Word); ok {
						cmdPath = append(cmdPath, es.Idx.GetWord(w.Index))
					}
				}
			default:
				es.FailureFlag = true
				return evaldo.MakeArgError(es, 2, []env.Type{env.StringType, env.BlockType}, "generate-help\\command")
			}

			cliSpec, err := CLI_ParseSpec(es, spec)
			if err != nil {
				es.FailureFlag = true
				return env.NewError2(400, "spec error: "+err.Error())
			}

			helpText := generateHelpText(es, cliSpec, cmdPath)
			return *env.NewString(helpText)
		},
	},

	"format-parse-errors": {
		Argsn: 1,
		Doc:   "Formats parse errors into human-readable messages.",
		Fn: func(es *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch errObj := arg0.(type) {
			case env.Dict:
				errors := make(map[string]env.Object)
				for k, v := range errObj.Data {
					if obj, ok := v.(env.Object); ok {
						errors[k] = obj
					}
				}
				return *env.NewString(formatParseErrors(errors))
			case *env.Error:

				if errObj.Values != nil {
					return *env.NewString(formatParseErrors(errObj.Values))
				}
				return *env.NewString(errObj.Message)
			default:
				es.FailureFlag = true
				return evaldo.MakeArgError(es, 1, []env.Type{env.DictType}, "format-parse-errors")
			}
		},
	},
}
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 evaldo.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:
						evaldo.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
						evaldo.Eval(ps)
						evaldo.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 evaldo.MakeArgError(ps, 1, []env.Type{env.BlockType, env.ListType}, "cmd")
			}

			if len(args) == 0 {
				return evaldo.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 evaldo.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 evaldo.MakeBuiltinError(ps, "arg1 must be of kind command", "Pipe!")
				}
			default:
				return evaldo.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 evaldo.MakeBuiltinError(ps, err.Error(), "Run")
			}
			err = c.cmd.Run()
			if err != nil {
				ps.FailureFlag = true
				return evaldo.MakeBuiltinError(ps, err.Error(), "Run")
			}
			return *env.NewBoolean(true)
		}),
	},

	"command//Start": {
		Argsn: 1,
		Doc:   "Start a command (and any piped commands) without waiting.",
		Fn: commandFn("Start", func(ps *env.ProgramState, c *command, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			if c.started {
				return arg0
			}
			if err := c.StartPipe(); err != nil {
				ps.FailureFlag = true
				return evaldo.MakeBuiltinError(ps, err.Error(), "Start")
			}
			if err := c.cmd.Start(); err != nil {
				ps.FailureFlag = true
				return evaldo.MakeBuiltinError(ps, err.Error(), "Start")
			}
			c.started = true
			return arg0
		}),
	},

	"command//Kill": {
		Argsn: 1,
		Doc:   "Kill a started command (and any started piped commands).",
		Fn: commandFn("Kill", func(ps *env.ProgramState, c *command, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			var firstErr error
			if c.cmd != nil && c.cmd.Process != nil {
				if err := c.cmd.Process.Kill(); err != nil && firstErr == nil {
					firstErr = err
				}
			}
			for _, pc := range c.pipe {
				if pc != nil && pc.Process != nil {
					if err := pc.Process.Kill(); err != nil && firstErr == nil {
						firstErr = err
					}
				}
			}
			_ = c.Close()
			c.closed = true
			if firstErr != nil {
				ps.FailureFlag = true
				return evaldo.MakeBuiltinError(ps, firstErr.Error(), "Kill")
			}
			return *env.NewBoolean(true)
		}),
	},

	"command//Pid": {
		Argsn: 1,
		Doc:   "Return the process id of the main command (or -1 if not started).",
		Fn: commandFn("Pid", func(ps *env.ProgramState, c *command, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			if c.cmd == nil || c.cmd.Process == nil {
				return *env.NewInteger(-1)
			}
			return *env.NewInteger(int64(c.cmd.Process.Pid))
		}),
	},

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

	"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 evaldo.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 evaldo.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 evaldo.MakeBuiltinError(ps, err.Error(), "Output")
			}
			c.cmd.Stdout = nil
			out, err := c.cmd.Output()
			if err != nil {
				ps.FailureFlag = true
				return evaldo.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 evaldo.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 evaldo.MakeBuiltinError(ps, err.Error(), "CombinedOutput")
			}
			return *env.NewString(string(out))
		}),
	},

	"command//Detach!": {
		Argsn: 1,
		Doc:   "Redirect stdin, stdout, and stderr of a command to /dev/null.",
		Fn: commandFn("Detach!", func(ps *env.ProgramState, c *command, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {

			f, err := os.OpenFile("/dev/null", os.O_RDWR, 0)
			if err != nil {
				ps.FailureFlag = true
				return evaldo.MakeBuiltinError(ps, err.Error(), "Detach!")
			}
			c.files = append(c.files, f)
			c.cmd.Stdin = f
			c.cmd.Stdout = f
			c.cmd.Stderr = f
			return arg0
		}),
	},
}
View Source
var Builtins_complex = map[string]*env.Builtin{

	"complex": {
		Argsn: 2,
		Doc:   "Creates a complex number from real and imaginary parts.",
		Pure:  true,
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			var real, imag float64

			switch r := arg0.(type) {
			case env.Integer:
				real = float64(r.Value)
			case env.Decimal:
				real = r.Value
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.IntegerType, env.DecimalType}, "complex")
			}

			switch i := arg1.(type) {
			case env.Integer:
				imag = float64(i.Value)
			case env.Decimal:
				imag = i.Value
			default:
				return evaldo.MakeArgError(ps, 2, []env.Type{env.IntegerType, env.DecimalType}, "complex")
			}

			return *env.NewComplexFromParts(real, imag)
		},
	},

	"complex?": {
		Argsn: 1,
		Doc:   "Checks if a value is a complex number.",
		Pure:  true,
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			_, ok := arg0.(env.Complex)
			return *env.NewBoolean(ok)
		},
	},

	"real": {
		Argsn: 1,
		Doc:   "Returns the real part of a complex number.",
		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 c := arg0.(type) {
			case env.Complex:
				return *env.NewDecimal(real(c.Value))
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.ComplexType}, "real")
			}
		},
	},

	"imag": {
		Argsn: 1,
		Doc:   "Returns the imaginary part of a complex number.",
		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 c := arg0.(type) {
			case env.Complex:
				return *env.NewDecimal(imag(c.Value))
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.ComplexType}, "imag")
			}
		},
	},

	"complex-conj": {
		Argsn: 1,
		Doc:   "Returns the complex conjugate of a complex number.",
		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 z := arg0.(type) {
			case env.Complex:
				return *env.NewComplex(cmplx.Conj(z.Value))
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.ComplexType}, "complex-conj")
			}
		},
	},

	"complex-phase": {
		Argsn: 1,
		Doc:   "Returns the phase (argument) of a complex number.",
		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 z := arg0.(type) {
			case env.Complex:
				return *env.NewDecimal(cmplx.Phase(z.Value))
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.ComplexType}, "complex-phase")
			}
		},
	},
}
View Source
var Builtins_console = map[string]*env.Builtin{

	"enter-console": {
		Argsn: 1,
		Doc:   "Stops execution and gives you an interactive Rye console to test code in the current 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("-------------------------------------------------------------")

				console.DoRyeRepl(ps, "rye", evaldo.ShowResults, false, "")
				fmt.Println("-------------------------------------------------------------")
				ps.Ser = ser
				return ps.Res
			default:
				return evaldo.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 based on a conversion specification block.",
		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:   "Registers 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 evaldo.MakeArgError(ps, 3, []env.Type{env.BlockType}, "converter")
					}
				default:
					return evaldo.MakeArgError(ps, 2, []env.Type{env.KindType, env.BlockType}, "converter")
				}
			default:
				return evaldo.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 evaldo.MakeBuiltinError(ps, "Failure to decode string.", "decode\\hex")
				}
				return *env.NewBytes(r)
			default:
				ps.FailureFlag = true
				return evaldo.MakeArgError(ps, 1, []env.Type{env.StringType}, "decode\\hex")
			}
		},
	},

	"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.Bytes:
				return *env.NewString(hex.EncodeToString(addr.Value))
			default:
				ps.FailureFlag = true
				return evaldo.MakeArgError(ps, 1, []env.Type{env.BytesType}, "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 evaldo.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 evaldo.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 evaldo.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 evaldo.MakeBuiltinError(ps, "Error in decoding string.", "ed25519-private-key")
				}
			default:
				ps.FailureFlag = true
				return evaldo.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 evaldo.MakeBuiltinError(ps, "Error in decoding string.", "ed25519-public-key")
				}
			default:
				ps.FailureFlag = true
				return evaldo.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.NewBytes(sigb)
				default:
					ps.FailureFlag = true
					return evaldo.MakeArgError(ps, 1, []env.Type{env.StringType}, "Ed25519-priv-key//Sign")
				}
			default:
				ps.FailureFlag = true
				return evaldo.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 evaldo.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 evaldo.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.Bytes:
				identity, err = age.ParseX25519Identity(hex.EncodeToString(ident.Value))
				if err != nil {
					ps.FailureFlag = true
					return evaldo.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 evaldo.MakeBuiltinError(ps, "Error in decoding string: "+err.Error(), "age-identity")
				}
			default:
				ps.FailureFlag = true
				return evaldo.MakeArgError(ps, 1, []env.Type{env.BytesType, 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.Bytes:
				recipient, err = age.ParseX25519Recipient(hex.EncodeToString(rec.Value))
				if err != nil {
					ps.FailureFlag = true
					return evaldo.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 evaldo.MakeBuiltinError(ps, "Error in decoding string: "+err.Error(), "age-recipient")
				}
			default:
				ps.FailureFlag = true
				return evaldo.MakeArgError(ps, 1, []env.Type{env.BytesType, 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 evaldo.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 evaldo.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 evaldo.MakeBuiltinError(ps, "Error in creating recipient: "+err.Error(), "age-encrypt")
					}
				default:
					ps.FailureFlag = true
					return evaldo.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 evaldo.MakeBuiltinError(ps, "Error in encrypting: "+err.Error(), "age-encrypt")
				}

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

				if _, err := w.Write(data); err != nil {
					ps.FailureFlag = true
					return evaldo.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 evaldo.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 evaldo.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 evaldo.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 evaldo.MakeBuiltinError(ps, "Error in creating identity: "+err.Error(), "age-decrypt")
					}
				default:
					ps.FailureFlag = true
					return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType, env.StringType}, "age-decrypt")
				}
				decrypted, err := age.Decrypt(reader, identity)
				if err != nil {
					ps.FailureFlag = true
					return evaldo.MakeBuiltinError(ps, "Error in decrypting: "+err.Error(), "age-decrypt")
				}
				return *env.NewNative(ps.Idx, decrypted, "reader")
			default:
				ps.FailureFlag = true
				return evaldo.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.Bytes:
				switch password := arg1.(type) {
				case env.String:
					blocks, err := pkcs12.ToPEM(p12Data.Value, password.Value)
					if err != nil {
						ps.FailureFlag = true
						return evaldo.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 evaldo.MakeArgError(ps, 2, []env.Type{env.StringType}, "pkcs12-to-pem")
				}
			default:
				ps.FailureFlag = true
				return evaldo.MakeArgError(ps, 1, []env.Type{env.BytesType}, "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.Bytes:
				switch password := arg1.(type) {
				case env.String:
					key, cert, caCerts, err := sslmate.DecodeChain(p12Data.Value, password.Value)
					if err != nil {
						ps.FailureFlag = true
						return evaldo.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 evaldo.MakeArgError(ps, 2, []env.Type{env.StringType}, "pkcs12-decode")
				}
			default:
				ps.FailureFlag = true
				return evaldo.MakeArgError(ps, 1, []env.Type{env.BytesType}, "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 evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "x509-parse-certificate")
				}
				pb, ok := certData.Value.(*pem.Block)
				if ok {
					return *env.NewString(pb.Type)
				}
				return evaldo.MakeBuiltinError(ps, fmt.Sprintf("Failed to parse certificate"), "x509-parse-certificate")

			default:
				ps.FailureFlag = true
				return evaldo.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 evaldo.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 evaldo.MakeBuiltinError(ps, fmt.Sprintf("Failed to parse certificate"), "x509-parse-certificate")

			default:
				ps.FailureFlag = true
				return evaldo.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 evaldo.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 evaldo.MakeBuiltinError(ps, fmt.Sprintf("Failed to parse certificate: %v", err), "x509-parse-certificate")
					}
					return *env.NewNative(ps.Idx, cert, "x509-certificate")
				}
				return evaldo.MakeBuiltinError(ps, fmt.Sprintf("Failed to parse certificate"), "x509-parse-certificate")

			default:
				ps.FailureFlag = true
				return evaldo.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 evaldo.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 evaldo.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 evaldo.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 evaldo.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 evaldo.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 evaldo.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 evaldo.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 evaldo.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 evaldo.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 evaldo.MakeArgError(ps, 2, []env.Type{env.DictType}, "generate-self-signed-certificate")
				}
			default:
				ps.FailureFlag = true
				return evaldo.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 evaldo.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 evaldo.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 evaldo.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 evaldo.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 evaldo.MakeArgError(ps, 2, []env.Type{env.NativeType}, "encode-to-pem")
				}
			default:
				ps.FailureFlag = true
				return evaldo.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 evaldo.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 evaldo.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 evaldo.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 evaldo.MakeArgError(ps, 3, []env.Type{env.StringType}, "encode-to-p12")
					}
				default:
					ps.FailureFlag = true
					return evaldo.MakeArgError(ps, 2, []env.Type{env.NativeType}, "encode-to-p12")
				}
			default:
				ps.FailureFlag = true
				return evaldo.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 evaldo.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 evaldo.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 evaldo.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 evaldo.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 evaldo.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 evaldo.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 evaldo.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 evaldo.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 evaldo.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 evaldo.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 evaldo.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 evaldo.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 evaldo.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 evaldo.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 evaldo.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 evaldo.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 evaldo.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 evaldo.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 evaldo.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 evaldo.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 evaldo.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 evaldo.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 evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "private-key//type?")
				}
				return *env.NewString(fmt.Sprintf("%T", key.Value))
			default:
				ps.FailureFlag = true
				return evaldo.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 evaldo.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 evaldo.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 evaldo.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 evaldo.MakeArgError(ps, 1, []env.Type{env.StringType}, "title-opts")
			}
			subtitle, ok := arg1.(env.String)
			if !ok {
				return evaldo.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 evaldo.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 evaldo.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 evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "echarts-bar//Global-options!")
			}
			bar, ok := barNat.Value.(*charts.Bar)
			if !ok {
				return evaldo.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 evaldo.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 evaldo.MakeBuiltinError(ps, "block must contain native echarts-global-opts", "echarts-bar//Global-options!")
					}
					gopt, ok := nat.Value.(charts.GlobalOpts)
					if !ok {
						return evaldo.MakeBuiltinError(ps, "block must contain echarts-global-opts natives", "echarts-bar//Global-options!")
					}
					gopts = append(gopts, gopt)
				}
			default:
				return evaldo.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 evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "echarts-bar//X-axis!")
			}
			bar, ok := barNat.Value.(*charts.Bar)
			if !ok {
				return evaldo.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 evaldo.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 evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "echarts-bar//Add-series")
			}
			bar, ok := barNat.Value.(*charts.Bar)
			if !ok {
				return evaldo.MakeNativeArgError(ps, 1, []string{"echarts-bar"}, "echarts-bar//Add-series")
			}
			name, ok := arg1.(env.String)
			if !ok {
				return evaldo.MakeArgError(ps, 2, []env.Type{env.StringType}, "echarts-bar//Add-series")
			}
			dataNat, ok := arg2.(env.Native)
			if !ok {
				return evaldo.MakeArgError(ps, 3, []env.Type{env.NativeType}, "echarts-bar//Add-series")
			}
			data, ok := dataNat.Value.([]opts.BarData)
			if !ok {
				return evaldo.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 evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "echarts-bar//Render")
			}
			bar, ok := barNat.Value.(*charts.Bar)
			if !ok {
				return evaldo.MakeNativeArgError(ps, 1, []string{"echarts-bar"}, "echarts-bar//Render")
			}
			writerNat, ok := arg1.(env.Native)
			if !ok {
				return evaldo.MakeArgError(ps, 2, []env.Type{env.NativeType}, "echarts-bar//Render")
			}
			writer, ok := writerNat.Value.(io.Writer)
			if !ok {
				return evaldo.MakeNativeArgError(ps, 2, []string{"io.Writer (e.g., file)"}, "echarts-bar//Render")
			}
			err := bar.Render(writer)
			if err != nil {
				return evaldo.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 evaldo.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 evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "echarts-line//Global-options!")
			}
			line, ok := lineNat.Value.(*charts.Line)
			if !ok {
				return evaldo.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 evaldo.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 evaldo.MakeBuiltinError(ps, "block must contain native echarts-global-opts", "echarts-line//Global-options!")
					}
					gopt, ok := nat.Value.(charts.GlobalOpts)
					if !ok {
						return evaldo.MakeBuiltinError(ps, "block must contain echarts-global-opts natives", "echarts-line//Global-options!")
					}
					gopts = append(gopts, gopt)
				}
			default:
				return evaldo.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 evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "echarts-line//X-axis!")
			}
			line, ok := lineNat.Value.(*charts.Line)
			if !ok {
				return evaldo.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 evaldo.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 evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "echarts-line//Add-series")
			}
			line, ok := lineNat.Value.(*charts.Line)
			if !ok {
				return evaldo.MakeNativeArgError(ps, 1, []string{"echarts-line"}, "echarts-line//Add-series")
			}
			name, ok := arg1.(env.String)
			if !ok {
				return evaldo.MakeArgError(ps, 2, []env.Type{env.StringType}, "echarts-line//Add-series")
			}
			dataNat, ok := arg2.(env.Native)
			if !ok {
				return evaldo.MakeArgError(ps, 3, []env.Type{env.NativeType}, "echarts-line//Add-series")
			}
			data, ok := dataNat.Value.([]opts.LineData)
			if !ok {
				return evaldo.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 evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "echarts-line//Render")
			}
			line, ok := lineNat.Value.(*charts.Line)
			if !ok {
				return evaldo.MakeNativeArgError(ps, 1, []string{"echarts-line"}, "echarts-line//Render")
			}
			writerNat, ok := arg1.(env.Native)
			if !ok {
				return evaldo.MakeArgError(ps, 2, []env.Type{env.NativeType}, "echarts-line//Render")
			}
			writer, ok := writerNat.Value.(io.Writer)
			if !ok {
				return evaldo.MakeNativeArgError(ps, 2, []string{"io.Writer"}, "echarts-line//Render")
			}
			err := line.Render(writer)
			if err != nil {
				return evaldo.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 evaldo.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 evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "echarts-pie//Global-options!")
			}
			pie, ok := pieNat.Value.(*charts.Pie)
			if !ok {
				return evaldo.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 evaldo.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 evaldo.MakeBuiltinError(ps, "block must contain native echarts-global-opts", "echarts-pie//Global-options!")
					}
					gopt, ok := nat.Value.(charts.GlobalOpts)
					if !ok {
						return evaldo.MakeBuiltinError(ps, "block must contain echarts-global-opts natives", "echarts-pie//Global-options!")
					}
					gopts = append(gopts, gopt)
				}
			default:
				return evaldo.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 evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "echarts-pie//Add-series")
			}
			pie, ok := pieNat.Value.(*charts.Pie)
			if !ok {
				return evaldo.MakeNativeArgError(ps, 1, []string{"echarts-pie"}, "echarts-pie//Add-series")
			}
			dataNat, ok := arg1.(env.Native)
			if !ok {
				return evaldo.MakeArgError(ps, 2, []env.Type{env.NativeType}, "echarts-pie//Add-series")
			}
			data, ok := dataNat.Value.([]opts.PieData)
			if !ok {
				return evaldo.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 evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "echarts-pie//Render")
			}
			pie, ok := pieNat.Value.(*charts.Pie)
			if !ok {
				return evaldo.MakeNativeArgError(ps, 1, []string{"echarts-pie"}, "echarts-pie//Render")
			}
			writerNat, ok := arg1.(env.Native)
			if !ok {
				return evaldo.MakeArgError(ps, 2, []env.Type{env.NativeType}, "echarts-pie//Render")
			}
			writer, ok := writerNat.Value.(io.Writer)
			if !ok {
				return evaldo.MakeNativeArgError(ps, 2, []string{"io.Writer"}, "echarts-pie//Render")
			}
			err := pie.Render(writer)
			if err != nil {
				return evaldo.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 evaldo.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 evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "echarts-scatter//Global-options!")
			}
			scatter, ok := scatterNat.Value.(*charts.Scatter)
			if !ok {
				return evaldo.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 evaldo.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 evaldo.MakeBuiltinError(ps, "block must contain native echarts-global-opts", "echarts-scatter//Global-options!")
					}
					gopt, ok := nat.Value.(charts.GlobalOpts)
					if !ok {
						return evaldo.MakeBuiltinError(ps, "block must contain echarts-global-opts natives", "echarts-scatter//Global-options!")
					}
					gopts = append(gopts, gopt)
				}
			default:
				return evaldo.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 evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "echarts-scatter//X-axis!")
			}
			scatter, ok := scatterNat.Value.(*charts.Scatter)
			if !ok {
				return evaldo.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 evaldo.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 evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "echarts-scatter//Add-series")
			}
			scatter, ok := scatterNat.Value.(*charts.Scatter)
			if !ok {
				return evaldo.MakeNativeArgError(ps, 1, []string{"echarts-scatter"}, "echarts-scatter//Add-series")
			}
			name, ok := arg1.(env.String)
			if !ok {
				return evaldo.MakeArgError(ps, 2, []env.Type{env.StringType}, "echarts-scatter//Add-series")
			}
			dataNat, ok := arg2.(env.Native)
			if !ok {
				return evaldo.MakeArgError(ps, 3, []env.Type{env.NativeType}, "echarts-scatter//Add-series")
			}
			data, ok := dataNat.Value.([]opts.ScatterData)
			if !ok {
				return evaldo.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 evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "echarts-scatter//Render")
			}
			scatter, ok := scatterNat.Value.(*charts.Scatter)
			if !ok {
				return evaldo.MakeNativeArgError(ps, 1, []string{"echarts-scatter"}, "echarts-scatter//Render")
			}
			writerNat, ok := arg1.(env.Native)
			if !ok {
				return evaldo.MakeArgError(ps, 2, []env.Type{env.NativeType}, "echarts-scatter//Render")
			}
			writer, ok := writerNat.Value.(io.Writer)
			if !ok {
				return evaldo.MakeNativeArgError(ps, 2, []string{"io.Writer"}, "echarts-scatter//Render")
			}
			err := scatter.Render(writer)
			if err != nil {
				return evaldo.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 evaldo.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 evaldo.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 evaldo.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 evaldo.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_encoding = map[string]*env.Builtin{

	"decode\\hex-string": {
		Argsn: 1,
		Doc:   "Decodes a hexadecimal string to a UTF-8 string.",
		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 hexStr := arg0.(type) {
			case env.String:
				decoded, err := hex.DecodeString(hexStr.Value)
				if err != nil {
					ps.FailureFlag = true
					return evaldo.MakeBuiltinError(ps, "Failed to decode hex string: "+err.Error(), "decode\\hex-string")
				}
				return *env.NewString(string(decoded))
			default:
				ps.FailureFlag = true
				return evaldo.MakeArgError(ps, 1, []env.Type{env.StringType}, "decode\\hex-string")
			}
		},
	},

	"encode\\hex-string": {
		Argsn: 1,
		Doc:   "Encodes a string to its hexadecimal representation.",
		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 str := arg0.(type) {
			case env.String:
				encoded := hex.EncodeToString([]byte(str.Value))
				return *env.NewString(encoded)
			default:
				ps.FailureFlag = true
				return evaldo.MakeArgError(ps, 1, []env.Type{env.StringType}, "encode\\hex-string")
			}
		},
	},

	"clean\\hex-string": {
		Argsn: 1,
		Doc:   "Removes all whitespace from a hex string and ensures even length.",
		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 hexStr := arg0.(type) {
			case env.String:
				var sb strings.Builder
				for _, r := range hexStr.Value {
					if !unicode.IsSpace(r) {
						sb.WriteRune(r)
					}
				}

				result := sb.String()
				if len(result)%2 != 0 {
					result = result[:len(result)-1]
				}
				return *env.NewString(result)
			default:
				ps.FailureFlag = true
				return evaldo.MakeArgError(ps, 1, []env.Type{env.StringType}, "clean\\hex-string")
			}
		},
	},

	"charmap\\windows-1250": {
		Argsn: 0,
		Doc:   "Returns the Windows-1250 (CP1250) character encoding for Central European languages.",
		Pure:  true,
		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, charmap.Windows1250, "charmap-encoding")
		},
	},

	"charmap\\iso-8859-1": {
		Argsn: 0,
		Doc:   "Returns the ISO-8859-1 (Latin-1) character encoding.",
		Pure:  true,
		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, charmap.ISO8859_1, "charmap-encoding")
		},
	},

	"charmap\\iso-8859-2": {
		Argsn: 0,
		Doc:   "Returns the ISO-8859-2 (Latin-2) character encoding for Central European languages.",
		Pure:  true,
		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, charmap.ISO8859_2, "charmap-encoding")
		},
	},

	"charmap\\windows-1252": {
		Argsn: 0,
		Doc:   "Returns the Windows-1252 character encoding for Western European languages.",
		Pure:  true,
		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, charmap.Windows1252, "charmap-encoding")
		},
	},

	"charmap\\code-page-437": {
		Argsn: 0,
		Doc:   "Returns the Code Page 437 (DOS/IBM PC) character encoding.",
		Pure:  true,
		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, charmap.CodePage437, "charmap-encoding")
		},
	},

	"charmap\\code-page-850": {
		Argsn: 0,
		Doc:   "Returns the Code Page 850 (DOS Latin-1) character encoding.",
		Pure:  true,
		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, charmap.CodePage850, "charmap-encoding")
		},
	},

	"charmap\\koi8r": {
		Argsn: 0,
		Doc:   "Returns the KOI8-R character encoding for Russian.",
		Pure:  true,
		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, charmap.KOI8R, "charmap-encoding")
		},
	},

	"charmap-encoding//Decoder": {
		Argsn: 1,
		Doc:   "Creates a new text decoder for the given character encoding.",
		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 encoding := arg0.(type) {
			case env.Native:
				if ps.Idx.GetWord(encoding.GetKind()) != "charmap-encoding" {
					ps.FailureFlag = true
					return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "charmap-encoding\\new-decoder")
				}
				enc := encoding.Value.(*charmap.Charmap)
				decoder := enc.NewDecoder()
				return *env.NewNative(ps.Idx, decoder, "text-decoder")
			default:
				ps.FailureFlag = true
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "charmap-encoding\\new-decoder")
			}
		},
	},

	"charmap-encoding//Encoder": {
		Argsn: 1,
		Doc:   "Creates a new text encoder for the given character encoding.",
		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 encoding := arg0.(type) {
			case env.Native:
				if ps.Idx.GetWord(encoding.GetKind()) != "charmap-encoding" {
					ps.FailureFlag = true
					return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "charmap-encoding\\new-encoder")
				}
				enc := encoding.Value.(*charmap.Charmap)
				encoder := enc.NewEncoder()
				return *env.NewNative(ps.Idx, encoder, "text-encoder")
			default:
				ps.FailureFlag = true
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "charmap-encoding\\new-encoder")
			}
		},
	},

	"text-decoder//Decode": {
		Argsn: 2,
		Doc:   "Decodes a string using the given text decoder.",
		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 decoder := arg0.(type) {
			case env.Native:
				if ps.Idx.GetWord(decoder.GetKind()) != "text-decoder" {
					ps.FailureFlag = true
					return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "text-decoder\\string")
				}
				switch input := arg1.(type) {
				case env.String:
					dec := decoder.Value.(*encoding.Decoder)
					decoded, err := dec.String(input.Value)
					if err != nil {
						ps.FailureFlag = true
						return evaldo.MakeBuiltinError(ps, "Failed to decode string: "+err.Error(), "text-decoder\\string")
					}
					return *env.NewString(decoded)
				default:
					ps.FailureFlag = true
					return evaldo.MakeArgError(ps, 2, []env.Type{env.StringType}, "text-decoder\\string")
				}
			default:
				ps.FailureFlag = true
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "text-decoder\\string")
			}
		},
	},

	"text-encoder//Encode": {
		Argsn: 2,
		Doc:   "Encodes a string using the given text encoder.",
		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 encoder := arg0.(type) {
			case env.Native:
				if ps.Idx.GetWord(encoder.GetKind()) != "text-encoder" {
					ps.FailureFlag = true
					return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "text-encoder\\string")
				}
				switch input := arg1.(type) {
				case env.String:
					enc := encoder.Value.(*encoding.Encoder)
					encoded, err := enc.String(input.Value)
					if err != nil {
						ps.FailureFlag = true
						return evaldo.MakeBuiltinError(ps, "Failed to encode string: "+err.Error(), "text-encoder\\string")
					}
					return *env.NewString(encoded)
				default:
					ps.FailureFlag = true
					return evaldo.MakeArgError(ps, 2, []env.Type{env.StringType}, "text-encoder\\string")
				}
			default:
				ps.FailureFlag = true
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "text-encoder\\string")
			}
		},
	},

	"is-space": {
		Argsn: 1,
		Doc:   "Checks if a single character string is a whitespace character.",
		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 str := arg0.(type) {
			case env.String:
				if len(str.Value) == 0 {
					return *env.NewBoolean(false)
				}

				for _, r := range str.Value {
					return *env.NewBoolean(unicode.IsSpace(r))
				}
				return *env.NewBoolean(false)
			default:
				ps.FailureFlag = true
				return evaldo.MakeArgError(ps, 1, []env.Type{env.StringType}, "is-space")
			}
		},
	},

	"remove-all-space": {
		Argsn: 1,
		Doc:   "Removes all whitespace characters from a string.",
		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 str := arg0.(type) {
			case env.String:
				var sb strings.Builder
				for _, r := range str.Value {
					if !unicode.IsSpace(r) {
						sb.WriteRune(r)
					}
				}
				return *env.NewString(sb.String())
			default:
				ps.FailureFlag = true
				return evaldo.MakeArgError(ps, 1, []env.Type{env.StringType}, "remove-all-space")
			}
		},
	},
}
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 evaldo.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
				evaldo.Rye0_EvalBlockInj(ps, nil, false)
				ps.Dialect = dialect
				ps.Ser = ser
				return ps.Res
			default:
				return evaldo.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
				evaldo.Rye00_EvalBlockInj(ps, nil, false)
				ps.Dialect = dialect
				ps.Ser = ser
				return ps.Res
			default:
				return evaldo.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 evaldo.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 evaldo.MakeArgError(ps, 2, []env.Type{env.BlockType}, "eyr\\loop")
				}
			default:
				return evaldo.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)))
				evaldo.CompileRyeToEyr(&bloc, ps, eBlock)
				return *eBlock
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.BlockType}, "eyr")
			}
		},
	},
}
View Source
var Builtins_flui = map[string]*env.Builtin{
	"select": {
		Argsn: 1,
		Doc:   "Interactively displays a selection interface for Block, Dict, Table, List, or TableRow. Returns the selected item. Ctrl+C cancels and returns a failure.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			term.SaveCurPos()
			var obj env.Object
			var esc bool
			switch val := arg0.(type) {
			case env.Block:
				obj, esc = term.DisplayBlock(val, ps.Idx)
			case *env.Block:
				obj, esc = term.DisplayBlock(*val, ps.Idx)
			case env.Dict:
				obj, esc = term.DisplayDict(val, ps.Idx)
			case *env.Dict:
				obj, esc = term.DisplayDict(*val, ps.Idx)
			case env.List:

				bloc := env.NewBlock(*env.NewTSeries(make([]env.Object, len(val.Data))))
				for i, item := range val.Data {
					bloc.Series.S[i] = env.ToRyeValue(item)
				}
				obj, esc = term.DisplayBlock(*bloc, ps.Idx)
			case *env.List:

				bloc := env.NewBlock(*env.NewTSeries(make([]env.Object, len(val.Data))))
				for i, item := range val.Data {
					bloc.Series.S[i] = env.ToRyeValue(item)
				}
				obj, esc = term.DisplayBlock(*bloc, ps.Idx)
			case env.Table:
				obj, esc = term.DisplayTable(val, ps.Idx)
			case *env.Table:
				obj, esc = term.DisplayTable(*val, ps.Idx)
			case env.TableRow:
				obj, esc = term.DisplayTableRow(val, ps.Idx)
			case *env.TableRow:
				obj, esc = term.DisplayTableRow(*val, ps.Idx)
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.BlockType, env.DictType, env.ListType, env.TableType}, "select")
			}
			if esc {
				ps.FailureFlag = true
				return env.NewError("canceled by user")
			}
			return obj
		},
	},
	"input": {
		Argsn: 1,
		Doc:   "Interactively displays an input field. Takes the max input width, returns the entered string. Ctrl+C cancels and returns a failure.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {

			term.SaveCurPos()
			switch width := arg0.(type) {
			case env.Integer:
				obj, esc := term.DisplayInputField(0, int(width.Value))
				if esc {
					ps.FailureFlag = true
					return env.NewError("canceled by user")
				}
				return obj
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.IntegerType}, "input")
			}
		},
	},
	"input\\integer": {
		Argsn: 1,
		Doc:   "Interactive date input in format YYYY-MM-DD. Use arrow keys to navigate between year/month/day fields and increment/decrement values, or type digits. Returns date string. Ctrl+C cancels and returns a failure.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			term.SaveCurPos()
			switch initialDate := arg0.(type) {
			case env.String:
				obj, esc := term.DisplayIntInput(initialDate.Value, 0)
				if esc {
					ps.FailureFlag = true
					return env.NewError("canceled by user")
				}
				return obj
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.StringType}, "input\\integer")
			}
		},
	},
	"datepicker": {
		Argsn: 1,
		Doc:   "Interactive date input in format YYYY-MM-DD. Use arrow keys to navigate between year/month/day fields and increment/decrement values, or type digits. Returns date string. Ctrl+C cancels and returns a failure.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			term.SaveCurPos()
			switch initialDate := arg0.(type) {
			case env.String:
				obj, esc := term.DisplayDateInput(initialDate.Value, 0)
				if esc {
					ps.FailureFlag = true
					return env.NewError("canceled by user")
				}
				return obj
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.StringType}, "datepicker")
			}
		},
	},
	"selectbox": {
		Argsn: 1,
		Doc:   "Interactive date input in format YYYY-MM-DD. Use arrow keys to navigate between year/month/day fields and increment/decrement values, or type digits. Returns date string. Ctrl+C cancels and returns a failure.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			term.SaveCurPos()
			switch options := arg0.(type) {
			case env.Block:
				obj, esc := term.DisplaySelection(options, ps.Idx, 0)
				if esc {
					ps.FailureFlag = true
					return env.NewError("canceled by user")
				}
				return obj
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.StringType}, "datepicker")
			}
		},
	},
	"textarea": {
		Argsn: 2,
		Doc:   "Interactive multiline text input. Takes width and height (number of lines). Use arrow keys to navigate, Enter for new line, Ctrl+D to submit. Returns string with newlines. Ctrl+C cancels.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			term.SaveCurPos()
			switch width := arg0.(type) {
			case env.Integer:
				switch height := arg1.(type) {
				case env.Integer:
					obj, esc := term.DisplayTextArea(int(width.Value), int(height.Value), "")
					if esc {
						ps.FailureFlag = true
						return env.NewError("canceled by user")
					}
					return obj
				default:
					return evaldo.MakeArgError(ps, 2, []env.Type{env.IntegerType}, "textarea")
				}
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.IntegerType}, "textarea")
			}
		},
	},
	"textarea\\": {
		Argsn: 3,
		Doc:   "Interactive multiline text input with initial text. Takes width, height (number of lines), and initial text string. Use arrow keys to navigate, Enter for new line, Ctrl+D to submit. Returns string with newlines. Ctrl+C cancels.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			term.SaveCurPos()
			switch width := arg1.(type) {
			case env.Integer:
				switch height := arg2.(type) {
				case env.Integer:
					switch text := arg0.(type) {
					case env.String:
						obj, esc := term.DisplayTextArea(int(width.Value), int(height.Value), text.Value)
						if esc {
							ps.FailureFlag = true
							return env.NewError("canceled by user")
						}
						return obj
					default:
						return evaldo.MakeArgError(ps, 3, []env.Type{env.StringType}, "textarea\\")
					}
				default:
					return evaldo.MakeArgError(ps, 2, []env.Type{env.IntegerType}, "textarea\\")
				}
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.IntegerType}, "textarea\\")
			}
		},
	},
	"displayx": {
		Argsn: 1,
		Doc:   "Returns a special !!! prefixed JSON representation of a Block for Flutter UI rendering. The JSON format is [\"block\", [[\"type\", \"value\"], ...]]. Used for interactive display in Flutter clients.",
		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.Block:
				return blockToDisplayJSON(val, ps.Idx)
			case *env.Block:
				return blockToDisplayJSON(*val, ps.Idx)
			case env.List:

				bloc := env.NewBlock(*env.NewTSeries(make([]env.Object, len(val.Data))))
				for i, item := range val.Data {
					bloc.Series.S[i] = env.ToRyeValue(item)
				}
				return blockToDisplayJSON(*bloc, ps.Idx)
			case *env.List:

				bloc := env.NewBlock(*env.NewTSeries(make([]env.Object, len(val.Data))))
				for i, item := range val.Data {
					bloc.Series.S[i] = env.ToRyeValue(item)
				}
				return blockToDisplayJSON(*bloc, ps.Idx)
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.BlockType, env.ListType}, "displayx")
			}
		},
	},
}
View Source
var Builtins_flui_v2 = map[string]*env.Builtin{

	"select": {
		Argsn: 1,
		Doc:   "Interactively displays a selection interface. Returns the selected item. Ctrl+C cancels.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			items, ok := extractItems(arg0, ps.Idx)
			if !ok {
				return evaldo.MakeArgError(ps, 1, []env.Type{env.BlockType, env.DictType, env.ListType, env.TableType}, "select")
			}

			_, height, termErr := goterm.GetSize(int(os.Stdout.Fd()))
			if termErr != nil {
				height = 20
			}
			pageSize := height - 4

			term.SaveCurPos()

			var widget term.Widget
			if len(items) <= pageSize {
				widget = term.NewSelectWidget(items, ps.Idx)
			} else {
				widget = term.NewPaginatedSelectWidget(items, pageSize, ps.Idx)
			}

			result, canceled := term.RunWidget(widget)
			if canceled {
				ps.FailureFlag = true
				return env.NewError("canceled by user")
			}
			return result
		},
	},

	"input": {
		Argsn: 1,
		Doc:   "Interactively displays an input field. Takes max width, returns entered string. Ctrl+C cancels.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch width := arg0.(type) {
			case env.Integer:
				term.SaveCurPos()
				widget := term.NewInputWidget(int(width.Value), ps.Idx)
				result, canceled := term.RunWidget(widget)
				if canceled {
					ps.FailureFlag = true
					return env.NewError("canceled by user")
				}
				return result
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.IntegerType}, "input")
			}
		},
	},

	"datepicker": {
		Argsn: 1,
		Doc:   "Interactive date input. Use arrow keys to navigate/change values, or type digits. Ctrl+C cancels.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch initialDate := arg0.(type) {
			case env.String:
				term.SaveCurPos()
				widget := term.NewDateWidget(initialDate.Value, ps.Idx)
				result, canceled := term.RunWidget(widget)
				if canceled {
					ps.FailureFlag = true
					return env.NewError("canceled by user")
				}
				return result
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.StringType}, "datepicker")
			}
		},
	},

	"textarea": {
		Argsn: 2,
		Doc:   "Interactive multiline text input. Takes width and height. Ctrl+D to submit, Ctrl+C cancels.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch width := arg0.(type) {
			case env.Integer:
				switch height := arg1.(type) {
				case env.Integer:
					term.SaveCurPos()
					widget := term.NewTextAreaWidget(int(width.Value), int(height.Value), "", ps.Idx)
					result, canceled := term.RunWidget(widget)
					if canceled {
						ps.FailureFlag = true
						return env.NewError("canceled by user")
					}
					return result
				default:
					return evaldo.MakeArgError(ps, 2, []env.Type{env.IntegerType}, "textarea")
				}
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.IntegerType}, "textarea")
			}
		},
	},

	"textarea\\": {
		Argsn: 3,
		Doc:   "Interactive multiline text input with initial text. Ctrl+D to submit, Ctrl+C cancels.",
		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:
				switch width := arg1.(type) {
				case env.Integer:
					switch height := arg2.(type) {
					case env.Integer:
						term.SaveCurPos()
						widget := term.NewTextAreaWidget(int(width.Value), int(height.Value), text.Value, ps.Idx)
						result, canceled := term.RunWidget(widget)
						if canceled {
							ps.FailureFlag = true
							return env.NewError("canceled by user")
						}
						return result
					default:
						return evaldo.MakeArgError(ps, 3, []env.Type{env.IntegerType}, "textarea\\")
					}
				default:
					return evaldo.MakeArgError(ps, 2, []env.Type{env.IntegerType}, "textarea\\")
				}
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.StringType}, "textarea\\")
			}
		},
	},

	"displayx": {
		Argsn: 1,
		Doc:   "Returns a !!! prefixed JSON representation for Flutter UI rendering.",
		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.Block:
				return blockToDisplayJSON(val, ps.Idx)
			case *env.Block:
				return blockToDisplayJSON(*val, ps.Idx)
			case env.List:
				return blockToDisplayJSON(*listToBlock(val), ps.Idx)
			case *env.List:
				return blockToDisplayJSON(*listToBlock(*val), ps.Idx)
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.BlockType, env.ListType}, "displayx")
			}
		},
	},
}
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 evaldo.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)
							}
						}()
						evaldo.CallFunction_CollectArgs(handler, &psTemp, arg, false, nil)
					}()

					return arg0
				default:
					ps.FailureFlag = true
					return evaldo.MakeArgError(ps, 2, []env.Type{env.FunctionType}, "go-with")
				}
			default:
				ps.FailureFlag = true
				return evaldo.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 evaldo.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)
						}
					}()
					evaldo.CallFunction_CollectArgs(handler, &psTemp, nil, false, nil)
				}()

				return arg0
			default:
				ps.FailureFlag = true
				return evaldo.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 evaldo.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 evaldo.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 evaldo.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) (result env.Object) {

			defer func() {
				if r := recover(); r != nil {
					ps.FailureFlag = true
					result = *env.NewError("send on closed channel")
				}
			}()
			switch chn := arg0.(type) {
			case env.Native:
				chn.Value.(chan *env.Object) <- &arg1
				return arg0
			default:
				ps.FailureFlag = true
				return evaldo.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 evaldo.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 {
			mtx := &RyeMutex{}
			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.(*RyeMutex).Lock()
				return arg0
			default:
				ps.FailureFlag = true
				return evaldo.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:
				err := mtx.Value.(*RyeMutex).Unlock()
				if err != nil {
					ps.FailureFlag = true
					return *env.NewError(err.Error())
				}
				return arg0
			default:
				ps.FailureFlag = true
				return evaldo.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 evaldo.MakeArgError(ps, 2, []env.Type{env.IntegerType}, "Rye-waitgroup//Add")
				}
			default:
				ps.FailureFlag = true
				return evaldo.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 evaldo.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 evaldo.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() {
					evaldo.EvalExpression_CollectArg(ps, false, false)
					defaultFn, ok := ps.Res.(env.Function)

					if ok {
						if hasDeafult {
							ps.FailureFlag = true
							return evaldo.MakeBuiltinError(ps, "select can only have one default case", "select\\fn")
						}
						if defaultFn.Argsn != 0 {
							ps.FailureFlag = true
							return evaldo.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 evaldo.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 evaldo.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)})

					evaldo.EvalExpression_CollectArg(ps, false, false)
					fn, ok := ps.Res.(env.Function)
					if !ok {
						ps.FailureFlag = true
						return evaldo.MakeBuiltinError(ps, "second argument of a case must be a function", "select\\fn")
					}
					if fn.Argsn > 1 {
						ps.FailureFlag = true
						return evaldo.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 evaldo.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 evaldo.MakeBuiltinError(ps, "value from channel is not an object", "select\\fn")
					}
					arg = *val
				}
				if fn.Argsn == 0 {
					arg = nil
				}
				evaldo.CallFunction_CollectArgs(fn, &psTemp, arg, false, nil)
				return psTemp.Res

			default:
				ps.FailureFlag = true
				return evaldo.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() {
					evaldo.EvalExpression_CollectArg(ps, false, false)

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

						evaldo.EvalExpression_CollectArg(ps, false, false)
						fn, ok := ps.Res.(env.Block)
						if !ok {
							ps.FailureFlag = true
							return evaldo.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 evaldo.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),
						})
						evaldo.EvalExpression_CollectArg(ps, false, false)
						fn, ok := ps.Res.(env.Block)
						if !ok {
							ps.FailureFlag = true
							return evaldo.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 evaldo.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 evaldo.MakeBuiltinError(ps, "value from channel is not an object", "select")
					}
					arg = *val
				}

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

				if psTemp.ErrorFlag {
					return psTemp.Res
				}

			default:
				ps.FailureFlag = true
				return evaldo.MakeArgError(ps, 1, []env.Type{env.BlockType}, "select")
			}
			return arg0
		},
	},
}
View Source
var Builtins_gpio = map[string]*env.Builtin{}
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 evaldo.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 evaldo.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 evaldo.MakeArgError(ps, 1, []env.Type{env.StringType}, "html->markdown")
			}
			mkd, err := htmltomarkdown.ConvertString(text.Value)
			if err != nil {
				return evaldo.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 evaldo.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 evaldo.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 evaldo.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 evaldo.MakeBuiltinError(ps, "Attribute '"+attrName+"' not found.", "rye-html-start//Attr?")
					default:
						return evaldo.MakeArgError(ps, 2, []env.Type{env.IntegerType, env.WordType, env.StringType}, "rye-html-start//Attr?")
					}
				default:
					return evaldo.MakeBuiltinError(ps, "Token value is not matching.", "rye-html-start//Attr?")
				}
			default:
				return evaldo.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 evaldo.MakeBuiltinError(ps, "Token value is not matching.", "rye-html-start//Attrs?")
				}
			default:
				return evaldo.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 evaldo.MakeBuiltinError(ps, "Not xml-start element.", "rye-html-start//Name?")
				}
			default:
				return evaldo.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 evaldo.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 evaldo.MakeError(ps, err.Error())
				}
				return arg0
			default:
				ps.FailureFlag = true
				return evaldo.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())

						}

						evaldo.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.CurriedCaller:

					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())
						}

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

						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 evaldo.MakeArgError(ps, 3, []env.Type{env.StringType, env.FunctionType, env.NativeType}, "Go-server//Handle")
				}
			default:
				ps.FailureFlag = true
				return evaldo.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 evaldo.MakeArgError(ps, 2, []env.Type{env.StringType}, "Go-server-response-writer//Write")
				}
			default:
				ps.FailureFlag = true
				return evaldo.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 evaldo.MakeArgError(ps, 2, []env.Type{env.StringType}, "Go-server-response-writer//Set-content-type")
				}
			default:
				ps.FailureFlag = true
				return evaldo.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 evaldo.MakeArgError(ps, 3, []env.Type{env.StringType}, "Go-server-response-writer//Set-header")
					}
				default:
					ps.FailureFlag = true
					return evaldo.MakeArgError(ps, 2, []env.Type{env.WordType}, "Go-server-response-writer//Set-header")
				}
			default:
				ps.FailureFlag = true
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "Go-server-response-writer//Set-header")
			}
		},
	},

	"Go-server-response-writer//Add-header": {
		Argsn: 3,
		Doc:   "Adds a custom HTTP header value in the response, preserving existing values for multi-value headers.",
		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().Add(name_, value.Value)
						return arg0
					default:
						ps.FailureFlag = true
						return evaldo.MakeArgError(ps, 3, []env.Type{env.StringType}, "Go-server-response-writer//Add-header")
					}
				default:
					ps.FailureFlag = true
					return evaldo.MakeArgError(ps, 2, []env.Type{env.WordType}, "Go-server-response-writer//Add-header")
				}
			default:
				ps.FailureFlag = true
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "Go-server-response-writer//Add-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 evaldo.MakeArgError(ps, 2, []env.Type{env.IntegerType}, "Go-server-response-writer//Write-header")
				}
			default:
				ps.FailureFlag = true
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "Go-server-response-writer//Write-header")
			}
		},
	},

	"Go-server//Handle-ws": {
		Argsn: 3,
		Doc:   "Registers a WebSocket handler for a specific path pattern on the server, upgrading HTTP connections to WebSocket protocol.",
		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 {

							return
						}
						go func() {
							defer conn.Close()
							ps.FailureFlag = false
							ps.ErrorFlag = false
							ps.ReturnFlag = false
							psTemp := env.ProgramState{}
							err := copier.Copy(&psTemp, &ps)
							if err != nil {
								return
							}
							evaldo.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 evaldo.MakeArgError(ps, 3, []env.Type{env.FunctionType}, "Go-server//Handle-ws")
				}
			default:
				ps.FailureFlag = true
				return evaldo.MakeArgError(ps, 2, []env.Type{env.StringType}, "Go-server//Handle-ws")
			}
		},
	},

	"Go-server-websocket//Read": {
		Argsn: 1,
		Doc:   "Reads a message from a WebSocket connection, blocking until data is available or an error occurs.",
		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:
				msg, _, err := wsutil.ReadClientData(conn.Value.(io.ReadWriter))
				if err != nil {
					ps.ReturnFlag = true
					ps.FailureFlag = true
					ps.ErrorFlag = true
					return evaldo.MakeBuiltinError(ps, "Error in reading client data.", "Go-server-websocket//Read")
				}
				return env.NewString(string(msg))
			default:
				ps.FailureFlag = true
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "Go-server-websocket//Read")
			}
		},
	},

	"Go-server-websocket//Write": {
		Argsn: 2,
		Doc:   "Writes a message to a WebSocket connection, sending data to the connected client.",
		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 {
						ps.FailureFlag = true
						return evaldo.MakeBuiltinError(ps, "Failed to write server message.", "Go-server-websocket//Write")
					}
					return arg1
				default:
					ps.FailureFlag = true
					return evaldo.MakeArgError(ps, 2, []env.Type{env.StringType}, "Go-server-websocket//Write")
				}
			default:
				ps.FailureFlag = true
				return evaldo.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 evaldo.MakeBuiltinError(ps, "Key is missing.", "Go-server-request//query?")
					}

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

	"Go-server-request//Header?": {
		Argsn: 2,
		Doc:   "Gets a header value from the HTTP request by name.",
		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 name := arg1.(type) {
				case env.String:
					val := req.Value.(*http.Request).Header.Get(name.Value)
					return *env.NewString(val)
				default:
					ps.FailureFlag = true
					return evaldo.MakeArgError(ps, 2, []env.Type{env.StringType}, "Go-server-request//header?")
				}
			default:
				ps.FailureFlag = true
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "Go-server-request//header?")
			}
		},
	},

	"Go-server-request//Basic-auth?": {
		Argsn: 1,
		Doc:   "Gets HTTP Basic Authentication credentials from the request as [username password].",
		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:
				username, password, ok := req.Value.(*http.Request).BasicAuth()
				if !ok {
					ps.FailureFlag = true
					return evaldo.MakeBuiltinError(ps, "Basic auth credentials are missing.", "Go-server-request//basic-auth?")
				}
				pair := make([]env.Object, 2)
				pair[0] = *env.NewString(username)
				pair[1] = *env.NewString(password)
				return *env.NewBlock(*env.NewTSeries(pair))
			default:
				ps.FailureFlag = true
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "Go-server-request//basic-auth?")
			}
		},
	},

	"Go-server-request//Method?": {
		Argsn: 1,
		Doc:   "Gets the HTTP request method.",
		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:
				return *env.NewString(req.Value.(*http.Request).Method)
			default:
				ps.FailureFlag = true
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "Go-server-request//method?")
			}
		},
	},

	"Go-server-request//Read-body": {
		Argsn: 1,
		Doc:   "Reads the HTTP request 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 req := arg0.(type) {
			case env.Native:
				data, err := io.ReadAll(req.Value.(*http.Request).Body)
				if err != nil {
					ps.FailureFlag = true
					return evaldo.MakeBuiltinError(ps, err.Error(), "Go-server-request//read-body")
				}
				return *env.NewString(string(data))
			default:
				ps.FailureFlag = true
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "Go-server-request//read-body")
			}
		},
	},

	"Go-server-request//Headers?": {
		Argsn: 1,
		Doc:   "Gets all HTTP request headers 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 req := arg0.(type) {
			case env.Native:
				headers := make(map[string]any)
				for key, values := range req.Value.(*http.Request).Header {
					if len(values) == 0 {
						headers[key] = ""
					} else if len(values) == 1 {
						headers[key] = values[0]
					} else {
						vals := make([]env.Object, len(values))
						for i, v := range values {
							vals[i] = *env.NewString(v)
						}
						headers[key] = *env.NewBlock(*env.NewTSeries(vals))
					}
				}
				return *env.NewDict(headers)
			default:
				ps.FailureFlag = true
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "Go-server-request//headers?")
			}
		},
	},

	"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 evaldo.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 evaldo.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 evaldo.MakeBuiltinError(ps, "Cookie key is missing.", "Go-server-request//cookie-val?")
					}
					return *env.NewString(cookie.Value)
				default:
					ps.FailureFlag = true
					return evaldo.MakeArgError(ps, 2, []env.Type{env.StringType}, "Go-server-request//cookie-val?")
				}
			default:
				ps.FailureFlag = true
				return evaldo.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 evaldo.MakeError(ps, err.Error())
					}
					val := r.FormValue(key.Value)
					if len(val) < 1 {
						ps.FailureFlag = true
						return evaldo.MakeBuiltinError(ps, "Value is missing.", "Go-server-request//form?")
					}
					return *env.NewString(val)
				default:
					ps.FailureFlag = true
					return evaldo.MakeArgError(ps, 2, []env.Type{env.StringType}, "Go-server-request//form?")
				}
			default:
				ps.FailureFlag = true
				return evaldo.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 evaldo.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 evaldo.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 evaldo.MakeError(ps, err.Error())
				}
				return arg0
			default:
				ps.FailureFlag = true
				return evaldo.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 evaldo.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 evaldo.MakeArgError(ps, 2, []env.Type{env.StringType}, "Go-server-request//form-file?")
				}
			default:
				ps.FailureFlag = true
				return evaldo.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 evaldo.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 evaldo.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 evaldo.MakeBuiltinError(ps, errMsg, "Http-cookie-store//get")
						}

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

						ps.FailureFlag = true
						return evaldo.MakeArgError(ps, 3, []env.Type{env.StringType}, "Http-cookie-store//get")
					}
				default:

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

				ps.FailureFlag = true
				return evaldo.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 evaldo.MakeArgError(ps, 3, []env.Type{env.StringType, env.IntegerType}, "Http-session//set")
					}

				default:
					return evaldo.MakeArgError(ps, 2, []env.Type{env.StringType}, "Http-session//set")
				}
			default:
				return evaldo.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 evaldo.MakeBuiltinError(ps, "Unknown type.", "Http-session//get")
						}
					} else {
						ps.FailureFlag = true
						return evaldo.MakeBuiltinError(ps, "Value is empty.", "Http-session//get")
					}
				default:
					return evaldo.MakeArgError(ps, 2, []env.Type{env.StringType}, "Http-session//get")
				}
			default:
				return evaldo.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 evaldo.MakeBuiltinError(ps, errMsg, "Http-session//save")
						}
						return *env.NewInteger(1)
					default:
						return evaldo.MakeArgError(ps, 3, []env.Type{env.NativeType}, "Http-session//save")
					}
				default:
					return evaldo.MakeArgError(ps, 2, []env.Type{env.NativeType}, "Http-session//save")
				}
			default:
				return evaldo.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 evaldo.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 evaldo.MakeArgError(ps, 1, []env.Type{env.UriType}, "new-static-handler")
			}

		},
	},

	"Http-handler//Strip-prefix": {
		Argsn: 2,
		Doc:   "Wraps an HTTP handler to strip a URL prefix from requests, useful for serving static files from a subdirectory.",
		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 evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "Http-handler//Strip-prefix")
				}
			default:
				return evaldo.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 evaldo.MakeArgError(ps, 2, []env.Type{env.StringType}, "https-response//Header?")
				}
			default:
				ps.FailureFlag = true
				return evaldo.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 evaldo.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 evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "https-response//Status-text?")
			}
		},
	},
}
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 evaldo.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 evaldo.MakeError(ps, err.Error())
				}
				return *env.NewNative(ps.Idx, file, "file")
			default:
				return evaldo.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 evaldo.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 evaldo.MakeBuiltinError(ps, err.Error(), "__openFile")
				}
				return *env.NewNative(ps.Idx, file, "file")
			default:
				return evaldo.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 evaldo.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 evaldo.MakeBuiltinError(ps, err.Error(), "__create")
				}
				return *env.NewNative(ps.Idx, file, "file")
			default:
				ps.ReturnFlag = true
				ps.FailureFlag = true
				return evaldo.MakeArgError(ps, 1, []env.Type{env.UriType}, "__create")
			}
		},
	},

	"file-uri//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 evaldo.MakeArgError(ps, 1, []env.Type{env.UriType, env.StringType}, "Ext?")
			}
		},
	},

	"file-uri//Name?": {
		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 evaldo.MakeArgError(ps, 1, []env.Type{env.UriType}, "Name?")
			}
		},
	},

	"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 evaldo.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 evaldo.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 evaldo.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 evaldo.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 evaldo.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 evaldo.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 evaldo.MakeBuiltinError(ps, err.Error(), "file-uri//Delete")
				}
				return *env.NewBoolean(true)
			default:
				return evaldo.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 evaldo.MakeBuiltinError(ps, "Error opening file.", "file//Reader")
				}
				return *env.NewNative(ps.Idx, bufio.NewReader(file), "reader")
			default:
				ps.FailureFlag = true
				return evaldo.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 evaldo.MakeBuiltinError(ps, "Error opening file.", "file//Reader")
				}
				return *env.NewNative(ps.Idx, bufio.NewWriter(file), "writer")
			default:
				ps.FailureFlag = true
				return evaldo.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 evaldo.MakeBuiltinError(ps, "Error opening file.", "file-uri//Reader")
				}
				return *env.NewNative(ps.Idx, bufio.NewReader(file), "reader")
			default:
				ps.FailureFlag = true
				return evaldo.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 evaldo.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 evaldo.MakeBuiltinError(ps, "Not Reader", "__read\\string")
				}
				buf := new(strings.Builder)
				_, err := io.Copy(buf, reader)
				if err != nil {
					ps.FailureFlag = true
					return evaldo.MakeBuiltinError(ps, err.Error(), "__read\\string")
				}
				return *env.NewString(buf.String())
			default:
				ps.FailureFlag = true
				return evaldo.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 evaldo.MakeBuiltinError(ps, err.Error(), "reader//Close")
					}
					return *env.NewString("")
				}

				return *env.NewString("")
			default:
				ps.FailureFlag = true
				return evaldo.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 evaldo.MakeBuiltinError(ps, err.Error(), "__copy")
					}
					return arg0
				default:
					ps.FailureFlag = true
					return evaldo.MakeArgError(ps, 2, []env.Type{env.NativeType}, "__copy")
				}
			default:
				ps.FailureFlag = true
				return evaldo.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 evaldo.MakeBuiltinError(ps, err.Error(), "__copy")
					}
					return arg0
				default:
					ps.FailureFlag = true
					return evaldo.MakeArgError(ps, 2, []env.Type{env.NativeType}, "__copy")
				}
			default:
				ps.FailureFlag = true
				return evaldo.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 evaldo.MakeBuiltinError(ps, err.Error(), "file//Stat")
				}
				return *env.NewNative(ps.Idx, info, "file-info")
			default:
				ps.FailureFlag = true
				return evaldo.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 evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "file-info//Size?")
			}
		},
	},

	"file//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 s := arg0.(type) {
			case env.Native:
				data, err := io.ReadAll(s.Value.(io.Reader))
				if err != nil {
					ps.FailureFlag = true
					return evaldo.MakeBuiltinError(ps, "Error reading file.", "Read")
				}
				return *env.NewString(string(data))
			default:
				ps.FailureFlag = true
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "Read")
			}
		},
	},

	"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 evaldo.MakeBuiltinError(ps, "Native not io.Reader", "file//Seek\\end")
				}
				reader.Seek(0, os.SEEK_END)
				return arg0
			default:
				ps.FailureFlag = true
				return evaldo.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 evaldo.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 evaldo.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 evaldo.MakeBuiltinError(ps, err.Error(), "file//Write")
					}
					return arg0
				default:
					ps.FailureFlag = true
					return evaldo.MakeArgError(ps, 2, []env.Type{env.StringType}, "file//Write")
				}
			default:
				ps.FailureFlag = true
				return evaldo.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 evaldo.MakeBuiltinError(ps, err.Error(), "__close")
				}
				return *env.NewString("")
			default:
				ps.FailureFlag = true
				return evaldo.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 evaldo.MakeBuiltinError(ps, err.Error(), "file-uri//Read")
				}
				return *env.NewString(string(data))
			default:
				return evaldo.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 evaldo.MakeBuiltinError(ps, err.Error(), "__fs_read_bytes")
				}
				return *env.NewBytes(data)
			default:
				return evaldo.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 evaldo.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 evaldo.MakeBuiltinError(ps, err.Error(), "file-uri//Read\\lines")
				}
				return *env.NewBlock(*env.NewTSeries(lines))
			default:
				return evaldo.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 evaldo.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 evaldo.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 evaldo.MakeBuiltinError(ps, err.Error(), "__fs_write")
					}
					return arg1
				default:
					return evaldo.MakeArgError(ps, 2, []env.Type{env.StringType, env.NativeType}, "__fs_write")
				}
			default:
				ps.FailureFlag = true
				return evaldo.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 evaldo.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 evaldo.MakeBuiltinError(ps, fmt.Sprintf("Failed to write file: %v", err), "write-file")
					}
					return env.Integer{1}
				default:
					ps.FailureFlag = true
					return evaldo.MakeArgError(ps, 2, []env.Type{env.StringType}, "write-file")
				}
			default:
				ps.FailureFlag = true
				return evaldo.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.Bytes:
				switch bytes2 := arg1.(type) {
				case env.Bytes:
					combined := append(bytes1.Value, bytes2.Value...)
					return *env.NewBytes(combined)
				default:
					ps.FailureFlag = true
					return evaldo.MakeArgError(ps, 2, []env.Type{env.BytesType}, "append-bytes")
				}
			default:
				ps.FailureFlag = true
				return evaldo.MakeArgError(ps, 1, []env.Type{env.BytesType}, "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.(io.Writer)
					if !ok {
						return evaldo.MakeBuiltinError(ps, "Native not io.Writer", "writer//Write")
					}
				}
			}

			switch s := arg1.(type) {
			case env.String:
				switch ww := arg0.(type) {
				case env.Native:

					if bw, ok := ww.Value.(*bufio.Writer); ok {
						_, err := bw.WriteString(s.Value)
						if err != nil {
							return evaldo.MakeBuiltinError(ps, "Error at write: "+err.Error(), "writer//Write")
						}
						return arg0
					}

					if w, ok := ww.Value.(io.Writer); ok {
						_, err := io.WriteString(w, s.Value)
						if err != nil {
							return evaldo.MakeBuiltinError(ps, "Error at write: "+err.Error(), "writer//Write")
						}
						return arg0
					}
					return evaldo.MakeBuiltinError(ps, "Native not io.Writer", "writer//Write")
				default:
					ps.FailureFlag = true
					return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "writer//Write")
				}
			default:
				ps.FailureFlag = true
				return evaldo.MakeArgError(ps, 1, []env.Type{env.StringType}, "writer//Write")
			}
		},
	},

	"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 evaldo.MakeBuiltinError(ps, errMsg, "https-uri://Open")
				}
			default:
				ps.FailureFlag = true
				return evaldo.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 evaldo.MakeBuiltinError(ps, errMsg, "https-uri//Get")
				}
			default:
				ps.FailureFlag = true
				return evaldo.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 evaldo.MakeBuiltinError(ps, "Wrong content type.", "https-uri//Post")
						}
					case env.String:

						tt = t.Value
					default:
						ps.FailureFlag = true
						return evaldo.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 evaldo.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 evaldo.MakeArgError(ps, 2, []env.Type{env.StringType}, "https-uri//Post")
				}
			default:
				ps.FailureFlag = true
				return evaldo.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 evaldo.MakeBuiltinError(ps, errMsg, "http-uri//Get")
				}
			default:
				ps.FailureFlag = true
				return evaldo.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 evaldo.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 evaldo.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 evaldo.MakeArgError(ps, 2, []env.Type{env.StringType}, "http-uri//Post")
					}
				default:
					ps.FailureFlag = true
					return evaldo.MakeArgError(ps, 3, []env.Type{env.WordType}, "http-uri//Post")
				}
			default:
				ps.FailureFlag = true
				return evaldo.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 evaldo.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 evaldo.MakeBuiltinError(ps, err.Error(), "https-uri//Request")
						}
						return *env.NewNative(ps.Idx, req, "https-request")
					default:
						ps.FailureFlag = true
						return evaldo.MakeArgError(ps, 3, []env.Type{env.StringType}, "https-uri//Request")
					}
				default:
					ps.FailureFlag = true
					return evaldo.MakeArgError(ps, 2, []env.Type{env.WordType}, "https-uri//Request")
				}
			default:
				ps.FailureFlag = true
				return evaldo.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 evaldo.MakeArgError(ps, 3, []env.Type{env.StringType}, "https-request//Header!")
					}
				default:
					return evaldo.MakeArgError(ps, 2, []env.Type{env.WordType}, "https-request//Header!")
				}
			default:
				return evaldo.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 evaldo.MakeArgError(ps, 3, []env.Type{env.StringType}, "https-request//Basic-auth!")
					}
				default:
					return evaldo.MakeArgError(ps, 2, []env.Type{env.StringType}, "https-request//Basic-auth!")
				}
			default:
				return evaldo.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 evaldo.MakeBuiltinError(ps, err.Error(), "https-request//Call")
				}

				return *env.NewNative(ps.Idx, resp, "https-response")
			default:
				return evaldo.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 evaldo.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 evaldo.MakeBuiltinError(ps, err.Error(), "https-response//Read-body")
				}
				return *env.NewString(string(data))
			default:
				ps.FailureFlag = true
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "https-response//Read-body")
			}
		},
	},

	"https-response//Close-body!": {
		Argsn: 1,
		Doc:   "Closes the HTTPS response body to free network resources.",
		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:
				err := resp.Value.(*http.Response).Body.Close()
				if err != nil {
					ps.FailureFlag = true
					return evaldo.MakeBuiltinError(ps, err.Error(), "https-response//Close-body!")
				}
				return *env.NewString("")
			default:
				ps.FailureFlag = true
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "https-response//Close-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 evaldo.MakeArgError(ps, 2, []env.Type{env.StringType}, "email//Send")
				}
			default:
				ps.FailureFlag = true
				return evaldo.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 evaldo.MakeBuiltinError(ps, "Error connecting to FTP server: "+err.Error(), "ftp-uri//Open")
				}

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

	"ftp-connection//Close": {
		Argsn: 1,
		Doc:   "Closes 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:
				if ps.Idx.GetWord(s.Kind.Index) != "ftp-connection" {
					return evaldo.MakeBuiltinError(ps, "Expected FTP connection.", "ftp-connection//Close")
				}
				conn, ok := s.Value.(*ftp.ServerConn)
				if !ok {
					return evaldo.MakeBuiltinError(ps, "Invalid FTP connection.", "ftp-connection//Close")
				}
				err := conn.Quit()
				if err != nil {
					return evaldo.MakeBuiltinError(ps, fmt.Sprintf("Error closing FTP connection: %v", err.Error()), "ftp-connection//Close")
				}
				return *env.NewInteger(1)
			default:
				ps.FailureFlag = true
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "ftp-connection//Close")
			}
		},
	},

	"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 evaldo.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 evaldo.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 evaldo.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 evaldo.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 evaldo.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 evaldo.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 evaldo.MakeBuiltinError(ps, "Expected tail-file object", "tail-file//Close")
				}

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

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

	"unix-uri//Open": {
		Argsn: 1,
		Doc:   "Opens a connection to a Unix domain socket.",
		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 := net.Dial("unix", s.Path)
				if err != nil {
					ps.FailureFlag = true
					return evaldo.MakeBuiltinError(ps, "Error connecting to Unix socket: "+err.Error(), "unix-uri//Open")
				}
				return *env.NewNative(ps.Idx, conn, "unix-connection")
			default:
				ps.FailureFlag = true
				return evaldo.MakeArgError(ps, 1, []env.Type{env.UriType}, "unix-uri//Open")
			}
		},
	},

	"unix-connection//Write": {
		Argsn: 2,
		Doc:   "Writes data to a Unix domain socket connection.",
		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:
				if ps.Idx.GetWord(conn.GetKind()) != "unix-connection" {
					ps.FailureFlag = true
					return evaldo.MakeBuiltinError(ps, "Expected unix-connection object", "unix-connection//Write")
				}
				switch data := arg1.(type) {
				case env.String:
					_, err := conn.Value.(net.Conn).Write([]byte(data.Value))
					if err != nil {
						ps.FailureFlag = true
						return evaldo.MakeBuiltinError(ps, "Error writing to Unix socket: "+err.Error(), "unix-connection//Write")
					}
					return arg0
				default:
					ps.FailureFlag = true
					return evaldo.MakeArgError(ps, 2, []env.Type{env.StringType}, "unix-connection//Write")
				}
			default:
				ps.FailureFlag = true
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "unix-connection//Write")
			}
		},
	},

	"unix-connection//Read": {
		Argsn: 1,
		Doc:   "Reads data from a Unix domain socket connection.",
		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:
				if ps.Idx.GetWord(conn.GetKind()) != "unix-connection" {
					ps.FailureFlag = true
					return evaldo.MakeBuiltinError(ps, "Expected unix-connection object", "unix-connection//Read")
				}
				buf := make([]byte, 1024)
				n, err := conn.Value.(net.Conn).Read(buf)
				if err != nil {
					ps.FailureFlag = true
					return evaldo.MakeBuiltinError(ps, "Error reading from Unix socket: "+err.Error(), "unix-connection//Read")
				}
				return *env.NewString(string(buf[:n]))
			default:
				ps.FailureFlag = true
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "unix-connection//Read")
			}
		},
	},

	"unix-connection//Close": {
		Argsn: 1,
		Doc:   "Closes a Unix domain socket connection.",
		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:
				if ps.Idx.GetWord(conn.GetKind()) != "unix-connection" {
					ps.FailureFlag = true
					return evaldo.MakeBuiltinError(ps, "Expected unix-connection object", "unix-connection//Close")
				}
				err := conn.Value.(net.Conn).Close()
				if err != nil {
					ps.FailureFlag = true
					return evaldo.MakeBuiltinError(ps, err.Error(), "unix-connection//Close")
				}
				return *env.NewString("")
			default:
				ps.FailureFlag = true
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "unix-connection//Close")
			}
		},
	},
}
View Source
var Builtins_js_interop = map[string]*env.Builtin{}

JavaScript interop functions for Rye WASM

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 evaldo.MakeBuiltinError(ps, "Failed to Unmarshal.", "_parse_json")

				}
				return env.ToRyeValue(m)
			default:
				return evaldo.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 evaldo.MakeBuiltinError(ps, "Failed to Unmarshal.", "_parse_json\\lines")
					}
					vals = append(vals, env.ToRyeValue(m))
				}
				return *env.NewList(vals)
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.StringType}, "_parse_json\\lines")
			}
		},
	},

	"to-json": {
		Argsn: 1,
		Doc:   "Converts a Rye value to a JSON string. Supports block (like list) and context (like dict).",
		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(RyeToJSONWithIdxs(arg0, ps.Idx))
		},
	},

	"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 evaldo.MakeBuiltinError(ps, err.Error(), "reader//parse-email")
				}
				return *env.NewNative(ps.Idx, email, "parsed-email")
			default:
				return evaldo.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 *evaldo.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 evaldo.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 evaldo.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 evaldo.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 evaldo.MakeArgError(ps, 1, []env.Type{env.StringType}, "markdown->html")
			}

			html, err := markdown_to_html(ps, text.Value)
			if err != nil {
				return evaldo.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 evaldo.MakeArgError(ps, 1, []env.Type{env.StringType, env.MarkdownType}, "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 evaldo.MakeArgError(ps, 1, []env.Type{env.MarkdownType}, "text")
			}
			return *env.NewString(md.Value)
		},
	},

	"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 evaldo.MakeArgError(ps, 1, []env.Type{env.MarkdownType}, "to-html")
			}

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

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

	"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 evaldo.MakeArgError(ps, 1, []env.Type{env.MarkdownType}, "headings")
			}

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

	"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 evaldo.MakeArgError(ps, 1, []env.Type{env.MarkdownType}, "paragraphs")
			}

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

	"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 evaldo.MakeArgError(ps, 1, []env.Type{env.MarkdownType}, "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 evaldo.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 evaldo.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 evaldo.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
						evaldo.EvalBlockInj(ps, value, true)
						ps.Ser = ser
						return ps.Res
					}

					ps.FailureFlag = oldFailureFlag
					_ = matchResult
				}

				ps.FailureFlag = true
				return evaldo.MakeBuiltinError(ps, "No pattern matched the value", "match")
			default:
				return evaldo.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 evaldo.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 evaldo.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 evaldo.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 evaldo.MakeArgError(ps, 2, []env.Type{env.IntegerType, env.DecimalType, env.ComplexType}, "pow")
				}
			default:
				return evaldo.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 evaldo.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 evaldo.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 evaldo.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 evaldo.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 evaldo.MakeBuiltinError(ps, "Can't compute logarithm of zero.", "log")
				}
				return *env.NewComplex(cmplx.Log(val.Value))
			case env.Vector:
				data := make(govector.Vector, len(val.Value))
				for i, v := range val.Value {
					data[i] = math.Log(v)
				}
				return *env.NewVector(data)
			case env.Matrix:
				data := make([]float64, len(val.Data))
				for i, v := range val.Data {
					data[i] = math.Log(v)
				}
				return *env.NewMatrixWithData(val.Rows, val.Cols, data)
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.IntegerType, env.DecimalType, env.ComplexType, env.VectorType, env.MatrixType}, "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 evaldo.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 evaldo.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 evaldo.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 evaldo.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 evaldo.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 evaldo.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))
			case env.Vector:
				data := make(govector.Vector, len(val.Value))
				for i, v := range val.Value {
					data[i] = math.Sqrt(v)
				}
				return *env.NewVector(data)
			case env.Matrix:
				data := make([]float64, len(val.Data))
				for i, v := range val.Data {
					data[i] = math.Sqrt(v)
				}
				return *env.NewMatrixWithData(val.Rows, val.Cols, data)
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.IntegerType, env.DecimalType, env.ComplexType, env.VectorType, env.MatrixType}, "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))
			case env.Vector:
				data := make(govector.Vector, len(val.Value))
				for i, v := range val.Value {
					data[i] = math.Abs(v)
				}
				return *env.NewVector(data)
			case env.Matrix:
				data := make([]float64, len(val.Data))
				for i, v := range val.Data {
					data[i] = math.Abs(v)
				}
				return *env.NewMatrixWithData(val.Rows, val.Cols, data)
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.IntegerType, env.DecimalType, env.ComplexType, env.VectorType, env.MatrixType}, "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 evaldo.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 evaldo.MakeBuiltinError(ps, "Invalid input: Acos is only defined for -1 <= x <= 1.", "acos")
				}
				return *env.NewDecimal(math.Acos(val.Value))
			default:
				return evaldo.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 evaldo.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 evaldo.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 evaldo.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 evaldo.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 evaldo.MakeBuiltinError(ps, "Invalid input: Asin is only defined for -1 <= x <= 1.", "asin")
				}
				return *env.NewDecimal(math.Asin(val.Value))
			default:
				return evaldo.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 evaldo.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 evaldo.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 evaldo.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 evaldo.MakeArgError(ps, 2, []env.Type{env.IntegerType, env.DecimalType}, "atan2")
				}
			default:
				return evaldo.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 evaldo.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 evaldo.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 evaldo.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 evaldo.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 evaldo.MakeArgError(ps, 2, []env.Type{env.IntegerType, env.DecimalType}, "copysign")
				}
			default:
				return evaldo.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 evaldo.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 evaldo.MakeArgError(ps, 2, []env.Type{env.IntegerType, env.DecimalType}, "dim")
				}
			default:
				return evaldo.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 evaldo.MakeArgError(ps, 2, []env.Type{env.IntegerType, env.DecimalType}, "round\\to")
				}
			default:
				return evaldo.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 evaldo.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 evaldo.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 evaldo.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 evaldo.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 evaldo.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 evaldo.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))
			case env.Vector:
				data := make(govector.Vector, len(val.Value))
				for i, v := range val.Value {
					data[i] = math.Exp(v)
				}
				return *env.NewVector(data)
			case env.Matrix:
				data := make([]float64, len(val.Data))
				for i, v := range val.Data {
					data[i] = math.Exp(v)
				}
				return *env.NewMatrixWithData(val.Rows, val.Cols, data)
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.IntegerType, env.DecimalType, env.ComplexType, env.VectorType, env.MatrixType}, "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 evaldo.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 evaldo.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 evaldo.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 evaldo.MakeArgError(ps, 3, []env.Type{env.IntegerType, env.DecimalType}, "fma")
					}
				default:
					return evaldo.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 evaldo.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 evaldo.MakeArgError(ps, 3, []env.Type{env.IntegerType, env.DecimalType}, "fma")
					}
				default:
					return evaldo.MakeArgError(ps, 2, []env.Type{env.IntegerType, env.DecimalType}, "fma")
				}
			default:
				return evaldo.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 evaldo.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 evaldo.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 evaldo.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 evaldo.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 evaldo.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 evaldo.MakeArgError(ps, 2, []env.Type{env.IntegerType, env.DecimalType}, "yn")
				}
			default:
				return evaldo.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 evaldo.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 evaldo.MakeArgError(ps, 2, []env.Type{env.IntegerType, env.DecimalType}, "jn")
				}
			default:
				return evaldo.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 evaldo.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 evaldo.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 evaldo.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 evaldo.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 evaldo.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 evaldo.MakeArgError(ps, 2, []env.Type{env.IntegerType}, "gcd")
				}
			default:
				return evaldo.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 evaldo.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 evaldo.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 evaldo.MakeArgError(ps, 2, []env.Type{env.BlockType}, "outer-product")
				}
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.BlockType}, "outer-product")
			}
		},
	},
}
View Source
var Builtins_matrix = map[string]*env.Builtin{

	"matrix\\zeros": {
		Argsn: 2,
		Doc:   "Creates a new matrix with the given dimensions, initialized to zeros.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch rows := arg0.(type) {
			case env.Integer:
				switch cols := arg1.(type) {
				case env.Integer:
					if rows.Value <= 0 || cols.Value <= 0 {
						return evaldo.MakeBuiltinError(ps, "Matrix dimensions must be positive", "matrix")
					}
					return *env.NewMatrix(int(rows.Value), int(cols.Value))
				default:
					return evaldo.MakeArgError(ps, 2, []env.Type{env.IntegerType}, "matrix")
				}
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.IntegerType}, "matrix")
			}
		},
	},

	"matrix": {
		Argsn: 2,
		Doc:   "Creates a matrix from a shape block and a data block.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch shape := arg0.(type) {
			case env.Block:
				if shape.Series.Len() != 2 {
					return evaldo.MakeBuiltinError(ps, "Shape must be { rows cols }", "matrix")
				}
				rowsObj := shape.Series.Get(0)
				colsObj := shape.Series.Get(1)
				rowsInt, ok1 := rowsObj.(env.Integer)
				colsInt, ok2 := colsObj.(env.Integer)
				if !ok1 || !ok2 {
					return evaldo.MakeBuiltinError(ps, "Shape must contain integers", "matrix")
				}
				rows := int(rowsInt.Value)
				cols := int(colsInt.Value)

				switch data := arg1.(type) {
				case env.Block:
					if data.Series.Len() != rows*cols {
						return evaldo.MakeBuiltinError(ps, "Data length must match rows*cols", "matrix")
					}
					floats := make([]float64, rows*cols)
					for i := 0; i < data.Series.Len(); i++ {
						switch v := data.Series.Get(i).(type) {
						case env.Decimal:
							floats[i] = v.Value
						case env.Integer:
							floats[i] = float64(v.Value)
						default:
							return evaldo.MakeBuiltinError(ps, "Data must contain numbers", "matrix")
						}
					}
					return *env.NewMatrixWithData(rows, cols, floats)
				default:
					return evaldo.MakeArgError(ps, 2, []env.Type{env.BlockType}, "matrix")
				}
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.BlockType}, "matrix")
			}
		},
	},

	"matrix\\randn": {
		Argsn: 2,
		Doc:   "Creates a matrix with random normal values (mean 0, std 1).",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch rows := arg0.(type) {
			case env.Integer:
				switch cols := arg1.(type) {
				case env.Integer:
					if rows.Value <= 0 || cols.Value <= 0 {
						return evaldo.MakeBuiltinError(ps, "Matrix dimensions must be positive", "matrix\\randn")
					}
					r := int(rows.Value)
					c := int(cols.Value)
					data := make([]float64, r*c)
					for i := range data {
						data[i] = rand.NormFloat64()
					}
					return *env.NewMatrixWithData(r, c, data)
				default:
					return evaldo.MakeArgError(ps, 2, []env.Type{env.IntegerType}, "matrix\\randn")
				}
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.IntegerType}, "matrix\\randn")
			}
		},
	},

	"matrix\\ones": {
		Argsn: 2,
		Doc:   "Creates a matrix filled with ones.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch rows := arg0.(type) {
			case env.Integer:
				switch cols := arg1.(type) {
				case env.Integer:
					if rows.Value <= 0 || cols.Value <= 0 {
						return evaldo.MakeBuiltinError(ps, "Matrix dimensions must be positive", "matrix\\ones")
					}
					r := int(rows.Value)
					c := int(cols.Value)
					data := make([]float64, r*c)
					for i := range data {
						data[i] = 1.0
					}
					return *env.NewMatrixWithData(r, c, data)
				default:
					return evaldo.MakeArgError(ps, 2, []env.Type{env.IntegerType}, "matrix\\ones")
				}
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.IntegerType}, "matrix\\ones")
			}
		},
	},

	"matrix\\eye": {
		Argsn: 1,
		Doc:   "Creates an identity matrix of size n×n.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch n := arg0.(type) {
			case env.Integer:
				if n.Value <= 0 {
					return evaldo.MakeBuiltinError(ps, "Matrix size must be positive", "matrix\\eye")
				}
				size := int(n.Value)
				data := make([]float64, size*size)
				for i := 0; i < size; i++ {
					data[i*size+i] = 1.0
				}
				return *env.NewMatrixWithData(size, size, data)
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.IntegerType}, "matrix\\eye")
			}
		},
	},

	"shape?": {
		Argsn: 1,
		Doc:   "Returns the shape of a matrix as { rows cols }.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch m := arg0.(type) {
			case env.Matrix:
				return *env.NewBlock(*env.NewTSeries([]env.Object{
					*env.NewInteger(int64(m.Rows)),
					*env.NewInteger(int64(m.Cols)),
				}))
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.MatrixType}, "shape?")
			}
		},
	},

	"rows?": {
		Argsn: 1,
		Doc:   "Returns the number of rows in a matrix.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch m := arg0.(type) {
			case env.Matrix:
				return *env.NewInteger(int64(m.Rows))
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.MatrixType}, "rows?")
			}
		},
	},

	"cols?": {
		Argsn: 1,
		Doc:   "Returns the number of columns in a matrix.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch m := arg0.(type) {
			case env.Matrix:
				return *env.NewInteger(int64(m.Cols))
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.MatrixType}, "cols?")
			}
		},
	},

	"mat-get": {
		Argsn: 3,
		Doc:   "Gets the element at the specified row and column (0-indexed).",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch m := arg0.(type) {
			case env.Matrix:
				switch row := arg1.(type) {
				case env.Integer:
					switch col := arg2.(type) {
					case env.Integer:
						r := int(row.Value)
						c := int(col.Value)
						if r < 0 || r >= m.Rows || c < 0 || c >= m.Cols {
							return evaldo.MakeBuiltinError(ps, fmt.Sprintf("Matrix indices out of bounds: row %d, col %d (matrix is %dx%d)", r, c, m.Rows, m.Cols), "mat-get")
						}
						return *env.NewDecimal(m.Get(r, c))
					default:
						return evaldo.MakeArgError(ps, 3, []env.Type{env.IntegerType}, "mat-get")
					}
				default:
					return evaldo.MakeArgError(ps, 2, []env.Type{env.IntegerType}, "mat-get")
				}
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.MatrixType}, "mat-get")
			}
		},
	},

	"mat-set!": {
		Argsn: 4,
		Doc:   "Sets the element at the specified row and column (0-indexed). Modifies matrix in place.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch m := arg0.(type) {
			case env.Matrix:
				switch row := arg1.(type) {
				case env.Integer:
					switch col := arg2.(type) {
					case env.Integer:
						r := int(row.Value)
						c := int(col.Value)
						if r < 0 || r >= m.Rows || c < 0 || c >= m.Cols {
							return evaldo.MakeBuiltinError(ps, fmt.Sprintf("Matrix indices out of bounds: row %d, col %d (matrix is %dx%d)", r, c, m.Rows, m.Cols), "mat-set!")
						}
						var val float64
						switch v := arg3.(type) {
						case env.Decimal:
							val = v.Value
						case env.Integer:
							val = float64(v.Value)
						default:
							return evaldo.MakeArgError(ps, 4, []env.Type{env.DecimalType, env.IntegerType}, "mat-set!")
						}
						m.Set(r, c, val)
						return m
					default:
						return evaldo.MakeArgError(ps, 3, []env.Type{env.IntegerType}, "mat-set!")
					}
				default:
					return evaldo.MakeArgError(ps, 2, []env.Type{env.IntegerType}, "mat-set!")
				}
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.MatrixType}, "mat-set!")
			}
		},
	},

	"mat-row": {
		Argsn: 2,
		Doc:   "Returns a row of the matrix as 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 m := arg0.(type) {
			case env.Matrix:
				switch row := arg1.(type) {
				case env.Integer:
					r := int(row.Value)
					if r < 0 || r >= m.Rows {
						return evaldo.MakeBuiltinError(ps, fmt.Sprintf("Row index %d out of bounds (matrix has %d rows)", r, m.Rows), "mat-row")
					}
					data := make(govector.Vector, m.Cols)
					for j := 0; j < m.Cols; j++ {
						data[j] = m.Get(r, j)
					}
					return *env.NewVector(data)
				default:
					return evaldo.MakeArgError(ps, 2, []env.Type{env.IntegerType}, "mat-row")
				}
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.MatrixType}, "mat-row")
			}
		},
	},

	"mat-col": {
		Argsn: 2,
		Doc:   "Returns a column of the matrix as 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 m := arg0.(type) {
			case env.Matrix:
				switch col := arg1.(type) {
				case env.Integer:
					c := int(col.Value)
					if c < 0 || c >= m.Cols {
						return evaldo.MakeBuiltinError(ps, fmt.Sprintf("Column index %d out of bounds (matrix has %d columns)", c, m.Cols), "mat-col")
					}
					data := make(govector.Vector, m.Rows)
					for i := 0; i < m.Rows; i++ {
						data[i] = m.Get(i, c)
					}
					return *env.NewVector(data)
				default:
					return evaldo.MakeArgError(ps, 2, []env.Type{env.IntegerType}, "mat-col")
				}
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.MatrixType}, "mat-col")
			}
		},
	},

	"mat-transpose": {
		Argsn: 1,
		Doc:   "Returns the transpose of a matrix.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch m := arg0.(type) {
			case env.Matrix:
				data := make([]float64, m.Rows*m.Cols)
				for i := 0; i < m.Rows; i++ {
					for j := 0; j < m.Cols; j++ {

						data[j*m.Rows+i] = m.Get(i, j)
					}
				}
				return *env.NewMatrixWithData(m.Cols, m.Rows, data)
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.MatrixType}, "mat-transpose")
			}
		},
	},

	"mat-mul": {
		Argsn: 2,
		Doc:   "Matrix multiplication. A (m×n) × B (n×p) = C (m×p).",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch A := arg0.(type) {
			case env.Matrix:
				switch B := arg1.(type) {
				case env.Matrix:
					if A.Cols != B.Rows {
						return evaldo.MakeBuiltinError(ps, "Matrix dimensions incompatible for multiplication", "mat-mul")
					}
					m, n, p := A.Rows, A.Cols, B.Cols
					data := make([]float64, m*p)
					for i := 0; i < m; i++ {
						for j := 0; j < p; j++ {
							var sum float64
							for k := 0; k < n; k++ {
								sum += A.Get(i, k) * B.Get(k, j)
							}
							data[i*p+j] = sum
						}
					}
					return *env.NewMatrixWithData(m, p, data)
				case env.Vector:

					if A.Cols != len(B.Value) {
						return evaldo.MakeBuiltinError(ps, "Matrix columns must match vector length", "mat-mul")
					}
					result := make(govector.Vector, A.Rows)
					for i := 0; i < A.Rows; i++ {
						var sum float64
						for j := 0; j < A.Cols; j++ {
							sum += A.Get(i, j) * B.Value[j]
						}
						result[i] = sum
					}
					return *env.NewVector(result)
				default:
					return evaldo.MakeArgError(ps, 2, []env.Type{env.MatrixType, env.VectorType}, "mat-mul")
				}
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.MatrixType}, "mat-mul")
			}
		},
	},

	"mat-hadamard": {
		Argsn: 2,
		Doc:   "Element-wise (Hadamard) multiplication of two matrices. In the future, could have a dedicated .* operator.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch A := arg0.(type) {
			case env.Matrix:
				switch B := arg1.(type) {
				case env.Matrix:
					if A.Rows != B.Rows || A.Cols != B.Cols {
						return evaldo.MakeBuiltinError(ps, "Matrix dimensions must match", "mat-hadamard")
					}
					data := make([]float64, len(A.Data))
					for i := range A.Data {
						data[i] = A.Data[i] * B.Data[i]
					}
					return *env.NewMatrixWithData(A.Rows, A.Cols, data)
				default:
					return evaldo.MakeArgError(ps, 2, []env.Type{env.MatrixType}, "mat-hadamard")
				}
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.MatrixType}, "mat-hadamard")
			}
		},
	},

	"mat-add": {
		Argsn: 2,
		Doc:   "Element-wise addition of two matrices. In the future, could have a dedicated .+ operator.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch A := arg0.(type) {
			case env.Matrix:
				switch B := arg1.(type) {
				case env.Matrix:
					if A.Rows != B.Rows || A.Cols != B.Cols {
						return evaldo.MakeBuiltinError(ps, "Matrix dimensions must match", "mat-add")
					}
					data := make([]float64, len(A.Data))
					for i := range A.Data {
						data[i] = A.Data[i] + B.Data[i]
					}
					return *env.NewMatrixWithData(A.Rows, A.Cols, data)
				default:
					return evaldo.MakeArgError(ps, 2, []env.Type{env.MatrixType}, "mat-add")
				}
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.MatrixType}, "mat-add")
			}
		},
	},

	"mat-sub": {
		Argsn: 2,
		Doc:   "Element-wise subtraction of two matrices. In the future, could have a dedicated .- operator.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch A := arg0.(type) {
			case env.Matrix:
				switch B := arg1.(type) {
				case env.Matrix:
					if A.Rows != B.Rows || A.Cols != B.Cols {
						return evaldo.MakeBuiltinError(ps, "Matrix dimensions must match", "mat-sub")
					}
					data := make([]float64, len(A.Data))
					for i := range A.Data {
						data[i] = A.Data[i] - B.Data[i]
					}
					return *env.NewMatrixWithData(A.Rows, A.Cols, data)
				default:
					return evaldo.MakeArgError(ps, 2, []env.Type{env.MatrixType}, "mat-sub")
				}
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.MatrixType}, "mat-sub")
			}
		},
	},

	"mat-scale": {
		Argsn: 2,
		Doc:   "Multiplies all elements of a matrix by a scalar.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch m := arg0.(type) {
			case env.Matrix:
				var scalar float64
				switch s := arg1.(type) {
				case env.Decimal:
					scalar = s.Value
				case env.Integer:
					scalar = float64(s.Value)
				default:
					return evaldo.MakeArgError(ps, 2, []env.Type{env.DecimalType, env.IntegerType}, "mat-scale")
				}
				data := make([]float64, len(m.Data))
				for i := range m.Data {
					data[i] = m.Data[i] * scalar
				}
				return *env.NewMatrixWithData(m.Rows, m.Cols, data)
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.MatrixType}, "mat-scale")
			}
		},
	},

	"mat-sum-rows": {
		Argsn: 1,
		Doc:   "Returns a vector containing the sum of each row.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch m := arg0.(type) {
			case env.Matrix:
				result := make(govector.Vector, m.Rows)
				for i := 0; i < m.Rows; i++ {
					var sum float64
					for j := 0; j < m.Cols; j++ {
						sum += m.Get(i, j)
					}
					result[i] = sum
				}
				return *env.NewVector(result)
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.MatrixType}, "mat-sum-rows")
			}
		},
	},

	"mat-sum-cols": {
		Argsn: 1,
		Doc:   "Returns a vector containing the sum of each column.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch m := arg0.(type) {
			case env.Matrix:
				result := make(govector.Vector, m.Cols)
				for j := 0; j < m.Cols; j++ {
					var sum float64
					for i := 0; i < m.Rows; i++ {
						sum += m.Get(i, j)
					}
					result[j] = sum
				}
				return *env.NewVector(result)
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.MatrixType}, "mat-sum-cols")
			}
		},
	},

	"mat-max-rows": {
		Argsn: 1,
		Doc:   "Returns a vector containing the maximum of each row.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch m := arg0.(type) {
			case env.Matrix:
				result := make(govector.Vector, m.Rows)
				for i := 0; i < m.Rows; i++ {
					maxVal := m.Get(i, 0)
					for j := 1; j < m.Cols; j++ {
						if v := m.Get(i, j); v > maxVal {
							maxVal = v
						}
					}
					result[i] = maxVal
				}
				return *env.NewVector(result)
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.MatrixType}, "mat-max-rows")
			}
		},
	},

	"mat-max-cols": {
		Argsn: 1,
		Doc:   "Returns a vector containing the maximum of each column.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch m := arg0.(type) {
			case env.Matrix:
				result := make(govector.Vector, m.Cols)
				for j := 0; j < m.Cols; j++ {
					maxVal := m.Get(0, j)
					for i := 1; i < m.Rows; i++ {
						if v := m.Get(i, j); v > maxVal {
							maxVal = v
						}
					}
					result[j] = maxVal
				}
				return *env.NewVector(result)
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.MatrixType}, "mat-max-cols")
			}
		},
	},

	"mat-to-block": {
		Argsn: 1,
		Doc:   "Converts a matrix to a block of blocks (each row is a block).",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch m := arg0.(type) {
			case env.Matrix:
				rows := make([]env.Object, m.Rows)
				for i := 0; i < m.Rows; i++ {
					row := make([]env.Object, m.Cols)
					for j := 0; j < m.Cols; j++ {
						row[j] = *env.NewDecimal(m.Get(i, j))
					}
					rows[i] = *env.NewBlock(*env.NewTSeries(row))
				}
				return *env.NewBlock(*env.NewTSeries(rows))
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.MatrixType}, "mat-to-block")
			}
		},
	},

	"block-to-mat": {
		Argsn: 1,
		Doc:   "Converts a block of blocks (rows) to a matrix.",
		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:
				if blk.Series.Len() == 0 {
					return evaldo.MakeBuiltinError(ps, "Block is empty", "block-to-mat")
				}

				firstRow, ok := blk.Series.Get(0).(env.Block)
				if !ok {
					return evaldo.MakeBuiltinError(ps, "Block must contain blocks (rows)", "block-to-mat")
				}
				rows := blk.Series.Len()
				cols := firstRow.Series.Len()
				data := make([]float64, rows*cols)

				for i := 0; i < rows; i++ {
					row, ok := blk.Series.Get(i).(env.Block)
					if !ok {
						return evaldo.MakeBuiltinError(ps, "Block must contain blocks (rows)", "block-to-mat")
					}
					if row.Series.Len() != cols {
						return evaldo.MakeBuiltinError(ps, "All rows must have the same length", "block-to-mat")
					}
					for j := 0; j < cols; j++ {
						switch v := row.Series.Get(j).(type) {
						case env.Decimal:
							data[i*cols+j] = v.Value
						case env.Integer:
							data[i*cols+j] = float64(v.Value)
						default:
							return evaldo.MakeBuiltinError(ps, "Rows must contain numbers", "block-to-mat")
						}
					}
				}
				return *env.NewMatrixWithData(rows, cols, data)
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.BlockType}, "block-to-mat")
			}
		},
	},

	"vector-to-mat": {
		Argsn: 2,
		Doc:   "Converts a vector to a matrix. Use 'row for 1×n or 'col for n×1.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch v := arg0.(type) {
			case env.Vector:
				switch orient := arg1.(type) {
				case env.Word:
					word := ps.Idx.GetWord(orient.Index)
					n := len(v.Value)
					data := make([]float64, n)
					copy(data, v.Value)
					if word == "row" {
						return *env.NewMatrixWithData(1, n, data)
					} else if word == "col" {
						return *env.NewMatrixWithData(n, 1, data)
					}
					return evaldo.MakeBuiltinError(ps, "Orientation must be 'row or 'col", "vector-to-mat")
				default:
					return evaldo.MakeArgError(ps, 2, []env.Type{env.WordType}, "vector-to-mat")
				}
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.VectorType}, "vector-to-mat")
			}
		},
	},

	"mat-slice": {
		Argsn: 3,
		Doc:   "Extracts a sub-matrix. Row and column ranges are { start end } (inclusive, 0-indexed).",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch m := arg0.(type) {
			case env.Matrix:
				switch rowRange := arg1.(type) {
				case env.Block:
					if rowRange.Series.Len() != 2 {
						return evaldo.MakeBuiltinError(ps, "Row range must be { start end }", "mat-slice")
					}
					switch colRange := arg2.(type) {
					case env.Block:
						if colRange.Series.Len() != 2 {
							return evaldo.MakeBuiltinError(ps, "Column range must be { start end }", "mat-slice")
						}
						r0, ok1 := rowRange.Series.Get(0).(env.Integer)
						r1, ok2 := rowRange.Series.Get(1).(env.Integer)
						c0, ok3 := colRange.Series.Get(0).(env.Integer)
						c1, ok4 := colRange.Series.Get(1).(env.Integer)
						if !ok1 || !ok2 || !ok3 || !ok4 {
							return evaldo.MakeBuiltinError(ps, "Ranges must contain integers", "mat-slice")
						}
						rowStart, rowEnd := int(r0.Value), int(r1.Value)
						colStart, colEnd := int(c0.Value), int(c1.Value)
						if rowStart < 0 || rowEnd >= m.Rows || rowStart > rowEnd {
							return evaldo.MakeBuiltinError(ps, "Invalid row range", "mat-slice")
						}
						if colStart < 0 || colEnd >= m.Cols || colStart > colEnd {
							return evaldo.MakeBuiltinError(ps, "Invalid column range", "mat-slice")
						}
						newRows := rowEnd - rowStart + 1
						newCols := colEnd - colStart + 1
						data := make([]float64, newRows*newCols)
						for i := 0; i < newRows; i++ {
							for j := 0; j < newCols; j++ {
								data[i*newCols+j] = m.Get(rowStart+i, colStart+j)
							}
						}
						return *env.NewMatrixWithData(newRows, newCols, data)
					default:
						return evaldo.MakeArgError(ps, 3, []env.Type{env.BlockType}, "mat-slice")
					}
				default:
					return evaldo.MakeArgError(ps, 2, []env.Type{env.BlockType}, "mat-slice")
				}
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.MatrixType}, "mat-slice")
			}
		},
	},

	"mat-softmax": {
		Argsn: 1,
		Doc:   "Applies softmax to each column of the matrix. Returns a new matrix.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch m := arg0.(type) {
			case env.Matrix:
				data := make([]float64, m.Rows*m.Cols)
				for j := 0; j < m.Cols; j++ {

					maxVal := m.Get(0, j)
					for i := 1; i < m.Rows; i++ {
						if v := m.Get(i, j); v > maxVal {
							maxVal = v
						}
					}

					sum := 0.0
					for i := 0; i < m.Rows; i++ {
						exp := math.Exp(m.Get(i, j) - maxVal)
						data[i*m.Cols+j] = exp
						sum += exp
					}

					for i := 0; i < m.Rows; i++ {
						data[i*m.Cols+j] /= sum
					}
				}
				return *env.NewMatrixWithData(m.Rows, m.Cols, data)
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.MatrixType}, "mat-softmax")
			}
		},
	},

	"mat-set-col!": {
		Argsn: 3,
		Doc:   "Sets a column of the matrix from a vector or block. Mutates in place.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch m := arg0.(type) {
			case env.Matrix:
				switch col := arg1.(type) {
				case env.Integer:
					c := int(col.Value)
					if c < 0 || c >= m.Cols {
						return evaldo.MakeBuiltinError(ps, fmt.Sprintf("Column index %d out of bounds (matrix has %d columns)", c, m.Cols), "mat-set-col!")
					}
					switch vals := arg2.(type) {
					case env.Vector:
						if len(vals.Value) != m.Rows {
							return evaldo.MakeBuiltinError(ps, "Vector length must match matrix rows", "mat-set-col!")
						}
						for i := 0; i < m.Rows; i++ {
							m.Set(i, c, vals.Value[i])
						}
						return m
					case env.Block:
						if vals.Series.Len() != m.Rows {
							return evaldo.MakeBuiltinError(ps, "Block length must match matrix rows", "mat-set-col!")
						}
						for i := 0; i < m.Rows; i++ {
							switch v := vals.Series.Get(i).(type) {
							case env.Decimal:
								m.Set(i, c, v.Value)
							case env.Integer:
								m.Set(i, c, float64(v.Value))
							default:
								return evaldo.MakeBuiltinError(ps, "Block must contain numbers", "mat-set-col!")
							}
						}
						return m
					default:
						return evaldo.MakeArgError(ps, 3, []env.Type{env.VectorType, env.BlockType}, "mat-set-col!")
					}
				default:
					return evaldo.MakeArgError(ps, 2, []env.Type{env.IntegerType}, "mat-set-col!")
				}
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.MatrixType}, "mat-set-col!")
			}
		},
	},

	"vec-add": {
		Argsn: 2,
		Doc:   "Adds two vectors element-wise. Returns a new vector.",
		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:
					if len(v1.Value) != len(v2.Value) {
						return evaldo.MakeBuiltinError(ps, "Vectors must have same length", "vec-add")
					}
					data := make(govector.Vector, len(v1.Value))
					for i := range v1.Value {
						data[i] = v1.Value[i] + v2.Value[i]
					}
					return *env.NewVector(data)
				default:
					return evaldo.MakeArgError(ps, 2, []env.Type{env.VectorType}, "vec-add")
				}
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.VectorType}, "vec-add")
			}
		},
	},

	"vec-sub": {
		Argsn: 2,
		Doc:   "Subtracts two vectors element-wise (v1 - v2). Returns a new vector.",
		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:
					if len(v1.Value) != len(v2.Value) {
						return evaldo.MakeBuiltinError(ps, "Vectors must have same length", "vec-sub")
					}
					data := make(govector.Vector, len(v1.Value))
					for i := range v1.Value {
						data[i] = v1.Value[i] - v2.Value[i]
					}
					return *env.NewVector(data)
				default:
					return evaldo.MakeArgError(ps, 2, []env.Type{env.VectorType}, "vec-sub")
				}
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.VectorType}, "vec-sub")
			}
		},
	},

	"vec-to-block": {
		Argsn: 1,
		Doc:   "Converts a vector to a block of decimal values.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch v := arg0.(type) {
			case env.Vector:
				items := make([]env.Object, len(v.Value))
				for i, val := range v.Value {
					items[i] = *env.NewDecimal(val)
				}
				return *env.NewBlock(*env.NewTSeries(items))
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.VectorType}, "vec-to-block")
			}
		},
	},
}
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 evaldo.MakeArgError(ps, 2, []env.Type{env.StringType}, "mcp-server//create")
				}
			default:
				ps.FailureFlag = true
				return evaldo.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 evaldo.MakeArgError(ps, 3, []env.Type{env.StringType}, "mcp-resource//create")
					}
				default:
					ps.FailureFlag = true
					return evaldo.MakeArgError(ps, 2, []env.Type{env.StringType}, "mcp-resource//create")
				}
			default:
				ps.FailureFlag = true
				return evaldo.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 evaldo.MakeArgError(ps, 2, []env.Type{env.StringType}, "mcp-tool//create")
				}
			default:
				ps.FailureFlag = true
				return evaldo.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 evaldo.MakeArgError(ps, 2, []env.Type{env.StringType}, "mcp-prompt//create")
				}
			default:
				ps.FailureFlag = true
				return evaldo.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 evaldo.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 evaldo.MakeBuiltinError(ps, "Failed to cast to server info", "Rye-mcp-server//get-name")
				}

				return env.String{Value: serverInfo.Name}
			default:
				ps.FailureFlag = true
				return evaldo.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 evaldo.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 evaldo.MakeBuiltinError(ps, "Failed to cast to server info", "Rye-mcp-server//get-version")
				}

				return env.String{Value: serverInfo.Version}
			default:
				ps.FailureFlag = true
				return evaldo.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 evaldo.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 evaldo.MakeBuiltinError(ps, "Failed to cast to resource info", "Rye-mcp-resource//get-uri")
				}

				return env.String{Value: resourceInfo.URI}
			default:
				ps.FailureFlag = true
				return evaldo.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 evaldo.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 evaldo.MakeBuiltinError(ps, "Failed to cast to resource info", "Rye-mcp-resource//get-name")
				}

				return env.String{Value: resourceInfo.Name}
			default:
				ps.FailureFlag = true
				return evaldo.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 evaldo.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 evaldo.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 evaldo.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 evaldo.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 evaldo.MakeBuiltinError(ps, "Failed to cast to tool info", "Rye-mcp-tool//get-name")
				}

				return env.String{Value: toolInfo.Name}
			default:
				ps.FailureFlag = true
				return evaldo.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 evaldo.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 evaldo.MakeBuiltinError(ps, "Failed to cast to tool info", "Rye-mcp-tool//get-description")
				}

				return env.String{Value: toolInfo.Description}
			default:
				ps.FailureFlag = true
				return evaldo.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 evaldo.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 evaldo.MakeBuiltinError(ps, "Failed to cast to prompt info", "Rye-mcp-prompt//get-name")
				}

				return env.String{Value: promptInfo.Name}
			default:
				ps.FailureFlag = true
				return evaldo.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 evaldo.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 evaldo.MakeBuiltinError(ps, "Failed to cast to prompt info", "Rye-mcp-prompt//get-description")
				}

				return env.String{Value: promptInfo.Description}
			default:
				ps.FailureFlag = true
				return evaldo.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 evaldo.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 evaldo.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 evaldo.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 evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "mqtt-client//Disconnect")
			}
		},
	},

	"mqtt-client//Close": {
		Argsn: 1,
		Doc:   "Closes the MQTT client connection (alias for Disconnect).",
		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 ps.Idx.GetWord(client.Kind.Index) != "mqtt-client" {
					return evaldo.MakeBuiltinError(ps, "Expected MQTT client connection.", "mqtt-client//Close")
				}
				mqttClient := client.Value.(mqtt.Client)
				mqttClient.Disconnect(250)
				return *env.NewInteger(1)
			default:
				ps.FailureFlag = true
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "mqtt-client//Close")
			}
		},
	},

	"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 evaldo.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 evaldo.MakeBuiltinError(ps, fmt.Sprintf("Failed to publish message: %v", token.Error()), "mqtt-client//Publish")
								}

								return *env.NewInteger(1)
							default:
								ps.FailureFlag = true
								return evaldo.MakeArgError(ps, 5, []env.Type{env.IntegerType}, "mqtt-client//Publish")
							}
						default:
							ps.FailureFlag = true
							return evaldo.MakeArgError(ps, 4, []env.Type{env.IntegerType}, "mqtt-client//Publish")
						}
					default:
						ps.FailureFlag = true
						return evaldo.MakeArgError(ps, 3, []env.Type{env.StringType}, "mqtt-client//Publish")
					}
				default:
					ps.FailureFlag = true
					return evaldo.MakeArgError(ps, 2, []env.Type{env.StringType}, "mqtt-client//Publish")
				}
			default:
				ps.FailureFlag = true
				return evaldo.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 evaldo.MakeBuiltinError(ps, fmt.Sprintf("Failed to publish message: %v", token.Error()), "mqtt-client//Publish-simple")
						}

						return *env.NewInteger(1)
					default:
						ps.FailureFlag = true
						return evaldo.MakeArgError(ps, 3, []env.Type{env.StringType}, "mqtt-client//Publish-simple")
					}
				default:
					ps.FailureFlag = true
					return evaldo.MakeArgError(ps, 2, []env.Type{env.StringType}, "mqtt-client//Publish-simple")
				}
			default:
				ps.FailureFlag = true
				return evaldo.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 evaldo.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()))

								evaldo.CallFunctionArgs2(handler,
									&psCallback,
									*env.NewString(string(msg.Payload())),
									*env.NewDict(msgDict),
									nil)
								if psCallback.FailureFlag || psCallback.ErrorFlag {
									fmt.Println("********* CALLBACK ERROR MQTT")
								}
								evaldo.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 evaldo.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 evaldo.MakeArgError(ps, 4, []env.Type{env.FunctionType}, "mqtt-client//Subscribe")
						}
					default:
						ps.FailureFlag = true
						return evaldo.MakeArgError(ps, 3, []env.Type{env.IntegerType}, "mqtt-client//Subscribe")
					}
				default:
					ps.FailureFlag = true
					return evaldo.MakeArgError(ps, 2, []env.Type{env.StringType}, "mqtt-client//Subscribe")
				}
			default:
				ps.FailureFlag = true
				return evaldo.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())

							evaldo.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 evaldo.MakeBuiltinError(ps, fmt.Sprintf("Failed to subscribe: %v", token.Error()), "mqtt-client//Subscribe-simple")
						}

						return *env.NewInteger(1)
					default:
						ps.FailureFlag = true
						return evaldo.MakeArgError(ps, 3, []env.Type{env.FunctionType}, "mqtt-client//Subscribe-simple")
					}
				default:
					ps.FailureFlag = true
					return evaldo.MakeArgError(ps, 2, []env.Type{env.StringType}, "mqtt-client//Subscribe-simple")
				}
			default:
				ps.FailureFlag = true
				return evaldo.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 evaldo.MakeBuiltinError(ps, fmt.Sprintf("Failed to unsubscribe: %v", token.Error()), "mqtt-client//Unsubscribe")
					}

					return *env.NewInteger(1)
				default:
					ps.FailureFlag = true
					return evaldo.MakeArgError(ps, 2, []env.Type{env.StringType}, "mqtt-client//Unsubscribe")
				}
			default:
				ps.FailureFlag = true
				return evaldo.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 evaldo.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 evaldo.MakeArgError(ps, 2, []env.Type{env.StringType}, "mqtt-options//Set-broker")
				}
			default:
				ps.FailureFlag = true
				return evaldo.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 evaldo.MakeArgError(ps, 2, []env.Type{env.StringType}, "mqtt-options//Set-client-id")
				}
			default:
				ps.FailureFlag = true
				return evaldo.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 evaldo.MakeArgError(ps, 2, []env.Type{env.IntegerType}, "mqtt-options//Set-keep-alive")
				}
			default:
				ps.FailureFlag = true
				return evaldo.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 evaldo.MakeArgError(ps, 2, []env.Type{env.StringType}, "mqtt-options//Set-username")
				}
			default:
				ps.FailureFlag = true
				return evaldo.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 evaldo.MakeArgError(ps, 2, []env.Type{env.StringType}, "mqtt-options//Set-password")
				}
			default:
				ps.FailureFlag = true
				return evaldo.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 evaldo.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 evaldo.MakeArgError(ps, 5, []env.Type{env.IntegerType}, "mqtt-options//Set-will")
							}
						default:
							ps.FailureFlag = true
							return evaldo.MakeArgError(ps, 4, []env.Type{env.IntegerType}, "mqtt-options//Set-will")
						}
					default:
						ps.FailureFlag = true
						return evaldo.MakeArgError(ps, 3, []env.Type{env.StringType}, "mqtt-options//Set-will")
					}
				default:
					ps.FailureFlag = true
					return evaldo.MakeArgError(ps, 2, []env.Type{env.StringType}, "mqtt-options//Set-will")
				}
			default:
				ps.FailureFlag = true
				return evaldo.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 evaldo.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 evaldo.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 evaldo.MakeArgError(ps, 2, []env.Type{env.DictType}, "msg-dispatcher")
				}
			default:
				return evaldo.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 evaldo.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 evaldo.MakeBuiltinError(ps, "Handler must accept 2 arguments (message, state)", "Rye-msg-dispatcher//Register")
						}
						dispatcher.RegisterHandler(msgType.Value, handler)
						return arg0
					default:
						return evaldo.MakeArgError(ps, 3, []env.Type{env.FunctionType}, "Rye-msg-dispatcher//Register")
					}
				default:
					return evaldo.MakeArgError(ps, 2, []env.Type{env.StringType}, "Rye-msg-dispatcher//Register")
				}
			default:
				return evaldo.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 evaldo.MakeBuiltinError(ps, "Expected MessageDispatcher", "Rye-msg-dispatcher//Unregister")
				}

				switch msgType := arg1.(type) {
				case env.String:
					dispatcher.UnregisterHandler(msgType.Value)
					return arg0
				default:
					return evaldo.MakeArgError(ps, 2, []env.Type{env.StringType}, "Rye-msg-dispatcher//Unregister")
				}
			default:
				return evaldo.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 evaldo.MakeBuiltinError(ps, "Expected MessageDispatcher", "Rye-msg-dispatcher//Send")
				}

				err := dispatcher.Send(arg1)
				if err != nil {
					return evaldo.MakeBuiltinError(ps, fmt.Sprintf("Send failed: %v", err), "Rye-msg-dispatcher//Send")
				}
				return arg0
			default:
				return evaldo.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 evaldo.MakeBuiltinError(ps, "Expected MessageDispatcher", "Rye-msg-dispatcher//State")
				}
				return dispatcher.GetState()
			default:
				return evaldo.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 evaldo.MakeBuiltinError(ps, "Expected MessageDispatcher", "Rye-msg-dispatcher//Set-state")
				}

				switch newState := arg1.(type) {
				case env.Dict:
					dispatcher.SetState(newState)
					return arg0
				default:
					return evaldo.MakeArgError(ps, 2, []env.Type{env.DictType}, "Rye-msg-dispatcher//Set-state")
				}
			default:
				return evaldo.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 evaldo.MakeBuiltinError(ps, "Expected MessageDispatcher", "Rye-msg-dispatcher//Start")
				}

				var updateCallback env.Function
				switch cb := arg1.(type) {
				case env.Function:
					if cb.Argsn != 1 {
						return evaldo.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 evaldo.MakeArgError(ps, 2, []env.Type{env.FunctionType, env.VoidType}, "Rye-msg-dispatcher//Start")
				}

				dispatcher.Start(ps, updateCallback)
				return arg0
			default:
				return evaldo.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 evaldo.MakeBuiltinError(ps, "Expected MessageDispatcher", "Rye-msg-dispatcher//Stop")
				}
				dispatcher.Stop()
				return arg0
			default:
				return evaldo.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:
				db, err := sql.Open("mysql", str.Path)
				if err != nil {
					return evaldo.MakeBuiltinError(ps, fmt.Sprintf("Error opening MySQL: %v", err.Error()), "mysql-uri//Open")
				}

				if err := db.Ping(); err != nil {
					return evaldo.MakeBuiltinError(ps, fmt.Sprintf("Error connecting to MySQL: %v", err.Error()), "mysql-uri//Open")
				}
				return *env.NewNative(ps.Idx, db, "Rye-mysql")
			default:
				return evaldo.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)
					db, err := sql.Open("mysql", path)
					if err != nil {
						return evaldo.MakeBuiltinError(ps, fmt.Sprintf("Error opening MySQL: %v", err.Error()), "mysql-uri//Open\\pwd")
					}

					if err := db.Ping(); err != nil {
						return evaldo.MakeBuiltinError(ps, fmt.Sprintf("Error connecting to MySQL: %v", err.Error()), "mysql-uri//Open\\pwd")
					}
					return *env.NewNative(ps.Idx, db, "Rye-mysql")
				default:
					return evaldo.MakeArgError(ps, 2, []env.Type{env.StringType}, "mysql-uri//Open\\pwd")
				}
			default:
				return evaldo.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 evaldo.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 evaldo.MakeBuiltinError(ps, err.Error(), "Rye-mysql//Exec")
					} else {
						num, _ := res.RowsAffected()
						if num > 0 {
							return env.NewInteger(1)
						} else {
							ps.FailureFlag = true
							return evaldo.MakeBuiltinError(ps, "No rows affected.", "Rye-mysql//Exec")
						}
					}
				} else {
					return evaldo.MakeBuiltinError(ps, "SQL string is blank.", "Rye-mysql//Exec")
				}
			default:
				return evaldo.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 evaldo.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 evaldo.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 evaldo.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 evaldo.MakeBuiltinError(ps, "No data.", "Rye-mysql//Query")
						}
						return *spr

					}
				} else {
					return evaldo.MakeBuiltinError(ps, "Empty SQL.", "Rye-mysql//Query")
				}

			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "Rye-mysql//Query")
			}
		},
	},

	"Rye-mysql//Close": {
		Argsn: 1,
		Doc:   "Closes the MySQL database connection.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch db := arg0.(type) {
			case env.Native:
				mysqlKind, _ := ps.Idx.GetIndex("Rye-mysql")
				if db.Kind.Index != mysqlKind {
					return evaldo.MakeBuiltinError(ps, "Expected MySQL database connection.", "Rye-mysql//Close")
				}
				sqlDB, ok := db.Value.(*sql.DB)
				if !ok {
					return evaldo.MakeBuiltinError(ps, "Invalid database connection.", "Rye-mysql//Close")
				}
				err := sqlDB.Close()
				if err != nil {
					return evaldo.MakeBuiltinError(ps, fmt.Sprintf("Error closing database: %v", err.Error()), "Rye-mysql//Close")
				}
				return *env.NewInteger(1)
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "Rye-mysql//Close")
			}
		},
	},
}
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 evaldo.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 := resolvePath(ps.WorkingPath, path.GetPath())
				res := FileExists(filePath)
				if res == -1 {
					return evaldo.MakeBuiltinError(ps, "Error checking if path exists: "+filePath, "does-exists")
				}
				return *env.NewBoolean(res == 1)
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.UriType}, "does-exist")
			}
		},
	},

	"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 evaldo.MakeBuiltinError(ps, err.Error(), "cd")
				}
				return arg0
			default:
				return evaldo.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 evaldo.MakeBuiltinError(ps, "Environment variable not found: "+variable_name.Value, "env?")
				}
				return *env.NewString(val)
			default:
				return evaldo.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 := resolvePath(ps.WorkingPath, path.GetPath())

				err := os.Mkdir(newDir, 0755)
				if err != nil {
					return evaldo.MakeBuiltinError(ps, "Error creating directory: "+err.Error(), "mkdir")
				} else {
					return arg0
				}
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.UriType}, "mkdir")
			}
		},
	},

	"mktmp": {
		Argsn: 0,
		Doc:   "Removed: use mktemp instead.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return evaldo.MakeBuiltinError(ps, "This function was removed. Use mktemp.", "mktmp")
		},
	},

	"rm": {
		Argsn: 1,
		Doc:   "Removes a file or empty 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:
				filePath := resolvePath(ps.WorkingPath, path.GetPath())
				err := os.Remove(filePath)
				if err != nil {
					return evaldo.MakeBuiltinError(ps, "Error removing file: "+err.Error(), "rm")
				}
				return arg0
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.UriType}, "rm")
			}
		},
	},

	"rmdir": {
		Argsn: 1,
		Doc:   "Removes a directory and all its contents recursively.",
		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:
				dirPath := resolvePath(ps.WorkingPath, path.GetPath())
				err := os.RemoveAll(dirPath)
				if err != nil {
					return evaldo.MakeBuiltinError(ps, "Error removing directory: "+err.Error(), "rmdir")
				}
				return arg0
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.UriType}, "rmdir")
			}
		},
	},

	"cp": {
		Argsn: 2,
		Doc:   "Copies a file to a new location.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch src := arg0.(type) {
			case env.Uri:
				switch dst := arg1.(type) {
				case env.Uri:
					srcPath := resolvePath(ps.WorkingPath, src.GetPath())
					dstPath := resolvePath(ps.WorkingPath, dst.GetPath())

					data, err := os.ReadFile(srcPath)
					if err != nil {
						return evaldo.MakeBuiltinError(ps, "Error reading source file: "+err.Error(), "cp")
					}

					srcInfo, err := os.Stat(srcPath)
					if err != nil {
						return evaldo.MakeBuiltinError(ps, "Error getting source file info: "+err.Error(), "cp")
					}

					err = os.WriteFile(dstPath, data, srcInfo.Mode())
					if err != nil {
						return evaldo.MakeBuiltinError(ps, "Error writing destination file: "+err.Error(), "cp")
					}
					return arg1
				default:
					return evaldo.MakeArgError(ps, 2, []env.Type{env.UriType}, "cp")
				}
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.UriType}, "cp")
			}
		},
	},

	"file-info?": {
		Argsn: 1,
		Doc:   "Gets detailed information about 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:
				filePath := resolvePath(ps.WorkingPath, path.GetPath())
				info, err := os.Stat(filePath)
				if err != nil {
					return evaldo.MakeBuiltinError(ps, "Error getting file info: "+err.Error(), "file-info?")
				}
				r := env.NewDict(make(map[string]any, 5))
				r.Data["name"] = *env.NewString(info.Name())
				r.Data["size"] = *env.NewInteger(info.Size())
				r.Data["mode"] = *env.NewString(info.Mode().String())
				r.Data["mod-time"] = *env.NewDate(info.ModTime())
				r.Data["is-dir"] = *env.NewBoolean(info.IsDir())
				return *r
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.UriType}, "file-info?")
			}
		},
	},

	"is-dir": {
		Argsn: 1,
		Doc:   "Checks if a path is a directory. Fails if the path does not exist.",
		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 := resolvePath(ps.WorkingPath, path.GetPath())
				info, err := os.Stat(filePath)
				if err != nil {
					return evaldo.MakeBuiltinError(ps, "Error checking path: "+err.Error(), "is-dir")
				}
				return *env.NewBoolean(info.IsDir())
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.UriType}, "is-dir")
			}
		},
	},

	"is-file": {
		Argsn: 1,
		Doc:   "Checks if a path is a regular file (not a directory). Fails if the path does not exist.",
		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 := resolvePath(ps.WorkingPath, path.GetPath())
				info, err := os.Stat(filePath)
				if err != nil {
					return evaldo.MakeBuiltinError(ps, "Error checking path: "+err.Error(), "is-file")
				}
				return *env.NewBoolean(info.Mode().IsRegular())
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.UriType}, "is-file")
			}
		},
	},

	"home-dir?": {
		Argsn: 0,
		Doc:   "Gets the current user's home 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.UserHomeDir()
			if err != nil {
				return evaldo.MakeBuiltinError(ps, "Error getting home directory: "+err.Error(), "home-dir?")
			}
			return *env.NewUri1(ps.Idx, "file://"+dir)
		},
	},

	"tmp-dir?": {
		Argsn: 0,
		Doc:   "Gets the system's default 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 := os.TempDir()
			return *env.NewUri1(ps.Idx, "file://"+dir)
		},
	},

	"glob": {
		Argsn: 1,
		Doc:   "Returns files matching 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 pattern := arg0.(type) {
			case env.String:
				patternPath := resolvePath(ps.WorkingPath, pattern.Value)
				matches, err := filepath.Glob(patternPath)
				if err != nil {
					return evaldo.MakeBuiltinError(ps, "Error in glob pattern: "+err.Error(), "glob")
				}
				items := make([]env.Object, len(matches))
				for i, match := range matches {
					items[i] = *env.NewUri1(ps.Idx, "file://"+match)
				}
				return *env.NewBlock(*env.NewTSeries(items))
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.StringType}, "glob")
			}
		},
	},

	"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 src := arg0.(type) {
			case env.Uri:
				switch dst := arg1.(type) {
				case env.Uri:
					oldPath := resolvePath(ps.WorkingPath, src.GetPath())
					newPath := resolvePath(ps.WorkingPath, dst.GetPath())
					err := os.Rename(oldPath, newPath)
					if err != nil {
						return evaldo.MakeBuiltinError(ps, "Error moving file: "+err.Error(), "mv")
					}
					return arg1
				default:
					return evaldo.MakeArgError(ps, 2, []env.Type{env.UriType}, "mv")
				}
			default:
				return evaldo.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 evaldo.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 with absolute paths when possible. If argument is a file-uri, lists that directory (or returns failure if not a directory). Otherwise filters current directory: '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 {
			var targetDir string = "."
			var doFiltering bool = true
			var filterArg env.Object = arg0

			if uri, ok := arg0.(env.Uri); ok {
				targetPath := resolvePath(ps.WorkingPath, uri.GetPath())

				info, err := os.Stat(targetPath)
				if err != nil {
					if os.IsNotExist(err) {
						return evaldo.MakeBuiltinError(ps, fmt.Sprintf("path doesn't exist: %s", uri.GetPath()), "ls\\")
					}
					if os.IsPermission(err) {
						return evaldo.MakeBuiltinError(ps, fmt.Sprintf("permission denied: %s", uri.GetPath()), "ls\\")
					}
					return evaldo.MakeBuiltinError(ps, fmt.Sprintf("error accessing path %s: %s", uri.GetPath(), err.Error()), "ls\\")
				}

				if !info.IsDir() {
					return evaldo.MakeBuiltinError(ps, fmt.Sprintf("not a directory (is file): %s", uri.GetPath()), "ls\\")
				}

				targetDir = targetPath
				doFiltering = false
			}

			files, err := os.ReadDir(targetDir)
			if err != nil {
				return evaldo.MakeBuiltinError(ps, "Error reading directory:"+err.Error(), "ls\\")
			}

			var items []env.Object

			if !doFiltering {

				for _, file := range files {
					absPath, err := filepath.Abs(filepath.Join(targetDir, file.Name()))
					if err != nil {

						items = append(items, *env.NewUri1(ps.Idx, "file://"+file.Name()))
					} else {
						items = append(items, *env.NewUri1(ps.Idx, "file://"+absPath))
					}
				}
			} else {

				switch filterArg := filterArg.(type) {
				case env.Word:
					filter := ps.Idx.GetWord(filterArg.Index)
					if filter != "dirs" && filter != "files" {
						return evaldo.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 {
							absPath, err := filepath.Abs(filepath.Join(targetDir, file.Name()))
							if err != nil {

								items = append(items, *env.NewUri1(ps.Idx, "file://"+file.Name()))
							} else {
								items = append(items, *env.NewUri1(ps.Idx, "file://"+absPath))
							}
						}
					}

				case env.String:

					pattern := filterArg.Value
					for _, file := range files {
						if strings.Contains(file.Name(), pattern) {
							absPath, err := filepath.Abs(filepath.Join(targetDir, file.Name()))
							if err != nil {

								items = append(items, *env.NewUri1(ps.Idx, "file://"+file.Name()))
							} else {
								items = append(items, *env.NewUri1(ps.Idx, "file://"+absPath))
							}
						}
					}

				case env.Native:

					if ps.Idx.GetWord(filterArg.Kind.Index) != "regexp" {
						return evaldo.MakeBuiltinError(ps, "Native object must be a regexp", "ls\\")
					}

					regex := filterArg.Value.(*regexp.Regexp)
					for _, file := range files {
						if regex.MatchString(file.Name()) {
							absPath, err := filepath.Abs(filepath.Join(targetDir, file.Name()))
							if err != nil {

								items = append(items, *env.NewUri1(ps.Idx, "file://"+file.Name()))
							} else {
								items = append(items, *env.NewUri1(ps.Idx, "file://"+absPath))
							}
						}
					}

				default:
					return evaldo.MakeArgError(ps, 1, []env.Type{env.UriType, env.WordType, env.StringType, env.NativeType}, "ls\\")
				}
			}

			return *env.NewBlock(*env.NewTSeries(items))
		},
	},

	"ls\\dirs": {
		Argsn: 0,
		Doc:   "Lists only 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 evaldo.MakeBuiltinError(ps, "Error reading directory:"+err.Error(), "ls\\dirs")
			}

			var items []env.Object
			for _, file := range files {
				if file.IsDir() {
					items = append(items, *env.NewUri1(ps.Idx, "file://"+file.Name()))
				}
			}
			return *env.NewBlock(*env.NewTSeries(items))
		},
	},

	"ls\\files": {
		Argsn: 0,
		Doc:   "Lists only files (non-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 evaldo.MakeBuiltinError(ps, "Error reading directory:"+err.Error(), "ls\\files")
			}

			var items []env.Object
			for _, file := range files {
				if !file.IsDir() {
					items = append(items, *env.NewUri1(ps.Idx, "file://"+file.Name()))
				}
			}
			return *env.NewBlock(*env.NewTSeries(items))
		},
	},

	"ls\\dirs\\": {
		Argsn: 1,
		Doc:   "Lists directories in the current directory with filtering. Use 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 evaldo.MakeBuiltinError(ps, "Error reading directory:"+err.Error(), "ls\\dirs\\")
			}

			var items []env.Object

			switch filterArg := arg0.(type) {
			case env.String:

				pattern := filterArg.Value
				for _, file := range files {
					if file.IsDir() && 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 evaldo.MakeBuiltinError(ps, "Native object must be a regexp", "ls\\dirs\\")
				}

				regex := filterArg.Value.(*regexp.Regexp)
				for _, file := range files {
					if file.IsDir() && regex.MatchString(file.Name()) {
						items = append(items, *env.NewUri1(ps.Idx, "file://"+file.Name()))
					}
				}

			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.StringType, env.NativeType}, "ls\\dirs\\")
			}

			return *env.NewBlock(*env.NewTSeries(items))
		},
	},

	"ls\\files\\": {
		Argsn: 1,
		Doc:   "Lists files (non-directories) in the current directory with filtering. Use 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 evaldo.MakeBuiltinError(ps, "Error reading directory:"+err.Error(), "ls\\files\\")
			}

			var items []env.Object

			switch filterArg := arg0.(type) {
			case env.String:

				pattern := filterArg.Value
				for _, file := range files {
					if !file.IsDir() && 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 evaldo.MakeBuiltinError(ps, "Native object must be a regexp", "ls\\files\\")
				}

				regex := filterArg.Value.(*regexp.Regexp)
				for _, file := range files {
					if !file.IsDir() && regex.MatchString(file.Name()) {
						items = append(items, *env.NewUri1(ps.Idx, "file://"+file.Name()))
					}
				}

			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.StringType, env.NativeType}, "ls\\files\\")
			}

			return *env.NewBlock(*env.NewTSeries(items))
		},
	},

	"symlink": {
		Argsn: 2,
		Doc:   "Creates a symbolic link.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch src := arg0.(type) {
			case env.Uri:
				switch link := arg1.(type) {
				case env.Uri:
					srcPath := resolvePath(ps.WorkingPath, src.GetPath())
					linkPath := resolvePath(ps.WorkingPath, link.GetPath())
					err := os.Symlink(srcPath, linkPath)
					if err != nil {
						return evaldo.MakeBuiltinError(ps, "Error creating symlink: "+err.Error(), "symlink")
					}
					return arg1
				default:
					return evaldo.MakeArgError(ps, 2, []env.Type{env.UriType}, "symlink")
				}
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.UriType}, "symlink")
			}
		},
	},

	"is-symlink": {
		Argsn: 1,
		Doc:   "Checks if a path is a symbolic link. Fails if the path does not exist.",
		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 := resolvePath(ps.WorkingPath, path.GetPath())
				info, err := os.Lstat(filePath)
				if err != nil {
					return evaldo.MakeBuiltinError(ps, "Error checking path: "+err.Error(), "is-symlink")
				}
				return *env.NewBoolean(info.Mode()&os.ModeSymlink != 0)
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.UriType}, "is-symlink")
			}
		},
	},

	"readlink": {
		Argsn: 1,
		Doc:   "Reads the target of a symbolic link.",
		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:
				linkPath := resolvePath(ps.WorkingPath, path.GetPath())
				target, err := os.Readlink(linkPath)
				if err != nil {
					return evaldo.MakeBuiltinError(ps, "Error reading symlink: "+err.Error(), "readlink")
				}
				return *env.NewUri1(ps.Idx, "file://"+target)
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.UriType}, "readlink")
			}
		},
	},

	"chmod": {
		Argsn: 2,
		Doc:   "Changes file or directory permissions.",
		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 mode := arg1.(type) {
				case env.Integer:
					filePath := resolvePath(ps.WorkingPath, path.GetPath())
					err := os.Chmod(filePath, os.FileMode(mode.Value))
					if err != nil {
						return evaldo.MakeBuiltinError(ps, "Error changing permissions: "+err.Error(), "chmod")
					}
					return arg0
				default:
					return evaldo.MakeArgError(ps, 2, []env.Type{env.IntegerType}, "chmod")
				}
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.UriType}, "chmod")
			}
		},
	},

	"abs-path": {
		Argsn: 1,
		Doc:   "Removed: use realpath instead.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return evaldo.MakeBuiltinError(ps, "This function was removed. Use realpath.", "abs-path")
		},
	},

	"dirname": {
		Argsn: 1,
		Doc:   "Returns the directory part of a 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.Uri:
				dir := filepath.Dir(path.GetPath())
				return *env.NewUri1(ps.Idx, "file://"+dir)
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.UriType}, "dirname")
			}
		},
	},

	"basename": {
		Argsn: 1,
		Doc:   "Returns the filename part of a 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.Uri:
				base := filepath.Base(path.GetPath())
				return *env.NewString(base)
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.UriType}, "basename")
			}
		},
	},

	"file-ext": {
		Argsn: 1,
		Doc:   "Returns the file extension of a path (including the dot).",
		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:
				ext := filepath.Ext(path.GetPath())
				return *env.NewString(ext)
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.UriType}, "file-ext")
			}
		},
	},

	"join-path": {
		Argsn: 1,
		Doc:   "Joins path elements into a single path.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch paths := arg0.(type) {
			case env.Block:
				pathStrs := make([]string, paths.Series.Len())
				for i := 0; i < paths.Series.Len(); i++ {
					item := paths.Series.Get(i)
					switch p := item.(type) {
					case env.Uri:
						pathStrs[i] = p.GetPath()
					case env.String:
						pathStrs[i] = p.Value
					default:
						return evaldo.MakeBuiltinError(ps, "Block must contain only uris or strings", "join-path")
					}
				}
				joined := filepath.Join(pathStrs...)
				return *env.NewUri1(ps.Idx, "file://"+joined)
			case env.Uri:

				return arg0
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.UriType, env.BlockType}, "join-path")
			}
		},
	},

	"whoami": {
		Argsn: 0,
		Doc:   "Returns the current user's username.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			username := os.Getenv("USER")
			if username == "" {
				username = os.Getenv("USERNAME")
			}
			if username == "" {
				return evaldo.MakeBuiltinError(ps, "Unable to determine username", "whoami")
			}
			return *env.NewString(username)
		},
	},

	"which": {
		Argsn: 1,
		Doc:   "Finds the path to an executable command.",
		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:
				path, err := findExecutable(cmd.Value)
				if err != nil {
					return evaldo.MakeBuiltinError(ps, "Command not found: "+cmd.Value, "which")
				}
				return *env.NewUri1(ps.Idx, "file://"+path)
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.StringType}, "which")
			}
		},
	},

	"pwd": {
		Argsn: 0,
		Doc:   "Gets the current working directory (alias of cwd?).",
		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 evaldo.MakeBuiltinError(ps, err.Error(), "pwd")
			}
			return *env.NewUri1(ps.Idx, "file://"+path)
		},
	},

	"realpath": {
		Argsn: 1,
		Doc:   "Returns the absolute path for a given path (alias of abs-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.Uri:
				absPath, err := filepath.Abs(resolvePath(ps.WorkingPath, path.GetPath()))
				if err != nil {
					return evaldo.MakeBuiltinError(ps, "Error getting absolute path: "+err.Error(), "realpath")
				}
				return *env.NewUri1(ps.Idx, "file://"+absPath)
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.UriType}, "realpath")
			}
		},
	},

	"mktemp": {
		Argsn: 0,
		Doc:   "Creates a new temporary directory (alias of mktmp).",
		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 evaldo.MakeBuiltinError(ps, "Error creating temporary directory: "+err.Error(), "mktemp")
			}
			return *env.NewUri1(ps.Idx, "file://"+dir)
		},
	},

	"envs?": {
		Argsn: 0,
		Doc:   "Gets all environment variables as a dictionary of key -> value.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			vars := os.Environ()
			d := make(map[string]any, len(vars))
			for _, kv := range vars {
				if eq := strings.IndexByte(kv, '='); eq >= 0 {
					key := kv[:eq]
					val := kv[eq+1:]
					d[key] = *env.NewString(val)
				}
			}
			return *env.NewDict(d)
		},
	},

	"process?": {
		Argsn: 1,
		Doc:   "Gets detailed information about a specific process by PID (alias of process).",
		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:
				proc, err := process.NewProcess(int32(pid.Value))
				if err != nil {
					return evaldo.MakeBuiltinError(ps, err.Error(), "process?")
				}
				s := proccesTableBase()
				processTableAdd(s, proc)
				return s.Rows[0].ToDict()
			default:
				return *evaldo.MakeArgError(ps, 1, []env.Type{env.IntegerType}, "process?")
			}
		},
	},

	"cp-r": {
		Argsn: 2,
		Doc:   "Recursively copies a directory and all its contents.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch src := arg0.(type) {
			case env.Uri:
				switch dst := arg1.(type) {
				case env.Uri:
					srcPath := resolvePath(ps.WorkingPath, src.GetPath())
					dstPath := resolvePath(ps.WorkingPath, dst.GetPath())
					err := copyRecursive(srcPath, dstPath)
					if err != nil {
						return evaldo.MakeBuiltinError(ps, "Error copying recursively: "+err.Error(), "cp-r")
					}
					return arg1
				default:
					return evaldo.MakeArgError(ps, 2, []env.Type{env.UriType}, "cp-r")
				}
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.UriType}, "cp-r")
			}
		},
	},

	"mkdir-p": {
		Argsn: 1,
		Doc:   "Creates a directory and any necessary parent directories.",
		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:
				dirPath := resolvePath(ps.WorkingPath, path.GetPath())
				err := os.MkdirAll(dirPath, 0755)
				if err != nil {
					return evaldo.MakeBuiltinError(ps, "Error creating directory: "+err.Error(), "mkdir-p")
				}
				return arg0
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.UriType}, "mkdir-p")
			}
		},
	},

	"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 evaldo.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 evaldo.MakeBuiltinError(ps, err.Error(), "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 evaldo.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 evaldo.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 evaldo.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 evaldo.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 evaldo.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 evaldo.MakeBuiltinError(ps, err.Error(), "processes?")
			}
			s := proccesTableBase()
			for _, process := range processes {
				processTableAdd(s, process)
			}
			return *s
		},
	},

	"process": {
		Argsn: 1,
		Doc:   "Removed: use process? instead.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return evaldo.MakeBuiltinError(ps, "This function was removed. Use process?.", "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 evaldo.MakeBuiltinError(ps, err.Error(), "lookup-address")
				}
				items := make([]env.Object, len(names))
				for i, name := range names {
					items[i] = *env.NewString(name)
				}
				return *env.NewBlock(*env.NewTSeries(items))
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.StringType}, "lookup-address")
			}
		},
	},

	"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 hostname := arg0.(type) {
			case env.String:
				ips, err := net.LookupIP(hostname.Value)
				if err != nil {
					return evaldo.MakeBuiltinError(ps, err.Error(), "lookup-ip")
				}
				items := make([]env.Object, len(ips))
				for i, ip := range ips {
					items[i] = *env.NewString(ip.String())
				}
				return *env.NewBlock(*env.NewTSeries(items))
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.StringType}, "lookup-ip")
			}
		},
	},

	"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 evaldo.MakeBuiltinError(ps, err.Error(), "write\\clipboard")
				}
				return arg0
			default:
				return *evaldo.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 evaldo.MakeBuiltinError(ps, err.Error(), "read\\clipboard")
			}
			return *env.NewString(val)
		},
	},

	"tgz": {
		Argsn: 2,
		Doc:   "Creates a .tar.gz archive from 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 src := arg0.(type) {
			case env.Uri:
				switch dst := arg1.(type) {
				case env.Uri:
					srcPath := resolvePath(ps.WorkingPath, src.GetPath())
					dstPath := resolvePath(ps.WorkingPath, dst.GetPath())
					err := createTarGz(srcPath, dstPath)
					if err != nil {
						return evaldo.MakeBuiltinError(ps, "Error creating tar.gz: "+err.Error(), "tgz")
					}
					return arg1
				default:
					return evaldo.MakeArgError(ps, 2, []env.Type{env.UriType}, "tgz")
				}
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.UriType}, "tgz")
			}
		},
	},

	"un-tgz": {
		Argsn: 2,
		Doc:   "Removed: use untgz instead.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return evaldo.MakeBuiltinError(ps, "This function was removed. Use untgz.", "un-tgz")
		},
	},

	"untgz": {
		Argsn: 2,
		Doc:   "Extracts a .tar.gz archive to a directory (alias of un-tgz).",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch src := arg0.(type) {
			case env.Uri:
				switch dst := arg1.(type) {
				case env.Uri:
					srcPath := resolvePath(ps.WorkingPath, src.GetPath())
					dstPath := resolvePath(ps.WorkingPath, dst.GetPath())
					if err := extractTarGz(srcPath, dstPath); err != nil {
						return evaldo.MakeBuiltinError(ps, "Error extracting tar.gz: "+err.Error(), "untgz")
					}
					return arg1
				default:
					return evaldo.MakeArgError(ps, 2, []env.Type{env.UriType}, "untgz")
				}
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.UriType}, "untgz")
			}
		},
	},

	"tar-gz": {
		Argsn: 2,
		Doc:   "Creates a .tar.gz archive from a file or directory (alias of tgz).",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch src := arg0.(type) {
			case env.Uri:
				switch dst := arg1.(type) {
				case env.Uri:
					srcPath := resolvePath(ps.WorkingPath, src.GetPath())
					dstPath := resolvePath(ps.WorkingPath, dst.GetPath())
					if err := createTarGz(srcPath, dstPath); err != nil {
						return evaldo.MakeBuiltinError(ps, "Error creating tar.gz: "+err.Error(), "tar-gz")
					}
					return arg1
				default:
					return evaldo.MakeArgError(ps, 2, []env.Type{env.UriType}, "tar-gz")
				}
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.UriType}, "tar-gz")
			}
		},
	},

	"untar-gz": {
		Argsn: 2,
		Doc:   "Extracts a .tar.gz archive to a directory (alias of un-tgz).",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch src := arg0.(type) {
			case env.Uri:
				switch dst := arg1.(type) {
				case env.Uri:
					srcPath := resolvePath(ps.WorkingPath, src.GetPath())
					dstPath := resolvePath(ps.WorkingPath, dst.GetPath())
					if err := extractTarGz(srcPath, dstPath); err != nil {
						return evaldo.MakeBuiltinError(ps, "Error extracting tar.gz: "+err.Error(), "untar-gz")
					}
					return arg1
				default:
					return evaldo.MakeArgError(ps, 2, []env.Type{env.UriType}, "untar-gz")
				}
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.UriType}, "untar-gz")
			}
		},
	},

	"zip": {
		Argsn: 2,
		Doc:   "Creates a .zip archive from 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 src := arg0.(type) {
			case env.Uri:
				switch dst := arg1.(type) {
				case env.Uri:
					srcPath := resolvePath(ps.WorkingPath, src.GetPath())
					dstPath := resolvePath(ps.WorkingPath, dst.GetPath())
					err := createZip(srcPath, dstPath)
					if err != nil {
						return evaldo.MakeBuiltinError(ps, "Error creating zip: "+err.Error(), "zip")
					}
					return arg1
				default:
					return evaldo.MakeArgError(ps, 2, []env.Type{env.UriType}, "zip")
				}
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.UriType}, "zip")
			}
		},
	},

	"unzip": {
		Argsn: 2,
		Doc:   "Extracts a .zip archive to a directory.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch src := arg0.(type) {
			case env.Uri:
				switch dst := arg1.(type) {
				case env.Uri:
					srcPath := resolvePath(ps.WorkingPath, src.GetPath())
					dstPath := resolvePath(ps.WorkingPath, dst.GetPath())
					err := extractZip(srcPath, dstPath)
					if err != nil {
						return evaldo.MakeBuiltinError(ps, "Error extracting zip: "+err.Error(), "unzip")
					}
					return arg1
				default:
					return evaldo.MakeArgError(ps, 2, []env.Type{env.UriType}, "unzip")
				}
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.UriType}, "unzip")
			}
		},
	},

	"find": {
		Argsn: 1,
		Doc:   "Removed: use new-finder instead.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return evaldo.MakeBuiltinError(ps, "This function was removed. Use new-finder.", "find")
		},
	},

	"new-finder": {
		Argsn: 1,
		Doc:   "Creates a new file finder starting from the given path(s) (alias of find).",
		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:
				finder := find.NewFind(path.GetPath())
				return *env.NewNative(ps.Idx, finder, "finder")
			case env.Block:
				paths := make([]string, 0, path.Series.Len())
				for i := 0; i < path.Series.Len(); i++ {
					item := path.Series.Get(i)
					switch p := item.(type) {
					case env.Uri:
						paths = append(paths, p.GetPath())
					case env.String:
						paths = append(paths, p.Value)
					default:
						return evaldo.MakeBuiltinError(ps, "Block must contain only uris or strings", "new-finder")
					}
				}
				finder := find.NewFind(paths...)
				return *env.NewNative(ps.Idx, finder, "finder")
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.UriType, env.BlockType}, "new-finder")
			}
		},
	},

	"finder//min-depth!": {
		Argsn: 2,
		Doc:   "Sets the minimum depth for file traversal.",
		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.Native:
				if finder, ok := f.Value.(*find.Find); ok {
					switch depth := arg1.(type) {
					case env.Integer:
						finder.MinDepth(int(depth.Value))
						return arg0
					default:
						return evaldo.MakeArgError(ps, 2, []env.Type{env.IntegerType}, "finder//min-depth!")
					}
				}
				return evaldo.MakeBuiltinError(ps, "Expected finder object", "finder//min-depth!")
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "finder//min-depth!")
			}
		},
	},

	"finder//max-depth!": {
		Argsn: 2,
		Doc:   "Sets the maximum depth for file traversal.",
		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.Native:
				if finder, ok := f.Value.(*find.Find); ok {
					switch depth := arg1.(type) {
					case env.Integer:
						finder.MaxDepth(int(depth.Value))
						return arg0
					default:
						return evaldo.MakeArgError(ps, 2, []env.Type{env.IntegerType}, "finder//max-depth!")
					}
				}
				return evaldo.MakeBuiltinError(ps, "Expected finder object", "finder//max-depth!")
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "finder//max-depth!")
			}
		},
	},

	"finder//type": {
		Argsn: 2,
		Doc:   "Filters results by type: 'file (or \"f\") for files, 'dir (or \"d\") for directories.",
		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.Native:
				if finder, ok := f.Value.(*find.Find); ok {
					var typeStr string
					switch t := arg1.(type) {
					case env.Word:
						word := ps.Idx.GetWord(t.Index)
						switch word {
						case "file":
							typeStr = "f"
						case "dir":
							typeStr = "d"
						default:
							return evaldo.MakeBuiltinError(ps, "Type must be 'file or 'dir", "finder//type")
						}
					case env.String:
						if t.Value != "f" && t.Value != "d" {
							return evaldo.MakeBuiltinError(ps, "Type must be \"f\" or \"d\"", "finder//type")
						}
						typeStr = t.Value
					default:
						return evaldo.MakeArgError(ps, 2, []env.Type{env.WordType, env.StringType}, "finder//type")
					}
					finder.Type(typeStr)
					return arg0
				}
				return evaldo.MakeBuiltinError(ps, "Expected finder object", "finder//type")
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "finder//type")
			}
		},
	},

	"finder//name": {
		Argsn: 2,
		Doc:   "Filters results by file name using 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 f := arg0.(type) {
			case env.Native:
				if finder, ok := f.Value.(*find.Find); ok {
					switch pattern := arg1.(type) {
					case env.String:
						finder.Name(pattern.Value)
						return arg0
					default:
						return evaldo.MakeArgError(ps, 2, []env.Type{env.StringType}, "finder//name")
					}
				}
				return evaldo.MakeBuiltinError(ps, "Expected finder object", "finder//name")
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "finder//name")
			}
		},
	},

	"finder//whole-name": {
		Argsn: 2,
		Doc:   "Filters results by full path using 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 f := arg0.(type) {
			case env.Native:
				if finder, ok := f.Value.(*find.Find); ok {
					switch pattern := arg1.(type) {
					case env.String:
						finder.WholeName(pattern.Value)
						return arg0
					default:
						return evaldo.MakeArgError(ps, 2, []env.Type{env.StringType}, "finder//whole-name")
					}
				}
				return evaldo.MakeBuiltinError(ps, "Expected finder object", "finder//whole-name")
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "finder//whole-name")
			}
		},
	},

	"finder//regex": {
		Argsn: 2,
		Doc:   "Filters results by regular expression on the full path.",
		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.Native:
				if finder, ok := f.Value.(*find.Find); ok {
					switch r := arg1.(type) {
					case env.Native:
						if regex, ok := r.Value.(*regexp.Regexp); ok {
							finder.Regex(regex)
							return arg0
						}
						return evaldo.MakeBuiltinError(ps, "Expected regexp object", "finder//regex")
					default:
						return evaldo.MakeArgError(ps, 2, []env.Type{env.NativeType}, "finder//regex")
					}
				}
				return evaldo.MakeBuiltinError(ps, "Expected finder object", "finder//regex")
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "finder//regex")
			}
		},
	},

	"finder//empty": {
		Argsn: 1,
		Doc:   "Filters for empty files or directories.",
		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.Native:
				if finder, ok := f.Value.(*find.Find); ok {
					finder.Empty()
					return arg0
				}
				return evaldo.MakeBuiltinError(ps, "Expected finder object", "finder//empty")
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "finder//empty")
			}
		},
	},

	"finder//eval": {
		Argsn: 1,
		Doc:   "Executes the find operation and returns matching paths as uris.",
		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.Native:
				if finder, ok := f.Value.(*find.Find); ok {
					results, err := finder.Evaluate()
					if err != nil {
						return evaldo.MakeBuiltinError(ps, "Error evaluating find: "+err.Error(), "finder//eval")
					}
					items := make([]env.Object, len(results))
					for i, path := range results {
						items[i] = *env.NewUri1(ps.Idx, "file://"+path)
					}
					return *env.NewBlock(*env.NewTSeries(items))
				}
				return evaldo.MakeBuiltinError(ps, "Expected finder object", "finder//eval")
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "finder//eval")
			}
		},
	},

	"file-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 path := arg0.(type) {
			case env.Uri:
				filePath := resolvePath(ps.WorkingPath, path.GetPath())
				info, err := os.Stat(filePath)
				if err != nil {
					return evaldo.MakeBuiltinError(ps, "Error getting file size: "+err.Error(), "file-size")
				}
				return *env.NewInteger(info.Size())
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.UriType}, "file-size")
			}
		},
	},

	"touch": {
		Argsn: 1,
		Doc:   "Creates a file if it doesn't exist, or updates its access time if it does.",
		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 := resolvePath(ps.WorkingPath, path.GetPath())
				now := time.Now()
				err := os.Chtimes(filePath, now, now)
				if os.IsNotExist(err) {

					file, err := os.Create(filePath)
					if err != nil {
						return evaldo.MakeBuiltinError(ps, "Error creating file: "+err.Error(), "touch")
					}
					file.Close()
				} else if err != nil {
					return evaldo.MakeBuiltinError(ps, "Error touching file: "+err.Error(), "touch")
				}
				return arg0
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.UriType}, "touch")
			}
		},
	},

	"hardlink": {
		Argsn: 2,
		Doc:   "Creates a hard link 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 src := arg0.(type) {
			case env.Uri:
				switch link := arg1.(type) {
				case env.Uri:
					srcPath := resolvePath(ps.WorkingPath, src.GetPath())
					linkPath := resolvePath(ps.WorkingPath, link.GetPath())
					err := os.Link(srcPath, linkPath)
					if err != nil {
						return evaldo.MakeBuiltinError(ps, "Error creating hard link: "+err.Error(), "hardlink")
					}
					return arg1
				default:
					return evaldo.MakeArgError(ps, 2, []env.Type{env.UriType}, "hardlink")
				}
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.UriType}, "hardlink")
			}
		},
	},

	"count-dir": {
		Argsn: 1,
		Doc:   "Counts the number of files and directories in a directory.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			var dirPath string
			switch path := arg0.(type) {
			case env.Uri:
				dirPath = resolvePath(ps.WorkingPath, path.GetPath())
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.UriType}, "count-dir")
			}

			files, err := os.ReadDir(dirPath)
			if err != nil {
				return evaldo.MakeBuiltinError(ps, "Error reading directory: "+err.Error(), "count-dir")
			}
			return *env.NewInteger(int64(len(files)))
		},
	},

	"pid": {
		Argsn: 0,
		Doc:   "Gets the current process ID.",
		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(int64(os.Getpid()))
		},
	},

	"ppid": {
		Argsn: 0,
		Doc:   "Gets the parent process ID.",
		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(int64(os.Getppid()))
		},
	},

	"sleep": {
		Argsn: 1,
		Doc:   "Sleeps for the specified number of seconds.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch seconds := arg0.(type) {
			case env.Integer:
				time.Sleep(time.Duration(seconds.Value) * time.Second)
				return arg0
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.IntegerType}, "sleep")
			}
		},
	},

	"tmux-available?": {
		Argsn: 0,
		Doc:   "Checks if tmux is available on the system.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			_, err := exec.LookPath("tmux")
			return *env.NewBoolean(err == nil)
		},
	},

	"tmux-new-session": {
		Argsn: 1,
		Doc:   "Creates a new tmux session with the given name using gotmux library.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			tmux, err := gotmux.DefaultTmux()
			if err != nil {
				return evaldo.MakeBuiltinError(ps, "Failed to connect to tmux: "+err.Error(), "tmux-new-session")
			}

			switch name := arg0.(type) {
			case env.String:
				session, err := tmux.NewSession(&gotmux.SessionOptions{
					Name: name.Value,
				})
				if err != nil {
					return evaldo.MakeBuiltinError(ps, "Failed to create session: "+err.Error(), "tmux-new-session")
				}
				return *env.NewNative(ps.Idx, session, "tmux-session")
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.StringType}, "tmux-new-session")
			}
		},
	},

	"tmux-list-sessions": {
		Argsn: 0,
		Doc:   "Lists all tmux sessions using gotmux library.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			tmux, err := gotmux.DefaultTmux()
			if err != nil {
				return evaldo.MakeBuiltinError(ps, "Failed to connect to tmux: "+err.Error(), "tmux-list-sessions")
			}

			sessions, err := tmux.ListSessions()
			if err != nil {
				return evaldo.MakeBuiltinError(ps, "Failed to list sessions: "+err.Error(), "tmux-list-sessions")
			}

			items := make([]env.Object, len(sessions))
			for i, session := range sessions {
				items[i] = *env.NewNative(ps.Idx, session, "tmux-session")
			}
			return *env.NewBlock(*env.NewTSeries(items))
		},
	},

	"tmux-get-session": {
		Argsn: 1,
		Doc:   "Gets a tmux session by name using gotmux library.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			tmux, err := gotmux.DefaultTmux()
			if err != nil {
				return evaldo.MakeBuiltinError(ps, "Failed to connect to tmux: "+err.Error(), "tmux-get-session")
			}

			switch name := arg0.(type) {
			case env.String:
				session, err := tmux.GetSessionByName(name.Value)
				if err != nil {
					return evaldo.MakeBuiltinError(ps, "Failed to get session: "+err.Error(), "tmux-get-session")
				}
				return *env.NewNative(ps.Idx, session, "tmux-session")
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.StringType}, "tmux-get-session")
			}
		},
	},

	"tmux-new-window": {
		Argsn: 1,
		Doc:   "Creates a new window in the given tmux session.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch sess := arg0.(type) {
			case env.Native:
				if session, ok := sess.Value.(*gotmux.Session); ok {
					window, err := session.New()
					if err != nil {
						return evaldo.MakeBuiltinError(ps, "Failed to create window: "+err.Error(), "tmux-new-window")
					}
					return *env.NewNative(ps.Idx, window, "tmux-window")
				}
				return evaldo.MakeBuiltinError(ps, "Expected tmux-session object", "tmux-new-window")
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "tmux-new-window")
			}
		},
	},

	"tmux-new-window-named": {
		Argsn: 2,
		Doc:   "Creates a new window in the given tmux session with a specific name.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch sess := arg0.(type) {
			case env.Native:
				if session, ok := sess.Value.(*gotmux.Session); ok {
					switch name := arg1.(type) {
					case env.String:
						window, err := session.NewWindow(&gotmux.NewWindowOptions{
							WindowName: name.Value,
						})
						if err != nil {
							return evaldo.MakeBuiltinError(ps, "Failed to create named window: "+err.Error(), "tmux-new-window-named")
						}
						return *env.NewNative(ps.Idx, window, "tmux-window")
					default:
						return evaldo.MakeArgError(ps, 2, []env.Type{env.StringType}, "tmux-new-window-named")
					}
				}
				return evaldo.MakeBuiltinError(ps, "Expected tmux-session object", "tmux-new-window-named")
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "tmux-new-window-named")
			}
		},
	},

	"tmux-list-windows": {
		Argsn: 1,
		Doc:   "Lists all windows in the given tmux session.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch sess := arg0.(type) {
			case env.Native:
				if session, ok := sess.Value.(*gotmux.Session); ok {
					windows, err := session.ListWindows()
					if err != nil {
						return evaldo.MakeBuiltinError(ps, "Failed to list windows: "+err.Error(), "tmux-list-windows")
					}

					items := make([]env.Object, len(windows))
					for i, window := range windows {
						items[i] = *env.NewNative(ps.Idx, window, "tmux-window")
					}
					return *env.NewBlock(*env.NewTSeries(items))
				}
				return evaldo.MakeBuiltinError(ps, "Expected tmux-session object", "tmux-list-windows")
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "tmux-list-windows")
			}
		},
	},

	"tmux-get-pane": {
		Argsn: 2,
		Doc:   "Gets a pane from a tmux window 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 win := arg0.(type) {
			case env.Native:
				if window, ok := win.Value.(*gotmux.Window); ok {
					switch idx := arg1.(type) {
					case env.Integer:
						pane, err := window.GetPaneByIndex(int(idx.Value))
						if err != nil {
							return evaldo.MakeBuiltinError(ps, "Failed to get pane: "+err.Error(), "tmux-get-pane")
						}
						return *env.NewNative(ps.Idx, pane, "tmux-pane")
					default:
						return evaldo.MakeArgError(ps, 2, []env.Type{env.IntegerType}, "tmux-get-pane")
					}
				}
				return evaldo.MakeBuiltinError(ps, "Expected tmux-window object", "tmux-get-pane")
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "tmux-get-pane")
			}
		},
	},

	"tmux-split-pane": {
		Argsn: 1,
		Doc:   "Splits a tmux pane horizontally.",
		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:
				if pane, ok := p.Value.(*gotmux.Pane); ok {
					err := pane.Split()
					if err != nil {
						return evaldo.MakeBuiltinError(ps, "Failed to split pane: "+err.Error(), "tmux-split-pane")
					}
					return arg0
				}
				return evaldo.MakeBuiltinError(ps, "Expected tmux-pane object", "tmux-split-pane")
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "tmux-split-pane")
			}
		},
	},

	"tmux-send-keys": {
		Argsn: 2,
		Doc:   "Sends keys/command to a tmux pane.",
		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:
				if pane, ok := p.Value.(*gotmux.Pane); ok {
					switch cmd := arg1.(type) {
					case env.String:
						err := pane.SendKeys(cmd.Value)
						if err != nil {
							return evaldo.MakeBuiltinError(ps, "Failed to send keys: "+err.Error(), "tmux-send-keys")
						}
						return arg0
					default:
						return evaldo.MakeArgError(ps, 2, []env.Type{env.StringType}, "tmux-send-keys")
					}
				}
				return evaldo.MakeBuiltinError(ps, "Expected tmux-pane object", "tmux-send-keys")
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "tmux-send-keys")
			}
		},
	},

	"tmux-kill-session": {
		Argsn: 1,
		Doc:   "Kills/destroys a tmux session.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch sess := arg0.(type) {
			case env.Native:
				if session, ok := sess.Value.(*gotmux.Session); ok {
					err := session.Kill()
					if err != nil {
						return evaldo.MakeBuiltinError(ps, "Failed to kill session: "+err.Error(), "tmux-kill-session")
					}
					return arg0
				}
				return evaldo.MakeBuiltinError(ps, "Expected tmux-session object", "tmux-kill-session")
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "tmux-kill-session")
			}
		},
	},

	"net-interface?": {
		Argsn: 1,
		Doc:   "Looks up a network interface by name and returns it as a native object.",
		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:
				iface, err := net.InterfaceByName(name.Value)
				if err != nil {
					ps.FailureFlag = true
					return evaldo.MakeBuiltinError(ps, err.Error(), "net-interface?")
				}
				return *env.NewNative(ps.Idx, iface, "net-iface")
			default:
				ps.FailureFlag = true
				return evaldo.MakeArgError(ps, 1, []env.Type{env.StringType}, "net-interface?")
			}
		},
	},

	"net-iface//Addrs?": {
		Argsn: 1,
		Doc:   "Returns a block of network addresses assigned to the interface.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch iface := arg0.(type) {
			case env.Native:
				addrs, err := iface.Value.(*net.Interface).Addrs()
				if err != nil {
					ps.FailureFlag = true
					return evaldo.MakeBuiltinError(ps, err.Error(), "net-iface//Addrs?")
				}
				items := make([]env.Object, len(addrs))
				for i, addr := range addrs {
					items[i] = *env.NewNative(ps.Idx, addr, "net-addr")
				}
				return *env.NewBlock(*env.NewTSeries(items))
			default:
				ps.FailureFlag = true
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "net-iface//Addrs?")
			}
		},
	},

	"net-addr//IPNet?": {
		Argsn: 1,
		Doc:   "Type-asserts a network address to *net.IPNet (CIDR form). Returns failure if the address is not an IP network.",
		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:
				ipnet, ok := addr.Value.(net.Addr).(*net.IPNet)
				if !ok {
					ps.FailureFlag = true
					return evaldo.MakeBuiltinError(ps, "Address is not an *net.IPNet.", "net-addr//IPNet?")
				}
				return *env.NewNative(ps.Idx, ipnet, "net-ipnet")
			default:
				ps.FailureFlag = true
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "net-addr//IPNet?")
			}
		},
	},

	"net-ipnet//Loopback?": {
		Argsn: 1,
		Doc:   "Reports whether the IP address in the IPNet is a loopback address.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch ipnet := arg0.(type) {
			case env.Native:
				return *env.NewBoolean(ipnet.Value.(*net.IPNet).IP.IsLoopback())
			default:
				ps.FailureFlag = true
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "net-ipnet//Loopback?")
			}
		},
	},

	"net-ipnet//IPv4?": {
		Argsn: 1,
		Doc:   "Reports whether the IP address in the IPNet is an IPv4 address (IP.To4() != nil).",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch ipnet := arg0.(type) {
			case env.Native:
				return *env.NewBoolean(ipnet.Value.(*net.IPNet).IP.To4() != nil)
			default:
				ps.FailureFlag = true
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "net-ipnet//IPv4?")
			}
		},
	},

	"net-ipnet//IP-string?": {
		Argsn: 1,
		Doc:   "Returns the IP address contained in the IPNet as a dotted-decimal (or colon-separated) string.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch ipnet := arg0.(type) {
			case env.Native:
				return *env.NewString(ipnet.Value.(*net.IPNet).IP.String())
			default:
				ps.FailureFlag = true
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "net-ipnet//IP-string")
			}
		},
	},
}
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 evaldo.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 evaldo.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 evaldo.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 evaldo.MakeBuiltinError(ps, "Block must contain only strings", "p-new-block")
					}
				}
				p := script.Slice(strs)
				return *env.NewNative(ps.Idx, p, "script-pipe")
			default:
				return evaldo.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 evaldo.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 evaldo.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 evaldo.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 evaldo.MakeArgError(ps, 2, []env.Type{env.StringType}, "p-exec")
					}
				default:
					return evaldo.MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-exec")
				}
			default:
				return evaldo.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 evaldo.MakeArgError(ps, 2, []env.Type{env.StringType}, "p-exec-for-each")
					}
				default:
					return evaldo.MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-exec-for-each")
				}
			default:
				return evaldo.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 evaldo.MakeBuiltinError(ps, err.Error(), "p-string")
					}
					return *env.NewString(str)
				default:
					return evaldo.MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-string")
				}
			default:
				return evaldo.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 evaldo.MakeBuiltinError(ps, err.Error(), "p-write-file")
						}
						return *env.NewInteger(i)
					default:
						return evaldo.MakeArgError(ps, 2, []env.Type{env.UriType}, "p-write-file")
					}
				default:
					return evaldo.MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-write-file")
				}
			default:
				return evaldo.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 evaldo.MakeBuiltinError(ps, err.Error(), "p-stdout")
					}
					return *env.NewInteger(int64(i))
				default:
					return evaldo.MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-stdout")
				}
			default:
				return evaldo.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 evaldo.MakeArgError(ps, 2, []env.Type{env.IntegerType}, "p-first-n")
					}
				default:
					return evaldo.MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-first-n")
				}
			default:
				return evaldo.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 evaldo.MakeArgError(ps, 2, []env.Type{env.IntegerType}, "p-last-n")
					}
				default:
					return evaldo.MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-last-n")
				}
			default:
				return evaldo.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 evaldo.MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-dirname")
				}
			default:
				return evaldo.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 evaldo.MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-basename")
				}
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "p-basename")
			}
		},
	},

	"wc\\l": {
		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 evaldo.MakeBuiltinError(ps, err.Error(), "p-count-lines")
					}
					return *env.NewInteger(int64(n))
				default:
					return evaldo.MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-count-lines")
				}
			default:
				return evaldo.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 evaldo.MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-freq")
				}
			default:
				return evaldo.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 evaldo.MakeArgError(ps, 2, []env.Type{env.IntegerType}, "p-column")
					}
				default:
					return evaldo.MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-column")
				}
			default:
				return evaldo.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 evaldo.MakeArgError(ps, 2, []env.Type{env.StringType}, "p-jq")
					}
				default:
					return evaldo.MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-jq")
				}
			default:
				return evaldo.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 evaldo.MakeArgError(ps, 2, []env.Type{env.StringType}, "p-match")
					}
				default:
					return evaldo.MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-match")
				}
			default:
				return evaldo.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 evaldo.MakeNativeArgError(ps, 2, []string{"regexp"}, "p-match-regexp")
						}
					default:
						return evaldo.MakeArgError(ps, 2, []env.Type{env.NativeType}, "p-match-regexp")
					}
				default:
					return evaldo.MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-match-regexp")
				}
			default:
				return evaldo.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 evaldo.MakeArgError(ps, 2, []env.Type{env.StringType}, "p-not-match")
					}
				default:
					return evaldo.MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-not-match")
				}
			default:
				return evaldo.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 evaldo.MakeNativeArgError(ps, 2, []string{"regexp"}, "p-not-match-regexp")
						}
					default:
						return evaldo.MakeArgError(ps, 2, []env.Type{env.NativeType}, "p-not-match-regexp")
					}
				default:
					return evaldo.MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-not-match-regexp")
				}
			default:
				return evaldo.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 evaldo.MakeArgError(ps, 3, []env.Type{env.StringType}, "p-replace")
						}
					default:
						return evaldo.MakeArgError(ps, 2, []env.Type{env.StringType}, "p-replace")
					}
				default:
					return evaldo.MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-replace")
				}
			default:
				return evaldo.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 evaldo.MakeArgError(ps, 3, []env.Type{env.StringType}, "p-replace-regexp")
							}
						default:
							return evaldo.MakeNativeArgError(ps, 2, []string{"regexp"}, "p-replace-regexp")
						}
					default:
						return evaldo.MakeArgError(ps, 2, []env.Type{env.NativeType}, "p-replace-regexp")
					}
				default:
					return evaldo.MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-replace-regexp")
				}
			default:
				return evaldo.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 evaldo.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 evaldo.MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-block")
				}
			default:
				return evaldo.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 evaldo.MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-error")
				}
			default:
				return evaldo.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 evaldo.MakeBuiltinError(ps, err.Error(), "pipes/sha256sum")
					}
					return *env.NewString(sha256)
				default:
					return evaldo.MakeNativeArgError(ps, 1, []string{"script-pipe"}, "pipes/sha256sum")
				}
			default:
				return evaldo.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 evaldo.MakeNativeArgError(ps, 1, []string{"script-pipe"}, "pipes/sha256sums")
				}
			default:
				return evaldo.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 evaldo.MakeNativeArgError(ps, 1, []string{"script-pipe"}, "decodeBase64")
				}
			default:
				return evaldo.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 evaldo.MakeNativeArgError(ps, 1, []string{"script-pipe"}, "encodeBase64")
				}
			default:
				return evaldo.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 evaldo.MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-join")
				}
			default:
				return evaldo.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 evaldo.MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-exit-status")
				}
			default:
				return evaldo.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 evaldo.MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-concat")
				}
			default:
				return evaldo.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 evaldo.MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-close")
				}
			default:
				return evaldo.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 evaldo.MakeArgError(ps, 2, []env.Type{env.StringType}, "p-get")
					}
				default:
					return evaldo.MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-get")
				}
			default:
				return evaldo.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 evaldo.MakeArgError(ps, 2, []env.Type{env.StringType}, "p-post")
					}
				default:
					return evaldo.MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-post")
				}
			default:
				return evaldo.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 evaldo.MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-wait")
				}
			default:
				return evaldo.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 evaldo.MakeArgError(ps, 2, []env.Type{env.StringType, env.UriType}, "p-append-to-file")
					}
				default:
					return evaldo.MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-append-to-file")
				}
			default:
				return evaldo.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 evaldo.MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-error")
				}
			default:
				return evaldo.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 evaldo.MakeArgError(ps, 2, []env.Type{env.StringType}, "p-set-error")
					}
				default:
					return evaldo.MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-set-error")
				}
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "p-set-error")
			}
		},
	},

	"extract\\regexp": {
		Argsn: 2,
		Doc:   "For each line in the pipe, extracts all regexp matches (capture group 1 if present, otherwise the whole match) and outputs each match on a separate line. Equivalent to grep -oP with a capture group.",
		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 rx := r.Value.(type) {
						case *regexp.Regexp:
							newPipe := pipe.Filter(func(r io.Reader, w io.Writer) error {
								scanner := bufio.NewScanner(r)
								for scanner.Scan() {
									line := scanner.Text()
									matches := rx.FindAllStringSubmatch(line, -1)
									for _, match := range matches {
										if len(match) > 1 {
											fmt.Fprintln(w, match[1])
										} else {
											fmt.Fprintln(w, match[0])
										}
									}
								}
								return scanner.Err()
							})
							return *env.NewNative(ps.Idx, newPipe, "script-pipe")
						default:
							return evaldo.MakeNativeArgError(ps, 2, []string{"regexp"}, "extract\\regexp")
						}
					default:
						return evaldo.MakeArgError(ps, 2, []env.Type{env.NativeType}, "extract\\regexp")
					}
				default:
					return evaldo.MakeNativeArgError(ps, 1, []string{"script-pipe"}, "extract\\regexp")
				}
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "extract\\regexp")
			}
		},
	},

	"sort": {
		Argsn: 1,
		Doc:   "Sorts the lines of the pipe alphabetically in ascending 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.Filter(func(r io.Reader, w io.Writer) error {
						scanner := bufio.NewScanner(r)
						var lines []string
						for scanner.Scan() {
							lines = append(lines, scanner.Text())
						}
						if err := scanner.Err(); err != nil {
							return err
						}
						sort.Strings(lines)
						for _, line := range lines {
							fmt.Fprintln(w, line)
						}
						return nil
					})
					return *env.NewNative(ps.Idx, newPipe, "script-pipe")
				default:
					return evaldo.MakeNativeArgError(ps, 1, []string{"script-pipe"}, "sort")
				}
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "sort")
			}
		},
	},

	"sort\\reverse": {
		Argsn: 1,
		Doc:   "Sorts the lines of the pipe alphabetically in descending (reverse) 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.Filter(func(r io.Reader, w io.Writer) error {
						scanner := bufio.NewScanner(r)
						var lines []string
						for scanner.Scan() {
							lines = append(lines, scanner.Text())
						}
						if err := scanner.Err(); err != nil {
							return err
						}
						sort.Sort(sort.Reverse(sort.StringSlice(lines)))
						for _, line := range lines {
							fmt.Fprintln(w, line)
						}
						return nil
					})
					return *env.NewNative(ps.Idx, newPipe, "script-pipe")
				default:
					return evaldo.MakeNativeArgError(ps, 1, []string{"script-pipe"}, "sort\\reverse")
				}
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "sort\\reverse")
			}
		},
	},

	"uniq": {
		Argsn: 1,
		Doc:   "Removes consecutive duplicate lines from the pipe, like the Unix uniq command. Combine with sort to remove all duplicates.",
		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.Filter(func(r io.Reader, w io.Writer) error {
						scanner := bufio.NewScanner(r)
						last := ""
						first := true
						for scanner.Scan() {
							line := scanner.Text()
							if first || line != last {
								fmt.Fprintln(w, line)
								last = line
								first = false
							}
						}
						return scanner.Err()
					})
					return *env.NewNative(ps.Idx, newPipe, "script-pipe")
				default:
					return evaldo.MakeNativeArgError(ps, 1, []string{"script-pipe"}, "uniq")
				}
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "uniq")
			}
		},
	},

	"trim-lines": {
		Argsn: 1,
		Doc:   "Trims leading and trailing whitespace from each line in 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:
					newPipe := pipe.FilterLine(func(line string) string {
						return strings.TrimSpace(line)
					})
					return *env.NewNative(ps.Idx, newPipe, "script-pipe")
				default:
					return evaldo.MakeNativeArgError(ps, 1, []string{"script-pipe"}, "trim-lines")
				}
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "trim-lines")
			}
		},
	},

	"prefix-lines": {
		Argsn: 2,
		Doc:   "Prepends a string to the beginning of each line in 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 prefix := arg1.(type) {
					case env.String:
						newPipe := pipe.FilterLine(func(line string) string {
							return prefix.Value + line
						})
						return *env.NewNative(ps.Idx, newPipe, "script-pipe")
					default:
						return evaldo.MakeArgError(ps, 2, []env.Type{env.StringType}, "prefix-lines")
					}
				default:
					return evaldo.MakeNativeArgError(ps, 1, []string{"script-pipe"}, "prefix-lines")
				}
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "prefix-lines")
			}
		},
	},

	"skip": {
		Argsn: 2,
		Doc:   "Skips 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:
						skipCount := int(n.Value)
						newPipe := pipe.Filter(func(r io.Reader, w io.Writer) error {
							scanner := bufio.NewScanner(r)
							lineNum := 0
							for scanner.Scan() {
								lineNum++
								if lineNum > skipCount {
									fmt.Fprintln(w, scanner.Text())
								}
							}
							return scanner.Err()
						})
						return *env.NewNative(ps.Idx, newPipe, "script-pipe")
					default:
						return evaldo.MakeArgError(ps, 2, []env.Type{env.IntegerType}, "skip")
					}
				default:
					return evaldo.MakeNativeArgError(ps, 1, []string{"script-pipe"}, "skip")
				}
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "skip")
			}
		},
	},

	"number-lines": {
		Argsn: 1,
		Doc:   "Prefixes each line with its line number (1-indexed).",
		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.Filter(func(r io.Reader, w io.Writer) error {
						scanner := bufio.NewScanner(r)
						lineNum := 0
						for scanner.Scan() {
							lineNum++
							fmt.Fprintf(w, "%d: %s\n", lineNum, scanner.Text())
						}
						return scanner.Err()
					})
					return *env.NewNative(ps.Idx, newPipe, "script-pipe")
				default:
					return evaldo.MakeNativeArgError(ps, 1, []string{"script-pipe"}, "number-lines")
				}
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "number-lines")
			}
		},
	},

	"count-matches": {
		Argsn: 2,
		Doc:   "Counts the number of lines containing the given string. This is a sink operation that consumes 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 s := arg1.(type) {
					case env.String:
						lines, err := pipe.Slice()
						if err != nil {
							return evaldo.MakeBuiltinError(ps, err.Error(), "count-matches")
						}
						count := 0
						for _, line := range lines {
							if strings.Contains(line, s.Value) {
								count++
							}
						}
						return *env.NewInteger(int64(count))
					default:
						return evaldo.MakeArgError(ps, 2, []env.Type{env.StringType}, "count-matches")
					}
				default:
					return evaldo.MakeNativeArgError(ps, 1, []string{"script-pipe"}, "count-matches")
				}
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "count-matches")
			}
		},
	},

	"between": {
		Argsn: 3,
		Doc:   "Returns lines between start and end marker lines (exclusive). Can handle multiple ranges.",
		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 startStr := arg1.(type) {
					case env.String:
						switch endStr := arg2.(type) {
						case env.String:
							newPipe := pipe.Filter(func(r io.Reader, w io.Writer) error {
								scanner := bufio.NewScanner(r)
								inside := false
								for scanner.Scan() {
									line := scanner.Text()
									if strings.Contains(line, endStr.Value) {
										inside = false
										continue
									}
									if inside {
										fmt.Fprintln(w, line)
									}
									if strings.Contains(line, startStr.Value) {
										inside = true
									}
								}
								return scanner.Err()
							})
							return *env.NewNative(ps.Idx, newPipe, "script-pipe")
						default:
							return evaldo.MakeArgError(ps, 3, []env.Type{env.StringType}, "between")
						}
					default:
						return evaldo.MakeArgError(ps, 2, []env.Type{env.StringType}, "between")
					}
				default:
					return evaldo.MakeNativeArgError(ps, 1, []string{"script-pipe"}, "between")
				}
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "between")
			}
		},
	},

	"tee\\file": {
		Argsn: 2,
		Doc:   "Writes the pipe contents to a file while also passing them through. Like the Unix tee 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 path := arg1.(type) {
					case env.Uri:
						file, err := os.Create(path.GetPath())
						if err != nil {
							return evaldo.MakeBuiltinError(ps, err.Error(), "tee\\file")
						}
						newPipe := pipe.Tee(file)
						return *env.NewNative(ps.Idx, newPipe, "script-pipe")
					case env.String:
						file, err := os.Create(path.Value)
						if err != nil {
							return evaldo.MakeBuiltinError(ps, err.Error(), "tee\\file")
						}
						newPipe := pipe.Tee(file)
						return *env.NewNative(ps.Idx, newPipe, "script-pipe")
					default:
						return evaldo.MakeArgError(ps, 2, []env.Type{env.UriType, env.StringType}, "tee\\file")
					}
				default:
					return evaldo.MakeNativeArgError(ps, 1, []string{"script-pipe"}, "tee\\file")
				}
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "tee\\file")
			}
		},
	},

	"map-each": {
		Argsn: 2,
		Doc:   "Transforms each line by evaluating a Rye block with the line injected. The block should return 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:
					switch block := arg1.(type) {
					case env.Block:

						lines, err := pipe.Slice()
						if err != nil {
							return evaldo.MakeBuiltinError(ps, err.Error(), "map-each")
						}

						result := make([]string, 0, len(lines))
						ser := ps.Ser
						for _, line := range lines {
							ps.Ser = block.Series
							ps.Ser.SetPos(0)
							evaldo.EvalBlockInj(ps, *env.NewString(line), true)
							if ps.ErrorFlag {
								ps.Ser = ser
								return evaldo.MakeBuiltinError(ps, "Error during evaluation of block", "map-each")
							}
							if ps.FailureFlag {
								ps.Ser = ser
								return ps.Res
							}

							switch res := ps.Res.(type) {
							case env.String:
								result = append(result, res.Value)
							default:

								result = append(result, ps.Res.Print(*ps.Idx))
							}
						}
						ps.Ser = ser

						newPipe := script.Slice(result)
						return *env.NewNative(ps.Idx, newPipe, "script-pipe")
					default:
						return evaldo.MakeArgError(ps, 2, []env.Type{env.BlockType}, "map-each")
					}
				default:
					return evaldo.MakeNativeArgError(ps, 1, []string{"script-pipe"}, "map-each")
				}
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "map-each")
			}
		},
	},

	"filter-each": {
		Argsn: 2,
		Doc:   "Filters lines by evaluating a Rye block with each line injected. Only lines for which the block returns truthy are kept.",
		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 block := arg1.(type) {
					case env.Block:

						lines, err := pipe.Slice()
						if err != nil {
							return evaldo.MakeBuiltinError(ps, err.Error(), "filter-each")
						}

						result := make([]string, 0)
						ser := ps.Ser
						for _, line := range lines {
							ps.Ser = block.Series
							ps.Ser.SetPos(0)
							evaldo.EvalBlockInj(ps, *env.NewString(line), true)
							if ps.ErrorFlag {
								ps.Ser = ser
								return evaldo.MakeBuiltinError(ps, "Error during evaluation of block", "filter-each")
							}
							if ps.FailureFlag {
								ps.Ser = ser
								return ps.Res
							}

							if util.IsTruthy(ps.Res) {
								result = append(result, line)
							}
						}
						ps.Ser = ser

						newPipe := script.Slice(result)
						return *env.NewNative(ps.Idx, newPipe, "script-pipe")
					default:
						return evaldo.MakeArgError(ps, 2, []env.Type{env.BlockType}, "filter-each")
					}
				default:
					return evaldo.MakeNativeArgError(ps, 1, []string{"script-pipe"}, "filter-each")
				}
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "filter-each")
			}
		},
	},
}
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 {
					return evaldo.MakeBuiltinError(ps, fmt.Sprintf("Error opening PostgreSQL: %v", err.Error()), "postgres-uri//Open")
				}

				if err := db.Ping(); err != nil {
					return evaldo.MakeBuiltinError(ps, fmt.Sprintf("Error connecting to PostgreSQL: %v", err.Error()), "postgres-uri//Open")
				}
				return *env.NewNative(ps.Idx, db, "Rye-psql")
			default:
				return evaldo.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 evaldo.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 evaldo.MakeBuiltinError(ps, "Sql string is empty.", "Rye-psql//Exec")
				}
			default:
				return evaldo.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 evaldo.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 evaldo.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 evaldo.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 evaldo.MakeBuiltinError(ps, "No data.", "Rye-psql//Query")
						}
						return *spr

					}
				} else {
					return evaldo.MakeBuiltinError(ps, "Empty SQL.", "Rye-psql//Query")
				}

			default:
				return evaldo.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 evaldo.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 evaldo.MakeBuiltinError(ps, "Empty SQL.", "Rye-psql//Show-SQL")
				}
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "Rye-psql//Show-SQL")
			}
		},
	},

	"Rye-psql//Close": {
		Argsn: 1,
		Doc:   "Closes the PostgreSQL database connection.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch db := arg0.(type) {
			case env.Native:
				psqlKind, _ := ps.Idx.GetIndex("Rye-psql")
				if db.Kind.Index != psqlKind {
					return evaldo.MakeBuiltinError(ps, "Expected PostgreSQL database connection.", "Rye-psql//Close")
				}
				sqlDB, ok := db.Value.(*sql.DB)
				if !ok {
					return evaldo.MakeBuiltinError(ps, "Invalid database connection.", "Rye-psql//Close")
				}
				err := sqlDB.Close()
				if err != nil {
					return evaldo.MakeBuiltinError(ps, fmt.Sprintf("Error closing database: %v", err.Error()), "Rye-psql//Close")
				}
				return *env.NewInteger(1)
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "Rye-psql//Close")
			}
		},
	},
}
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 evaldo.MakeError(ps, err.Error())
				}
				return *env.NewNative(ps.Idx, val, "regexp")
			default:
				return evaldo.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 evaldo.MakeError(ps, err.Error())
				}
				return *env.NewNative(ps.Idx, val, "regexp")
			default:
				return evaldo.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 evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "regexp//Is-match")
				}
			default:
				return evaldo.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 evaldo.MakeBuiltinError(ps, "No submatch.", "regexp//Submatch?")
					}
				default:
					return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "regexp//Submatch?")
				}
			default:
				return evaldo.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 evaldo.MakeBuiltinError(env1, "No results", "Submatches?")
				default:
					return evaldo.MakeError(env1, "Arg2 not Native")
				}
			default:
				return evaldo.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 evaldo.MakeBuiltinError(env1, "No results", "Submatches?")
				default:
					return evaldo.MakeError(env1, "Arg2 not Native")
				}
			default:
				return evaldo.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 evaldo.MakeBuiltinError(env1, "No results", "Find-all")
				default:
					return evaldo.MakeError(env1, "Arg2 not Native")
				}
			default:
				return evaldo.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 evaldo.MakeBuiltinError(ps, "No result", "Match?")
				default:
					return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "regexp//Match?")
				}
			default:
				return evaldo.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 evaldo.MakeArgError(ps, 3, []env.Type{env.StringType}, "regexp//Replace-all")
					}
				default:
					return evaldo.MakeArgError(ps, 2, []env.Type{env.StringType}, "regexp//Replace-all")
				}
			default:
				return evaldo.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
								}

								evaldo.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 evaldo.MakeError(ps, err.Error())
						}
						return arg0
					default:
						return evaldo.MakeArgError(ps, 3, []env.Type{env.StringType}, "smtpd//serve")
					}
				default:
					return evaldo.MakeArgError(ps, 2, []env.Type{env.FunctionType}, "smtpd//serve")
				}
			default:
				return evaldo.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, err := sql.Open("sqlite", str.GetPath())
				if err != nil {
					return evaldo.MakeBuiltinError(ps, fmt.Sprintf("Error opening SQLite: %v", err.Error()), "sqlite-uri//Open")
				}

				if err := db.Ping(); err != nil {
					return evaldo.MakeBuiltinError(ps, fmt.Sprintf("Error connecting to SQLite: %v", err.Error()), "sqlite-uri//Open")
				}
				return *env.NewNative(ps.Idx, db, "Rye-sqlite")
			default:
				return evaldo.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 evaldo.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 evaldo.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 evaldo.MakeBuiltinError(ps, err.Error(), "Rye-sqlite//Exec")
					}

					return arg0
				} else {
					return evaldo.MakeBuiltinError(ps, "sql string not found.", "Rye-sqlite//Exec")
				}
			default:
				return evaldo.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

			paramToAny := func(o env.Object) any {
				switch v := o.(type) {
				case env.Getword:
					val, _ := ps.Ctx.Get(v.Index)
					return sqlResultToJS(val)
				case env.Word:
					val, _ := ps.Ctx.Get(v.Index)
					return sqlResultToJS(val)
				case env.String:
					return v.Value
				case *env.String:
					return v.Value
				case env.Integer:
					return v.Value
				case *env.Integer:
					return v.Value
				case env.Decimal:
					return v.Value
				case *env.Decimal:
					return v.Value
				case env.Boolean:
					return v.Value
				case *env.Boolean:
					return v.Value
				case env.Void:
					return nil
				default:
					return sqlResultToJS(o)
				}
			}

			switch db1 := arg0.(type) {
			case env.Native:
				switch str := arg1.(type) {
				case env.Block:

					if str.Series.Len() > 0 {
						first := str.Series.Get(0)
						if s, ok := first.(env.String); ok {

							sqlstr = s.Value
							for i := 1; i < str.Series.Len(); i++ {
								p := str.Series.Get(i)

								if _, isComma := p.(env.Comma); isComma {
									continue
								}
								vals = append(vals, paramToAny(p))
							}
						} else {

							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
						}
					} else {

						return evaldo.MakeBuiltinError(ps, "Sql block is empty.", "Rye-sqlite//Query")
					}
				case env.String:
					sqlstr = str.Value
				default:
					return evaldo.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 evaldo.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 evaldo.MakeBuiltinError(ps, "Empty SQL.", "Rye-sqlite//Query")
				} else {
					return evaldo.MakeBuiltinError(ps, "Sql string not found.", "Rye-sqlite//Query")
				}
			default:
				return evaldo.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 evaldo.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 evaldo.MakeBuiltinError(ps, "Empty SQL.", "Rye-sqlite//Show-SQL")
				}
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "Rye-sqlite//Show-SQL")
			}
		},
	},

	"Rye-sqlite//Close": {
		Argsn: 1,
		Doc:   "Closes the SQLite database connection.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch db := arg0.(type) {
			case env.Native:
				sqliteKind, _ := ps.Idx.GetIndex("Rye-sqlite")
				if db.Kind.Index != sqliteKind {
					return evaldo.MakeBuiltinError(ps, "Expected SQLite database connection.", "Rye-sqlite//Close")
				}
				sqlDB, ok := db.Value.(*sql.DB)
				if !ok {
					return evaldo.MakeBuiltinError(ps, "Invalid database connection.", "Rye-sqlite//Close")
				}
				err := sqlDB.Close()
				if err != nil {
					return evaldo.MakeBuiltinError(ps, fmt.Sprintf("Error closing database: %v", err.Error()), "Rye-sqlite//Close")
				}
				return *env.NewInteger(1)
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "Rye-sqlite//Close")
			}
		},
	},
}
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 evaldo.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 evaldo.MakeArgError(ps, 1, []env.Type{env.BlockType}, "ry0-loop")
				}
			default:
				return evaldo.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 evaldo.MakeArgError(ps, 2, []env.Type{env.NativeType}, "dict->struct")
				}
			default:
				return evaldo.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 evaldo.MakeBuiltinError(ps, err.Error(), "dict->new-struct")
					}

					return *env.NewNative(ps.Idx, structPtr, nameObj.Value)
				default:
					return evaldo.MakeArgError(ps, 2, []env.Type{env.StringType}, "dict->new-struct")
				}
			default:
				return evaldo.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 evaldo.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 evaldo.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 evaldo.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 evaldo.MakeBuiltinError(ps, "Attribute '"+attrName+"' not found.", "rye-sxml-start//Attr?")
					default:
						return evaldo.MakeArgError(ps, 2, []env.Type{env.IntegerType, env.WordType, env.StringType}, "rye-sxml-start//Attr?")
					}
				default:
					return evaldo.MakeBuiltinError(ps, "Not xml-start element.", "rye-sxml-start//Attr?")
				}
			default:
				return evaldo.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 evaldo.MakeBuiltinError(ps, "Not xml-start element.", "rye-sxml-start//Attrs?")
				}
			default:
				return evaldo.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 evaldo.MakeBuiltinError(ps, "Not xml-start element.", "rye-sxml-start//Name?")
				}
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "rye-sxml-start//Name?")
			}
		},
	},
}
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 evaldo.MakeBuiltinError(ps, "Error in NewBotAPI function.", "new-telegram-bot")
				}
				return *env.NewNative(ps.Idx, bot, "telegram-bot")
			default:
				return evaldo.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)
						evaldo.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())

						}
						evaldo.CallFunctionArgsN(code, ps, nil, dict)
					}
					return env.NewInteger(1)

				default:
					return evaldo.MakeArgError(ps, 2, []env.Type{env.BlockType}, "telegram-bot//on-update")
				}
			default:
				return evaldo.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 evaldo.MakeError(ps, err.Error())
					}
					return arg0
				default:
					return evaldo.MakeArgError(ps, 2, []env.Type{env.NativeType}, "telegram-message//send")
				}
			default:
				return evaldo.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 evaldo.MakeArgError(ps, 2, []env.Type{env.NativeType}, "telegram-message//send")
				}
			default:
				return evaldo.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 evaldo.MakeArgError(ps, 2, []env.Type{env.StringType}, "new-telegram-message")
				}
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.IntegerType}, "new-telegram-message")
			}
		},
	},
}
View Source
var Builtins_term = map[string]*env.Builtin{

	"clear-line": {
		Argsn: 0,
		Doc:   "Clears the current terminal line.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			term.ClearLine()
			return *env.NewInteger(1)
		},
	},

	"cursor-up": {
		Argsn: 1,
		Doc:   "Moves the cursor up by the specified number 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 lines := arg0.(type) {
			case env.Integer:
				if lines.Value > 0 {
					fmt.Printf("\033[%dA", lines.Value)
				}
				return *env.NewInteger(1)
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.IntegerType}, "cursor-up")
			}
		},
	},

	"cursor-down": {
		Argsn: 1,
		Doc:   "Moves the cursor down by the specified number 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 lines := arg0.(type) {
			case env.Integer:
				if lines.Value > 0 {
					fmt.Printf("\033[%dB", lines.Value)
				}
				return *env.NewInteger(1)
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.IntegerType}, "cursor-down")
			}
		},
	},

	"clear-down": {
		Argsn: 0,
		Doc:   "Clears from the cursor position to the bottom of the screen.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			fmt.Print("\033[J")
			return *env.NewInteger(1)
		},
	},

	"clear-screen": {
		Argsn: 0,
		Doc:   "Clears the entire screen.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			fmt.Print("\033[2J\033[H")
			return *env.NewInteger(1)
		},
	},

	"hide-cursor": {
		Argsn: 0,
		Doc:   "Hides the terminal cursor.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			fmt.Print("\033[?25l")
			return *env.NewInteger(1)
		},
	},

	"show-cursor": {
		Argsn: 0,
		Doc:   "Shows the terminal cursor.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			fmt.Print("\033[?25h")
			return *env.NewInteger(1)
		},
	},

	"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 evaldo.MakeArgError(ps, 1, []env.Type{env.StringType}, "wrap")
			}
			wdth, ok := arg1.(env.Integer)
			if !ok {
				return evaldo.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 evaldo.MakeArgError(ps, 1, []env.Type{env.StringType}, "wrap\\words")
			}
			wdth, ok := arg1.(env.Integer)
			if !ok {
				return evaldo.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 evaldo.MakeArgError(ps, 1, []env.Type{env.StringType}, "indent")
			}
			wdth, ok := arg1.(env.Integer)
			if !ok {
				return evaldo.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 evaldo.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
						evaldo.Eval(ps)
						evaldo.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 evaldo.MakeArgError(ps, 1, []env.Type{env.StringType}, "spin-it")
				}
			default:
				return evaldo.MakeArgError(ps, 2, []env.Type{env.BlockType}, "spin-it")
			}
		},
	},

	"pane": {
		Argsn: 2,
		Doc:   "Displays content in a bordered pane with a title header.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			title, ok1 := arg0.(env.String)
			if !ok1 {
				return evaldo.MakeArgError(ps, 1, []env.Type{env.StringType}, "pane")
			}
			content, ok2 := arg1.(env.String)
			if !ok2 {
				return evaldo.MakeArgError(ps, 2, []env.Type{env.StringType}, "pane")
			}

			lines := strings.Split(content.Value, "\n")

			maxContentWidth := 0
			for _, line := range lines {
				if len(line) > maxContentWidth {
					maxContentWidth = len(line)
				}
			}

			titleWidth := len(title.Value) + 4

			paneWidth := maxContentWidth + 2
			if titleWidth > paneWidth {
				paneWidth = titleWidth
			}
			if paneWidth < 10 {
				paneWidth = 10
			}

			titlePadding := paneWidth - len(title.Value) - 4
			leftPadding := titlePadding / 2
			rightPadding := titlePadding - leftPadding

			topBorder := "╭" + strings.Repeat("─", leftPadding) + "─ " + title.Value + " ─" + strings.Repeat("─", rightPadding) + "╮"
			fmt.Println(topBorder)

			for _, line := range lines {
				contentPadding := paneWidth - len(line)
				rightContentPadding := contentPadding
				fmt.Printf("│%s%s│\n", line, strings.Repeat(" ", rightContentPadding))
			}

			bottomBorder := "╰" + strings.Repeat("─", paneWidth) + "╯"
			fmt.Println(bottomBorder)

			return *env.NewInteger(1)
		},
	},
}
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_tui = map[string]*env.Builtin{

	"text": {
		Argsn: 1,
		Doc:   "Creates a text widget (no wrapping). Returns { 'text { } content }",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return tuiMakeWidget(ps, "text", *env.NewDict(nil), arg0)
		},
	},

	"text\\": {
		Argsn: 2,
		Doc:   "Creates a styled text widget. Returns { 'text { styles } content }",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			var styles env.Dict
			switch s := arg0.(type) {
			case env.Dict:
				styles = s
			case env.Word:

				styles = *env.NewDict(map[string]any{"_style": ps.Idx.GetWord(s.Index)})
			default:
				styles = *env.NewDict(nil)
			}
			return tuiMakeWidget(ps, "text", styles, arg1)
		},
	},

	"block": {
		Argsn: 1,
		Doc:   "Creates a text block widget that wraps. Returns { 'block { } content }",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return tuiMakeWidget(ps, "block", *env.NewDict(nil), arg0)
		},
	},

	"block\\": {
		Argsn: 2,
		Doc:   "Creates a styled text block widget. Returns { 'block { styles } content }",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			var styles env.Dict
			switch s := arg0.(type) {
			case env.Dict:
				styles = s
			default:
				styles = *env.NewDict(nil)
			}
			return tuiMakeWidget(ps, "block", styles, arg1)
		},
	},

	"hline": {
		Argsn: 0,
		Doc:   "Creates a horizontal line widget. Returns { 'hline { } \"─\" }",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return tuiMakeWidget(ps, "hline", *env.NewDict(nil), *env.NewString("─"))
		},
	},

	"hline\\char": {
		Argsn: 1,
		Doc:   "Creates a horizontal line with custom character. Returns { 'hline { } char }",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return tuiMakeWidget(ps, "hline", *env.NewDict(nil), arg0)
		},
	},

	"vspace": {
		Argsn: 1,
		Doc:   "Creates a vertical spacer widget. Returns { 'vspace { } height }",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			return tuiMakeWidget(ps, "vspace", *env.NewDict(nil), arg0)
		},
	},

	"vbox": {
		Argsn: 1,
		Doc:   "Creates a vertical box container. Evaluates the block and collects widget results. Returns { 'vbox { } children }",
		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:
				// Evaluate the block to get widget children
				// Each expression in the block should return a widget block
				var children []env.Object

				psTemp := *ps
				psTemp.Ser = block.Series
				psTemp.Ser.Reset()

				for psTemp.Ser.Pos() < psTemp.Ser.Len() {
					evaldo.EvalExpression(&psTemp, nil, false, false, false, false)
					if psTemp.ErrorFlag || psTemp.FailureFlag {
						return psTemp.Res
					}
					if psTemp.Res != nil {

						if _, ok := psTemp.Res.(env.Block); ok {
							children = append(children, psTemp.Res)
						}
					}
				}

				childrenBlock := *env.NewBlock(*env.NewTSeries(children))
				return tuiMakeWidget(ps, "vbox", *env.NewDict(nil), childrenBlock)
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.BlockType}, "vbox")
			}
		},
	},

	"vbox\\": {
		Argsn: 2,
		Doc:   "Creates a styled vertical box container. Supports background, color, padding, bold.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			styles, ok := arg0.(env.Dict)
			if !ok {
				return evaldo.MakeArgError(ps, 1, []env.Type{env.DictType}, "vbox\\")
			}

			switch block := arg1.(type) {
			case env.Block:
				// Evaluate the block to get widget children
				var children []env.Object

				psTemp := *ps
				psTemp.Ser = block.Series
				psTemp.Ser.Reset()

				for psTemp.Ser.Pos() < psTemp.Ser.Len() {
					evaldo.EvalExpression(&psTemp, nil, false, false, false, false)
					if psTemp.ErrorFlag || psTemp.FailureFlag {
						return psTemp.Res
					}
					if psTemp.Res != nil {
						if _, ok := psTemp.Res.(env.Block); ok {
							children = append(children, psTemp.Res)
						}
					}
				}

				childrenBlock := *env.NewBlock(*env.NewTSeries(children))
				return tuiMakeWidget(ps, "vbox", styles, childrenBlock)
			default:
				return evaldo.MakeArgError(ps, 2, []env.Type{env.BlockType}, "vbox\\")
			}
		},
	},

	"select": {
		Argsn: 1,
		Doc:   "Creates a selection list widget. Returns { 'select { selected: 0 } items }",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			styles := env.NewDict(map[string]any{"selected": *env.NewInteger(0)})
			return tuiMakeWidget(ps, "select", *styles, arg0)
		},
	},

	"select\\selected": {
		Argsn: 2,
		Doc:   "Creates a selection list with initial selection. Returns { 'select { selected: n } items }",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			idx, ok := arg0.(env.Integer)
			if !ok {
				return evaldo.MakeArgError(ps, 1, []env.Type{env.IntegerType}, "select\\selected")
			}
			styles := env.NewDict(map[string]any{"selected": idx})
			return tuiMakeWidget(ps, "select", *styles, arg1)
		},
	},

	"tabs": {
		Argsn: 1,
		Doc:   "Creates a horizontal tabs widget. Returns { 'tabs { selected: 0 } items }",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			styles := env.NewDict(map[string]any{"selected": *env.NewInteger(0)})
			return tuiMakeWidget(ps, "tabs", *styles, arg0)
		},
	},

	"tabs\\selected": {
		Argsn: 2,
		Doc:   "Creates tabs with initial selection. Returns { 'tabs { selected: n } items }",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			idx, ok := arg0.(env.Integer)
			if !ok {
				return evaldo.MakeArgError(ps, 1, []env.Type{env.IntegerType}, "tabs\\selected")
			}
			styles := env.NewDict(map[string]any{"selected": idx})
			return tuiMakeWidget(ps, "tabs", *styles, arg1)
		},
	},

	"input": {
		Argsn: 1,
		Doc:   "Creates a managed text input widget with built-in key handling. Returns native TuiInput.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			placeholder, ok := arg0.(env.String)
			if !ok {
				return evaldo.MakeArgError(ps, 1, []env.Type{env.StringType}, "input")
			}
			inp := NewTuiInput(placeholder.Value)
			inp.ps = ps
			return *env.NewNative(ps.Idx, inp, "tui-input")
		},
	},

	"field": {
		Argsn: 1,
		Doc:   "Creates an unmanaged text field widget (pure data). Handle keys manually. Returns { 'field { } { value: '' placeholder: ... } }",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			placeholder, ok := arg0.(env.String)
			if !ok {
				return evaldo.MakeArgError(ps, 1, []env.Type{env.StringType}, "field")
			}
			content := env.NewDict(map[string]any{
				"value":       *env.NewString(""),
				"placeholder": placeholder,
				"cursor":      *env.NewInteger(0),
			})
			return tuiMakeWidget(ps, "field", *env.NewDict(nil), *content)
		},
	},

	"field\\value": {
		Argsn: 2,
		Doc:   "Creates an unmanaged text field with initial value.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			value, ok := arg0.(env.String)
			if !ok {
				return evaldo.MakeArgError(ps, 1, []env.Type{env.StringType}, "field\\value")
			}
			placeholder, ok := arg1.(env.String)
			if !ok {
				return evaldo.MakeArgError(ps, 2, []env.Type{env.StringType}, "field\\value")
			}
			content := env.NewDict(map[string]any{
				"value":       value,
				"placeholder": placeholder,
				"cursor":      *env.NewInteger(int64(len(value.Value))),
			})
			return tuiMakeWidget(ps, "field", *env.NewDict(nil), *content)
		},
	},

	"tui-input//On-submit": {
		Argsn: 2,
		Doc:   "Sets the callback function called when Enter is pressed. Callback receives (value).",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch inp := arg0.(type) {
			case env.Native:
				if tinp, ok := inp.Value.(*TuiInput); ok {
					tinp.onSubmit = arg1
					tinp.ps = ps
					return arg0
				}
				return evaldo.MakeBuiltinError(ps, "Expected TuiInput", "tui-input//On-submit")
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "tui-input//On-submit")
			}
		},
	},

	"tui-input//On-change": {
		Argsn: 2,
		Doc:   "Sets the callback function called when value changes. Callback receives (value).",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch inp := arg0.(type) {
			case env.Native:
				if tinp, ok := inp.Value.(*TuiInput); ok {
					tinp.onChange = arg1
					tinp.ps = ps
					return arg0
				}
				return evaldo.MakeBuiltinError(ps, "Expected TuiInput", "tui-input//On-change")
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "tui-input//On-change")
			}
		},
	},

	"tui-input//Value?": {
		Argsn: 1,
		Doc:   "Returns the current value 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 inp := arg0.(type) {
			case env.Native:
				if tinp, ok := inp.Value.(*TuiInput); ok {
					return *env.NewString(tinp.GetValue())
				}
				return evaldo.MakeBuiltinError(ps, "Expected TuiInput", "tui-input//Value?")
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "tui-input//Value?")
			}
		},
	},

	"tui-input//Set-value": {
		Argsn: 2,
		Doc:   "Sets the value 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 inp := arg0.(type) {
			case env.Native:
				if tinp, ok := inp.Value.(*TuiInput); ok {
					if val, ok := arg1.(env.String); ok {
						tinp.SetValue(val.Value)
						return arg0
					}
					return evaldo.MakeArgError(ps, 2, []env.Type{env.StringType}, "tui-input//Set-value")
				}
				return evaldo.MakeBuiltinError(ps, "Expected TuiInput", "tui-input//Set-value")
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "tui-input//Set-value")
			}
		},
	},

	"tui-input//Focus": {
		Argsn: 2,
		Doc:   "Sets the focus state of the input (1 = focused, 0 = not focused).",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch inp := arg0.(type) {
			case env.Native:
				if tinp, ok := inp.Value.(*TuiInput); ok {
					if val, ok := arg1.(env.Integer); ok {
						tinp.focused = val.Value != 0
						return arg0
					}
					return evaldo.MakeArgError(ps, 2, []env.Type{env.IntegerType}, "tui-input//Focus")
				}
				return evaldo.MakeBuiltinError(ps, "Expected TuiInput", "tui-input//Focus")
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "tui-input//Focus")
			}
		},
	},

	"tui-input//Width": {
		Argsn: 2,
		Doc:   "Sets the display width 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 inp := arg0.(type) {
			case env.Native:
				if tinp, ok := inp.Value.(*TuiInput); ok {
					if val, ok := arg1.(env.Integer); ok {
						tinp.width = int(val.Value)
						return arg0
					}
					return evaldo.MakeArgError(ps, 2, []env.Type{env.IntegerType}, "tui-input//Width")
				}
				return evaldo.MakeBuiltinError(ps, "Expected TuiInput", "tui-input//Width")
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "tui-input//Width")
			}
		},
	},

	"tui-input//Handle-key": {
		Argsn: 2,
		Doc:   "Processes a key event. Returns 1 if handled, 0 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 inp := arg0.(type) {
			case env.Native:
				if tinp, ok := inp.Value.(*TuiInput); ok {
					if key, ok := arg1.(env.String); ok {
						handled := tinp.HandleKey(key.Value, ps)
						if handled {
							return *env.NewInteger(1)
						}
						return *env.NewInteger(0)
					}
					return evaldo.MakeArgError(ps, 2, []env.Type{env.StringType}, "tui-input//Handle-key")
				}
				return evaldo.MakeBuiltinError(ps, "Expected TuiInput", "tui-input//Handle-key")
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "tui-input//Handle-key")
			}
		},
	},

	"tui-input//Widget": {
		Argsn: 1,
		Doc:   "Returns the widget block for rendering this input.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch inp := arg0.(type) {
			case env.Native:
				if tinp, ok := inp.Value.(*TuiInput); ok {
					tinp.ps = ps
					return tinp.Render()
				}
				return evaldo.MakeBuiltinError(ps, "Expected TuiInput", "tui-input//Widget")
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "tui-input//Widget")
			}
		},
	},

	"render": {
		Argsn: 1,
		Doc:   "Renders a widget tree to the terminal and returns number of lines.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			widget, ok := arg0.(env.Block)
			if !ok {
				return evaldo.MakeArgError(ps, 1, []env.Type{env.BlockType}, "render")
			}

			width := term.GetTerminalColumns()
			if width < 20 {
				width = 80
			}

			theme := *env.NewDict(nil)
			lines := tuiRenderWidget(ps, widget, width, theme)

			for _, line := range lines {
				fmt.Println(line)
			}

			return *env.NewInteger(int64(len(lines)))
		},
	},

	"render\\theme": {
		Argsn: 2,
		Doc:   "Renders a widget tree with a theme.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			theme, ok := arg0.(env.Dict)
			if !ok {
				return evaldo.MakeArgError(ps, 1, []env.Type{env.DictType}, "render\\theme")
			}
			widget, ok := arg1.(env.Block)
			if !ok {
				return evaldo.MakeArgError(ps, 2, []env.Type{env.BlockType}, "render\\theme")
			}

			width := term.GetTerminalColumns()
			if width < 20 {
				width = 80
			}

			lines := tuiRenderWidget(ps, widget, width, theme)

			for _, line := range lines {
				fmt.Println(line)
			}

			return *env.NewInteger(int64(len(lines)))
		},
	},

	"render\\to-string": {
		Argsn: 2,
		Doc:   "Renders a widget tree to a string.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			widget, ok := arg0.(env.Block)
			if !ok {
				return evaldo.MakeArgError(ps, 1, []env.Type{env.BlockType}, "render\\to-string")
			}
			width, ok := arg1.(env.Integer)
			if !ok {
				return evaldo.MakeArgError(ps, 2, []env.Type{env.IntegerType}, "render\\to-string")
			}

			theme := *env.NewDict(nil)
			lines := tuiRenderWidget(ps, widget, int(width.Value), theme)

			return *env.NewString(strings.Join(lines, "\n"))
		},
	},

	"app": {
		Argsn: 1,
		Doc:   "Creates a new TUI app with the given theme.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			theme, ok := arg0.(env.Dict)
			if !ok {
				return evaldo.MakeArgError(ps, 1, []env.Type{env.DictType}, "app")
			}
			app := NewTuiApp(theme)
			return *env.NewNative(ps.Idx, app, "tui-app")
		},
	},

	"tui-app//View": {
		Argsn: 2,
		Doc:   "Sets the view for the TUI app. Can be a widget block or a function that returns one.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			native, ok := arg0.(env.Native)
			if !ok {
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "tui-app//View")
			}
			app, ok := native.Value.(*TuiApp)
			if !ok {
				return evaldo.MakeBuiltinError(ps, "Expected TuiApp", "tui-app//View")
			}
			app.SetView(arg1)
			return arg0
		},
	},

	"tui-app//State": {
		Argsn: 2,
		Doc:   "Sets the state for the TUI app.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			native, ok := arg0.(env.Native)
			if !ok {
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "tui-app//State")
			}
			app, ok := native.Value.(*TuiApp)
			if !ok {
				return evaldo.MakeBuiltinError(ps, "Expected TuiApp", "tui-app//State")
			}
			state, ok := arg1.(env.Dict)
			if !ok {
				return evaldo.MakeArgError(ps, 2, []env.Type{env.DictType}, "tui-app//State")
			}
			app.SetState(state)
			return arg0
		},
	},

	"tui-app//State?": {
		Argsn: 1,
		Doc:   "Gets the current state of the TUI app.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			native, ok := arg0.(env.Native)
			if !ok {
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "tui-app//State?")
			}
			app, ok := native.Value.(*TuiApp)
			if !ok {
				return evaldo.MakeBuiltinError(ps, "Expected TuiApp", "tui-app//State?")
			}
			return app.GetState()
		},
	},

	"tui-app//Update": {
		Argsn: 2,
		Doc:   "Updates the state and re-renders.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			native, ok := arg0.(env.Native)
			if !ok {
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "tui-app//Update")
			}
			app, ok := native.Value.(*TuiApp)
			if !ok {
				return evaldo.MakeBuiltinError(ps, "Expected TuiApp", "tui-app//Update")
			}
			updates, ok := arg1.(env.Dict)
			if !ok {
				return evaldo.MakeArgError(ps, 2, []env.Type{env.DictType}, "tui-app//Update")
			}
			app.Update(updates)
			return arg0
		},
	},

	"tui-app//On-key": {
		Argsn: 3,
		Doc:   "Registers a handler for a specific key. Key can be 'up', 'down', 'enter', 'escape', 'q', etc.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			native, ok := arg0.(env.Native)
			if !ok {
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "tui-app//On-key")
			}
			app, ok := native.Value.(*TuiApp)
			if !ok {
				return evaldo.MakeBuiltinError(ps, "Expected TuiApp", "tui-app//On-key")
			}
			key, ok := arg1.(env.String)
			if !ok {
				return evaldo.MakeArgError(ps, 2, []env.Type{env.StringType}, "tui-app//On-key")
			}
			switch arg2.(type) {
			case env.Function, env.Block:
				app.OnKey(key.Value, arg2)
				return arg0
			default:
				return evaldo.MakeArgError(ps, 3, []env.Type{env.FunctionType, env.BlockType}, "tui-app//On-key")
			}
		},
	},

	"tui-app//On-keys": {
		Argsn: 2,
		Doc:   "Registers a handler for ALL keys. Function receives (state, key). Use switch on key to handle different keys.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			native, ok := arg0.(env.Native)
			if !ok {
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "tui-app//On-keys")
			}
			app, ok := native.Value.(*TuiApp)
			if !ok {
				return evaldo.MakeBuiltinError(ps, "Expected TuiApp", "tui-app//On-keys")
			}
			switch arg1.(type) {
			case env.Function, env.Block:
				app.OnKeys(arg1)
				return arg0
			default:
				return evaldo.MakeArgError(ps, 2, []env.Type{env.FunctionType, env.BlockType}, "tui-app//On-keys")
			}
		},
	},

	"tui-app//Focus": {
		Argsn: 2,
		Doc:   "Sets the focused input widget. Keys are routed to focused input first.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			native, ok := arg0.(env.Native)
			if !ok {
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "tui-app//Focus")
			}
			app, ok := native.Value.(*TuiApp)
			if !ok {
				return evaldo.MakeBuiltinError(ps, "Expected TuiApp", "tui-app//Focus")
			}

			if i, ok := arg1.(env.Integer); ok && i.Value == 0 {
				app.mu.Lock()
				app.focusedInput = nil
				app.mu.Unlock()
				return arg0
			}

			inputNative, ok := arg1.(env.Native)
			if !ok {
				return evaldo.MakeArgError(ps, 2, []env.Type{env.NativeType}, "tui-app//Focus")
			}
			inp, ok := inputNative.Value.(*TuiInput)
			if !ok {
				return evaldo.MakeBuiltinError(ps, "Expected TuiInput", "tui-app//Focus")
			}

			app.mu.Lock()
			app.focusedInput = inp
			inp.focused = true
			inp.ps = ps
			app.mu.Unlock()
			return arg0
		},
	},

	"tui-app//Start": {
		Argsn: 1,
		Doc:   "Starts the TUI app, entering raw mode and beginning the event loop.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			native, ok := arg0.(env.Native)
			if !ok {
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "tui-app//Start")
			}
			app, ok := native.Value.(*TuiApp)
			if !ok {
				return evaldo.MakeBuiltinError(ps, "Expected TuiApp", "tui-app//Start")
			}
			err := app.Start(ps)
			if err != nil {
				return evaldo.MakeBuiltinError(ps, err.Error(), "tui-app//Start")
			}
			return arg0
		},
	},

	"tui-app//Stop": {
		Argsn: 1,
		Doc:   "Stops the TUI app.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			native, ok := arg0.(env.Native)
			if !ok {
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "tui-app//Stop")
			}
			app, ok := native.Value.(*TuiApp)
			if !ok {
				return evaldo.MakeBuiltinError(ps, "Expected TuiApp", "tui-app//Stop")
			}
			app.Stop()
			return arg0
		},
	},

	"tui-app//Wait": {
		Argsn: 1,
		Doc:   "Blocks until the TUI app stops.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			native, ok := arg0.(env.Native)
			if !ok {
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "tui-app//Wait")
			}
			app, ok := native.Value.(*TuiApp)
			if !ok {
				return evaldo.MakeBuiltinError(ps, "Expected TuiApp", "tui-app//Wait")
			}
			app.Wait()
			return arg0
		},
	},

	"tui-app//Redraw": {
		Argsn: 1,
		Doc:   "Forces a re-render of the TUI app.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			native, ok := arg0.(env.Native)
			if !ok {
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "tui-app//Redraw")
			}
			app, ok := native.Value.(*TuiApp)
			if !ok {
				return evaldo.MakeBuiltinError(ps, "Expected TuiApp", "tui-app//Redraw")
			}

			app.mu.Lock()
			if app.ps == nil {
				app.ps = ps
			}
			app.mu.Unlock()
			app.Render()
			return arg0
		},
	},

	"tui-app//Send": {
		Argsn: 2,
		Doc:   "Sends a message into the app's event loop. Thread-safe, can be called from goroutines. The message is handled by the on-message handler.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			native, ok := arg0.(env.Native)
			if !ok {
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "tui-app//Send")
			}
			app, ok := native.Value.(*TuiApp)
			if !ok {
				return evaldo.MakeBuiltinError(ps, "Expected TuiApp", "tui-app//Send")
			}

			select {
			case app.msgChan <- arg1:

			default:

			}
			return arg0
		},
	},

	"tui-app//On-message": {
		Argsn: 2,
		Doc:   "Registers a handler for async messages sent via Send. Function receives (state, msg). Return a dict to update state.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			native, ok := arg0.(env.Native)
			if !ok {
				return evaldo.MakeArgError(ps, 1, []env.Type{env.NativeType}, "tui-app//On-message")
			}
			app, ok := native.Value.(*TuiApp)
			if !ok {
				return evaldo.MakeBuiltinError(ps, "Expected TuiApp", "tui-app//On-message")
			}
			switch arg1.(type) {
			case env.Function:
				app.mu.Lock()
				app.msgHandler = arg1
				app.mu.Unlock()
				return arg0
			default:
				return evaldo.MakeArgError(ps, 2, []env.Type{env.FunctionType}, "tui-app//On-message")
			}
		},
	},

	"style": {
		Argsn: 1,
		Doc:   "Creates a style dict from a block. Example: tui-style { bold: 1 color: 'blue }",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch b := arg0.(type) {
			case env.Block:

				data := make(map[string]any)
				for i := 0; i < b.Series.Len(); i += 2 {
					if i+1 >= b.Series.Len() {
						break
					}
					key := b.Series.Get(i)
					val := b.Series.Get(i + 1)

					var keyStr string
					switch k := key.(type) {
					case env.Tagword:
						keyStr = ps.Idx.GetWord(k.Index)
					case env.Word:
						keyStr = ps.Idx.GetWord(k.Index)
					case env.String:
						keyStr = k.Value
					default:
						continue
					}

					data[keyStr] = val
				}
				return *env.NewDict(data)
			case env.Dict:
				return b
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.BlockType, env.DictType}, "style")
			}
		},
	},

	"theme": {
		Argsn: 1,
		Doc:   "Creates a theme dict. Example: tui-theme { text { color: 'blue } hline { color: 'gray } }",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch b := arg0.(type) {
			case env.Block:
				data := make(map[string]any)
				for i := 0; i < b.Series.Len(); i += 2 {
					if i+1 >= b.Series.Len() {
						break
					}
					key := b.Series.Get(i)
					val := b.Series.Get(i + 1)

					var keyStr string
					switch k := key.(type) {
					case env.Tagword:
						keyStr = ps.Idx.GetWord(k.Index)
					case env.Word:
						keyStr = ps.Idx.GetWord(k.Index)
					case env.String:
						keyStr = k.Value
					default:
						continue
					}

					switch v := val.(type) {
					case env.Block:

						styleData := make(map[string]any)
						for j := 0; j < v.Series.Len(); j += 2 {
							if j+1 >= v.Series.Len() {
								break
							}
							sk := v.Series.Get(j)
							sv := v.Series.Get(j + 1)

							var skStr string
							switch skk := sk.(type) {
							case env.Tagword:
								skStr = ps.Idx.GetWord(skk.Index)
							case env.Word:
								skStr = ps.Idx.GetWord(skk.Index)
							case env.String:
								skStr = skk.Value
							default:
								continue
							}
							styleData[skStr] = sv
						}
						data[keyStr] = *env.NewDict(styleData)
					case env.Dict:
						data[keyStr] = v
					}
				}
				return *env.NewDict(data)
			case env.Dict:
				return b
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.BlockType, env.DictType}, "theme")
			}
		},
	},
}
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 evaldo.MakeError(ps, err.Error())
				}
				return *env.NewVector(val)
			default:
				return evaldo.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 evaldo.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 evaldo.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 evaldo.MakeBuiltinError(ps, err.Error(), "cosine-similarity?")
					}
					return *env.NewDecimal(res)
				default:
					return evaldo.MakeArgError(ps, 2, []env.Type{env.VectorType}, "cosine-similarity?")
				}
			default:
				return evaldo.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 evaldo.MakeError(ps, err.Error())
					}
					return *env.NewDecimal(res)
				default:
					return evaldo.MakeArgError(ps, 2, []env.Type{env.VectorType}, "correlation")
				}
			default:
				return evaldo.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 evaldo.MakeError(ps, err.Error())
					}
					return *env.NewDecimal(res)
				default:
					return evaldo.MakeArgError(ps, 2, []env.Type{env.VectorType}, "dot-product")
				}
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.VectorType}, "dot-product")
			}
		},
	},

	"euclidean-distance": {
		Argsn: 2,
		Doc:   "Calculates the Euclidean distance between two vectors. Useful for K-Means clustering.",
		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:
					if len(v1.Value) != len(v2.Value) {
						return evaldo.MakeBuiltinError(ps, "Vectors must have the same length", "euclidean-distance")
					}
					var sum float64
					for i := 0; i < len(v1.Value); i++ {
						diff := v1.Value[i] - v2.Value[i]
						sum += diff * diff
					}
					return *env.NewDecimal(sqrtFloat64(sum))
				default:
					return evaldo.MakeArgError(ps, 2, []env.Type{env.VectorType}, "euclidean-distance")
				}
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.VectorType}, "euclidean-distance")
			}
		},
	},

	"mean-vectors": {
		Argsn: 1,
		Doc:   "Calculates the element-wise mean of multiple vectors. Useful for creating 'Master Anchors'.",
		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:
				if block.Series.Len() == 0 {
					return evaldo.MakeBuiltinError(ps, "Block must contain at least one vector", "mean-vectors")
				}

				first := block.Series.Get(0)
				firstVec, ok := first.(env.Vector)
				if !ok {
					return evaldo.MakeBuiltinError(ps, "Block must contain only vectors", "mean-vectors")
				}
				vecLen := len(firstVec.Value)
				result := make(govector.Vector, vecLen)

				for i := 0; i < block.Series.Len(); i++ {
					item := block.Series.Get(i)
					vec, ok := item.(env.Vector)
					if !ok {
						return evaldo.MakeBuiltinError(ps, "Block must contain only vectors", "mean-vectors")
					}
					if len(vec.Value) != vecLen {
						return evaldo.MakeBuiltinError(ps, "All vectors must have the same length", "mean-vectors")
					}
					for j := 0; j < vecLen; j++ {
						result[j] += vec.Value[j]
					}
				}

				count := float64(block.Series.Len())
				for i := 0; i < vecLen; i++ {
					result[i] /= count
				}
				return *env.NewVector(result)
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.BlockType}, "mean-vectors")
			}
		},
	},

	"unit-vector": {
		Argsn: 1,
		Doc:   "Returns a new normalized vector (length = 1). Essential for consistent dot products and overlays.",
		Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
			switch v := arg0.(type) {
			case env.Vector:
				norm := govector.Norm(v.Value, 2.0)
				if norm == 0 {
					return evaldo.MakeBuiltinError(ps, "Cannot normalize zero vector", "Vector//unit")
				}
				result := make(govector.Vector, len(v.Value))
				for i := 0; i < len(v.Value); i++ {
					result[i] = v.Value[i] / norm
				}
				return *env.NewVector(result)
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.VectorType}, "Vector//unit")
			}
		},
	},

	"project-vector": {
		Argsn: 2,
		Doc:   "Projects vector onto another vector. Answers: 'How much of this vector is in the direction of another?'",
		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:
					if len(v1.Value) != len(v2.Value) {
						return evaldo.MakeBuiltinError(ps, "Vectors must have the same length", "Vector//project")
					}

					dotAB, err := govector.DotProduct(v1.Value, v2.Value)
					if err != nil {
						return evaldo.MakeBuiltinError(ps, err.Error(), "Vector//project")
					}
					dotBB, err := govector.DotProduct(v2.Value, v2.Value)
					if err != nil {
						return evaldo.MakeBuiltinError(ps, err.Error(), "Vector//project")
					}
					if dotBB == 0 {
						return evaldo.MakeBuiltinError(ps, "Cannot project onto zero vector", "Vector//project")
					}
					scalar := dotAB / dotBB
					result := make(govector.Vector, len(v2.Value))
					for i := 0; i < len(v2.Value); i++ {
						result[i] = v2.Value[i] * scalar
					}
					return *env.NewVector(result)
				default:
					return evaldo.MakeArgError(ps, 2, []env.Type{env.VectorType}, "Vector//project")
				}
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.VectorType}, "Vector//project")
			}
		},
	},

	"reject-vector": {
		Argsn: 2,
		Doc:   "Removes projection from vector. Use this to 'subtract' a concept direction from 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 v1 := arg0.(type) {
			case env.Vector:
				switch v2 := arg1.(type) {
				case env.Vector:
					if len(v1.Value) != len(v2.Value) {
						return evaldo.MakeBuiltinError(ps, "Vectors must have the same length", "Vector//reject")
					}

					dotAB, err := govector.DotProduct(v1.Value, v2.Value)
					if err != nil {
						return evaldo.MakeBuiltinError(ps, err.Error(), "Vector//reject")
					}
					dotBB, err := govector.DotProduct(v2.Value, v2.Value)
					if err != nil {
						return evaldo.MakeBuiltinError(ps, err.Error(), "Vector//reject")
					}
					if dotBB == 0 {

						return v1
					}
					scalar := dotAB / dotBB
					result := make(govector.Vector, len(v1.Value))
					for i := 0; i < len(v1.Value); i++ {
						result[i] = v1.Value[i] - (v2.Value[i] * scalar)
					}
					return *env.NewVector(result)
				default:
					return evaldo.MakeArgError(ps, 2, []env.Type{env.VectorType}, "Vector//reject")
				}
			default:
				return evaldo.MakeArgError(ps, 1, []env.Type{env.VectorType}, "Vector//reject")
			}
		},
	},
}

Functions

func ArrayFloat32FromSeries

func ArrayFloat32FromSeries(block env.TSeries) []float32

func BlockToJSON

func BlockToJSON(block env.Block) string

BlockToJSON converts a Block to JSON array format.

func BlockToJSONWithIdxs

func BlockToJSONWithIdxs(block env.Block, idxs *env.Idxs) string

BlockToJSONWithIdxs converts a Block to JSON array format with Idxs for context support.

func BsonToValue_Map

func BsonToValue_Map(ps *env.ProgramState, val any, typ string, meta any, topLevel bool) env.Object

func BsonToValue_Val

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 BuiParseArgs

func BuiParseArgs(es *env.ProgramState, args env.Object, specBlock env.Object) env.Object

BuiParseArgs is the main builtin function for parse-args

func ContextToJSON

func ContextToJSON(ctx *env.RyeCtx, idxs *env.Idxs) string

ContextToJSON converts a RyeCtx to JSON object format.

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 DialectMath

func DialectMath(env1 *env.ProgramState, arg0 env.Object) env.Object

func DictToJSON

func DictToJSON(dict env.Dict) string

DictToJSON converts a Dict to JSON object format.

func DictToJSONWithIdxs

func DictToJSONWithIdxs(dict env.Dict, idxs *env.Idxs) string

DictToJSONWithIdxs converts a Dict to JSON object format with Idxs for context support.

func EmptyRM

func EmptyRM() env.Dict

EmptyRM creates an empty Dict

func EscapeJson

func EscapeJson(val string) string

func EvalBlockInPersistentCtx

func EvalBlockInPersistentCtx(ps *env.ProgramState, pctx *PersistentCtx)

EvalBlockInPersistentCtx evaluates a block within a PersistentCtx, ensuring persistence

func Eyr_CallBuiltin

func Eyr_CallBuiltin(bi env.Builtin, ps *env.ProgramState, arg0_ env.Object, toLeft bool) *env.ProgramState

func Eyr_CallBuiltinPipe

func Eyr_CallBuiltinPipe(bi env.Builtin, ps *env.ProgramState, arg0_ env.Object) *env.ProgramState

func Eyr_CallFunction

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

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

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 FileExists

func FileExists(filePath string) int

func ListToJSON

func ListToJSON(list env.List) string

ListToJSON converts a List to JSON array format.

func ListToJSONWithIdxs

func ListToJSONWithIdxs(list env.List, idxs *env.Idxs) string

ListToJSONWithIdxs converts a List to JSON array format with Idxs for context support.

func Math_EvalBlock

func Math_EvalBlock(es *env.ProgramState) []env.Object

func RegisterBatteries

func RegisterBatteries(ps *env.ProgramState)

RegisterBatteries registers all battery (non-base) builtins into the program state. Call this after evaldo.RegisterBuiltins to get the full standard set of Rye builtins.

func RyeToJSON

func RyeToJSON(res any) string

func RyeToJSONLines

func RyeToJSONLines(res any) string

func RyeToJSONWithIdxs

func RyeToJSONWithIdxs(res any, idxs *env.Idxs) string

func SQL_EvalBlock

func SQL_EvalBlock(es *env.ProgramState, mode int, values []any) (*env.ProgramState, []any)

SQL_EvalBlock evaluates a block of SQL expressions and builds a SQL string

func SQL_EvalExpression

func SQL_EvalExpression(es *env.ProgramState, vals []any, mode int) (*env.ProgramState, string, []any)

SQL_EvalExpression evaluates a single SQL expression and converts Rye objects to SQL syntax mode 1: SQLite (uses ? placeholders), mode 2: PostgreSQL (uses $1, $2, etc. placeholders)

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

func TableRowToJSON(row env.TableRow) string

TableRowToJSON converts a TableRow to JSON object format.

func TableRowToJSONWithIdxs

func TableRowToJSONWithIdxs(row env.TableRow, idxs *env.Idxs) string

TableRowToJSONWithIdxs converts a TableRow to JSON object format with Idxs for context support.

func TableToJSON

func TableToJSON(s env.Table) string

TableToJSON converts a Table to JSON array format.

func TableToJSONLines

func TableToJSONLines(s env.Table) string

func TableToJSONWithIdxs

func TableToJSONWithIdxs(s env.Table, idxs *env.Idxs) string

TableToJSONWithIdxs converts a Table to JSON array format with Idxs for context support.

func TelegramUpdateToRyeDict

func TelegramUpdateToRyeDict(update_ tgm.Update) env.Dict

func TruncateToWidth

func TruncateToWidth(s string, width int, ellipsis string) string

TruncateToWidth truncates a string to fit within the given width, preserving ANSI escape codes and optionally adding an ellipsis

func ValueToBSON

func ValueToBSON(arg0 env.Object, topLevel bool) any

func VectorToJSON

func VectorToJSON(vector env.Vector) string

func VectorToJSONWithIdxs

func VectorToJSONWithIdxs(vector env.Vector, idxs *env.Idxs) string

func VisibleWidth

func VisibleWidth(s string) int

VisibleWidth returns the display width of a string, ignoring ANSI escape codes

func WrapText

func WrapText(s string, width int) []string

WrapText wraps text to the given width, preserving ANSI codes across lines

Types

type ArgSpec

type ArgSpec struct {
	Name         string     // Name for the result (from flagword long name or setword)
	ShortFlag    string     // Short flag name (e.g., "v")
	LongFlag     string     // Long flag name (e.g., "verbose")
	IsFlag       bool       // True if it's a boolean flag (no value)
	IsPositional bool       // True if it's a positional argument
	IsRequired   bool       // True if required
	IsList       bool       // True if can be repeated (collects into list)
	IsMany       bool       // True if positional accepts many values
	ValueType    string     // "string", "integer", "decimal", "boolean", "file", "any"
	Default      env.Object // Default value
	CheckBlock   *env.Block // Optional validation block
	CheckError   string     // Error message if check fails
	Doc          string     // Documentation string
}

ArgSpec holds the specification for a single argument

type CLISpec

type CLISpec struct {
	GlobalArgs  []ArgSpec
	Subcommands map[string]*SubcommandSpec
	ProgramName string // Optional program name for help
	ProgramDoc  string // Optional program description for help
}

CLISpec holds the complete CLI specification

func CLI_ParseSpec

func CLI_ParseSpec(es *env.ProgramState, specBlock env.Block) (*CLISpec, error)

CLI_ParseSpec parses the specification block into a CLISpec

type ConversionError

type ConversionError struct {
	// contains filtered or unexported fields
}

Integer represents an integer.

type HtmlDialectNode

type HtmlDialectNode struct {
	Condition *HtmlNavigCondition
	Code      *env.Block
	SubNode   *env.Dict
	Type      int // 1 - node , 2 - code , 3 - direct_descendant (later)
}

type HtmlNavigCondition

type HtmlNavigCondition struct {
	Class string
	Id    string
}

type MarkdownDisplayItem

type MarkdownDisplayItem struct {
	Type         string   // "heading", "paragraph", "code", "list", "quote", "hr", "link"
	Content      string   // Raw content
	DisplayLines []string // Formatted lines for display
	Level        int      // For headings (1-6), or 0 for others
	Language     string   // For code blocks
}

MarkdownDisplayItem represents a selectable markdown element with its type and content

type MessageDispatcher

type MessageDispatcher struct {
	// contains filtered or unexported fields
}

MessageDispatcher provides a high-performance message routing system

func NewMessageDispatcher

func NewMessageDispatcher(bufferSize int, initialState env.Dict) *MessageDispatcher

NewMessageDispatcher creates a new message dispatcher

func (*MessageDispatcher) GetState

func (md *MessageDispatcher) GetState() env.Dict

GetState returns a copy of the current state

func (*MessageDispatcher) RegisterHandler

func (md *MessageDispatcher) RegisterHandler(msgType string, handler env.Function)

RegisterHandler registers a message handler function

func (*MessageDispatcher) Send

func (md *MessageDispatcher) Send(msg env.Object) error

Send sends a message to the dispatcher

func (*MessageDispatcher) SetState

func (md *MessageDispatcher) SetState(state env.Dict)

SetState updates the state

func (*MessageDispatcher) Start

func (md *MessageDispatcher) Start(ps *env.ProgramState, updateCallback env.Function)

Start begins processing messages in a goroutine

func (*MessageDispatcher) Stop

func (md *MessageDispatcher) Stop()

Stop stops the message processing loop

func (*MessageDispatcher) UnregisterHandler

func (md *MessageDispatcher) UnregisterHandler(msgType string)

UnregisterHandler removes a message handler

type ParsedArgs

type ParsedArgs struct {
	Values      map[string]env.Object
	Command     string   // Full command path: "remote add"
	CommandPath []string // ["remote", "add"]
	Positional  []env.Object
}

ParsedArgs holds the result of parsing

func CLI_ParseArgs

func CLI_ParseArgs(es *env.ProgramState, args env.Block, spec *CLISpec) (*ParsedArgs, map[string]env.Object)

CLI_ParseArgs parses command line arguments (as Rye values) according to the spec

type PersistentCtx

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

func NewPersistentCtx(dbPath string, ps *env.ProgramState) (*PersistentCtx, error)

NewPersistentCtx creates a new persistent context or loads an existing one.

func (*PersistentCtx) AsRyeCtx

func (pc *PersistentCtx) AsRyeCtx() *env.RyeCtx

AsRyeCtx returns the underlying RyeCtx for backward compatibility

func (*PersistentCtx) Copy

func (pc *PersistentCtx) Copy() env.Context

Copy creates a copy of the persistent context (note: copy won't be persistent)

func (*PersistentCtx) Get

func (pc *PersistentCtx) Get(word int) (env.Object, bool)

Get overrides the embedded Get method to read from database.

func (*PersistentCtx) GetDoc

func (pc *PersistentCtx) GetDoc() string

GetDoc returns the documentation string

func (*PersistentCtx) GetKindWord

func (pc *PersistentCtx) GetKindWord() env.Word

GetKindWord returns the Kind as a Word

func (*PersistentCtx) GetParent

func (pc *PersistentCtx) GetParent() env.Context

GetParent returns the parent context

func (*PersistentCtx) IsVariable

func (pc *PersistentCtx) IsVariable(word int) bool

IsVariable checks if a word is a variable by reading from database

func (*PersistentCtx) MarkAsVariable

func (pc *PersistentCtx) MarkAsVariable(word int)

MarkAsVariable marks a word as a variable in the database

func (*PersistentCtx) Mod

func (pc *PersistentCtx) Mod(word int, val env.Object) bool

Mod overrides the embedded Mod method to add ACID persistence.

func (*PersistentCtx) Set

func (pc *PersistentCtx) Set(word int, val env.Object) env.Object

Set overrides the embedded Set method to add ACID persistence.

func (*PersistentCtx) SetDoc

func (pc *PersistentCtx) SetDoc(doc string)

SetDoc sets the documentation string

func (*PersistentCtx) SetKindWord

func (pc *PersistentCtx) SetKindWord(kind env.Word)

SetKindWord sets the Kind

func (*PersistentCtx) SetNew

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

func (pc *PersistentCtx) SetParent(parent env.Context)

SetParent sets the parent context

func (PersistentCtx) Type

func (pc PersistentCtx) Type() env.Type

func (*PersistentCtx) Unset

func (pc *PersistentCtx) Unset(word int, idxs *env.Idxs) env.Object

Unset overrides the embedded Unset method to add ACID persistence.

type PersistentCtxEvaluator

type PersistentCtxEvaluator struct {
	// contains filtered or unexported fields
}

PersistentCtxEvaluator intercepts evaluation to ensure persistence operations go through PersistentCtx

func (*PersistentCtxEvaluator) Eval

func (pce *PersistentCtxEvaluator) Eval()

evaldo.EvalBlock evaluates the current series while intercepting persistence operations

type PersistentRyeCtx

type PersistentRyeCtx struct {
	env.RyeCtx
	// contains filtered or unexported fields
}

PersistentRyeCtx is a RyeCtx with persistence methods injected

func CreatePersistentRyeCtx

func CreatePersistentRyeCtx(pctx *PersistentCtx) *PersistentRyeCtx

CreatePersistentRyeCtx creates a RyeCtx that has persistent behavior by injecting persistence functions

func (*PersistentRyeCtx) Mod

func (w *PersistentRyeCtx) Mod(word int, val env.Object) bool

Override Mod to use PersistentCtx persistence

func (*PersistentRyeCtx) Set

func (w *PersistentRyeCtx) Set(word int, val env.Object) env.Object

Override Set to use PersistentCtx persistence

func (*PersistentRyeCtx) SetNew

func (w *PersistentRyeCtx) SetNew(word int, val env.Object, idxs *env.Idxs) bool

Override SetNew to use PersistentCtx persistence

func (*PersistentRyeCtx) Unset

func (w *PersistentRyeCtx) Unset(word int, idxs *env.Idxs) env.Object

Override Unset to use PersistentCtx persistence

type RyeMutex

type RyeMutex struct {
	// contains filtered or unexported fields
}

RyeMutex wraps sync.Mutex with state tracking to prevent fatal errors on unlocking unlocked mutex

func (*RyeMutex) Lock

func (m *RyeMutex) Lock()

func (*RyeMutex) Unlock

func (m *RyeMutex) Unlock() error

type SubcommandSpec

type SubcommandSpec struct {
	Name        string
	Args        []ArgSpec
	Subcommands map[string]*SubcommandSpec // Nested subcommands
	Doc         string                     // Documentation for subcommand
}

SubcommandSpec holds the specification for a subcommand

type TuiApp

type TuiApp struct {
	// contains filtered or unexported fields
}

TuiApp represents an inline terminal app

func NewTuiApp

func NewTuiApp(theme env.Dict) *TuiApp

NewTuiApp creates a new TUI app

func (*TuiApp) GetState

func (app *TuiApp) GetState() env.Dict

GetState returns the state

func (*TuiApp) IsRunning

func (app *TuiApp) IsRunning() bool

IsRunning returns whether the app is running

func (*TuiApp) OnKey

func (app *TuiApp) OnKey(key string, handler env.Object)

OnKey registers a key handler for a specific key

func (*TuiApp) OnKeys

func (app *TuiApp) OnKeys(handler env.Object)

OnKeys registers a handler for all keys

func (*TuiApp) Render

func (app *TuiApp) Render()

Render renders the current view

func (*TuiApp) SetState

func (app *TuiApp) SetState(state env.Dict)

SetState sets the state

func (*TuiApp) SetView

func (app *TuiApp) SetView(view env.Object)

SetView sets the view (block or function)

func (*TuiApp) Start

func (app *TuiApp) Start(ps *env.ProgramState) error

Start starts the app

func (*TuiApp) Stop

func (app *TuiApp) Stop()

Stop stops the app

func (*TuiApp) Update

func (app *TuiApp) Update(updates env.Dict)

Update merges updates into state and re-renders

func (*TuiApp) Wait

func (app *TuiApp) Wait()

Wait blocks until the app stops

type TuiInput

type TuiInput struct {
	// contains filtered or unexported fields
}

TuiInput represents a text input field with cursor and selection

func NewTuiInput

func NewTuiInput(placeholder string) *TuiInput

NewTuiInput creates a new input widget

func (*TuiInput) Dump

func (inp *TuiInput) Dump(e env.Idxs) string

Dump returns a printable representation

func (*TuiInput) Equal

func (inp *TuiInput) Equal(other env.Object) bool

Equal checks equality

func (*TuiInput) GetKind

func (inp *TuiInput) GetKind() int

GetKind returns the kind string

func (*TuiInput) GetValue

func (inp *TuiInput) GetValue() string

GetValue returns the current value

func (*TuiInput) HandleKey

func (inp *TuiInput) HandleKey(key string, ps *env.ProgramState) bool

HandleKey processes a key event, returns true if handled

func (*TuiInput) Inspect

func (inp *TuiInput) Inspect(idxs env.Idxs) string

Inspect returns a string representation

func (*TuiInput) Print

func (inp *TuiInput) Print(e env.Idxs) string

Print returns printable string

func (*TuiInput) Render

func (inp *TuiInput) Render() env.Block

Render returns the widget block for this input

func (*TuiInput) SetValue

func (inp *TuiInput) SetValue(val string)

SetValue sets the input value

func (*TuiInput) Trace

func (inp *TuiInput) Trace(msg string)

Trace returns a trace representation

func (*TuiInput) Type

func (inp *TuiInput) Type() env.Type

Type returns the type name for env.Native interface

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL