FractalPark
FRM formula language

Write Fractals with FRM

Learn FractalPark's tested FRM subset, understand how source becomes a GPU shader, and build three working formulas from the same examples used by the editor.

01

What Is FRM

FRM is a compact, text-based way to describe an iterative fractal. A formula names its starting state, the calculation repeated for each orbit, and the condition that decides whether iteration continues.

The format grew out of the Fractint ecosystem, where formula files made it possible to exchange experiments without rebuilding the rendering program. FractalPark carries that authoring idea into a browser workflow while documenting its own tested subset instead of claiming complete compatibility.

For the wider project's origins and history, see the Fractint project site.

02

FRM Support in FractalPark

FractalPark tokenizes, parses, validates, and compiles a deliberate FRM subset. The table separates constructs that work directly, constructs with documented FractalPark semantics, and constructs the current workflow cannot preserve.

LevelMeaningVerified scope
SupportedCovered by compiler tests and usable without a semantic qualification.
  • One formula declaration per source document
  • init, loop, and bailout sections
  • Assignments and user variables
  • Real and complex literals; arithmetic, comparison, logical, unary, and magnitude expressions
  • if / elseif / else / endif branches
  • z, c, pixel, zPrev, p1–p5, constants, and tested built-in functions
  • FRM comments
  • Structured diagnostics and FRM-to-GLSL source mapping
AdaptedAccepted with a documented semantic difference or as a FractalPark extension.
  • ismand maps to FractalPark's current Mandelbrot/Julia runtime mode
  • fn1–fn4 use compile-time function dispatch
  • @mode: native, @default-view, and @default-coloring are FractalPark extensions; default directives apply only in native mode
UnsupportedNot preserved by the current compiler or file workflow; rejected rather than silently rewritten.
  • Selecting among multiple formulas in one file
  • Automatic conversion of classic Fractint dialects
  • Arbitrary source directives
  • Non-ASCII identifiers
  • User-defined functions or macros
  • Preprocessor features
  • Any construct rejected by the current compile pipeline

This is a tested compatibility baseline, not a claim of full Fractint compatibility. When the compiler changes, this matrix and its tests must change together.

Verified compatibility

These capability counts come from the versioned manifest: 588 target entries comprise 579 strict-v2 passes and 9 documented waivers; 117 separate entries are excluded with stable reasons.

Target entries
588
Strict-v2 passes
579
Documented waivers
9
Excluded with reasons
117
Bailout descriptor kinds
4
Built-in functions
20

Bailout descriptors

  • C1
  • C2
  • C4R
  • C5

Stable reject reasons

  • unknown-predicate
  • unknown-magnitude-form
  • threshold-not-loop-invariant
  • chained-logical

Built-in functions

  • sin
  • cos
  • tan
  • sinh
  • cosh
  • tanh
  • exp
  • log
  • sqrt
  • abs
  • sqr
  • conj
  • flip
  • recip
  • cabs
  • real
  • imag
  • atan2
  • cosxx
  • cotanh

Parameters: p1, p2, p3, p4, p5 · Function slots: fn1, fn2, fn3, fn4

Capability manifest v1 · strict semantics v2

03

Formula Anatomy

A FractalPark FRM formula has one named declaration and three explicit sections. Together they define the state transition for every pixel.

01

init:

Runs once for a pixel. Set the initial orbit value and any helper variables here.

02

loop:

Runs once per iteration. Update z and any state that the next iteration needs.

03

bailout:

Returns the condition for continuing the orbit. When it becomes false, the point has escaped.

The section names are structural, not comments: omitting or misspelling one produces a diagnostic.

04

Syntax Guide

The language stays intentionally small: expressions describe complex arithmetic, statements update orbit state, and control flow selects among updates.

Declaration and sections
Wrap one named formula in braces, then write init:, loop:, and bailout: in that order.
Values and variables
Use real numbers such as 0.15, complex pairs such as (0.05, -0.02), built-in orbit values, or your own assigned variables.
Expressions
Arithmetic, powers, comparisons, logical operators, unary operators, |z| magnitude syntax, and tested complex functions can be combined.
Control flow
Use if, elseif, else, and endif when an orbit update depends on a condition. Blocks must be balanced.
Built-ins
Core names include z, c, pixel, zPrev, p1–p5, pi, e, maxit, ismand, fn1–fn4, and the functions covered by compiler tests.
Comments and directives
Semicolon comments document source. Recognized @ directives configure FractalPark native behavior; unknown directives are not silently ignored.
05

