Rulz Programming Language

This is the second version of the language specification — a formal version numbering value has not been defined. This language is still evolving. The "proof of concept" is being written in Go.

What Rulz Is

Rulz –- pronounced "rules" -– is a general purpose language with a machine language like format of one statement per line. It includes flow control, loops and subroutines. The language is minimalist with no use of traditional braces, parentheses or commas.

The Rulz Language is Copyright © G.A.Jennings, 2015-2019. (It is still evolving and subject to change.)

Introduction

This document introduces a new programming language. Though yet to be described formally, the language has an assembly language structure and uses PHP-like variables and types, and borrows features from Bash and Perl.

A statement is called a "rule". A group of "rules" in a subroutine is called a "Rule". Together, rules and Rules make up a Rulz program.

OperatorsVariablesData TypesSubroutines

Index

Introduction

Hello World

Here is the ubiquitous "Hello World" program in Rulz.

^Hello World

The ^ is the "print operator" which is like echo in Bash, outputting all arguments, separated by spaces, terminated with a newline. It also shows that, like Bash and Perl, barewords — identifiers of letters only — are treated as strings. To use any other characters quotes need to be used.

^"Hello, World!"

Otherwise the punctuation characters will be treated as separate arguments:

^Hello, World!           ; prints as 'Hello , World !'

Left-handedness

Rulz language's most unique syntax is that operators are always "first on the line" and there is always only one (and therefore there is no operator precedence). See #Operators.

For example, assignment is =var argument and not var=argument. As in Bash, variable assignment does not include the $. Here is the "Hello World" program with assigning a variable.

=name 'Hello World'
^$name
This is known as "prefix notation" for operations, but Rulz syntax is more "prefix statement notation".

Spaces

Spaces are needed only in the case of ambiguous arguments. These two rules are parsed identically as above.

= name'Hello World'
^ $name

For clarity, most examples here use spaces (though it's kind of a convention to not use a space after the leading operator if it is unambiguous).

Naming Conventions

This document uses some identifiers in particular ways.

rule                    a Rulz language statement
Rule                    two or more rules together or a subroutine
var                     a variable name to be set
val                     a literal value (number, string, etc.)
$var                    a variable
argument|arg            a literal, variable or function name

Basic Syntax

The basic format of a rule is:

<[operator][builtin|subroutine|label]>[arguments]

Where:

operator                arithmetic, conditional, or other operator
builtin                 builtin command or function
subroutine              a named set of one or more rules; called a Rule
label                   a placeholder for the "jump" operator
arguments               zero or more arguments (usually) separated by spaces

Currently supported operators are: conditionals, assignment, comparison, arithmetic, bitwise, execution, call, logical, string, list and a jump operator.

(And a few others like percent and some mathematical operators like for some mathematical functions.)

Rulz implements many functions as operators for regular expressions, file I/O, file and type tests and others; not unlike Perl's binding operator (or Perl's named unary operators using two characters rather than names).

"While we usually think of quotes as literal values, in Perl they function as operators, providing various kinds of interpolating and pattern matching capabilities." - PerlOp

See Rulz Operator Quick Reference.

Builtins

Builtins are defined by the language and are similar to basic functions provided by Bash, Perl and PHP.

Similar to Perl, many have default values for arguments and/or return value (see #Variables).

Some builtins are also referred to as commands or functions, depending on there category, (with the acronym BCF). Subroutines can create new builtins, even redefining them - see href.

Types

The following types are supported: boolean, integer, float, string, list, hash (arrays) and the PHP types NULL and handle (resource).

Types and examples.

boolean                 TRUE FALSE
integer                 123 0x1A 1Ah 033 0b0001 0001b
float                   .123 1e4
string                  "interpolated" 'non-interpolated' bareword
list                    (1,2,3) (a..z) ($a,$b)
hash                    (a=1,b=2,c=1) (a=$a,b=$b)

Rulz introduces several other pseudo-types such as file and argument — which are similar to barewords. See href.

Variables

Basic variables are like $var where "var" is one or more lowercase letters, and, PHP-like, can be assigned any type. Variable assignment is Bash-like with the $ not used.

Like Bash and Perl all variables are global and there are "my" and "local" attributes for subroutines.

There are Perl-like special variables of the format: $href]. The special variables $0 and $_, differ from their Perl counterparts and are used as defaults for most Operators and Builtins.

