Two main FunctionalScript principles:
- if FS code passes validation/compilation, then it doesn't have side-effects,
- the code that passed validation/compilation should behave on FunctionalScript VM the same way as on any other modern JavaScript engine.
FunctionalScript does not whitelist individual JavaScript operations in isolation. It whitelists complete semantic patterns. Some otherwise-forbidden JavaScript constructs may appear only as components of recognized patterns that lower to FunctionalScript primitives.
When we implement features of FunctionalScript, the first priority is a simplification of the VM.
This directory specifies the language that the compiler accepts today: a module of the language described here is exactly a module that
fjs compile <input> <output>compiles. Every feature listed below is recognized by the fjs parser and has
a specification document in this directory.
Everything else — features the parser does not recognize yet, and the design
documents for the VM, I/O, serialization, and the rest of the roadmap — lives
in spec/todo/. A document moves from spec/todo/ to
spec/ when the parser recognizes its feature.
| File Type | Extension | Notes |
|---|---|---|
| JSON | .json |
Tree. |
| FJS source | .f.mjs |
Graph with functions. Authored ESM JavaScript with JSDoc types; the extension does not imply that the current FunctionalScript parser/compiler accepts the module. |
| FJS source | .f.js |
Generated output; must not be authored. |
Once authored .f.js package support is complete, compiler-supported .f.mjs
modules may move to authored .f.js, making .f.js the
compiler-compatibility marker. This migration grows incrementally as compiler
support grows. See fjs/fsc/README.md for the
authoritative extension contract and
todo/migrate-typescript-to-mjs.md for the
repository migration plan.
A JSON document forms a tree of values and is itself a valid FunctionalScript module: JSON is a subset of FunctionalScript.
- JSON.
DJS is the data subset of FunctionalScript: a module denotes a graph of
values — import and const name the shared parts — and a DJS value can be
serialized without additional run-time information.
A module is a sequence of statements. Each statement is terminated by the end of the line; semicolons are not part of the language.
| Statement | Form | Specification |
|---|---|---|
| default import | import name from "./path" |
default-import |
| constant | const name = expression |
const |
| default export | export default expression |
default-export |
export defaultis the last statement of a module; only comments and whitespace may follow it.- Imported and constant names share one namespace: declaring the same name twice is an error.
- A name must be declared before it is used; forward references are not recognized yet.
- An import path is a string literal, resolved relative to the importing module. Each module is parsed and evaluated once per resolved path; a circular dependency is an error.
An expression is a data expression. Function definitions, operators, and property access are not recognized yet — see the roadmap.
| Expression | Example | Specification |
|---|---|---|
null, true, false |
null |
JSON |
| number | -42.5, 3e2 |
JSON number syntax, JSON |
| string | "hello" |
JSON string syntax, JSON |
undefined |
undefined |
undefined |
bigint |
34n |
bigint |
| array | [1, "a"] |
JSON |
| object | { "a": 1 } |
JSON |
| reference | a |
a declared import or const name |
Notes:
- String literals use JSON string syntax at every level: double quotes and JSON escapes. Single quotes, and the full set of JS string spellings, are a deferred feature — see js-string-literals.
- An object property key is a string literal or an identifier (identifier-property).
- Arrays and objects may have a trailing comma (trailing-comma).
Comments are trivia: they may appear between any two tokens and are ignored.
- block-comment —
/* ... */, needed for JSDoc/TypeScript type declarations, - line-comment —
// ....
fjs compile evaluates the input module — resolving every import — and
serializes its exported value. The output file extension picks the format:
fjs compile input.f.js output.f.js # JavaScript module
fjs compile input.f.js output.json # JSON- A JavaScript module output preserves the object graph: a value referenced
more than once is emitted as a
constand stays shared. - A JSON output is a tree, so shared values are expanded, and types that JSON
cannot express (
bigint,undefined) are not available. - Object properties are emitted in sorted key order.
See fjs/djs/README.md for the data language implementation and fjs/fsc/README.md for the compiler.
| # | Feature |
|---|---|
| 1000 | JSON |
| 2110 | default-export |
| 2120 | const |
| 2130 | default-import |
| 2210 | block-comment |
| 2310 | undefined |
| 2320 | bigint |
| 2410 | identifier-property |
| 2420 | line-comment |
| 2430 | trailing-comma |
Everything not listed here — unimplemented language features (§1010, §2.x
remainder, §3 FJS functions), ECMAScript proposals, I/O effects, the
content-addressable VM, object identity, mutability, and serialization — is
in spec/todo/.