diff --git a/__pkginfo__.py b/__pkginfo__.py
index d7877cf6281eb7b6175c62fdd767511559153f43_X19wa2dpbmZvX18ucHk=..f14ebce130ddd822ac4bc643f3084c520cecb5ea_X19wa2dpbmZvX18ucHk= 100644
--- a/__pkginfo__.py
+++ b/__pkginfo__.py
@@ -32,4 +32,6 @@
 pyversions = ['2.4']
 
 
+from distutils.core import Extension
+
 include_dirs = []
@@ -35,1 +37,7 @@
 include_dirs = []
+
+ext_modules = [ Extension('rql_solve',
+                          ['gecode_solver.cpp'],
+                          libraries=['gecodeint', 'gecodekernel', 'gecodesearch'],
+                          
+                          ) ]
diff --git a/analyze.py b/analyze.py
index d7877cf6281eb7b6175c62fdd767511559153f43_YW5hbHl6ZS5weQ==..f14ebce130ddd822ac4bc643f3084c520cecb5ea_YW5hbHl6ZS5weQ== 100644
--- a/analyze.py
+++ b/analyze.py
@@ -15,4 +15,5 @@
 from rql import TypeResolverException, nodes
 from pprint import pprint
 
+from copy import deepcopy
 
@@ -18,5 +19,12 @@
 
-class CSPProblem(object):
+try:
+    import rql_solve
+except ImportError:
+    rql_solve = None
+    # Gecode solver not available
+
+
+class ConstraintCSPProblem(object):
     def __init__(self):
         self.constraints = []
         self.domains = {}
@@ -85,7 +93,6 @@
         expr = " or ".join( list(orred) )
         self.add_expr( tuple(variables), expr )
 
-
 class _eq(object):
     def __init__(self, var, val):
         self.var = var
@@ -97,11 +104,6 @@
     def get_vars(self, s):
         s.add(self.var)
 
-    def simplify(self, doms):
-        dom = doms[self.var]
-        if self.val not in dom:
-            return -1
-        if len(dom)==1:
-            return 1
-        return 0
+    def for_gecode(self, all_vars, all_values):
+        return ["eq", all_vars.index( self.var ), all_values.index(self.val) ]
 
@@ -107,27 +109,4 @@
 
-    def accept(self, vis):
-        vis.visit_eq(self)
-        
-class _true(object):
-    def __str__(self):
-        return "True"
-    def get_vars(self, s):
-        pass
-    def simplify(self, doms):
-        return 1
-    def accept(self, vis):
-        vis.visit_true( self )
-
-class _false(object):
-    def __str__(self):
-        return "False"
-    def get_vars(self, s):
-        pass
-    def simplify(self, doms):
-        return -1
-    def accept(self, vis):
-        vis.visit_false( self )
-    
 class _eqv(object):
     def __init__(self, vars):
         self.vars = set(vars)
@@ -135,13 +114,14 @@
         return '(' + " == ".join( str(t) for t in self.vars ) + ')'
     def get_vars(self, s):
         s+=self.vars
-    def simplify(self, doms):
-        return 0
-    def accept(self, vis):
-        vis.visit_eqv( self )
+    def for_gecode(self, all_vars, all_values):
+        l = ["eqv"]
+        for v in self.vars:
+            l.append( all_vars.index( v ) )
+        return l
 
 class _and(object):
     def __init__(self):
         self.cond = []
     def add(self, expr):
         self.cond.append( expr )
@@ -142,11 +122,13 @@
 
 class _and(object):
     def __init__(self):
         self.cond = []
     def add(self, expr):
         self.cond.append( expr )
+        #if expr not in self.cond:
+        #    self.cond.append( expr )
     def __str__(self):
         return '(' + " and ".join( str(t) for t in self.cond ) + ')'
     def get_vars(self, s):
         for t in self.cond:
             t.get_vars(s)
@@ -148,8 +130,11 @@
     def __str__(self):
         return '(' + " and ".join( str(t) for t in self.cond ) + ')'
     def get_vars(self, s):
         for t in self.cond:
             t.get_vars(s)
-    def accept(self, vis):
-        vis.visit_and( self )
+    def for_gecode(self, all_vars, all_values):
+        l = ["and"]
+        for n in self.cond:
+            l.append( n.for_gecode(all_vars, all_values) )
+        return l
 
@@ -155,23 +140,5 @@
 
-    def simplify(self, doms):
-        cd = []
-        for f in self.cond:
-            res = f.simplify(doms)
-            if res==-1:
-                # always false
-                self.cond = [ _false() ]
-                return -1
-            if res==1:
-                # always true don't keep it
-                continue
-            cd.append(f)
-        self.cond = cd
-        if not cd:
-            # all true
-            self.cond = [ _true() ]
-            return 1
-        return 0
 
 class _or(_and):
     def __str__(self):
         return '(' + " or ".join( str(t) for t in self.cond ) + ')'
