Last active
March 15, 2022 05:47
-
-
Save guregu/0acbcc691b277740ca521b9efc373a4b to your computer and use it in GitHub Desktop.
ichiban/prolog implementation: between/3
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package lib | |
import ( | |
"context" | |
"math" | |
"github.com/ichiban/prolog/engine" | |
"github.com/guregu/predicates/internal" | |
) | |
// Between (between/3) succeeds iff low <= value <= high. | |
// If value is a variable, it is unified with successive integers from low to high. | |
// between(+Low, +High, ?Value). | |
// See: https://www.swi-prolog.org/pldoc/doc_for?object=between/3 | |
func Between(low, high, value engine.Term, k func(*engine.Env) *engine.Promise, env *engine.Env) *engine.Promise { | |
var lo, hi engine.Integer | |
switch l := env.Resolve(low).(type) { | |
case engine.Integer: | |
lo = l | |
case engine.Variable: | |
return engine.Error(engine.ErrInstantiation) | |
default: | |
return engine.Error(internal.TypeErrorInteger(low)) | |
} | |
switch h := env.Resolve(high).(type) { | |
case engine.Integer: | |
hi = h | |
case engine.Variable: | |
return engine.Error(engine.ErrInstantiation) | |
case engine.Atom: | |
switch h { | |
case "infinite", "inf": | |
hi = math.MaxInt64 // is this dumb? | |
default: | |
return engine.Error(internal.TypeErrorInteger(high)) | |
} | |
default: | |
return engine.Error(internal.TypeErrorInteger(high)) | |
} | |
switch x := env.Resolve(value).(type) { | |
case engine.Integer: | |
if x >= lo && x <= hi { | |
return k(env) | |
} | |
return engine.Bool(false) | |
case engine.Variable: | |
return engine.Delay(func(context.Context) *engine.Promise { | |
i := lo - 1 | |
return engine.Repeat(func(context.Context) *engine.Promise { | |
i++ | |
switch { | |
case i-1 > i: | |
return engine.Error(internal.EvaluationErrorIntOverflow()) | |
case i > hi: | |
return engine.Bool(true) | |
} | |
return engine.Unify(value, i, k, env) | |
}) | |
}) | |
} | |
return engine.Error(internal.TypeErrorInteger(value)) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment