{$page} Syntax All CFL block consists of a series of instructions. Each instruction tells CFL what to do. An expression terminates when it reaches a semicolon (;) or no more text follows. [[code]] Instruction Instruction Instruction Instruction Instruction; Instruction Instruction Instruction Instruction Instruction; Instruction Instruction Instruction Instruction // Comment on Instruction [[code]] White Space When writing CFL, the use of spacing makes formulas easier to read. Adding blank lines between logical areas or indenting related instructions can help. In CFL, these extra spaces, tabs, line returns, and blank lines are known as white space because those characters simply act as aids. CFL ignores white space. Thus, it does not slow computations down. Comments **Comments** describe what is going on. The author may thoroughly understand their own work, but when they return for maintenance in six months, they often forgot the intricacies of their own creation. Just like white space, CFL ignores all comments, regardless of how lengthy they are. A **single-line comment** is created by typing in two slashes (//). Comments go at the end of a line of code. [[code]] Declare x : 3*4 ; // Explain what x is used for here [[code]] A **multi-line comment** begins with an open curly bracket ({) and ends with a closed curly bracket (}). [[code]] {The multi-line comment is very useful when comments span multiple lines and using slashes is counter productive.} [[code]] Adding comments to code aids understanding, but commenting is excessive and even confusing if used for every line. Comments, like white space, should be used judiciously. Blocks A **block** is a group of CFL expressions. They are denoted by BEGIN and END keywords. Blocks combine multiple expressions. The main rule to remember is that for every BEGIN, there must be an END. [[code]] BEGIN Declare Circumference PI * Radius\^2; IF Circumference > 3 SqFeet THEN "Too Big" ELSE "Just Right" ENDIF END [[code]] Note the use of white space to aid the reader in their understanding. Data Types CFL works with a number of data types. The most common types are numbers and strings. Number Type **Number types** store numeric information. All mathematical operations require a number type. In CFL, numeric data is written in a series of numbers, with an optional decimal place between the numbers. Thousand separators, currency symbols, and other text are **not** valid when writing a number in CFL. Examples of valid numbers (in the US) are: [[code]] 56937.34 1344 584. 0.984737594 [[code]] Examples of invalid numbers are: [[code]] 1,024,037 10E7 $122.85 3.45.68 [[code]] Internally, the numbers are stored as floating point numbers and maintain 15-16 significant places. The value to the left of a decimal point is the integer. The portion to the right of the decimal point is the fractional part. 3.1416 Integer Fractional Understanding mathematic vocabulary is an important part of using CFL code. String Types **String types**, or **strings**, describe information that is stored as text within CFL. Strings are written between single or double-quote symbols and may be of any length. Single quotes can nest inside double quotes, and vice-versa. Examples of valid strings are: [[code]] "This is a string!" "" 'That was an empty string.' "0.984737594" 'John said, "Cool!" ' 'Don''t do that!' [[code]] Examples of invalid strings are: [[code]] I forgot the quotes! "John said, "Oops" " [[code]] Each letter, space, number, or symbol in a string is called a **character**. The length of a string is the total number of characters it contains. Boolean **Boolean types** are commonly used to evaluate conditions, but can also be used to store information. Boolean types are either logical, binary, true/false, yes/no, or 1/0 types. They store one of two states. One state is normally TRUE or YES. Likewise, the other state is normally FALSE or NO. In CFL, the constants TRUE, YES, FALSE, and NO are valid Boolean values. Examples of valid Boolean expressions are: [[code]] TRUE (Color "Red") or (Name "Tigers") NO Quantity > 16 [[code]] Examples of invalid Boolean expressions are: [[code]] MAYBE (no such predefined keyword) "YES" (since it is in quotes, this is a string, not a Boolean value) [[code]] CFL treats Booleans as a special case of the number type mentioned already. Zero (0) is considered NO or FALSE, whereas one (1) is considered to be YES or TRUE. DateTime Types **DateTime types** store dates and times. In CFL, adding and subtracting DateTime types determines the number of days/hours/minutes between two events. For portability purposes, the format for DateTime data in CFL does not vary by region. DateTime types begin and end with the number sign (#). Examples of valid DateTime expressions are: [[code]] #03/15/2005# #1/18/05 3:12 PM# #12/31/2004 23:59:59.99# #11:52 AM# [[code]] Examples of invalid DateTime expressions are: [[code]] #2005-03-14# #1/05 5:30 PM# #1/1/01 23.15# [[code]] CFL treats DateTime as a special case of the number type mentioned already. The integer portion stores the number of days from December 30, 1899. The fractional portion stores the fraction of the day since Midnight of the previous morning. Expressions and Operators An **expression** is an instruction that performs some kind of calculation (using **operators**) and returns a value. CFL supports all expressions and operators listed on the following pages. Numeric Operators || **Operator** || **Description** || **Example** || || - || Subtraction || 4 – 3 1 || || % || Percentage || 35 % 0.35 || || * || Multiplication || 6 * 7 42 || || / || Division || 24 / 4 6 || || \^ || Exponentiation || 2\^3 8 || || + || Addition || 3 + 4 7 || || < || Less Than || 4 < 6.5 || || || Greater Than || 7 > 5 || || > || Greater Than or Equal To || || || BitAND || Binary AND || 10 BitAND 7 2 || || BitNOT || Binary Negation || BitNot 10 (2\^32 - 10) || || BitOR || Binary OR || 10 BitOR 7 15 || || BitXOR || Binary XOR || 10 BitXOR 7 14 || || MOD || Modulus Division (remainder) || 7 mod 3 1 || BitOR, BitAND, and BitNOT are binary functions that deal with the individual bits (binary digits) in a number. The number 7 in binary is "0111". The number 10 in binary is "1010". Coverage of binary numbers is beyond the scope of this reference. If not familiar with them, they should be avoided in expressions. \\ Additionally, BitNOT results may vary for 32 and 64-bit systems. Very large numbers may display as negative values. If many BitNOT statements are used, they should be counter-balanced with BitAND (with a number like (2\^16 - 1)) to "clean up" the higher-order bits. \\ String Operators \\ || **Operator** || **Description** || **Example** || || * || Replication || "E1" * 3 "E1E1E1" || || /+ || Line Concatenation \\ Combines two strings with a line break between \\ If either value is blank, no line break is added and the other value is returned || "Line 1" /+ "Line 2" \\ "Line 1 \\ Line 2" || || + || Concatenation || "Ho" + "use" "House" || || < || Less Than || "Green" < "Grocer" || || || Greater Than || "Red" > "Apple" || || > || Greater Than or Equal To || || Boolean Operators \\ || **Operator** || **Description** || **Example** || || AND || Logical AND || ((3 4) AND (1 1)) False || || NOT || Negation || ( Not (3 4) ) True || || OR || Logical OR || ((3 4) OR (1 1)) True || || XOR || Logical XOR || ((3 4) XOR (1 1)) True || DateTime Operators \\ || **Operator** || **Description** || **Example** || || - || Subtraction || || || * || Multiplication || || || / || Division || || || + || Addition || || || < || Less Than || || || || Greater Than || || || > || Greater Than or Equal To || || || MOD || Modulus Division (remainder) || || Operator Precedence \\ When an expression contains more than one operator, CFL uses a set of rules to determine which operator to evaluate first, second, third, and so on, until the entire expression is evaluated. Each **operator** has a built-in priority, or **precedence**, which the compiler uses to determine the operator to evaluate next. \\ Look at the following expression: \\ [[code]] \\ 3 + 4 * 5 \\ [[code]] \\ At first glance, many would think this evaluates to 35. This would be correct if CFL simply evaluated from left to right and did the addition first and the multiplication second. However, since multiplication has higher operator precedence than addition, multiplication is done first. CFL will evaluate 4*5 and then add this result (20) to 3 and get 23. \\ Parentheses override operator precedence. For example: \\ [[code]] \\ ( 3 + 4 ) * 5 \\ [[code]] \\ This expression would indeed evaluate to 35 because parenthesis have a higher precedence than multiplication (or anything else for that matter). \\ CFL recognizes the following operator precedence: \\ || **Priority** || **Category** || **Operators** || || Highest || Grouping || Parenthesis, Functions || || 2nd Highest || Unary || +, -, Not, BitNot, % || || 3rd Highest || Units || Per, In, *, /, Units || || || Exponentiation || \^ || || || Multiplicative || *, /, Mod || || 3rd Lowest || Additive || +, - , And, Or, XOR, BitOr, BitAnd, BitXOR || || 2nd Lowest || Relational || , , , || || Lowest || Assignment || :, 24 SqInches ) ; \\ IF ( 12 inches 1 foot ) THEN "Elementary" \\ ELSE "Error" ENDIF \\ [[code]] \\ Here are some simple rules to remember about using units: \\ * Units apply to the number or variable immediately before them. \\ * Variables are stored internally in their own units. Units are not needed when multiplying or adding variables, only when working with numbers or numbers compared to variables. \\ [[code]] \\ Area : Height * Width ; // Does not require units \\ Area : Height * 12 inches ; // Numbers always need units \\ Area : 24 * 48 SqInches ; // Still a number, add the units \\ IF Height > 5 SqFeet THEN … // required here \\ IF Height > 5 Feet*Feet THEN … // and here \\ IF Height in SqFeet > 5 THEN … // here a different approach \\ IF Height > Width THEN … // not here, both variables \\ [[code]] \\ * Either the singular form (like inch) or the plural form (like inches) can be used. Both are identical. \\ * For square and cubic dimensions, precede the unit with "Sq" or "Cu" to make the square or cubic unit of that version. Alternately, "Unit*Unit" for the square or "Unit*Unit*Unit" for the cubic can be used. \\ [[code]] \\ 9 SqFeet : 3 Feet * 3 Feet ; // Standard Form \\ 9 SqFeet : 9 Feet*Feet ; // Alternate Form \\ 27 CuFeet : 3 Feet * 3 Feet * 3 Feet; // Standard Form \\ 27 CuFeet : 27 Feet*Feet*Feet ; // Alternate Form \\ [[code]] \\ * The keywords IN and PER can be used to modify the meaning of the unit. These keywords can also be used to combine units with other units. \\ [[code]] \\ // Here is one set of equivalent expressions. \\ FinalPrice : Area * 5 PER SqFeet ; \\ FinalPrice : Area IN SqFeet * 5 ; \\ // Here is a slightly tougher form of equivalence … \\ ElapsedTime : Distance / 12 miles PER hour ; \\ ElapsedTime : Distance IN Miles / 12 PER hour ; \\ [[code]] \\ The units defined in CFL include the following: \\ || **Measure** || **Unit** || **Accepted Abbreviations** || || Area || Square Centimeter || SqCentimeter, SqCentimeters, SqCentimetre, SqCentimetres || || Area || Square Foot || SqFoot, SqFeet || || Area || Square Inch || SqInch, SqInches || || Area || Square Meter || SqMeter, SqMeters, SqMetre, SqMetres || || Area || Square Millimeter || SqMillimeter, SqMillimeters, SqMillimetre, SqMillimetres || || Area || Square Yard || SqYard, SqYards || || Discrete || (none) || N/A || || Discrete || Each || Each || || Discrete || Impression || Impression, Impressions || || Discrete || Page || Page, Pages || || Discrete || Piece || Piece, Pieces || || Discrete || Sheet || Sheet, Sheets || || Length || Centimeter || Centimeter, Centimeters, Centimetre, Centimetres || || Length || Foot || Foot, Feet || || Length || Inch || Inch, Inches || || Length || Meter || Meter, Meters, Metre, Metres || || Length || Millimeter || Millimeter, Millimeters, Millimetre, Millimetres || || Length || Yard || Yard, Yards || || Time || Day || Day, Days || || Time || Hour || Hour, Hours || || Time || Minute || Minute, Minutes || || Time || Second || Second, Seconds || || Volume || Cubic Centimeter || CuCentimeter, CuCentimeters, CuCentimetre, CuCentimetres || || Volume || Cubic Foot || CuFoot, CuFeet || || Volume || Cubic Inch || CuInch, CuInches || || Volume || Cubic Meter || CuMeter, CuMeters, CuMetre, CuMetres || || Volume || Cubic Millimeter || CuMillimeter, CuMillimeters, CuMillimetre, CuMillimetres || || Volume || Cubic Yard || CuYard, CuYards || || Volume || Cup || Cup, Cups || || Volume || Gallon || Gallon, Gallons || || Volume || Liter || Liter, Liters, Litre, Litres || || Volume || Milliliter || Milliliter, Milliliters, Millilitre, Millilitres || || Volume || Pint || Pint, Pints || || Volume || Quart || Quart, Quarts || || Weight || FluidOunce || FluidOunce, FluidOunces || || Weight || Gram || Gram, Grams || || Weight || Kilogram || Kilogram, Kilograms || || Weight || Milligram || Milligram, Milligrams || || Weight || Ounce || Ounce, Ounces || || Weight || Pound || Pound, Pounds || || Weight || Ton || Ton, Tons || Expressions using units are found throughout the rest of this reference. After a bit of practice with using units, CFL's easy-to-use unit syntax is mastered in no time. CONTROL (BRANCHING) OPERATIONS IF THEN Using **IF** statements can alter the path calculations use to determine their result. The IF statement enables a user to test for a Boolean logical condition in the program, and if that condition is true, the program returns some expression contained in that branch. If the condition is false, then the program returns an expression in a different branch. The syntax for the IF statement is as follows. Since white space does not matter, a different style can be used. [[code]] IF condition THEN TrueExpression ; ELSE FalseExpression ; ENDIF [[code]] Translation: If the condition is true, then TrueExpression will be evaluated. If condition is false, then FalseExpression will be evaluated. The condition can be any expression that returns a Boolean value. An example of the IF statement may help illustrate the how this all works in practice. [[code]] IF (Height > SheetHeight) or (Width > SheetWidth) THEN PiecesPerSheet : 0 ; ELSE Declare SheetsHigh Int( SheetHeight / Height ) ; Declare SheetsAcross Int( SheetWidth / Width ) ; PiecesPerSheet : SheetsHigh * SheetsAcross ; ENDIF ; // Now return PiecesPerSheet as our Answer PiecesPerSheet ; [[code]] There is no limit to one expression for TrueExpression or FalseExpression. Rather, CFL uses everything between THEN and ELSE as the TrueExpression and everything between the ELSE and ENDIF as the FalseExpression. An IF statement can also be placed within another IF statement; the inner IF is then said to be **nested** within the other. The following syntax shows a nested IF statement. [[code]] IF condition THEN IF condition THEN TrueTrueExpression ; ELSE TrueFalseExpression ; ENDIF ; ELSE FalseExpression ; ENDIF ; [[code]] It is considered good syntax to index nested IF's so that they can be easily followed. There is no limit to the number of nested statements that can be created in CFL. CASE The **CASE** statement is similar to an IF statement, but provides an unlimited number of branches instead of just two. The syntax of the CASE statement is as follows: [[code]] CASE [ TestExpression ] IS TestExpression1 THEN Expression1 TestExpression2 THEN Expression2 TestExpression3 THEN Expression3 … TestExpressionX THEN ExpressionX ELSE FalseExpression ENDCASE ; [[code]] The CASE statement works like a long string of IF statements. - TestExpression is compared to TestExpression1. - If they are equal, Expression1 is evaluated and returned. (The CASE comparison is an approximate equal, not an exact equal. If an exact equal is required, IF statements must be used.) - If they are not equal, then TestExpression is compared to TestExpression2. If these are equal, Expression2 is evaluated and returned. - This process continues until all TestExpressionX are compared. If none is found to match, then the FalseExpression located between the ELSE and ENDCASE is evaluated. - The expressions to be compared may be any data types. If TestExpression is omitted, then CFL defaults to TRUE. This enables use of the CASE statement even when not comparing similar items. Rather, each TestExpressionX is evaluated as a Boolean expression. When the first true TestExpressionX is found, its corresponding ExpressionX is evaluated and the case statement ends. Two examples may help illustrate the usage: [[code]] CASE Quantity IS 1 THEN "One" 2 THEN "Two" 3 THEN "Three" ELSE "More" ENDCASE [[code]] The secod form allows more flexibility in what is compared, allowing each evaluation to be conducted with different arguments until one is successfully found. It can be used to replace a complicated IF/THEN/ELSEIF/ELSEIF type statement. [[code]] CASE IS Quantity1 THEN "One" Quantity*24 THEN "Two" Sqr(Quantity)9 THEN "Three" ELSE "More" ENDCASE [[code]] LOOPING OPERATIONS FOR Use **For** statements to create a loop that that executes a fixed number of times. This is most often used for looping through child items, parts, or modifiers on a line item. The syntax for the FOR statement is as follows. Since white space does not matter, a different style can be used. [[code]] FOR variable : startingnumber TO endingnumber [STEP increment] [MAXCOUNT maxloops] DO ExpressionBlock ; ENDFOR; [[code]] An alternate form of the FOR statement counts down and looks like this: [[code]] FOR variable : startingnumber DOWNTO endingnumber [STEP increment] [MAXCOUNT maxloops] DO ExpressionBlock ; ENDFOR; [[code]] The pieces of the FOR statement are: * **variable**. This is an actual variable and must be declared (with a DECLARE variablename; statement) before the FOR statement. This is called the loop variable. * **startingnumber**. The value is assigned to variable at the start of the FOR statement. * **endingnumber**. The value that sets the maximum value for variable.minimum value in the case of the DOWNTO variant * **increment**. The value to increment/decrement variable by each iteration of the loop. This defaults to 1.0 if not specified. * **maxloops**. This optional identifier sets a maximum number of loops that the loop will perform. If this limit is reached, execution automatically moved to the line of CFL following the loop. At the start of every loop (except the first), the loop variable is increased by the increment value (which defaults to 1)decreased by the increment value in the case of DOWNTO variant . If the loop variable is then less than or equal to the ending variablegreater than or equal to in the case of the DOWNTO variant , the ExpressionBlock is skipped else is is run and the process repeats. An example of the FOR statement follows: [[code]] //// This is some helpful code to put in the products warning message Declare i; Declare S : ''; FOR i : 0 TO Parts.SonCount-1 DO IF (Parts[i].TrackInventory "True") AND (Parts[i].QuantityAvailable < Parts[i].YellowNotificationPoint) THEN S: S + (Parts[i].PartCode) + " is below the yellow level of " + ToString(Parts[i].YellowNotificationPoint ) ELSE "" ENDIF; ENDFOR; // The value of any CFL statement is the value of the last computation/display // Now we need to return our value as the value of this function. // S; [[code]] Another example of the FOR Statement follows: [[code]] // This is code loops through the index of all parts and displays the part code and part description. // Additional CFL can be embedded as needed, you can use IF statements and other things to filter the results that appear. Declare i; Declare S : ''; FOR i : 0 TO Parts.SonCount-1 DO S: S + (Parts[i].PartCode) + " is the part name and " + (Parts[i].Description) + " is the description of the part. " + HTMLRETURN ENDFOR; // To display the results of our FOR statement we need to notate S; below since it was a declared variable above. S; [[code]] The increasing FOR statement can be rewritten using a WHILE loop as follows: [[code]] variable : startingnumber; WHILE variable