kurilasyn - Perl Kurila syntax |
kurilasyn - Perl Kurila syntax
A Perl Kurila program consists of a sequence statements which run from the top to the bottom. Loops, subroutines and other control structures allow you to jump around within the code.
Perl Kurila is a layout dependent language, the indentation is an important part of the syntax.
Perl Kurila borrows syntax and concepts from many languages: Perl 5, awk, sed, C, Bourne Shell, Smalltalk, Lisp, Haskell and even English. So if you have programmed in another language you will see familiar pieces in Perl Kurila. They often work the same, but see the perltrap manpage for information about how they differ.
Text from a "#"
character until the end of the line is a comment,
and is ignored. Exceptions include "#"
inside a string or regular
expression.
Blocks are usually made using layout. When a block is expected the column of the first token of block, determines the indentation of the block.
The next token after when a block is expected determines the starting column. A statement is terminated if the next line is equally or less indented as the block. The block is terminated if a line is indented less than the indentation of the block.
Each file or eval string is started with an implicit block with zero indentation.
Empty lines, Comments, Pod and heredocs are ignored for the layout.
The operators @:
, %:
and <:
start a layout based lists.
Similar as with blocks the next token after the operator determines the starting column. And a new list item is started starts at the same starting column. The list is terminated if a line indented less than the starting column.
Instead of using layout to make blocks, they can also be created by
using a {
to start a block. If this is done layout is ignored, and
statements have to be terminated by a semicolon ;
. The block has to
be ended with with a closing brace }
, after which the previous
layout rule is restored.
An example of layout based blocks and statements,
if ($cond) statement1() statement2() + cont_statement2() statement3() else else_statement1()
or equivalent,
if ($cond) statement1() statement2() + cont_statement2() statement3() else else_statement1()
or using layout insensitive syntax,
if ($cond) { statement1(); statement2() + cont_statement2(); } else { else_statement1(); }
The only kind of simple statement is an expression evaluated for its
side effects. A statement can be terminated with a semicolon. Note that there are some operators like try {}
and
do
that look like compound statements, but aren't (they're just
TERMs in an expression), and thus need an explicit termination if used
as the last item in a statement.
The number 0, the strings '0'
and ''
, the empty list ()
, an empty
array @()
, an empty hash %()
and
undef
are all false in a boolean context. All other values are true.
Negation of a true value by !
or not
returns a special false value.
When evaluated as a string it is treated as ''
, but as a number, it
is treated as 0.
Any simple statement may optionally be followed by a SINGLE modifier. The possible modifiers are:
if EXPR unless EXPR while EXPR until EXPR foreach EXPR
The EXPR
following the modifier is referred to as the "condition".
Its truth or falsehood determines how the modifier will behave.
if
executes the statement once if and only if the condition is
true. unless
is the opposite, it executes the statement unless
the condition is true (i.e., if the condition is false).
print $^STDOUT, "Basset hounds got long ears" if length $ear +>= 10; go_outside() and play() unless $is_raining;
The foreach
modifier is an iterator: it executes the statement once
for each element of the array EXPR (with $_
aliased to each item in turn).
print $^STDOUT, "Hello $_!\n" foreach qw(world Dolly nurse);
while
repeats the statement while the condition is true.
until
does the opposite, it repeats the statement until the
condition is true (or while the condition is false):
# Both of these count from 0 to 10. print $i++ while $i +<= 10; print $j++ until $j +> 10;
The while
and until
modifiers have the usual "while
loop"
semantics (conditional evaluated first). Note also that the loop control statements described
later will NOT work in this construct, because modifiers don't take
loop labels.
NOTE: The behaviour of a my
statement modified with a statement
modifier conditional or loop construct (e.g. my $x if ...
) is
undefined. The value of the my
variable may be undef
, any
previously assigned value, or possibly anything else. Don't rely on
it. Future versions of perl might do something different from the
version of perl you try it out on. Here be dragons.
In Perl, a sequence of statements that defines a scope is called a block. Sometimes a block is delimited by the file containing it (in the case of a required file, or the program as a whole), and sometimes a block is delimited by the extent of a string (in the case of an eval).
But generally, a block is delimited by the layout, or delimited by curly brackets, also known as braces. We will call this syntactic construct a BLOCK.
The following compound statements may be used to control flow:
if (EXPR) BLOCK if (EXPR) BLOCK else BLOCK if (EXPR) BLOCK elsif (EXPR) BLOCK ... else BLOCK LABEL while (EXPR) BLOCK LABEL while (EXPR) BLOCK continue BLOCK LABEL until (EXPR) BLOCK LABEL until (EXPR) BLOCK continue BLOCK LABEL for VAR (EXPR) BLOCK LABEL for VAR (EXPR) BLOCK continue BLOCK LABEL loop BLOCK while (EXPR) LABEL loop BLOCK until (EXPR)
The if
statement is straightforward. If you use unless
in place of if
,
the sense of the test is reversed.
The while
statement executes the block as long as the expression is
true.
The until
statement executes the block as long as the expression is
false.
The LABEL is optional, and if present, consists of an identifier followed
by a colon. The LABEL identifies the loop for the loop control
statements next
, last
, and redo
.
If the LABEL is omitted, the loop control statement
refers to the innermost enclosing loop. This may include dynamically
looking back your call-stack at run time to find the LABEL. Such
desperate behavior triggers a warning if you use the use warnings
pragma or the -w flag.
If there is a continue
BLOCK, it is always executed just before the
conditional is about to be evaluated again. Thus it can be used to
increment a loop variable, even when the loop has been continued via
the next
statement.
The next
command starts the next iteration of the loop:
LINE: while (~< $^STDIN) next LINE if m/^#/ # discard comments ...
The last
command immediately exits the loop in question. The
continue
block, if any, is not executed:
LINE: while (~< $^STDIN) last LINE if m/^$/ # exit when done with header ...
The redo
command restarts the loop block without evaluating the
conditional again. The continue
block, if any, is not executed.
This command is normally used by programs that want to lie to themselves
about what was just input.
For example, when processing a file like /etc/termcap. If your input lines might end in backslashes to indicate continuation, you want to skip ahead and get the next record.
while (~< *ARGV) chomp if (s/\\$//) $_ .= ~< *ARGV redo unless eof() # now process $_
which is Perl Kurila short-hand for the more explicitly written version:
LINE: while (defined($line = ~< *ARGV)) chomp($line) if ($line =~ s/\\$//) $line .= ~< *ARGV redo LINE unless eof() # not eof(ARGV)! # now process $line
Note that if there were a continue
block on the above code, it would
get executed only on lines discarded by the regex (since redo skips the
continue block).
If the word while
is replaced by the word until
, the sense of the
test is reversed, but the conditional is still tested before the first
iteration.
The loop control statements don't work in an if
or unless
, since
they aren't loops.
The for
loop iterates over an array and sets the
variable VAR to be each element of the list in turn. If the variable
is preceded with the keyword my
, then it is lexically scoped, and
is therefore visible only within the loop. Otherwise, the variable is
implicitly local to the loop and regains its former value upon exiting
the loop. If the variable was previously declared with my
, it uses
that variable instead of the global one, but it's still localized to
the loop. This implicit localisation occurs only in a for
loop.
The foreach
keyword is a synonym for the for
keyword.
If the array is an lvalue, you can modify it by modifying
VAR inside the loop. Conversely, if the array is NOT an
lvalue, any attempt to modify that element will fail. In other words,
the for
loop index variable is an implicit alias for each element
in the array that you're looping over.
Examples:
for (@ary) s/foo/bar/
for my $elem (@elements) $elem *= 2
for $count (10,9,8,7,6,5,4,3,2,1,'BOOM') print $^STDOUT, $count, "\n"; sleep(1)
for (1..15) print $^STDOUT, "Merry Christmas\n"
foreach $item (split(qr/:[\\\n:]*/, env::var('TERMCAP'))) print $^STDOUT, "Item: $item\n"
Perl Kurila has a mechanism for intermixing documentation with source code. While it's expecting the beginning of a new statement, if the compiler encounters a line that begins with an equal sign and a word, like this
=head1 Here There Be Pods!
Then that text and all remaining text up through and including a line
beginning with =cut
will be ignored. The format of the intervening
text is described in the perlpod manpage.
This allows you to intermix your source code and your documentation text freely, as in
=item snazzle($)
The snazzle() function will behave in the most spectacular form that you can possibly imagine, not even excepting cybernetic pyrotechnics.
=cut back to the compiler, nuff of this pod stuff!
sub snazzle($thingie) .........
Note that pod translators should look at only paragraphs beginning with a pod directive (it makes parsing easier), whereas the compiler actually knows to look for pod escapes even in the middle of a paragraph. This means that the following secret stuff will be ignored by both the compiler and the translators.
$a=3 =secret stuff warn "Neither POD nor CODE!?" =cut back print $^STDOUT, "got $a\n"
You probably shouldn't rely upon the warn()
being podded out forever.
Not all pod translators are well-behaved in this regard, and perhaps
the compiler will become pickier.
One may also use pod directives to quickly comment out a section of code.
Perl Kurila can process line directives, much like the C preprocessor. Using
this, one can control Perl's idea of filenames and line numbers in
error or warning messages (especially for strings that are processed
with eval()
). The syntax for this mechanism is the same as for most
C preprocessors: it matches the regular expression
# example: '# line 42 "new_filename.plx"' /^\# \s* line \s+ (\d+) \s* (?:\s("?)([^"]+)\2)? \s* $/x
with $1
being the line number for the next line, and $3
being
the optional filename (specified with or without quotes).
There is a fairly obvious gotcha included with the line directive: Debuggers and profilers will only show the last source line to appear at a particular line number in a given file. Care should be taken not to cause line number collisions in code you'd like to debug later.
kurilasyn - Perl Kurila syntax |