コード例 #1
0
ファイル: combinator.go プロジェクト: catb0t/gelo
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()
	})
}
コード例 #2
0
ファイル: dict.go プロジェクト: catb0t/gelo
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()
}
コード例 #3
0
ファイル: regexp.go プロジェクト: catb0t/gelo
func Re_matches(vm *gelo.VM, args *gelo.List, ac uint) gelo.Word {
	if ac != 2 {
		gelo.ArgumentError(vm, "matches", "regexp string", args)
	}
	r := ReOrElse(vm, args.Value)
	s := args.Next.Value.Ser().Bytes()
	list := extensions.ListBuilder()
	for _, v := range r.FindSubmatch(s) {
		list.Push(gelo.BytesToSym(v))
	}
	return list.List()
}
コード例 #4
0
ファイル: combinator.go プロジェクト: catb0t/gelo
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))
	})
}
コード例 #5
0
ファイル: control.go プロジェクト: catb0t/gelo
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
}
コード例 #6
0
ファイル: combinator.go プロジェクト: catb0t/gelo
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())
	})
}