diff --git a/pub/src/expr.cpp b/pub/src/expr.cpp
index 31e6ffb78b28c8dc582ce77b9d21f95cc8370386..8c0c076911bd14be8ac83cf5f3aa29f528807c8b 100644
--- a/pub/src/expr.cpp
+++ b/pub/src/expr.cpp
@@ -27,7 +27,7 @@ extern bool allow_slow_conv; // TODO unify parameter treatment
 #define DEBUG 0
 
 //***************************************************************************//
-//* class CContext                                                          *//
+//* CContext                                                                *//
 //***************************************************************************//
 
 //! Constructor. Set k,j,i, checking validity. Set other par's to default.
@@ -111,7 +111,7 @@ string CContext::context_info() const
 
 
 //***************************************************************************//
-//* class CResult                                                           *//
+//* CResult                                                                 *//
 //***************************************************************************//
 
 //! Introspection, for debugging.
@@ -127,20 +127,20 @@ string CResult::result_info() const
 
 
 //***************************************************************************//
-//* class CRef (references like y[k,j,0] or p3[2] or ...)                   *//
+//* CRef (references like y[k,j,0] or p3[2] or ...)                         *//
 //***************************************************************************//
 
 //! Description of reference (for use in ??)
 
 void CRef::set_coord( CCoord& ret, uint k_in ) const
 {
-    if     ( typ == _K ) {
+    if        ( var.typ == CVariable::_K ) {
         ret = CCoord("k","");
         return;
-    } else if ( typ == _J ) {
+    } else if ( var.typ == CVariable::_J ) {
         ret = CCoord("j","");
         return;
-    } else if ( typ == _I ) {
+    } else if ( var.typ == CVariable::_I ) {
         ret = CCoord("i","");
         return;
     }
@@ -161,56 +161,77 @@ void CRef::set_coord( CCoord& ret, uint k_in ) const
     if (!f)
         throw "set_coord: ref where not refering to a file";
 
-    if  ( typ == _Z ) {
-        if (num>=f->ZCo.size())
-            throw "set_coord: z" + strg(num) + " undefined";
-        ret = f->ZCo[num];
-    } else if  ( typ == _R ) {
-        if (num>=f->RPar.size())
-            throw "set_coord: r" + strg(num) + " undefined";
-        ret = f->RPar[num].Co;
-    } else if ( typ == _NJ ) {
+    if  ( var.typ == CVariable::_Z ) {
+        if (var.num>=f->ZCo.size())
+            throw "set_coord: z" + strg(var.num) + " undefined";
+        ret = f->ZCo[var.num];
+    } else if  ( var.typ == CVariable::_R ) {
+        if (var.num>=f->RPar.size())
+            throw "set_coord: r" + strg(var.num) + " undefined";
+        ret = f->RPar[var.num].Co;
+    } else if ( var.typ == CVariable::_NJ ) {
         ret = CCoord("#spectra", "");
     } else {
         POld fd = P2D( f );
         POlc fc = P2C( f );
         if         ( fd ) {
-            if       ( typ == _X )
+            if       ( var.typ == CVariable::_X )
                 ret = fd->xco;
-            else if  ( typ == _Y )
+            else if  ( var.typ == CVariable::_Y )
                 ret = fd->yco;
-            else if  ( typ == _DY )
+            else if  ( var.typ == CVariable::_DY )
                 ret = CCoord( "d"+fd->yco.name, fd->yco.unit );
-            else if  ( typ == _NI )
+            else if  ( var.typ == CVariable::_NI )
                 ret = CCoord("#points", "");
             else
-                throw "reference " + var_info() + " not allowed in data file";
+                throw "reference " + var.var_info() +
+                    " not allowed in data file";
         } else if ( fc ) {
-            if     ( typ == _CP ) {
-                if( num>=fc->nPar() )
-                    throw "invalid reference p" + strg(num);
-                ret = fc->PCo[num];
-            } else if ( typ == _CQ )
-                ret = CCoord("cq"+strg(num), ""); // fit quality indicator
-            else if ( typ == _C )
+            if     ( var.typ == CVariable::_CP ) {
+                if( var.num>=fc->nPar() )
+                    throw "invalid reference p" + strg(var.num);
+                ret = fc->PCo[var.num];
+            } else if ( var.typ == CVariable::_CQ )
+                ret = CCoord("cq"+strg(var.num), ""); // fit quality indicator
+            else if ( var.typ == CVariable::_C )
                 ret = CCoord(fc->expr,"");
             else
-                throw "reference " + var_info() + " not allowed in curve file";
+                throw "reference " + var.var_info() +
+                    " not allowed in curve file";
         } else
             throw "BUG: ref->set_coord unexpected else";
     }
 }
 
+string CRef::ref_info() const
+{
+    string out = "ref: ";
+    if ( tk )
+        out += "tk[" + tk->tree_info() + "], ";
+    else
+        out += "tk=0, ";
+    if ( tj )
+        out += "tj[" + tj->tree_info() + "], ";
+    else
+        out += "tj=0, ";
+    if ( ti )
+        out += "ti[" + ti->tree_info() + "]";
+    else
+        out += "ti=0";
+    return out;
+}
+
 
 //***************************************************************************//
-//* CRef / evaluation                                                       *//
+//* CRef: evaluation                                                        *//
 //***************************************************************************//
 
 //! Evaluate reference in given context. Result returned in ret.
 
 void CRef::ref_val( CResult& ret, const CContext& ctx ) const
 {
-    if ( (typ==_I || typ==_J || typ==_K) && ( ti || tj || tk ) )
+    if ( (var.typ == CVariable::_I || var.typ == CVariable::_J ||
+          var.typ == CVariable::_K) && ( ti || tj || tk ) )
         throw "invalid cross reference: index cannot be indexed";
 
     // Get k from context:
@@ -219,7 +240,7 @@ void CRef::ref_val( CResult& ret, const CContext& ctx ) const
     if ( tk ) {
         tk->tree_val( tmp, ctx );
         if ( tmp.vectorial ) {
-            if ( typ==_K ) {
+            if ( var.typ == CVariable::_K ) {
                 ret.preset_v( ctx.nv );
                 for( uint i=0; i<ctx.nv; ++i )
                     ret.v[i] = tmp.v[i];
@@ -237,7 +258,7 @@ void CRef::ref_val( CResult& ret, const CContext& ctx ) const
         throw "index k=" + strg(k) + " out of bounds";
 
     // Return k-dependent reference (unless already done above):
-    if ( typ == _K ) {
+    if ( var.typ == CVariable::_K ) {
         ret.set_r( k );
         return;
     }
@@ -245,13 +266,13 @@ void CRef::ref_val( CResult& ret, const CContext& ctx ) const
     // Proceed with file reference f[k]:
     POlo f = NOlm::MOM[k];
 
-    if ( typ==_NJ ) {
+    if        ( var.typ == CVariable::_NJ ) {
         ret.set_r( f->nJ() );
         return;
-    } else if ( typ==_R ) {
-        if ( num>= f->RPar.size() )
-            throw "invalid reference " + var_info();
-        ret.set_r( f->RPar[num].val );
+    } else if ( var.typ == CVariable::_R ) {
+        if ( var.num>= f->RPar.size() )
+            throw "invalid reference " + var.var_info();
+        ret.set_r( f->RPar[var.num].val );
         return;
     }
 
@@ -260,20 +281,20 @@ void CRef::ref_val( CResult& ret, const CContext& ctx ) const
     if ( tj ) {
         tj->tree_val( tmp, ctx );
         if ( tmp.vectorial ) {
-            if ( typ==_J ) {
+            if ( var.typ == CVariable::_J ) {
                 ret.preset_v( ctx.nv );
                 for( uint i=0; i<ctx.nv; ++i )
                     ret.v[i] = tmp.v[i];
                 return;
-            } else if ( typ==_Z ) {
-                if ( num>= f->nZ() )
-                    throw "invalid reference " + var_info();
+            } else if ( var.typ == CVariable::_Z ) {
+                if ( var.num>= f->nZ() )
+                    throw "invalid reference " + var.var_info();
                 ret.preset_v( ctx.nv );
                 for( uint i=0; i<ctx.nv; ++i ) {
                     j = (uint)( tmp.v[i]+0.5 );
                     if( j>=f->V.size() )
                         throw "j out of bounds";
-                    ret.v[i] = f->V[j]->z[num];
+                    ret.v[i] = f->V[j]->z[var.num];
                 }
                 return;
             } else
@@ -289,13 +310,13 @@ void CRef::ref_val( CResult& ret, const CContext& ctx ) const
         throw "index j=" + strg(j) + " out of bounds";
 
     // Return k-j-dependent reference (unless done above):
-    if        ( typ == _J ) {
+    if        ( var.typ == CVariable::_J ) {
         ret.set_r( ctx.j );
         return;
-    } else if ( typ == _Z ) {
-        if ( num>= f->nZ() )
-            throw "invalid reference " + var_info();
-        ret.set_r( f->V[j]->z[num] );
+    } else if ( var.typ == CVariable::_Z ) {
+        if ( var.num>= f->nZ() )
+            throw "invalid reference " + var.var_info();
+        ret.set_r( f->V[j]->z[var.num] );
         return;
     }
 
@@ -303,8 +324,8 @@ void CRef::ref_val( CResult& ret, const CContext& ctx ) const
     POld fd = P2D( f );
     if ( fd ) {
         PSpec sj = fd->VS(j);
-        if        ( typ==_I || typ == _X || typ == _Y || typ == _DY ) {
-            if ( typ==_DY && !sj->dy.size() )
+        if        ( var.pointwise() ) {
+            if ( var.typ == CVariable::_DY && !sj->dy.size() )
                 throw string( "dy not set" );
             if        ( ctx.dim==CContext::_1 ) {
                 uint i;
@@ -318,15 +339,15 @@ void CRef::ref_val( CResult& ret, const CContext& ctx ) const
                 if( i>= sj->size() )
                     throw "i=" + strg(i) + " exceeds scan size" +
                         strg(sj->size());
-                if       ( typ == _I ) {
+                if       ( var.typ == CVariable::_I ) {
                     ret.set_r( i );
-                } else if ( typ == _X ) {
+                } else if ( var.typ == CVariable::_X ) {
                     ret.set_r( sj->x[i] );
-                } else if ( typ == _Y ) {
+                } else if ( var.typ == CVariable::_Y ) {
                     ret.set_r( sj->y[i] );
                     if ( ctx.want_error && sj->dy.size() )
                         ret.dr = sj->dy[i];
-                } else if ( typ == _DY ) {
+                } else if ( var.typ == CVariable::_DY ) {
                     ret.set_r( sj->dy[i] );
                 }
             } else if ( ctx.dim==CContext::_VI ) {
@@ -334,7 +355,8 @@ void CRef::ref_val( CResult& ret, const CContext& ctx ) const
                     CContext myctx = ctx;
                     myctx.dim = CContext::_1;
                     ret.preset_v( ctx.nv );
-                    if ( typ==_Y && ctx.want_error && sj->dy.size() )
+                    if ( var.typ == CVariable::_Y && ctx.want_error &&
+                         sj->dy.size() )
                         ret.dv.resize( ctx.nv );
                     for( uint ii=0; ii<ctx.nv; ++ii ){
                         myctx.i = ii;
@@ -343,43 +365,43 @@ void CRef::ref_val( CResult& ret, const CContext& ctx ) const
                         if( i >= sj->size() )
                             throw "i=" + strg(i) + " exceeds scan size" +
                                 strg(sj->size());
-                        if        ( typ == _I ) {
+                        if        ( var.typ == CVariable::_I ) {
                             ret.v[ii] = i;
-                        } else if ( typ == _X ) {
+                        } else if ( var.typ == CVariable::_X ) {
                             ret.v[ii] = sj->x[i];
-                        } else if ( typ == _Y ) {
+                        } else if ( var.typ == CVariable::_Y ) {
                             ret.v[ii] = sj->y[i];
                             if ( ret.dv.size() )
                                 ret.dv[ii] = sj->dy[i];
-                        } else if ( typ == _DY ) {
+                        } else if ( var.typ == CVariable::_DY ) {
                             ret.v[ii] = sj->dy[i];
                         }
                     }
                 } else {
                     if ( ctx.nv != sj->size() )
-                        throw "ref_val " + var_info() + ": requested vec(" +
+                        throw "ref_val " + var.var_info() + ": requested vec(" +
                             strg(ctx.nv) + "), found vec(" +
                             strg( sj->size() );
-                    if        ( typ == _I ) {
+                    if        ( var.typ == CVariable::_I ) {
                         ret.preset_v( ctx.nv );
                         for( uint i=0; i<ctx.nv; ++i )
                             ret.v[i] = i;
-                    } else if ( typ == _X ) {
+                    } else if ( var.typ == CVariable::_X ) {
                         ret.set_v( sj->x );
-                    } else if ( typ == _Y ) {
+                    } else if ( var.typ == CVariable::_Y ) {
                         ret.set_v( sj->y );
                         if ( ctx.want_error )
                             ret.dv = sj->dy;
-                    } else if ( typ == _DY ) {
+                    } else if ( var.typ == CVariable::_DY ) {
                         ret.set_v( sj->dy );
                     }
                 }
             } else
                 throw string( "BUG: invalid context::dim" );
-        } else if ( typ == _NI ) {
+        } else if ( var.typ == CVariable::_NI ) {
             ret.set_r( sj->size() );
         } else
-            throw "invalid ref(" + var_info() + ") in data file";
+            throw "invalid ref(" + var.var_info() + ") in data file";
         return;
     }
 
@@ -387,38 +409,20 @@ void CRef::ref_val( CResult& ret, const CContext& ctx ) const
     POlc fc = P2C( f );
     if ( fc ) {
         PCurve cj = fc->VC(j);
-        if       ( typ == _CP ) {
-            if ( num>= fc->nPar() )
-                throw "invalid p ref(" + var_info() + ") in curve file";
-            ret.set_r( cj->P[num] );
-        } else if ( typ == _CQ ) {
-            if ( num >= CCurve::mQuality )
-                throw "invalid fm ref(" + var_info() + ") in curve file";
-            ret.set_r( cj->Quality[num] );
+        if       ( var.typ == CVariable::_CP ) {
+            if ( var.num>= fc->nPar() )
+                throw "invalid p ref(" + var.var_info() + ") in curve file";
+            ret.set_r( cj->P[var.num] );
+        } else if ( var.typ == CVariable::_CQ ) {
+            if ( var.num >= CCurve::mQuality )
+                throw "invalid fm ref(" + var.var_info() + ") in curve file";
+            ret.set_r( cj->Quality[var.num] );
         } else 
-            throw "invalid ref(" + var_info() + ") in curve file";
+            throw "invalid ref(" + var.var_info() + ") in curve file";
         return;
     }
 }
 
-string CRef::ref_info() const
-{
-    string out = "ref: ";
-    if ( tk )
-        out += "tk[" + tk->tree_info() + "], ";
-    else
-        out += "tk=0, ";
-    if ( tj )
-        out += "tj[" + tj->tree_info() + "], ";
-    else
-        out += "tj=0, ";
-    if ( ti )
-        out += "ti[" + ti->tree_info() + "]";
-    else
-        out += "ti=0";
-    return out;
-}
-
 
 //***************************************************************************//
 //* CTree: status requests                                                  *//
@@ -433,7 +437,6 @@ uint CTree::npar() const
     return np;
 }
 
-
 //! Does the result depend on k?
 
 bool CTree::k_dependent() const
@@ -733,8 +736,8 @@ CNodeIva::CNodeIva( PRef& _ref )
 
 void CNodeIva::npar_exec( uint *np ) const
 {
-    if ( ref->typ==CRef::_CP )
-        *np = max( *np, ref->num+1 );
+    if ( ref->var.typ == CVariable::_CP )
+        *np = max( *np, ref->var.num+1 );
 }
 
 //***************************************************************************//
diff --git a/pub/src/expr.h b/pub/src/expr.h
index 5afe5caf106f47f256d93199816c4a3395cdf32f..e233d33fc56e3f65aa7b71c0cc9ec00e9e401994 100644
--- a/pub/src/expr.h
+++ b/pub/src/expr.h
@@ -64,13 +64,14 @@ class CResult {
 
 //! References to data points, indices, ...; used as endpoints of CTree's.
 
-class CRef: public CVariable {
+class CRef {
  public:
+    CVariable var;
     PTree tk;
     PTree tj;
     PTree ti;
 
-    CRef( const string s="" ) : CVariable(s) {};
+    CRef( const string s="" ) : var(s) {};
     
     void ref_val( CResult& ret, const CContext& ctx ) const;
     void set_coord( CCoord& ret, uint k ) const;
diff --git a/pub/src/node.h b/pub/src/node.h
index 918c5df1f785ca2a23d1e3ebd6ac3832e6a02aec..4cfda5225b96421e7592fc92862fdad525b83c72 100644
--- a/pub/src/node.h
+++ b/pub/src/node.h
@@ -57,7 +57,7 @@ class CNodeIva: public CTree {
     void kdep_exec( bool *kd ) const { *kd = true; }
     void set_coord( CCoord& ret, uint k ) const {
         ref->set_coord( ret, k ); }
-    string tree_info() const { return "ref[" + ref->var_info() + "]"; }
+    string tree_info() const { return "ref[" + ref->var.var_info() + "]"; }
 };
 
 
@@ -105,7 +105,7 @@ class CNodeCev: public CTree {
     void tree_val( CResult& ret, const CContext& ctx ) const;
     bool has_dummy() const { return arg->has_dummy(); }
     void set_coord( CCoord& ret, uint k ) const;
-    string tree_info() const { return "c[" + ref->var_info() + "]"; }
+    string tree_info() const { return "c[" + ref->var.var_info() + "]"; }
 };