I added some basic control structures to the tutorial.
However I left out quite a bit! Here are some extras!

1. Non-local goto
=============

In a felix function only jumps to labels in the function are allowed.
However a procedure can jump to any label in scope not masked by
a function boundary (that is, you cannot jump out of or through a function).

A jump to a label not in the same procedure is called a non-local goto.
For example:

proc f(x:int) {
  proc g() { if x < 0 goto negative; }
  g();
  println$ "Non-negative";
  return;

negative:>
  println$ "Negative";
}

A non-local goto is a bit like throwing and catching an exception.

Non local gotos are not safe. A useful technique is to capture a non-local
goto in a procedure and pass it as an argument to handle errors:

proc doer (x:int, error: 1 -> 0)
{
  if x < 0 call error;
  println$ "Non-negative";
}

proc f(x:int) {
  proc error () { goto error-handler; }
  doer (x, error);
  println$ "OK";

error-handler:>
  println$ "ERROR-Negative";
}

This unwinds the procedure stack like an exception.
This example is safe. However you can write unsafe code
by storing a closure containing a non-local goto somewhere
and calling it after the procedure containing the target has
returned. You can also pass it into a function and call it,
which will not work either.

Although non-local gotos are dangerous they're essential
because often a goto that seems to be local isn't. Inside
some constructions, such as matches, the action bodies
are wrapped in procedures, so a jump out of them whilst
no explicitly in a user defined procedure, are in fact inside
a compiler defined procedure.

On the other hand non-local jumps can be localised
by inlining.

2. break, continue, and redo
======================

Most loops support break, and continue like C, and for loops
also support redo which restarts the loop like continue without
incrementing the control variable.

however unlike C, these three construction REQUIRE a named
loop, and take the name of the loop. For example

myloop:
  while x >0 do
    blah;
    break myloop;
  done

Of course, this means if you have nested loops you can specify
which one to break out of. Much better than C :)

3. Return from
===========

A procedural return can specify which procedure to return from.
This allows "fast exit" from any parent. For example:

proc f() {
  proc g () { return from f; }
}

4. yield
======

A function may yield a value instead of returning it.
If it does so, the function is a generator and must be 
called a generator.

A yielding generator must be formed into a closure and
stored into a variable.

Yielding remembers the point of yield so that a subsequent
invocation restarts just after the yield, so that yield is like
an inside out subroutine call. For example

gen seq () { for var i in 0 upto 2 do yield i; done return -1; }
var seqgen = seq;
println$ seqgen();
println$ seqgen();
...

A yielding generator can be a finite or infinte loop.
If it terminates, then the final value should be returned not
yielded. In this case subsequent calls to the generator will
return the final value repeatedly.

5. Iterators
========

More on request .. :-)
Suffice it to say an iterator is a generator that returns all the values
of a data structure as Some x, and then infinite stream of None.
There's special syntax for using them:

        for v in D do ... done

where D is the data structure. This works for lists, arrays, indeed any
data structure with a suitable generator called "iterator".
There's also an advanced form which pattern matches the
fetched values.

6. Fibres (fthreads) and threads (pthreads).
=================================

And schannels and pchannels.
Which are used to implement pipelines and futures.

Summary: Felix has some of the most advanced control structures of
any programming language. There are two kinds: basic ones, and derived
ones built on top of the basic ones.

For example, there are no while loops or for loops. They're all built
with conditional gotos.

Of the "basic" ones there are two kinds. Ones defined by the compiler,
such as "goto". And ones defined (at least partly) in the C++ RTL.
All the threading and coroutine stuff is defined in the RTL with a single
operation provided by the compiler. The primitive there is 

        _svc argument;

which is a "service request" also called a "software interrupt" or
a "kernel call".


--
john skaller
skal...@users.sourceforge.net
http://felix-lang.org




------------------------------------------------------------------------------
Rapidly troubleshoot problems before they affect your business. Most IT 
organizations don't have a clear picture of how application performance 
affects their revenue. With AppDynamics, you get 100% visibility into your 
Java,.NET, & PHP application. Start your 15-day FREE TRIAL of AppDynamics Pro!
http://pubads.g.doubleclick.net/gampad/clk?id=84349831&iu=/4140/ostg.clktrk
_______________________________________________
Felix-language mailing list
Felix-language@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/felix-language

Reply via email to