Log in - Edit - History

Fythe

Fythe is intended to be a virtual machine for dynamic languages. Although it is designed for Plof, it is also designed to be broad enough to be useful for other languages, even more static languages.

Fythe is under active development (as of February, 2012). There are versions in JavaScript and C. The C version is an JITting engine. The source to both is available at https://codu.org/projects/fythe/hg/ , and the spec (what little of it is done) is available at https://codu.org/projects/fythe/spechg/ . When more is developed, Fythe's home page will be http://fythe.org/ , until then discussion of Fythe is on the #plof or #fythe channel on FreeNode.

An implementation of Fythe is not an interpreter. It is more akin to a JIT compiler, with the caveat that the definition of the source code is added by code, so the compilation process is defined at runtime. There are two stages, parsing and transformation.

The parsing phase is relatively simple. A definition such as

plof_add "+"n plof_add_next => (PlofAdd $0 $2)

creates a tree (initially similar to an AST) given by the list expression every time the left hand side is parsed.

The transformation phase is more open-ended. The user defines multiple transformation phases. A phase declaration must simply say when the phase goes in terms of a current phase, e.g.

parsing => constantFolding

declares the constantFolding phase to come after the parsing phase.

A phase is a set of transformations. Each may be in one of two forms. The first is a direct tree transformation:

constantFolding (PlofAdd (PlofInteger x) (PlofInteger y)) => (PlofInteger (Add x y))

The left hand side is a pattern to match against, where capitalized elements are literals and lower-case elements are variables to be bound. The right hand side is produced simply by replacing its bound variables with the values attained on the left. The other form of transformation is code transformation (exactly how Plof code would look is not yet clear, so this is just a possibility):

constantFolding (PlofAdd (PlofInteger x) (PlofInteger y)) => plof {
    return new FytheTree([[PlofInteger, bv.x + bv.y]])
}

The advantage of this method is that the value returned by the right hand side may require more complex computation than could be performed otherwise.

In neither case does the returned right hand side need to be a tree. In fact, in the final stage of tree-transformation, it MUST be a function literal (although the production of this function literal is implementation-specific). The produced function literal is the actual code to be run.

A given implementation of Fythe must initially have a parse tree (partially defined in baseparser.txt in the repository) sufficient to provide grammar statements, and tree transformations sufficient to compile them. It must have at least two tree transformation phases, the first of which is named "parsing" which has no actual transformations, and the rest of which have names beginning with a "+" (to indicate that they're internal) and must ultimately reduce a standard set of expressions into runnable code. Note that the "parsing" phase of transformation is not actually the parsing phase, it's named that such that the first phase of transformation is clearly associated with the previous phase of execution, parsing; the "parsing" phase may be purely symbolic and not allow the addition of transformations, as an implementation option.

Fythe values consist of a non-optional heap pointer associated with an optional primitive value. The primitive value types are integers, floating-point numbers, strings and functions. The heap pointers are effectively arrays, and are exposed as such to allow the programmer to have complete control of the object model. Trees (as used by the transformation phase) are arrays containing other arrays and strings, of which those strings associated with Null are symbolic and those associated with any other object are assumed to be string literals (they are not matched against). There is one transformation which produces a callable function from a string; the implementation of this transformation is of course entirely system-dependent.