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.

Instruction Instruction Instruction Instruction Instruction;
Instruction Instruction Instruction Instruction Instruction;
Instruction Instruction Instruction Instruction // Comment on Instruction

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.

//'' Declare x : 3*4 ; ''  //'' Explain what x is used for here ''

A multi-line comment begins with an open curly bracket ({) and ends with a closed curly bracket (}).

{The multi-line comment is very useful
when comments span multiple lines
and using slashes is counter productive.}

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.

BEGIN
Declare Circumference  PI * \Radius^2;
IF Circumference> 3 SqFeet THEN "Too Big" ELSE  "Just Right" ENDIF
END

Note the use of white space to aid the reader in their understanding.

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:

56937.34
1344
584.
0.984737594

Examples of invalid numbers are:

1,024,037
10E7
$122.85
3.45.68

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:

"This is a string!"
""
'That was an empty string.'
"0.984737594"
'John said, "Cool!" '
'Don''t do that!'

Examples of invalid strings are:

I forgot the quotes!
"John said, "Oops" "

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:

TRUE
(Color  "Red") or (Name  "Tigers")
NO
Quantity> 16

Examples of invalid Boolean expressions are:

MAYBE           (no such predefined keyword)
"YES"           (since it is in quotes, this is a string, not a Boolean value)

CFL treats Booleans as a special case of the number type mentioned already. Zero (0) is considered NO or FALSE, whereas one 1) )</sup> 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:

#03/15/2005#
#1/18/05 3:12 PM#
#12/31/2004 23:59:59.99#
#11:52 AM#

Examples of invalid DateTime expressions are:

#2005-03-14#
#1/05 5:30 PM#
#1/1/01 23.15#

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.

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
-Subtraction4 – 3 1
%Percentage35 % 0.35
*Multiplication6 * 7 42
/Division24 / 4 6
\ Exponentiation2\3 8
+Addition3 + 4 7
<Less Than4 < 6.5
Greater Than7 > 5
>Greater Than or Equal To
BitANDBinary AND10 BitAND 7 2
BitNOTBinary NegationBitNot 10 (2\32 - 10)
BitORBinary OR10 BitOR 7 15
BitXORBinary XOR10 BitXOR 7 14
MODModulus 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
InList[]Acts like the IN operator in SQL Order.StatusText InList [“WIP”, “Built”, “Sale”]

Boolean Operators

Operator Description Example
ANDLogical AND False
NOTNegation( Not (3 4) ) True
ORLogical OR2) )</sup> True
XORLogical XOR3) )</sup> True

DateTime Operators

Operator Description Example
-Subtraction
*Multiplication
/Division
+Addition
<Less Than
Greater Than
>Greater Than or Equal To
MODModulus 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:

3 + 4 * 5

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:

  ( 3 + 4 ) * 5

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
HighestGroupingParenthesis, Functions
2nd HighestUnary+, -, Not, BitNot, %
3rd HighestUnitsPer, In, *, /, Units
Exponentiation\
Multiplicative*, /, Mod
3rd LowestAdditive+, - , And, Or, XOR, BitOr, BitAnd, BitXOR
2nd LowestRelational, , ,
LowestAssignment

When operands are between operators of the same precedence, then operations are performed from left to right, with the exception of unary and assignment operators. Therefore,

3 * 4 / 0 * 5

is equivalent to ( ( ( 3 * 4 ) / 0 ) * 5 ), and gives an error, due to division by zero, whereas the expression

3 * 4 / 5 * 0

will not give an error.

Temporary Variables Complex formulas are easier (and usually faster) if they are broken down into steps. Temporary variables are ideal for such occasions. Temporary variables are created within the CFL block and do not retain their values after the evaluation of the block is complete. (This is in contrast to Global Variables, which is discussed later.) Temporary variables use the “DECLARE” keyword and can be assigned a value immediately or upon later use, as in this example:

// First, convert the temperature Global Variable to Centigrade
Declare Centigrade := (Temperature – 32) * 5/9 ;
Declare ExpansionText ;
// Calculate the expansion coefficient for the C temperature
Declare Expansion := \Centigrade^1.5 / 6.17323 ;
ExpansionText := "Expansion of " + ToString( Expansion ) + "nm / Y"  ;
// Now repeat the expansion text 2 times as the result
ExpansionText + " ! " + ExpansionText + " ! "

Note that the assignment operator is the colon-equals, and not just the equal sign as in some programming languages. This is to prevent confusion with the comparison operator. In this example, the temporary variable “Centigrade” converted the global variable “Temperature” to degrees C. From this, CFL calculated the expansion coefficient. This entire calculation could not be done in one step, and the multiple-step approach makes the logic easier to follow. As in the example above, temporary variables are not limited to numbers. They can be any of the CFL data types, including Objects!

// First, define our local object reference variables
Declare Referral := 'None';
Declare Salesperson := 'None';

// Assign the 'Referral' variable
IF TransactionUDFIsAssigned('Referred By Customer') THEN
  Referral := TransactionUDFObject('Reffered By Customer');
ENDIF;

// Assign the referring Sales person
Salesperson := Referral.Company.Salesperson1.IDAsString;
SetTransactionUDFObjectID( "InitialSalesperson", Salesperson );

// Output referral and salesperson
Referral + "referred by " + Salesperson

Units One of the most powerful features of CFL is the built-in support for units. Units are written in CFL just as in high-school science: after the number or variable they modify.

Declare WorkingPrice := Area in SqFeet * 5;
MaxSize :=      IF ( Height <3 SqMeters  )
THEN 500 millimeters
ELSE 0.95 meters
ENDIF ;
Declare TooBig := ( MaxSize*MaxSize> 24 SqInches ) ;
IF ( 12 inches = 1 foot ) THEN "Elementary"
ELSE "Error" ENDIF

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.
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
  • 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.
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
  • 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.
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 ;

The units defined in CFL include the following:

Measure Unit Accepted Abbreviations
AreaSquare CentimeterSqCentimeter, SqCentimeters, SqCentimetre, SqCentimetres
AreaSquare FootSqFoot, SqFeet
AreaSquare InchSqInch, SqInches
AreaSquare MeterSqMeter, SqMeters, SqMetre, SqMetres
AreaSquare MillimeterSqMillimeter, SqMillimeters, SqMillimetre, SqMillimetres
AreaSquare YardSqYard, SqYards
Discrete(none)N/A
DiscreteEachEach
DiscreteImpressionImpression, Impressions
DiscretePagePage, Pages
DiscretePiecePiece, Pieces
DiscreteSheetSheet, Sheets
LengthCentimeterCentimeter, Centimeters, Centimetre, Centimetres
LengthFootFoot, Feet
LengthInchInch, Inches
LengthMeterMeter, Meters, Metre, Metres
LengthMillimeterMillimeter, Millimeters, Millimetre, Millimetres
LengthYardYard, Yards
TimeDayDay, Days
TimeHourHour, Hours
TimeMinuteMinute, Minutes
TimeSecondSecond, Seconds
VolumeCubic CentimeterCuCentimeter, CuCentimeters, CuCentimetre, CuCentimetres
VolumeCubic FootCuFoot, CuFeet
VolumeCubic InchCuInch, CuInches
VolumeCubic MeterCuMeter, CuMeters, CuMetre, CuMetres
VolumeCubic MillimeterCuMillimeter, CuMillimeters, CuMillimetre, CuMillimetres
VolumeCubic YardCuYard, CuYards
VolumeCupCup, Cups
VolumeGallonGallon, Gallons
VolumeLiterLiter, Liters, Litre, Litres
VolumeMilliliterMilliliter, Milliliters, Millilitre, Millilitres
VolumePintPint, Pints
VolumeQuartQuart, Quarts
WeightFluidOunceFluidOunce, FluidOunces
WeightGramGram, Grams
WeightKilogramKilogram, Kilograms
WeightMilligramMilligram, Milligrams
WeightOunceOunce, Ounces
WeightPoundPound, Pounds
WeightTonTon, 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.

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.

IF condition THEN
TrueExpression ;
ELSE
FalseExpression ;
ENDIF

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.

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 ;

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.

IF condition THEN
  IF condition THEN
  TrueTrueExpression ;
  ELSE
  TrueFalseExpression ;
  ENDIF ;
ELSE
  FalseExpression ;
ENDIF ;

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.

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:

CASE  [ TestExpression  ] IS
  TestExpression1 THEN  Expression1
  TestExpression2 THEN  Expression2
  TestExpression3 THEN  Expression3
  …
  TestExpressionX THEN  ExpressionX
ELSE
  FalseExpression
ENDCASE  ;

The CASE statement works like a long string of IF statements.

  1. TestExpression is compared to TestExpression1.
  2. 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.)
  3. If they are not equal, then TestExpression is compared to TestExpression2. If these are equal, Expression2 is evaluated and returned.
  4. 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.
  5. 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:

CASE Quantity IS
  1 THEN "One"
  2 THEN "Two"
  3 THEN "Three"
ELSE
  "More"
ENDCASE

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.

CASE IS
  Quantity1 THEN "One"
  Quantity*24 THEN "Two"
  Sqr(Quantity)9 THEN "Three"
ELSE
  "More"
ENDCASE

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.

FOR variable : startingnumber TO endingnumber [STEP increment] [MAXCOUNT  maxloops] DO
  ExpressionBlock ;
ENDFOR;

An alternate form of the FOR statement counts down and looks like this:

FOR variable : startingnumber DOWNTO endingnumber [STEP increment] [MAXCOUNT  maxloops] DO
  ExpressionBlock ;
ENDFOR;

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:

//// 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;

Another example of the FOR Statement follows:

// 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;

The increasing FOR statement can be rewritten using a WHILE loop as follows:

variable := startingnumber;
WHILE variable <= endingnumber DO
  ExpressionBlock;
  variable := variable + increment;
ENDWHILE

Use REPEAT statements to create loops that executes once and then continues as long as some condition is true.
The syntax for the REPEAT statement is as follows. Since white space does not matter, a different style can be used.

REPEAT
  ExpressionBlock ;
UNTIL (condition) [MAXCOUNT = maxloops];

The pieces of the WHILE statement are:

  • condition.
  • 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.


An example of the WHILE statement follows:

[[code|]]

===WHILE===

Use **WHILE** statements to create loops that execute if and while something is true.
The syntax for the WHILE statement is as follows. Since white space does not matter, a different style can be used.

WHILE (condition) [MAXCOUNT = maxloops] DO

ExpressionBlock;

ENDWHILE;

The pieces of the WHILE statement are:
* **condition**.
* **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.



1)
1
2)
2
3)
3
You could leave a comment if you were logged in.