PEBL 2.2
Psychology Experiment Building Language - Cross-platform psychological experiment development system
Loader Class Reference

#include <Loader.h>

Public Member Functions

 Loader ()
 
 ~Loader ()
 
void FindFunctions (const PNode *Node)
 
void LoadUserFunctions (OpNode *node)
 
void LoadLibraryFunctions ()
 
bool Verify ()
 
PNodeGetMainPEBLFunction ()
 
void DumpFunctionSet ()
 

Detailed Description

This class takes a parsed program and loads it into the evaluation environment. This involves following the upper levels of the parse tree (which in effect form a list of function/functions nodes) and moving functions into a FunctionMap. It also does preliminary checking, and can be a place to do other debugging stuff and perhaps optimizing.

Definition at line 47 of file Loader.h.

Constructor & Destructor Documentation

◆ Loader()

Loader::Loader ( )

Definition at line 69 of file Loader.cpp.

70{
71
72}

◆ ~Loader()

Loader::~Loader ( )

Definition at line 74 of file Loader.cpp.

75{
76
77 //cout << "Deleting loader\n";
78 //DumpFunctionSet();
79}

Member Function Documentation

◆ DumpFunctionSet()

void Loader::DumpFunctionSet ( )

Definition at line 385 of file Loader.cpp.

386{
387 //Get an iterator to the first item
388 std::set<Variant>::iterator p;
389 p=mFunctionSet.begin();
390
391 cerr << "\t-----------------------------------------------------------\n";
392 cerr << "\tPrinting all functions in mFunctionSet\n";
393 while(p != mFunctionSet.end())
394 {
395 cerr << "\t\tFunction: ["<< *p << "]\n";
396 p++;
397 }
398 cerr << "\t-----------------------------------------------------------\n";
399
400
401}

Referenced by PEBLInterpret().

◆ FindFunctions()

void Loader::FindFunctions ( const PNode node)

This will perform a recursive search through a node tree and place the names of any functions it finds in the list mFunctionList, for later use by the verify routine. This probably could be done more quickly during the initial parse, or eliminated altogether for faster (riskier) loading.

This will perform a recursive search through a node tree and place the names of any functions it finds in the list mFunctionSet, for later use by the verify routine.

Definition at line 88 of file Loader.cpp.

89{
90
91
92 //First, determine if this is a data node; if it is,
93 //see if it is a function name.
94 if(node->GetType() == PEBL_DATA_NODE)
95 {
96 //cout << "A Data node." << endl;
97 if(((DataNode*)node)->GetDataType() == P_DATA_FUNCTION)
98 {
99 //cout << "\tA Function Node: " << *node << endl;
100 //If the node is a function name, insert the name into the
101 //functionname set
102
103 //This cast should be done in a smarter way:
104 Variant v = ((DataNode*)(node))->GetValue();
105
106
107 //Now, convert the function name in v to upper case
108 //It is really just a string.
109 std::string ucasename = PEBLUtility::ToUpper(v);
110
111 Variant v2 = Variant(ucasename.c_str(), P_DATA_FUNCTION);
112
113 //cout << "\tValue: " << v2 << "|" << v2.GetDataTypeName() << endl;
114 //std::pair<std::set<Variant>::iterator, bool> myPair;
115 //myPair = mFunctionSet.insert(v2);
116 mFunctionSet.insert(v2);
117
118 // cout << "Result: " << *(myPair.first) << " " << (myPair.second) << endl;
119 //DumpFunctionSet();
120 }
121 }
122 else
123 {
124
125 //Otherwise, it is an OpNode. Recurse on the left and right nodes.
126
127 PNode * node1 = ((OpNode*)node)->GetLeft();
128
129
130 if(node1)
131 {
132 FindFunctions(node1);
133 }
134
135 node1 = ((OpNode*)node)->GetRight();
136 if(node1)
137 {
138 FindFunctions(node1);
139 }
140 }
141}
@ PEBL_DATA_NODE
Definition PNode.h:36
@ P_DATA_FUNCTION
Definition Variant.h:43
void FindFunctions(const PNode *Node)
Definition Loader.cpp:88
Definition PNode.h:45
PNODE_TYPE GetType() const
Access mType data.
Definition PNode.h:61
std::string ToUpper(const std::string &text)

References FindFunctions(), PNode::GetType(), P_DATA_FUNCTION, PEBL_DATA_NODE, and PEBLUtility::ToUpper().

Referenced by FindFunctions(), main(), PEBLInterpret(), and PEBLInterpret().

◆ GetMainPEBLFunction()

PNode * Loader::GetMainPEBLFunction ( )

This looks inside the functionmap for a function titled "start", which it then retrieves.

Definition at line 372 of file Loader.cpp.

373{
374 // Get the main PEBL Function, returning it
375 // or 0 if it doesn't exist.
376 PNode * node = Evaluator::mFunctionMap.GetFunction("START");
377 if (node)
378 return node;
379 else
380 return 0;
381}
static FunctionMap mFunctionMap
Initiate some static member data.
PNode * GetFunction(const std::string &funcname)

