F.E.L.T.

Functionally Equivalent Language Translation

Coding for JavaScript

First of all, please please please read the PHP guidelines and make sure that you have a basic understanding of how and what FELT is actually trying to do.

There are major differences between PHP and JavaScript as you would expect and of course, FELT in no way tries to translate run-time library calls, that would be a Herculean task. The onus is on you to ensure that any functions that are called at run-time for the JavaScript code are firmly locked and loaded.

Some useful resources

Before continuing it's worth mentioning a very useful JavaScript site that I have come across that will help you write portable code more easily.

Phpjs.org

This is a truly amazing site, one of those projects that just had to exist and when you find it you can't believe it's for real!

You can find it here: Phpjs.org

In a nutshell it contains JavaScript equivalents of the major PHP functions that a typical application might use. I don't think it contains all of them, and some are impossible to re-create because of the security model that is in place when JavaScript runs inside a browser, and if you wish to help them extend the coverage then I am sure that they will be more than happy!

The current PHP/JavaScript Functions list is available on this page. You won't be disappointed.

Formatted Printing

If you just want a sprintf() like function then this site also has a JavaScript implementation that I have used and found to be very good: JavaScript sprintf

It is a very slick and clever utility that saves an awful lot of mucking about with strings, especially for formatting numbers and dates and things.

Including Files

In the JavaScript back-end the REQUIRE group of instructions will generate a SCRIPT tag that will allow files to be included for web-use etc.

Here is a full example that shows how you might include some files for three different language generation modes, and the we shall show the code generated for each:

(#f:when JSCoder
  (require "http://mysite/file1.js")
  (require "http://mysite/file2.js"))

(#f:when NodejsCoder
  (require "local-fs-file1.js")
  (require "local-fs-file2.js"))

(#f:when PHPCoder
  (require "../some/folder/file1.php")
  (require "../some/folder/file2.php"))

;; now we continue with all files loaded...

And the output, from the command line as shown...

$ felt docex.felt -as nodejscoder
require("local-fs-file1.js");
require("local-fs-file2.js");


$ felt docex.felt -as jscoder
<script type="text/javascript" src="http://mysite/file1.js"></script>
<script type="text/javascript" src="http://mysite/file2.js"></script>


$ felt docex.felt -as phpcoder
require("../some/folder/file1.php");
require("../some/folder/file2.php");
sean@sean-desktop:~/tmp$ 

NOTE: In the FELT code the coder names must match including the case but the command line tool doesn't care.

Creating Classes

First of all, there are no interfaces in JavaScript. Secondly, @@ isn't really an OO language, it in fact belongs to a family of languages called "prototype based" languages. Your humble author can vaguely remember back in the '80-s downloading a language called "Self" and playing with it as he was into Smalltalk in a big way then. Squeak!

If you think JavaScript is new and funky, you need to learn your history!

Anyway, given that JavaScript is not an "OO" language as such but one that provides a means to "do" "OO" in a very effective and practical way, there is, as usual, "more than one way to do it!".

FELT chooses the seemingly most popular way of defining a class as a function that defines public properties and public functions. Therefore note that in FELT, for now at least, JavaScript functions and properties will always be public. That's the way it is, accept it, deal with it and move on! ;)

Constructors

In FELT there is a specially recognised function name, ctor, that will be treated in a "special" way by the back-end coders such that they will use that as as signal that the function name may be different in the final code.

It's probably easiest to just define a simple class with some functions and properties and then see what comes out, it saves me typing a lot and you get to see how things are in code:

(class Foo
  (mvar
   (age 0)
   (name ""))

  (defun ctor (anAge aName)
    (= (my :age) anAge)
    (= (my :name) aName))

  (defun announce ()
    (emit (my :name) " says he is " (my :age) " years old")))

;; Show that our class works
(defvar peep (new Foo 47 "Eric"))
(emit peep)
(-> peep (announce))

HINT: Cut and paste this into the REPL window and execute it with Node.js selected as the back-end and use the developer tools to view the JavaScript console and you will the see the output.

Rendering the above through the Node.js backend so we can use the console as stdout generates the following code:

function Foo (anAge, aName) {
this.age = 0;
this.name = "";
this.age = anAge;
this.name = aName;

this.announce = function()
{console.log(this.name+ " says he is "+ this.age+ " years old");}

}

var peep = new Foo(47, "Eric");
console.log(peep);
peep.announce();

and if we pipe that through "node" we get this:

$ felt docex.felt -as nodejscoder | node
{ age: 47, name: 'Eric', announce: [Function] }
Eric says he is 47 years old