summaryrefslogtreecommitdiff
path: root/src/piraha/Call.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/piraha/Call.cc')
-rw-r--r--src/piraha/Call.cc838
1 files changed, 689 insertions, 149 deletions
diff --git a/src/piraha/Call.cc b/src/piraha/Call.cc
index 9df8fd10..ef981fd6 100644
--- a/src/piraha/Call.cc
+++ b/src/piraha/Call.cc
@@ -1,11 +1,14 @@
#include <iostream>
+#include <iomanip>
#include <string.h>
#include "Piraha.hpp"
#include <stdlib.h>
#include <sstream>
+#include "cctk_core.h"
#include "cctk_Parameter.h"
#include <map>
#include <math.h>
+#include <algorithm>
namespace piraha {
@@ -13,168 +16,665 @@ namespace piraha {
extern "C" int CCTK_ParameterFilename(int len, char *filename);
-std::map<std::string,std::map<std::string,std::string> > values;
-typedef std::map<std::string,std::map<std::string,std::string> >::iterator th_iter;
-typedef std::map<std::string,std::string>::iterator nm_iter;
+/**
+ * This holds the structure required for parsing
+ * a Cactus par file.
+ */
+static smart_ptr<Grammar> par_file_grammar = new Grammar();
+
+static std::string mklower(std::string& in) {
+ std::string s = in;
+ std::transform(s.begin(), s.end(), s.begin(), ::tolower);
+ return s;
+}
+
+enum ValueType { PIR_STRING,PIR_INT,PIR_REAL,PIR_BOOL,PIR_VOID };
+
+std::string get_parfile() {
+ char path[500];
+ CCTK_ParameterFilename(500, path);
+ char *value = strrchr (path, '/');
+ if (value == NULL) {
+ value = path;
+ } else {
+ value++;
+ }
+ int n = strlen(value);
+ if(n > 4 && strcmp(value+n-4,".par")==0) {
+ value[n-4] = '\0';
+ }
+ std::string s = value;
+ return s;
+}
+
+std::ostream& operator<<(std::ostream& o,const ValueType& vt) {
+ if(vt == PIR_STRING)
+ o << "STRING";
+ else if(vt == PIR_INT)
+ o << "INT";
+ else if(vt == PIR_REAL)
+ o << "REAL";
+ else if(vt == PIR_BOOL)
+ o << "BOOL";
+ else if(vt == PIR_VOID)
+ o << "VOID";
+ else
+ o << "UNDEF";
+ return o;
+}
+
+std::string current_thorn;
+
+/**
+ * The Value class is something like a union. It holds
+ * integer, real, and string data and has a type field
+ * that identifies which field is currently valid.
+ */
+struct Value {
+ /** This field holds the parse tree element associated with this Value. */
+ smart_ptr<Group> hold;
+ double ddata;
+ int idata;
+ std::string sdata;
+ ValueType type;
+ Value(smart_ptr<Group> g) : hold(g), ddata(0), idata(0), sdata(), type(PIR_VOID) {}
+ ~Value() {}
+ /**
+ * Create a string representation of the Value.
+ */
+ std::string copy() {
+ assert(type != PIR_VOID);
+ if(type == PIR_STRING) {
+ return sdata;
+ } else if(type == PIR_BOOL) {
+ std::string s = idata ? "yes" : "no";
+ return s;
+ } else {
+ std::ostringstream o;
+ if(type == PIR_REAL) {
+ o << std::setprecision(15) << ddata;
+ } else {
+ o << idata;
+ }
+ return o.str();
+ }
+ }
+ /**
+ * Check to see if something is a bool and throw an error
+ * if it's not.
+ */
+ void checkBool() {
+ if(type != PIR_BOOL) {
+ std::ostringstream msg;
+ msg << "Does not evaluate to a boolean: " << hold->substring();
+ std::string par = get_parfile();
+ CCTK_Error(hold->line(),par.c_str(),current_thorn.c_str(),msg.str().c_str());
+ }
+ }
+ /**
+ * Compares with another Value, and throws a CCTK_Error
+ * if the comparison doesn't make sense.
+ */
+ bool equals(smart_ptr<Value> v) {
+ if(type == PIR_BOOL && v->type == PIR_BOOL) {
+ return idata == v->idata;
+ } else if(type == PIR_INT && v->type == PIR_INT) {
+ return idata == v->idata;
+ } else if(type == PIR_INT && v->type == PIR_REAL) {
+ return idata == v->ddata;
+ } else if(type == PIR_REAL && v->type == PIR_INT) {
+ return ddata == v->idata;
+ } else if(type == PIR_REAL && v->type == PIR_REAL) {
+ return ddata == v->ddata;
+ } else if(type == PIR_STRING && v->type == PIR_STRING) {
+ return sdata == v->sdata;
+ }
+ std::ostringstream msg;
+ msg << "Cannot compare " << type << " and " << v->type << std::endl;
+ std::string par = get_parfile();
+ CCTK_Error(hold->line(),par.c_str(),current_thorn.c_str(),msg.str().c_str());
+ }
+ /**
+ * Return a double value, whether the underlying
+ * quantity is integer or real.
+ */
+ double doubleValue() {
+ if(type == PIR_REAL)
+ return ddata;
+ else if(type == PIR_INT)
+ return idata;
+ std::ostringstream msg;
+ msg << "Cannot convert " << type << " to double." << std::endl;
+ std::string par = get_parfile();
+ CCTK_Error(hold->line(),par.c_str(),current_thorn.c_str(),msg.str().c_str());
+ return 0;
+ }
+ bool intOrDouble() {
+ return type == PIR_INT || type == PIR_REAL;
+ }
+ /**
+ * This function converts a double to a real, but
+ * only if this can be done without loss of precision.
+ */
+ void integerize() {
+ if(type == PIR_REAL) {
+ idata = ddata;
+ if(idata == ddata) {
+ type = PIR_INT;
+ }
+ }
+ }
+ void booleanize(smart_ptr<Group> gr) {
+ if(type == PIR_STRING) {
+ std::string s = mklower(sdata);
+ if(s == "yes" || s == "true") {
+ idata = 1;
+ type = PIR_BOOL;
+ } else if(s == "no" || s == "false") {
+ idata = 0;
+ type = PIR_BOOL;
+ }
+ } else if(type == PIR_INT) {
+ /// Steven R. Brandt would like to remove this
+ /// particular auto-conversion
+ if(idata == 1 || idata == 0) {
+ type = PIR_BOOL;
+ std::ostringstream msg;
+ msg << "Boolean variable is set with integer: " << gr->substring() << std::endl;
+ std::string par = get_parfile();
+ CCTK_Warn(1,gr->line(),par.c_str(),current_thorn.c_str(),msg.str().c_str());
+ }
+ }
+ }
+};
+
+std::ostream& operator<<(std::ostream& o,const smart_ptr<Value>& val) {
+ if(!val.valid()) {
+ return o << "NULL";
+ }
+ o << "(" << val->type << ")";
+ if(val->type == PIR_REAL) {
+ o << val->ddata;
+ } else if(val->type == PIR_INT) {
+ o << val->idata;
+ } else if(val->type == PIR_BOOL) {
+ o << (val->idata ? "true" : "false");
+ } else if(val->type == PIR_STRING) {
+ o << "\"" << val->sdata << "\"";
+ } else {
+ o << val->hold->substring();
+ }
+ return o;
+}
+
+std::map<std::string,std::map<std::string,smart_ptr<Value> > > values;
+typedef std::map<std::string,std::map<std::string,smart_ptr<Value> > >::iterator th_iter;
+typedef std::map<std::string,smart_ptr<Value> >::iterator nm_iter;
+
+smart_ptr<Value> eval_expr(std::string inp);
// If the value was already defined in this parameter file, look
// it up in the map. Otherwise, get it from Cactus.
-bool find_val(std::string thorn,std::string name,std::string& ret) {
+smart_ptr<Value> find_val(std::string thorn,std::string name) {
+ smart_ptr<Value> ret;
th_iter th = values.find(thorn);
if(th != values.end()) {
nm_iter nm = th->second.find(name);
if(nm != th->second.end()) {
ret = nm->second;
- return true;
+ return ret;
}
}
const cParamData *data = CCTK_ParameterData(name.c_str(),thorn.c_str());
- if(data == NULL)
- return false;
- ret = data->defval;
- return true;
+ if(data != NULL) {
+ std::string expr = data->defval;
+ ret = eval_expr(expr);
+ }
+ return ret;
}
-bool lookup_var(smart_ptr<Group> gr,std::string& res) {
+smart_ptr<Value> lookup_var(smart_ptr<Group> gr) {
+ smart_ptr<Value> ret;
if(gr->group(0)->getPatternName() == "env") {
const char *env = getenv(gr->group(0)->group(0)->substring().c_str());
if(env != NULL) {
- res = env;
- return true;
+ ret = new Value(gr);
+ ret->type = PIR_STRING;
+ ret->sdata = env;
}
} else if(gr->group(0)->substring() == "parfile") {
- char path[500];
- CCTK_ParameterFilename(500, path);
- char *value = strrchr (path, '/');
- if (value == NULL) {
- value = path;
- } else {
- value++;
- }
- /* skip the parameter file extension */
- if (strcmp (value + strlen (value) - 4, ".par") == 0)
- {
- value[strlen (value) - 4] = '\0';
- }
- res = value;
- return true;
+ ret = new Value(gr);
+ ret->type = PIR_STRING;
+ ret->sdata = get_parfile();
} else if(gr->group(0)->substring() == "pi") {
- std::ostringstream ostr;
- ostr << (4.0*atan2(1.,1.)) << std::flush;
- res = ostr.str();
- return true;
+ ret = new Value(gr);
+ ret->type = PIR_REAL;
+ ret->ddata = 4.0*atan2(1.0,1.0);
+ }
+ if(!ret.valid()) {
+ std::ostringstream msg;
+ msg << "Unknown variable: " << gr->substring() << std::endl;
+ std::string par = get_parfile();
+ CCTK_Error(gr->line(),par.c_str(),current_thorn.c_str(),msg.str().c_str());
}
- return false;
+ return ret;
}
-// Converts a value to a string
-void meval(smart_ptr<Group> gr,std::string& val) {
- val.clear();
- if(gr->getPatternName() == "value" || gr->getPatternName() == "paren") {
- meval(gr->group(0),val);
- } else if(gr->getPatternName() == "quot") {
- smart_ptr<Group> inquot = gr->group(0);
- val = inquot->substring();
- int last = 0;
- std::string nw;
- for(int i=0;i < inquot->groupCount();i++) {
- smart_ptr<Group> vr = inquot->group(i);
- std::string sub;
- if(lookup_var(vr,sub)) {
- int start = vr->start() - inquot->start();
- nw += val.substr(last,start-last);
- nw += sub;
- last = vr->end() - inquot->start();
+/**
+ * The meval() function takes any node within
+ * the parse tree and creates a Value object
+ * from it. It is, therefore, designed to be
+ * used recursively.
+ **/
+smart_ptr<Value> meval(smart_ptr<Group> gr) {
+ assert(gr.valid());
+ std::string pn = gr->getPatternName();
+ smart_ptr<Value> ret = new Value(gr);
+ if(pn == "num") {
+ std::string s = gr->substring();
+ ret->ddata = atof(s.c_str());
+ ret->idata = ret->ddata;
+ if(ret->idata == ret->ddata && (s.find('.') == std::string::npos))
+ ret->type = PIR_INT;
+ else
+ ret->type = PIR_REAL;
+ } else if(pn == "paren" || pn == "parindex") {
+ return meval(gr->group(0));
+ } else if(pn == "func") {
+ std::string fn = gr->group(0)->substring();
+ fn = mklower(fn);
+ smart_ptr<Value> val = meval(gr->group(1));
+ if(val->type == PIR_REAL || val->type == PIR_INT) {
+ if(fn == "trunc") {
+ val->ddata = trunc(val->doubleValue());
+ val->type = PIR_REAL;
+ return val;
+ } else if(fn == "floor") {
+ val->ddata = floor(val->doubleValue());
+ val->type = PIR_REAL;
+ return val;
+ } else if(fn == "ceil") {
+ val->ddata = ceil(val->doubleValue());
+ val->type = PIR_REAL;
+ return val;
+ } else if(fn == "sqrt") {
+ val->ddata = sqrt(val->doubleValue());
+ val->type = PIR_REAL;
+ return val;
+ } else if(fn == "atan") {
+ val->ddata = atan(val->doubleValue());
+ val->type = PIR_REAL;
+ return val;
+ } else if(fn == "sin") {
+ val->ddata = sin(val->doubleValue());
+ val->type = PIR_REAL;
+ return val;
+ } else if(fn == "cos") {
+ val->ddata = cos(val->doubleValue());
+ val->type = PIR_REAL;
+ return val;
+ } else if(fn == "tan") {
+ val->ddata = tan(val->doubleValue());
+ val->type = PIR_REAL;
+ return val;
+ } else if(fn == "exp") {
+ val->ddata = exp(val->doubleValue());
+ val->type = PIR_REAL;
+ return val;
+ } else if(fn == "log") {
+ val->ddata = log(val->doubleValue());
+ val->type = PIR_REAL;
+ return val;
+ } else if(fn == "abs") {
+ val->ddata = fabs(val->doubleValue());
+ val->type = PIR_REAL;
+ return val;
+ } else if(fn == "acos") {
+ val->ddata = acos(val->doubleValue());
+ val->type = PIR_REAL;
+ return val;
+ } else if(fn == "asin") {
+ val->ddata = asin(val->doubleValue());
+ val->type = PIR_REAL;
+ return val;
+ } else if(fn == "bool") {
+ if(val->type == PIR_REAL) {
+ val->idata = val->ddata;
+ }
+ val->type = PIR_BOOL;
+ return val;
+ } else if(fn == "int") {
+ if(val->type == PIR_REAL) {
+ val->idata = val->ddata;
+ val->type = PIR_INT;
+ }
+ return val;
+ } else if(fn == "real") {
+ if(val->type == PIR_INT) {
+ val->ddata = val->idata;
+ val->type = PIR_REAL;
+ }
+ return val;
}
+ } else if(val->type == PIR_BOOL) {
+ if(fn == "int") {
+ val->type = PIR_INT;
+ return val;
+ } else if(fn == "real") {
+ val->type = PIR_REAL;
+ val->ddata = val->idata;
+ return val;
+ }
+ }
+ std::ostringstream msg;
+ msg << "Unknown func: " << fn << "(" << val->type << ")" << std::endl;
+ std::string par = get_parfile();
+ CCTK_Error(gr->line(),par.c_str(),current_thorn.c_str(),msg.str().c_str());
+ } else if(pn == "name") {
+ std::string s = gr->substring();
+ s = mklower(s);
+ if(s == "no" || s == "false") {
+ ret->type = PIR_BOOL;
+ ret->idata = 0;
+ } else if(s == "yes" || s == "true") {
+ ret->type = PIR_BOOL;
+ ret->idata = 1;
+ } else {
+ ret->type = PIR_STRING;
+ ret->sdata = gr->substring();
}
- if(last < val.size())
- nw += val.substr(last,val.size()-last);
- val = nw;
- } else if(gr->getPatternName() == "par") {
+ return ret;
+ } else if(pn == "par") {
std::string thorn = gr->group(0)->substring();
std::string name = gr->group(1)->substring();
-
- bool found = find_val(thorn,name,val);
- if(found) {
- ;
+ if(gr->groupCount() == 3) {
+ std::ostringstream vn;
+ smart_ptr<Value> index = meval(gr->group(2));
+ if(index->type == PIR_INT) {
+ std::stringstream o;
+ o << name << "[" << index->idata << "]";
+ o << std::flush;
+ std::string keyi = o.str();
+ ret = find_val(thorn,keyi);
+ return ret;
+ }
} else {
- val += thorn;
- val += "::";
- val += name;
- }
- } else if(gr->getPatternName() == "name") {
- val += gr->substring();
- } else if(gr->getPatternName() == "num") {
- val += gr->substring();
- } else if(gr->getPatternName() == "var") {
- lookup_var(gr,val);
- } else if(gr->getPatternName() == "mexpr") {
- if(gr->groupCount()==1) {
- meval(gr->group(0),val);
- return;
+ ret = find_val(thorn,name);
+ return ret;
}
- std::string val2;
- meval(gr->group(0),val2);
- double v2 = atof(val2.c_str());
- for(int i=1;i < gr->groupCount();i += 2) {
- std::string val3;
- meval(gr->group(i+1),val3);
- double v3 = atof(val3.c_str());
- if(gr->group(i)->substring() == "*") {
- v2 *= v3;
+ std::ostringstream msg;
+ msg << "Unknown par: " << thorn << "::" << name << std::endl;
+ std::string par = get_parfile();
+ CCTK_Error(gr->line(),par.c_str(),current_thorn.c_str(),msg.str().c_str());
+ } else if(pn == "var") {
+ ret = lookup_var(gr);
+ } else if(pn == "value") {
+ if(gr->groupCount()==2) {
+ std::string unop = gr->group(0)->substring();
+ ret = meval(gr->group(1));
+ if(unop == "-") {
+ if(ret->type == PIR_INT) {
+ ret->idata = -ret->idata;
+ } else if(ret->type == PIR_REAL) {
+ ret->ddata = -ret->ddata;
+ } else {
+ std::ostringstream msg;
+ msg << "Unknown operation: " << unop << ret->type << std::endl;
+ std::string par = get_parfile();
+ CCTK_Error(gr->line(),par.c_str(),current_thorn.c_str(),msg.str().c_str());
+ }
+ } else if(unop == "!") {
+ if(ret->type == PIR_BOOL) {
+ ret->idata = !ret->idata;
+ } else {
+ std::ostringstream msg;
+ msg << "Unknown operation: " << unop << ret->type << std::endl;
+ std::string par = get_parfile();
+ CCTK_Error(gr->line(),par.c_str(),current_thorn.c_str(),msg.str().c_str());
+ }
} else {
- v2 /= v3;
+ std::ostringstream msg;
+ msg << "Unknown operation: " << unop << ret->type << std::endl;
+ std::string par = get_parfile();
+ CCTK_Error(gr->line(),par.c_str(),current_thorn.c_str(),msg.str().c_str());
}
-// std::cout << "MEXPR: " << v2 << gr->group(i)->substring() << v3 << std::endl;
+ } else {
+ return meval(gr->group(0));
}
- std::ostringstream ostr;
- ostr << v2 << std::flush;
- val = ostr.str();
- } else if(gr->getPatternName() == "aexpr") {
- if(gr->groupCount()==1) {
- meval(gr->group(0),val);
- return;
+ } else if(pn == "quot") {
+ ret->type = PIR_STRING;
+ ret->sdata = gr->group(0)->substring();
+ } else if(pn == "inquot") {
+ ret->type = PIR_STRING;
+ ret->sdata = gr->substring();
+ } else if(pn == "expr") {
+ if(gr->groupCount()==1)
+ return meval(gr->group(0));
+ smart_ptr<Value> v1 = meval(gr->group(0));
+ smart_ptr<Value> v2 = meval(gr->group(1));
+ v1->checkBool();
+ v2->checkBool();
+ ret->type = PIR_BOOL;
+ ret->idata = v1->idata || v2->idata;
+ } else if(pn == "powexpr") {
+ if(gr->groupCount()==1)
+ return meval(gr->group(0));
+ smart_ptr<Value> v1 = meval(gr->group(0));
+ smart_ptr<Value> v2 = meval(gr->group(1));
+ ret->type = PIR_REAL;
+ ret->ddata = pow(v1->doubleValue(),v2->doubleValue());
+ } else if(pn == "andexpr") {
+ if(gr->groupCount()==1)
+ return meval(gr->group(0));
+ smart_ptr<Value> v1 = meval(gr->group(0));
+ smart_ptr<Value> v2 = meval(gr->group(1));
+ v1->checkBool();
+ v2->checkBool();
+ ret->type = PIR_BOOL;
+ ret->idata = v1->idata && v2->idata;
+ } else if(pn == "eqexpr") {
+ if(gr->groupCount()==1)
+ return meval(gr->group(0));
+ smart_ptr<Value> v1 = meval(gr->group(0));
+ std::string eqop = gr->group(1)->substring();
+ smart_ptr<Value> v2 = meval(gr->group(2));
+ ret->type = PIR_BOOL;
+ if(eqop == "==") {
+ ret->idata = v1->equals(v2);
+ } else if(eqop == "!=") {
+ ret->idata = !v1->equals(v2);
+ } else {
+ std::ostringstream msg;
+ msg << "Unknown equality operator: " << eqop << std::endl;
+ std::string par = get_parfile();
+ CCTK_Error(gr->line(),par.c_str(),current_thorn.c_str(),msg.str().c_str());
}
- std::string val2;
- meval(gr->group(0),val2);
- double v2 = atof(val2.c_str());
- for(int i=1;i < gr->groupCount();i += 2) {
- std::string val3;
- meval(gr->group(i+1),val3);
- double v3 = atof(val3.c_str());
- if(gr->group(i)->substring() == "+") {
- v2 += v3;
+ } else if(pn == "compexpr") {
+ if(gr->groupCount()==1)
+ return meval(gr->group(0));
+ smart_ptr<Value> v1 = meval(gr->group(0));
+ if(gr->groupCount()>0) {
+ std::string compop = gr->group(1)->substring();
+ smart_ptr<Value> v2 = meval(gr->group(2));
+ double d1 = v1->doubleValue();
+ double d2 = v2->doubleValue();
+ ret->type = PIR_BOOL;
+ if(compop == "<") {
+ ret->idata = (d1 < d2);
+ return ret;
+ } else if(compop == ">") {
+ ret->idata = (d1 > d2);
+ return ret;
+ } else if(compop == "<=") {
+ ret->idata = (d1 <= d2);
+ return ret;
+ } else if(compop == ">=") {
+ ret->idata = (d1 >= d2);
+ return ret;
+ }
+ std::ostringstream msg;
+ msg << "Unknown comparison operator: " << compop << std::endl;
+ std::string par = get_parfile();
+ CCTK_Error(gr->line(),par.c_str(),current_thorn.c_str(),msg.str().c_str());
+ }
+ } else if(pn == "aexpr") {
+ if(gr->groupCount()==1)
+ return meval(gr->group(0));
+ smart_ptr<Value> v1 = meval(gr->group(0));
+ for(int i=1;i+1<gr->groupCount();i+=2) {
+ std::string addop = gr->group(i)->substring();
+ smart_ptr<Value> v2 = meval(gr->group(i+1));
+ assert(v2.valid());
+ if(v1->type == PIR_INT && v2->type == PIR_INT) {
+ ret->type = PIR_INT;
+ if(addop == "+") {
+ ret->idata = v1->idata + v2->idata;
+ } else if(addop == "-") {
+ ret->idata = v1->idata - v2->idata;
+ } else {
+ std::ostringstream msg;
+ msg << "Unknown add operator: " << addop << std::endl;
+ std::string par = get_parfile();
+ CCTK_Error(gr->line(),par.c_str(),current_thorn.c_str(),msg.str().c_str());
+ }
+ } else if(v1->type == PIR_STRING && v2->type == PIR_STRING) {
+ ret->type = PIR_STRING;
+ if(addop == "+") {
+ ret->sdata = v1->sdata + v2->sdata;
+ } else {
+ std::ostringstream msg;
+ msg << "Unknown add operator: " << addop << std::endl;
+ std::string par = get_parfile();
+ CCTK_Error(gr->line(),par.c_str(),current_thorn.c_str(),msg.str().c_str());
+ }
+ } else if(v1->intOrDouble() && v2->intOrDouble()) {
+ ret->type = PIR_REAL;
+ if(addop == "+") {
+ ret->ddata = v1->doubleValue()+v2->doubleValue();
+ } else if(addop == "-") {
+ ret->ddata = v1->doubleValue()-v2->doubleValue();
+ } else {
+ std::ostringstream msg;
+ msg << "Unknown add operator: " << addop << std::endl;
+ std::string par = get_parfile();
+ CCTK_Error(gr->line(),par.c_str(),current_thorn.c_str(),msg.str().c_str());
+ }
} else {
- v2 -= v3;
+ std::ostringstream msg;
+ msg << "Unknown operation: " << v1->type;
+ msg << " " << addop << v2->type << std::endl;
+ std::string par = get_parfile();
+ CCTK_Error(gr->line(),par.c_str(),current_thorn.c_str(),msg.str().c_str());
}
-// std::cout << "AEXPR: " << v2 << gr->group(i)->substring() << v3 << std::endl;
+ v1 = ret;
}
- std::ostringstream ostr;
- ostr << v2 << std::flush;
- val = ostr.str();
- } else if(gr->getPatternName() == "func") {
- std::string func_name = gr->group(0)->substring();
- std::string arg;
- meval(gr->group(1),arg);
- std::stringstream ostr;
- if(func_name == "sin") {
- ostr << sin(atof(arg.c_str()));
- } else if(func_name == "cos") {
- ostr << cos(atof(arg.c_str()));
- } else if(func_name == "sqrt") {
- ostr << sqrt(atof(arg.c_str()));
- } else if(func_name == "tan") {
- ostr << tan(atof(arg.c_str()));
- } else if(func_name == "log") {
- ostr << log(atof(arg.c_str()));
- } else if(func_name == "exp") {
- ostr << exp(atof(arg.c_str()));
+ } else if(pn == "mexpr") {
+ if(gr->groupCount()==1)
+ return meval(gr->group(0));
+ smart_ptr<Value> v1 = meval(gr->group(0));
+ for(int i=1;i+1<gr->groupCount();i+=2) {
+ std::string mulop = gr->group(i)->substring();
+ smart_ptr<Value> v2 = meval(gr->group(i+1));
+ if(v1->type == PIR_INT && v2->type == PIR_INT) {
+ ret->type = PIR_INT;
+ if(mulop == "*") {
+ ret->idata = v1->idata * v2->idata;
+ } else if(mulop == "/") {
+ ret->idata = v1->idata / v2->idata;
+ } else if(mulop == "%") {
+ ret->idata = v1->idata % v2->idata;
+ } else {
+ std::ostringstream msg;
+ msg << "Unknown mul operator: " << v1->type << mulop << v2->type << std::endl;
+ std::string par = get_parfile();
+ CCTK_Error(gr->line(),par.c_str(),current_thorn.c_str(),msg.str().c_str());
+ }
+ } else if(v1->type == PIR_STRING && v2->type == PIR_INT) {
+ ret->type = PIR_STRING;
+ if(mulop == "*") {
+ ret->sdata = v1->sdata + v2->sdata;
+ } else {
+ std::ostringstream msg;
+ msg << "Unknown mul operator: " << v1->type << mulop << v2->type << std::endl;
+ std::string par = get_parfile();
+ CCTK_Error(gr->line(),par.c_str(),current_thorn.c_str(),msg.str().c_str());
+ }
+ } else if(v1->intOrDouble() && v2->intOrDouble()) {
+ ret->type = PIR_REAL;
+ if(mulop == "*") {
+ ret->ddata = v1->doubleValue()*v2->doubleValue();
+ } else if(mulop == "/") {
+ ret->ddata = v1->doubleValue()/v2->doubleValue();
+ } else {
+ std::ostringstream msg;
+ msg << "Unknown mul operator: " << v1->type << mulop << v2->type << std::endl;
+ std::string par = get_parfile();
+ CCTK_Error(gr->line(),par.c_str(),current_thorn.c_str(),msg.str().c_str());
+ }
+ } else {
+ std::ostringstream msg;
+ msg << "Unknown operation: " << v1->type << " " << mulop << v2->type << std::endl;
+ std::string par = get_parfile();
+ CCTK_Error(gr->line(),par.c_str(),current_thorn.c_str(),msg.str().c_str());
+ }
+ v1 = ret;
}
- ostr << std::flush;
- val = ostr.str();
} else {
- std::cout << "Not handled[" << gr->getPatternName() << "]" << std::endl;
- abort();
+ std::ostringstream msg;
+ std::string par = get_parfile();
+ msg << "Pattern not handled[" << gr->getPatternName() << "]=" << gr->substring() <<
+ " at " << gr->line() << " in " << par << std::endl;
+ CCTK_Error(__LINE__,__FILE__,"piraha",msg.str().c_str());
+ }
+ return ret;
+}
+
+
+smart_ptr<Value> eval_expr(std::string input) {
+ smart_ptr<Matcher> m = new Matcher(par_file_grammar,"eval",input.c_str());
+ smart_ptr<Value> ret;
+ if(m->matches()) {
+ ret = meval(m->group(0));
+ }
+ return ret;
+}
+
+void check_types(const char *thorn,int line,ValueType v,int t) {
+ bool ok = false;
+ if(v == PIR_STRING && (t == PARAMETER_STRING || t == PARAMETER_KEYWORD))
+ ok = true;
+ else if(v == PIR_INT && t == PARAMETER_INT)
+ ok = true;
+ else if(v == PIR_BOOL && t == PARAMETER_BOOLEAN)
+ ok = true;
+ else if((v == PIR_INT || v == PIR_REAL) && t == PARAMETER_REAL)
+ ok = true;
+ if(!ok) {
+ std::string par = get_parfile();
+ std::ostringstream msg;
+ msg << "Parameter type mismatch ";
+ switch(t) {
+ case PARAMETER_BOOLEAN:
+ msg << "BOOL";
+ break;
+ case PARAMETER_INT:
+ msg << "INT";
+ break;
+ case PARAMETER_KEYWORD:
+ msg << "KEYWORD";
+ break;
+ case PARAMETER_STRING:
+ msg << "STRING";
+ break;
+ case PARAMETER_REAL:
+ msg << "REAL";
+ break;
+ default:
+ msg << "type(" << t << ")";
+ break;
+ }
+ msg << " != " << v << std::endl;
+ CCTK_Error(line,par.c_str(),thorn,msg.str().c_str());
}
}
@@ -190,39 +690,49 @@ extern "C" int cctk_PirahaParser(const char *buffer,unsigned long buffersize,int
"inquot = ({var}|\\\\.|[^\\\\\"])*\n"
"fname = \\.?/[-\\./0-9a-zA-Z_]+\n"
"quot = \"{inquot}\"|{fname}\n"
- "num = [-+]?([0-9]+(\\.[0-9]*|)|\\.[0-9]+)(e[+-]?[0-9]+|)\n"
+ "num = (inf|([0-9]+(\\.[0-9]*|)|\\.[0-9]+)(e[+-]?[0-9]+|))\n"
"env = ENV\\{{name}\\}\n"
"var = \\$({env}|{name}|\\{{name}\\})\n"
- "mulop = [*/]\n"
- "mexpr = {value}( {mulop} {value})*\n"
+ "powexpr = {value}( \\*\\* {value})?\n"
+ "mulop = [*/%]\n"
+ "mexpr = {powexpr}( {mulop} {powexpr})*\n"
"addop = [+-]\n"
"aexpr = {mexpr}( {addop} {mexpr})*\n"
- "paren = \\( {aexpr} \\)\n"
- "par = {name} :: {name}\n"
- "func = {name} \\( {aexpr} \\)\n"
- "array = \\[ {aexpr}( , {aexpr})* \\]\n"
+ "compop = [<>]=?\n"
+ "compexpr = {aexpr}( {compop} {aexpr})?\n"
+ "eqop = [!=]=\n"
+ "eqexpr = {compexpr}( {eqop} {eqexpr})?\n"
+ "andexpr = {eqexpr}( && {eqexpr})?\n"
+ "expr = {andexpr}( \\|\\| {andexpr})?\n"
+ "eval = {expr}\n"
- "value = {func}|{paren}|{num}|{quot}|{par}|{name}|{var}\n"
+ "paren = \\( {expr} \\)\n"
+ "par = {name} :: {name}( {parindex})?\n"
+ "func = {name} \\( {expr} \\)\n"
+ "array = \\[ {expr}( , {expr})* \\]\n"
+
+ "value = {unop}?({par}|{func}|{paren}|{num}|{quot}|{name}|{var})\n"
+ "unop = [-!]\n"
"int = [0-9]+\n"
"index = \\[ {int} \\]\n"
+ "parindex = \\[ {expr} \\]\n"
"active = (?i:ActiveThorns)\n"
- "set = ({active}|{par}( {index}|)) = ({array}|{aexpr}){-skipeol}\n"
- "file = ( !DESC {quot}|)( ({set} )*)$\n";
+ "set = ({active} = ({quot}|{name})|{par}( {index}|) = ({array}|\\+?{expr})){-skipeol}\n"
+ "file = ^( !DESC {quot}|)( ({set}|{active}) )*$\n";
- smart_ptr<Grammar> g = new Grammar();
- compileFile(g,par_file_src,strlen(par_file_src));
+ compileFile(par_file_grammar,par_file_src,strlen(par_file_src));
std::string active;
- smart_ptr<Matcher> m2 = new Matcher(g,"file",buffer,buffersize);
+ smart_ptr<Matcher> m2 = new Matcher(par_file_grammar,"file",buffer,buffersize);
if(m2->matches()) {
int line = -1;
for(int i=0;i<m2->groupCount();i++) {
smart_ptr<Group> gr = m2->group(i);
if(gr->group(0)->getPatternName() == "active") {
- std::string val;
- meval(gr->group(1),val);
+ smart_ptr<Value> smv = meval(gr->group(1));
+ std::string val = smv->copy();
active += val;
active += ' ';
line = gr->line();
@@ -242,19 +752,40 @@ extern "C" int cctk_PirahaParser(const char *buffer,unsigned long buffersize,int
key += thorn;
key += "::";
key += name;
+ const cParamData *data = CCTK_ParameterData(name.c_str(),thorn.c_str());
- smart_ptr<Group> index = gr->group("index");
+ smart_ptr<Group> index = par->group("parindex");
if(index.valid()) {
key += '[';
- key += index->group(0)->substring();
+ smart_ptr<Value> vv = meval(index);
+ if(vv->type != PIR_INT) {
+ std::ostringstream msg;
+ std::string par = get_parfile();
+ msg << "bad index " << vv << std::endl;
+ CCTK_Error(index->line(),par.c_str(),thorn.c_str(),msg.str().c_str());
+ }
+ std::string vvstr = vv->copy();
+ key += vvstr;
key += ']';
}
std::string val;
- smart_ptr<Group> aexpr = gr->group("aexpr");
+ smart_ptr<Group> aexpr = gr->group("expr");
if(aexpr.valid()) {
- meval(aexpr,val);
- values[thorn][key] = val;
+ current_thorn = thorn;
+ smart_ptr<Value> smv = meval(aexpr);
+ val = smv->copy();
+ assert(smv.valid());
+ values[thorn][key] = smv;
+ std::cout << "set_function(" << key << "," << val << ")" << std::endl;
+ smv->integerize();
+ if(data != NULL) {
+ if(data->type == PARAMETER_REAL)
+ smv->integerize();
+ if(data->type == PARAMETER_BOOLEAN)
+ smv->booleanize(gr);
+ check_types(thorn.c_str(),aexpr->line(),smv->type,data->type);
+ }
set_function(
strdup(key.c_str()),
strdup(val.c_str()),
@@ -264,9 +795,18 @@ extern "C" int cctk_PirahaParser(const char *buffer,unsigned long buffersize,int
for(int i=0;i<arr->groupCount();i++) {
aexpr = arr->group(i);
std::ostringstream keyi;
- keyi << key << '[' << (i+1) << ']';
- meval(aexpr,val);
- values[thorn][keyi.str()] = val;
+ keyi << key << '[' << i << ']';
+ smart_ptr<Value> smv = meval(aexpr);
+ val = smv->copy();
+ values[thorn][keyi.str()] = smv;
+ std::cout << "set_function_array(" << keyi.str() << "," << val << ")" << std::endl;
+ if(data != NULL) {
+ if(data->type == PARAMETER_REAL)
+ smv->integerize();
+ if(data->type == PARAMETER_BOOLEAN)
+ smv->booleanize(gr);
+ check_types(thorn.c_str(),aexpr->line(),smv->type,data->type);
+ }
set_function(
strdup(keyi.str().c_str()),
strdup(val.c_str()),
@@ -276,7 +816,7 @@ extern "C" int cctk_PirahaParser(const char *buffer,unsigned long buffersize,int
}
}
} else {
- std::cout << "ERROR IN PARAMETER FILE: ";
+ std::cout << "ERROR IN PARAMETER FILE:" << std::endl;
m2->showError();
return 1;
}