The variable $0 is called the "return value", or "r-value",and contains the result of function calls and is the default for most operators and commands.

The variable $_ is called the "function value", or "f-value", and is the default argument for some operators and functions.

Operators

Comments

;                       line ignored before parsing
#                       line ignored after parsing
##                      start of multi-line comment, ends at the next ## or end of Rule

Internally, #, ## comments are implemented as operators — # and ; comments can trail a rule but they must be preceded by whitespace.

No Op

:                       ignored

Conditional Operators

There are two conditional operators. In their simplest for they test the $0 special variable.

? rule                  run rule if previous rule ($0) was true
! rule                  run rule if previous rule ($0) was false

The logical operations are "true if true" and "true if false".

There are two "special" conditions to test a variable, running the rule if the variable is true or not:

? $var rule             run rule if $var true
! $var rule             run rule if $var false

The combination of these two rules are the reduction of the syntax of these two PHP statements.

if ($var) statement;
if (!$var) statement;

The conditional operators have "compound forms".

<?!> [operator [$var]] rule

See #Compound Conditionals.

And there are ternary versions based on a variable.

? $var rule rule
! $var rule rule

And for result of a rule.

? rule rule rule
! rule rule rule

These are not a "ternary assignment operator" as in other languages. For Rulz, the ternary construct is a form of an if/else block; as if PHP or Perl were able to do this:

(expression) ? statement : statement;

Which is also:

if (expression) {
statement;
} else {
statement;
}

True vs. False

Rulz implements the PHP boolean type, TRUE and FALSE. The Conditional Operators are "loose" comparisons, with 0, "0", empty string and empty list evaluating false, with all other values evaluating true.

Assignment Operators

The assignment operator is = and their "combined operator" equivalents. Assignment without an argument is a special case which "resets" $0; with one argument it assigns $0; with two arguments the first is a variable name to assign.

=                       reset $0 (to NULL)
= argument              set $0 to argument
= var argument          set $var to argument

It is important to note that the last two examples above are how nearly all operators work.

There are "compound" versions for multiple variables.

= a,b,c 1,2,3

Without values, compound variables are set to 0.

= i,j

With just one value the variables are all set to it. This is same as above.

= i,j 0

To set some and default some, use a comma.

= i,j 1,

Un-Assignment Operator

!= var [vars]           unset $var and all following variables

Logical Operators

The logical operators set $0 with the result of the operation.

!! [argument]           true if argument or $_ not true
|| [arguments]          true if any argument or $_ true
&& [arguments]          true if all arguments or $_ true
^^ argument [argument]  true if either argument or argument and $_ true but not both

The Perl Logical Defined-Or is supported.

// var argument         result is $var if defined else argument

In addition, there are two named operators that operate a little different.

or argument [arguments] result is the first argument that is found true
and argument [arguments] result is the first argument if all are true

And two that are unique to Rulz.

is argument [argument]  true if argument or argument and $_ are of the same type
non argument [argument] true if argument or argument and $_ are not of the same type

Arithmetic Operators

These are combined assignment operators; if a variable is undefined it is set to 0 first — or "" in the case concatenation (which is grouped here for its syntax).

+= argument             add to $0
-= argument             subtract from $0
*= argument             multiply $0
/= argument             divide $0
%= argument             modulo $0
.= argument             concatenate $0
+= var argument         add to $var
-= var argument         subtract from $var
*= var argument         multiply $var
/= var argument         divide $var
%= var argument         modulo $var
.= var argument         concatenate $var

