F.E.L.T.

Functionally Equivalent Language Translation

SWITCH

(switch expression       ...example:    (switch (parse mode)
   match-1 handler-1                      0             (do-exit)
   (match-2 .. match-2) handler-2         (:h :help :?) (show-help)
   match-3 handler 3                      "l"           (list-files)
   [ default-handler ] )                  (show-unknown-command))

note: You can group clauses as shown for match-2... this will produce multiple case tests for a single handler as you would expect.

See also IF

This tests an expression against various constant values and executes a code block when the first match is found. Exactly how is dependent on the back-end coder but essentially this instruction is the classical "switch-case" statement found in C, C++, PHP, JavaScript et al. The match and handler expressions must be present in pairs. If an odd number of terms is presented, the last expression is evaluated as the 'default' of the switch.


Switch and Case

The FELT SWITCH instruction may look a little different to the PHP or JavaScript equivalent but it is in fact easier to enter as there is less typing involved. The words case, break and default are added automatically by the back-end coder so you don't need to enter them at all.. they are implied by dint of the position of the arguments to SWITCH.

The switch expression

This need not be a simple variable but can be as complicated a FELT expression as you can think of. So long as the final code that is generated is syntactically correct then the expression will be compiled / interpreted and execute as expected.

The case handlers

The case handlers, like socks, are best supplied in two-s. This means that you don't have to waste time typing all that unnecessary stuff, the FELT back-end coders will do that for you. The only potential downside is that precisely because the back-end coder does generate the code for you, there is no way to implement the "technique" of deliberately omitting a "break" so that one handler runs into the next. If that's the kind of code you like to write then FELT probably won't appeal to you that much on that front; it tends to prefer non-clever but reliable code as opposed to sleight-of-hand trickery.

The default handler

It is very common to supply a default handler to catch those values that are either invalid or require some common processing than those specifically picked out by the match handlers. All you have to do to instruct FELT that a handler is a default handler is to place it ** at the end of an odd number of terms** in the instruction. FELT will see that after parsing it has 'one left over' and mark that as being the default handler.

Simple Example

The following example shows a simple handler that could be the top level REPL handler (read-eval-print loop) of some simple terminal based utility. Without going into too many details, it could be implemented like so, note how the default handler is used to print an error about the last command not being recognised.

(defvar quit? #f)
(while (not quit?)
    (emit "foo-console > ")
    (switch (get-command)
      :open (open-file)
      (:quit :exit) (= quit? #t)
      :list (list-files)
      (show-error)))
(emit "foo-console says good-bye!\n")

The PHP code generated from the above FELT source is as follows:

$quit_qm_ = FALSE;
while((!($quit_qm_))) {
  echo "foo-console > ";
  switch(get_command()) {
    case 'open':
        {open_file();}
        break;
    case 'quit': case 'exit':
        {$quit_qm_ = TRUE;}
        break;
    case 'list':
        {list_files();}
        break;
    default:
        {show_error();}
        break;
  }
}
echo "foo-console says good-bye!\n";

And the same code but as JavaScript (Node) looks like this.

var quit_qm_ = false;
while((!(quit_qm_))) {
  console.log("foo-console > ");
  switch(get_command()) {
    case 'open':
        {open_file();}
        break;
    case 'quit': case 'exit':
        {quit_qm_ = true;}
        break;
    case 'list':
        {list_files();}
        break;
    default:
        {show_error();}
        break;
  }
}
console.log("foo-console says good-bye!\n");

By careful planning you can see how easy it is to build language portable code with FELT!