this repo has no description
at develop 9.0 kB view raw
1/* 2 * Author: 3 * Tai Tran <tai.tran@student.adelaide.edu.au> 4 * Supervisor: 5 * Guido Tack <guido.tack@monash.edu> 6 */ 7#ifndef __PYINTERFACE_H 8#define __PYINTERFACE_H 9 10#include "Annotation.h" 11#include "Expression.h" 12#include "Model.cpp" 13#include "Model.h" 14#include "Object.h" 15#include "Set.cpp" 16#include "Set.h" 17#include "Solver.cpp" 18#include "Solver.h" 19#include "VarSet.h" 20#include "global.cpp" 21#include "global.h" 22 23/* Helper functions that load data into a new model 24 * For example: instead of 25 import minizinc_internal 26 model = minizinc_internal.Model() 27 model.load(...) 28 we can do this: 29 import minizinc_internal 30 model = minizinc_internal.load(...) 31 */ 32static PyObject* Mzn_load(PyObject* self, PyObject* args, PyObject* keywds); 33static PyObject* Mzn_load_from_string(PyObject* self, PyObject* args, PyObject* keywds); 34 35// GC::lock() and GC::unlock() 36static PyObject* Mzn_lock(PyObject* self) { 37 GC::lock(); 38 Py_RETURN_NONE; 39} 40static PyObject* Mzn_unlock(PyObject* self) { 41 GC::unlock(); 42 Py_RETURN_NONE; 43} 44 45/************************************************************ 46 Groups of function that need an outer GCLock to work 47 ************************************************************/ 48// Note: Please see Note 1 of the first python_to_minizinc declaration in global.h first 49 50// Requires: 51// - An UnOpType integer opcode 52// - A MiniZinc expression or Python value 53static PyObject* Mzn_UnOp(PyObject* self, PyObject* args); 54 55// Requires: 56// - A left hand sided MiniZinc expression or Python value 57// - A BinOpType integer opcode 58// - A right hand sided MiniZinc expression or Python value 59static PyObject* Mzn_BinOp(PyObject* self, PyObject* args); 60 61// Requires: 62// - Name of the MiniZinc function to be called (string) 63// - List of MiniZinc object or Python value 64// - (Optional, deprecated) Return type of Mzn_Call 65static PyObject* Mzn_Call(PyObject* self, PyObject* args); 66 67// Requires a name(string) 68static PyObject* Mzn_Id(PyObject* self, PyObject* args); 69// Requires: 70// - A MiniZinc expression of array type 71// - A list of integer indices (can be MiniZinc expression as well) 72static PyObject* Mzn_at(PyObject* self, PyObject* args); 73 74// ***************** END OF GROUPS ***************** 75 76/* Definition: Returns a dictionary of keys: "boolfuncs", "annfuncs" and "annvars" (currently) 77 For each '*funcs': 78 Itself is another dictionary: 79 key: name of function 80 value: a list of all possible combination of parsing argument types and return type: 81 for each item in that list: 82 item[0] is a tuple argument types: 83 if a function accepts (int, int), it should be (<type 'long'>, <type 'long'>) 84 85 if a function accepts (array of [int, int]), it should be 86 ( [<type 'long'>, <type 'long'>], ) 87 (notice the appearance of a list here) 88 item[1] is the return type: 89 MiniZinc Type - Python Type 90 int - long 91 float - float 92 bool - bool 93 string - str 94 VarSet - minizinc.VarSet 95 Ann - minizinc.Annotation 96 Top - NoneType (accepts everything) 97 others - minizinc.Object (means an error) 98 99 For 'annvars': 100 Just a list of ann names 101 102 */ 103static PyObject* Mzn_retrieveNames(PyObject* self, PyObject* args); 104 105/********************* SKIP ******************************* */ 106PyObject* eval_type(TypeInst* ti) { 107 ASTExprVec<TypeInst> ranges = ti->ranges(); 108 PyObject* v; 109 switch (ti->type().bt()) { 110 case Type::BT_BOOL: 111 v = reinterpret_cast<PyObject*>(&PyBool_Type); 112 break; 113 case Type::BT_INT: 114 if (ti->type().st() == Type::ST_SET) 115 v = reinterpret_cast<PyObject*>(&MznVarSet_Type); 116 else 117 v = reinterpret_cast<PyObject*>(&PyLong_Type); 118 break; 119 case Type::BT_FLOAT: 120 v = reinterpret_cast<PyObject*>(&PyFloat_Type); 121 break; 122 case Type::BT_STRING: 123 v = reinterpret_cast<PyObject*>(&PyUnicode_Type); 124 break; 125 case Type::BT_ANN: 126 v = reinterpret_cast<PyObject*>(&MznAnnotation_Type); 127 break; 128 case Type::BT_TOP: 129 v = Py_None; 130 break; 131 default: // v = reinterpret_cast<PyObject*>(&MznVariable_Type); 132 // cout << ti->type().bt() << endl; 133 v = reinterpret_cast<PyObject*>(&MznObject_Type); 134 break; 135 throw runtime_error("CollectBoolFunctionNames: unexpected type"); 136 } 137 138 if (ranges.size() == 0) { 139 Py_INCREF(v); 140 return v; 141 } else { 142 PyObject* args_tuple = PyList_New(ranges.size()); 143 for (int i = 0; i != ranges.size(); ++i) { 144 Py_INCREF(v); 145 PyList_SET_ITEM(args_tuple, i, v); 146 } 147 return args_tuple; 148 } 149} 150 151void add_to_dictionary(FunctionI* fi, PyObject* toAdd) { 152 ASTExprVec<VarDecl> params = fi->params(); 153 const char* str = fi->id().str().c_str(); 154 PyObject* key = PyUnicode_FromString(str); 155 156 PyObject* args_and_return_type_tuple = PyTuple_New(2); 157 PyObject* args_tuple = PyTuple_New(params.size()); 158 for (unsigned int i = 0; i < params.size(); ++i) { 159 PyTuple_SET_ITEM(args_tuple, i, eval_type(params[i]->ti())); 160 } 161 PyObject* return_type = eval_type(fi->ti()); 162 163 PyTuple_SET_ITEM(args_and_return_type_tuple, 0, args_tuple); 164 PyTuple_SET_ITEM(args_and_return_type_tuple, 1, return_type); 165 166 PyObject* toAdd_item = PyDict_GetItem(toAdd, key); 167 if (toAdd_item == NULL) { 168 toAdd_item = PyList_New(1); 169 PyList_SET_ITEM(toAdd_item, 0, args_and_return_type_tuple); 170 if (PyDict_SetItem(toAdd, key, toAdd_item) != 0) 171 throw runtime_error("CollectBoolFunctionNames: cannot set new key to the dictionary"); 172 Py_DECREF(toAdd_item); 173 } else { 174 if (PyList_Append(toAdd_item, args_and_return_type_tuple) != 0) 175 throw runtime_error("CollectBoolFunctionNames: cannot append item to the list"); 176 } 177} 178 179class CollectBoolFuncNames : public ItemVisitor { 180protected: 181 bool include_global_mzn; 182 PyObject* _boolfuncs; 183 184public: 185 CollectBoolFuncNames(PyObject* boolfuncs, bool include_global_mzn0) 186 : _boolfuncs(boolfuncs), include_global_mzn(include_global_mzn0) {} 187 bool enterModel(Model* m) { 188 return m->filename() != "stdlib.mzn" && (include_global_mzn || m->filename() != "globals.mzn"); 189 } 190 void vFunctionI(FunctionI* fi) { 191 if (fi->ti()->type().isvarbool() == false) return; 192 193 add_to_dictionary(fi, _boolfuncs); 194 } 195}; 196 197class CollectAnnNames : public ItemVisitor { 198protected: 199 PyObject* _annfuncs; 200 PyObject* _annvars; 201 bool include_global_mzn; 202 203public: 204 CollectAnnNames(PyObject* annfuncs, PyObject* annvars, bool include_global_mzn0) 205 : _annfuncs(annfuncs), _annvars(annvars), include_global_mzn(include_global_mzn0) {} 206 bool enterModel(Model* m) { 207 return include_global_mzn || (m->filename() != "globals.mzn" && m->filename() != "stdlib.mzn"); 208 } 209 void vFunctionI(FunctionI* fi) { 210 if (fi->ti()->type().isann() == false) return; 211 212 add_to_dictionary(fi, _annfuncs); 213 } 214 void vVarDeclI(VarDeclI* vdi) { 215 if (vdi->e()->ti()->type().isann()) { 216 PyList_Append(_annvars, PyUnicode_FromString(vdi->e()->id()->str().c_str())); 217 } 218 } 219}; 220 221/********************* END OF SKIP ******************************* */ 222 223static PyMethodDef Mzn_methods[] = { 224 {"load", (PyCFunction)Mzn_load, METH_KEYWORDS, "Load MiniZinc model from MiniZinc file"}, 225 {"load_from_string", (PyCFunction)Mzn_load_from_string, METH_KEYWORDS, 226 "Load MiniZinc model from stdin"}, 227 {"BinOp", (PyCFunction)Mzn_BinOp, METH_VARARGS, "Add a binary expression into the model"}, 228 {"UnOp", (PyCFunction)Mzn_UnOp, METH_VARARGS, "Add a unary expression into the model"}, 229 {"Id", (PyCFunction)Mzn_Id, METH_VARARGS, 230 "Return a MiniZinc Variable containing the given name"}, 231 {"Call", (PyCFunction)Mzn_Call, METH_VARARGS, "MiniZinc Call"}, 232 233 {"at", (PyCFunction)Mzn_at, METH_VARARGS, "Array Access"}, 234 {"retrieveNames", (PyCFunction)Mzn_retrieveNames, METH_VARARGS, 235 "Returns names of MiniZinc functions and variables"}, 236 {"lock", (PyCFunction)Mzn_lock, METH_NOARGS, "Internal: Create a lock for garbage collection"}, 237 {"unlock", (PyCFunction)Mzn_lock, METH_NOARGS, 238 "Internal: Unlock a lock for garbage collection"}, 239 {NULL}}; 240 241#if PY_MAJOR_VERSION >= 3 242 243static struct PyModuleDef moduledef = {PyModuleDef_HEAD_INIT, 244 "minizinc", 245 "A python interface for MiniZinc constraint modeling", 246 -1, 247 Mzn_methods, 248 NULL, 249 NULL, 250 NULL, 251 NULL}; 252 253#endif 254 255#endif