Block.st
changeset 9145 c0ccf0f361ba
parent 9042 f41b8427068e
child 9253 a7d4f72181f2
--- a/Block.st	Mon Feb 20 10:49:52 2006 +0100
+++ b/Block.st	Mon Feb 20 10:51:28 2006 +0100
@@ -520,6 +520,11 @@
      a := 0.
      [ 123 / a ] ifError:[self halt]
     "
+!
+
+valueWithPossibleArgs:argArray
+     self halt.
+     ^ self
 ! !
 
 !Block methodsFor:'Compatibility-V''Age'!
@@ -1340,6 +1345,292 @@
      block := [:arg1 :arg2 | Transcript showCR:arg1. Transcript showCR:arg2 ].
      block valueWithOptionalArgument:10 and:20.     
     "
+!
+
+valueWithOptionalArguments:argArray
+    "evaluate the receiver with arguments as required taken from argArray.
+     Only the required number of arguments is taken from argArray or nil;
+     (i.e. argArray may be larger than the required number).
+     If the size of the argArray is smaller than the number of arguments, an error is raised."
+
+    |numArgsProvided a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15|
+
+    (argArray notNil and:[(argArray class ~~ Array) and:[argArray isArray not]]) ifTrue:[
+        ^ self badArgumentArray:argArray
+    ].
+    (argArray size >= nargs) ifFalse:[
+        ^ self wrongNumberOfArguments:argArray size
+    ].
+%{
+    REGISTER OBJFUNC thecode;
+    OBJ home;
+    REGISTER OBJ *ap;
+    OBJ nA;
+    int __numArgsProvided = __intVal(numArgsProvided);
+
+#if defined(THIS_CONTEXT)
+    if (__ISVALID_ILC_LNO(__pilc))
+            __ContextInstPtr(__thisContext)->c_lineno = __ILC_LNO_AS_OBJ(__pilc);
+#endif
+    thecode = __BlockInstPtr(self)->b_code;
+
+    nA = __INST(nargs);
+
+    if (argArray == nil) {
+        ap = 0;  
+    } else {
+        ap = __arrayVal(argArray);   /* nonNil after above test (size is known to be ok) */
+    }
+
+#ifndef NEW_BLOCK_CALL
+    home = __BlockInstPtr(self)->b_home;
+    if (thecode != (OBJFUNC)nil) {
+        /* the most common case (0 args) here (without a switch) */
+
+        if (nA == __mkSmallInteger(0)) {
+            RETURN ( (*thecode)(home) );
+        }
+
+        switch ((INT)(nA)) {
+            default:
+                goto error;
+            case (INT)__mkSmallInteger(15):
+                RETURN ( (*thecode)(home, ap[0], ap[1], ap[2], ap[3], ap[4], ap[5], ap[6], ap[7], ap[8], ap[9], ap[10], ap[11], ap[12], ap[13], ap[14]) );
+            case (INT)__mkSmallInteger(14):
+                RETURN ( (*thecode)(home, ap[0], ap[1], ap[2], ap[3], ap[4], ap[5], ap[6], ap[7], ap[8], ap[9], ap[10], ap[11], ap[12], ap[13]) );
+            case (INT)__mkSmallInteger(13):
+                RETURN ( (*thecode)(home, ap[0], ap[1], ap[2], ap[3], ap[4], ap[5], ap[6], ap[7], ap[8], ap[9], ap[10], ap[11], ap[12]) );
+            case (INT)__mkSmallInteger(12):
+                RETURN ( (*thecode)(home, ap[0], ap[1], ap[2], ap[3], ap[4], ap[5], ap[6], ap[7], ap[8], ap[9], ap[10], ap[11]) );
+            case (INT)__mkSmallInteger(11):
+                RETURN ( (*thecode)(home, ap[0], ap[1], ap[2], ap[3], ap[4], ap[5], ap[6], ap[7], ap[8], ap[9], ap[10]) );
+            case (INT)__mkSmallInteger(10):
+                RETURN ( (*thecode)(home, ap[0], ap[1], ap[2], ap[3], ap[4], ap[5], ap[6], ap[7], ap[8], ap[9]) );
+            case (INT)__mkSmallInteger(9):
+                RETURN ( (*thecode)(home, ap[0], ap[1], ap[2], ap[3], ap[4], ap[5], ap[6], ap[7], ap[8]) );
+            case (INT)__mkSmallInteger(8):
+                RETURN ( (*thecode)(home, ap[0], ap[1], ap[2], ap[3], ap[4], ap[5], ap[6], ap[7]) );
+            case (INT)__mkSmallInteger(7):
+                RETURN ( (*thecode)(home, ap[0], ap[1], ap[2], ap[3], ap[4], ap[5], ap[6]) );
+            case (INT)__mkSmallInteger(6):
+                RETURN ( (*thecode)(home, ap[0], ap[1], ap[2], ap[3], ap[4], ap[5]) );
+            case (INT)__mkSmallInteger(5):
+                RETURN ( (*thecode)(home, ap[0], ap[1], ap[2], ap[3], ap[4]) );
+            case (INT)__mkSmallInteger(4):
+                RETURN ( (*thecode)(home, ap[0], ap[1], ap[2], ap[3]) );
+            case (INT)__mkSmallInteger(3):
+                RETURN ( (*thecode)(home, ap[0], ap[1], ap[2]) );
+            case (INT)__mkSmallInteger(2):
+                RETURN ( (*thecode)(home, ap[0], ap[1]) );
+            case (INT)__mkSmallInteger(1):
+                RETURN ( (*thecode)(home, ap[0]) );
+            case (INT)__mkSmallInteger(0):
+                RETURN ( (*thecode)(home) );
+                break;
+        }
+    }
+#endif
+
+    if (nA != __mkSmallInteger(0)) {
+        ap = __arrayVal(argArray);   /* nonNil after above test (size is known to be ok) */
+        switch ((INT)nA) {
+            default:
+                goto error;
+            case (INT)__mkSmallInteger(15):
+                a15 = ap[14];
+            case (INT)__mkSmallInteger(14):
+                a14 = ap[13];
+            case (INT)__mkSmallInteger(13):
+                a13 = ap[12];
+            case (INT)__mkSmallInteger(12):
+                a12 = ap[11];
+            case (INT)__mkSmallInteger(11):
+                a11 = ap[10];
+            case (INT)__mkSmallInteger(10):
+                a10 = ap[9];
+            case (INT)__mkSmallInteger(9):
+                a9 = ap[8];
+            case (INT)__mkSmallInteger(8):
+                a8 = ap[7];
+            case (INT)__mkSmallInteger(7):
+                a7 = ap[6];
+            case (INT)__mkSmallInteger(6):
+                a6 = ap[5];
+            case (INT)__mkSmallInteger(5):
+                a5 = ap[4];
+            case (INT)__mkSmallInteger(4):
+                a4 = ap[3];
+            case (INT)__mkSmallInteger(3):
+                a3 = ap[2];
+            case (INT)__mkSmallInteger(2):
+                a2 = ap[1];
+            case (INT)__mkSmallInteger(1):
+                a1 = ap[0];
+            case (INT)__mkSmallInteger(0):
+                break;
+        }
+    }
+#ifdef NEW_BLOCK_CALL
+    if (thecode != (OBJFUNC)nil) {
+        RETURN ( (*thecode)(self, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15) );
+    }
+# ifdef PASS_ARG_POINTER
+    RETURN ( __interpret(self, __intVal(nA), nil, nil, nil, nil, &a1) );
+# else
+    RETURN ( __interpret(self, __intVal(nA), nil, nil, nil, nil, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15) );
+# endif
+
+#else
+
+# ifdef PASS_ARG_POINTER
+    RETURN ( __interpret(self, __intVal(nA), nil, home, nil, nil, &a1) );
+# else
+    RETURN ( __interpret(self, __intVal(nA), nil, home, nil, nil, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15) );
+# endif
+
+#endif
+
+error: ;
+%}.
+    "
+     the above code only supports up-to 15 arguments
+    "
+    ^ ArgumentError
+        raiseRequestWith:self
+        errorString:'only blocks with up-to 15 arguments supported'
+!
+
+valueWithPossibleArguments:argArray
+    "evaluate the receiver with arguments as required taken from argArray.
+     If argArray provides less than the required number of arguments, 
+     nil is assumed for any remaining argument.
+     (i.e. argArray may be smaller than the required number).
+     Only the required number of arguments is taken from argArray or nil;
+     (i.e. argArray may be larger than the required number)."
+
+    |numArgsProvided a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15|
+
+    (argArray notNil and:[(argArray class ~~ Array) and:[argArray isArray not]]) ifTrue:[
+        ^ self badArgumentArray:argArray
+    ].
+    numArgsProvided := argArray size.
+%{
+    REGISTER OBJFUNC thecode;
+    OBJ home;
+    REGISTER OBJ *ap;
+    OBJ nA;
+    int __numArgsProvided = __intVal(numArgsProvided);
+
+#if defined(THIS_CONTEXT)
+    if (__ISVALID_ILC_LNO(__pilc))
+            __ContextInstPtr(__thisContext)->c_lineno = __ILC_LNO_AS_OBJ(__pilc);
+#endif
+    thecode = __BlockInstPtr(self)->b_code;
+
+    nA = __INST(nargs);
+
+    if (argArray == nil) {
+        ap = 0;  
+    } else {
+        ap = __arrayVal(argArray);   /* nonNil after above test (size is known to be ok) */
+    }
+    switch (__numArgsProvided) {
+        default:
+        case 15: a15 = ap[14];
+        case 14: a14 = ap[13];
+        case 13: a13 = ap[12];
+        case 12: a12 = ap[11];
+        case 11: a11 = ap[10];
+        case 10: a10 = ap[9];
+        case 9: a9 = ap[8];
+        case 8: a8 = ap[7];
+        case 7: a7 = ap[6];
+        case 6: a6 = ap[5];
+        case 5: a5 = ap[4];
+        case 4: a4 = ap[3];
+        case 3: a3 = ap[2];
+        case 2: a2 = ap[1];
+        case 1: a1 = ap[0];
+        case 0: ;
+    }
+
+#ifndef NEW_BLOCK_CALL
+    home = __BlockInstPtr(self)->b_home;
+    if (thecode != (OBJFUNC)nil) {
+        /* the most common case (0 args) here (without a switch) */
+
+        if (nA == __mkSmallInteger(0)) {
+            RETURN ( (*thecode)(home) );
+        }
+
+        switch ((INT)(nA)) {
+            default:
+                goto error;
+            case (INT)__mkSmallInteger(15):
+                RETURN ( (*thecode)(home, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15) );
+            case (INT)__mkSmallInteger(14):
+                RETURN ( (*thecode)(home, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14) );
+            case (INT)__mkSmallInteger(13):
+                RETURN ( (*thecode)(home, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13) );
+            case (INT)__mkSmallInteger(12):
+                RETURN ( (*thecode)(home, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12) );
+            case (INT)__mkSmallInteger(11):
+                RETURN ( (*thecode)(home, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11) );
+            case (INT)__mkSmallInteger(10):
+                RETURN ( (*thecode)(home, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) );
+            case (INT)__mkSmallInteger(9):
+                RETURN ( (*thecode)(home, a1, a2, a3, a4, a5, a6, a7, a8, a9) );
+            case (INT)__mkSmallInteger(8):
+                RETURN ( (*thecode)(home, a1, a2, a3, a4, a5, a6, a7, a8) );
+            case (INT)__mkSmallInteger(7):
+                RETURN ( (*thecode)(home, a1, a2, a3, a4, a5, a6, a7) );
+            case (INT)__mkSmallInteger(6):
+                RETURN ( (*thecode)(home, a1, a2, a3, a4, a5, a6) );
+            case (INT)__mkSmallInteger(5):
+                RETURN ( (*thecode)(home, a1, a2, a3, a4, a5) );
+            case (INT)__mkSmallInteger(4):
+                RETURN ( (*thecode)(home, a1, a2, a3, a4) );
+            case (INT)__mkSmallInteger(3):
+                RETURN ( (*thecode)(home, a1, a2, a3) );
+            case (INT)__mkSmallInteger(2):
+                RETURN ( (*thecode)(home, a1, a2) );
+            case (INT)__mkSmallInteger(1):
+                RETURN ( (*thecode)(home, a1) );
+            case (INT)__mkSmallInteger(0):
+                RETURN ( (*thecode)(home) );
+                break;
+        }
+    }
+#endif
+
+#ifdef NEW_BLOCK_CALL
+    if (thecode != (OBJFUNC)nil) {
+        RETURN ( (*thecode)(self, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15) );
+    }
+# ifdef PASS_ARG_POINTER
+    RETURN ( __interpret(self, __intVal(nA), nil, nil, nil, nil, &a1) );
+# else
+    RETURN ( __interpret(self, __intVal(nA), nil, nil, nil, nil, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15) );
+# endif
+
+#else
+
+# ifdef PASS_ARG_POINTER
+    RETURN ( __interpret(self, __intVal(nA), nil, home, nil, nil, &a1) );
+# else
+    RETURN ( __interpret(self, __intVal(nA), nil, home, nil, nil, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15) );
+# endif
+
+#endif
+
+error: ;
+%}.
+    "
+     the above code only supports up-to 15 arguments
+    "
+    ^ ArgumentError
+        raiseRequestWith:self
+        errorString:'only blocks with up-to 15 arguments supported'
 ! !
 
 !Block methodsFor:'exception handling'!
@@ -2265,7 +2556,7 @@
 !Block class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libbasic/Block.st,v 1.147 2005-12-21 18:34:28 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libbasic/Block.st,v 1.148 2006-02-20 09:51:28 cg Exp $'
 ! !
 
 Block initialize!