References FunctionMap::GetFunction(), and Evaluator::mFunctionMap.

Referenced by main(), PEBLInterpret(), and PEBLInterpret().

◆ LoadLibraryFunctions()

void Loader::LoadLibraryFunctions ( )

If any functions found by FindFunctions are in libraries, this method will load them properly.

If any functions found by FindFunctions are in libraries, this method will load them properly. The method iterates through mFunctionSet, checking each item first against mFunctionMap to see if it has already been loaded (e.g., user functions), and then each of the standard function libraries

Definition at line 195 of file Loader.cpp.

196{
197 //Get an iterator to the first item
198 std::set<Variant>::iterator p;
199 p=mFunctionSet.begin();
200
201 PEBL_Function_Type * functionTable = NULL;
202
203 while(p != mFunctionSet.end())
204 {
205 //Check inside mFunctionMap, to make sure it hasn't been found yet;
206 //If it is found, it may be a user-defined function (as in Start), or
207 //one that has already been loaded previously.
208
209 string name = (*p).GetFunctionName();
210 //cout << "Checking [" << name <<"]"<< endl;
211 if(!(Evaluator::mFunctionMap.IsFunction(name)) )
212 {
213 //cout <<"isfuncion"<< endl;
214 bool functionNotFound = true;
215
216 //Go through each library, searching for the function.
217 for(int library = 0; library < 6; library++)
218 {
219 switch(library)
220 {
221 case 0:
222 //********************Check the Math Library******************
223 functionTable = PEBLMath::FunctionTable;
224 break;
225
226 case 1:
227 //********************Check the Stream Library******************
228 functionTable = PEBLStream::FunctionTable;
229 break;
230
231 case 2:
232 //********************Check the Objects Library******************
233 functionTable = PEBLObjects::FunctionTable;
234 break;
235
236 case 3:
237 //********************Check the Environment Library******************
238 functionTable = PEBLEnvironment::FunctionTable;
239 break;
240
241 case 4:
242 //********************Check the List Library******************
243 functionTable = PEBLList::FunctionTable;
244 break;
245 case 5:
246 functionTable = PEBLString::FunctionTable;
247 break;
248 default:
249 PError::SignalFatalError("Library Not Found.");
250 }
251
252
253 int i = 0;
254
255 while (functionTable[i].name && functionNotFound)
256 {
257 //cout << "checking name:[" <<name<< "]"<<endl;
258 bool globalnamespace = true;
259 string name2 = name;
260 if(name[0]== ':')
261 {
262 name2=name.substr(1,name.length());
263 }
264 //cout << "checking name:[" <<name2<< "]"<<endl;
265 if(functionTable[i].name == name2)
266 {
267 //Its a match. Construct a top-level function node with pieces below it
268 //that can be processed appropriately by the Evaluator.
269
270 //The filename and linenumber are irrelevant; this is not tied directly
271 //to the source code.
272 string filename = "<PEBL STANDARD LIBRARY FILE>";
273 int linenum = -1;
274
275 //Make a DataNode with numargs to signal the number of arguments required by the function; connect
276 //them with an AND node.
277 PNode * node0a = new DataNode(Variant(functionTable[i].minNumArgs),filename, linenum);
278 PNode * node0b = new DataNode(Variant(functionTable[i].maxNumArgs),filename, linenum);
279 PNode * node0 = new OpNode(PEBL_AND, node0a, node0b,filename, linenum);
280
281 //Make a DataNode with a functionpointer variant in it.
282 PNode * node1 = new DataNode(functionTable[i].funcname,filename, linenum);
283
284
285 if(globalnamespace)
286 {
287 //if we call a :Function(), thise aren't
288 //declared specifically, but implicitly created on-demand at this point.
289
290 OpNode * node2 = new OpNode(PEBL_LIBRARYFUNCTION, node0, node1,filename, linenum);
291 Variant newname = name;
292 node2->SetFunctionName(newname);
294 // cout << "2\n";
295
296 }else{
297 //this is a normal function
298 // Make a new OpNode with the *NumArgs on the left and the function pointer on the right.
299 OpNode * node2 = new OpNode(PEBL_LIBRARYFUNCTION, node0, node1,filename, linenum);
300 node2->SetFunctionName(*p);
302 }
303
304
305 //Add a :Function version that will always be callable, because it can't be overwritteen
306 //with define(). This lets you override Draw() but call :Draw() inside it.
307
308 /*
309 node2 = new OpNode(PEBL_LIBRARYFUNCTION, node0, node1,filename, linenum);
310 Variant newname = Variant(":")+(*p);
311 node2->SetFunctionName(newname);
312 Evaluator::mFunctionMap.AddFunction(newname,node2);
313 cout << "2\n";
314 */
315
316 //break out of the while--we are done.
317 functionNotFound = false;
318 }
319
320 i++;
321 }
322 }
323
324
325 //At this point, if functionNotFound is still true, we are in trouble.
326
327
328 //If this happens, we should parse all .pbl files in pebl-lib,
329 //run FindFunctions on it, and try again.
330 if(functionNotFound == true)
331 {
332 string message = "Function [" ;
333 message += name;
334 message += "] not found in libraries or user-defined functions.";
336 std::cerr << "********>>>>>ERROR: " << message << std::endl;
337 std::cerr.flush();
338#ifdef PEBL_EMSCRIPTEN
339 EM_ASM({
340 console.error("MISSING FUNCTION: " + UTF8ToString($0));
341 }, message.c_str());
342#endif
344 }
345
346 }
347 else
348 {
349
350
351
352 //In this case, the named function WAS found in the functionmap.
353 }
354
355 //Move on to the next function to load.
356 p++;
357 }
358
359}
#define NULL
Definition BinReloc.cpp:317
void DumpValues()
void AddFunction(std::string funcname, OpNode *node)
void SetFunctionName(const std::string &funcname)
Definition PNode.cpp:107
PEBL_Function_Type FunctionTable[]
Definition Functions.h:297
PEBL_Function_Type FunctionTable[]
Definition Functions.h:420
PEBL_Function_Type FunctionTable[]
Definition Functions.h:51
PEBL_Function_Type FunctionTable[]
Definition Functions.h:207
PEBL_Function_Type FunctionTable[]
Definition Functions.h:123
PEBL_Function_Type FunctionTable[]
Definition Functions.h:461
void SignalFatalError(const std::string &message)

