[pypy-svn] r43600 - in pypy/dist/pypy/lang/prolog/interpreter: . test
cfbolz at codespeak.net
cfbolz at codespeak.net
Thu May 24 16:30:14 CEST 2007
Author: cfbolz
Date: Thu May 24 16:30:14 2007
New Revision: 43600
Modified:
pypy/dist/pypy/lang/prolog/interpreter/arithmetic.py
pypy/dist/pypy/lang/prolog/interpreter/error.py
pypy/dist/pypy/lang/prolog/interpreter/helper.py
pypy/dist/pypy/lang/prolog/interpreter/parsing.py
pypy/dist/pypy/lang/prolog/interpreter/term.py
pypy/dist/pypy/lang/prolog/interpreter/test/test_parsing.py
Log:
refactor arithmetic functions a bit. rename the .num attribute of Float
instances too floatval, to be less confusing.
Modified: pypy/dist/pypy/lang/prolog/interpreter/arithmetic.py
==============================================================================
--- pypy/dist/pypy/lang/prolog/interpreter/arithmetic.py (original)
+++ pypy/dist/pypy/lang/prolog/interpreter/arithmetic.py Thu May 24 16:30:14 2007
@@ -9,25 +9,83 @@
pattern_to_function = {}
-def wrap_builtin_operation(pattern, unwrap_spec, can_overflow):
- code = ["def f(engine, query):"]
+class CodeCollector(object):
+ def __init__(self):
+ self.code = []
+ self.blocks = []
+
+ def emit(self, line):
+ for line in line.split("\n"):
+ self.code.append(" " * (4 * len(self.blocks)) + line)
+
+ def start_block(self, blockstarter):
+ assert blockstarter.endswith(":")
+ self.emit(blockstarter)
+ self.blocks.append(blockstarter)
+
+ def end_block(self, starterpart=""):
+ block = self.blocks.pop()
+ assert starterpart in block, "ended wrong block %s with %s" % (
+ block, starterpart)
+
+ def tostring(self):
+ assert not self.blocks
+ return "\n".join(self.code)
+
+def wrap_builtin_operation(name, pattern, unwrap_spec, can_overflow, intversion):
+ code = CodeCollector()
+ code.start_block("def prolog_%s(engine, query):" % name)
for i, spec in enumerate(unwrap_spec):
varname = "var%s" % (i, )
- code.append(
- " %s = eval_arithmetic(engine, query.args[%s])" % (varname, i))
- code.append(
- " v%s = 0" % (i, ))
- code.append(" if isinstance(%s, term.Number):" % (varname, ))
- code.append(" v%s = %s.num" % (i, varname))
+ code.emit("%s = eval_arithmetic(engine, query.args[%s])" %
+ (varname, i))
+ for i, spec in enumerate(unwrap_spec):
+ varname = "var%s" % (i, )
+ if spec == "int":
+ code.start_block(
+ "if not isinstance(%s, term.Number):" % (varname, ))
+ code.emit("error.throw_type_error('int', %s)" % (varname, ))
+ code.end_block("if")
+ if "expr" in unwrap_spec and intversion:
+ # check whether all arguments are ints
+ for i, spec in enumerate(unwrap_spec):
+ varname = "var%s" % (i, )
+ if spec == "int":
+ continue
+ code.start_block(
+ "if isinstance(%s, term.Number):" % (varname, ))
+ code.emit("v%s = var%s.num" % (i, i))
+ code.emit("return term.Number(int(%s))" % (pattern, ))
+ for i, spec in enumerate(unwrap_spec):
+ if spec == "int":
+ continue
+ code.end_block("if")
+
+ #general case in an extra function
+ args = ", ".join(["var%s" % i for i in range(len(unwrap_spec))])
+ code.emit("return general_%s(%s)" % (name, args))
+ code.end_block("def")
+ code.start_block("def general_%s(%s):" % (name, args))
+ for i, spec in enumerate(unwrap_spec):
+ varname = "var%s" % (i, )
+ code.emit("v%s = 0" % (i, ))
+ code.start_block("if isinstance(%s, term.Number):" % (varname, ))
+ code.emit("v%s = %s.num" % (i, varname))
+ code.end_block("if")
+ expected = 'int'
if spec == "expr":
- code.append(" elif isinstance(%s, term.Float):" % (varname, ))
- code.append(" v%s = %s.num" % (i, varname))
- code.append(" else:")
- code.append(" error.throw_type_error('int', %s)" % (varname, ))
- code.append(" return norm_float(%s)" % pattern)
+ code.start_block("elif isinstance(%s, term.Float):" % (varname, ))
+ code.emit("v%s = %s.floatval" % (i, varname))
+ code.end_block("elif")
+ expected = 'float'
+ code.start_block("else:")
+ code.emit("error.throw_type_error('%s', %s)" % (expected, varname, ))
+ code.end_block("else")
+ code.emit("return norm_float(term.Float(%s))" % pattern)
+ code.end_block("def")
miniglobals = globals().copy()
- exec py.code.Source("\n".join(code)).compile() in miniglobals
- return miniglobals['f']
+ exec py.code.Source(code.tostring()).compile() in miniglobals
+ return miniglobals["prolog_" + name]
wrap_builtin_operation._annspecialcase_ = 'specialize:memo'
@@ -36,14 +94,14 @@
if isinstance(query, term.Number):
return query
if isinstance(query, term.Float):
- return norm_float(query.num)
+ return norm_float(query)
if isinstance(query, term.Atom):
#XXX beautify that
if query.name == "pi":
return term.Float(math.pi)
if query.name == "e":
return term.Float(math.e)
- raise error.UncatchableError("not implemented")
+ error.throw_type_error("evaluable", query.get_prolog_signature())
if isinstance(query, term.Term):
func = arithmetic_functions.get(query.signature, None)
if func is None:
@@ -51,37 +109,45 @@
return func(engine, query)
raise error.UncatchableError("not implemented")
-def norm_float(v):
+def norm_float(obj):
+ v = obj.floatval
if v == int(v):
return term.Number(int(v))
else:
- return term.Float(v)
+ return obj
simple_functions = [
- ("+", ["expr", "expr"], "v0 + v1", True),
- ("-", ["expr", "expr"], "v0 - v1", True),
- ("*", ["expr", "expr"], "v0 * v1", True),
- ("//", ["int", "int"], "v0 / v1", True),
- ("**", ["expr", "expr"], "v0 ** v1", True),
- (">>", ["int", "int"], "v0 >> v1", False),
- ("<<", ["int", "int"], "intmask(v0 << v1)", False),
- ("\\/", ["int", "int"], "v0 | v1", False),
- ("/\\", ["int", "int"], "v0 & v1", False),
- ("xor", ["int", "int"], "v0 ^ v1", False),
- ("mod", ["int", "int"], "v0 % v1", False),
- ("\\", ["int"], "v0 ^ 0", False),
- ("abs", ["expr"], "abs(v0)", True),
-# ("max", ["expr", "expr"], "max(v0, v1)", False),
-# ("min", ["expr", "expr"], "min(v0, v1)", False),
- ("round", ["expr"], "int(v0 + 0.5)", False),
- ("floor", ["expr"], "math.floor(v0)", False),
- ("ceiling", ["expr"], "math.ceil(v0)", False),
- ("floor", ["expr"], "math.floor(v0)", False),
- ("float_fractional_part", ["expr"], "v0 - int(v0)", False),
- ("float_integer_part", ["expr"], "int(v0)", False),
+ ("+", ["expr", "expr"], "v0 + v1", True, True),
+ ("-", ["expr", "expr"], "v0 - v1", True, True),
+ ("*", ["expr", "expr"], "v0 * v1", True, True),
+ ("//", ["int", "int"], "v0 / v1", True, False),
+ ("**", ["expr", "expr"], "v0 ** v1", True, True),
+ (">>", ["int", "int"], "v0 >> v1", False, False),
+ ("<<", ["int", "int"], "intmask(v0 << v1)", False,
+ False),
+ ("\\/", ["int", "int"], "v0 | v1", False, False),
+ ("/\\", ["int", "int"], "v0 & v1", False, False),
+ ("xor", ["int", "int"], "v0 ^ v1", False, False),
+ ("mod", ["int", "int"], "v0 % v1", False, False),
+ ("\\", ["int"], "~v0", False, False),
+ ("abs", ["expr"], "abs(v0)", True, True),
+ ("max", ["expr", "expr"], "max(v0, v1)", False, True),
+ ("min", ["expr", "expr"], "min(v0, v1)", False, True),
+ ("round", ["expr"], "int(v0 + 0.5)", False, False),
+ ("floor", ["expr"], "math.floor(v0)", False, True), #XXX
+ ("ceiling", ["expr"], "math.ceil(v0)", False, True), #XXX
+ ("float_fractional_part", ["expr"], "v0 - int(v0)", False, True), #XXX
+ ("float_integer_part", ["expr"], "int(v0)", False, True),
]
-for prolog_name, unwrap_spec, pattern, overflow in simple_functions:
- f = wrap_builtin_operation(pattern, unwrap_spec, overflow)
+for prolog_name, unwrap_spec, pattern, overflow, intversion in simple_functions:
+ # the name is purely for flowgraph viewing reasons
+ if prolog_name.replace("_", "").isalnum():
+ name = prolog_name
+ else:
+ import unicodedata
+ name = "".join([unicodedata.name(unicode(c)).replace(" ", "_").replace("-", "").lower() for c in prolog_name])
+ f = wrap_builtin_operation(name, pattern, unwrap_spec, overflow,
+ intversion)
signature = "%s/%s" % (prolog_name, len(unwrap_spec))
arithmetic_functions[signature] = f
Modified: pypy/dist/pypy/lang/prolog/interpreter/error.py
==============================================================================
--- pypy/dist/pypy/lang/prolog/interpreter/error.py (original)
+++ pypy/dist/pypy/lang/prolog/interpreter/error.py Thu May 24 16:30:14 2007
@@ -25,8 +25,6 @@
def __init__(self, continuation):
self.continuation = continuation
- pass
-
def throw_instantiation_error():
from pypy.lang.prolog.interpreter import term
raise CatchableError(term.Atom.newatom("instantiation_error"))
Modified: pypy/dist/pypy/lang/prolog/interpreter/helper.py
==============================================================================
--- pypy/dist/pypy/lang/prolog/interpreter/helper.py (original)
+++ pypy/dist/pypy/lang/prolog/interpreter/helper.py Thu May 24 16:30:14 2007
@@ -36,7 +36,7 @@
if isinstance(obj, term.Number):
return obj.num
elif isinstance(obj, term.Float):
- f = obj.num; i = int(f)
+ f = obj.floatval; i = int(f)
if f == i:
return i
error.throw_type_error('integer', obj)
@@ -74,6 +74,6 @@
elif isinstance(obj, term.Number):
return str(obj.num)
elif isinstance(obj, term.Float):
- return str(obj.num)
+ return str(obj.floatval)
error.throw_type_error("atomic", obj)
Modified: pypy/dist/pypy/lang/prolog/interpreter/parsing.py
==============================================================================
--- pypy/dist/pypy/lang/prolog/interpreter/parsing.py (original)
+++ pypy/dist/pypy/lang/prolog/interpreter/parsing.py Thu May 24 16:30:14 2007
@@ -321,7 +321,7 @@
if isinstance(child, Number):
return Number(factor * child.num)
if isinstance(child, Float):
- return Float(factor * child.num)
+ return Float(factor * child.floatval)
return Term(name, children)
def build_list(self, node):
@@ -391,7 +391,7 @@
if isinstance(result, Number):
return Number(-result.num)
elif isinstance(result, Float):
- return Float(-result.num)
+ return Float(-result.floatval)
return self.visit(node.children[1])
def visit_listexpr(self, node):
Modified: pypy/dist/pypy/lang/prolog/interpreter/term.py
==============================================================================
--- pypy/dist/pypy/lang/prolog/interpreter/term.py (original)
+++ pypy/dist/pypy/lang/prolog/interpreter/term.py Thu May 24 16:30:14 2007
@@ -318,12 +318,12 @@
TAG = tag()
STANDARD_ORDER = 2
_immutable_ = True
- def __init__(self, num):
- self.num = num
+ def __init__(self, floatval):
+ self.floatval = floatval
@specialize.arg(3)
def basic_unify(self, other, heap, occurs_check=False):
- if isinstance(other, Float) and other.num == self.num:
+ if isinstance(other, Float) and other.floatval == self.floatval:
return
raise UnificationFailed
@@ -332,22 +332,22 @@
def copy_and_basic_unify(self, other, heap, memo):
hint(self, concrete=True)
- if isinstance(other, Float) and other.num == self.num:
+ if isinstance(other, Float) and other.floatval == self.floatval:
return self
else:
raise UnificationFailed
def get_unify_hash(self, heap):
#XXX no clue whether this is a good idea...
- m, e = math.frexp(self.num)
+ m, e = math.frexp(self.floatval)
m = intmask(int(m / 2 * 2 ** (32 - TAGBITS)))
return intmask(m << TAGBITS | self.TAG)
def __str__(self):
- return repr(self.num)
+ return repr(self.floatval)
def __repr__(self):
- return "Float(%r)" % (self.num, )
+ return "Float(%r)" % (self.floatval, )
class BlackBox(NonVar):
# meant to be subclassed
@@ -589,10 +589,10 @@
if isinstance(obj2, Number):
return rcmp(obj1.num, obj2.num)
elif isinstance(obj2, Float):
- return rcmp(obj1.num, obj2.num)
+ return rcmp(obj1.num, obj2.floatval)
if isinstance(obj1, Float):
if isinstance(obj2, Number):
- return rcmp(obj1.num, obj2.num)
+ return rcmp(obj1.floatval, obj2.num)
elif isinstance(obj2, Float):
- return rcmp(obj1.num, obj2.num)
+ return rcmp(obj1.floatval, obj2.floatval)
assert 0
Modified: pypy/dist/pypy/lang/prolog/interpreter/test/test_parsing.py
==============================================================================
--- pypy/dist/pypy/lang/prolog/interpreter/test/test_parsing.py (original)
+++ pypy/dist/pypy/lang/prolog/interpreter/test/test_parsing.py Thu May 24 16:30:14 2007
@@ -94,7 +94,7 @@
facts = builder.build(t)
assert len(facts) == 2
assert facts[0].args[1].num == -1
- assert facts[1].args[1].num == -1.345
+ assert facts[1].args[1].floatval == -1.345
t = parse_file("""
X = -1.
arg(X, h(a, b, c), b), X = 2.
More information about the Pypy-commit
mailing list