File: param_ext.cpp

package info (click to toggle)
falconpl 0.9.6.9-git20120606-2
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 46,176 kB
  • sloc: cpp: 181,389; ansic: 109,025; yacc: 2,310; xml: 1,218; sh: 403; objc: 245; makefile: 82; sql: 20
file content (352 lines) | stat: -rw-r--r-- 11,715 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
/*
   FALCON - The Falcon Programming Language.
   FILE: param_ext.cpp

   Variable parameter management support.
   -------------------------------------------------------------------
   Author: Giancarlo Niccolai
   Begin: Thu, 14 Aug 2008 01:54:37 +0200

   -------------------------------------------------------------------
   (C) Copyright 2008: the FALCON developers (see list in AUTHORS file)

   See LICENSE file for licensing details.
*/

#include "core_module.h"
#include <string.h>

/*#
   @beginmodule core
*/

namespace Falcon {
namespace core {

/*#
   @funset varparams_support Variable parameters support
   @brief Functions giving informations on variable parameters.

   Falcon supports variable parameter calling; a function or method may
   access the items that have been used in the parameter call by counting
   them and accessing them one by one.

   Parameter passed by reference may be modified with the appropriate function.

   This functions may be used whether the calling function provides a list of
   formal parameters or not. The first formal parameter will be treated as the
   variable parameter number zero, and the parameter count may be the same as,
   more than or less than the number of formal parameters.
   So, part of the parameters may be accessible via parameter names,
   and the others may be accessed with the functions in this group.
*/

/*#
   @function paramCount
   @return The parameter count.
   @inset varparams_support
   @brief Returns number of parameter that have been passed to the current function or method.

   The return value is the minimum value between the formal parameters declared
   for the current function and the number of actual parameters the caller passed.
   Formal parameters which are declared in the function header, but for which the
   caller didn't provide actual parameters, are filled with nil.
*/

FALCON_FUNC  paramCount ( ::Falcon::VMachine *vm )
{
   StackFrame *thisFrame = vm->currentFrame();
   if( thisFrame == 0 || thisFrame->prev() == 0 )
      throw new GenericError( ErrorParam( e_stackuf, __LINE__ ).origin( e_orig_runtime ) );

   vm->retval( (int64) thisFrame->prev()->m_param_count );
}

/*#
   @function parameter
   @brief Gets the Nth parameter
   @inset varparams_support
   @param pnum The ordinal number of the paremeter, zero based
   @return The nth paramter (zero based) or NIL if the parameter is not given.
   @raise AccessError if @b pnum is out of range.

   This function returns the required parameter, being the first one passed to
   the function indicated as 0, the second as 1 and so on. Both formally declared
   parameters and optional parameters can be accessed this way.

   If the given parameter number cannot be accessed, a AccessError is raised.

   @note This function used to be called "paramNumber", and has been renamed in
      version 0.8.10. The function is still aliased throught the old function name
      for compatibility reason, but its usage is deprecated. Use @b parameter instead.
*/

FALCON_FUNC  _parameter ( ::Falcon::VMachine *vm )
{
   Item *number = vm->param(0);
   if ( number == 0 || ! number->isOrdinal() ) {
      throw new ParamError( ErrorParam( e_param_range ).origin( e_orig_runtime ).extra( "(N)" ) );
   }

   StackFrame *thisFrame = vm->currentFrame();
   if ( thisFrame == 0 || thisFrame->prev() == 0 )
      throw new GenericError( ErrorParam( e_stackuf, __LINE__ ).origin( e_orig_runtime ) );

   // ...but we want the parameter count of our caller.
   StackFrame *prevFrame = thisFrame->prev();

   // ...while the parameters are below our frame's base.
   uint32 val = (uint32) number->forceInteger();
   if( val >= 0 && val < prevFrame->m_param_count )
   {
      vm->retval( prevFrame->m_params[val] );
   }
   else {
      vm->retnil();
   }
}

/*#
   @function paramIsRef
   @inset varparams_support
   @brief Checks whether the nth parameter has been passed by reference or not.
   @param number The paramter that must be checked (zero based)
   @return true if the parameter has been passed by reference, false otherwise.
   @raise AccessError if @b number is out of range.

   Both assigning a value to a certain parameter and using the paramSet()
   function will change locally the value of the parameter, but
   this value won't be reflected in the actual parameter that was used to
   call the function, unless the parameter was explicitly passed by reference.
   In some contexts, it may be useful to know if this is the case.

   If the given parameter number cannot be accessed, a AccessError is raised.
*/

FALCON_FUNC  paramIsRef ( ::Falcon::VMachine *vm )
{
   Item *number = vm->param(0);
   if ( number == 0 || ! number->isOrdinal() ) {
      throw new ParamError( ErrorParam( e_param_range, __LINE__ ).origin( e_orig_runtime ).extra( "N" ) );
   }

   StackFrame *thisFrame = vm->currentFrame();
   if ( thisFrame == 0 || thisFrame->prev() == 0 )
      throw new GenericError( ErrorParam( e_stackuf, __LINE__ ).origin( e_orig_runtime ) );

   // ...but we want the parameter count of our caller.
   StackFrame *prevFrame = thisFrame->prev();

   uint32 val = (uint32) number->forceInteger();
   if( val >= 0 && val < prevFrame->m_param_count )
   {
      vm->regA().setBoolean( prevFrame->m_params[val].isReference() ? true: false );
   }
   else {
      vm->regA().setBoolean( false );
   }
}

/*#
   @function paramSet
   @inset varparams_support
   @brief Changes the nth paramter if it has been passed by reference.
   @param number the paramter to be changed (zero based)
   @param value the new value for the parameter
   @raise AccessError if @b number is out of range.

   The function is equivalent to assigning the value directly to the required
   parameter; of course, in this way also optional parameter may be accessed.
   If the required parameter was passed by reference, also the original value
   in the caller is changed.

   If the given parameter number cannot be accessed, an AccessError is raised.
*/
FALCON_FUNC  paramSet ( ::Falcon::VMachine *vm )
{

   Item *number = vm->param(0);
   Item *value = vm->param(1);
   if ( number == 0 || ! number->isOrdinal() || value == 0) {
      throw new ParamError( ErrorParam( e_param_range ).origin( e_orig_runtime ).extra( "N,X" ) );
   }

   StackFrame *thisFrame = vm->currentFrame();
   if ( thisFrame == 0 || thisFrame->prev() == 0 )
      throw new GenericError( ErrorParam( e_stackuf, __LINE__ ).origin( e_orig_runtime ) );

   // ...but we want the parameter count of our caller.
   StackFrame *prevFrame = thisFrame->prev();


   uint32 val = (uint32) number->forceInteger();
   if( val >= 0 && val < prevFrame->m_param_count )
   {
      prevFrame->m_params[val].dereference()->copy( *value );
   }
}


/*#
   @function argv
   @inset varparams_support
   @brief Returns all the parameters of the current function as a vector.

   If the current function doesn't receive any parameter, it returns nil.  
*/
FALCON_FUNC core_argv( VMachine *vm )
{
   StackFrame *thisFrame = vm->currentFrame();
   if ( thisFrame == 0 || thisFrame->prev() == 0 )
      throw new GenericError( ErrorParam( e_stackuf, __LINE__ ).origin( e_orig_runtime ) );

   // ...but we want the parameter count of our caller.
   StackFrame *prevFrame = thisFrame->prev();

   // ...while the parameters are below our frame's base.
   if( prevFrame->m_param_count > 0 )
   {
      CoreArray* arr = new CoreArray(prevFrame->m_param_count);
      Item* first = prevFrame->m_params;
      memcpy( arr->items().elements(), first, arr->items().esize( prevFrame->m_param_count ) );
      arr->length( prevFrame->m_param_count );
      vm->retval( arr );
   }
}

/*#
   @function argd
   @inset varparams_support
   @brief Returns a dictionary containing all the parameters passed to the current function.

   The dictionary contains the parameter names associated with the value passed by the caller.
   Parameters received beyond the officially declared ones aren't returned in this dictionary.
   
   If the function doesn't declare any parameter, returns nil.
*/
FALCON_FUNC core_argd( VMachine *vm )
{
   StackFrame *thisFrame = vm->currentFrame();
   if ( thisFrame == 0 || thisFrame->prev() == 0 )
      throw new GenericError( ErrorParam( e_stackuf, __LINE__ ).origin( e_orig_runtime ) );

   // ...but we want the parameter count of our caller.
   StackFrame *prevFrame = thisFrame->prev();
   
   // get the caller function symbol --- it holds the declared parameters
   const Symbol* sym = thisFrame->m_symbol;
   const Map* st =  sym->isFunction()? 
      &sym->getFuncDef()->symtab().map() :
      &sym->getExtFuncDef()->parameters()->map();
      
   CoreDict* ret = 0;
   Item* first = prevFrame->m_params;
      
   // ...while the parameters are below our frame's base.
   MapIterator iter = st->begin();
   while( iter.hasCurrent() )
   {
      Symbol *p = (*(Symbol**)iter.currentValue());
      if( p->isParam() )
      {
         if( ret == 0 )
            ret = new CoreDict( new LinearDict );
         ret->put( Item(new CoreString( p->name() )), first[p->itemId()] );
      }
      
     iter.next();
   }
   
   if ( ret != 0 )
      vm->retval( ret );
}

/*#
   @function passvp
   @inset varparams_support
   @brief Returns all the undeclared parameters, or passes them to a callable item
   @optparam citem Callable item on which to pass the parameters.
   @return An array containing unnamed parameters, or the return value \b citem.
   
   This function returns all the parameters passed to this function but not declared
   in its prototype (variable parameters) in an array.
   
   If the host function doesn't receive any extra parameter, this function returns
   an empty array. This is useful in case the array is immediately added to a direct
   call. For example:

   @code
   function receiver( a, b )
      > "A: ", a
      > "B: ", b
      > "Others: ", passvp().describe()
   end

   receiver( "one", "two", "three", "four" )
   @endcode
   
   If @b citem is specified, the function calls citem passing all the extra parameters
   to it. For example:

   @code
   function promptPrint( prompt )
      passvp( .[printl prompt] )
   end

   promptPrint( "The prompt: ", "arg1", " ", "arg2" )
   @endcode
*/
FALCON_FUNC core_passvp( VMachine *vm )
{
   StackFrame *thisFrame = vm->currentFrame();
   if ( thisFrame == 0 || thisFrame->prev() == 0 )
      throw new GenericError( ErrorParam( e_stackuf, __LINE__ ).origin( e_orig_runtime ) );
      
   // ok, do we have an item to call?
   Item* i_citem = vm->param(0);
   if ( i_citem != 0 && ! i_citem->isCallable() )
      throw new ParamError( ErrorParam( e_inv_params, __LINE__ ).extra("[C]").origin( e_orig_runtime ) );
   
   // ...but we want the parameter count of our caller.
   StackFrame *prevFrame = thisFrame->prev();
   
   // get the caller function symbol --- it holds the declared parameters
   const Symbol* sym = thisFrame->m_symbol;
   unsigned size =  sym->isFunction()? 
      sym->getFuncDef()->params() :
      sym->getExtFuncDef()->parameters()->size();
   
   Item* first = prevFrame->m_params;
   int pcount = prevFrame->m_param_count - size;
   if ( pcount < 0 )
      pcount = 0;
   
   if ( i_citem )
   {
      while( size < prevFrame->m_param_count )
      {
         vm->pushParam( first[size] );
         ++size;
      }
      
      // size may be > param count in ext funcs.
      vm->callFrame(*i_citem, pcount );
   }
   else
   {
      CoreArray* arr = new CoreArray( pcount );
      while( size < prevFrame->m_param_count )
      {
         arr->append( first[size] );
         ++size;
      }

      vm->retval( arr );
   }
}


}
}

/* end of param_ext.cpp */