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

Go to the documentation of this file.
00001 /*if.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 
00023 #include "../command.h"
00024 
00025 /*POD
00026 =H 'if' conditional statement
00027 CUT*/
00028 
00029 /* Convert a variable to 0 or 1 for SLIF, IF, ELSIF commands */
00030 static int IsTrue(VARIABLE v){
00031 
00032   if( memory_IsUndef(v) )return 0;/* undef is false*/
00033   switch( TYPE(v) ){
00034       case VTYPE_LONG:
00035         if( LONGVALUE(v) )return 1; else return 0;
00036       case VTYPE_DOUBLE:
00037         if(  DOUBLEVALUE(v) )return 1; else return 0;
00038       case VTYPE_STRING:
00039         if( * STRINGVALUE(v) == (char)0 )return 0; else return 1;
00040       case VTYPE_ARRAY:
00041         return 0;
00042       }
00043   return 0;
00044   }
00045 
00046 
00047 /*POD
00048 =section SLIF
00049 =H Signle line 'IF' conditional statement
00050 
00051 This command is a single line version of the IF statement
00052 This has the form:
00053 
00054 =verbatim
00055  IF expression THEN command
00056 =noverbatim
00057 
00058 CUT*/
00059 
00060 
00112 COMMAND(SLIF)/* Single line IF */
00113 #if NOTIMP_WHEN
00114 NOTIMPLEMENTED;
00115 #else
00116   NODE nGoForward;
00117   VARIABLE ItemResult;
00118 
00119   ItemResult = EVALUATEEXPRESSION(PARAMETERNODE);
00120   ASSERTOKE;
00121 
00122   /* to the next statement */
00123   nGoForward = pEo->CommandArray[pEo->ProgramCounter-1].Parameter.NodeList.rest;
00124   /* to the next statement after the next statement */
00125   if( nGoForward ){
00126     nGoForward = pEo->CommandArray[nGoForward-1].Parameter.NodeList.rest;
00127     }
00128 
00129   if( ! IsTrue(ItemResult) ){
00130     SETPROGRAMCOUNTER(nGoForward);
00131     RETURN;
00132     }
00133 #endif
00134 END
00135 
00136 
00137 /*POD
00138 =section IF
00139 =H 'if' conditional statement
00140 
00141 The IF conditional statement is implemented in a very special way. This is because IF can
00142 be very compound on several lines. If an IF expression is false then the command checks
00143 if there is any daingling ELSEIF and in case there is any it goes on and on until there
00144 is any ELSEIF with a true expression or there is no more ELSEIF but ELSE or ENDIF.
00145 
00146 CUT*/
00147 COMMAND(IF)
00148 #if NOTIMP_IF
00149 NOTIMPLEMENTED;
00150 #else
00151   NODE nItem;
00152   NODE nGoForward;
00153   NODE nCode;
00154   VARIABLE ItemResult;
00155 
00156   while(1){
00157     nItem = PARAMETERNODE;
00158     ItemResult = EVALUATEEXPRESSION(nItem);
00159     ASSERTOKE;
00160     NEXTPARAMETER;
00161     /* if the condition is FALSE then we step forward to the ENDIF/ELSIF or ELSE statement */
00162     nGoForward = PARAMETERNODE;
00163     nCode = CAR(nGoForward); /* the code node of the instruction */
00164 
00165     switch( OPCODE(nCode) ){
00166       case CMD_ELSE:
00167       case CMD_ENDIF:
00168         /* go AFTER the ELSE or ENDIF statement */
00169         nGoForward = CDR(nGoForward);
00170         break;
00171       case CMD_ELSIF:
00172         break;
00173       default:; /*TODO: report an internal error*/
00174       }
00175 
00176     /* If the expression is true then we have to continue with the next statement. This is
00177        usually the default, but here we have to explicitely set the program counter because
00178        in case we wen onto an ELSEIF the execution would start on the command after the
00179        IF statement. 
00180 
00181        If the expression is false then we either continue the execution after the ELSE or ENDIF
00182        statement or set the program counter to the ELSEIF statement and loop back to execute it
00183        if it were an IF statement.
00184     */
00185     if( IsTrue(ItemResult) ){
00186       SETPROGRAMCOUNTER(pEo->CommandArray[pEo->ProgramCounter-1].Parameter.NodeList.rest);
00187       RETURN;
00188       }else{
00189       if( OPCODE(nCode) == CMD_ELSIF ){
00190         pEo->ProgramCounter = nGoForward;
00191         _ActualNode=PROGRAMCOUNTER;
00192         }else{
00193         SETPROGRAMCOUNTER(nGoForward);
00194         RETURN;
00195         }
00196       }
00197     }
00198 #endif
00199 END
00200 
00201 COMMAND(ELSE)
00202 #if NOTIMP_ELSE
00203 NOTIMPLEMENTED;
00204 #else
00205 
00206 
00207   SETPROGRAMCOUNTER(PARAMETERNODE);
00208 
00209 #endif
00210 END
00211 
00212 COMMAND(ENDIF)
00213 #if NOTIMP_ENDIF
00214 NOTIMPLEMENTED;
00215 #else
00216 
00217   /* this command does not do anything */
00218 #endif
00219 END
00220 
00221 /*POD
00222 =section ELSIF
00223 =H 'else if' conditional statement
00224 
00225 Note that this piece of code does nothing. The execution gets here only when a previous
00226 IF or ELSIF was true. In that case the expression has to be ignored and the ELSIF treated
00227 like if it was an ELSE.
00228 
00229 The expression after an ELSEIF is checked by the preceeding IF command.
00230 
00231 CUT*/
00232 COMMAND(ELSIF)
00233 #if NOTIMP_ELSIF
00234 NOTIMPLEMENTED;
00235 #else
00236 
00237   NEXTPARAMETER;/* skip the expression */
00238   SETPROGRAMCOUNTER(PARAMETERNODE);
00239 
00240 #endif
00241 END

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