Beispiel #1
0
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
	})
}
Beispiel #2
0
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))
	})
}
Beispiel #3
0
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))
	})
}
Beispiel #4
0
func NS_capture(vm *gelo.VM, args *gelo.List, ac uint) gelo.Word {
	if ac != 1 {
		gelo.ArgumentError(vm, "ns.capture", "code-quote", args)
	}
	cmd, dict := vm.API.QuoteOrElse(args.Value), vm.Ns.Locals(0)
	vm.API.Trace("current namespace captured")
	return gelo.Alien(func(vm *gelo.VM, args *gelo.List, _ uint) gelo.Word {
		vm.API.Trace("switching to captured namespace")
		vm.Ns.Fork(nil)
		defer vm.Ns.Unfork()
		vm.Ns.Inject(0, dict)
		//can't tail invoke because the ns would be unforked
		return vm.API.InvokeCmdOrElse(cmd, args)
	})
}
Beispiel #5
0
func MakeInvokable(vm *gelo.VM, args *gelo.List, ac uint) gelo.Word {
	if ac == 0 {
		return gelo.Noop
	}
	return args.MapOrApply(func(w gelo.Word) gelo.Word {
		i, ok := vm.API.IsInvokable(w)
		if !ok {
			return gelo.Alien(
				func(vm *gelo.VM, args *gelo.List, ac uint) gelo.Word {
					if ac != 0 {
						gelo.ArgumentError(vm, w.Ser(), "", args)
					}
					return w
				})
		}
		return i
	})
}
Beispiel #6
0
func Cleave(vm *gelo.VM, args *gelo.List, ac uint) gelo.Word {
	if ac < 1 {
		gelo.ArgumentError(vm, "cleave", "cmds+", args)
	}
	builder := extensions.ListBuilder()
	defer builder.Destroy()
	for ; args != nil; args = args.Next {
		builder.Push(vm.API.InvokableOrElse(args.Value))
	}
	list := builder.List()
	return gelo.Alien(func(vm *gelo.VM, args *gelo.List, ac uint) gelo.Word {
		builder := extensions.ListBuilder()
		for c := list; c != nil; c = c.Next {
			builder.Push(vm.API.InvokeCmdOrElse(c.Value, args))
		}
		return builder.List()
	})
}
Beispiel #7
0
func Aggregate(items map[string]interface{}) gelo.Alien {
	Map := make(map[string]gelo.Word)
	for k, v := range items {
		Map[k] = gelo.Convert(v)
	}
	d := gelo.NewDictFrom(Map)
	return gelo.Alien(func(vm *gelo.VM, args *gelo.List, ac uint) gelo.Word {
		if ac == 0 {
			return d
		}
		item, there := Map[args.Value.Ser().String()]
		if !there {
			//XXX this error message could be comprehensible in theory
			//will fix itself when vm contains name, lineno, etc
			gelo.ArgumentError(vm, "<an aggregate>", "command args*", args.Next)
		}
		return vm.API.TailInvokeCmd(item, args.Next)
	})
}
Beispiel #8
0
func ArgumentParser(_ *gelo.VM, args *gelo.List, ac uint) gelo.Word {
	parser := extensions.MakeOrElseArgParser(_args_to_spec(args, ac))
	return gelo.Alien(func(vm *gelo.VM, args *gelo.List, _ uint) gelo.Word {
		return gelo.NewDictFrom(parser(vm, args))
	})
}
Beispiel #9
0
func Partial(vm *gelo.VM, args *gelo.List, ac uint) gelo.Word {
	//TODO all of the argument errors in this function could be more informative
	if ac < 2 {
		gelo.ArgumentError(vm, "partial", "command [args*|'*|'X]+", args)
	}
	cmd, args := vm.API.InvokableOrElse(args.Value), args.Next

	a_star := false
	var val gelo.Word
	var kind _partial_kind
	var ph, pt *_partial
	for ; args != nil; args = args.Next {
		kind, val = _pk_fill, nil
		if sym, ok := args.Value.(gelo.Symbol); ok {
			if gelo.StrEqualsSym("X", sym) {
				if a_star {
					gelo.ArgumentError(vm, "partial",
						"there will be no arguments left after *", args)
				}
				kind = _pk_hole
			} else if gelo.StrEqualsSym("*", sym) {
				if a_star {
					gelo.ArgumentError(vm, "partial",
						"only one * can be specfied", args)
				}
				kind, a_star = _pk_slurp, true
			} else {
				val = sym
			}
		} else {
			val = args.Value
		}
		if ph != nil {
			pt.next = &_partial{kind, val, nil}
			pt = pt.next
		} else {
			ph = &_partial{kind, val, nil}
			pt = ph
		}
	}
	pt = nil

	return gelo.Alien(func(vm *gelo.VM, args *gelo.List, ac uint) gelo.Word {
		real_args := extensions.ListBuilder(cmd)
		for pls := ph; pls != nil; pls = pls.next {
			switch pls.kind {
			case _pk_fill:
				real_args.Push(pls.item)
			case _pk_hole:
				if args == nil {
					gelo.ArgumentError(vm, "partial function",
						"requires at least one more argument", args)
				}
				real_args.Push(args.Value)
				args = args.Next
			case _pk_slurp:
				real_args.Extend(args.Copy().(*gelo.List))
				args = nil
			}
		}
		if args != nil {
			gelo.ArgumentError(vm, "partial function", "got too many arguments",
				args)
		}
		return vm.API.InvokeOrElse(real_args.List())
	})
}
Beispiel #10
0
func Dict_sub(vm *gelo.VM, args *gelo.List, ac uint) gelo.Word {
	if ac != 2 {
		gelo.ArgumentError(vm, "dict.sub", "dictionary1 dictionary2", args)
	}
	d1 := vm.API.DictOrElse(args.Value)
	d2 := vm.API.DictOrElse(args.Next.Value)
	for k, _ := range d2.Map() {
		if d1.StrHas(k) {
			d1.StrDel(k)
		}
	}
	return d1
}

var _dict_commands = map[string]gelo.Alien{
	"set!":   gelo.Alien(Dict_setx),
	"set?":   gelo.Alien(Dict_setp),
	"unset!": gelo.Alien(Dict_unsetx),
	"get":    gelo.Alien(Dict_get),
	"get!":   gelo.Alien(Dict_getx),
	"add":    gelo.Alien(Dict_add),
	"sub":    gelo.Alien(Dict_sub),
	"keys":   gelo.Alien(Dict_keys),
	"values": gelo.Alien(Dict_values),
	"items":  gelo.Alien(Dict_items),
}

func DictAggregate(vm *gelo.VM, args *gelo.List, ac uint) gelo.Word {
	if ac < 2 {
		gelo.ArgumentError(vm, "dict", "dictionary command args*", args)
	}