Browse Source

Merge pull request #168 from VasiliyRyabtsev/feature/map-apply-extra

Allow additional parameters in array.map()/array.apply() handler
Alberto Demichelis 7 years ago
parent
commit
9bc87aebfc
2 changed files with 24 additions and 3 deletions
  1. 3 2
      doc/source/reference/language/builtin_functions.rst
  2. 21 1
      squirrel/sqbaselib.cpp

+ 3 - 2
doc/source/reference/language/builtin_functions.rst

@@ -412,12 +412,13 @@ returns the string "(array : pointer)".
 removes all the items from the array
 
 
-.. js:function:: array.map(func(a))
+.. js:function:: array.map(func(item_value, [item_index], [array_ref]))
 
 Creates a new array of the same size. For each element in the original array invokes the function 'func' and assigns the return value of the function to the corresponding element of the newly created array.
+Provided func can accept up to 3 arguments: array item value (required), array item index (optional), reference to array itself (optional).
 
 
-.. js:function:: array.apply(func(a))
+.. js:function:: array.apply(func([item_value, [item_index], [array_ref]))
 
 for each element in the array invokes the function 'func' and replace the original value of the element with the return value of the function.
 

+ 21 - 1
squirrel/sqbaselib.cpp

@@ -596,16 +596,36 @@ static SQInteger array_resize(HSQUIRRELVM v)
 static SQInteger __map_array(SQArray *dest,SQArray *src,HSQUIRRELVM v) {
     SQObjectPtr temp;
     SQInteger size = src->Size();
+    SQObject &closure = stack_get(v, 2);
+    v->Push(closure);
+
+    SQInteger nArgs;
+    if(sq_type(closure) == OT_CLOSURE) {
+        nArgs = _closure(closure)->_function->_nparameters;
+    }
+    else if (sq_type(closure) == OT_NATIVECLOSURE) {
+        SQInteger nParamsCheck = _nativeclosure(closure)->_nparamscheck;
+        if (nParamsCheck > 0)
+            nArgs = nParamsCheck;
+        else // push all params when there is no check or only minimal count set
+            nArgs = 4;
+    }
+
     for(SQInteger n = 0; n < size; n++) {
         src->Get(n,temp);
         v->Push(src);
         v->Push(temp);
-        if(SQ_FAILED(sq_call(v,2,SQTrue,SQFalse))) {
+        if (nArgs >= 3)
+            v->Push(SQObjectPtr(n));
+        if (nArgs >= 4)
+            v->Push(src);
+        if(SQ_FAILED(sq_call(v,nArgs,SQTrue,SQFalse))) {
             return SQ_ERROR;
         }
         dest->Set(n,v->GetUp(-1));
         v->Pop();
     }
+    v->Pop();
     return 0;
 }