From dec6b1e05093f5067621a3ae7e2503778ed4583c Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Sun, 18 Oct 2015 11:55:10 +0200
Subject: [PATCH] migrated x,y,dy to new tree_val

---
 pub/lib/expr.cpp     |  45 +++-----
 pub/lib/expr.hpp     |  15 ++-
 pub/lib/node.cpp     | 268 ++++++++++++++-----------------------------
 pub/lib/node.hpp     |  80 +++++++++----
 pub/lib/slice.hpp    |  36 +++---
 pub/lib/toplevel.cpp |   4 +
 pub/lib/xax_lex.lpp  |  12 +-
 pub/lib/xax_yacc.ypp |  10 +-
 8 files changed, 206 insertions(+), 264 deletions(-)

diff --git a/pub/lib/expr.cpp b/pub/lib/expr.cpp
index a29585c6..1548b73b 100644
--- a/pub/lib/expr.cpp
+++ b/pub/lib/expr.cpp
@@ -126,6 +126,14 @@ int CRef1::get_k( const CContext& ctx ) const
 }
 
 
+//! Returns true if index k has an explicit dependence on i.
+
+bool CRef1::k_depends_on_i() const
+{
+    return tk && tk->i_dependent();
+}
+
+
 //! Returns string representation of the class instance.
 
 string CRef1::ref_info() const
@@ -161,6 +169,14 @@ int CRef2::get_j( const CContext& ctx, int nj ) const
 }
 
 
+//! Returns true if index j has an explicit dependence on i.
+
+bool CRef2::j_depends_on_i() const
+{
+    return tj && tj->i_dependent();
+}
+
+
 //! Returns string representation of the class instance.
 
 string CRef2::ref_info() const
@@ -187,31 +203,6 @@ string CRef3::ref_info() const
 }
 
 
-//**************************************************************************************************
-//*  CNode: status requests
-//**************************************************************************************************
-
-
-//! Returns number of curve parameters used in node and below.
-
-int CNode::npar() const
-{
-    int np=0;
-    npar_exec( &np ); // implemented with pointer argument to allow recursion
-    return np;
-}
-
-
-//! Does the node depend on k?
-
-bool CNode::k_dependent() const
-{
-    bool kd=false;
-    kdep_exec( &kd );
-    return kd;
-}
-
-
 //**************************************************************************************************
 //*  CNode: low-level tree evaluation
 //**************************************************************************************************
@@ -224,10 +215,10 @@ int CNode::tree_val_idx( const CContext& ctx, const string& name ) const
     RObj val = tree_val( ctx );
     RObjInt pi = PCAST<const CObjInt>(val);
     if ( !pi )
-        throw "Index "+name+"="+val->to_s()+" is not integer";
+        throw "index "+name+"="+val->to_s()+" is not integer";
     int ret = pi->val;
     if( ret<0 )
-        throw "Index "+name+"="+val->to_s()+" is negativ";
+        throw "index "+name+"="+val->to_s()+" is negativ";
     return ret;
 }
 
diff --git a/pub/lib/expr.hpp b/pub/lib/expr.hpp
index 9b7a1737..69dbbf75 100644
--- a/pub/lib/expr.hpp
+++ b/pub/lib/expr.hpp
@@ -36,6 +36,7 @@ class CRef1 {
     RNode tk; //!< A node yielding the workspace index k.
     CRef1( RNode _tk=RNode() ) : tk(_tk) {}
     int get_k( const CContext& ctx ) const;
+    bool k_depends_on_i() const;
     virtual string ref_info() const;
 };
 
@@ -47,6 +48,7 @@ class CRef2 : public CRef1 {
     RNode tj; //!< A node yielding the spectrum index j.
     CRef2( RNode _tk=RNode(), RNode _tj=RNode() ) : CRef1(_tk), tj(_tj) {}
     int get_j( const CContext& ctx, int nj ) const;
+    bool j_depends_on_i() const;
     virtual string ref_info() const;
 };
 