FRM to AST to GLSL Pipeline

FractalPark does not paste FRM text into a shader. It passes source through a staged compiler so syntax, meaning, generated code, and diagnostics stay connected.

  1. 1

    FRM source

    The exact text from the editor, paste, or local file is the authoritative input.

  2. 2

    Lexer tokens

    The lexer recognizes names, numbers, operators, section markers, comments, and directives while retaining source locations.

  3. 3

    Parsed AST

    The parser builds a structured formula tree and reports malformed declarations, expressions, and control-flow blocks.

  4. 4

    Validation and canonical form

    The validator checks names, types, sections, and supported semantics before a canonical formula is created.

  5. 5

    GLSL and source map

    Code generation emits shader functions and records mappings from generated GLSL back to FRM source.

  6. 6

    Formula plugin

    A successful compile becomes the same formula-plugin contract used by the renderer and shader assembly system.

The shared compiler contract keeps Explore, the standalone Editor, saved custom formulas, examples, and tests on one implementation path.

06

Progressive Tutorials

These examples advance from the smallest quadratic formula to parameters and stateful feedback. Each source block is taken directly from the shared example registry and compiled during tests.

Lesson 1

Starter Mandelbrot

starter-brotOpen in FRM Editor

The smallest escape-time formula, useful for learning the init / loop / bailout structure first.

Focus: the declaration and the init / loop / bailout structure. Change the exponent or escape threshold only after this version compiles.

starter-brot.frm
StarterBrot {
init:
  z = 0
loop:
  z = z^2 + c
bailout:
  |z| < 4
}

Lesson 2

Parameter Drift

parameter-driftOpen in FRM Editor

Demonstrates p1 / p2 parameter slots and the difference between cabs and |z|.

Focus: p1 and p2 parameter slots, a complex literal, and cabs(z) as an explicit magnitude function.

parameter-drift.frm
ParameterDrift {
init:
  z = 0
loop:
  z = z^2 + c + p1 * 0.15 + p2 * (0.05, -0.02)
bailout:
  cabs(z) < 8
}

Lesson 3

Orbit Echo

Uses zPrev as feedback memory and pairs well with orbitEcho coloring for orbit envelopes.

Focus: zPrev as the previous orbit state. Feedback adds memory without introducing a second manually managed state variable.

orbit-echo.frm
OrbitEcho {
init:
  z = pixel
loop:
  z = sqr(z) + zPrev * (0.30, -0.12) + pixel * (0.85, 0.0)
bailout:
  |z| < 48
}

The FRM Editor opens these same compile-checked examples by stable ID. Formula source stays in the current tab until you save it to your cloud library, and is never embedded in the URL.

07

Errors and Diagnostics

Compilation stops at the earliest unsafe stage and reports source-oriented messages. A rejected construct is never rewritten into something that merely looks similar.

Lexical errors

Unexpected characters and unsupported identifiers are reported with their line and column.

Parse errors

Malformed sections, expressions, or control-flow blocks are diagnosed before semantic validation.

Validation errors

Unknown variables, invalid assignments, type mismatches, and unsupported semantics prevent code generation.

Shader source mapping

Generated GLSL retains mappings that can point a shader compilation failure back to the originating FRM location.

When fixing an error, start with the first reported message: later diagnostics can be consequences of the same missing token or invalid expression.

08

Sharing and publishing

A formula you write is private until you choose otherwise. There are three ways it can travel — each explicit, none silent.

  • Private by default

    Formulas live in your cloud library, visible only to you. Artworks you save carry a copy of the formula source inside the draft, so they always open the way you left them.

  • Download the .frm file

    Your formula is plain text. Download it from My Formulas any time and keep your own copy — no export request, no waiting.

  • Publish an artwork, share the source

    Publishing an artwork that uses your formula makes the formula source public under the MIT License: anyone may read, copy, and build on it. The community page shows the formula name from its metadata and offers the source as a download. This cannot be undone for that publication.

The full MIT License text lives at opensource.org.

09

Examples, Next Steps, and References

See the renderer in context

Open Explore to compare built-in formula behavior, coloring, transforms, animation, and export controls before writing a custom formula.

Open Explore

Use the dedicated FRM Editor to compile, preview, import, and download formulas; sign in to save one to your cloud library before handing it off to Explore.

References

Historical context and implementation details are linked separately so the guide can distinguish the Fractint lineage from FractalPark's current compiler contract.