@@ -174,60 +141,19 @@
 
 class _or(_and):
     def __str__(self):
         return '(' + " or ".join( str(t) for t in self.cond ) + ')'
-
-    def simplify(self, doms):
-        cd = []
-        for f in self.cond:
-            res = f.simplify(doms)
-            if res==1:
-                # always true
-                self.cond = [ _true() ]
-                return 1
-            if res==-1:
-                # always false don't keep it
-                continue
-            cd.append(f)
-        self.cond = cd
-        if not cd:
-            self.cond = [ _false() ]
-            return -1
-        return 0
-    def accept(self, vis):
-        vis.visit_or( self )
-
-
-class DistributeVisitor(object):
-    """The purpose of this visitor is to distribute and's over
-    or's in the expression tree. For example if A and B is
-    represented as A*B and A or B as A+B we want to transform :
-    A*(B+C*(D+E)+A*B) into A*B+A*C*D+A*C*E+A*A*B
-    """
-    def __init__(self):
-        self.stack = []
-    def visit_and(self, node):
-        first = self.cond.pop(0)
-        if isinstance(first, _or):
-            distrib = _or.cond[:]
-        else:
-            distrib = [first]
-        while self.cond:
-            next = self.cond.pop(0)
-        
-    def visit_or(self, node):
-        pass
-    def visit_true(self, node):
-        pass
-    def visit_false(self, node):
-        pass
-    def visit_eq(self, node):
-        pass
-    def visit_eqv(self, node):
-        pass
-
-class _CSPProblem(object):
+    def for_gecode(self, all_vars, all_values):
+        l = ["or"]
+        for n in self.cond:
+            l.append( n.for_gecode(all_vars, all_values) )
+        return l
+# TODO: refactor/optimize:
+# now that gecode solver is working we don't need the above _and/_or... classes
+# we can generate the constraint tree directly as ["and", ['or',...], ... ]
+# Another thing that 
+class GecodeCSPProblem(object):
     def __init__(self):
         self.constraints = []
         self.op = _and()
         self.domains = {}
 
@@ -229,8 +155,34 @@
     def __init__(self):
         self.constraints = []
         self.op = _and()
         self.domains = {}
 
+    def get_output(self):
+        return ""
+    def solve(self):
+        # assign an integer to each var and each domain values
+        all_values = set()
+        all_vars = sorted(self.domains.keys())
+        for values in self.domains.values():
+            all_values.update(values)
+        all_values = sorted(all_values)
+        constraints = self.op.for_gecode( all_vars, all_values )
+        var_domains = []
+        for var in all_vars:
+            dom = []
+            for val in self.domains[var]:
+                dom.append( all_values.index(val) )
+            var_domains.append( dom )
+
+        sols = rql_solve.solve( var_domains, len(all_values), constraints )
+        rql_sols = []
+        for s in sols:
+            r={}
+            for var,val in zip(all_vars,s):
+                r[var] = all_values[val]
+            rql_sols.append(r)
+        return rql_sols
+
     def add_var(self, name, values):
         self.domains[name] = set(values)
 
@@ -234,41 +186,6 @@
     def add_var(self, name, values):
         self.domains[name] = set(values)
 
-    def get_domains(self):
-        self.simplify()
-        d = {}
-        for var, dom in self.domains.items():
-            print var, "==", dom
-            d[var] = fd.FiniteDomain(dom)
-        return d
-
-    def get_constraints(self):
-        self.simplify()
-        lst = []
-        for expr in self.op.cond:
-            constr = str(expr)
-            print constr
-            if isinstance(expr, _eq):
-                # taken into account bye simplify
-                continue
-            vrs = set()
-            expr.get_vars( vrs )
-            lst.append( fd.make_expression( tuple(vrs), constr ) )
-        print "----------"
-        return lst
-
-    def simplify(self):
-        print "EQN=", self.op
-        for op in self.op.cond:
-            if isinstance(op, _eqv):
-                s = self.domains[op.vars[0]]
-                for var in op.vars:
-                    s.intersection_update( self.domains[var] )
-                    self.domains[var] = s
-            if isinstance(op, _eq):
-                self.domains[op.var].intersection_update([op.val])
-        self.op.simplify(self.domains)
-
     def and_eq( self, var, value ):
         eq = _eq(var, value)
         self.op.add(eq)
@@ -310,8 +227,8 @@
                     else:
                         or2 = _or()
                         for t in types:
-                            or2.add( _eq(var, types[0]) )
+                            or2.add( _eq(var, t) )
                         anded.add( or2 )
             orred.add(anded)
         self.op.add(orred)
 
@@ -314,7 +231,12 @@
                         anded.add( or2 )
             orred.add(anded)
         self.op.add(orred)
 
