Difference between revisions of "IF"
Jump to navigation
Jump to search
ConvertBot (talk | contribs) (implements a logical block if-then-else function in a macro) |
(No difference)
|
Latest revision as of 18:04, 27 April 2020
implements a logical block if-then-else function in a macro
<VALUE> Left side of expression <TEST> Logical test to be performed. <VALUE> Right side of expression There are two forms of the IF statement; both can only be used in a macro. The first form is the block IF, the second is the one-line IF. Block IF Statement: The block IF statement evaluates a logical expression and, if the logical expression is true, executes the set of statements following. If the logical expression is false, control transfers to the next ELSE, ELSEIF, or ENDIF statement at the same IF level. The syntax is as follows (optional items are in braces): IF <conditional> THEN <action> [ELSEIF <conditional> THEN <action> ] [ELSE <action> ] ENDIF IF-ELSEIF-ELSEIF-...-ELSE-ENDIF blocks can be nested without limit. Note that "THEN" is technically optional, but highly recommended. One-Line IF Statement: The one-line IF requires that the <action> be a single executable Midas command, such as GOTO, BREAK, ENDMODE, CALC, etc. It should not be the start or end of a structure (such as WHILE,ENDWHILE,LOOP,ENDLOOP,IF,ENDIF,etc), or an operating system command. For those, the block IF should be used. IF <conditional> THEN <action> Prior releases indicated that the THEN was optional for the one-line IF; this is not always the case. Since NeXtMidas 2.1.2 the THEN is required for one-line IF statements. WARNING: When using a one-line IF statement the <action> may be cleaned (i.e. converted to uppercase) before execution. If this is a problem, use the multi-line IF syntax. Conditional Expressions: A <conditional> expression has the following form: <value1> <test1> <value2> [ <conjunction> <value3> <test2> <value4> ... ] where <conjunction> is either AND or OR. Tests: A EQ B Numeric A is equal to B A == B Numeric A is equal to B (since 2.5.0) A NE B Numeric A is not equal to B A != B Numeric A is not equal to B (since 2.5.0) A GT B Numeric A is greater than B A > B Numeric A is greater than B (since 2.5.0) A LT B Numeric A is less than B A < B Numeric A is less than B (since 2.5.0) A GE B Numeric A is greater or equal to B A >= B Numeric A is greater or equal to B (since 2.5.0) A LE B Numeric A is less or equal to B A <= B Numeric A is less or equal to B (since 2.5.0) A EQT B Alias for EQ/T, see below for details. A ~= B Alias for EQ/T, see below for details. (since 2.5.0) A EQTOL B Old alias for EQ/T (rarely used any more). *********************************************************** * Note: Prior to NeXtMidas 3.3.2 the above tests assumed * * scalar input values and only considered the first part * * of any non-scalar input. This behavior was deprecated * * in NeXtMidas 2.7.0 and removed in NeXtMidas 3.3.2. Now * * all entries in a non-scalar value are considered. * *********************************************************** ************************************************************** * The following test modifiers for EQ can be combined (e.g. * * "A EQ/M/T B" compare magnitude of A and B with a tolerance.* ************************************************************** A EQ/S B Makes sure both have the same number of elements (size). This is almost always combined with /M or /V. A EQ/B B Use a binary data comparison. Use with caution since this will return false if even the slightest thing is different (e.g. "1 EQ/B 1.0" -- which compares a L: to a D: will fail) A EQ/T B Numeric A is equal to B within tolerance. By default this will use a relative tolerance check using the system-wide tolerance (usually 1e-6). This can be overridden using the following switches: /TOL=<tol> - Use *relative* tolerance <tol> /DELTA=<tol> - Use *absolute* tolerance <tol> (since 3.3) See nxm.sys.libm.Tolerance for more info on "relative". A EQ/M B Compare the magnitude of the values of each atom (refer to nxm.sys.lib.Data.getMagnitude()). A EQ/V B Compare each value in an atom one-by-one. This is the same as computing vector equality in Euclidean space. A NE/? B Same as NEQ/? where ? is any valid modifier(s) for EQ. A GT/M B Numeric A has greater magnitude than B A LT/M B Numeric A has less magnitude than B A GE/M B Numeric A has greater or equal magnitude than B A LE/M B Numeric A has less or equal magnitude than B A ANYBITS B Integer A contains any of the bits set in integer B A ALLBITS B Integer A contains all of the bits set in integer B *********************************************************** * Note: String tests ignore case unless /CS is present! * *********************************************************** A ENDS B A ends with B. TRUE if A ends with all the characters in B. This is same as A.endsWith(B). (Since NeXtMidas 3.1.2) A EQS B String A equal to string B in length and content A EQSS B EQual Shortest String: Equality is checked only up to the length of the shorter of A or B A SEQS B String A equal to String B (alias for EQS) A STARTS B A starts with B. TRUE if A starts with all the chars in B. This is same as A.startsWith(B). (Since NeXtMidas 3.5.0) A SUBS B A is a substring of B. TRUE if all the characters of A are found in their entirety and in order somewhere within B. A FEXISTS The file named A exists (note that the file existence tests can be customized in the case of a URL, see javadocs for HttpResource for more info). A DEXISTS The directory named A exists A REXISTS The results parameter named A exists A PEXISTS The parameter or switch named A or /A exists for this macro A ISNULL The object A is NULL or does not exist A ISTRUE The state of A resolves to true. [This is the DEFAULT test.] (TRUE states include: Y|YES|T|TRUE|ON|1|PASS|SUCCESS|ABSC|AB) A ISFALSE The state of A resolves to false (FALSE states include: N|NO|F|FALSE|OFF|0|FAIL|INDEX|IN) A FEQ B File A is equal to File B (same as FEQ/H/D/S, files must be equal in size) A FEQ/B B File A is equal to File B - BINARY comparison A FEQ/D B File A DATA is equal to File B DATA A FEQ/H B File A HEADER is equal to File B HEADER A FEQ/K B File A *extended* header KEYWORDS are equal to File B extended header KEYWORDS. A FEQ/L B File A is equal to File B (limits length of binary or data comparison to size of shorter file, when applicable) (Since NeXtMidas 3.7.0) A FEQ/S B File A is equal in size to File B A FEQ/T B File A is equal within *relative* tolerance to File B. See notes about /TOL=<tol> with IF/T (above). A OEQ B Object A is equal to Object B A TYPEOF B The result A matches the type specified in B (see below). A INSTANCEOF B The result A is an instance of class B (see below). A CONTAINS B This is the same as CONTAINS/K test. A CONTAINS/K B The table A contains the key B (String). -or- Since 3.5.4, the Map A contains the key B (any Object). FALSE if A is not a java.util.Map. Table is a Map. Since 3.5.4, supports /CS switch to do a case-sensitive key B containment check on the Table. NOTE: Key B containment on Map that is NOT a table, always does an Object check (and hence it is case-sensitive). A CONTAINS/V B The Map/Table A contains the value B (via Object.equals). FALSE if A is not a java.util.Map. (Since NeXtMidas 3.5.4) Putting an "N" on the beginning of any test (except for the "C-style" numeric tests) will test for its logical opposite, for example: A NEQS B String A does not equal B A NEQ B Numeric A is not equal to B (same as NE) A NFEQ B The files differ A N< B Not allowed If the <test> is omitted, the ISTRUE state test is assumed. Note that ANDs and ORs are short-circuiting; as soon as a condition is evaluated which can stop evaluation, evaluation will stop. TYPEOF vs INSTANCEOF: INSTANCEOF matches the Java instanceof operator. The right-hand-argument is always the (case sensitive) name of a class or interface. The test will return true for "a INSTANCEOF b" if... (1) The class of a is the same as b (2) The class of a is a subclass of b (3) The class of a is a implements of b where b is an interface Due to this "a INSTANCEOF java.lang.Object" will always return true since all objects are subclasses of java.lang.Object. TYPEOF has two sets of functionality. The first takes in the name of a Java class as the right-hand-argument and checks to see if the class is an *exact* match. In this form, "a TYPEOF b" maps to the Java code a.getClass().getName().equalsIgnoreCase(b). The second form takes in the name of a Midas format type (e.g. 'D'=double,'F'=float,...) or digraph (e.g. "SF"=ScalarFloat,"VD"=VectorDouble,"3D"=ThreeDouble). This test will return true for "a TYPEOF b": if... (1) The class of a is the same as b (ignoring the case of b) (2) The class of a is String and b is "S" (special case) (3) The class of a is Data and the type of a matches b where b is a single-letter type specifier (4) The class of a is Data and the format digraph of a matches b where b is a two-letter format digraph (note that this does an "exactness" check where "VD" is *not* the same as "3D") Due to this "a TYPEOF b" will always return false when b is the name of an interface or abstract class since it is doing an exactness check. Precedence Rules: The precedence rules is LEFT to RIGHT between conjunctions (AND|OR). Additionally, the logical test will short-circuit when an OR conjunction is used and the result is TRUE on the LEFT side, hence all tests to the right of the OR conjunction will be ignored and not processed. The test will also short-circuit when an AND conjunction is used and the result is FALSE on the LEFT side, hence all tests to the right of the AND conjunction will be ignored and not processed. IF 1 LT 2 OR 2 GT 3 AND 3 EQ 4 ! TRUE (all tests after OR are skipped) IF 1 EQ 2 AND "A" EQ "B" OR 3 EQ 3 ! FALSE (all tests after AND are skipped) Current versions of NeXtMidas permit parenthesis around the test cases which give more control over the precedence. IF ( (1 LT 2) OR (2 GT 3) AND (3 EQ 4)) ! TRUE IF (((1 LT 2) OR (2 GT 3)) AND (3 EQ 4)) ! FALSE String Rules: The following rules apply to the string comparisons (SUBS,EQSS,EQS,etc.): - String tests are Case Insensitive unless the /CS switch is used. - Length of a string literal is the number of characters between the quotes. - Trailing spaces are not trimmed. - If an argument to a string test is a switch name and that switch is not present the string will contain the text "NULL" and can be tested appropriately. WARNING: The results of EQS, EQSS and SUBS comparisons are different from X-Midas, since X-Midas treats "" and " " as being equal, NeXtMidas does not do this. Examples: Numeric Tests: Given that D1=D:1.0, D2=D:1.00001, L1=L:1 IF D1 EQ D2 ! FALSE (Different numbers) IF D1 EQ L1 ! TRUE (Same numbers) IF D1 EQ/B L1 ! FALSE (Different bits for D: vs L:) IF D1 EQT D2 ! FALSE (use default tolerance, normally 1e-6) IF D1 EQT D2 /TOL=1e-5 ! TRUE (use relative tolerance of 1e-5) IF 100 EQ/T 99.95 /TOL=1e-6 ! FALSE (relative tolerance) IF 100 EQ/T 99.999999 /TOL=1e-6 ! TRUE (relative tolerance) IF 100 EQ/T 99.95 /DELTA=0.2 ! TRUE (absolute tolerance) IF 100 EQ/T 99.999999 /DELTA=0.0000002 ! FALSE (absolute tolerance) String Tests: Given that LS is the MAX of LA and LB. A EQS B is TRUE if LA equals LB and all characters of both strings are the same. RESULTS A:S1 "A " ! S1 has length 2 RESULTS A:S2 " " ! S2 has length 1 IF "A" EQS "A " ! FALSE (Different lengths) IF "aBc" EQS "ABC" ! TRUE (defaults to non-case sensitive comparison) IF "AA" EQS "aa" /CS ! FALSE (case sensitive comparison) IF " " EQS "" ! FALSE (empty string and blank are different!) IF "" EQS "A" ! FALSE ("" does not equal "A") IF S1 EQS "A" ! FALSE IF S1 EQS "A " ! TRUE IF S2 EQS "" ! FALSE (empty string and blank are different!) IF S2 EQS " " ! TRUE IF S2 EQS "A" ! FALSE IF "A" EQSS "A " ! TRUE (the first chars are the same) IF "A " EQSS "A" ! TRUE (same as above, order is not important) IF S1 EQSS "A " ! TRUE (same as above) IF " " EQSS "" ! TRUE (empty string is EQSS with any string) IF "ABC" EQSS "" ! TRUE (same as above) IF S2 EQSS "ABC" ! FALSE (S2 starts with a ' ') IF S1 EQSS S2 ! FALSE (S2 starts with a ' ') IF "A " EQSS " A" ! FALSE (leading space is important) IF "A" EQSS " A" ! FALSE (leading space is important) IF "AB" EQSS "BAB" ! FALSE (first 2 characters not the same) IF "A " EQSS "AB " ! FALSE (first 2 characters not the same) IF "A" EQSS "AB" ! TRUE (first character is the same) IF " AB" EQSS " " ! TRUE IF "ABC" STARTS "A" ! TRUE (First string starts with "A") IF "Abc" STARTS "b" ! FALSE IF "Abc" STARTS "a" /CS! FALSE (Fails case sensitive starts with check.) IF "A" SUBS "A " ! TRUE ("A" found in the first character) IF "A" SUBS "BCDA" ! TRUE ("A" found at the 4th character) IF S1 SUBS "A" ! FALSE IF "^S1" SUBS "A" ! FALSE IF "A " SUBS "A" ! FALSE IF "A " SUBS "CA B" ! TRUE ("A " found at the second character) IF " " SUBS "" ! FALSE (no space at all on right hand side) IF S1 SUBS S2 ! FALSE (no leading string "A" in an empty string) IF S2 SUBS S1 ! TRUE IF "BCD" SUBS "ABCDE" ! TRUE Invoking methods on a java.lang.String results to do comparisons. IF "".isEmpty() ! ERROR (not supported at this time) IF S1.isEmpty() ! FALSE IF S1.contains("A") ! TRUE (same as "A" SUBS S1) IF S1.contains("a") ! FALSE (since 3.5.0 lower case passed correctly) IF S1.contains(s2) ! TRUE (same as S2 SUBS S1) IF S1.matches("A.") ! TRUE (using regex - 'A' followed by any char) IF S1.matches("A*") ! FALSE (using regex - zero or more 'A's) IF S1.matches("A.*") ! TRUE (using regex) IF S1.startsWith(" ",1) ! TRUE (prefix,toffset) IF S1.startsWith("A",1) ! FALSE IF S1.regionMatches(1,"ABC ",3,1) ! TRUE (toffset,other,ooffset,len) IF S1.regionMatches(1,"ABC ",3,2) ! FALSE (len does not match) IF S1.regionMatches(1,S2,0,1) ! TRUE IF S1.regionMatches(0,"TMA ",2,2) ! TRUE IF S1.regionMatches(0,"Da ",1,1) ! FALSE (since 3.5.0 lower case 'a') IF S1.regionMatches(true,0,"Da",1,1) ! TRUE (ignore case) File/Directory Tests: Gracefully deletes a Midas file. Note that this is a one-line IF. IF file FEXISTS THEN ERASE file Recalculates the maximum of the file "myfile", if either REDO has been set to 1, or the result "filemax" does NOT exist and the file DOES exist: IF redo EQ 1 OR filemax NREXIST AND myfile FEXIST THEN MAXMIN myfile filemax ENDIF Switches: /CS - Perform a CASE SENSITIVE test. For EQS, EQSS, ENDS, SEQS, STARTS, SUBS, and CONTAINS (in Table) only. [DEF=IgnoreCase] /DELTA=<tol> - The *absolute* tolerance for the EQ/T, and FEQ/T tests. This will override any use of /TOL= without warning (this permits /TOL= to be given at top of macro to override system-wide relative tolerance without restricting use of /DELTA=). If /DELTA= is not specified *relative* tolerance checks will be used. [DEF=<use relative tol>] (since NeXtMidas 3.3.2) /TOL=<tol> - The *relative* tolerance for the EQ/T, and FEQ/T tests. If not specified (and /DELTA= is not specified) the system-wide *relative* tolerance (usually 1e-6) will be used. SEE ALSO: ELSE, ELSEIF, ENDIF, nxm.sys.libm.Tolerance, nxm.sys.lib.Args, nxm.sys.lib.Data