Statistics
| Branch: | Revision:

root / src / sim / nedsupport.cc @ fbe00e73

History | View | Annotate | Download (12.2 KB)

1
//==========================================================================
2
//   NEDSUPPORT.CC  - part of
3
//                     OMNeT++/OMNEST
4
//            Discrete System Simulation in C++
5
//
6
//  Author: Andras Varga
7
//
8
//==========================================================================
9

    
10
/*--------------------------------------------------------------*
11
  Copyright (C) 1992-2008 Andras Varga
12
  Copyright (C) 2006-2008 OpenSim Ltd.
13

14
  This file is distributed WITHOUT ANY WARRANTY. See the file
15
  `license' for details on this and other legal matters.
16
*--------------------------------------------------------------*/
17

    
18
#include "cdynamicexpression.h"
19
#include "cxmlelement.h"
20
#include "cmathfunction.h"
21
#include "cnedfunction.h"
22
#include "cexception.h"
23
#include "cenvir.h"
24
#include "cmodule.h"
25
#include "ccomponenttype.h"
26
#include "nedsupport.h"
27
#include "stringutil.h"
28

    
29

    
30
NAMESPACE_BEGIN
31

    
32
namespace NEDSupport {
33

    
34
ModuleIndex::ModuleIndex()
35
{
36
}
37

    
38
Value ModuleIndex::evaluate(cComponent *context, Value args[], int numargs)
39
{
40
    ASSERT(numargs==0 && context!=NULL);
41
    cModule *module = dynamic_cast<cModule *>(context);
42
    if (!module)
43
        throw cRuntimeError(context,"cannot evaluate `index' operator in expression: context is not a module");
44
    return (double) module->getIndex();
45
}
46

    
47
std::string ModuleIndex::str(std::string args[], int numargs)
48
{
49
    return "index";
50
}
51

    
52
//----
53

    
54
ParameterRef::ParameterRef(const char *paramName, bool ofParent, bool explicitKeyword)
55
{
56
    this->paramName = paramName;
57
    this->ofParent = ofParent;
58
    this->explicitKeyword = explicitKeyword;
59
}
60

    
61
Value ParameterRef::evaluate(cComponent *context, Value args[], int numargs)
62
{
63
    ASSERT(numargs==0 && context!=NULL);
64
    cComponent *component = ofParent ? context->getParentModule() : context;
65
    if (!component)
66
        throw cRuntimeError(context,eENOPARENT);
67

    
68
    // In inner types, a "paramName" should be first tried as the enclosing type's
69
    // parameter, only then as local parameter.
70
    // However, "this.paramName" (that is, ofParent==false and explicitKeyword==true)
71
    // means local parameter, so parent should not be looked up in that case
72
    if (!ofParent && !explicitKeyword && component->getComponentType()->isInnerType())
73
        if (component->getParentModule() && component->getParentModule()->hasPar(paramName.c_str()))
74
            return component->getParentModule()->par(paramName.c_str());
75

    
76
    return component->par(paramName.c_str());
77
}
78

    
79
std::string ParameterRef::str(std::string args[], int numargs)
80
{
81
    if (!explicitKeyword)
82
        return paramName;
83
    else if (ofParent)
84
        return std::string("parent.")+paramName; // not a legal NED syntax
85
    else
86
        return std::string("this.")+paramName;
87
}
88

    
89
//----
90

    
91
SiblingModuleParameterRef::SiblingModuleParameterRef(const char *moduleName, const char *paramName, bool ofParent, bool withModuleIndex)
92
{
93
    ASSERT(!opp_isempty(moduleName) && !opp_isempty(paramName) && opp_strcmp(moduleName,"this")!=0);
94
    this->moduleName = moduleName;
95
    this->paramName = paramName;
96
    this->ofParent = ofParent;
97
    this->withModuleIndex = withModuleIndex;
98
}
99

    
100
Value SiblingModuleParameterRef::evaluate(cComponent *context, Value args[], int numargs)
101
{
102
    ASSERT(context!=NULL);
103
    ASSERT(!withModuleIndex || (withModuleIndex && numargs==1 && args[0].type==Value::DBL));
104
    cModule *compoundModule = dynamic_cast<cModule *>(ofParent ? context->getParentModule() : context); // this works for channels too
105
    if (!compoundModule)
106
        throw cRuntimeError(context,eENOPARENT);
107
    int moduleIndex = withModuleIndex ? (int)args[0].dbl : -1;
108
    cModule *siblingModule = compoundModule->getSubmodule(moduleName.c_str(), moduleIndex);
109
    if (!siblingModule) {
110
        std::string modName = moduleIndex==-1 ? moduleName : opp_stringf("%s[%d]", moduleName.c_str(), moduleIndex);
111
        throw cRuntimeError(context,"cannot find submodule for parameter `%s.%s'", modName.c_str(), paramName.c_str());
112
    }
113
    return siblingModule->par(paramName.c_str());
114
}
115

    
116
std::string SiblingModuleParameterRef::str(std::string args[], int numargs)
117
{
118
    if (withModuleIndex)
119
        return moduleName+"["+args[0]+"]."+paramName;
120
    else
121
        return moduleName+"."+paramName;
122
}
123

    
124
//----
125

    
126
const char *LoopVar::varNames[32];
127
long LoopVar::vars[32];
128
int LoopVar::varCount = 0;
129

    
130
long& LoopVar::pushVar(const char *varName)
131
{
132
    ASSERT(varCount<32);
133
    varNames[varCount] = varName;
134
    return vars[varCount++];
135
}
136

    
137
void LoopVar::popVar()
138
{
139
    ASSERT(varCount>0);
140
    varCount--;
141
}
142

    
143
void LoopVar::reset()
144
{
145
    varCount = 0;
146
}
147

    
148
Value LoopVar::evaluate(cComponent *context, Value args[], int numargs)
149
{
150
    ASSERT(numargs==0);
151
    const char *var = varName.c_str();
152
    for (int i=0; i<varCount; i++)
153
        if (strcmp(var, varNames[i])==0)
154
            return vars[i];
155
    throw cRuntimeError(context, "loop variable %s not found", varName.c_str());
156
}
157

    
158
std::string LoopVar::str(std::string args[], int numargs)
159
{
160
    // return varName;
161
    return std::string("(loopvar)")+varName;  //XXX debugging only
162
}
163

    
164
//---
165

    
166
Sizeof::Sizeof(const char *ident, bool ofParent, bool explicitKeyword)
167
{
168
    this->ident = ident;
169
    this->ofParent = ofParent;
170
    this->explicitKeyword = explicitKeyword;
171
}
172

    
173
Value Sizeof::evaluate(cComponent *context, Value args[], int numargs)
174
{
175
    ASSERT(numargs==0 && context!=NULL);
176
    cModule *module = dynamic_cast<cModule *>(ofParent ? context->getParentModule() : context);
177
    if (!module)
178
        throw cRuntimeError(context,eENOPARENT);
179

    
180
//FIXME stuff already implemented at the bottom of this file????
181

    
182
//FIXME decide it at buildtime, not now? (info is known then already!)
183
    // ident might be a gate vector of the *parent* module, or a sibling submodule vector
184
    // Note: it might NOT mean gate vector of this module
185
    if (module->hasGate(ident.c_str()))
186
    {
187
        return (long) module->gateSize(ident.c_str()); // returns 1 if it's not a vector
188
    }
189
    else
190
    {
191
        // Find ident among submodules. If there's no such submodule, it may
192
        // be that such submodule vector never existed, or can be that it's zero
193
        // size -- we cannot tell, so we have to return 0 (and cannot throw error).
194
        cModule *siblingModule = module->getSubmodule(ident.c_str(), 0); // returns NULL if submodule is not a vector
195
        if (!siblingModule && module->getSubmodule(ident.c_str()))
196
            return 1L; // return 1 if submodule exists but not a vector
197
        return (long) siblingModule ? siblingModule->size() : 0L;
198
    }
199

    
200
}
201

    
202
std::string Sizeof::str(std::string args[], int numargs)
203
{
204
    const char *prefix = !explicitKeyword ? "" : ofParent ? "parent." : "this."; // "parent" is not a legal NED syntax though
205
    return std::string("sizeof(") + prefix + ident + ")";
206
}
207

    
208
//---
209

    
210
Value XMLDoc::evaluate(cComponent *context, Value args[], int numargs)
211
{
212
    ASSERT((numargs==1 || numargs==2) && args[0].type==Value::STR && (numargs==1 || args[1].type==Value::STR));
213
    cXMLElement *node;
214
    if (numargs==1)
215
    {
216
        node = ev.getXMLDocument(args[0].s.c_str(), NULL);
217
        if (!node)
218
            throw cRuntimeError("xmldoc(\"%s\"): element not found", args[0].s.c_str());
219
    }
220
    else
221
    {
222
        node = ev.getXMLDocument(args[0].s.c_str(), args[1].s.c_str());
223
        if (!node)
224
            throw cRuntimeError("xmldoc(\"%s\", \"%s\"): element not found", args[0].s.c_str(), args[1].s.c_str());
225
    }
226
    return node;
227
}
228

    
229
std::string XMLDoc::str(std::string args[], int numargs)
230
{
231
    ASSERT(numargs==1 || numargs==2);
232
    if (numargs==1)
233
        return std::string("xmldoc(")+args[0]+")";
234
    else
235
        return std::string("xmldoc(")+args[0]+", "+args[1]+")";
236
}
237

    
238
};
239

    
240
NAMESPACE_END
241

    
242
/*
243
//FIXME make error messages consistent
244

245
typedef cDynamicExpression::Value Value; // abbreviation for local use
246

247
//
248
// internal function to support NED: resolves a sizeof(moduleOrGateVectorName) reference
249
//
250
Value cDynamicExpression::getSizeofIdent(cComponent *context, Value args[], int numargs)
251
{
252
    ASSERT(numargs==1 && args[0].type==Value::STR);
253
    const char *ident = args[0].s.c_str();
254

255
    // ident might be a gate vector of the *parent* module, or a sibling submodule vector
256
    // Note: it might NOT mean gate vector of this module
257
    cModule *parentModule = dynamic_cast<cModule *>(context->getParentModule()); // this works for channels too
258
    if (!parentModule)
259
        throw cRuntimeError(context, "sizeof(%s) occurs in wrong context", ident);
260
    if (parentModule->hasGate(ident))
261
    {
262
        return (long) parentModule->gateSize(ident); // returns 1 if it's not a vector
263
    }
264
    else
265
    {
266
        // Find ident among submodules. If there's no such submodule, it may
267
        // be that such submodule vector never existed, or can be that it's zero
268
        // size -- we cannot tell, so we have to return 0.
269
        cModule *siblingModule = parentModule->getSubmodule(ident, 0); // returns NULL if submodule is not a vector
270
        if (!siblingModule && parentModule->getSubmodule(ident))
271
            return 1L; // return 1 if submodule exists but not a vector
272
        return (long) siblingModule ? siblingModule->size() : 0L;
273
    }
274
}
275

276
//
277
// internal function to support NED: resolves a sizeof(this.gateVectorName) reference
278
//
279
Value cDynamicExpression::getSizeofGate(cComponent *context, Value args[], int numargs)
280
{
281
    ASSERT(numargs==1 && args[0].type==Value::STR);
282
    const char *gateName = args[0].s.c_str();
283
    cModule *module = dynamic_cast<cModule *>(context);
284
    if (!module || !module->hasGate(gateName))
285
        throw cRuntimeError(context, "error evaluating sizeof(): no such gate: `%s'", gateName);
286
    return (long) module->gateSize(gateName); // returns 1 if it's not a vector
287
}
288

289
//
290
// internal function to support NED: resolves a sizeof(parent.gateVectorName) reference
291
//
292
Value cDynamicExpression::getSizeofParentModuleGate(cComponent *context, Value args[], int numargs)
293
{
294
    ASSERT(numargs==1 && args[0].type==Value::STR);
295
    const char *gateName = args[0].s.c_str();
296
    cModule *parentModule = dynamic_cast<cModule *>(context->getParentModule()); // this works for channels too
297
    if (!parentModule)
298
        throw cRuntimeError(context, "sizeof() occurs in wrong context", gateName);
299
    if (!parentModule->hasGate(gateName))
300
        throw cRuntimeError(context, "error evaluating sizeof(): no such gate: `%s'", gateName);
301
    return (long) parentModule->gateSize(gateName); // returns 1 if it's not a vector
302
}
303

304
//
305
// internal function to support NED: resolves a sizeof(module.gateName) reference
306
//
307
Value cDynamicExpression::getSizeofSiblingModuleGate(cComponent *context, Value args[], int numargs)
308
{
309
    ASSERT(numargs==2 && args[0].type==Value::STR && args[1].type==Value::STR);
310
    const char *siblingModuleName = args[0].s.c_str();
311
    const char *gateName = args[1].s.c_str();
312

313
    cModule *parentModule = dynamic_cast<cModule *>(context->getParentModule()); // this works for channels too
314
    if (!parentModule)
315
        throw cRuntimeError(context, "sizeof() occurs in wrong context", gateName);
316
    cModule *siblingModule = parentModule->getSubmodule(siblingModuleName); // returns NULL if submodule is not a vector
317
    if (!siblingModule->hasGate(gateName))
318
        throw cRuntimeError(context, "error evaluating sizeof(): no such gate: `%s'", gateName);
319
    return (long) siblingModule->gateSize(gateName); // returns 1 if it's not a vector
320
}
321

322
//
323
// internal function to support NED: resolves a sizeof(module.gateName) reference
324
//
325
Value cDynamicExpression::getSizeofIndexedSiblingModuleGate(cComponent *context, Value args[], int numargs)
326
{
327
    ASSERT(numargs==3 && args[0].type==Value::STR && args[1].type==Value::STR && args[2].type==Value::DBL);
328
    const char *gateName = args[1].s.c_str();
329
    const char *siblingModuleName = args[1].s.c_str();
330
    int siblingModuleIndex = (int)args[2].dbl;
331
    cModule *parentModule = dynamic_cast<cModule *>(context->getParentModule()); // this works for channels too
332
    cModule *siblingModule = parentModule ? parentModule->getSubmodule(siblingModuleName, siblingModuleIndex) : NULL;
333
    if (!siblingModule)
334
        throw cRuntimeError(context,"sizeof(): cannot find submodule %[%d]",
335
                                siblingModuleName, siblingModuleIndex,
336
                                siblingModuleName, siblingModuleIndex, gateName);
337
    return (long) siblingModule->gateSize(gateName); // returns 1 if it's not a vector
338
}
339
*/