@@ -64,14 +66,17 @@ class CRef3 : public CRef2 {
 //! Virtual base class for all kinds of nodes in an expression tree.
 
 class CNode {
+ private:
  public:
     virtual ~CNode() {}
-    virtual void npar_exec( int *np ) const {};
-    //! Recursive: set *kd=true if a subnode is K dependent
-    virtual void kdep_exec( bool *kd ) const {;} //!< default: do nothing
 
-    int npar() const;
-    bool k_dependent() const;
+    virtual void npar_exec( int *ret ) const {};  //!< increase *ret if a subnode is a curve par
+    virtual void kdep_exec( bool *ret ) const {;} //!< set *ret=true if a subnode is K dependent
+    virtual void idep_exec( bool *ret ) const {;} //!< set *ret=true if a subnode is I dependent
+    int npar() const { int ret=0; npar_exec( &ret ); return ret; }
+    bool k_dependent() const { bool ret=false; kdep_exec( &ret ); return ret; }
+    bool i_dependent() const { bool ret=false; idep_exec( &ret ); return ret; }
+
     virtual bool has_dummy() const { return false; } //!< does node depend on t ?
     virtual bool has_conv() const { return false; } //!< does node depend on resolution ?
 
diff --git a/pub/lib/node.cpp b/pub/lib/node.cpp
index 5fada15a..5de53b98 100644
--- a/pub/lib/node.cpp
+++ b/pub/lib/node.cpp
@@ -27,8 +27,6 @@
 
 extern bool allow_slow_conv; // set in curve.cpp
 
-#define DEBUG 0
-
 
 //**************************************************************************************************
 //* CNodeWithArgs
@@ -50,18 +48,25 @@ bool CNodeWithArgs::has_conv() const
     return false;
 }
 
-void CNodeWithArgs::kdep_exec( bool *kd ) const
+void CNodeWithArgs::npar_exec( int *ret ) const
+{
+    for ( int iarg=0; iarg<narg; ++iarg )
+        if( arg[iarg] )
+            arg[iarg]->npar_exec( ret );
+}
+
+void CNodeWithArgs::kdep_exec( bool *ret ) const
 {
     for ( int iarg=0; iarg<narg; ++iarg )
         if( arg[iarg] )
-            arg[iarg]->kdep_exec( kd );
+            arg[iarg]->kdep_exec( ret );
 }
 
-void CNodeWithArgs::npar_exec( int *np ) const
+void CNodeWithArgs::idep_exec( bool *ret ) const
 {
     for ( int iarg=0; iarg<narg; ++iarg )
         if( arg[iarg] )
-            arg[iarg]->npar_exec( np );
+            arg[iarg]->idep_exec( ret );
 }
 
 
@@ -557,7 +562,7 @@ RObj CNodeGeni::tree_val( const CContext& ctx ) const
         return RObjDbl( new CObjDbl( val ) );
 
     } catch( string& ex ) {
-        throw ex+" in NodeGeni "+tree_info()+" {context: "+ctx.context_info()+"}";
+        throw ex+"\n called by integral node "+tree_info()+" {context: "+ctx.context_info()+"}";
     }
 }
 
@@ -782,7 +787,7 @@ RObj CNodeFileR::tree_val_scalar( const CContext& ctx ) const
     
 
 //**************************************************************************************************
-//* CNodeSlice: slice-wide information
+//* CNodeSlice/Spec/Curve: slice-wide information
 //**************************************************************************************************
 
 
@@ -836,196 +841,99 @@ RObj CNodeCurveR2::curve_val_scalar( RCurve c ) const
 }
     
 
-
-
-/*
-RObj CCurve::get_var( const RVar& var ) const
+RObj CNodePoint::tree_val( const CContext& ctx ) const
 {
-    if       ( var->categ == VCateg::CP ) {
-        if ( var->num >= P.size() )
-            throw "invalid p ref("+var->var_info()+") in curve file";
-        return RObjDbl( new CObjDbl( P[var->num] ) );
-
-    } else if ( var->categ == VCateg::COUTCOME ) {
-        return RObjInt( new CObjInt( fitOutcome ) );
-
-    } else if ( var->categ == VCateg::CCHI2 ) {
-        return RObjDbl( new CObjDbl( fitChi2 ) );
-
-    } else if ( var->categ == VCateg::CR2 ) {
-        return RObjDbl( new CObjDbl( fitR2 ) );
-
+    if ( ctx.dim==CContext::_VI ) {
+        if ( ref->k_depends_on_i() || PCAST<const CRef2>(ref)->j_depends_on_i() ) {
+            if ( ctx.nv<0 )
+                throw S("BUG: i-dependent K or J incompatible with unspecified return array length");
+            PObjVecObj tmp( new CObjVecObj() );
+            for ( int i=0; i<ctx.nv; ++i ) {
+                tmp->v.push_back( tree_val_point( ctx, i ) );
+            }
+            return tmp->to_vecnum();
+        } else {
+            return tree_val_vector( ctx );
+        }
+    } else {
+        if ( PCAST<const CRef3>(ref)->ti ) {
+            return tree_val_point( ctx, PCAST<const CRef3>(ref)->ti->tree_val_idx( ctx, "i" )  );
+        } else {
+            return tree_val_point( ctx, ctx.i );
+        }
     }
-    throw "invalid reference "+var->var_info()+" to curve file";
 }
-*/
 
-//**************************************************************************************************
-//* CNodeIva: indexed variable node
-//**************************************************************************************************
 
-void CNodeIva::npar_exec( int *np ) const
+RObj CNodePoint::tree_val_point( const CContext& ctx, int i ) const
+{
+    POlo f = NOlm::mem_get( ref->get_k( ctx ) );
+    POld fd = P2D( f );
+    int j = PCAST<const CRef2>(ref)->get_j( ctx, f->nJ() );
+    RSpec s = fd->VS(j);
+    if ( i<0 || i>= s->size() )
+        throw "invalid data point index "+S(i)+", spectrum has length "+S(s->size());
+    return spec_val_point( s, i, ctx.want_error );
+}
+    
+
+RObj CNodePoint::tree_val_vector( const CContext& ctx ) const
 {
-    if ( var->categ == VCateg::CP )
-        *np = std::max( *np, var->num+1 );
+    if ( ctx.dim!=CContext::_VI )
+        throw S("BUG: unexpected context in tree_val_vector");
+    POlo f = NOlm::mem_get( ref->get_k( ctx ) );
+    POld fd = P2D( f );
+    int j = PCAST<const CRef2>(ref)->get_j( ctx, f->nJ() );
+    RSpec s = fd->VS(j);
+    int n = ctx.nv;
+    if ( n<0 )
+        n = s->size();
+    else if ( n>s->size() )
+        throw "requested "+S(n)+" points while spectrum "+S(j)+" only has "+S(s->size())+" points";
+    return spec_val_vector( s, n, ctx.want_error );
 }
 
-//! Evaluates indexed variable in given context.
 
-RObj CNodeIva::tree_val( const CContext& ctx ) const
+RObj CNodePointX::spec_val_point( RSpec s, int i, bool want_error ) const
 {
-    // check syntactic validity
-    if ( !var->pointwise() && PCAST<const CRef3>(ref)->ti )
-        throw "reference "+var->var_info()+" does not admit three indices";
-    if ( !(var->pointwise() || var->slicewise()) && PCAST<const CRef2>(ref)->tj )
-        throw "reference "+var->var_info()+" does not admit two indices";
-    if ( !(var->pointwise() || var->slicewise() || var->filewise()) && PCAST<const CRef2>(ref)->tk )
-        throw "reference "+var->var_info()+" does not admit an index";
+    return RObjDbl( new CObjDbl( s->x[i] ) );
+}
 
-    int k = ref->get_k( ctx );
-    POlo f = NOlm::mem_get(k);
+RObj CNodePointX::spec_val_vector( RSpec s, int n, bool want_error ) const
+{
+    return RObjVecDbl( new CObjVecDbl( vector<double>(s->x.begin(), s->x.begin()+n ) ) );
+}
 
