func Die(vm *gelo.VM, args *gelo.List, ac uint) gelo.Word { if ac == 0 { args = gelo.AsList(gelo.StrToSym("die")) } gelo.RuntimeError(vm, args) return gelo.Null //Issue 65 }
func Compose(vm *gelo.VM, args *gelo.List, ac uint) gelo.Word { if ac == 0 { return gelo.Alien(Id) //defined in eval.go } else if ac == 1 { return vm.API.InvokableOrElse(args.Value) } //reverse and type check (as much as possible) builder := extensions.ListBuilder() defer builder.Destroy() for ; args != nil; args = args.Next { builder.PushFront(vm.API.InvokableOrElse(args.Value)) } fs := builder.List() return gelo.Alien(func(vm *gelo.VM, args *gelo.List, ac uint) gelo.Word { c := fs var ret gelo.Word = args for ; c.Next != nil; c = c.Next { ret = gelo.AsList(vm.API.InvokeCmdOrElse(c.Value, ret.(*gelo.List))) } return vm.API.TailInvokeCmd(c.Value, ret.(*gelo.List)) }) }
func Case_of(vm *gelo.VM, args *gelo.List, ac uint) gelo.Word { Args := _cases_parser(vm, args) key := Args["value"] arguments := gelo.AsList(key) cases, ok := vm.API.PartialEval(vm.API.QuoteOrElse(Args["cases"])) if !ok || cases.Next == nil && cases.Value == nil { gelo.SyntaxError(vm, "Expected:", _cases_parser, "{[value+ => resultant\n]+ [otherwise result]?} Got:", args) } //Give val a name, specified by var, in clauses of the cases block //XXX This disallows us from making tail calls if name, there := Args["var"]; there { if d, there := vm.Ns.DepthOf(name); there && d == 0 { defer vm.Ns.Set(0, name, vm.Ns.LookupOrElse(name)) } else { defer vm.Ns.Del(name) } vm.Ns.Set(0, name, key) } //run val through cmd before comparing if cmd, there := Args["cmd"]; there { key = vm.API.InvokeCmdOrElse(cmd, arguments) } //Parse lines for ; cases != nil; cases = cases.Next { //if last line, see if it's the otherwise clause if cases.Next == nil { item := cases.Value.(*gelo.List) s, ok := item.Value.(gelo.Symbol) if ok && gelo.StrEqualsSym("otherwise", s) { if item.Next == nil || item.Next.Next != nil { _cases_synerr() } return _case_eval(vm, item.Next.Value, arguments) } } item := cases.Value.(*gelo.List) //line is too short if item.Next == nil || item.Next.Next == nil { _cases_synerr() } //Parse a single line list := extensions.ListBuilder() var resultant gelo.Word for ; item != nil; item = item.Next { if item.Next == nil { //ultimate cell resultant = item.Value } else if item.Next.Next == nil { //penultimate cell s, ok := item.Value.(gelo.Symbol) if ok && gelo.StrEqualsSym("=>", s) { continue } _cases_synerr() } else { list.Push(item.Value) } } //see if key matches any of the items we found on this line for head := list.List(); head != nil; head = head.Next { if key.Equals(head.Value) { return _case_eval(vm, resultant, arguments) } } } return gelo.Null //no match, no otherwise }