718 lines
22 KiB
Python
718 lines
22 KiB
Python
|
# -*- python -*-
|
||
|
#==============================================================================
|
||
|
# Copyright (C) 2011 by Denys Duchier
|
||
|
#
|
||
|
# This program is free software: you can redistribute it and/or modify it under
|
||
|
# the terms of the GNU General Public License as published by the Free Software
|
||
|
# Foundation, either version 3 of the License, or (at your option) any later
|
||
|
# version.
|
||
|
#
|
||
|
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||
|
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||
|
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||
|
# details.
|
||
|
#
|
||
|
# You should have received a copy of the GNU General Public License along with
|
||
|
# this program. If not, see <http://www.gnu.org/licenses/>.
|
||
|
#==============================================================================
|
||
|
|
||
|
import re
|
||
|
|
||
|
NOTICE_CC = """// -*- c++ -*-
|
||
|
//=============================================================================
|
||
|
// Copyright (C) 2011 by Denys Duchier
|
||
|
//
|
||
|
// This program is free software: you can redistribute it and/or modify it
|
||
|
// under the terms of the GNU Lesser General Public License as published by the
|
||
|
// Free Software Foundation, either version 3 of the License, or (at your
|
||
|
// option) any later version.
|
||
|
//
|
||
|
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||
|
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||
|
// more details.
|
||
|
//
|
||
|
// You should have received a copy of the GNU Lesser General Public License
|
||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
|
//=============================================================================
|
||
|
"""
|
||
|
|
||
|
NOTICE_PROLOG="""%% -*- prolog -*-
|
||
|
%%=============================================================================
|
||
|
%% Copyright (C) 2011 by Denys Duchier
|
||
|
%%
|
||
|
%% This program is free software: you can redistribute it and/or modify it
|
||
|
%% under the terms of the GNU Lesser General Public License as published by the
|
||
|
%% Free Software Foundation, either version 3 of the License, or (at your
|
||
|
%% option) any later version.
|
||
|
%%
|
||
|
%% This program is distributed in the hope that it will be useful, but WITHOUT
|
||
|
%% ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||
|
%% FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||
|
%% more details.
|
||
|
%%
|
||
|
%% You should have received a copy of the GNU Lesser General Public License
|
||
|
%% along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
|
%%=============================================================================
|
||
|
"""
|
||
|
|
||
|
def prolog_print_notice():
|
||
|
print NOTICE_PROLOG
|
||
|
|
||
|
def cc_print_notice():
|
||
|
print NOTICE_CC
|
||
|
|
||
|
class Type(object):
|
||
|
|
||
|
DEFAULT = re.compile("""^(.+)=(.+)$""")
|
||
|
CONST = re.compile("""^const\\b(.+)$""")
|
||
|
UNSIGNED = re.compile("""^unsigned\\b(.+)$""")
|
||
|
REFERENCE = re.compile("""^(.+)&$""")
|
||
|
|
||
|
def __init__(self, text):
|
||
|
if isinstance(text, Type):
|
||
|
self.clone_from(text)
|
||
|
return
|
||
|
text = text.strip()
|
||
|
m = self.DEFAULT.match(text)
|
||
|
if m:
|
||
|
self.default = m.group(2).strip()
|
||
|
text = m.group(1).strip()
|
||
|
else:
|
||
|
self.default = None
|
||
|
m = self.CONST.match(text)
|
||
|
if m:
|
||
|
self.const = True
|
||
|
text = m.group(1).strip()
|
||
|
else:
|
||
|
self.const = False
|
||
|
m = self.UNSIGNED.match(text)
|
||
|
if m:
|
||
|
self.unsigned = True
|
||
|
text = m.group(1).strip()
|
||
|
else:
|
||
|
self.unsigned = False
|
||
|
m = self.REFERENCE.match(text)
|
||
|
if m:
|
||
|
self.reference = True
|
||
|
text = m.group(1).strip()
|
||
|
else:
|
||
|
self.reference = False
|
||
|
self.type = text
|
||
|
|
||
|
def __str__(self):
|
||
|
l = []
|
||
|
if self.const: l.append("const ")
|
||
|
if self.unsigned: l.append("unsigned ")
|
||
|
l.append(self.type)
|
||
|
if self.reference: l.append("&")
|
||
|
if self.default is not None:
|
||
|
l.append("=")
|
||
|
l.append(self.default)
|
||
|
return ''.join(l)
|
||
|
|
||
|
def clone_from(self, other):
|
||
|
self.const = other.const
|
||
|
self.unsigned = other.unsigned
|
||
|
self.type = other.type
|
||
|
self.reference = other.reference
|
||
|
self.default = other.default
|
||
|
|
||
|
def clone(self):
|
||
|
return type(self)(self)
|
||
|
|
||
|
|
||
|
class Constraint(object):
|
||
|
|
||
|
DECL = re.compile("""^([^(]+)\\b(\w+)\((.*)\);$""")
|
||
|
ARG = re.compile("""((?:[^,<(]|<[^>]*>|\([^)]*\))+),?""")
|
||
|
|
||
|
def __init__(self, line):
|
||
|
if isinstance(line, Constraint):
|
||
|
self.clone_from(line)
|
||
|
return
|
||
|
line = line.strip()
|
||
|
m = self.DECL.match(line)
|
||
|
self.rettype = Type(m.group(1).strip())
|
||
|
self.name = m.group(2)
|
||
|
argtypes = []
|
||
|
for x in self.ARG.finditer(m.group(3).strip()):
|
||
|
argtypes.append(Type(x.group(1)))
|
||
|
self.argtypes = tuple(argtypes)
|
||
|
self.api = None
|
||
|
|
||
|
def __str__(self):
|
||
|
l = []
|
||
|
l.append(str(self.rettype))
|
||
|
l.append(" ")
|
||
|
l.append(self.name)
|
||
|
sep = "("
|
||
|
for x in self.argtypes:
|
||
|
l.append(sep)
|
||
|
sep = ", "
|
||
|
l.append(str(x))
|
||
|
l.append(")")
|
||
|
if self.api is not None:
|
||
|
l.append(" -> ")
|
||
|
l.append(self.api)
|
||
|
l.append(";")
|
||
|
return ''.join(l)
|
||
|
|
||
|
def clone_from(self, other):
|
||
|
self.rettype = other.rettype.clone()
|
||
|
self.name = other.name
|
||
|
self.argtypes = tuple(t.clone() for t in other.argtypes)
|
||
|
|
||
|
def clone(self):
|
||
|
return type(self)(self)
|
||
|
|
||
|
|
||
|
COMMENT = re.compile("""^\\s*//.*$""")
|
||
|
|
||
|
def load_decls(filename):
|
||
|
decls = []
|
||
|
for line in open(filename):
|
||
|
line = line.strip()
|
||
|
if not line: continue
|
||
|
m = COMMENT.match(line)
|
||
|
if m: continue
|
||
|
decls.append(Constraint(line))
|
||
|
return decls
|
||
|
|
||
|
class DeclsLoader(object):
|
||
|
|
||
|
def __init__(self, filename):
|
||
|
self.decls = load_decls(filename)
|
||
|
|
||
|
def print_decls(self):
|
||
|
for con in self.decls:
|
||
|
print str(con)
|
||
|
|
||
|
class PredGenerator(DeclsLoader):
|
||
|
|
||
|
OMIT = ("VarBranchOptions",
|
||
|
"ValBranchOptions",
|
||
|
"TieBreakVarBranch<IntVarBranch>",
|
||
|
"TieBreak<IntVarBranch>",
|
||
|
"TieBreak<FloatVarBranch>",
|
||
|
"TieBreak<SetVarBranch>",
|
||
|
"TieBreakVarBranchOptions",
|
||
|
"TieBreakVarBranch<SetVarBranch>")
|
||
|
|
||
|
def __init__(self, filename):
|
||
|
super(PredGenerator, self).__init__(filename)
|
||
|
self._change_home_to_space()
|
||
|
self._change_intsharedarray_to_intargs()
|
||
|
self._generate()
|
||
|
self._number()
|
||
|
|
||
|
def _change_home_to_space(self):
|
||
|
for p in self.decls:
|
||
|
for t in p.argtypes:
|
||
|
if t.type=="Home":
|
||
|
t.type="Space"
|
||
|
|
||
|
def _change_intsharedarray_to_intargs(self):
|
||
|
for p in self.decls:
|
||
|
for t in p.argtypes:
|
||
|
if t.type=="IntSharedArray":
|
||
|
t.type="IntArgs"
|
||
|
|
||
|
def _generate(self):
|
||
|
# drop the constraints and optional arguments we can't handle
|
||
|
preds = []
|
||
|
for con in self.decls:
|
||
|
if self._con_ok(con):
|
||
|
con = con.clone()
|
||
|
con.argtypes = tuple(self._drop_deco(t) for t in con.argtypes
|
||
|
if t.type not in self.OMIT)
|
||
|
preds.append(con)
|
||
|
# for each pred that has an argument with a default produce
|
||
|
# 2 preds (1 without, 1 with). repeat until all defaults have
|
||
|
# been removed.
|
||
|
again = True
|
||
|
while again:
|
||
|
preds_ = []
|
||
|
again = False
|
||
|
for con in preds:
|
||
|
i = self._defaulted(con.argtypes)
|
||
|
if i is None:
|
||
|
preds_.append(con)
|
||
|
else:
|
||
|
again = True
|
||
|
before = con.argtypes[:i]
|
||
|
# without the default argument
|
||
|
# and therefore without the args that follow
|
||
|
con1 = con.clone()
|
||
|
con1.argtypes = before
|
||
|
preds_.append(con1)
|
||
|
# with the default argument (not default anymore)
|
||
|
con2 = con.clone()
|
||
|
arg = con.argtypes[i].clone()
|
||
|
arg.default=None
|
||
|
after = con.argtypes[i+1:]
|
||
|
con2.argtypes = before + (arg,) + after
|
||
|
preds_.append(con2)
|
||
|
preds = preds_
|
||
|
self.preds = preds
|
||
|
|
||
|
def _con_ok(self, con):
|
||
|
for t in con.argtypes:
|
||
|
if (t.type in self.OMIT) and (t.default is None):
|
||
|
return False
|
||
|
return True
|
||
|
|
||
|
def _drop_deco(self, t):
|
||
|
# drop const, ref, and unsigned indications
|
||
|
t.const = False
|
||
|
t.reference = False
|
||
|
t.unsigned = False
|
||
|
return t
|
||
|
|
||
|
def _defaulted(self, argtypes):
|
||
|
i = 0
|
||
|
for x in argtypes:
|
||
|
if x.default is not None:
|
||
|
return i
|
||
|
i += 1
|
||
|
return None
|
||
|
|
||
|
def _number(self):
|
||
|
i = 1
|
||
|
for x in self.preds:
|
||
|
x.api = "%s_%d" % (x.name,i)
|
||
|
i += 1
|
||
|
|
||
|
def print_preds(self):
|
||
|
for p in self.preds:
|
||
|
print str(p)
|
||
|
|
||
|
class Cluster(object):
|
||
|
|
||
|
def __init__(self, name, arity):
|
||
|
self.name = name
|
||
|
self.arity = arity
|
||
|
self.preds = []
|
||
|
|
||
|
# discriminating tree based on argument types
|
||
|
class DTree(object):
|
||
|
|
||
|
def __init__(self, i, preds, cluster):
|
||
|
self.index = i
|
||
|
self.cluster = cluster
|
||
|
if len(preds) == 1 and len(preds[0].argtypes) == i:
|
||
|
self.is_leaf = True
|
||
|
self.pred = preds[0]
|
||
|
return
|
||
|
self.is_leaf = False
|
||
|
# i is the index of the current arg
|
||
|
# preds are the predicates to be indexed under this tree node
|
||
|
dispatch = {}
|
||
|
for p in preds:
|
||
|
t = p.argtypes[i]
|
||
|
d = dispatch.get(t.type, None)
|
||
|
if d is None:
|
||
|
d = []
|
||
|
dispatch[t.type] = d
|
||
|
d.append(p)
|
||
|
self.subtrees = tuple((t2,DTree(i+1,p2,cluster))
|
||
|
for t2,p2 in dispatch.iteritems())
|
||
|
|
||
|
def _generate_body(self, user_vars, lib_vars):
|
||
|
if self.is_leaf:
|
||
|
return PrologLiteral("gecode_constraint_%s(%s)" % (self.pred.api, ",".join(lib_vars)))
|
||
|
X = user_vars[self.index]
|
||
|
Y = lib_vars[self.index]
|
||
|
return self._generate_dispatch(0, user_vars, lib_vars)
|
||
|
|
||
|
def _generate_dispatch(self, i, user_vars, lib_vars):
|
||
|
if i == len(self.subtrees):
|
||
|
return PrologLiteral("throw(gecode_argument_error(%s(%s),arg=%d))" \
|
||
|
% (self.cluster.name, ",".join(user_vars),
|
||
|
self.index+1))
|
||
|
typ, dtree = self.subtrees[i]
|
||
|
idx = self.index
|
||
|
X = user_vars[idx]
|
||
|
Y = lib_vars[idx]
|
||
|
# hack for disjunctor support
|
||
|
if typ=="Space":
|
||
|
typ = "Space_or_Clause"
|
||
|
return PrologIF(
|
||
|
PrologLiteral("is_%s(%s,%s)" % (typ,X,Y)),
|
||
|
dtree._generate_body(user_vars, lib_vars),
|
||
|
self._generate_dispatch(i+1, user_vars, lib_vars))
|
||
|
|
||
|
def _cc_descriptors(self, name, argtypes):
|
||
|
if self.is_leaf:
|
||
|
return (CCDescriptor(name, argtypes, self.pred.api),)
|
||
|
descriptors = []
|
||
|
for typ,dtree in self.subtrees:
|
||
|
descriptors.extend(dtree._cc_descriptors(name,(argtypes+(typ,))))
|
||
|
return descriptors
|
||
|
|
||
|
class YAPConstraintGeneratorBase(PredGenerator):
|
||
|
|
||
|
def __init__(self, filename):
|
||
|
super(YAPConstraintGeneratorBase, self).__init__(filename)
|
||
|
self._classify()
|
||
|
self._dtreefy()
|
||
|
|
||
|
# create clusters (predicate,arity)
|
||
|
def _classify(self):
|
||
|
clusters = {}
|
||
|
for pred in self.preds:
|
||
|
name = pred.name
|
||
|
arity = len(pred.argtypes)
|
||
|
key = (name,arity)
|
||
|
cluster = clusters.get(key, None)
|
||
|
if cluster is None:
|
||
|
cluster = Cluster(name, arity)
|
||
|
clusters[key] = cluster
|
||
|
cluster.preds.append(pred)
|
||
|
self.clusters = clusters
|
||
|
|
||
|
# for each cluster, create a dtree
|
||
|
def _dtreefy(self):
|
||
|
dtrees = {}
|
||
|
for key, cluster in self.clusters.iteritems():
|
||
|
dtree = DTree(0, cluster.preds, cluster)
|
||
|
dtrees[key] = dtree
|
||
|
self.dtrees = dtrees
|
||
|
|
||
|
def _user_vars(self, arity):
|
||
|
return tuple(("X%d" % i) for i in range(arity))
|
||
|
|
||
|
def _lib_vars(self, arity):
|
||
|
return tuple(("Y%d" % i) for i in range(arity))
|
||
|
|
||
|
class YAPConstraintPrologGenerator(YAPConstraintGeneratorBase):
|
||
|
|
||
|
def __init__(self, filename):
|
||
|
super(YAPConstraintPrologGenerator, self).__init__(filename)
|
||
|
|
||
|
def _prolog_clauses(self):
|
||
|
clauses = []
|
||
|
for (name, arity), dtree in self.dtrees.iteritems():
|
||
|
user_vars = self._user_vars(arity)
|
||
|
lib_vars = self._lib_vars(arity)
|
||
|
head = "%s(%s)" % (name, ",".join(user_vars))
|
||
|
body = dtree._generate_body(user_vars, lib_vars)
|
||
|
clause = PrologClause(head, body)
|
||
|
clauses.append(clause)
|
||
|
return clauses
|
||
|
|
||
|
def generate(self):
|
||
|
out = OStream(sys.stdout)
|
||
|
for clause in self._prolog_clauses():
|
||
|
clause.pp(out, 0)
|
||
|
|
||
|
class YAPConstraintCCGenerator(YAPConstraintGeneratorBase):
|
||
|
|
||
|
def __init__(self, filename):
|
||
|
super(YAPConstraintCCGenerator, self).__init__(filename)
|
||
|
|
||
|
def _cc_descriptors(self):
|
||
|
descriptors = []
|
||
|
for (name, arity), dtree in self.dtrees.iteritems():
|
||
|
descriptors.extend(dtree._cc_descriptors(name,()))
|
||
|
return descriptors
|
||
|
|
||
|
def generate_impl(self):
|
||
|
for d in self._cc_descriptors():
|
||
|
d.generate_impl()
|
||
|
|
||
|
def generate_init(self):
|
||
|
for d in self._cc_descriptors():
|
||
|
d.generate_init()
|
||
|
|
||
|
# output stream that keeps track of the current column
|
||
|
# to facilitate proper indentation
|
||
|
|
||
|
import sys
|
||
|
|
||
|
class OStream(object):
|
||
|
|
||
|
def __init__(self, fd=sys.stdout):
|
||
|
self.file = fd
|
||
|
self.column = 0
|
||
|
|
||
|
def write(self, s):
|
||
|
reset = False
|
||
|
for x in s.split('\n'):
|
||
|
if reset:
|
||
|
self.newline()
|
||
|
else:
|
||
|
reset = True
|
||
|
self.file.write(x)
|
||
|
self.column += len(x)
|
||
|
|
||
|
def newline(self):
|
||
|
self.file.write("\n")
|
||
|
self.column = 0
|
||
|
|
||
|
def writeln(self, s=None):
|
||
|
if s is not None:
|
||
|
self.write(s)
|
||
|
self.newline()
|
||
|
|
||
|
def indent_to(self, n):
|
||
|
if n<self.column:
|
||
|
self.newline()
|
||
|
n = n - self.column
|
||
|
while n>0:
|
||
|
self.write(' ')
|
||
|
n -= 1
|
||
|
|
||
|
# representation of prolog code that automatically supports proper indentation
|
||
|
|
||
|
class PrologObject(object):
|
||
|
pass
|
||
|
|
||
|
class PrologClause(PrologObject):
|
||
|
|
||
|
def __init__(self, head, body):
|
||
|
self.head = head
|
||
|
self.body = body
|
||
|
|
||
|
def pp(self, out, offset):
|
||
|
out.indent_to(offset)
|
||
|
out.write(self.head)
|
||
|
out.writeln(" :-")
|
||
|
self.body.pp(out, offset+8)
|
||
|
out.writeln(".")
|
||
|
out.writeln()
|
||
|
|
||
|
class PrologLiteral(PrologObject):
|
||
|
|
||
|
def __init__(self, lit):
|
||
|
self.literal = lit
|
||
|
|
||
|
def pp(self, out, offset):
|
||
|
out.indent_to(offset)
|
||
|
out.write(self.literal)
|
||
|
|
||
|
class PrologIF(PrologObject):
|
||
|
|
||
|
def __init__(self, cond, left, right):
|
||
|
self.cond = cond
|
||
|
self.left = left
|
||
|
self.right = right
|
||
|
|
||
|
def pp(self, out, offset):
|
||
|
out.indent_to(offset)
|
||
|
out.write("("),
|
||
|
indent = offset+1
|
||
|
self.cond.pp(out, indent)
|
||
|
out.writeln()
|
||
|
out.indent_to(indent)
|
||
|
out.write("-> ")
|
||
|
self.left.pp(out, indent+3)
|
||
|
out.writeln()
|
||
|
out.indent_to(indent)
|
||
|
out.write("; ")
|
||
|
self.right.pp(out, indent+3)
|
||
|
out.write(")")
|
||
|
|
||
|
ENUM_CLASSES = None
|
||
|
ENUM_CLASSES_AVOID = ('ScriptMode','ViewSelStatus','ExecStatus',
|
||
|
'ActorProperty','SpaceStatus')
|
||
|
|
||
|
def enum_classes():
|
||
|
global ENUM_CLASSES
|
||
|
if ENUM_CLASSES is None:
|
||
|
filename = "gecode-enums-%s.py" % gecode_version()
|
||
|
import imp
|
||
|
ENUM_CLASSES = imp.load_source(
|
||
|
"gecode_enums",
|
||
|
filename).ENUM_CLASSES
|
||
|
ENUM_CLASSES = tuple(x for x in ENUM_CLASSES if x.TYPE not in ENUM_CLASSES_AVOID)
|
||
|
return ENUM_CLASSES
|
||
|
|
||
|
class YAPEnumImpl(object):
|
||
|
|
||
|
def generate(self):
|
||
|
self._generate_atoms()
|
||
|
self._generate_from_term()
|
||
|
|
||
|
def _generate_atoms(self):
|
||
|
for x in self.ENUM:
|
||
|
print "static YAP_Term gecode_%s;" % x
|
||
|
print
|
||
|
|
||
|
def _generate_from_term(self):
|
||
|
print "static %s gecode_%s_from_term(YAP_Term X)" % (self.TYPE,self.TYPE)
|
||
|
print "{"
|
||
|
for x in self.ENUM:
|
||
|
print " if (X==gecode_%s) return %s;" % (x,x)
|
||
|
print ' cerr << "this should never happen" << endl; exit(1);'
|
||
|
print "}"
|
||
|
print
|
||
|
|
||
|
def _generate_from_term_forward_decl(self):
|
||
|
print "static %s gecode_%s_from_term(YAP_Term);" % (self.TYPE,self.TYPE)
|
||
|
|
||
|
class YAPEnumImplGenerator(object):
|
||
|
|
||
|
def generate(self):
|
||
|
for c in enum_classes():
|
||
|
class C(c,YAPEnumImpl): pass
|
||
|
o = C()
|
||
|
o.generate()
|
||
|
|
||
|
class YAPEnumForwardGenerator(object):
|
||
|
|
||
|
def generate(self):
|
||
|
for c in enum_classes():
|
||
|
class C(c,YAPEnumImpl): pass
|
||
|
o = C()
|
||
|
o._generate_from_term_forward_decl()
|
||
|
|
||
|
class YAPEnumInit(object):
|
||
|
|
||
|
def generate(self):
|
||
|
for x in self.ENUM:
|
||
|
print '{ YAP_Atom X= YAP_LookupAtom("%s");' % x
|
||
|
print ' gecode_%s = YAP_MkAtomTerm(X);' % x
|
||
|
print ' YAP_AtomGetHold(X); }'
|
||
|
print
|
||
|
|
||
|
class YAPEnumInitGenerator(object):
|
||
|
|
||
|
def generate(self):
|
||
|
for c in enum_classes():
|
||
|
class C(c,YAPEnumInit): pass
|
||
|
o = C()
|
||
|
o.generate()
|
||
|
|
||
|
class YAPEnumProlog(object):
|
||
|
|
||
|
def generate(self):
|
||
|
for x in self.ENUM:
|
||
|
print "is_%s_('%s')." % (self.TYPE, x)
|
||
|
print
|
||
|
for x in self.ENUM:
|
||
|
print "is_%s_('%s','%s')." % (self.TYPE, x, x)
|
||
|
print
|
||
|
print "is_%s(X,Y) :- nonvar(X), is_%s_(X,Y)." % (self.TYPE,self.TYPE)
|
||
|
print "is_%s(X) :- is_%s(X,_)." % (self.TYPE,self.TYPE)
|
||
|
print
|
||
|
|
||
|
class YAPEnumPrologGenerator(object):
|
||
|
|
||
|
def generate(self):
|
||
|
for c in enum_classes():
|
||
|
class C(c,YAPEnumProlog): pass
|
||
|
o = C()
|
||
|
o.generate()
|
||
|
|
||
|
class CCDescriptor(object):
|
||
|
|
||
|
def __init__(self, name, argtypes, api):
|
||
|
self.name = name
|
||
|
self.argtypes = argtypes
|
||
|
self.api = api
|
||
|
|
||
|
def generate_impl(self):
|
||
|
print "static int gecode_constraint_%s(void)" % self.api
|
||
|
print "{"
|
||
|
i = 1
|
||
|
args = []
|
||
|
has_space = False
|
||
|
for t in self.argtypes:
|
||
|
v = "X%d" % i
|
||
|
a = "YAP_ARG%d" % i
|
||
|
if t=="Space":
|
||
|
v = "*space"
|
||
|
print " GenericSpace* space = gecode_Space_from_term(%s);" % a
|
||
|
has_space = True
|
||
|
else:
|
||
|
extra = ""
|
||
|
if t in ("IntVar","BoolVar","SetVar","FloatVar","IntVarArgs","BoolVarArgs","SetVarArgs","FloatVarArgs"):
|
||
|
extra = "space,"
|
||
|
if has_space == False:
|
||
|
print " GenericSpace* space = gecode_Space_from_term(%s);" % a
|
||
|
has_space = True
|
||
|
print " %s %s = gecode_%s_from_term(%s%s);" % (t,v,t,extra,a)
|
||
|
args.append(v)
|
||
|
i += 1
|
||
|
print " %s(%s);" % (self.name, ",".join(args))
|
||
|
print " return TRUE;"
|
||
|
print "}"
|
||
|
print
|
||
|
|
||
|
def generate_init(self):
|
||
|
print 'YAP_UserCPredicate("gecode_constraint_%s", gecode_constraint_%s, %d);' \
|
||
|
% (self.api, self.api, len(self.argtypes))
|
||
|
|
||
|
GECODE_VERSION = None
|
||
|
|
||
|
def gecode_version():
|
||
|
global GECODE_VERSION
|
||
|
if GECODE_VERSION is not None:
|
||
|
return GECODE_VERSION
|
||
|
from distutils.ccompiler import new_compiler
|
||
|
try:
|
||
|
from distutils.ccompiler import customize_compiler
|
||
|
except:
|
||
|
from distutils.sysconfig import customize_compiler
|
||
|
import os
|
||
|
cxx = new_compiler()
|
||
|
customize_compiler(cxx)
|
||
|
pid = os.getpid()
|
||
|
file_hh = "_gecode_version_%d.hh" % pid
|
||
|
file_txt = "_gecode_version_%d.txt" % pid
|
||
|
f = file(file_hh,"w")
|
||
|
f.write("""#include "gecode/support/config.hpp"
|
||
|
@@GECODE_VERSION""")
|
||
|
f.close()
|
||
|
cxx.preprocess(file_hh,output_file=file_txt)
|
||
|
f = open(file_txt)
|
||
|
version = ""
|
||
|
for line in f:
|
||
|
if line.startswith("@@"):
|
||
|
version = line[3:-2]
|
||
|
break
|
||
|
f.close()
|
||
|
os.remove(file_hh)
|
||
|
os.remove(file_txt)
|
||
|
GECODE_VERSION = version
|
||
|
return version
|
||
|
|
||
|
def generate_files():
|
||
|
DIR = "../%s" % gecode_version()
|
||
|
import os, os.path
|
||
|
DIR = os.path.abspath(DIR)
|
||
|
if not os.path.exists(DIR):
|
||
|
os.mkdir(DIR)
|
||
|
filename = "gecode-prototypes-%s.hh" % gecode_version()
|
||
|
import sys
|
||
|
stdout = sys.stdout
|
||
|
try:
|
||
|
sys.stdout = file(os.path.join(DIR,"gecode-version.txt"),"w")
|
||
|
print gecode_version()
|
||
|
sys.stdout.close()
|
||
|
sys.stdout = file(os.path.join(DIR,"gecode_yap_auto_generated.yap"),"w")
|
||
|
prolog_print_notice()
|
||
|
YAPEnumPrologGenerator().generate()
|
||
|
YAPConstraintPrologGenerator(filename).generate()
|
||
|
sys.stdout.close()
|
||
|
sys.stdout = file(os.path.join(DIR,"gecode_yap_cc_impl_auto_generated.icc"),"w")
|
||
|
cc_print_notice()
|
||
|
YAPEnumImplGenerator().generate()
|
||
|
YAPConstraintCCGenerator(filename).generate_impl()
|
||
|
sys.stdout.close()
|
||
|
sys.stdout = file(os.path.join(DIR,"gecode_yap_cc_init_auto_generated.icc"),"w")
|
||
|
cc_print_notice()
|
||
|
YAPEnumInitGenerator().generate()
|
||
|
YAPConstraintCCGenerator(filename).generate_init()
|
||
|
sys.stdout.close()
|
||
|
sys.stdout = file(os.path.join(DIR,"gecode_yap_cc_forward_auto_generated.icc"),"w")
|
||
|
cc_print_notice()
|
||
|
YAPEnumForwardGenerator().generate()
|
||
|
sys.stdout.close()
|
||
|
finally:
|
||
|
sys.stdout = stdout
|
||
|
|
||
|
if __name__ == '__main__':
|
||
|
generate_files()
|