-    // Ref2erences for data file
-    POld fd = P2D( f );
-    if ( fd ) {
-        if        ( var->pointwise() ) {
-            if        ( ctx.dim==CContext::_1 ) {
-                int j = PCAST<const CRef2>(ref)->get_j( ctx, f->nJ() );
-                PSpec sj = fd->VS(j);
-                int i;
-                if ( PCAST<const CRef3>(ref)->ti ) {
-                    i = PCAST<const CRef3>(ref)->ti->tree_val_idx( ctx, "I" );
-                } else {
-                    i = ctx.i;
-                    if ( i==(int)-1 )
-                        throw S("missing index I");
-                }
-                if( i>= sj->size() )
-                    throw "i="+S(i)+" while there are only ni="+S(sj->size())+" points";
-                if ( var->categ == VCateg::X ) {
-                    return RObjDbl( new CObjDbl( sj->x[i] ) );
-                } else if ( var->categ == VCateg::Y ) {
-                    if ( ctx.want_error && sj->has_dy() )
-                        return RObjEnu( new CObjEnu( sj->y[i], sj->dy[i] ) );
-                    else
-                        return RObjDbl( new CObjDbl( sj->y[i] ) );
-                } else if ( var->categ == VCateg::DY ) {
-                    return RObjDbl( new CObjDbl( sj->dy[i] ) );
-                } else
-                    throw S("BUG: unexpected case");
-
-            } else if ( ctx.dim==CContext::_VI ) {
-                if ( PCAST<const CRef3>(ref)->ti ) {
-                    CContext myctx = ctx;
-                    myctx.dim = CContext::_1;
-                    if ( var->categ == VCateg::Y ) {
-                        if ( ctx.want_error ) {
-                            PObjVecEnu pret( new CObjVecEnu( ctx.nv ) );
-                            for ( int ii=0; ii<ctx.nv; ++ii ) {
-                                myctx.i = ii;
-                                int j = PCAST<const CRef2>(ref)->get_j( myctx, f->nJ() );
-                                RSpec sj = fd->VS(j);
-                                if ( !sj->has_dy() )
-                                    goto vi_y_dbl;
-                                int i = PCAST<const CRef3>(ref)->ti->tree_val_idx( myctx, "I" );
-                                if( i >= sj->size() )
-                                    throw "i="+S(i)+" while there are only"
-                                        " ni="+S(sj->size())+" points";
-                                pret->v[ii] = sj->y[i];
-                                pret->dv[ii] = sj->dy[i];
-                            }
-                            return pret;
-                        }
-                    vi_y_dbl:
-                        PObjVecDbl pret2( new CObjVecDbl( ctx.nv ) );
-                        for ( int ii=0; ii<ctx.nv; ++ii ) {
-                            myctx.i = ii;
-                            int j = PCAST<const CRef2>(ref)->get_j( myctx, f->nJ() );
-                            RSpec sj = fd->VS(j);
-                            int i = PCAST<const CRef3>(ref)->ti->tree_val_idx( myctx, "I" );
-                            if( i >= sj->size() )
-                                throw "i="+S(i)+" while there are only"
-                                    " ni="+S(sj->size())+" points";
-                            pret2->v[ii] = sj->y[i];
-                        }
-                        return pret2;
-                    } else if ( var->categ == VCateg::X ) {
-                        PObjVecDbl pret( new CObjVecDbl( ctx.nv ) );
-                        for ( int ii=0; ii<ctx.nv; ++ii ) {
-                            myctx.i = ii;
-                            int j = PCAST<const CRef2>(ref)->get_j( myctx, f->nJ() );
-                            RSpec sj = fd->VS(j);
-                            int i = PCAST<const CRef3>(ref)->ti->tree_val_idx( myctx, "I" );
-                            if( i >= sj->size() )
-                                throw "i="+S(i)+" while there are only"
-                                    " ni="+S(sj->size())+" points";
-                            pret->v[ii] = sj->x[i];
-                        }
-                        return pret;
-                    } else if ( var->categ == VCateg::DY ) {
-                        PObjVecDbl pret( new CObjVecDbl( ctx.nv ) );
-                        for ( int ii=0; ii<ctx.nv; ++ii ) {
-                            myctx.i = ii;
-                            int j = PCAST<const CRef2>(ref)->get_j( myctx, f->nJ() );
-                            RSpec sj = fd->VS(j);
-                            int i = PCAST<const CRef3>(ref)->ti->tree_val_idx( myctx, "I" );
-                            if( i >= sj->size() )
-                                throw "i="+S(i)+" while there are only"
-                                    " ni="+S(sj->size())+" points";
-                            pret->v[ii] = sj->dy[i];
-                        }
-                        return pret;
-                    }
-                    throw S("BUG: unexpected case");
 
-                } else {
-                    int j = PCAST<const CRef2>(ref)->get_j( ctx, f->nJ() );
-                    PSpec sj = fd->VS(j);
-                    int nv = ctx.nv;
-                    if ( nv==-1 ) {
-                        nv = sj->size();
-                    } else if ( nv != sj->size() )
-                        throw "ref_val "+var->var_info()+": requested vec("+S(ctx.nv)+
-                            "), found vec("+S( sj->size() );
-                    if ( var->categ == VCateg::X ) {
-                        return RObjVecDbl( new CObjVecDbl( sj->x ) );
-                    } else if ( var->categ == VCateg::Y ) {
-                        if ( ctx.want_error && sj->has_dy() )
-                            return RObjVecEnu( new CObjVecEnu( sj->y, sj->dy ) );
-                        else
-                            return RObjVecDbl( new CObjVecDbl( sj->y ) );
-                    } else if ( var->categ == VCateg::DY ) {
-                        return RObjVecDbl( new CObjVecDbl( sj->dy ) );
-                    }
-                    throw S("BUG: unexpected case");
-                }
-            }
-            throw S("BUG: invalid context::dim");
+RObj CNodePointY::spec_val_point( RSpec s, int i, bool want_error ) const
+{
+    return want_error && s->has_dy() ?
+        RObjEnu( new CObjEnu( s->y[i], s->dy[i] ) ) :
+        RObjDbl( new CObjDbl( s->y[i] ) );
+}
 
-        } else if ( var->categ == VCateg::NI ) {
-            int j = PCAST<const CRef2>(ref)->get_j( ctx, f->nJ() );
-            PSpec sj = fd->VS(j);
-            return PObjInt( new CObjInt( sj->size() ) );
+RObj CNodePointY::spec_val_vector( RSpec s, int n, bool want_error ) const
+{
+    return want_error && s->has_dy() ?
+        RObjVecEnu( new CObjVecEnu( vector<double>(s->y.begin(), s->y.begin()+n ),
+                                    vector<double>(s->dy.begin(), s->dy.begin()+n ) ) ) :
+        RObjVecDbl( new CObjVecDbl( vector<double>(s->y.begin(), s->y.begin()+n ) ) );
+}
 
-        } else
-            throw "invalid reference "+var->var_info()+" to data file";
 
-    } else { // Ref2erences for curve file.
-        /*
-        POlc fc = P2C( f );
-        if ( fc ) {
-            if ( PCAST<const CRef3>(ref)->ti )
-                throw S("unexpected i dependence of curve property");
-            int j = PCAST<const CRef2>(ref)->get_j( ctx, f->nJ() );
-            return fc->VC(j)->get_var( var );
-        }
-        */
-    }
-    return NULL;
+RObj CNodePointDY::spec_val_point( RSpec s, int i, bool want_error ) const
+{
+    return RObjDbl( new CObjDbl( s->dy[i] ) );
 }
 
