Dialect
The triple script dialect is designed so that every program output by its compiler is valid according to the grammar of ECMA-262. However, the dialect is not a subset of ECMAScript, and it's not JavaScript. (In fact, "This is not JavaScript" is one motto of trplkt, the triple script build tool.)
It's also important to pay attention to the order of implication—which way the figurative arrow is pointing—when we speak about all programs as valid under ECMA-262. The grammar of the triple script dialect does not permit the full range of language elements that the ECMA-262 standard allows to appear in programs; there are constructs that are valid in the ECMA-262 grammar that are not valid for triple scripts.
Many of the dialect's relative limitations are inherent to the restrictions imposed by the concatenated t-block format. The dialect is the result of design constraints that involve retrofitting everything onto an existing platform for reasons of portability and backwards compatibility. Aside from those constraints, there are a number of language design choices made for reasons attributable to taste. (Although, even those tastes are shaped by pragmatism, too). The design choices, where they are truly choices, have are meant to encourage programmers to eschew with cleverness and favor clarity, even if it is boring or slightly less "fun" to write.
Before and after
Triple scripts exist in two forms: pre-compilation and post-compilation. It is an explicit goal that the compiled form remain readable and modifiable (in the sense of "preferred form for modification") with no need for auxiliary files like symbol maps.
Unlike most other languages, compilation is not a destructive process. Given a triple script in compiled form, it's possible for trplkt to recover the original source code of the pre-compilation form with perfect fidelity. This is called automorphism, and it's one of the three invariants that a program written in the triple script dialect must satisfy in order to be a valid triple script.
Rules
Each input module must have zero or one exports. In practice, all source code modules SHOULD have an export, with one exception: the shunting block, which, for all practical purposes, exports nothing. (There is actually no prohibition on an export in the shunting block; it's just not something you should expect to encounter.)
Exports are functions, classes, or let
, const
, or var
declarations
decorated with the export
keyword.
Static imports using the import
keyword are permitted,
but they are of a fixed form:
import { Foo } from "./foo.js"
... which is a (semi) whitespace-sensitive statement that must appear on a single line starting in the first column (i.e. unindented).
Top-level code should be either a static declaration or a static simple assignment. We'll use "static assignment" as shorthand for static simple assigment, so as not to confuse with SSA form. But know that all "static assignments" mentioned with respect to the triple script dialect are of the "simple" form: where the rval is either a constant or a declaration-as-an-expression.
IIFEs are also permitted at the top-level, and they are the go-to way to work around the dialect's restrictions regarding what is permitted in top-level code but scripts SHOULD limit their use to mostly logic-less definitions in the same spirit as the restrictions on top-level code. Every triple script is likely to contain at least one IIFE—in the shunting block.
Formal grammar
Unfortunately, there is no specification for the grammar at this time. Refer to the programs published by triplescripts.org to get an idea of the shape that the grammar will take. Follow the work of this group or check back on this page for developments about the creation of a concrete grammar. Consider bookmarking the trplkt changelog.
Future
Authors should not rely on the fact that a 0.9.x release accepts a given input as evidence that it is valid in the triple script dialect. The compiler reference implementation will change to reject illegal constructs that it currently lets pass through due to undefined behavior. (Technically, though, at this point almost the entire dialect is undefined behavior.) The trplkt source code for the 0.9.x releases itself likely contains problematic syntax that wouldn't pass without errors after the grammar is defined. These are bugs. If they exist, they'll be fixed as the compiler is rewritten on the march towards 1.0.
(The compiler today is not a full-fledged compiler; its partial parsing strategy is the reason that it ignores many errors that will be flagged in future versions. This implementation strategy in the early releases of trplkt reflects the philosophy of starting out by doing the easiest possible thing that works.)
Additionally, the triple script dialect will diverge, semantically, from ECMA-262 implementations in the future. Note that this will be done in such a way that backwards compatibility is still preserved at runtime—the stability of the browser as the universal application runtime is something that the browser makers take seriously and that triplescripts.org takes seriously, too.
In particular, under consideration are native type annotations for post-1.0. (These are already supported in theory, but not used internally in any of the triplescripts.org projects and will need to be standardized.)
Beyond the language, under consideration are:
- a purpose-built runtime (codename "treason") created for the express goal of running triple scripts, to enforce sandboxing on the command-line, and a browser extension, to enforce a capabilities system with even stronger guarantees than browsers themselves impose / make available
- runtime helpers (think Objective-C) in an embeddable payload, to enable the work that wouldn't otherwise be possible without them, especially for use on legacy runtimes