Minsky
valueId.cc
Go to the documentation of this file.
1 /*
2  @copyright Steve Keen 2021
3  @author Russell Standish
4  This file is part of Minsky.
5 
6  Minsky is free software: you can redistribute it and/or modify it
7  under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  Minsky is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with Minsky. If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 #include "cairoItems.h"
21 #include "valueId.h"
22 #include "group.h"
23 #include "lasso.h"
24 #include "latexMarkup.h"
25 #include "minsky_epilogue.h"
26 
27 #include <boost/locale.hpp>
28 using namespace boost::locale::conv;
29 using namespace std;
30 
31 namespace minsky
32 {
33  bool isValueId(const string& name)
34  {
35  // original code, left for reference
36  // static regex pattern("((constant)?\\d*:[^:\\ \f\n\r\t\v]+)");
37  // return name.length()>1 && name.substr(name.length()-2)!=":_" &&
38  // regex_match(utf_to_utf<char>(name), pattern); // Leave curly braces in valueIds. For ticket 1165
39  if (name.substr(name.length()-2)==":_") return false;
40 
41  static const string constantPrefix="constant:", tempPrefix="temp:";
42  auto nameCStr=name.c_str();
43  const char* endp=nullptr;
44  strtoull(nameCStr,&const_cast<char*&>(endp),10);
45  if (*endp==':' || name.starts_with(constantPrefix)||name.starts_with(tempPrefix))
46  {
47  if (*endp!=':')
48  {
49  if (name[constantPrefix.length()-1]==':')
50  endp=nameCStr+constantPrefix.length()-1;
51  else
52  endp=nameCStr+tempPrefix.length()-1;
53  }
54  // check unqualified name portion has no verboten characters
55  for (auto c=endp+1; *c!='\0'; ++c)
56  if (strchr(":\\ \f\n\r\t\v",*c))
57  return false;
58  return true;
59  }
60  return false;
61  }
62 
63  string canonicalName(const string& name)
64  {
65  return utf_to_utf<char>(stripActive(trimWS(latexToPangoNonItalicised(uqName(name)))));
66  }
67 
68  string valueIdCanonical(size_t scope, const string& name)
69  {
70  auto tmp=":"+name;
71  if (scope==0) return tmp;
72  return to_string(scope)+tmp;
73  }
74 
75  string valueId(const string& name)
76  {
77  return valueIdCanonical(scope(name), canonicalName(name));
78  }
79 
80  string valueId(const GroupPtr& ref, const string& name)
81  {return valueIdFromScope(scope(ref,utf_to_utf<char>(name)), canonicalName(name));}
82 
83  size_t scope(const string& name)
84  {
85  if (name.starts_with("temp:")) return 0; // temporaries are "global"
86  auto nm=utf_to_utf<char>(name);
87  auto nameCStr=nm.c_str();
88  char* endp=nullptr;
89  const size_t r=strtoull(nameCStr,&endp,10);
90  if (endp && *endp==':')
91  return r;
92  throw error("scope requested for local variable");
93  // old implementation left for reference
94  // smatch m;
95  // if (regex_search(nm, m, regex(R"((\d*)]?:.*)")))
96  // if (m.size()>1 && m[1].matched && !m[1].str().empty())
97  // return stoull(m[1].str());
98  // else
99  // return 0;
100  // else
101  // // no scope information is present
102  // throw error("scope requested for local variable");
103  }
104 
105  GroupPtr scope(GroupPtr scope, const string& a_name)
106  {
107  auto name=canonicalName(a_name);
108  if (a_name[0]==':' && scope)
109  {
110  // find maximum enclosing scope that has this same-named variable
111  for (auto g=scope->group.lock(); g; g=g->group.lock())
112  for (auto& i: g->items)
113  if (auto v=i->variableCast())
114  {
115  if (v->canonicalName()==name)
116  {
117  scope=g;
118  goto break_outerloop;
119  }
120  }
121  scope.reset(); // global var
122  break_outerloop: ;
123  }
124  return scope;
125  }
126 
127 
128  string valueIdFromScope(const GroupPtr& scope, const std::string& name)
129  {
130  if (name.empty() || !scope || !scope->group.lock())
131  return valueIdCanonical(0,name); // retain previous global var id
132  return valueIdCanonical(size_t(scope.get()), name);
133 }
134 
135  std::string uqName(const std::string& name)
136  {
137  const string::size_type p=name.rfind(':');
138  if (p==string::npos)
139  return utf_to_utf<char>(name);
140  return utf_to_utf<char>(name).substr(p+1);
141  }
142 
143 }
string valueIdCanonical(size_t scope, const string &name)
construct a valueId @ name should be canonicalised
Definition: valueId.cc:68
STL namespace.
std::string uqName(const std::string &name)
extract unqualified portion of name
Definition: valueId.cc:135
string valueId(const GroupPtr &ref, const string &name)
construct a valueId. @ name should not be canonicalised if name has leading :, then heirarchy is sear...
Definition: valueId.cc:80
Creation and access to the minskyTCL_obj object, which has code to record whenever Minsky&#39;s state cha...
Definition: constMap.h:22
std::string trimWS(const std::string &s)
Definition: str.h:49
std::string stripActive(const std::string &s)
repaces characters that cause interpretation by TCL, backslashes are replaced by the set minus operat...
Definition: str.h:63
string latexToPangoNonItalicised(const char *input)
Definition: latexMarkup.cc:855
string canonicalName(const string &name)
convert a raw name into a canonical name - this is not idempotent.
Definition: valueId.cc:63
bool isValueId(const string &name)
check that name is a valid valueId (useful for assertions)
Definition: valueId.cc:33
string valueIdFromScope(const GroupPtr &scope, const std::string &name)
value Id from scope and canonical name name
Definition: valueId.cc:128
std::shared_ptr< Group > GroupPtr
Definition: port.h:32
string to_string(CONST84 char *x)
Definition: minskyTCLObj.h:33
GroupPtr scope(GroupPtr scope, const string &a_name)
starting from reference group ref, applying scoping rules to determine the actual scope of name If na...
Definition: valueId.cc:105