-//! Description of reference (for use in ??)
+RObj CNodePointDY::spec_val_vector( RSpec s, int n, bool want_error ) const
+{
+    if ( !s->has_dy() )
+        throw S("requested dy does not exist");
+    return RObjVecDbl( new CObjVecDbl( vector<double>(s->dy.begin(), s->dy.begin()+n ) ) );
+}
 
+/*
 void CNodeIva::set_coord( CCoord& ret, int k_in ) const
 {
     int k;
@@ -1089,7 +997,7 @@ string CNodeIva::tree_info() const
 {
     return "ref[" + var->var_info() + "]";
 }
-
+*/
 
 //**************************************************************************************************
 //* CNodeIdf: identifier node
diff --git a/pub/lib/node.hpp b/pub/lib/node.hpp
index 44969780..60a8a45b 100644
--- a/pub/lib/node.hpp
+++ b/pub/lib/node.hpp
@@ -18,13 +18,13 @@ class CNodeWithArgs: public CNode {
  protected:
     int narg;
     vector<RNode> arg;
- private:
-    void npar_exec( int *np ) const;
  public:
     CNodeWithArgs( int _narg ) : narg(_narg) { arg.resize(narg); };
+    void npar_exec( int *ret ) const;
+    void kdep_exec( bool *ret ) const;
+    void idep_exec( bool *ret ) const;
     bool has_dummy() const;
     bool has_conv() const;
-    void kdep_exec( bool *kd ) const;
     virtual string tree_info() const =0;
 };
 
@@ -110,9 +110,9 @@ class CNodeGeni: public CNodeWithArgs {
     CNodeGeni( const class CGeni *_geni, RRef _ref );
     CNodeGeni( const class CGeni *_geni, RNode a0 );
     CNodeGeni( const class CGeni *_geni, RNode a0, RNode a1 );
+    void kdep_exec( bool *kd ) const { *kd = true; }
     RObj tree_val( const CContext& ctx ) const;
     void set_coord( CCoord& ret, int k ) const;
-    void kdep_exec( bool *kd ) const { *kd = true; }
     string tree_info() const;
 };
 
@@ -125,9 +125,9 @@ class CNodeCvin: public CNodeWithArgs {
     RRef ref;
  public:
     CNodeCvin( const class CCvin *_cvin, RRef _ref, RNode a0, RNode a1 );
+    void kdep_exec( bool *kd ) const { *kd = true; }
     RObj tree_val( const CContext& ctx ) const;
     void set_coord( CCoord& ret, int k ) const;
-    void kdep_exec( bool *kd ) const { *kd = true; }
     string tree_info() const;
 };
 
