The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

Introduction

Jako is a simple malleable language. It has very little built-in functionality, but it is very easy to build a reasonable language out of it.

Constructs

The basic constructs of Jako are predefined, but the ways in which they combine are programmer-defined.

Words

A word is a contiguous string of characters matching the Perl regular expression m/[A-Za-z][A-Za-z0-9_]*/. Words can be used as the names of types, variables and constants, and can also be used as key words.

Symbols

Symbols are

Expressions

Blocks / Environments

A named block can be executed by passing it to eval.

The section "A Mathematical Note" of [MEYER-2001] presents a model of a class as a set of name-value bindings.

Lesson 3, "Semantic Building Blocks" of [MEAD-2001] describes the environment (or context) of a program at a specific point in its execution in a similar way.

A block is an environment. Names not explicitly bound in that environment are implicitly bound if they are explicitly bound in an ancestor environment.

    bind env E word N any V := { E.N = V; }

Blocklists

Parentheses are used to delimit blocklists. A parenthetical list of expressions is semantically equivalent to the same number of single-expression blocks, one after the other. That is,

    (a < b, 5, i++)

is exactly the same as

    {a < b} {5} {i++}

Definitions

  def

Intrinsic Flow Control Statements

if

goto

    def goto label L := ...

Defining Conventional Constructs

Even though Jako doesn't have conventional constructs built-in, it is very easy to define them using the facilities Jako does provide:

Eiffel-like loops

Translating from Eiffel notation to a Perl-like notation yields something like this:

    from {...} invariant (...) variant {...} until (...) loop {...} end;

where each {...} represents a block of statements and each (...) represents a single boolean expression.

Since the body of the loop is delimited by the braces, we can get rid of the end keyword:

    from {...} invariant (...) variant {...} until (...) loop {...};

Since we are used to using redo to go back to the top of the loop block and re-do the current iteration, we'll replace loop with do:

    from {...} invariant (...) variant {...} until (...) do {...};

Eiffel's variant clause is equivalent to the Perl continue clause:

    from {...} invariant (...) continue {...} until (...) do {...};

But, we like to see that clause at the end:

    from {...} invariant (...) until (...) do {...} continue {...};

Since we've adopted the Perlish continue in place of variant, now invariant seems out of place, but check seems to fit nicely:

    from {...} check (...) until (...) do {...} continue {...};

while

With this Jako definition:

    def while block W ( do? block D ( continue? block C )? )? := {
      var R: typeof(D); # TODO: typeof(D) == block, we want type of *last statement of* D.
      CONT: goto :LAST unless eval W;
      REDO: R = eval D;
      NEXT: eval C;
            goto :CONT;
      LAST: return R;
    }

we can write Perlish while loops:

    i = 0;
    while (x[i] < y[i]) do {
      print "$i\n";
    } continue {
      i++
    }

In fact, we can even write very concise while loops, given the optionality of the do and continue blocks and the equivalence of (x;y) to {x} {y}:

    i = 0;
    while (x[i] < y[i]; print "$i\n"; i++);

(which almost looks like a for loop).

for

This Jako definition:

    def for block F while? block W continue? block C do? block D := {
      var R: typeof(D); # TODO: typeof(D) == block, we want type of *last statement of* D.
      FOR:  eval F;
      CONT: goto :LAST unless eval W;
      REDO: R = eval D;
      NEXT: eval C;
            goto :CONT;
      LAST: return R;
    }

allows us to write for loops the way we are used to, such as:

    for (i = 0; i < l; i++) { print x[i], "\n" }

which is really shorthand for:

    for { i = 0 } { i < l } { i++ } { print x[i], "\n" }

or, more verbosely:

    for {
      i = 0;
    } while {
      i < l
    } continue {
      i++
    } do {
      print x[i], "\n"
    }

redo, next and last

We can define the familiar loop control statements given the consistency of label definitions above:

    def redo ( label L )? := {
      goto L:REDO; # if L not given, means "goto :REDO"
    }

    def next ( label L )? := {
      goto L:NEXT; # if L not given, means "goto :NEXT"
    }

    def last ( label L )? := {
      goto L:LAST; # if L not given, means "goto :LAST"
    }

TODO: Allow x = next? -- What would that mean?

if, then, elseif and else

    def if block I then? block T ( elsif block EI then? block ET )* (else block E)? := {
      var R: typeof(...);
      IF:    goto +:NEXT unless eval I; # "+" --> forward-only
      REDO:  R = eval T;
             goto +:LAST;
      NEXT:  {
        *:IF:    goto :*:NEXT unless eval *EI;
        *:REDO:  R = eval *ET;
                 goto LAST;
        *:NEXT:
      } over elsif
      REDO:  R = eval E;
      LAST: return R;
    }

Object-Oriented Programming

A class is an environment template. An instance is an environment built from such a template. Method application is the execution of code within the instance's environment. For example:

    y = foo.x

means to find 'x' in the environment 'foo' and point 'y' in the current environment at it.

Issues: Multiple inheritance for blocks that represent classes vs. single parents for blocks that represent general code sequences.

Analogy:

    closure : block  ::  instance : class

Instantiation as environment cloning.

self

The word 'self' means the enclosing environment (instance, in the case of an object method).

The word 'class' means the enclosing environment's enclosing environment.

Problem:

    class {
        method x {
            {
                self.y;      # Looks in method
            }
            self.z;          # Looks in instance
        }
        int y;
        int z;
    }

To Do

  • Templates and generic programming

  • Multiple inheritance, renaming and redefinition.

  • Run-time definition and modification of environments.

References

[MEAD-2001]

Mead, Jerud J. and Shende, Anil M. Persuasive Programming, A|B|F Content, Wilsonville, OR, 2001.

[MEYER-1997]

Meyer, Bertrand. "Object-Oriented Software Construction, Second Edition," Prentice Hall PTR, Upper Saddle River, NJ, 1997.

[MEYER-2001]

Meyer, Bertrand. "Overloading vs. Object Technology," Journal of Object-Oriented Programming, October/November 2001 (Vol 14, No. 4).