An easy way to remember these two character operators are to think of them as "modified assignment operators", with the operation character, +, -, *, etc., modifying the = operator — in the "left-handed" way.

When used with a variable name and two arguments the result is like other language arithmetic.

+= var arg arg          $var = arg + arg
-= var arg arg          $var = arg - arg
*= var arg arg          $var = arg * arg
/= var arg arg          $var = arg / arg
%= var arg arg          $var = arg % arg
.= var arg arg          $var = arg . arg

See also #List Assignment Operations.

Constant Assignment Operators

There are two ways to create constants — one for eumerations and one for values.

,= A B C                A = 1; B = 2; C = 3
:= A 1, B 2, C 3        same

Exponentiation Operator

The exponentiation operator works just like assignment operators but stands outside them by not having a trailing =.

** arg                  $0 = $0 ** arg
** arg arg              $0 = arg ** arg
** var arg              $var = $var ** arg
** var arg arg          $var = arg ** arg

See also #Mathematical Operators.

Increment and Decrement Operators

++                      increment $0
--                      decrement $0
++ var                  increment $var
-- var                  decrement $var

Bitwise Operators

These operators are listed by number of arguments.

The unary not of bits takes zero or one arguments. If none, $0 is a not of itself, else it is not of the variable.

~= [var]                result is Not of bits

The xor and shift operators take one or two arguments, with the result in $0 or a variable respectively.

^= argument [argument]  result is Xor of bits
<= argument [argument]  result is bit shift left
>= argument [argument]  result is bit shift right

The and and or operators can take from one to many arguments.

&= argument [arguments] result is And of bits
|= argument [arguments] result is Or of bits

With one or two values, the result is in $0 (with one value the result is the binary operation with $0 (itself) as the first operand).

Examples

&= 1                    $0 is $0 And 1
&= $a $b                $0 is $a And $b

With a variable name the operations are the same:

&= a 1                  $a is $0 And 1
&= c $a $b              $c is $a And $b

With three or more arguments, the result is the operator applied to all values.

|= 1 2 4 8              $0 is 15
|= var 1 2 4 8          $var is 15

Comparison Operators

These operators set the result in $0, and take one or two arguments. If one the comparison is against $_; if two the comparison is between the first and second arguments.

=? argument [argument]  true if equal
=! argument [argument]  true if not equal
<? argument [argument]  true if less than
<! argument [argument]  true if not less than
>? argument [argument]  true if greater than
>! argument [argument]  true if not greater than

These are "modified conditional operators", with the test type character, =, < and >, modifying the ? and ! operators.

See #Compound Conditionals.

List Assignment Operations

The #Assignment Operators can be used with lists.

+= list value           add value to each list element
+= list list            add each element of second to each element of first

All basic arithmetic operations are similarly supported.

Concatenation is either push (append) or merge.

.= list value           push value onto list
.= list list            merge second list into first list

There are also several operators dedicated to lists.

List Bitwise Operations

Bitwise operations also can be applied to lists in a unique way — with just one argument $_ will be used as if it were the second.

&= [list] list          union
|= [list] list          replace
^= [list] list          unique
~= [list] list          intersect
<= [var] list           shift
>= [var|val] list       unshift

See also #List Operators.

List Comparison Operators

=? list [list]          true if have same key/value pairs
=! list [list]          true if not the same

Evaluation Operators

Evaluation operators mimic the PHP isset and the Perl defined functions.

?? var                  isset (defined)
?! var                  not isset (not defined)
&? var                  defined [subroutine]
&! var                  not defined [subroutine]

Percent Operators

The percent operators are function-like.

=% argument [argument]  percentage of
/% argument [argument]  percentage against
+% argument [argument]  percentage add
-% argument [argument]  percentage from
*% argument [argument]  percentage between

Mathematical Operators

The Mathematical operators are function-like.

