G:/ScriptBasic/source/commands/let.c

Go to the documentation of this file.
00001 /*let.c
00002 
00003 --GNU LGPL
00004 This library is free software; you can redistribute it and/or
00005 modify it under the terms of the GNU Lesser General Public
00006 License as published by the Free Software Foundation; either
00007 version 2.1 of the License, or (at your option) any later version.
00008 
00009 This library is distributed in the hope that it will be useful,
00010 but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012 Lesser General Public License for more details.
00013 
00014 You should have received a copy of the GNU Lesser General Public
00015 License along with this library; if not, write to the Free Software
00016 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017 
00018 */
00019 
00020 #include <stdlib.h>
00021 #include <stdio.h>
00022 #include <limits.h>
00023 
00024 #include <math.h>
00025 #include "../command.h"
00026 
00027 /* this function is defined in mathops.c */
00028 long *RaiseError(pExecuteObject pEo);
00029 
00030 /*POD
00031 =H Commands that assign values to variables
00032 
00033 This file contains commands that assign value to variables.
00034 
00035 CUT*/
00036 
00049 COMMAND(LET)
00050 #if NOTIMP_LET
00051 NOTIMPLEMENTED;
00052 #else
00053   VARIABLE ExpressionResult,ArrayCopyTo;
00054   LEFTVALUE LetThisVariable;
00055   long refcount;
00056 
00057   /* we get the pointer to the variable that points to the value */
00058   LetThisVariable = EVALUATELEFTVALUE(PARAMETERNODE);
00059   ASSERTOKE;
00060 
00061   /* if this points to a reference value then we search the "real" variable
00062      to modify */
00063   DEREFERENCE(LetThisVariable);
00064 
00065   /* get the next parameter of the command, which is the expression */
00066   NEXTPARAMETER;
00067 
00068   /* Evaluate the expression, and if the expression is simple create a copy of the result
00069      to be sure that no two variables point to the same value */
00070   ExpressionResult = execute_Evaluate(pEo,PARAMETERNODE,_pThisCommandMortals,&iErrorCode,1);
00071   ASSERTOKE;
00072 
00073   /* If this is not an expression then copy the value. */
00074   if( ExpressionResult == NULL || TYPE(ExpressionResult) != VTYPE_ARRAY ){
00075     memory_ReplaceVariable(pEo->pMo,LetThisVariable,ExpressionResult,_pThisCommandMortals,1);
00076     RETURN;
00077     }
00078 
00079   /* If this is an array then copy the array itself. All elements, but the references will remain
00080      references. */
00081   ArrayCopyTo = memory_CopyArray(pEo->pMo,ExpressionResult);
00082   if( ArrayCopyTo == NULL )ERROR(COMMAND_ERROR_MEMORY_LOW);
00083   memory_ReplaceVariable(pEo->pMo,LetThisVariable,ArrayCopyTo,_pThisCommandMortals,0);
00084 #endif
00085 END
00086 
00087 COMMAND(LLET)
00088 END
00089 
00100 COMMAND(SWAP)
00101 #if NOTIMP_SWAP
00102 NOTIMPLEMENTED;
00103 #else
00104   LEFTVALUE VariableA,VariableB;
00105   pFixSizeMemoryObject VSWAP;
00106   long refcount;
00107 
00108   /* we get the pointer to the variable that points to the value */
00109   VariableA = EVALUATELEFTVALUE(PARAMETERNODE);
00110   ASSERTOKE;
00111 
00112   /* if this points to a reference value then we search the "real" variable
00113      to modify */
00114   DEREFERENCE(VariableA);
00115 
00116   /* get the next parameter of the command, which is the other variable */
00117   NEXTPARAMETER;
00118 
00119   /* we get the pointer to the variable that points to the value */
00120   VariableB = EVALUATELEFTVALUE(PARAMETERNODE);
00121   ASSERTOKE;
00122 
00123   /* if this points to a reference value then we search the "real" variable
00124      to modify */
00125   DEREFERENCE(VariableB);
00126 
00127   VSWAP = *VariableA;
00128   *VariableA = *VariableB;
00129   *VariableB = VSWAP;
00130 
00131 #endif
00132 END
00133 
00144 COMMAND(REF)
00145 #if NOTIMP_REF
00146 NOTIMPLEMENTED;
00147 #else
00148   LEFTVALUE v1,v2;
00149   VARIABLE NewValue;
00150   long refcount;
00151   int iError;
00152 
00153   /* we get the pointer to the variable that points to the value */
00154   v1 = EVALUATELEFTVALUE(PARAMETERNODE);
00155   ASSERTOKE;
00156 
00157   /* Dereference the variable to set the variable referenced by the actual variable
00158      to be a reference to another variable. In case this is not what the programmer
00159      wants then he/she can undef the variable first. */
00160   DEREFERENCE(v1);
00161 
00162   /* get the next parameter of the command, which is the expression */
00163   NEXTPARAMETER;
00164 
00165   /* Evaluate the expression, and if the expression is simple create a copy of the result
00166      to be sure that no two variables point to the same value */
00167   v2 = EVALUATELEFTVALUE_A(PARAMETERNODE);
00168   ASSERTOKE;
00169   DEREFERENCE(v2);
00170 
00171   /* capture it here, this is a harmless action, no v1 was changed or left in an unusable state
00172      */
00173   if( v1 == v2 )RETURN;
00174 
00175   NewValue = memory_NewRef(pEo->pMo);
00176   if( *v1 ){
00177     NewValue->link.rprev = (*v1)->link.rprev;
00178     (*v1)->link.rprev = NULL;
00179     }else{
00180     NewValue->link.rprev = NULL;
00181     }
00182   if( *v1 )memory_ReleaseVariable(pEo->pMo,*v1);
00183 
00184   *v1 = NewValue;
00185 
00186   iError = memory_SetRef(pEo->pMo,v1,v2);
00187 
00188   if( iError )ERROR(iError);
00189 #endif
00190 END
00191 
00233 COMMAND(CUNDEF)
00234 #if NOTIMP_CUNDEF
00235 NOTIMPLEMENTED;
00236 #else
00237 
00238   NODE nItem;
00239   LEFTVALUE LetThisVariable;
00240 
00241   nItem = PARAMETERNODE;
00242   while( nItem ){
00243 
00244     LetThisVariable = EVALUATELEFTVALUE_A(CAR(nItem));
00245     ASSERTOKE;
00246     /* do NOT dereference by definition */
00247     if( *LetThisVariable == NULL ){
00248       nItem = CDR(nItem);
00249       continue;
00250       }
00251 
00252     memory_ReleaseVariable(pEo->pMo,*LetThisVariable);
00253     *LetThisVariable = NULL;
00254     nItem = CDR(nItem);
00255     }
00256 
00257 #endif
00258 END
00259 
00260 /*BYVAL
00261 =section misc
00262 
00263 Convert an argument variable to local. Saying
00264 
00265 =verbatim
00266 SUB fun(a,b,c)
00267 BYVAL a,b
00268 
00269  ....
00270 
00271 END SUB
00272 =noverbatim
00273 
00274 will make the variables T<a> and T<b> truly local, and assigning a value to them will not alter the variable that was passed as parameter when calling T<fun>.
00275 
00276 This keyword can also be used as an operator, like
00277 
00278 =verbatim
00279 CALL fun(BYVAL a, BYVAL B)
00280 =noverbatim
00281 
00282 that will pass the variables T<a> and T<b> to the function by value instead of reference.
00283 
00284 =details
00285 
00286 T<BYVAL> as an operator actually does nothing but returns the value of its argument.
00287 
00288 When T<BYVAL> is used as a command it assigns the value of the variable to the local variable that may have been a reference to a global variable before that.
00289 */
00290 COMMAND(CBYVAL)
00291 #if NOTIMP_CBYVAL
00292 NOTIMPLEMENTED;
00293 #else
00294 
00295   NODE nItem;
00296   LEFTVALUE LetThisVariable;
00297   VARIABLE NewValue;
00298   unsigned long refcount;
00299 
00300   nItem = PARAMETERNODE;
00301   while( nItem ){
00302 
00303     LetThisVariable = EVALUATELEFTVALUE_A(CAR(nItem));
00304     ASSERTOKE;
00305 
00306     if( *LetThisVariable == NULL || TYPE(*LetThisVariable) != VTYPE_REF ){
00307       nItem = CDR(nItem);
00308       continue;
00309       }
00310     NewValue = *LetThisVariable;
00311     refcount = pEo->pMo->maxderef;
00312     while( NewValue && TYPE(NewValue) == VTYPE_REF ){
00313       NewValue = *(NewValue->Value.aValue);
00314       if( ! refcount-- )ERROR(COMMAND_ERROR_CIRCULAR);
00315       }
00316     if( NewValue ){
00317       NewValue = memory_DupImmortal(pEo->pMo,NewValue,&iErrorCode);
00318       }
00319     if( *LetThisVariable )
00320       memory_ReleaseVariable(pEo->pMo,*LetThisVariable); /* release the ref value */
00321     *LetThisVariable = NewValue;
00322     nItem = CDR(nItem);
00323     }
00324 
00325 #endif
00326 END
00327 
00341 COMMAND(LETM)
00342 #if NOTIMP_LETM
00343 NOTIMPLEMENTED;
00344 #else
00345   VARIABLE ExpressionResult;
00346   VARIABLE Op1,Op2;
00347   LEFTVALUE LetThisVariable;
00348   long refcount;
00349   int bResultIsBig;
00350   long Lop2;
00351   double dResult;
00352   long lResult;
00353 
00354   /* we get the pointer to the variable that points to the value */
00355   LetThisVariable = EVALUATELEFTVALUE(PARAMETERNODE);
00356   ASSERTOKE;
00357 
00358   /* if this points to a reference value then we search the "real" variable
00359      to modify */
00360   DEREFERENCE(LetThisVariable);
00361 
00362   /* get the next parameter of the command, which is the expression */
00363   NEXTPARAMETER;
00364 
00365   /* Evaluate the expression, and if the expression is simple create a copy of the result
00366      to be sure that no two variables point to the same value */
00367   Op2 = execute_Evaluate(pEo,PARAMETERNODE,_pThisCommandMortals,&iErrorCode,0);
00368   ASSERTOKE;
00369 
00370   if( memory_Type(*LetThisVariable) == VTYPE_DOUBLE ){
00371     dResult = DOUBLEVALUE(*LetThisVariable) - GETDOUBLEVALUE(Op2);
00372     lResult = (long)dResult;
00373     if( dResult == (double)lResult ){
00374       ExpressionResult = NEWMORTALLONG;
00375       ASSERTNULL(ExpressionResult);
00376       LONGVALUE(ExpressionResult) = lResult;
00377       IMMORTALIZE(ExpressionResult);
00378       if( *LetThisVariable )memory_ReleaseVariable(pEo->pMo,*LetThisVariable);
00379       *LetThisVariable = ExpressionResult;
00380       RETURN;
00381       }
00382     DOUBLEVALUE(*LetThisVariable) = dResult;
00383     RETURN;
00384     }
00385 
00386   /* we assume that the result is not big so long as long it turns out to be */
00387   bResultIsBig = 0;
00388   /* If the variable is long and the expression is convertable to long (aka not double) then
00389      there is no reason to release the variable and allocate a new one to hold the resulting 
00390      long. The result is stored in the same place as the original value.
00391      This code could be left out but it increases the interpreter speed. I did measure. */
00392   if( memory_Type(*LetThisVariable) == VTYPE_LONG &&
00393       (memory_Type(Op2) == VTYPE_LONG || (memory_Type(Op2) == VTYPE_STRING && ISSTRINGINTEGER(Op2)) )){
00394     Lop2 = GETLONGVALUE(Op2);
00395     dResult = ((double)LONGVALUE(*LetThisVariable)) - ((double)Lop2);
00396     if( dResult <= ((double)LONG_MAX) && dResult >= ((double)LONG_MIN) ){
00397       LONGVALUE(*LetThisVariable) -= Lop2;
00398       RETURN;
00399       }
00400     bResultIsBig = 1;
00401     }
00402 
00403   Op1 = *LetThisVariable;
00404 
00405       /* if the numbers are integer, but the result overflows plus or minus */
00406   if( bResultIsBig ||
00407      /* if any of the arguments is double then the result is double */
00408      (memory_Type(Op1) == VTYPE_DOUBLE || memory_Type(Op2) == VTYPE_DOUBLE) ||
00409 
00410      /* if the first argument is string and is NOT integer */
00411      ( memory_Type(Op1) == VTYPE_STRING && !ISSTRINGINTEGER(Op1)) ||
00412 
00413      /* if the second argument is string and is NOT integer */
00414      ( memory_Type(Op2) == VTYPE_STRING && !ISSTRINGINTEGER(Op2))
00415      ){
00416     dResult = GETDOUBLEVALUE(Op1) - GETDOUBLEVALUE(Op2);
00417     lResult = (long)dResult;
00418     if( dResult == (double)lResult ){
00419       ExpressionResult = NEWMORTALLONG;
00420       ASSERTNULL(ExpressionResult);
00421       LONGVALUE(ExpressionResult) = lResult;
00422       }else{
00423       ExpressionResult = NEWMORTALDOUBLE;
00424       ASSERTNULL(ExpressionResult);
00425       DOUBLEVALUE(ExpressionResult) = dResult;
00426       }
00427     }else{
00428     ExpressionResult = NEWMORTALLONG;
00429     ASSERTNULL(ExpressionResult);
00430     LONGVALUE(ExpressionResult) = GETLONGVALUE(Op1) - GETLONGVALUE(Op2);
00431     }
00432 
00433   /* if the result of the expression is not undef then immortalize */
00434   if( ExpressionResult ){
00435     /* we immortalize the new variable if it is a variable and not NULL meaning undef */
00436     IMMORTALIZE(ExpressionResult);
00437     }
00438 
00439   /* if this variable had value assigned to it then release that value */
00440   if( *LetThisVariable )memory_ReleaseVariable(pEo->pMo,*LetThisVariable);
00441 
00442   /* and finally assign the code to the variable */
00443   *LetThisVariable = ExpressionResult;
00444 
00445 #endif
00446 END
00447 
00459 COMMAND(LETP)
00460 #if NOTIMP_LETP
00461 NOTIMPLEMENTED;
00462 #else
00463   VARIABLE ExpressionResult;
00464   VARIABLE Op1,Op2;
00465   LEFTVALUE LetThisVariable;
00466   long refcount;
00467   int bResultIsBig;
00468   long Lop2;
00469   double dResult;
00470   long lResult;
00471 
00472   /* we get the pointer to the variable that points to the value */
00473   LetThisVariable = EVALUATELEFTVALUE(PARAMETERNODE);
00474   ASSERTOKE;
00475 
00476   /* if this points to a reference value then we search the "real" variable
00477      to modify */
00478   DEREFERENCE(LetThisVariable);
00479 
00480   /* get the next parameter of the command, which is the expression */
00481   NEXTPARAMETER;
00482 
00483   /* Evaluate the expression, and if the expression is simple create a copy of the result
00484      to be sure that no two variables point to the same value */
00485   Op2 = execute_Evaluate(pEo,PARAMETERNODE,_pThisCommandMortals,&iErrorCode,0);
00486   ASSERTOKE;
00487 
00488   if( memory_Type(*LetThisVariable) == VTYPE_DOUBLE ){
00489     dResult = DOUBLEVALUE(*LetThisVariable) + GETDOUBLEVALUE(Op2);
00490     lResult = (long)dResult;
00491     if( dResult == (double)lResult ){
00492       ExpressionResult = NEWMORTALLONG;
00493       ASSERTNULL(ExpressionResult);
00494       LONGVALUE(ExpressionResult) = lResult;
00495       IMMORTALIZE(ExpressionResult);
00496       if( *LetThisVariable )memory_ReleaseVariable(pEo->pMo,*LetThisVariable);
00497       *LetThisVariable = ExpressionResult;
00498       RETURN;
00499       }
00500     DOUBLEVALUE(*LetThisVariable) = dResult;
00501     RETURN;
00502     }
00503 
00504   /* we assume that the result is not big so long as long it turns out to be */
00505   bResultIsBig = 0;
00506   /* If the variable is long and the expression is convertable to long (aka not double) then
00507      there is no reason to release the variable and allocate a new one to hold the resulting 
00508      long. The result is stored in the same place as the original value.
00509      This code could be left out but it increases the interpreter speed. I did measure. */
00510   if( memory_Type(*LetThisVariable) == VTYPE_LONG &&
00511       (memory_Type(Op2) == VTYPE_LONG || (memory_Type(Op2) == VTYPE_STRING && ISSTRINGINTEGER(Op2)) )){
00512     Lop2 = GETLONGVALUE(Op2);
00513     dResult = ((double)Lop2) + ((double)LONGVALUE(*LetThisVariable));
00514     if( dResult <= ((double)LONG_MAX) && dResult >= ((double)LONG_MIN) ){
00515       LONGVALUE(*LetThisVariable) += Lop2;
00516       RETURN;
00517       }
00518     bResultIsBig = 1;
00519     }
00520   Op1 = *LetThisVariable;
00521 
00522       /* if the numbers are integer, but the result overflows plus or minus */
00523   if( bResultIsBig ||
00524      /* if any of the arguments is double then the result is double */
00525      (memory_Type(Op1) == VTYPE_DOUBLE || memory_Type(Op2) == VTYPE_DOUBLE) ||
00526 
00527      /* if the first argument is string and is NOT integer */
00528      ( memory_Type(Op1) == VTYPE_STRING && !ISSTRINGINTEGER(Op1)) ||
00529 
00530      /* if the second argument is string and is NOT integer */
00531      ( memory_Type(Op2) == VTYPE_STRING && !ISSTRINGINTEGER(Op2))
00532      ){
00533     dResult = GETDOUBLEVALUE(Op1) + GETDOUBLEVALUE(Op2);
00534     lResult = (long)dResult;
00535     if( dResult == (double)lResult ){
00536       ExpressionResult = NEWMORTALLONG;
00537       ASSERTNULL(ExpressionResult);
00538       LONGVALUE(ExpressionResult) = lResult;
00539       }else{
00540       ExpressionResult = NEWMORTALDOUBLE;
00541       ASSERTNULL(ExpressionResult);
00542       DOUBLEVALUE(ExpressionResult) = dResult;
00543       }
00544     }else{
00545     ExpressionResult = NEWMORTALLONG;
00546     ASSERTNULL(ExpressionResult);
00547     LONGVALUE(ExpressionResult) = GETLONGVALUE(Op1) + GETLONGVALUE(Op2);
00548     }
00549 
00550   /* if the result of the expression is not undef then immortalize */
00551   if( ExpressionResult ){
00552     /* we immortalize the new variable if it is a variable and not NULL meaning undef */
00553     IMMORTALIZE(ExpressionResult);
00554     }
00555 
00556   /* if this variable had value assigned to it then release that value */
00557   if( *LetThisVariable )memory_ReleaseVariable(pEo->pMo,*LetThisVariable);
00558 
00559   /* and finally assign the code to the variable */
00560   *LetThisVariable = ExpressionResult;
00561 
00562 #endif
00563 END
00564 
00576 COMMAND(LETS)
00577 #if NOTIMP_LETS
00578 NOTIMPLEMENTED;
00579 #else
00580   VARIABLE ExpressionResult;
00581   VARIABLE Op1,Op2;
00582   LEFTVALUE LetThisVariable;
00583   long refcount;
00584   int bResultIsBig;
00585   long Lop2;
00586   double dResult;
00587   long lResult;
00588 
00589   /* we get the pointer to the variable that points to the value */
00590   LetThisVariable = EVALUATELEFTVALUE(PARAMETERNODE);
00591   ASSERTOKE;
00592 
00593   /* if this points to a reference value then we search the "real" variable
00594      to modify */
00595   DEREFERENCE(LetThisVariable);
00596 
00597   /* get the next parameter of the command, which is the expression */
00598   NEXTPARAMETER;
00599 
00600   /* Evaluate the expression, and if the expression is simple create a copy of the result
00601      to be sure that no two variables point to the same value */
00602   Op2 = execute_Evaluate(pEo,PARAMETERNODE,_pThisCommandMortals,&iErrorCode,0);
00603   ASSERTOKE;
00604 
00605   /* If the variable is double then the final value is double and thus there is no reason to
00606      release the variable and allocate a new one to hold the resulting double. The result is 
00607      stored in the same place as the original value. This code could be left out but it
00608      increases the interpreter speed. I did measure. */
00609   if( memory_Type(*LetThisVariable) == VTYPE_DOUBLE ){
00610     dResult = DOUBLEVALUE(*LetThisVariable) * GETDOUBLEVALUE(Op2);
00611     lResult = (long)dResult;
00612     if( dResult == (double)lResult ){
00613       ExpressionResult = NEWMORTALLONG;
00614       ASSERTNULL(ExpressionResult);
00615       LONGVALUE(ExpressionResult) = lResult;
00616       IMMORTALIZE(ExpressionResult);
00617       if( *LetThisVariable )memory_ReleaseVariable(pEo->pMo,*LetThisVariable);
00618       *LetThisVariable = ExpressionResult;
00619       RETURN;
00620       }
00621     DOUBLEVALUE(*LetThisVariable) = dResult;
00622     RETURN;
00623     }
00624 
00625   /* we assume that the result is not big so long as long it turns out to be */
00626   bResultIsBig = 0;
00627   /* If the variable is long and the expression is convertable to long (aka not double) then
00628      there is no reason to release the variable and allocate a new one to hold the resulting 
00629      long. The result is stored in the same place as the original value.
00630      This code could be left out but it increases the interpreter speed. I did measure. */
00631   if( memory_Type(*LetThisVariable) == VTYPE_LONG &&
00632       (memory_Type(Op2) == VTYPE_LONG || (memory_Type(Op2) == VTYPE_STRING && ISSTRINGINTEGER(Op2)) )){
00633     Lop2 = GETLONGVALUE(Op2);
00634     dResult = ((double)Lop2) * ((double)LONGVALUE(*LetThisVariable));
00635     if( dResult <= ((double)LONG_MAX) && dResult >= ((double)LONG_MIN) ){
00636       LONGVALUE(*LetThisVariable) *= Lop2;
00637       RETURN;
00638       }
00639     bResultIsBig = 1;
00640     }
00641 
00642   Op1 = *LetThisVariable;
00643 
00644       /* if the numbers are integer, but the result overflows plus or minus */
00645   if( bResultIsBig ||
00646      /* if any of the arguments is double then the result is double */
00647      (memory_Type(Op1) == VTYPE_DOUBLE || memory_Type(Op2) == VTYPE_DOUBLE) ||
00648 
00649      /* if the first argument is string and is NOT integer */
00650      ( memory_Type(Op1) == VTYPE_STRING && !ISSTRINGINTEGER(Op1)) ||
00651 
00652      /* if the second argument is string and is NOT integer */
00653      ( memory_Type(Op2) == VTYPE_STRING && !ISSTRINGINTEGER(Op2))
00654      ){
00655     dResult = GETDOUBLEVALUE(Op1) * GETDOUBLEVALUE(Op2);
00656     lResult = (long)dResult;
00657     if( dResult == (double)lResult ){
00658       ExpressionResult = NEWMORTALLONG;
00659       ASSERTNULL(ExpressionResult);
00660       LONGVALUE(ExpressionResult) = lResult;
00661       }else{
00662       ExpressionResult = NEWMORTALDOUBLE;
00663       ASSERTNULL(ExpressionResult);
00664       DOUBLEVALUE(ExpressionResult) = dResult;
00665       }
00666     }else{
00667     ExpressionResult = NEWMORTALLONG;
00668     ASSERTNULL(ExpressionResult);
00669     LONGVALUE(ExpressionResult) = GETLONGVALUE(Op1) * GETLONGVALUE(Op2);
00670     }
00671 
00672   /* if the result of the expression is not undef then immortalize */
00673   if( ExpressionResult ){
00674     /* we immortalize the new variable if it is a variable and not NULL meaning undef */
00675     IMMORTALIZE(ExpressionResult);
00676     }
00677 
00678   /* if this variable had value assigned to it then release that value */
00679   if( *LetThisVariable )memory_ReleaseVariable(pEo->pMo,*LetThisVariable);
00680 
00681   /* and finally assign the code to the variable */
00682   *LetThisVariable = ExpressionResult;
00683 
00684 #endif
00685 END
00686 
00698 COMMAND(LETD)
00699 #if NOTIMP_LETD
00700 NOTIMPLEMENTED;
00701 #else
00702   VARIABLE ExpressionResult;
00703   VARIABLE Op1,Op2;
00704   LEFTVALUE LetThisVariable;
00705   long refcount;
00706   long lop2;
00707   double dResult;
00708   long lResult;
00709 
00710   /* we get the pointer to the variable that points to the value */
00711   LetThisVariable = EVALUATELEFTVALUE(PARAMETERNODE);
00712   ASSERTOKE;
00713 
00714   /* if this points to a reference value then we search the "real" variable
00715      to modify */
00716   DEREFERENCE(LetThisVariable);
00717 
00718   /* get the next parameter of the command, which is the expression */
00719   NEXTPARAMETER;
00720 
00721   /* Evaluate the expression, and if the expression is simple create a copy of the result
00722      to be sure that no two variables point to the same value */
00723   Op2 = execute_Evaluate(pEo,PARAMETERNODE,_pThisCommandMortals,&iErrorCode,0);
00724   ASSERTOKE;
00725 
00726   /* If the variable is double then the final value is double and thus there is no reason to
00727      release the variable and allocate a new one to hold the resulting double. The result is 
00728      stored in the same place as the original value. This code could be left out but it
00729      increases the interpreter speed. I did measure. */
00730   if( memory_Type(*LetThisVariable) == VTYPE_DOUBLE ){
00731     if( memory_Type(Op2) != VTYPE_DOUBLE )Op2 = CONVERT2DOUBLE(Op2);
00732     if( DOUBLEVALUE(Op2) == 0.0 ){
00733       if( *LetThisVariable )memory_ReleaseVariable(pEo->pMo,*LetThisVariable);
00734       *LetThisVariable = NULL;
00735       if((*RaiseError(pEo))&1 ){
00736         ERROR(COMMAND_ERROR_DIV);
00737         }
00738       RETURN;
00739       }
00740     dResult = DOUBLEVALUE(*LetThisVariable) / DOUBLEVALUE(Op2);
00741     lResult = (long)dResult;
00742     /* if the result can be stored as a long then we do so */
00743     if( dResult == (double)lResult ){
00744       if( *LetThisVariable )memory_ReleaseVariable(pEo->pMo,*LetThisVariable);
00745       *LetThisVariable = NULL;
00746       ExpressionResult = NEWMORTALLONG;
00747       ASSERTNULL(ExpressionResult)
00748       LONGVALUE(ExpressionResult) = lResult;
00749       IMMORTALIZE(ExpressionResult);
00750       *LetThisVariable = ExpressionResult;
00751       RETURN;
00752       }
00753     DOUBLEVALUE(*LetThisVariable) = dResult;
00754     RETURN;
00755     }
00756 
00757   if( memory_Type(*LetThisVariable) == VTYPE_LONG &&
00758       (memory_Type(Op2) == VTYPE_LONG || (memory_Type(Op2) == VTYPE_STRING && ISSTRINGINTEGER(Op2)) )){
00759     lop2 = GETLONGVALUE(Op2);
00760     if( lop2 == 0 ){
00761       if( *LetThisVariable )memory_ReleaseVariable(pEo->pMo,*LetThisVariable);
00762       *LetThisVariable = NULL;
00763       if((*RaiseError(pEo))&1 ){
00764         ERROR(COMMAND_ERROR_DIV);
00765         }
00766       RETURN;
00767       }
00768     if( LONGVALUE(*LetThisVariable) % lop2 == 0 ){
00769       LONGVALUE(*LetThisVariable) /= lop2;
00770       RETURN;
00771       }
00772     }
00773 
00774   Op1 = *LetThisVariable;
00775 
00776   /* if any of the arguments is double then the result is double */
00777   if( (memory_Type(Op1) == VTYPE_DOUBLE || memory_Type(Op2) == VTYPE_DOUBLE) ||
00778 
00779      /* if the first argument is string and is NOT integer */
00780      ( memory_Type(Op1) == VTYPE_STRING && !ISSTRINGINTEGER(Op1)) ||
00781 
00782      /* if the second argument is string and is NOT integer */
00783      ( memory_Type(Op2) == VTYPE_STRING && !ISSTRINGINTEGER(Op2))
00784      ){
00785     Op1 = CONVERT2DOUBLE(Op1);
00786     Op2 = CONVERT2DOUBLE(Op2);
00787     if( DOUBLEVALUE(Op2) == 0.0 ){
00788       if((*RaiseError(pEo))&1 ){
00789         ERROR(COMMAND_ERROR_DIV);
00790         }
00791       ExpressionResult = NULL;
00792     }else{
00793       ExpressionResult = NEWMORTALDOUBLE;
00794       ASSERTNULL(ExpressionResult);
00795       DOUBLEVALUE(ExpressionResult) = DOUBLEVALUE(Op1) / DOUBLEVALUE(Op2);
00796       }
00797     }else{
00798     Op1 = CONVERT2LONG(Op1);
00799     Op2 = CONVERT2LONG(Op2);
00800     if( LONGVALUE(Op2) == 0 ){
00801       if((*RaiseError(pEo))&1 ){
00802         ERROR(COMMAND_ERROR_DIV);
00803         }
00804       ExpressionResult = NULL;
00805       }else{
00806       if( LONGVALUE(Op1) % LONGVALUE(Op2) ){
00807         ExpressionResult = NEWMORTALDOUBLE;
00808         ASSERTNULL(ExpressionResult)
00809         DOUBLEVALUE(ExpressionResult) = ((double)LONGVALUE(Op1)) / ((double)LONGVALUE(Op2));
00810         }else{
00811         ExpressionResult = NEWMORTALLONG;
00812         ASSERTNULL(ExpressionResult)
00813         LONGVALUE(ExpressionResult) = LONGVALUE(Op1) / LONGVALUE(Op2);
00814         }
00815       }
00816     }
00817 
00818   /* if the result of the expression is not undef then immortalize */
00819   if( ExpressionResult ){
00820     /* we immortalize the new variable if it is a variable and not NULL meaning undef */
00821     IMMORTALIZE(ExpressionResult);
00822     }
00823 
00824   /* if this variable had value assigned to it then release that value */
00825   if( *LetThisVariable )memory_ReleaseVariable(pEo->pMo,*LetThisVariable);
00826 
00827   /* and finally assign the code to the variable */
00828   *LetThisVariable = ExpressionResult;
00829 
00830 #endif
00831 END
00832 
00846 COMMAND(LETI)
00847 #if NOTIMP_LETI
00848 NOTIMPLEMENTED;
00849 #else
00850   VARIABLE ExpressionResult;
00851   VARIABLE Op1,Op2;
00852   LEFTVALUE LetThisVariable;
00853   long refcount;
00854   double dResult;
00855   long lResult;
00856 
00857   /* we get the pointer to the variable that points to the value */
00858   LetThisVariable = EVALUATELEFTVALUE(PARAMETERNODE);
00859   ASSERTOKE;
00860 
00861   /* if this points to a reference value then we search the "real" variable
00862      to modify */
00863   DEREFERENCE(LetThisVariable);
00864 
00865   /* get the next parameter of the command, which is the expression */
00866   NEXTPARAMETER;
00867 
00868   /* Evaluate the expression, and if the expression is simple create a copy of the result
00869      to be sure that no two variables point to the same value */
00870   Op2 = execute_Evaluate(pEo,PARAMETERNODE,_pThisCommandMortals,&iErrorCode,0);
00871   ASSERTOKE;
00872 
00873   Op1 = *LetThisVariable;
00874 
00875   /* if any of the arguments is double then the result is double */
00876   if( (memory_Type(Op1) == VTYPE_DOUBLE || memory_Type(Op2) == VTYPE_DOUBLE) ||
00877 
00878      /* if the first argument is string and is NOT integer */
00879      ( memory_Type(Op1) == VTYPE_STRING && !ISSTRINGINTEGER(Op1)) ||
00880 
00881      /* if the second argument is string and is NOT integer */
00882      ( memory_Type(Op2) == VTYPE_STRING && !ISSTRINGINTEGER(Op2))
00883      ){
00884     Op1 = CONVERT2DOUBLE(Op1);
00885     Op2 = CONVERT2DOUBLE(Op2);
00886     if( DOUBLEVALUE(Op2) == 0.0 ){
00887       if((*RaiseError(pEo))&1 ){
00888         ERROR(COMMAND_ERROR_DIV);
00889         }
00890       ExpressionResult = NULL;
00891       }else{
00892       dResult = floor(DOUBLEVALUE(Op1) / DOUBLEVALUE(Op2));
00893       lResult = (long)dResult;
00894       if( dResult == (double)lResult ){
00895         ExpressionResult = NEWMORTALLONG;
00896         ASSERTNULL(ExpressionResult);
00897         LONGVALUE(ExpressionResult) = lResult;
00898         }else{
00899         ExpressionResult = NEWMORTALDOUBLE;
00900         ASSERTNULL(ExpressionResult);
00901         DOUBLEVALUE(ExpressionResult) = dResult;
00902         }
00903       }
00904     }else{
00905     Op1 = CONVERT2LONG(Op1);
00906     Op2 = CONVERT2LONG(Op2);
00907     if( LONGVALUE(Op2) == 0 ){
00908       if((*RaiseError(pEo))&1 ){
00909         ERROR(COMMAND_ERROR_DIV);
00910         }
00911       ExpressionResult = NULL;
00912       }else{
00913       ExpressionResult = NEWMORTALLONG;
00914       ASSERTNULL(ExpressionResult);
00915       LONGVALUE(ExpressionResult) = LONGVALUE(Op1) / LONGVALUE(Op2);
00916       }
00917     }
00918 
00919   /* if the result of the expression is not undef then immortalize */
00920   if( ExpressionResult ){
00921     /* we immortalize the new variable if it is a variable and not NULL meaning undef */
00922     IMMORTALIZE(ExpressionResult);
00923     }
00924 
00925   /* if this variable had value assigned to it then release that value */
00926   if( *LetThisVariable )memory_ReleaseVariable(pEo->pMo,*LetThisVariable);
00927 
00928   /* and finally assign the code to the variable */
00929   *LetThisVariable = ExpressionResult;
00930 
00931 #endif
00932 END
00933 
00945 COMMAND(LETC)
00946 #if NOTIMP_LETC
00947 NOTIMPLEMENTED;
00948 #else
00949   VARIABLE ExpressionResult;
00950   VARIABLE Op1,Op2;
00951   LEFTVALUE LetThisVariable;
00952   long refcount;
00953 
00954   /* we get the pointer to the variable that points to the value */
00955   LetThisVariable = EVALUATELEFTVALUE(PARAMETERNODE);
00956   ASSERTOKE;
00957 
00958   /* if this points to a reference value then we search the "real" variable
00959      to modify */
00960   DEREFERENCE(LetThisVariable);
00961 
00962   /* get the next parameter of the command, which is the expression */
00963   NEXTPARAMETER;
00964 
00965   /* Evaluate the expression, and if the expression is simple create a copy of the result
00966      to be sure that no two variables point to the same value */
00967   Op2 = execute_Evaluate(pEo,PARAMETERNODE,_pThisCommandMortals,&iErrorCode,0);
00968   ASSERTOKE;
00969 
00970   Op1 = *LetThisVariable;
00971 
00972   Op1 = CONVERT2STRING(Op1);
00973   Op2 = CONVERT2STRING(Op2);
00974 
00975   if( STRLEN(Op2) == 0 )RETURN;
00976 
00977   ExpressionResult = NEWMORTALSTRING( STRLEN(Op1) + STRLEN(Op2) );
00978   ASSERTNULL(ExpressionResult)
00979   memcpy(STRINGVALUE(ExpressionResult),STRINGVALUE(Op1),STRLEN(Op1));
00980   memcpy(STRINGVALUE(ExpressionResult)+STRLEN(Op1),STRINGVALUE(Op2),STRLEN(Op2));
00981 
00982   /* if the result of the expression is not undef then immortalize */
00983   if( ExpressionResult ){
00984     /* we immortalize the new variable if it is a variable and not NULL meaning undef */
00985     IMMORTALIZE(ExpressionResult);
00986     }
00987 
00988   /* if this variable had value assigned to it then release that value */
00989   if( *LetThisVariable )memory_ReleaseVariable(pEo->pMo,*LetThisVariable);
00990 
00991   /* and finally assign the code to the variable */
00992   *LetThisVariable = ExpressionResult;
00993 
00994 #endif
00995 END

Generated on Sun Mar 12 23:56:27 2006 for ScriptBasic by  doxygen 1.4.6-NO