123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573 |
- package muesli
- import "fmt"
- import "log"
- import "runtime"
- import "strings"
- import "sort"
- type LogTracer struct {
- }
- func (t LogTracer) Trace(vm VM, fmt string, args ... interface{}) bool {
- args = append([]interface{}{vm.BackTrace()}, args...)
- log.Printf("%s: " + fmt, args...)
- return false
- }
- type FmtTracer struct {
- }
- func (t FmtTracer) Trace(vm VM, fm string, args ... interface{}) bool {
- args = append([]interface{}{vm.BackTrace()}, args...)
- fmt.Printf("%s: " + fm + "\n", args...)
- return false
- }
- func printf(vm *VM, args ...Value) []Value {
- var format string
- rest, err := ParseArgs(args, &format)
- if err != nil {
- return Fail(err)
- }
- extra := ListFromList(rest)
- fmt.Printf(format, extra...)
- return None()
- }
- func println(vm *VM, args ...Value) []Value {
- var msg string
- _, err := ParseArgs(args, &msg)
- if err != nil {
- return Fail(err)
- } else {
- fmt.Println(msg)
- }
- return None()
- }
- func p(vm *VM, args ...Value) []Value {
- for _, arg := range args {
- fmt.Printf("%v\n", arg)
- }
- return None()
- }
- func trace(vm *VM, args ...Value) []Value {
- var b bool = true
- fmt.Printf("command trace: %v\n", args)
- _, err := ParseArgs(args, &b)
- if err != nil {
- fmt.Printf("Error: %s\n", err.Error())
- return Fail(err)
- }
- fmt.Printf("command trace: bool: %v\n", b)
- if b {
- vm.Tracer = FmtTracer{}
- } else {
- vm.Tracer = nil
- }
- return Ok(BoolValue(b))
- }
- func sumi(vm *VM, args ...Value) []Value {
- slice, err := ParseArgsToIntSlice(args)
- if err != nil {
- fmt.Printf("Error: %s\n", err.Error())
- return Fail(err)
- }
- res := int(0)
- for _, val := range slice {
- res += val
- }
- return IntOk(res)
- }
- func sumf(vm *VM, args ...Value) []Value {
- slice, err := ParseArgsToFloat64Slice(args)
- if err != nil {
- fmt.Printf("Error: %s\n", err.Error())
- return Fail(err)
- }
- res := float64(0)
- for _, val := range slice {
- res += val
- }
- return FloatOk(res)
- }
- func addi(vm *VM, args ...Value) []Value {
- var v1, v2 int
- _, err := ParseArgs(args, &v1, &v2)
- if err != nil {
- return Fail(err)
- }
- return IntOk(v1 + v2)
- }
- func addf(vm *VM, args ...Value) []Value {
- var v1, v2 float64
- _, err := ParseArgs(args, &v1, &v2)
- if err != nil {
- return Fail(err)
- }
- return FloatOk(v1 + v2)
- }
- func subi(vm *VM, args ...Value) []Value {
- var v1, v2 int
- _, err := ParseArgs(args, &v1, &v2)
- if err != nil {
- return Fail(err)
- }
- return IntOk(v1 - v2)
- }
- func subf(vm *VM, args ...Value) []Value {
- var v1, v2 float64
- _, err := ParseArgs(args, &v1, &v2)
- if err != nil {
- return Fail(err)
- }
- return FloatOk(v1 - v2)
- }
- func muli(vm *VM, args ...Value) []Value {
- var v1, v2 int
- _, err := ParseArgs(args, &v1, &v2)
- if err != nil {
- return Fail(err)
- }
- return IntOk(v1 * v2)
- }
- func mulf(vm *VM, args ...Value) []Value {
- var v1, v2 float64
- _, err := ParseArgs(args, &v1, &v2)
- if err != nil {
- return Fail(err)
- }
- return FloatOk(v1 * v2)
- }
- func divi(vm *VM, args ...Value) []Value {
- var v1, v2 int
- _, err := ParseArgs(args, &v1, &v2)
- if err != nil {
- return Fail(err)
- }
- return IntOk(v1 / v2)
- }
- func divf(vm *VM, args ...Value) []Value {
- var v1, v2 float64
- _, err := ParseArgs(args, &v1, &v2)
- if err != nil {
- return Fail(err)
- }
- return FloatOk(v1 / v2)
- }
- func andb(vm * VM, args ...Value) []Value {
- var v1, v2 bool
- _, err := ParseArgs(args, &v1, &v2)
- if err != nil {
- return Fail(err)
- }
- return BoolOk(v1 && v2)
- }
- func orb(vm * VM, args ...Value) []Value {
- var v1, v2 bool
- _, err := ParseArgs(args, &v1, &v2)
- if err != nil {
- return Fail(err)
- }
- return BoolOk(v1 || v2)
- }
- func val(vm *VM, args ...Value) []Value {
- if len(args) < 1 {
- return []Value{NewErrorValuef("val requres at least one argument.")}
- }
- return args
- }
- func builtin_return(vm *VM, args ...Value) []Value {
- vm.Frame.returned = true
- vm.Frame.results = args
- vm.Trace("Returning... %v", vm.Frame)
- return args
- }
- func to(vm *VM, args ...Value) []Value {
- var name string
- rest, err := ParseArgs(args, &name)
- if err != nil {
- return Fail(err)
- }
-
- if len(rest) < 1 {
- return Fail(NewErrorValuef("Need at least 2 arguments: %v", args))
- }
-
- last := rest[len(rest)-1]
- block, isBlock := last.(*BlockValue)
- if ! isBlock {
- return Fail(NewErrorValuef("Not a block: %v", last))
- }
- param := rest[0:len(rest)-1]
- defpars := []*Parameter{}
- for i := 1 ; i < len(param) ; i += 2 {
- par := &Parameter{}
- name := param[i-1]
- typ := param[i]
- var ok bool
- if par.Name, ok = name.(WordValue); !ok {
- return Fail(NewErrorValuef("Not a word value: %v", name))
- }
- if par.Type, ok = typ.(TypeValue); !ok {
- return Fail(NewErrorValuef("Not a type value: %v", typ))
- }
- defpars = append(defpars, par)
- }
-
- // To must register one level up.
- return Ok(vm.RegisterDefined(name, defpars, block, 1))
- }
- func cover(vm *VM, args ...Value) []Value {
- var name, target string
- rest, err := ParseArgs(args, &name, &target)
- if err != nil {
- return Fail(err)
- }
- types := []TypeValue{}
- for i, arg := range rest {
- if typ, ok := arg.(TypeValue) ; ok {
- types = append(types, typ)
- } else {
- return Fail(NewErrorValuef("Argument %d: not a type: %v %s", i+2, arg, arg.String()))
- }
- }
- // Overload must be defined one scope up.
- err = vm.AddOverload(name, target, 1, types...)
-
- if err != nil {
- return Fail(err)
- }
- return Ok()
- }
- func types(vm *VM, args ...Value) []Value {
- result := []Value{}
- for i, arg := range args {
- typ := arg.Type()
- result = append(result, typ)
- fmt.Printf("Type %d: %s\n", i, typ.String())
- }
- return Ok(NewListValue(result...))
- }
- func set(vm *VM, val ...Value) []Value {
- if len(val) < 2 {
- return Fail(fmt.Errorf("set needs at least 2 arguments: received %v", val))
- }
- target := val[0].String()
- value := val[1]
- if target == "(" || target == "$" {
- if len(val) < 3 {
- return Fail(fmt.Errorf("indirect get needs results: received %v", val))
- }
- target = val[1].String()
- value = val[2]
- }
- vm.RegisterUp(target, value, 1)
- return Ok(value)
- }
- func get(vm *VM, val ...Value) []Value {
- if len(val) < 1 {
- return Fail(fmt.Errorf("get needs at least 1 argument"))
- }
- target := val[0].String()
- if target == "(" || target == "$" {
- if len(val) < 2 {
- return Fail(fmt.Errorf("indirect get needs results: received %v", val))
- }
- target = val[1].String()
- }
- return Ok(vm.Lookup(target))
- }
- func fetchl(vm *VM, args ...Value) []Value {
- var index int
- var list *ListValue
- _, err := ParseArgs(args, &list, &index)
- if err != nil {
- return Fail(err)
- }
- return Ok(list.List[index])
- }
- func storel(vm *VM, args ...Value) []Value {
- var index int
- var list *ListValue
- rest, err := ParseArgs(args, &list, &index)
- if err != nil {
- return Fail(err)
- }
- if len (rest) < 1 {
- return Fail(fmt.Errorf("fetch: need 3 arguments"))
- }
- list.List[index] = rest[0]
- return Ok(list.List[index])
- }
- func fetchm(vm *VM, args ...Value) []Value {
- var index Value
- var hmap *MapValue
- _, err := ParseArgs(args, &hmap, &index)
- if err != nil {
- return Fail(err)
- }
- return Ok(hmap.Map[index])
- }
- func storem(vm *VM, args ...Value) []Value {
- var index Value
- var hmap *MapValue
- rest, err := ParseArgs(args, &hmap, &index)
- if err != nil {
- return Fail(err)
- }
- if len (rest) < 1 {
- return Fail(fmt.Errorf("fetch: need 3 arguments"))
- }
- hmap.Map[index] = rest[0]
- return Ok(hmap.Map[index])
- }
- func newmap(vm *VM, args ...Value) []Value {
- result := make(map[Value] Value)
- for i := 1; i < len(args) ; i+=2 {
- result[args[i-1]] = args[i]
- }
- return Ok(NewMapValue(result))
- }
- func help(vm *VM, val ...Value) [] Value {
- if len(val) < 1 {
- fmt.Printf("help <callable> will display help on the callable\n\nThe following commands are available:\n")
- helpers := vm.DefinedHelpers()
- sort.SliceStable(helpers, func(i, j int) bool {
- return helpers[i].HelperName() < helpers[j].HelperName()
- })
- for _, helper := range helpers {
- fl := strings.SplitN(helper.Help(),"\n", 2)
- fmt.Printf("%s %s: \n", helper.HelperName(), fl[0])
- }
- return Ok()
- }
- targetName := val[0].String()
- target := vm.Lookup(targetName)
- if target == nil {
- fmt.Printf("help: %s not found.\n", targetName)
- }
-
- if helper, isHelper := target.(Helper) ; isHelper {
- help := helper.Help()
- fmt.Printf("%s: %s.\n", targetName, help)
- return Ok(StringValue(help))
- }
-
- return Ok()
- }
- func explain(vm *VM, val ...Value) [] Value {
- var target, help string
- _, err := ParseArgs(val, &target, &help)
- if err != nil {
- return Fail(err)
- }
- err = vm.SetHelp(target, help)
- if err != nil {
- return Fail(err)
- }
- return Ok(StringValue(help))
- }
- func exit(vm *VM, val ...Value) [] Value {
- var code int
- _, err := ParseArgs(val, &code)
- if err != nil {
- runtime.Goexit()
- }
- vm.ExitStatus = code
- runtime.Goexit()
- return Ok()
- }
- type Door struct {
- name string
- locked bool
- opened bool
- }
- // Implement callable ...
- func (door * Door) Position() *Position {
- return &Position{"builtin.go", 427, 8}
- }
- type ValueCallable interface {
- Callable
- Value
- }
- func Redispatch(from ValueCallable, vm *VM, args...Value) []Value {
- if len(args) < 1 {
- return EmptyValueArray()
- }
- var word WordValue
- _, err := ParseOptArgs(args, 1, &word)
- if err != nil {
- return Fail(err)
- }
- args[0] = from
- return vm.CallNamed(string(word), args...)
- }
- func (door * Door) Call(vm *VM, args...Value) []Value {
- return Redispatch(door, vm, args...)
- }
- var doorSignature = NewSignature(WordTypeValue)
- func (door * Door) Signature() *Signature {
- return &doorSignature
- }
- var _ Callable = &Door{}
- const DoorType = TypeValue("Door")
- func (door * Door) String() string {
- return fmt.Sprintf("Door: %s %v %v", door.name, door.locked, door.opened)
- }
- func (*Door) Type() TypeValue {
- return DoorType
- }
- func (from * Door) Convert(to interface{}) error {
- switch toPtr := to.(type) {
- case **Door:
- (*toPtr) = from
- case *Door:
- (*toPtr) = *from
- case *Value:
- (*toPtr) = from
- default:
- return NewErrorValuef("Cannot convert DoorValue value %v to %v", from, to)
- }
- return nil
- }
- func door(vm *VM, val ...Value) [] Value {
- var name string
- var locked bool
- _, err := ParseOptArgs(val, 1, &name, &locked)
- if err != nil {
- return Fail(err)
- }
- return Ok(&Door{name: name, locked: locked, opened:false})
- }
- func (door * Door) Open() {
- door.opened = true
- }
- func openDoor(vm *VM, val ...Value) [] Value {
- var door *Door
- _, err := ParseArgs(val, &door)
- if err != nil {
- return Fail(err)
- }
- if door == nil {
- return Fail(NewErrorValuef("Door may not be nil."))
- }
-
- fmt.Printf("Door: %v %s", door, door)
- door.Open()
- return Ok(door)
- }
- func (vm *VM) RegisterBuiltins() {
- vm.RegisterBuiltinWithHelp("addi", addi, `[Int Int] -> Int: adds two integers together`)
- vm.RegisterBuiltinWithHelp("addf", addf, `[Int Int] -> Int: adds two floats together`)
- vm.RegisterBuiltinWithHelp("andb", andb, `[Bool Bool] -> Bool: returns true if all it's arguments are true`)
- vm.RegisterBuiltin("cover", cover)
- vm.RegisterBuiltin("fetchl", fetchl)
- vm.RegisterBuiltin("fetchm", fetchm)
- vm.RegisterBuiltin("sumi", sumi)
- vm.RegisterBuiltin("sumf", sumf)
- vm.RegisterBuiltin("subi", subi)
- vm.RegisterBuiltin("subf", subf)
- vm.RegisterBuiltin("divi", divi)
- vm.RegisterBuiltin("divf", divf)
- vm.RegisterBuiltin("map", newmap)
- vm.RegisterBuiltin("muli", muli)
- vm.RegisterBuiltin("mulf", mulf)
- vm.RegisterBuiltinWithHelp("orb", orb, `[Bool Bool] -> Bool: returns true if on of it's arguments is true`)
- // vm.RegisterCover("add")
- vm.RegisterBuiltin("p", p)
- vm.RegisterBuiltin("println", println)
- vm.RegisterBuiltin("printf", printf)
- vm.RegisterBuiltin("storel", storel)
- vm.RegisterBuiltin("storem", storem)
- vm.RegisterBuiltin("trace", trace)
- vm.RegisterBuiltin("to", to)
- vm.RegisterBuiltin("types", types)
- vm.RegisterBuiltin("return", builtin_return)
- vm.RegisterBuiltin("val", val)
- vm.RegisterBuiltin("set", set)
- vm.RegisterBuiltin("get", get)
- vm.RegisterBuiltin("help", help)
- vm.RegisterBuiltin("explain", explain)
- vm.RegisterBuiltin("exit", exit)
- vm.RegisterBuiltin("door", door)
- vm.RegisterBuiltin("openDoor", openDoor)
- vm.Register("Door", DoorType)
- vm.AddOverloads("open", Over("openDoor", 0, DoorType))
-
- vm.AddOverloads("mul",
- Over("mulf", 0, FloatTypeValue, FloatTypeValue),
- Over("muli", 0, IntTypeValue, IntTypeValue),
- Over("mulf", 0, FloatTypeValue, IntTypeValue),
- Over("mulf", 0, FloatTypeValue, IntTypeValue))
-
- vm.SetHelp("mul", " Num: Multiplies two numbers. Cover for muli and mulf.")
- vm.AddOverloads("fetch",
- Over("fetchl", 0, ListTypeValue, IntTypeValue),
- Over("fetchm", 0, MapTypeValue, AnyTypeValue),
- )
- vm.SetHelp("fetch", " storage, index. Fetch value in storage at given index.")
- /*
- vm.AddOverloads("store",
- Over("storel", ListTypeValue, IntTypeValue, AnyTypeValue),
- Over("storem", MapTypeValue, AnyTypeValue, AnyTypeValue),
- )
- vm.SetHelp("store", " storage, index, value. Store value in storage at given index.")
- */
- }
|