func MaybeArgumentParser(_ *gelo.VM, args *gelo.List, ac uint) gelo.Word { parser := extensions.MakeArgParser(_args_to_spec(args, ac)) return gelo.Alien(func(vm *gelo.VM, args *gelo.List, _ uint) gelo.Word { Args, ok := parser(args) if !ok { return gelo.NewList(gelo.False) } return gelo.NewList(gelo.True, gelo.NewDictFrom(Args)) }) }
func Dict_items(vm *gelo.VM, args *gelo.List, ac uint) gelo.Word { if ac != 1 { gelo.ArgumentError(vm, "dict.values", "dictionary", args) } d, list := vm.API.DictOrElse(args.Value), extensions.ListBuilder() for k, v := range d.Map() { list.Push(gelo.NewList(gelo.NewList(gelo.StrToSym(k), v))) } return list.List() }
func Re_replace_by(vm *gelo.VM, args *gelo.List, ac uint) gelo.Word { if ac != 3 { gelo.ArgumentError(vm, "replace-all", "regexp string replace-cmd", args) } r := ReOrElse(vm, args.Value) src := args.Next.Value.Ser().Bytes() repl := args.Next.Next.Value return gelo.BytesToSym(r.ReplaceAllFunc(src, func(s []byte) []byte { args := gelo.NewList(gelo.BytesToSym(s)) return vm.API.InvokeCmdOrElse(repl, args).Ser().Bytes() })) }
func MakeArgParser(spec string) func(*gelo.List) (map[string]gelo.Word, bool) { if len(spec) == 0 || gelo.SlurpWS([]byte(spec), 0) == len(spec) { return _empty_parser } pp := &__arg_parserparser{ make(map[string]bool), nil, []byte(spec), _char, -1, new(bytes.Buffer)} p := pp._parse_seq(true) pp.buf = nil //allow these to be garbage collected pp.spec = nil //TODO pass map[string]bool around instead of pp return func(args *gelo.List) (map[string]gelo.Word, bool) { //don't want old matches skewing results so we create an l map each time pp.l = make(map[string]bool) //attempt to match ok, m := p.match(args, pp) if !ok || m.cont != nil { return nil, false } defer func() { pp.l = nil }() out := make(map[string]gelo.Word) repeat := make(map[string]*gelo.List) //process matches for kv := m.head; kv != nil; kv = kv.next { key, val := kv.key, kv.val if pp.s[key] { //symbol out[key] = gelo.Null } else if pp.l[key] { //list if tail, ok := repeat[key]; ok { tail.Next = &gelo.List{val, nil} repeat[key] = tail.Next } else { //not seen yet l := &gelo.List{val, nil} out[key] = l repeat[key] = l } } else { //single var if v, ok := out[key]; ok { //promote to list pp.l[key] = true l := gelo.NewList(v, val) out[key] = l repeat[key] = l.Next } else { //just assign out[key] = val } } } return out, true } }