v/ argument             square root
2/ argument             square
1/ argument             reciprocal
a/ argument             absolute
^/ argument				exponentiation

They work like #String Operators defined below. (There will eventually be many more.)

File Operators

The file I/O operators mimic basic file functions. The $0 variable is TRUE on success or FALSE on error.

&  [fh] file            open file for reading, handle in $_ or $fh
-& [fh] file            open file for writing, handle in $_ or $fh
+& [fh] file            open file for appending, handle in $_ or $fh

The read operators returns the number of bytes read or FALSE on error.

<& [$fh] var           read line from $fh or $_ to $var
<& [$fh] var number    read number bytes from $fh or $_ to $var
[& [$fh] var           read line from $fh or $_ to $var without EOL
{& [$fh] var           read character from $fh or $_ to $var
(& [$fh] var format    parse line from $fh or $_ to $var according to format 
/& [$fh] var pattern   parse line from $fh or $_ to $var according to regular expression

The write operators returns the number of bytes written or FALSE on error.

>& [$fh] $var           write $var to $fh or $_ with EOL
]& [$fh] $var           write $var to $fh or $_ without EOL
}& [$fh] $var           write character $var to $fh or $_
)& [$fh] var format     write $var to $fh or $_ according to format

Other file operators.

@& [$fh]                eof test
.& [$fh]                close
%& [$fh]                stat
=& [$fh] number         seek
,& [$fh]                rewind
?& [$fh]                tell
:+ [$fh]                truncate

With some file name versions.

%& file                 stat
^& file                 touch
!& file                 delete
|& file file            rename/move

The use of $_ as a default for the file handle is odd as many other operators can subsequently and inadvertently overwrite $_. Using $_ is recommended only for short sequences of code.

See also #Test Operators.

There are several function-like operators that read or write files directly.

<< [var] file           get file as string into $_ or $var
[< [var] file           get file as list into $_ or $var with EOL
(< [var] file           get file as list into $_ or $var without EOL
>> [$var] file          put $var or $_ as string to file
]> [$var] file          put $var or $_ as list to file with EOL
)> [$var] file          put $var or $_ as list to file without EOL
+> [$var] file          append $var or $_ as string to file
-> [$var] file          prepend $var or $_ as string to file

Special variable $0 is set to FALSE for error, TRUE for success; except that read operators return the number of bytes read, and write operators return the numbers of bytes written on success.

The put, append and prepend file operators have a dual role with two arguments in that if the first argument is the name of a file that exists the file's contents will be used in place of the variable contents.

>> filea fileb          copy file
+> filea fileb          append file
-> filea fileb          prepend file

Finally, a file can be read and output.

~< file                 output file