References FunctionMap::AddFunction(), FunctionMap::DumpValues(), PEBLMath::FunctionTable, PEBLStream::FunctionTable, PEBLObjects::FunctionTable, PEBLEnvironment::FunctionTable, PEBLList::FunctionTable, PEBLString::FunctionTable, Evaluator::mFunctionMap, NULL, PNode::SetFunctionName(), and PError::SignalFatalError().

Referenced by main(), PEBLInterpret(), and PEBLInterpret().

◆ LoadUserFunctions()

void Loader::LoadUserFunctions ( OpNode node)

This will load the parsed PNode tree into mFunctionList, for use by the Evaluator.

This marches through the topmost nodes of the PNode tree and puts functions in the mFunctionMap. These nodes will all be either PEBL_FUNCTIONS or PEBL_FUNCTION.

Definition at line 147 of file Loader.cpp.

148{
149
150 //This will only parse down to PEBL_FUNCTION
151 //OpNodes, and so should only include two types:
152 //PEBL_FUNCTION and PEBL_FUNCTIONS.
153
154 OpNode *node1;
155
156 //If this is a PEBL_FUNCTIONS node, the left is either a PEBL_FUNCTIONS or
157 // a PEBL_FUNCTION and the right is either a PEBL_FUNCTIONS
158 //or a NULL. If null, we are done.
159
160
161 //Add the PEBL_FUNCTION
162 node1 = (OpNode*)(node->GetLeft());
163 if(node1->GetOp() == PEBL_FUNCTION)
164 {
165
166 Evaluator::mFunctionMap.AddFunction( ((DataNode*)(((OpNode*)node1)->GetLeft()))->GetValue(),
167 (OpNode*)node1->GetRight());
168 }
169 else if (node1->GetOp() == PEBL_FUNCTIONS)
170 {
171 LoadUserFunctions(node1);
172 }
173 else
174 {
175 cerr << "PEBL_FUNCTION is " << PEBL_FUNCTION << endl;
176 cerr << "PEBL_FUNCTIONS is " << PEBL_FUNCTIONS << endl;
177 cerr << "Unknown Node type in Loader::LoadUserFunctions: " << node1->GetOp() << endl;
178 PError::SignalFatalError("Unknown Node Type");
179 }
180 //Get the PEBL_FUNCTIONS node and recurse
181 node1 = (OpNode*)(node->GetRight());
182 if(node1)
183 {
184 LoadUserFunctions(node1);
185 }
186
187}
void LoadUserFunctions(OpNode *node)
Definition Loader.cpp:147
PNode * GetRight() const
Definition PNode.h:115
int GetOp() const
Definition PNode.h:111
PNode * GetLeft() const
Definition PNode.h:114

References FunctionMap::AddFunction(), OpNode::GetLeft(), OpNode::GetOp(), OpNode::GetRight(), LoadUserFunctions(), Evaluator::mFunctionMap, and PError::SignalFatalError().

Referenced by LoadUserFunctions(), main(), PEBLInterpret(), and PEBLInterpret().

◆ Verify()

bool Loader::Verify ( )

This checks to see whether everything loaded into the environment is legal; i.e, if all functions used exist.

This method checks to see whether everything is ready for a potentially error-free run. This includes determining whether all of the used functions actually exist, and if there is an entry function, and perhaps other stuff tbd later.

Definition at line 365 of file Loader.cpp.

366{
367
368 return true;
369}

The documentation for this class was generated from the following files: