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 ArgumentError(vm *gelo.VM, args *gelo.List, ac uint) gelo.Word { if ac != 2 { gelo.ArgumentError(vm, "ArgumentError", "name arg-spec args", args) } gelo.ArgumentError(vm, args.Value.Ser(), args.Next.Value.Ser(), args.Next.Next.Value.Ser()) panic("Issue 65") }
func DictAggregate(vm *gelo.VM, args *gelo.List, ac uint) gelo.Word { if ac < 2 { gelo.ArgumentError(vm, "dict", "dictionary command args*", args) } d := args.Value command := args.Next.Value.Ser().String() rest := args.Next.Next if _, ok := _dict_commands[command]; !ok { gelo.ArgumentError(vm, "dict", "dictionary 'set!|'unset!|'get|'get!|'set?|'keys|'value args*", command) } return _dict_commands[command](vm, &gelo.List{d, rest}, ac-1) }
func MakeOrElseArgParser(spec string) func(*gelo.VM, *gelo.List) map[string]gelo.Word { parser := MakeArgParser(spec) return func(vm *gelo.VM, args *gelo.List) map[string]gelo.Word { Args, ok := parser(args) if !ok { if len(spec) != 0 { gelo.ArgumentError(vm, "argparser", spec, args) } else { gelo.ArgumentError(vm, "argparser", "no arguments", args) } } return Args } }
func (p *ConfigParser) set(vm *gelo.VM, args *gelo.List, ac uint) gelo.Word { if ac == 0 { gelo.ArgumentError(vm, "set", "<name> [args*]", args) } name := vm.API.SymbolOrElse(args.Value) // Check that we're in correct section checkInSection(vm, "set", "port", "plugin") // Check that all arguments are compatible values for tmp := args; tmp != nil; tmp = tmp.Next { _, oksym := tmp.Value.(gelo.Symbol) _, oknum := tmp.Value.(*gelo.Number) _, okbool := tmp.Value.(gelo.Bool) if !(oksym || oknum || okbool) { runtimeError(vm, "Arguments of set should be symbols or numbers or booleans") } } var values *gelo.List if ac == 1 { values = gelo.NewListFromGo([]interface{}{gelo.True}) } else { values = args.Next } d := getOrMakeDict(vm, "data") d.Set(name, values) return nil }
func NS_globals(vm *gelo.VM, args *gelo.List, ac uint) gelo.Word { if ac != 0 { gelo.ArgumentError(vm, "ns.globals", "", args) } d := vm.Ns.Locals(-1) return d }
func PortClosedp(vm *gelo.VM, args *gelo.List, ac uint) gelo.Word { if ac != 1 { gelo.ArgumentError(vm, "closed?", "port", args) } p := vm.API.PortOrElse(args.Value) return gelo.ToBool(p.Closed()) }
func (p *ConfigParser) plugin(vm *gelo.VM, args *gelo.List, ac uint) gelo.Word { if ac != 2 { gelo.ArgumentError(vm, "plugin", "<name> {body}", args) } name := args.Value.Ser().String() body := vm.API.QuoteOrElse(args.Next.Value) checkInSection(vm, "plugin", "plugins") insideSection(vm, "plugin", name, func() { p.conf.Plugins[name] = new(conf.PluginConf) p.conf.Plugins[name].Name = name vm.API.InvokeCmdOrElse(body, args) p.conf.Plugins[name].Options = make(map[string][]string) d := getOrMakeDict(vm, "data") for k, v := range d.Map() { var elements []string args.Slice() for e := vm.API.ListOrElse(v); e != nil; e = e.Next { elements = append(elements, e.Value.Ser()) } p.conf.Plugins[name].Options[k] = elements } }, ) return nil }
//For each item, Value acts as the identity unless the item is a quote. //If it is a quote attempt to invoke and return result if there were no errors //If invocation fails for any reason Value returns the quote as a literal. func Value(vm *gelo.VM, args *gelo.List, ac uint) gelo.Word { if ac == 0 { gelo.ArgumentError(vm, "value", "items+", "") } return args.MapOrApply(func(w gelo.Word) gelo.Word { return vm.API.TailInvokeWordOrReturn(w) }) }
func Copy(vm *gelo.VM, args *gelo.List, ac uint) gelo.Word { if ac == 0 { gelo.ArgumentError(vm, "copy", "values+", "") } return args.MapOrApply(func(w gelo.Word) gelo.Word { return w.Copy() }) }
func Mod(vm *gelo.VM, args *gelo.List, ac uint) gelo.Word { if ac != 2 { gelo.ArgumentError(vm, "mod", "number base", args) } n := vm.API.NumberOrElse(args.Value).Real() m := vm.API.NumberOrElse(args.Next.Value).Real() return gelo.NewNumber(math.Mod(n, m)) }
func TypeMismatchError(vm *gelo.VM, args *gelo.List, ac uint) gelo.Word { if ac != 2 { gelo.ArgumentError(vm, "TypeMismatchError", "expected-type recieved-type", args) } gelo.TypeMismatch(vm, args.Value.Ser(), args.Next.Value.Ser()) panic("Issue 65") }
func SyntaxError(vm *gelo.VM, args *gelo.List, ac uint) gelo.Word { if ac == 0 { gelo.ArgumentError(vm, "SyntaxError", "error-msg+", "") } //TODO should get a line-no, etc to allow creation of good error message gelo.SyntaxError(args) panic("Issue 65") }
func Dict_setp(vm *gelo.VM, args *gelo.List, ac uint) gelo.Word { if ac != 2 { gelo.ArgumentError(vm, "dict.setp?", "dictionary key", args) } d := vm.API.DictOrElse(args.Value.(*gelo.Dict)) k := args.Next.Value return gelo.ToBool(d.Has(k)) }
func NS_inject(vm *gelo.VM, args *gelo.List, ac uint) gelo.Word { if ac != 1 { gelo.ArgumentError(vm, "ns.inject", "dictionary", args) } d := vm.API.DictOrElse(args.Value) vm.Ns.Inject(0, d) return d }
func Setx(vm *gelo.VM, args *gelo.List, ac uint) gelo.Word { if ac != 2 { gelo.ArgumentError(vm, "set!", "name value", args) } val := args.Next.Value vm.Ns.Set(0, args.Value, val) return val }
//Commands for namespaces func NS_fork(vm *gelo.VM, args *gelo.List, ac uint) gelo.Word { if ac != 0 { gelo.ArgumentError(vm, "ns.fork", "", args) } vm.Ns.Fork(nil) vm.API.Trace("Child namespace created") return gelo.Null }
func Re_matchp(vm *gelo.VM, args *gelo.List, ac uint) gelo.Word { if ac != 2 { gelo.ArgumentError(vm, "match?", "regexp string", args) } r := ReOrElse(vm, args.Value) s := args.Next.Value.Ser().Bytes() return gelo.ToBool(r.Match(s)) }
func Type_of(vm *gelo.VM, args *gelo.List, ac uint) gelo.Word { if ac == 0 { gelo.ArgumentError(vm, "type-of", "value+", "") } return args.MapOrApply(func(w gelo.Word) gelo.Word { return w.Type() }) }
func Re_replace(vm *gelo.VM, args *gelo.List, ac uint) gelo.Word { if ac != 3 { gelo.ArgumentError(vm, "replace-all", "regexp string replace", args) } r := ReOrElse(vm, args.Value) src := args.Next.Value.Ser().Bytes() repl := args.Next.Next.Value.Ser().Bytes() return gelo.BytesToSym(r.ReplaceAll(src, repl)) }
func Setp(vm *gelo.VM, args *gelo.List, ac uint) gelo.Word { if ac == 0 { gelo.ArgumentError(vm, "set?", "name+", args) } return args.MapOrApply(func(w gelo.Word) gelo.Word { _, ok := vm.Ns.Lookup(w) return gelo.ToBool(ok) }) }
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 Dict_setx(vm *gelo.VM, args *gelo.List, ac uint) gelo.Word { if ac != 3 { gelo.ArgumentError(vm, "dict.set", "dictionary key value", args) } d := vm.API.DictOrElse(args.Value) k := args.Next.Value v := args.Next.Next.Value d.Set(k, v) return v }
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 Dict_keys(vm *gelo.VM, args *gelo.List, ac uint) gelo.Word { if ac != 1 { gelo.ArgumentError(vm, "dict.keys", "dictionary", args) } d, list := vm.API.DictOrElse(args.Value), extensions.ListBuilder() for k, _ := range d.Map() { list.Push(gelo.StrToSym(k)) } return list.List() }
//Not the best name. Rewrites quote (ie rewrites $@[]) then returns //a list of lists of symbols func Partial_eval(vm *gelo.VM, args *gelo.List, ac uint) gelo.Word { if ac != 1 { gelo.ArgumentError(vm, "partial-eval", "quote", args) } lists, ok := vm.API.PartialEval(vm.API.QuoteOrElse(args.Value)) if !ok { gelo.TypeMismatch(vm, "code quote", "literal quote") } return lists }
func ReCon(vm *gelo.VM, args *gelo.List, ac uint) gelo.Word { if ac != 1 { gelo.ArgumentError(vm, "Re", "specification", args) } spec := vm.API.LiteralOrElse(args.Value) rex, err := regexp.Compile(string(spec)) if err != nil { gelo.SyntaxError(vm, err.Error()) } return &Regexp{rex} }
func Updatex(vm *gelo.VM, args *gelo.List, ac uint) gelo.Word { if ac != 2 { gelo.ArgumentError(vm, "update!", "name value", args) } toreset := args.Value val := args.Next.Value if !vm.Ns.Mutate(toreset, val) { gelo.VariableUndefined(vm, toreset) } return val }
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 Unsetx(vm *gelo.VM, args *gelo.List, ac uint) gelo.Word { if ac == 0 { gelo.ArgumentError(vm, "unset!", "name+", args) } return args.MapOrApply(func(w gelo.Word) gelo.Word { val, ok := vm.Ns.Del(w) if !ok { gelo.VariableUndefined(vm, w) } return val }) }