(To add one last thing, Perl's documentation categorizes some functions as "operators". For Rulz, most functions are operators.)

STDIN

There are three operators to read STDIN directly (without having to "open" it).

=< [var]                read line from STDIN to $var or $_
_< [var]                read line from STDIN to $var or $_ without EOL
,< [var]                read character from STDIN to $var or $_

Load Rules Operator

A Rule file can be included with the include operator.

.< file                 load

The file being included will not be run and any rules outside of subroutines will be ignored — see href. What this means is that only subroutines will be loaded.

Unlike PHP and Perl, Rulz subroutines can be redefined — any existing subroutine of the same name will be replaced.

There are Rulz builtins for running Rulz programs. See href.

Execution Operator

The execution operator is like PHP or Bash, returning the program's output in $0, or NULL if error.

`whoami`

Or used as an argument:

=var `whoami`

Call Operator

The & (function) operator is for using a function return value as an argument.

This Rule calls time with the return in $0 which is passed to date.

time
date "M d, Y" $0

The & operator turns functions into arguments.

date "M d, Y" &time

Search and Replace Operators

/pattern/               search $_ for pattern
/pattern/ $var          search $var for pattern
/pattern/text/          search $_ and replace with text
/pattern/text/ var      search $var and replace with text

As with variable assignment, the variable name for replace is without the $.

After a successful match, the following special variables are set:

$#                      number of matches
$&                      the string that matched
$1                      the first subexpression that matched; $2 the 2nd, etc.

For search, $0 is set to the number of matches; for replace, the number of replacements.

These are full PCRE strings.

Jump Operator and Labels

:label                  define label
. label                 jump to label
. 3                     jump 3 lines
.. [rule]               exit Rule or program; running optional rule

A jump operator can be preceded by a conditional operator:

! . label               conditional jump to label
? ..                    conditional exit

Variables can be used for jump conditions:

=n 3                    assign $n
. $n                    jump $n lines
=l label                assign $l
. $l                    jump to label $l

Jumps can only be positive or "into the future".

Loop Operators

@do                     while (1)
<rules>
@end
@each [$var]            foreach on $0 or $var (as hash)
<rules>
@end
@for [$var]             foreach on $0 or $var (as list)
<rules>
@end
@until [$var|rule]      while $0 is false or while [$var|rule] is false
<rules>
@end
@while [$var|rule]      while $0 true or while [$var|rule] is true
<rules>
@end

With @for the special variable $_ is set to the array value. With @each the special variable $( is set to the array key, and $) the array value.

These operators cannot be nested.

The following operators can control the loop:

.. [rule]               break
>. [rule]               next
<. [rule]               redo

(These are "modified" jump operators.)

The @until and @while operators have one line versions.

@while <$var|rule> <rule>

With the caveat that for a conditional <rule> the loop condition is $0, which means that the loop will continue or not based on either <rule> setting $0 at some point.

With the loop conditional a variable, the <rule> argument has to set the variable to continue or stop the loop, either through a subroutine or a builtin.

If Else Operators

These are not blocks in the sense of PHP or Perl; but are similar.

@if [$var|rule]          if $0 or $var or rule is true
<rules>
[@else]
[rules]
@end

These operators cannot nest.

Test Operators

Test Operators, based on Bash conditional operators, set $0 with the result of a test on a file — TRUE or FALSE. If the test argument is missing $_ will be used.

f- [file]               file exists
d- [file]               file exists and is a directory
r- [file]               file is readable
w- [file]               file is writable

The following "tests" will return a value other than TRUE for success.

s- [file]               file size
p- [file]               file permissions
t- [file]               file type
g- [file]               file group
a- [file]               file access time
c- [file]               file change time
m- [file]               file modification time

The type test operators test the type of it's argument or $_.

S- [argument]           is string
I- [argument]           is integer
D- [argument]           is double
A- [argument]           is list or hash
N- [argument]           is numeric
B- [argument]           is boolean
U- [argument]           is null
T- [argument]           is true (PHP like)
Z- [argument]           is empty (PHP like)

These return a value other than TRUE.

L- [argument]           integer length if string or count if list
Y- [argument]           string indicating type (PHP like)

The tests are "backward" compared to Perl and Bash, which do -f. But they simply adhere to the "left handedness" of the Rulz language — the - is the base test operator which always requires letter modifiers.

Type Operators

Type Operators are extensions to Test Operators on types, and are similar to PCRE generic character types escapes, POSIX notation for character classes, or PHP ctype functions.

Again, $_ is used if no argument and the boolean result is in $0.

u? [argument]           is uppercase
l? [argument]           is lowercase
d? [argument]           is decimal
s? [argument]           is whitespace 
w? [argument]           is word character
n? [argument]           is alpha numeric
a? [argument]           is alpha
c? [argument]           is control
g? [argument]           is graph
p? [argument]           is printable
v? [argument]           is punctuation
x? [argument]           is hexadecimal

All have an ! version to negate the test. The test is a string and not just a single character. (Though they look it, these are not considered modified conditional operators.)

String Operators

The string operator extensions perform function-like operations on strings. These can be either operators or arguments. As an operator the default is the "return" setting $_. However, missing "main" arguments will default to use $_ as well.

u~ [count] [arg]        to upper case
l~ [count] [arg]        ro lower case
n~ [arg]                length
q~ [arg]                quote meta 
i~ offset [len] [arg]   index (substr)
s~ string [off] [arg]   string occurrence
S~ string [off] [arg]   string occurrence (case insensitive)
p~ string [off] [arg]   string position
P~ string [off] [arg]   string position (case insensitive)
c~ [arg]                chop (PHP like)
C~ [arg]                chomp (Perl like)
t~ [string] [arg]       trim
T~ [string] [arg]       trim right
L~ [string] [arg]       trim left
f~ format arg [args]    sprintf
F~ format arg [args]    sscanf
h~ [arg]                htmlentities
H~ [arg]                htmlspecialchars
x~ [string] [arg]       explode
w~ [len] [string] [arg] wordwrap
r~ string string [arg]  string replace
R~ string string [arg]  string replace (case insensitive)
e~ [arg]                urlencode
E~ [arg]                urldecode
y~ [string] [arg]       crypt
g~ string [arg]         preg split
b~ [string] [arg]       basename
d~ [arg]                dirname

Of note is the "swapping" of the arguments compared to any equivalent builtin function, e.g.

trim $var /
t~ / $var
Rulz makes decisions on argument defaults and types based on the number of arguments.

Examples.

t~
t~ $var
= t~
= t~ $var
= var t~ $var

Which are equivalent to the following rules using the trim function (which defaults to use $_ for a missing argument).

= _ &trim
= _ &trim $var
= &trim
= &trim $var
= var &trim $var

The last example assigns itself. While assignment and arithmetic operators can set a variable, e.g. = var 1 or |= var 1 2, string operators do not have that feature, but can directly modify a variable by reference. (See #Argument Interpolation.)

t~ \$var
Though typically "references" are for functions, e.g. like (PHP) array_pop(&array). A Rulz reference needs a litle help for such functions, e.g. pop \$arr. String operators play a little trick in making trim(&string) act like &string was a reference with t~ \$s.

These operators/arguments are implemented to reduce code.

string operator         string function

t~ /                    = _ &trim $_ /
= t~ $var               = &trim $var
= t~ / $var             = &trim $var /
= b t~ / $a             = b &trim $a /
t~ \$a                  = a &trim $a
u~ t~ $a                = _ &strtoupper &trim $a

Some string operators set $0, like the typical sscanf function.

F~ "24 Lewis Carroll" "%d %s %s" \$id \$first \$last
^$0 $id $first $last

Which produces this output.

3 24 Lewis Carroll

With only two arguments the result is an array in $0.

F~ "24 Lewis Carroll" "%d %s %s"
^$0

Return is an array.

(24,Lewis,Carroll)

Rulz shares Perl's default variable for functions.

= _ "24 Lewis Carroll"
F~ "%d %s %s"
^$0

Return is again an array.

(24,Lewis,Carroll)

Assign to a variable.

=
=v F~ "%d %s %s"
^$0,$v

Still an array and $0 is unchanged.

, (24,Lewis,Carroll)
To make the setting of $_ simpler, it actually has it's own assignment operaror, _. Which is like _ "24 Lewis Carroll".

Another string operator using $0 is the Rulz function verify which works with crypt. Crypt muscledorf with y~, and then use Y~ to verify it.

y~ muscledorf
^$_
Y~ muscledorf
^
Y~ $_ muscledorf
^
Y~ notthehash muscledorf
^

The hash result is in $_; the test result is in $0. (The test function uses $_ as a default if one argument — with the first argument the hash if two.)

$2y$10$c80d82ad2c9e5940448fP.4h/fDSLaLIUzeGr4GNysUwakdVR81Nm
1
1
0

See Crypt Internals for more details.

List Operators

List operators perform Perl/PHP functions. Most create (or modify) lists.

/[ [var] string [string] split
:[ [var] list [string]  join
~[ [var] list           values
%[ [var] list           keys
@[ [var] list           sort
\[ [var] list           reverse
<[ [var] list           shift
>[ [var] list           unshift
-[ [var] list           pop
+[ [var] list           push
,[ [var] list off [len] slice
([ [var] list string    extract
^[ [var] list list      difference

Without var the results are in $_. For @[ and [ list can be a reference to a list.

The ([ operator extracts lists out of a list using string as the "boundary" character.

= a ('a',',','b','c')
([ b $a ,               $b = (('a'),('b','c'))

The ^[ operator returns an array containing all the entries from the first list that are not present in the second list.

Operators that act upon a list.

+[ [var] list           sum
-[ [var] list           subtract
*[ [var] list           product

Operators that act upon a list or a hash.

#[ [var] <list|hash>    count
=[ [var] <list|hash>    index/key exists (boolean)
![ [var] <list|hash>    value exists (boolean)
'[ [var] <list|hash>    value exists (search) returns value
?[ [var] <list|hash>    random value

See also #List Assignment Operations, #List Bitwise Operations and #List Interpolation.

List Operator Alternatives

j[                      join
v[                      values
k[                      keys
s[                      sort
r[                      reverse
p[                      pop
P[                      push
l[                      split
L[                      slice
d[                      difference
i[                      index/key exists
e[                      value exists (boolean)
E[                      value exists (search)

Heredoc

A PHP-like heredoc is supported, with a slightly different syntax.

<<<
Here, here documents are multi-line print statements.
They include interpolation and escapes (\$foo = $foo).
And they end with the string '>>>' on a line by itself.
Identifiers are not used.

Lines are concatenated with spaces; blank lines are 
replaced by a newline.

  * Leading whitespace is preserved.
>>>
<<< var
This heredoc is assigned to a variable.
>>>

By adding a single quote (') the result is a nowdoc.

<<<'
A "nowdoc" does not interpolate $vars and does not convert 
escapes like \\ or even \'.
>>>

The default is actually as if a double quote (") was used. By adding two quotes, single or double, all lines are terminated by a newline.

<<<""
1) Line 1.
2) Line 2.
3) Line 3.
>>>

Filedoc

An extension to heredoc is to output text to a file. This uses the operator >>> and a file name, with the text ending on <<<.

=title "Rulz Programming Language"
>>>"" head.htm
<!DOCTYPE html>
<html>
<head>
<title>$title</title>
</head>
<<<

Compound Conditionals

The #Conditional Operators can test some operators — basically combining two rules in one.

? <rule> <rule>
! f- .. ^$_ not found
! f- $f .. ^$f not found
! &error.log .. ^could not open log file

Similar to basing the conditional test on a variable, here, the conditional test is a rule and only those with operators that set $0 will work as expected.

! ++v ^foo

That rule will always increment $v but will only print foo if $0 "is false".

! ++ ^foo

That rule will always increment $0 but will only print foo if $0 "was false".

Even though a BCF might set $0, they will not work this way.

? function $v ^foo

The ^foo will get passed to the function (as two arguments), which will be called based on $0. This is where the comma operator comes in.

? function $v , ^foo

So, ^foo will run based on the return of function $v.

A limited switch construct can be simulated with comparison operators.

= n &getname
=? $n value &value
=? $n comment &comment

Calling subroutines in this case.

The slower — with regular expressions — but less visually impaired way.

= n &getname
? /value/ $n &value
? /comment/ $n &comment

For an example of parsing program options see href.

Whitespace

Leading and trailing spaces and tabs are ignored. Operators and arguments can be separated by spaces or tabs.

? func
= foo 10
! ++ foo
>? 10
= v ~/*

The jump operator requires a space before it's label. The execution operator ignores leading and trailing spaces within it.

If there is no ambiguity between operator and argument(s) spaces are not required at all.

?func
=foo10
!++foo
>?10
=v ~/*