func DictToCommand(vm *gelo.VM, args *gelo.List, ac uint) gelo.Word { if ac != 1 { gelo.ArgumentError(vm, "dict->command", "dictionary", args) } m := vm.API.DictOrElse(args.Value).Map() return gelo.Alien(func(vm *gelo.VM, args *gelo.List, ac uint) gelo.Word { if ac == 0 { gelo.ArgumentError(vm, "command generated by dict->command", "argument+", args) } name := args.Value.Ser().String() if v, ok := m[name]; ok { if args.Next != nil { return vm.API.TailInvokeCmd(v, args.Next) } else { return vm.API.TailInvokeWordOrReturn(v) } } else if args.Next != nil { gelo.RuntimeError(vm, name, "is not a valid subcommand") } else { gelo.RuntimeError(vm, name, "is not a valid subcommand or entry") } panic("command generated by dict->command in impossible state") //Issue 65 }) }
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 NS_unfork(vm *gelo.VM, args *gelo.List, ac uint) gelo.Word { if ac != 0 { gelo.ArgumentError(vm, "ns.unfork", "", args) } if _, ok := vm.Ns.Unfork(); !ok { gelo.RuntimeError(vm, "Fatal: Last namespace destroyed") } vm.API.Trace("Namespace destroyed") return gelo.Null }
func PortReadx(vm *gelo.VM, args *gelo.List, ac uint) gelo.Word { if ac != 1 { gelo.ArgumentError(vm, "read!", "port", args) } p := vm.API.PortOrElse(args.Value) if p.Closed() { gelo.RuntimeError(vm, "attempted to read from a closed port") } return p.Recv() }
func PortClosex(vm *gelo.VM, args *gelo.List, ac uint) gelo.Word { if ac != 1 { gelo.ArgumentError(vm, "close!", "port", args) } p := vm.API.PortOrElse(args.Value) if p.Closed() { gelo.RuntimeError(vm, "port already closed") } p.Close() return gelo.Null }
func checkNotInSection(vm *gelo.VM, command string) { k := gelo.StrToSym("section") if s, ok := vm.Ns.Get(0, k); ok { gelo.RuntimeError( vm, fmt.Sprintf( "%s command is used inside a section %s while it should be toplevel", command, s.Ser().String(), ), ) } }
func Exportx(vm *gelo.VM, args *gelo.List, ac uint) gelo.Word { lvl := 1 if ac == 4 { lvl, args = _export_parser(vm, args) } else if ac != 2 { gelo.ArgumentError(vm, "export!", "[up levels]? name value", args) } value := args.Next.Value if !vm.Ns.Set(lvl, args.Value, value) { gelo.RuntimeError(vm, "invalid namespace specified") } return value }
func DictCon(vm *gelo.VM, args *gelo.List, ac uint) gelo.Word { if ac == 0 { return gelo.NewDict() } if ac != 1 { gelo.ArgumentError(vm, "Dict", "{{k1 v1} {k2 v2} ... {kn vn}}", args) } d, ok := gelo.UnserializeDictFrom(args.Value) if !ok { gelo.RuntimeError(vm, "Cannot unserialize", args.Value, "into a dict") } return d }
func Dict_unsetx(vm *gelo.VM, args *gelo.List, ac uint) gelo.Word { if ac != 2 { gelo.ArgumentError(vm, "dict.unset!", "dictionary key", args) } d := vm.API.DictOrElse(args.Value) k := args.Next.Value v, ok := d.Get(k) if !ok { gelo.RuntimeError(vm, "dict.unset! attempted to unset a key not in dictionary") } d.Del(k) return v }
//Left-to-right func Quotient(vm *gelo.VM, args *gelo.List, ac uint) gelo.Word { if ac == 0 { return gelo.NewNumber(0) } acc := vm.API.NumberOrElse(args.Value).Real() for args = args.Next; args != nil; args = args.Next { n := vm.API.NumberOrElse(args.Value).Real() if n == 0 { gelo.RuntimeError(vm, "Division by 0") } acc /= n } return gelo.NewNumber(acc) }
func Swapx(vm *gelo.VM, args *gelo.List, ac uint) gelo.Word { if ac != 2 { gelo.ArgumentError(vm, "swap!", "name name", args) } fst, snd := args.Value, args.Next.Value sndw, _, ok := vm.Ns.Swap(fst, snd) //don't need fstw if !ok { //we've lost our locks so this may produce nonsense _, fstb := vm.Ns.Lookup(fst) _, sndb := vm.Ns.Lookup(snd) if fstb && sndb { gelo.RuntimeError(vm, "Neither", fst, "nor", snd, "are defined") } if fstb { gelo.VariableUndefined(vm, fst) } if sndb { gelo.VariableUndefined(vm, snd) } gelo.RuntimeError(vm, "swap failed but both operands were defined") } return sndw //returned because this is now the "closest" }
func Exportsx(vm *gelo.VM, args *gelo.List, ac uint) gelo.Word { lvls, args := _export_parser(vm, args) m := make(map[string]gelo.Word) for ; args != nil; args = args.Next { //Ns Ser's value anyway so no point in doing it twice k := args.Value.Ser() v := vm.Ns.LookupOrElse(k) m[k.String()] = v } d := gelo.NewDictFrom(m) if !vm.Ns.Inject(lvls, d) { gelo.RuntimeError(vm, "invalid namespace specified") } return d }
func Dict_get(vm *gelo.VM, args *gelo.List, ac uint) gelo.Word { if !(ac == 2 || ac == 3) { gelo.ArgumentError(vm, "dict.get", "dictionary key default?", args) } d := vm.API.DictOrElse(args.Value) k := args.Next.Value ret, ok := d.Get(k) if !ok { if ac == 3 { //return default value return args.Next.Next.Value } gelo.RuntimeError(vm, "dictionary does not contain", k) } return ret }
func PortWritex(vm *gelo.VM, args *gelo.List, ac uint) gelo.Word { if ac < 2 { gelo.ArgumentError(vm, "write!", "port rest+", args) } p := vm.API.PortOrElse(args.Value) if p.Closed() { gelo.RuntimeError(vm, "attempted to write to a closed port") } var msg gelo.Word if ac == 2 { msg = args.Next.Value } else { msg = args.Next } p.Send(msg) return msg }
func booleanOption(vm *gelo.VM, args *gelo.List, ac uint, dst *bool, command string, sections ...string) { if ac > 1 { gelo.ArgumentError(vm, command, "[true | false]", args) } // Check whether we're in the specified sections checkInSection(vm, command, sections...) if ac > 0 { enabled, ok := args.Value.(gelo.Bool) if !ok { gelo.RuntimeError(vm, command, "argument should be equal to true or false or be absent") } *dst = enabled.True() } else { *dst = true } }
func (p *ConfigParser) discoverable(vm *gelo.VM, args *gelo.List, ac uint) gelo.Word { if ac < 2 || !gelo.StrEqualsSym("at", args.Value.Ser()) { gelo.ArgumentError(vm, "discoverable", "at <port> [<port> ...]", args) } // Check whether we're in common section checkInSection(vm, "discoverable", "common") args = args.Next // Skip first 'at' symbol // Collect all port numbers from the arguments var ports []uint16 for p := args; p != nil; p = p.Next { port, ok := p.Value.(*gelo.Number) if !ok { gelo.RuntimeError(vm, "discoverable arguments should be numbers") } ports = append(ports, uint16(port.Int())) } p.conf.Common.Discoverable = ports return nil }
func IndexError(vm *gelo.VM, idx int, w gelo.Word) { gelo.RuntimeError(vm, "Invalid index", idx, "in", w) }
func runtimeError(vm *gelo.VM, fmt string, args ...interface{}) { gelo.RuntimeError(vm, fmt.Sprintf(fmt, args...)) }