Esempio n. 1
0
// ->/2
func BuiltinIfThen(m Machine, args []term.Term) ForeignReturn {
	cond := args[0]
	then := args[1]

	// CUT_BARRIER, (cond, !, then)
	cut := term.NewCallable("!")
	goal := term.NewCallable(",", cond, term.NewCallable(",", cut, then))
	return m.DemandCutBarrier().PushConj(goal)
}
Esempio n. 2
0
func ifThenElse(m Machine, args []term.Term) ForeignReturn {
	semicolon := args[0].(*term.Compound)
	cond := semicolon.Arguments()[0]
	then := semicolon.Arguments()[1]
	els := args[1]

	// CUT_BARRIER, (call(cond), !, then; else)
	cut := term.NewCallable("!")
	cond = term.NewCallable("call", cond)
	goal := term.NewCallable(",", cond, term.NewCallable(",", cut, then))
	goal = term.NewCallable(";", goal, els)
	return m.DemandCutBarrier().PushConj(goal)
}
Esempio n. 3
0
// findall/3
func BuiltinFindall3(m Machine, args []term.Term) ForeignReturn {
	template := args[0]
	goal := args[1]

	// call(Goal), X=Template
	x := term.NewVar("_")
	call := term.NewCallable("call", goal)
	unify := term.NewCallable("=", x, template)
	prove := term.NewCallable(",", call, unify)
	proofs := m.ClearConjs().ClearDisjs().ProveAll(prove)

	// build a list from the results
	instances := make([]term.Term, 0)
	for _, proof := range proofs {
		t, err := proof.Resolve(x)
		MaybePanic(err)
		instances = append(instances, t)
	}

	return ForeignUnify(args[2], term.NewTermList(instances))
}
Esempio n. 4
0
// call/*
func BuiltinCall(m Machine, args []term.Term) ForeignReturn {

	// build a new goal with extra arguments attached
	bodyTerm := args[0].(term.Callable)
	functor := bodyTerm.Name()
	newArgs := make([]term.Term, 0)
	newArgs = append(newArgs, bodyTerm.Arguments()...)
	newArgs = append(newArgs, args[1:]...)
	goal := term.NewCallable(functor, newArgs...)

	// construct a machine that will prove this goal next
	return m.DemandCutBarrier().PushConj(goal)
}
Esempio n. 5
0
func (r *TermReader) restTerm(leftP, p priority, i *lex.List, o **lex.List, leftT term.Term, t *term.Term) bool {
	var op string
	var rightT term.Term
	var opP, lap, rap priority
	//  fmt.Printf("seeking restTerm @ %d with %s\n", p, i.Value.Content)

	if r.infix(&op, &opP, &lap, &rap, i, o) && p >= opP && leftP <= lap && r.term(rap, *o, o, &rightT) {
		//      fmt.Printf("  infix %s\n", op)
		t0 := term.NewCallable(op, leftT, rightT)
		return r.restTerm(opP, p, *o, o, t0, t)
	}
	if r.postfix(&op, &opP, &lap, i, o) && opP <= p && leftP <= lap {
		opT := term.NewCallable(op, leftT)
		return r.restTerm(opP, p, *o, o, opT, t)
	}

	// ε rule can always succeed
	//  fmt.Printf("  invoking ε\n")
	*o = i
	*t = leftT
	return true
}
Esempio n. 6
0
// parse all list items after the first one
func (r *TermReader) listItems(i *lex.List, o **lex.List, t *term.Term) bool {
	var arg, rest term.Term
	if r.tok(',', i, o) && r.term(999, *o, o, &arg) && r.listItems(*o, o, &rest) {
		*t = term.NewCallable(".", arg, rest)
		return true
	}
	if r.tok('|', i, o) && r.term(999, *o, o, &arg) && r.tok(']', *o, o) {
		*t = arg
		return true
	}
	if r.tok(']', i, o) {
		*t = term.NewAtom("[]")
		return true
	}
	return false
}
Esempio n. 7
0
// parse a single term
func (r *TermReader) term(p priority, i *lex.List, o **lex.List, t *term.Term) bool {
	var op, f string
	var t0, t1 term.Term
	var opP, argP priority
	//  fmt.Printf("seeking term with %s\n", i.Value.Content)

	// prefix operator
	if r.prefix(&op, &opP, &argP, i, o) && opP <= p && r.term(argP, *o, o, &t0) {
		opT := term.NewCallable(op, t0)
		return r.restTerm(opP, p, *o, o, opT, t)
	}

	// list notation for compound terms §6.3.5
	if r.tok('[', i, o) && r.term(999, *o, o, &t0) && r.listItems(*o, o, &t1) {
		list := term.NewCallable(".", t0, t1)
		return r.restTerm(0, p, *o, o, list, t)
	}
	if r.tok('[', i, o) && r.tok(']', *o, o) {
		list := term.NewAtom("[]")
		return r.restTerm(0, p, *o, o, list, t)
	}

	// parenthesized terms
	if r.tok('(', i, o) && r.term(1200, *o, o, &t0) && r.tok(')', *o, o) {
		//      fmt.Printf("open paren %s close paren\n", t0)
		return r.restTerm(0, p, *o, o, t0, t)
	}

	switch i.Value.Type {
	case lex.Int: // integer term §6.3.1.1
		n := term.NewInt(i.Value.Content)
		*o = i.Next()
		return r.restTerm(0, p, *o, o, n, t)
	case lex.Float: // float term §6.3.1.1
		f := term.NewFloat(i.Value.Content)
		*o = i.Next()
		return r.restTerm(0, p, *o, o, f, t)
	case lex.Atom: // atom term §6.3.1.3
		a := term.NewAtomFromLexeme(i.Value.Content)
		*o = i.Next()
		return r.restTerm(0, p, *o, o, a, t)
	case lex.String: // double quated string §6.3.7
		cl := term.NewCodeListFromDoubleQuotedString(i.Value.Content)
		*o = i.Next()
		return r.restTerm(0, p, *o, o, cl, t)
	case lex.Variable: // variable term §6.3.2
		v := term.NewVar(i.Value.Content)
		*o = i.Next()
		return r.restTerm(0, p, *o, o, v, t)
	case lex.Void: // variable term §6.3.2
		v := term.NewVar("_")
		*o = i.Next()
		return r.restTerm(0, p, *o, o, v, t)
	case lex.Comment:
		*o = i.Next()              // skip the comment
		return r.term(p, *o, o, t) // ... and try again
	}

	// compound term - functional notation §6.3.3
	if r.functor(i, o, &f) && r.tok('(', *o, o) {
		var args []term.Term
		var arg term.Term
		for r.term(999, *o, o, &arg) { // 999 priority per §6.3.3.1
			args = append(args, arg)
			if r.tok(')', *o, o) {
				break
			}
			if r.tok(',', *o, o) {
				continue
			}
			panic("Unexpected content inside compound term arguments")
		}
		f := term.NewTermFromLexeme(f, args...)
		return r.restTerm(0, p, *o, o, f, t)
	}

	*t = term.NewError("Syntax error", i.Value)
	return false
}