JavaScript 68 – progetto di un linguaggio di programmazione – 3

Continuo da qui, copio qui.

Sempre alle prese con l’esercizio lungo 😎 Il post è comprensibile solo come continuazione dei fue precedenti.

L’Ambiente
The environment accepted by evaluate is an object with properties whose names correspond to variable names and whose values correspond to the values those variables are bound to. Let’s define an environment object to represent the global scope.

To be able to use the if construct we just defined, we must have access to Boolean values. Since there are only two Boolean values, we do not need special syntax for them. We simply bind two variables to the values true and false and use those.

var topEnv = Object.create(null);

topEnv["true"] = true;
topEnv["false"] = false;

We can now evaluate a simple expression that negates a Boolean value.

var prog = parse("if(true, false, true)");
console.log(evaluate(prog, topEnv));

Per eseguire lo script nel terminale occorre raccogliere tutti i pezzi di codice visti finora, io li ho messi in p-egg.js, non lo riporto perché sta diventanto lungo:

To supply basic arithmetic and comparison operators, we will also add some function values to the environment. In the interest of keeping the code short, we’ll use new Function to synthesize a bunch of operator functions in a loop, rather than defining them all individually.

["+", "-", "*", "/", "==", "<", ">"].forEach(function(op) {
  topEnv[op] = new Function("a, b", "return a " + op + " b;");
});

A way to output values is also very useful, so we’ll wrap console.log in a function and call it print.

topEnv["print"] = function(value) {
  console.log(value);
  return value;
};

That gives us enough elementary tools to write simple programs. The following run function provides a convenient way to write and run them. It creates a fresh environment and parses and evaluates the strings we give it as a single program.

function run() {
  var env = Object.create(topEnv);
  var program = Array.prototype.slice
    .call(arguments, 0).join("\n");
  return evaluate(parse(program), env);
}

The use of Array.prototype.slice.call is a trick to turn an array-like object, such as arguments, into a real array so that we can call join on it. It takes all the arguments given to run and treats them as the lines of a program.

run("do(define(total, 0),",
    "   define(count, 1),",
    "   while(<(count, 11),",
    "         do(define(total, +(total, count)),",
    "            define(count, +(count, 1)))),",
    "   print(total))");

Aggiorno il file p-egg.js inserendo le ultime aggiunte. Notare che le istruzioni di console.log precedenti vengono commentate.

This is the program we’ve seen several times before, which computes the sum of the numbers 1 to 10, expressed in Egg. It is clearly uglier than the equivalent JavaScript program but not bad for a language implemented in less than 150 lines of code.

Funzioni
A programming language without functions is a poor programming language indeed.

Fortunately, it is not hard to add a fun construct, which treats its last argument as the function’s body and treats all the arguments before that as the names of the function’s arguments.

specialForms["fun"] = function(args, env) {
  if (!args.length)
    throw new SyntaxError("Functions need a body");
  function name(expr) {
    if (expr.type != "word")
      throw new SyntaxError("Arg names must be words");
    return expr.name;
  }
  var argNames = args.slice(0, args.length - 1).map(name);
  var body = args[args.length - 1];

  return function() {
    if (arguments.length != argNames.length)
      throw new TypeError("Wrong number of arguments");
    var localEnv = Object.create(env);
    for (var i = 0; i < arguments.length; i++)
      localEnv[argNames[i]] = arguments[i];
    return evaluate(body, localEnv);
  };
};

Functions in Egg have their own local environment, just like in JavaScript. We use Object.create to make a new object that has access to the variables in the outer environment (its prototype) but that can also contain new variables without modifying that outer scope.

The function created by the fun form creates this local environment and adds the argument variables to it. It then evaluates the function body in this environment and returns the result.

run("do(define(plusOne, fun(a, +(a, 1))),",
    "   print(plusOne(10)))");

run("do(define(pow, fun(base, exp,",
    "     if(==(exp, 0),",
    "        1,",
    "        *(base, pow(base, -(exp, 1)))))),",
    "   print(pow(2, 10)))");

Dopo l’aggiornamento di p-egg.js ecco

😊 😎 😊 manca solo un ultimo post 😊

:megreen:

Posta un commento o usa questo indirizzo per il trackback.

Trackback

Rispondi

Inserisci i tuoi dati qui sotto o clicca su un'icona per effettuare l'accesso:

Logo di WordPress.com

Stai commentando usando il tuo account WordPress.com. Chiudi sessione /  Modifica )

Google photo

Stai commentando usando il tuo account Google. Chiudi sessione /  Modifica )

Foto Twitter

Stai commentando usando il tuo account Twitter. Chiudi sessione /  Modifica )

Foto di Facebook

Stai commentando usando il tuo account Facebook. Chiudi sessione /  Modifica )

Connessione a %s...

Questo sito utilizza Akismet per ridurre lo spam. Scopri come vengono elaborati i dati derivati dai commenti.

%d blogger hanno fatto clic su Mi Piace per questo: