func Print(args ...interface{}) {
	for i, v := range args {
		if i != 0 {
			fmt.Print(" ")
		}
		fmt.Printf("%v", v)
	}
}
Print implements the print function.
package runtime
import (
	"fmt"
	"reflect"
	"runtime"
	"strings"
	"github.com/rumlang/rum/parser"
)
const (
	ErrPanic = iota
	ErrUnknownVariable
)
type ErrorCode int
func (c ErrorCode) String() string {
	switch c {
	case ErrPanic:
		return "Panic"
	case ErrUnknownVariable:
		return "UnknownVariable"
	default:
		return fmt.Sprintf("Unknown[%d]", c)
	}
}
type Error struct {
	Code ErrorCode
	Msg  string
	Stack []parser.Value
	PanicRecovered interface{}
	PanicStack     []byte
}
func (e *Error) String() string {
	out := fmt.Sprintf("runtime error: %s[%d] - %s\n", e.Code, e.Code, e.Msg)
	var (
		triggeredAt = "  # triggered at:\n"
		calledFrom  = "  # called from:\n"
		msg         = &triggeredAt
	)
	for _, v := range e.Stack {
		out += *msg
		out += v.Ref().Context("    ")
		msg = &calledFrom
	}
	if e.Code == ErrPanic {
		out += "  # Interpreter trace:\n"
		for _, line := range strings.Split(string(e.PanicStack), "\n") {
			out += fmt.Sprintf("    %s\n", line)
		}
	}
	return out
}
func (e *Error) Error() string {
	return e.String()
}
type Internal func(*Context, ...parser.Value) parser.Value
type Context struct {
	parent       *Context
	env          map[parser.Identifier]parser.Value
	typeRegistry map[string]reflect.Type
}
func (c *Context) Get(id parser.Identifier) parser.Value {
	v, ok := c.env[id]
	if !ok {
		if c.parent != nil {
			return c.parent.Get(id)
		}
		panic(&Error{
			Code: ErrUnknownVariable,
			Msg:  fmt.Sprintf("%q does not exist", string(id)),
		})
	}
	return v
}
func (c *Context) Set(id parser.Identifier, v parser.Value) parser.Value {
	_, ok := c.env[id]
	if !ok {
		c.env[id] = v
		return v
	}
	panic(fmt.Sprintf("Variable called %s just has a value in that scope", id))
}
func (c *Context) SetFn(id parser.Identifier, v interface{}, adapters ...Adapter) {
	f := func(values ...interface{}) interface{} {
		args := values
		var err error
		for _, adapter := range adapters {
			args, err = adapter(args...)
			if err != nil {
				panic(fmt.Sprint("Error in adapter", values[0], err))
			}
		}
		vargs := []reflect.Value{}
		for _, arg := range args {
			vargs = append(vargs, reflect.ValueOf(arg))
		}
		result := reflect.ValueOf(v).Call(vargs)
		return result[0].Interface()
	}
	c.env[id] = parser.NewAny(f, nil)
}
func (c *Context) RegisterType(typedNil interface{}) {
	t := reflect.TypeOf(typedNil).Elem()
	c.typeRegistry[t.PkgPath()+"."+t.Name()] = t
}
func (c *Context) dispatch(input parser.Value) (parser.Value, error) {
	switch data := input.Value().(type) {
	case []parser.Value:
		if len(data) <= 0 {
			return parser.NewAny(nil, nil), nil
		}
		fn, err := c.eval(data[0])
		if err != nil {
			return nil, err
		}
		if internal, ok := fn.Value().(Internal); ok {
			return internal(c, data[1:]...), nil
		}
		var args []reflect.Value
		for _, child := range data[1:] {
			v, err := c.eval(child)
			if err != nil {
				return nil, err
			}
			data := v.Value()
			if data == nil {
				args = append(args, reflect.ValueOf(&data).Elem())
				continue
			}
			args = append(args, reflect.ValueOf(data))
		}
		result := reflect.ValueOf(fn.Value()).Call(args)
		if len(result) == 0 {
			return parser.NewAny(nil, nil), nil
		}
		if len(result) == 1 {
			return parser.NewAny(result[0].Interface(), nil), nil
		}
		panic("Multiple arguments unsupported")
	case parser.Identifier:
		return c.Get(data), nil
	default:
		return input, nil
	}
}
func (c *Context) eval(input parser.Value) (parser.Value, error) {
	var recov interface{}
	var result parser.Value
	var stack []byte
	var err error
	func() {
		defer func() {
			const size = 16384
			stack = make([]byte, size)
			stack = stack[:runtime.Stack(stack, false)]
			recov = recover()
		}()
		result, err = c.dispatch(input)
	}()
	if recov != nil {
		err = &Error{
			Code:           ErrPanic,
			Msg:            fmt.Sprintf("%v", recov),
			PanicRecovered: recov,
			PanicStack:     stack,
		}
		if details, ok := recov.(*Error); ok {
			err = details
		}
	}
	if err != nil {
		err.(*Error).Stack = append(err.(*Error).Stack, input)
	}
	return result, err
}
func (c *Context) TryEval(input parser.Value) (parser.Value, error) {
	return c.eval(input)
}
func (c *Context) MustEval(input parser.Value) parser.Value {
	v, err := c.eval(input)
	if err != nil {
		panic(err)
	}
	return v
}
func NewContext(parent *Context) *Context {
	c := &Context{
		parent:       parent,
		env:          make(map[parser.Identifier]parser.Value),
		typeRegistry: make(map[string]reflect.Type),
	}
	if parent == nil {
		defaults := map[parser.Identifier]interface{}{
			"package": Package,
			"array":   Internal(Array),
			"let":     Internal(Let),
			"if":      Internal(If),
			"def":     Internal(Def),
			"lambda":  Internal(Lambda),
			"eval":    Internal(Eval),
			"for":     Internal(For),
			"coerce":  Internal(Coerce),
			".":       Internal(Invoke),
			"import":  Internal(Import),
			"panic":   Panic,
			"len":     Length,
			"print":   Print,
			"println": Println,
			"sprintf": Sprintf,
			"fprintf": fmt.Fprintf,
			"type":    Type,
			"nil":     nil,
			"true":    true,
			"false":   false,
			"+":       OpAdd,
			"-":       OpSub,
			"*":       OpMul,
			"**":      OpPow,
			"==":      OpEqual,
			"!=":      OpNotEqual,
			"<":       OpLess,
			"<=":      OpLessEqual,
			">":       OpGreater,
			">=":      OpGreaterEqual,
		}
		for name, value := range defaults {
			c.env[name] = parser.NewAny(value, nil)
		}
	}
	return c
}
func Array(ctx *Context, args ...parser.Value) parser.Value {
	if len(args) != 1 {
		panic("Invalid number of arguments for array")
	}
	return args[0]
}
func Package(name string, values ...interface{}) interface{} {
	if len(values) == 0 {
		return nil
	}
	return values[len(values)-1]
}
func Import(ctx *Context, args ...parser.Value) (v parser.Value) {
	if len(args) == 0 {
		panic("Invalid arguments")
	}
	for key := range args {
		var packageID parser.Identifier
		var packageName parser.Value
		var packageNameStr string
		input := args[key]
		switch data := input.Value().(type) {
		case []parser.Value:
			packageID = data[0].Value().(parser.Identifier)
			packageName = data[1]
			packageNameStr = data[1].Value().(string)
		case parser.Identifier:
			packageID = data
			packageName = input
			packageNameStr = data.String()
		default:
			panic(fmt.Sprintf("package %s not found", Type(args[key].Value())))
		}
		loadStdLib(packageNameStr, ctx, packageID)
		v = ctx.Set(packageID, packageName)
	}
	return v
}
func Let(ctx *Context, args ...parser.Value) parser.Value {
	if len(args) != 2 {
		panic("Invalid arguments")
	}
	id, ok := args[0].Value().(parser.Identifier)
	if !ok {
		panic("TODO")
	}
	return ctx.Set(id, ctx.MustEval(args[1]))
}
func If(ctx *Context, args ...parser.Value) parser.Value {
	if len(args) < 2 || len(args) > 3 {
		panic("Invalid arguments")
	}
	cond := ctx.MustEval(args[0]).Value().(bool)
	if cond {
		return ctx.MustEval(args[1])
	}
	if len(args) <= 2 {
		return parser.NewAny(nil, nil)
	}
	return ctx.MustEval(args[2])
}
func Def(ctx *Context, args ...parser.Value) parser.Value {
	if len(args) != 3 {
		panic("Invalid arguments")
	}
	id, ok := args[0].Value().(parser.Identifier)
	if !ok {
		panic("TODO")
	}
	params, ok := args[1].Value().([]parser.Value)
	if !ok {
		panic("TODO")
	}
	names := []parser.Identifier{}
	for _, v := range params {
		nameid, ok := v.Value().(parser.Identifier)
		if !ok {
			panic("TODO")
		}
		names = append(names, nameid)
	}
	implValue := args[2]
	impl := func(implCtx *Context, args ...parser.Value) parser.Value {
		if len(args) != len(names) {
			panic("TODO")
		}
		nested := NewContext(implCtx)
		for i, name := range names {
			nested.Set(name, implCtx.MustEval(args[i]))
		}
		return nested.MustEval(implValue)
	}
	ctx.env[id] = parser.NewAny(Internal(impl), nil)
	return ctx.env[id]
}
func Lambda(ctx *Context, args ...parser.Value) parser.Value {
	if len(args) != 2 {
		panic("Invalid arguments")
	}
	params, ok := args[0].Value().([]parser.Value)
	if !ok {
		panic("TODO")
	}
	names := []parser.Identifier{}
	for _, v := range params {
		id, ok := v.Value().(parser.Identifier)
		if !ok {
			panic("TODO")
		}
		names = append(names, id)
	}
	implValue := args[1]
	impl := func(implCtx *Context, args ...parser.Value) parser.Value {
		if len(args) != len(names) {
			panic("TODO")
		}
		nested := NewContext(implCtx)
		for i, name := range names {
			nested.Set(name, implCtx.MustEval(args[i]))
		}
		return nested.MustEval(implValue)
	}
	return parser.NewAny(Internal(impl), nil)
}
func Type(v interface{}) string {
	return fmt.Sprintf("%T", v)
}
func Length(elt []parser.Value) int64 {
	return int64(len(elt))
}
func Panic(v interface{}) {
	panic(v)
}