wrapping Python's comparsion (<=, ==), and logical operators (and, or,qq not).
move examples/lists into repl tests.
updated examples/force to use dyna lists
updated some other tests..
+++ /dev/null
-
-Solution
-========
-a = [1, 2].
-b = true.
-c = true.
-d = false.
-things = [1, [2, 2], [3, 4]].
-thingsbag = [1, 1, 2, "three"].
-thingset = [1, 2, "three"].
-
-d/1
-===
-d(2) = true.
-d(4) = true.
-
-f/1
-===
-f([1, 2]).
-
-foo/1
-=====
-foo("a") = true.
-
-goal/1
-======
-goal([2]) = true.
-
-goo/1
-=====
-goo([1, 2]) = true.
-
% Constants
a := 0.15.
-niter := 200.
+niter := 20.
edgelen := 4.0. % "the unit edge length"
% should `a` be negative?
node(U) :- true for _ is edge(U,_).
node(U) :- true for _ is edge(_,U).
-% pack x and y into a tuple
-pos(U,T) := tuple(x(U, T), y(U, T)).
+% pack x and y into a list
+pos(U,T) := [x(U, T), y(U, T)].
% visualization
frame(T, &text(Name, pos(Name, T))) := true for node(Name).
+++ /dev/null
-f([1,2]).
-
-a := [1,2].
-
-goal(X) := f([1|X]).
-
-% structured term, sould be true
-b := &f("a") in [1,2,&f("a"),3].
-
-% should be true
-c := 2 in [1,2,3].
-
-% should be false
-d := 4 in [1,2,3].
-
-% simpler iteration of a complex list
-things set= X for X in [1,[2,2],[3,4]].
-
-% unpack structure requiring a check
-d(&X) := true for [X,X] in [1,[2,2],[3,4],[4,4]].
-
-% these two examples should an interesting behavior
-foo(A) := true for &f(A) in [1,2,&f("a"),3].
-
-% this one checks if the value of f(A) is in the list, (note: 1 == True, in python).
-goo(A) := true for f(A) in [1,2,&f("a"),3].
-
-thingsbag bag= "three".
-thingsbag bag= 1.
-thingsbag bag= 1.
-thingsbag bag= 2.
-
-thingset set= "three".
-thingset set= 1.
-thingset set= 1.
-thingset set= 2.
\ No newline at end of file
where
go ("-",1) = Just $ PDBS $ call "-" []
go ("^",2) = Just $ PDBS $ infixOp "^"
- go ("|",2) = Just $ PDBS $ infixOp "|"
go ("-",2) = Just $ PDBS $ infixOp "-"
go ("/",2) = Just $ PDBS $ infixOp "/"
go ("*",2) = Just $ PDBS $ infixOp "*"
go ("**",2) = Just $ PDBS $ infixOp "**"
- go ("&",2) = Just $ PDBS $ infixOp "&"
- go ("%",2) = Just $ PDBS $ infixOp "%"
go ("+",2) = Just $ PDBS $ infixOp "+"
go ("mod",2) = Just $ PDBS $ infixOp "%"
go ("log",_) = Just $ PDBS $ call "log" []
go ("exp",1) = Just $ PDBS $ call "exp" []
go ("sqrt",1) = Just $ PDBS $ call "sqrt" []
- go ("getattr",_) = Just $ PDBS $ call "getattr" []
+
+
go ("uniform",_) = Just $ PDBS $ call "uniform" []
+ go ("pycall",_) = Just $ PDBS $ call "pycall" []
go ("split",_) = Just $ PDBS $ call "split" []
go ("float",_) = Just $ PDBS $ call "float" []
go ("int",_) = Just $ PDBS $ call "int" []
- go ("pycall",_) = Just $ PDBS $ call "pycall" []
-
go ("range",_) = Just $ PDBS $ call "range" []
- go ("in",2) = Just $ PDBS $ call "in_list" []
-
- go ("<=",2) = Just $ PDBS $ infixOp "<="
- go ("<",2) = Just $ PDBS $ infixOp "<"
- go ("=",2) = Just $ PDBS $ call "equals" []
- go ("==",2) = Just $ PDBS $ call "equals" []
- go (">=",2) = Just $ PDBS $ infixOp ">="
- go (">",2) = Just $ PDBS $ infixOp ">"
- go ("!=",2) = Just $ PDBS $ infixOp "!="
+ go ("<=",2) = Just $ PDBS $ call "lte" []
+ go ("<",2) = Just $ PDBS $ call "lt" []
+ go ("=",2) = Just $ PDBS $ call "eq" []
+ go ("==",2) = Just $ PDBS $ call "eq" []
+ go (">=",2) = Just $ PDBS $ call "gte" []
+ go (">",2) = Just $ PDBS $ call "gt" []
+ go ("!=",2) = Just $ PDBS $ call "not_eq" []
- go ("and",2) = Just $ PDBS $ infixOp "and"
- go ("or",2) = Just $ PDBS $ infixOp "or"
+ go ("|",2) = Just $ PDBS $ call "or_" []
+ go ("&",2) = Just $ PDBS $ call "and_" []
+ go ("!",1) = Just $ PDBS $ call "not_" []
- go ("true",0) = Just $ PDBS $ nullary "True"
- go ("false",0) = Just $ PDBS $ nullary "False"
- go ("null",0) = Just $ PDBS $ nullary "None"
+ go ("true",0) = Just $ PDBS $ nullary "true"
+ go ("false",0) = Just $ PDBS $ nullary "false"
+ go ("null",0) = Just $ PDBS $ nullary "null"
- go ("!",1) = Just $ PDBS $ call "not" []
- go ("not",1) = Just $ PDBS $ call "not" []
-
- go ("eval",1) = Just $ PDBS $ call "None;exec " []
- go ("tuple",_) = Just $ PDBS $ call "" []
+ --go ("eval",1) = Just $ PDBS $ call "None;exec " []
+ --go ("tuple",_) = Just $ PDBS $ call "" []
+ go ("in",2) = Just $ PDBS $ call "in_list" []
go ("nil",0) = Just $ PDBS $ call "build" ["nil/0"]
go ("cons",2) = Just $ PDBS $ call "build" ["cons/2"]
pdope_ :: S.Set DFunctAr -> DOpAMine PyDopeBS -> State Int (Doc e)
pdope_ _ (OPIndr _ _) = dynacSorry "indirect evaluation not implemented"
pdope_ _ (OPAsgn v val) = return $ pretty v <+> equals <+> pretty val
-pdope_ _ (OPCheq v val) = return $ "if not equals(" <> pretty v <> ", " <> pretty val <> "): continue"
-pdope_ _ (OPCkne v val) = return $ "if equals(" <> pretty v <> ", " <> pretty val <> "): continue"
+pdope_ _ (OPCheq v val) = return $ "if not eq(" <> pretty v <> ", " <> pretty val <> "): continue"
+pdope_ _ (OPCkne v val) = return $ "if eq(" <> pretty v <> ", " <> pretty val <> "): continue"
pdope_ _ (OPPeel vs i f _) = return $
"try:" `above` (indent 4 $
tupledOrUnderscore vs
test_End_To_End :: [Test]
test_End_To_End = map mkExample
[ "simple", "equalities", "fib-limit", "dijkstra", "papa2", "matrixops"
- , "factorial-bc", "geom", "lists", "dijkstra-backpointers" ]
+ , "factorial-bc", "geom", "dijkstra-backpointers" ]
--test_REPL :: [Test]
--test_REPL = map (\n -> testProgramRuns n ("./test/repl/"++n) [])
import operator
from collections import Counter
-from utils import drepr, _repr, user_vars
+from utils import drepr, _repr, user_vars, isbool, true, false
from errors import AggregatorError
s = [x for x, m in self.iteritems() if m > 0]
if len(s):
for val in s:
- if val is not True and val is not False:
+ if not isbool(val):
raise TypeError('%s is not Boolean.' % _repr(val))
- return reduce(lambda x,y: x or y, s)
+ # TODO: can short circuit as soon as we get a true... but above we
+ # check the types.. so we don't get the benefit.
+ for val in s:
+ if val is true:
+ return true
+ return false
+
class and_equals(BAggregator):
s = [x for x, m in self.iteritems() if m > 0]
if len(s):
for val in s:
- if val is not True and val is not False:
+ if not isbool(val):
raise TypeError('%s is not Boolean.' % _repr(val))
- return reduce(lambda x,y: x and y, s)
+ # TODO: can short circuit as soon as we get a false. but above we
+ # check the types.. so we don't get the benfit
+ for val in s:
+ if val is false:
+ return false
+ return true
+
class set_equals(BAggregator):
def fold(self):
from collections import defaultdict
from aggregator import aggregator
from term import Term
-from utils import _repr
-from stdlib import equals
+from utils import _repr, true
+
class Chart(object):
heading = [self.name, '='*len(self.name)]
# special handing or-equals aggregators -- only list true facts (and errors)
- if self.agg_name == ':-' or self.agg_name == '|=':
+ if self.agg_name == ':-':
lines = []
for term in sorted(rows):
- if term.value is True:
+ if term.value is true:
lines.append('%s.' % _repr(term))
elif term.value: # e.g. $error
lines.append('%s = %s.' % (_repr(term), _repr(term.value)))
yield term, term.args, term.value
else:
for term in candidates:
- if equals(term.value, val):
+ if term.value == val:
yield term, term.args, term.value
def insert(self, args): # TODO: rename
from term import Term, Cons, Nil, MapsTo
from chart import Chart
from utils import ip, red, green, blue, magenta, yellow, parse_attrs, \
- ddict, dynac, read_anf, strip_comments, _repr, hide_ugly_filename
+ ddict, dynac, read_anf, strip_comments, _repr, hide_ugly_filename, \
+ true, false
from prioritydict import prioritydict
from config import dotdynadir
def build(self, fn, *args):
# TODO: codegen should handle true/0 is True and false/0 is False
if fn == 'true/0':
- return True
+ return true
if fn == 'false/0':
- return False
+ return false
if fn == 'cons/2':
return Cons(*args)
if fn == 'nil/0':
return Nil
if fn == '->/2':
return MapsTo(*args)
-
if fn == '$key/1':
self.new_fn(fn, '=')
# remove $rule
if hasattr(rule, 'item'):
- self.delete_emit(rule.item, True, ruleix=None, variables=None)
+ self.delete_emit(rule.item, true, ruleix=None, variables=None)
if rule.init is not None:
# remove update handlers
# Thus, we can skip the delete-updates.
self.update_dispatcher(item, was, delete=True)
+
+ assert now is not True or now is not False # invalid dyna types.
+
item.value = now
if now is not None:
h(*args, emit=_emit)
head.value = head.aggregator.fold()
+
return head.value
def new_query(self, fn, ruleix, handler):
if interp.agg_name[fn] is None:
interp.new_fn(fn, ':=')
item = interp.build(fn, ix, *a)
- interp.emit(item, True, ruleix=None, variables=None, delete=False)
+ interp.emit(item, true, ruleix=None, variables=None, delete=False)
return item
for i in new_rules:
r = self.rules[i]
and constants (possibly an empty tuple).
"""
if fn == "true/0":
- assert item is True
+ assert item is true
return
if fn == "false/0":
- assert item is False
+ assert item is false
return
assert isinstance(item, Term)
assert item.fn == fn
"""
import re
+from utils import true
class tsv(object):
"""
fn = '%s/%s' % (name, len(a))
if interp.agg_name[fn] is None:
- interp.new_fn(fn, ':=')
+ interp.new_fn(fn, ':-')
interp.emit(interp.build(fn, *a),
- True,
+ true,
ruleix=None,
variables=None,
delete=False)
import re
from term import Term, Cons, Nil, MapsTo
from collections import Counter
-from utils import pretty, pretty_print
-
-
+from utils import pretty, pretty_print, true, false, null, isbool
from math import log, exp, sqrt
from random import random as _random
+
def uniform(a=0, b=1):
return _random() * (b - a) + a
-def equals(x,y):
+def or_(x, y):
+ if not (isbool(x) and isbool(y)):
+ raise TypeError('')
+ return todyna(x or y)
+
+def and_(x, y):
+ if not (isbool(x) and isbool(y)):
+ raise TypeError('')
+ return todyna(x and y)
+
+def not_(x):
+ if not isbool(x):
+ raise TypeError('')
+ if x:
+ return false
+ else:
+ return true
+
+def gt(x, y):
+ return todyna(x > y)
+
+def gte(x, y):
+ return todyna(x >= y)
+
+def lt(x, y):
+ return todyna(x < y)
+
+def lte(x, y):
+ return todyna(x <= y)
+
+def eq(x,y):
"""
My work around for discrepency in bool equality True==1 and False==0.
- >>> equals(True, 1)
- False
+ >>> eq(true, 1)
+ false
- >>> equals(1, 1.0)
- True
+ >>> eq(1, 1.0)
+ true
"""
- if isinstance(x, bool) or isinstance(y, bool):
- return type(x) == type(y) and x == y
- else:
- return x == y
+ return todyna(x == y)
+def not_eq(x, y):
+ if x != y:
+ return true
+ else:
+ return false
_range = range
def range(*x):
return todyna(_range(*x))
+
def split(s, delim='\s+'):
- return todynalist(re.split(delim, s))
+ return todyna(re.split(delim, s))
+
def crash():
class Crasher(Exception): pass
raise Crasher('Hey, you asked for it!')
+
def pycall(name, *args):
"""
Temporary foreign function interface - call Python functions from dyna!
def topython(x):
- #if isinstance(x, AList) or x is Nil:
- # return {topython(k): topython(v) for k,v in x.aslist}
- if isinstance(x, Cons) or x is Nil:
- return [topython(y) for y in x.aslist]
- return x
-
-def todynalist(x): # TODO: get rid of this.
- return todyna(x)
+ if islist(x):
+ return [topython(y) for y in x.aslist]
-def getkey(m, k):
- return m[k]
+ elif isinstance(x, MapsTo):
+ return tuple(x.args)
-def setkey(m, k, v):
- m[k] = v
- return m
+ return x
def todyna(x):
x.sort()
return todyna(x)
+ elif x is True:
+ return true
+
+ elif x is False:
+ return false
+
elif isinstance(x, dict):
- #c = Nil
- #for k,v in x.items():
- # c = AList(todyna([k,v]), c)
- #return c
return todyna([MapsTo(k,v) for k,v in x.items()])
elif isinstance(x, (list, tuple)):
c = Cons(todyna(y), c)
return c
else:
+
return x
def get(x, i):
return x[i]
+
+def getkey(m, k):
+ return m[k]
+
+
+def setkey(m, k, v):
+ m[k] = v
+ return m
+
+
+def islist(x):
+ return isinstance(x, Cons) or x is Nil
+
+
def iter_cons(x):
- if not (isinstance(x, Cons) or x is Nil):
- raise TypeError("Attemping to iterate something which isn't a list.")
+ if not islist(x):
+ raise TypeError("Attemping to iterate something which isn't a list. %r" % (x,))
return x.like_chart()
+
def in_list(x, a):
- if not (isinstance(a, Cons) or a is Nil):
- raise TypeError("Attemping to iterate something which isn't a list.")
+ if not islist(a):
+ raise TypeError("Attemping to iterate something which isn't a list. %r" % (a,))
return x in a.aslist
+
# should probably be done with memoized backchaining...
def read_lines(filename):
with file(filename) as f:
from errors import notimplemented
-from utils import _repr
+from utils import _repr, true, false
from aggregator import NoAggregator
return '[%s]' % (', '.join(map(_repr, self.aslist)))
def __contains__(self, x):
- return x in self.aslist
+ if x in self.aslist:
+ return true
+ else:
+ return false
def like_chart(self):
for a in self.aslist:
return '[]'
def __contains__(self, x):
- return False
+ return false
def like_chart(self):
return iter([])
from cStringIO import StringIO
+
+class _true(object):
+ def __nonzero__(self):
+ return True
+ def __repr__(self):
+ return 'true'
+
+class _false(object):
+ def __nonzero__(self):
+ return False
+ def __repr__(self):
+ return 'false'
+
+true = _true()
+false = _false()
+null = None
+
+def isbool(x):
+ return x is true or x is false
+
+
+
+
def _repr(x):
+
+# TODO: this assertion should eventually hold.
+# assert x is not True and x is not False, x
if x is True:
return 'true'
elif x is False:
return 'false'
+
elif x is None:
return 'null'
elif isinstance(x, basestring):
d(2) = true.
d(4) = true.
-% quote is important! or else we enumerate everything!
-> foo(A) := true for &bar(A) in [1,2,&bar("a"),3].
-|
-| bar("int") = 1.
+
+% let's look at a the difference between Booleans and integers
+> bar("int") = 1.
| bar("bool") = true.
-| bar("spaz") = 2.
-|
-| goo(A) := true for bar(A) in [true,2,&bar("a"),3].
+| bar("two") = 2.
Changes
=======
bar("bool") = true.
bar("int") = 1.
-bar("spaz") = 2.
+bar("two") = 2.
+
+% quote is important! or else we enumerate everything!
+> foo(A) := true for &bar(A) in [1,2,&bar("a"),3].
+
+Changes
+=======
foo("a") = true.
+
+% if you don't quote bar(A) drives the querym checking membership in the list.
+> goo(A) := true for bar(A) in [true,2,&bar("a")].
+
+Changes
+=======
goo("bool") = true.
-goo("int") = true. % TODO: this should't appear in the results (XREF:bool)
-goo("spaz") = true.
+goo("two") = true.
% unfortunately 1 == true and 0 == false in python so the following is true
Changes
=======
-testbool = true. % TODO: XREF:bool
+testbool = false.
% fun with set= at bag=
Changes
=======
-thingsbag = [1, 1, 1, 2, "three"].
-thingset = [1, 2, "three"].
+thingsbag = [1, 1, 2, "three", true].
+thingset = [1, 2, true, "three"].