F.E.L.T.

Functionally Equivalent Language Translation

DEFUN / FUNCTION

(defun func-name ( [ p1 p2 .. pN ] ) body)
(function func-name ( [ p1 p2 .. pN ] ) body)
(defun+ func-name ( [ (p1 "Hello") ] ))   ; acl: public,    p1 defaults to a string value
(defun# func-name ( [ (p1 :ref) ] ))      ; acl: protected, p1 is a reference variable
(defun- func-name ( [ (p1 ()) ] ))        ; acl: private    p1 defaults to 'NULL'
(defun* ( [ p1 p2 ] ) body )              ; anonymous function with two parameters

This instruction is one of the most widely used in FELT. A DEFUN instruction must be followed by the name of the function (unless DEFUN* is used) and then the parameters enclosed in (). If there are no parameters then the parentheses remain empty but they must be present. A parameter can be a simple name, thing, a name and a default expression within parentheses, (thing "Hello") and finally it can be a mutable reference parameter, again within parentheses: (thing :ref). The form () will be translated into the value for NULL/nil/void etc. for the selected output language. Understand DEFUN and you also understand DEFUNC, FUNCTION and FUNCTIONC.


Alternative Forms

If you are defining a class method / function then this instruction, DEFUN is the same as defining a method that has public access. FELT supports the notion of methods that can be "public", "private" or "protected" and in order to express those intentions you can choose from the following:

Instruction Visibility
DEFUN public
DEFUN+ public
DEFUN- private
DEFUN# protected


This pattern of characters at the end is also the same for when you want to declare a class method or "static method", for which you should refer to the DEFUNC page for more information.

Anonymous Functions

There is a variation on the DEFUN form that allows you to declare a function that has no name, just a signature and a body. This is used a lot for the javaScript (JSCoder) back-end and also in the PHP back-end. FELT is clever enough to see if your version of PHP supports anonymous functions (PHP5.3+) or not and acts accordingly; if you have them it uses them, if you don't it will generate a unique name for that function and at the call site the name of that function is emitted and then in the "post-render" phase of translation the actual functions will be rendered out. For most of the time this works just fine and causes no troubles, and is completely transparent to you as a developer.

Closures

You can create closures using the DEFUN* form but FELT itself has absolutely no bearing at all on whether or not it will work as success ultimately depends completely and utterly on the chosen output language.

All I can tell you is that for PHP, for example, if you follow "the rules" relating to closures and anonymous functions with respect to scope (see PHP -- Anonymous functions then you should be fine, the code that comprises this site makes use of them in plenty of places and it works as you would expect it to.

Function Signatures

FELT allows most types of function signatures to be created, including default parameters and reference parameters. Not all languages support these features so again, be careful about what you are doing. If you try to use a feature that is not supported in a particular language then the core classes (those that come with FELT out of the box) will generate a warning message in the rendered code. Anybody else that writes a back-end coder should also follow the same principles.

Parameter Typing

On the surface of it FELT would appear to fall into the category of "loosely typed" as defining parameters doesn't include specifying a type. FELT was initially written to allow PHP code to be created using a LISP like syntax but it kind of grew from there when I realised that, given the amount of effort that I was putting into it, I might as well tackle all loosely-typed languages at the same time and even then, in the back of my mind I was hatching a plan to cope with typed languages as well. That will come later, for now let's continue in the loosely typed world of languages...

Standard parameters

Let's define a function that takes two parameters and then returns the result of adding them together. Remember that this doesn't actually mean the function will work at run-time because if the parameters are of different types and the language doesn't allow the addition of such things then get the mop and bucket ready. PHP however does allow such things, as do some other languages. Here's the function definition and the PHP:

(defun add-em-up (p1 p2)
  (return (+ p1 p2)))

which gives this as PHP output:

function add_em_up($p1, $p2) {
  return ($p1 + $p2); }

Nothing too exciting there which is what we want; good clean normal run-of-the-mill parameters. And remember that FELT allows you to name parameters using almost any printable characters as it converts them into a valid form for the chosen back-end language, for example, lets re-do the above with some funkier names all round:

(defun vals->total (val#1 val#2)
  (return (+ val#1 val#2)))

and the javaScript code produced is:

function vals__gt_total($val_hash_1, $val_hash_2) {
  return ($val_hash_1 + $val_hash_2); }

Looks kind of interesting but it is still valid PHP nonetheless and will run just fine. The point is that FELT allows you greater expressivity of variable and function naming which hopefully means more readable intentions. I have said before that FELT doesn't care for good looking output code as I don't want you to look at anything except FELT code. If it works, it works. Your code repositories will be full of FELT code which is of course beautiful to look at being essentially LISP to look at. ;)

Default parameters

FELT allows you to define parameters that can have what is commonly referred to as a "default" value, sometimes these are referred to as "optional" parameters. Again not all languages support this and the back-end coders will adapt accordingly.

Here is the initial example function but this time the second parameter has been modified so that "by default" it will add one to the first parameter, the output this time is again PHP for reference with the original but javaScript is also shown as a comparison because javaScript does not have this facility. If you think you will be needing this feature then the best way is to design your functions to take a single array that contains keys and values and go from there.

(defun vals->total (val#1 (val#2 1))
  (return (+ val#1 val#2)))

and the PHP code from the above is:

function vals__gt_total($val_hash_1, $val_hash_2 = 1) {
  return ($val_hash_1 + $val_hash_2); }

And for a quick reference you can see that the javaScript output just doesn't do anything with the default and assumes normal operation. This is one of the things to keep in mind when writing code that you think you may want to re-use on a different target!

function vals__gt_total(val_hash_1, val_hash_2) {
  return (val_hash_1 + val_hash_2); }

which translates into this javaScript code:

function vals__gt_total(val_hash_1, val_hash_2) {
  return (val_hash_1 + val_hash_2); }

Reference (mutable) parameters

FELT supports the notion of mutable parameters, often referred to as "reference" parameters by many languages and sometimes as "out" parameters in other systems. Essentially they are alterable by the function being executed.

To declare a reference parameter in felt, all you do is place the keyword :ref after the name of the variable and enclose them in parentheses. Let's re-write the example so that this time we return nothing but write the answer back into the reference parameter passed in that will the total:

(defun add-em-up (p1 p2 (total :ref))
    (= total (+ p1 p2)))

which renders into this PHP code;

function add_em_up($p1, $p2, &$total) {
  $total = ($p1 + $p2); }

Parameter Types and Return Types

This has been one of the more interesting and challenging parts of creating FELT and whilst it may look a little ungly in places, it does work and currently the Java back-end is functional but not yet ready for general release until I am happy that it is good enough to do Android development.

Simply, by taking advantage of the fact that FELT allows most printable characters to be used in a variable name and a function name, those back-end coders that produce typed languages will look for the "reverse solidus" or, more commonly "/" (foward slash) and infer from the characters after it a type for the the function or variable.

The Java coder has a built in set of types that it will recognise. They are listed in full in the Java Coder Documentation pages but for clarity here is a short example of a class in FELT that produces a Java class that when run produces a familiar greeting:

(class Greeting
       (defunc+ main/v (args/as)
     (emit "Hello World")))

And the following console session shows how that translates into Java code and then compiles it and runs it:

$ felt greeting.felt -as javacoder

class Greeting {
  public static void main(String[] args)
    {System.out.println("Hello, World!");}
}

$ felt docex.felt -as javacoder -o Greeting.java
$ javac Greeting.java 
$ java Greeting
Hello, World!

So, FELT can and does support typed languages but it is a little early for me to say exactly how this will pan out. I am working on this and I think that what I have in mind will be good enough, which is usually all that is required to make things work. It involves each "typed" coder having a built in set of types plus the ability for you as the FELT developer to "plug-in" your own set of abbreviations and by following some simples rules, that should be all you need to manage typed output. For now, using the Java coder is definitely classed as experimental as it is not offically ready for release but I have made it available nonetheless.