@@ -163,6 +163,7 @@ class CNodeIdxI: public CNodeIdx {
     RObj tree_val( const CContext& ctx ) const;
     void set_coord( CCoord& ret, int k ) const { ret = CCoord("i", ""); }
     string tree_info() const { return "i {index}"; }
+    void idep_exec( bool *ret ) const { *ret = true; }
 };
 
 
@@ -190,8 +191,8 @@ class CNodeIdxK: public CNodeIdx {
 
 class CNodeSessionNK: public CNode {
  public:
-    RObj tree_val( const CContext& ctx ) const;
     void kdep_exec( bool *kd ) const { *kd = false; }
+    RObj tree_val( const CContext& ctx ) const;
     void set_coord( CCoord& ret, int k ) const { ret = CCoord("nk", ""); }
     string tree_info() const { return "nk {number of online files}"; }
 };
@@ -200,16 +201,18 @@ class CNodeSessionNK: public CNode {
 //! File-wide information.
 
 class CNodeFile: public CNode {
+ private:
+    virtual RObj tree_val_scalar( const CContext& ctx ) const {
+        throw S("BUG: unforeseen call to CNodeFile::tree_val_scalar"); }
  protected:
     RRef ref;
  public:
     CNodeFile( RRef _ref ) : ref(_ref) {}
-    RObj tree_val( const CContext& ctx ) const;
     void kdep_exec( bool *kd ) const { *kd = true; }
+    RObj tree_val( const CContext& ctx ) const;
     string tree_info() const { return name() + "[" + ref->ref_info() + "]"; }
     void set_coord( CCoord& ret, int k ) const { ret = CCoord(name(), ""); }
     virtual string name() const = 0;
-    virtual RObj tree_val_scalar( const CContext& ctx ) const = 0;
 };
 
 
@@ -318,19 +321,51 @@ class CNodeCurveR2: public CNodeCurve {
 };
 
 
-//! Indexed variable node.
+//! Pointwise information.
 
-class CNodeIva: public CNode {
+class CNodePoint: public CNodeSlice {
  private:
-    RVar var;
-    RRef ref;
-    void npar_exec( int *np ) const;
+    RObj tree_val_point( const CContext& ctx, int i ) const;
+    RObj tree_val_vector( const CContext& ctx ) const;
+ protected:
+    virtual RObj spec_val_point( RSpec s, int i, bool want_error ) const = 0;
+    virtual RObj spec_val_vector( RSpec s, int n, bool want_error ) const = 0;
  public:
-    CNodeIva( RVar _var, RRef _ref=RRef( new CRef3() ) ) : var(_var), ref(_ref) {}
+    CNodePoint( RRef _ref ) : CNodeSlice( _ref ) {}
     RObj tree_val( const CContext& ctx ) const;
-    void kdep_exec( bool *kd ) const { *kd = true; }
-    void set_coord( CCoord& ret, int k ) const;
-    string tree_info() const;
+};
+
+
+//! Pointwise information: X.
+
+class CNodePointX: public CNodePoint {
+ public:
+    CNodePointX( RRef _ref ) : CNodePoint( _ref ) {}
+    string name() const { return "x"; }
+    RObj spec_val_point( RSpec s, int i, bool want_error ) const;
+    RObj spec_val_vector( RSpec s, int n, bool want_error ) const;
+};
+
+
+//! Pointwise information: Y.
+
+class CNodePointY: public CNodePoint {
+ public:
+    CNodePointY( RRef _ref ) : CNodePoint( _ref ) {}
+    string name() const { return "y"; }
+    RObj spec_val_point( RSpec s, int i, bool want_error ) const;
+    RObj spec_val_vector( RSpec s, int n, bool want_error ) const;
+};
+
+
+//! Pointwise information: DY.
+
+class CNodePointDY: public CNodePoint {
+ public:
+    CNodePointDY( RRef _ref ) : CNodePoint( _ref ) {}
+    string name() const { return "dy"; }
+    RObj spec_val_point( RSpec s, int i, bool want_error ) const;
+    RObj spec_val_vector( RSpec s, int n, bool want_error ) const;
 };
 
 
@@ -369,9 +404,9 @@ class CNodeCev: public CNode {
  public:
     CNodeCev( RRef _ref, RNode _arg ) : ref( _ref ), arg( _arg ) {}
     RObj tree_val( const CContext& ctx ) const;
+    void kdep_exec( bool *kd ) const { *kd = true; }
     bool has_dummy() const { return arg->has_dummy(); }
     bool has_conv() const { return arg->has_conv(); }
-    void kdep_exec( bool *kd ) const { *kd = true; }
     void set_coord( CCoord& ret, int k ) const;
     string tree_info() const { return "c[" + ref->ref_info() + "]"; }
 };
@@ -396,12 +431,12 @@ class CNodeMixin: public CNode {
 class CNodeConvBase: public CNodeMixin {
  protected:
     RNode theory;
-    void npar_exec( int *np ) const;
  public:
     CNodeConvBase( const RNode& _theory, const RNode& _shift )
         : CNodeMixin( _shift ), theory(_theory) {}
-    bool has_dummy() const { return theory->has_dummy(); }
+    void npar_exec( int *np ) const;
     void kdep_exec( bool *kd ) const;
+    bool has_dummy() const { return theory->has_dummy(); }
     void set_coord( CCoord& ret, int k ) const { theory->set_coord( ret, k ); }
 };
 
@@ -437,17 +472,16 @@ class CNodePConv: public CNodeConvBase {
 //! Dirac's delta function node, to request a copy of the resolution function.
 
 class CNodeDirac: public CNodeMixin {
- private:
-    void npar_exec( int *np ) const;
  public:
     CNodeDirac( const RNode& _shift=RNode( new CNodeVal( 0.0 ) ) )
         : CNodeMixin( _shift ) {};
     RObj copy_theory( const CContext& ctx, double theshift ) const;
     RObjVecDbl convolve( const CContext& ctx, double theshift, const PSpec& sv,
                          double conv_norm, double conv_step ) const;
+    void npar_exec( int *np ) const;
+    void kdep_exec( bool *kd ) const;
     bool has_dummy() const { return true; } // has implicit t dependence
     bool has_conv() const { return true; }
-    void kdep_exec( bool *kd ) const;
     void set_coord( CCoord& ret, int k ) const;
     string tree_info() const { return "resol(" + shift->tree_info() + ")"; }
 };
diff --git a/pub/lib/slice.hpp b/pub/lib/slice.hpp
index d426a4d9..48cae719 100644
--- a/pub/lib/slice.hpp
+++ b/pub/lib/slice.hpp
@@ -24,24 +24,6 @@ class CSlice {
 };
 
 
-//! A CSlice within a curve file, holds parameters and fit outcome.
-
-class CCurve: public CSlice {
- public:
-    vector<double> P;
-    vector<char>   ParAttr;
-    int    fitOutcome;
-    double fitChi2;
-    double fitR2;
-
-    CCurve() : CSlice() { clear_fit_outcome(); };
-    void clear_fit_outcome();
-    void assert_attr() const;
-    bool has_global_par() const;
-    string info_line() const;
-};
-
-
 //! A CSlice within a data file, holds a x-y-dy data set.
 
 class CSpec: public CSlice {
@@ -67,6 +49,24 @@ class CSpec: public CSlice {
 };
 
 
+//! A CSlice within a curve file, holds parameters and fit outcome.
+
+class CCurve: public CSlice {
+ public:
+    vector<double> P;
+    vector<char>   ParAttr;
+    int    fitOutcome;
+    double fitChi2;
+    double fitR2;
+
+    CCurve() : CSlice() { clear_fit_outcome(); };
+    void clear_fit_outcome();
+    void assert_attr() const;
+    bool has_global_par() const;
+    string info_line() const;
+};
+
+
 //! at global scope, for use in sorting.
 
 bool CompareZ( const RSlice& E1, const RSlice& E2 );
diff --git a/pub/lib/toplevel.cpp b/pub/lib/toplevel.cpp
index c561e601..068ff8a3 100644
--- a/pub/lib/toplevel.cpp
+++ b/pub/lib/toplevel.cpp
@@ -158,6 +158,10 @@ void CFrida::interactive()
         } catch( const char* ex ) {
             cerr << "BUG: '" << cmdline << "' failed with unforeseen message: " << ex << "\n";
             NMacro::clear();
+        } catch( std::exception& ex ) {
+            cerr << "BUG: '" << cmdline << "' failed with unforeseen std exception: " <<
+                ex.what() << "\n";
+            NMacro::clear();
         } catch( ... ) {
             cerr << "BUG: '" << cmdline << "' failed with unforeseen exception\n";
             NMacro::clear();
diff --git a/pub/lib/xax_lex.lpp b/pub/lib/xax_lex.lpp
index 49000f2b..278506fe 100644
--- a/pub/lib/xax_lex.lpp
+++ b/pub/lib/xax_lex.lpp
@@ -41,7 +41,6 @@ struct xaxtype {
     int     i;
     RNode   t;
     RObj    o;
-    RVar    v;
     RRef    r;
 };
 #define YYSTYPE xaxtype
@@ -77,8 +76,9 @@ EXP      [eE]"-"?[0-9]+
 	xaxlval->t = RNode( new CNodeVal( PObjStr( new CObjStr( s ) ) ) );
 	return VAL; }
 
-{DIG}+	{ xaxlval->i = atoi(xaxtext);
-	return INT; }
+{DIG}+	{ 
+	xaxlval->t = RNode( new CNodeVal( atoi(xaxtext) ) );
+	return VAL; }
 
 ({DIG}+"."{DIG}*{EXP}?)|("."?{DIG}*{EXP}?) {
 	xaxlval->t = RNode( new CNodeVal( atof(xaxtext) ) );
@@ -113,9 +113,9 @@ oc      { return REF_OC; }
 chi2    { return REF_CHI2; }
 R2      { return REF_R2; }
 
-[xy]|dy {
-        xaxlval->v = PVar( new CVar(xaxtext) );
-        return REF; }
+x       { return REF_X; }
+y       { return REF_Y; }
+dy      { return REF_DY; }
 
 t {     return DUMMY; }
 
diff --git a/pub/lib/xax_yacc.ypp b/pub/lib/xax_yacc.ypp
index 912e1028..0d56b4d1 100644
--- a/pub/lib/xax_yacc.ypp
+++ b/pub/lib/xax_yacc.ypp
@@ -35,7 +35,6 @@ struct xaxtype {
     int     i;
     RNode   t;
     RObj    o;
-    RVar    v;
     RRef    r;
 };
 #define YYSTYPE xaxtype
@@ -75,7 +74,7 @@ int xaxlex(YYSTYPE *xaxlval); // created by lex.l
 %left BOP_PM  /* error */
 
 /* other tokens created by xax_lex.lpp: */
-%token INT VAL REF_NJ REF_R REF_Z REF_NI REF_P REF_OC REF_CHI2 REF_R2 REF DUMMY CEV FNCT GENI CVIN END CONV PCONV DIRAC IDF
+%token VAL REF_NJ REF_R REF_Z REF_NI REF_P REF_OC REF_CHI2 REF_R2 REF_X REF_Y REF_DY DUMMY CEV FNCT GENI CVIN END CONV PCONV DIRAC IDF
 
 /* Grammar follows */
 
@@ -104,8 +103,7 @@ range:
       | exp BOP_BLW exp ':' exp { $$.t = RNode( new CNodeRange( false, $1.t, $3.t, $5.t ) ); }
 
 exp:                       /* scalar expression */
-        INT                 { $$.t = RNode( new CNodeVal( $1.i ) ); }
-      | VAL                 { $$.t = $1.t; }
+        VAL                 { $$.t = $1.t; }
       | REF_NJ bra1         { $$.t = RNode( new CNodeFileNJ( $2.r ) ); }
       | REF_R bra1          { $$.t = RNode( new CNodeFileR( $1.i, $2.r ) ); }
       | REF_Z bra2          { $$.t = RNode( new CNodeSliceZ( $1.i, $2.r ) ); }
@@ -114,7 +112,9 @@ exp:                       /* scalar expression */
       | REF_OC bra2         { $$.t = RNode( new CNodeCurveOutcome( $2.r ) ); }
       | REF_CHI2 bra2       { $$.t = RNode( new CNodeCurveChi2( $2.r ) ); }
       | REF_R2 bra2         { $$.t = RNode( new CNodeCurveR2( $2.r ) ); }
-      | REF bra3            { $$.t = RNode( new CNodeIva( $1.v, $2.r ) ); }
+      | REF_X bra3          { $$.t = RNode( new CNodePointX( $2.r ) ); }
+      | REF_Y bra3          { $$.t = RNode( new CNodePointY( $2.r ) ); }
+      | REF_DY bra3         { $$.t = RNode( new CNodePointDY( $2.r ) ); }
       | IDF                 { $$.t = RNode( new CNodeIdf( (PCAST<const CObjStr>($1.o))->to_s() ) ); }
       | DUMMY               { $$.t = RNode( new CNodeDummy() ); }
       | CEV bra2 '(' exp ')' { $$.t = RNode( new CNodeCev( $2.r, $4.t ) ); }
-- 
GitLab