+if rql_solve is None:
+    CSPProblem = ConstraintCSPProblem
+else:
+    CSPProblem = GecodeCSPProblem
+
 
 class ETypeResolver(object):
     """Resolve variables types according to the schema.
@@ -361,7 +283,6 @@
             pprint(domains)
             print "CONSTRAINTS:"
             pprint(constraints.scons)
-        domains = constraints.get_domains()
 
         sols = constraints.solve()
 
diff --git a/gecode_solver.cpp b/gecode_solver.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f14ebce130ddd822ac4bc643f3084c520cecb5ea_Z2Vjb2RlX3NvbHZlci5jcHA=
--- /dev/null
+++ b/gecode_solver.cpp
@@ -0,0 +1,269 @@
+#include <Python.h>
+#include <iostream>
+#include "gecode/kernel.hh"
+#include "gecode/int.hh"
+#include "gecode/search.hh"
+
+using namespace std;
+using namespace Gecode;
+
+class RqlContext {
+public:
+    RqlContext(long nvars, PyObject* domains,
+	       long nvalues, PyObject* constraints, PyObject* sols):
+	solutions(-1),
+	time(1000),
+	fails(-1),
+	nvars(nvars),
+	nvalues(nvalues),
+	constraints(constraints),
+	sols(sols),
+	domains(domains),
+	verbosity(false)
+    {
+    }
+
+    long solutions;
+    long time;
+    long fails;
+    long nvars;
+    long nvalues;
+    PyObject* constraints;
+    PyObject* sols;
+    PyObject* domains;
+    bool verbosity;
+};
+
+class RqlSolver : public Space {
+protected:
+    IntVarArray  variables;
+public:
+    RqlSolver() {}
+    RqlSolver(const RqlContext& pb):
+	variables(this,pb.nvars,0,pb.nvalues-1)
+    {
+	BoolVar root(this, 1,1);
+	set_domains( pb.domains );
+	add_constraints( pb.constraints, root );
+	
+	branch(this, variables, INT_VAR_NONE, INT_VAL_MIN);
+    }
+
+    ~RqlSolver() {};
+
+    RqlSolver(bool share, RqlSolver& s) : Space(share,s)
+    {
+	variables.update(this, share, s.variables);
+    }
+
+    void set_domains( PyObject* domains )
+    {
+	PyObject* ovalues;
+	int n = PyList_Size( domains );
+	for(int var=0;var<n;++var) {
+	    int i, nval;
+	    ovalues = PyList_GetItem( domains, var );
+	    nval = PyList_Size( ovalues );
+	    int* vals = new int[nval];
+	    for(i=0;i<nval;++i) {
+		vals[i] = PyInt_AsLong( PyList_GetItem( ovalues, i ) );
+	    }
+	    IntSet gvalues(vals,nval);
+	    dom(this, variables[var], gvalues);
+	    delete [] vals;
+	}
+    }
+
+    void add_constraints( PyObject* desc, BoolVar& var )
+    {
+	PyObject* type;
+	char* s_type;
+	type = PyList_GetItem( desc, 0 );
+	s_type = PyString_AsString( type );
+	if (strcmp(s_type, "eq")==0) {
+	    add_equality( desc, var );
+	} else if (strcmp(s_type, "eqv")==0) {
+	    add_equivalence( desc, var );
+	} else if (strcmp(s_type, "and")==0) {
+	    add_and( desc, var );
+	} else if (strcmp(s_type, "or")==0) {
+	    add_or( desc, var );
+	}
+    }
+
+    long get_int( PyObject* lst, int index ) {
+	PyObject* val;
+	val = PyList_GetItem(lst, index);
+	return PyInt_AsLong(val);
+    }
+
+    void add_equality( PyObject* desc, BoolVar& var ) {
+	long variable, value;
+	
+	variable = get_int( desc, 1 );
+	value = get_int( desc, 2 );
+	rel(this, variables[variable], IRT_EQ, value, var);
+    }
+
+    void add_equivalence( PyObject* desc, BoolVar& var ) {
+	int len = PyList_Size(desc);
+	int var0 = get_int( desc, 1 );
+
+	for (int i=1;i<len-1;++i) {
+	    int var1 = get_int(desc, i+1);
+	    rel( this, variables[var0], IRT_EQ, variables[var1], var );
+	}
+    }
+
+    void add_and( PyObject* desc, BoolVar& var ) {
+	int len = PyList_Size(desc);
+	BoolVarArray terms(this, len-1,0,1);
+	for(int i=0;i<len-1;++i) {
+	    PyObject* expr = PyList_GetItem(desc, i+1);
+	    add_constraints( expr, terms[i] );
+	}
+	rel(this, BOT_AND, terms, var);
+    }
+
+    void add_or( PyObject* desc, BoolVar& var ) {
+	int len = PyList_Size(desc);
+	BoolVarArray terms(this, len-1,0,1);
+	for(int i=0;i<len-1;++i) {
+	    PyObject* expr = PyList_GetItem(desc, i+1);
+	    add_constraints( expr, terms[i] );
+	}
+	rel(this, BOT_OR, terms, var);
+    }
+
+    template <template<class> class Engine>
+    static void run( RqlContext& pb, Search::Stop* stop )
+    {
+    double t0 = 0;
+    int i = pb.solutions;
+    //Timer t;
+    RqlSolver* s = new RqlSolver( pb );
+    //t.start();
+    unsigned int n_p = 0;
+    unsigned int n_b = 0;
+    if (s->status() != SS_FAILED) {
+	n_p = s->propagators();
+	n_b = s->branchings();
+    }
+    Search::Options opts;
+    //opts.c_d = pb.c_d;
+    //opts.a_d = pb.a_d;
+    opts.stop = stop;
+    Engine<RqlSolver> e(s, opts);
+    delete s;
+    do {
+	RqlSolver* ex = e.next();
+	if (ex == NULL)
+	    break;
+	ex->print(pb);
+	delete ex;
+	//t0 = t0 + t.stop();
+    } while (--i != 0 && t0 < pb.time);
+    Search::Statistics stat = e.statistics();
+    if (pb.verbosity) {
+	cout << endl;
+	cout << "Initial" << endl
+	     << "\tpropagators:   " << n_p << endl
+	     << "\tbranchings:    " << n_b << endl
+	     << endl
+	     << "Summary" << endl
+	     //<< "\truntime:       " << t.stop() << endl
+	     << "\truntime:       " << t0 << endl
+	     << "\tsolutions:     " << abs(static_cast<int>(pb.solutions) - i) << endl
+	     << "\tpropagations:  " << stat.propagate << endl
+	     << "\tfailures:      " << stat.fail << endl
+	     << "\tclones:        " << stat.clone << endl
+	     << "\tcommits:       " << stat.commit << endl
+	     << "\tpeak memory:   "
+	     << static_cast<int>((stat.memory+1023) / 1024) << " KB"
+	     << endl;
+    }
+    }
+    virtual void print(RqlContext& pb) {
+	PyObject *tuple, *ival;
+	tuple = PyTuple_New( pb.nvars );
+	for(int i=0;i<pb.nvars;++i) {
+	    ival = PyInt_FromLong( variables[i].val() );
+	    PyTuple_SetItem( tuple, i, ival );
+	}
+	PyList_Append( pb.sols, tuple );
+    }
+    virtual Space* copy(bool share) {
+	return new RqlSolver(share, *this);
+    }
+
+};
+
+class FailTimeStop : public Search::Stop {
+private:
+    Search::TimeStop *ts;
+    Search::FailStop *fs;
+public:
+    FailTimeStop(int fails, int time):ts(0L),fs(0L) {
+	if (time>=0)
+	    ts = new Search::TimeStop(time);
+	if (fails>=0) {
+	    fs = new Search::FailStop(fails);
+	}
+    }
+    bool stop(const Search::Statistics& s) {
+	int sigs = PyErr_CheckSignals();
+	bool fs_stop = false;
+	bool ts_stop = false;
+	if (fs) {
+	    fs_stop = fs->stop(s);
+	}
+	if (ts) {
+	    ts_stop = ts->stop(s);
+	}
+	return sigs || fs_stop || ts_stop;
+    }
+    /// Create appropriate stop-object
+    static Search::Stop* create(int fails, int time) {
+	return new FailTimeStop(fails, time);
+    }
+};
+
+static void _solve( RqlContext& ctx )
+{
+    Search::Stop *stop = FailTimeStop::create(ctx.fails, ctx.time);
+
+    RqlSolver::run<DFS>( ctx, stop );
+}
+
+
+static PyObject *
+rql_solve(PyObject *self, PyObject *args)
+{
+    PyObject* sols = 0L;
+    PyObject* constraints;
+    PyObject* domains;
+    long nvars, nvalues;
+    sols = PyList_New(0);
+    if (!PyArg_ParseTuple(args, "OiO", &domains, &nvalues, &constraints))
+        return NULL;
+    nvars = PyList_Size(domains);
+    RqlContext ctx(nvars, domains, nvalues, constraints, sols );
+    _solve( ctx );
+    return sols;
+}
+
+static PyMethodDef SolveRqlMethods[] = {
+    {"solve",  rql_solve, METH_VARARGS,
+     "Solve RQL variable types problem."},
+    {NULL, NULL, 0, NULL}        /* Sentinel */
+};
+
+
+PyMODINIT_FUNC
+initrql_solve(void)
+{
+    PyObject* m;
+    m = Py_InitModule("rql_solve", SolveRqlMethods);
+    if (m == NULL)
+        return;
+}