Skip to content

Latest commit

 

History

History
954 lines (718 loc) · 27.9 KB

File metadata and controls

954 lines (718 loc) · 27.9 KB

FROG logo

🐸 FROG Type Specification

Definition of the FROG value type system for .frog programs
FROG — Free Open Graphical Language


Contents


1. Overview

The FROG type system defines how value types are described, serialized, validated, connected, and converted inside a .frog program.

For v0.1, the type system is intentionally small, explicit, and durable. It provides:

  • a fixed set of built-in primitive scalar types,
  • a minimal built-in array type system,
  • a canonical textual type-expression syntax for source serialization,
  • deterministic type identity, compatibility, and coercion rules.

The type system applies to value-carrying elements such as:

  • public interface ports,
  • diagram ports and edges,
  • structure boundaries,
  • widget primary values,
  • typed widget properties or method values when those members are typed,
  • typed configuration values such as default or initial.

This document defines value types only. It does not define widget classes, widget object references, public interface ownership, control-structure semantics, scheduling, execution order, or runtime memory policy.

This document also does not define repository-wide version policy. Top-level spec_version identifies the source-format compatibility target of the containing .frog file, while the published specification corpus version remains governed centrally in Versioning/Readme.md.


2. Scope

This document specifies:

  • canonical source-level type expressions,
  • built-in primitive and array types,
  • type identity rules,
  • type compatibility rules,
  • language-defined implicit coercion rules for values.

This document does not specify:

  • widget object identity or widget-reference semantics,
  • execution scheduling,
  • cycle legality,
  • primitive-local behavior except where typed compatibility is referenced,
  • future runtime, lowering, or IR type systems beyond the canonical source type layer,
  • the repository-wide version-transition doctrine.

3. Goals of the Type System

The FROG type system is designed to satisfy the following goals:

  • Clarity — types MUST be readable and unambiguous in source form.
  • Determinism — type identity, compatibility, and coercion behavior MUST be explicitly defined.
  • Portability — type meaning MUST NOT depend on platform-specific compiler behavior.
  • Graph usability — the system SHOULD support practical graphical programming with limited but useful implicit coercions.
  • Durability — canonical type expressions SHOULD remain stable across editors, validators, runtimes, and future tooling layers.
  • Separation of concerns — value typing MUST remain distinct from widget object models, public interface ownership, authoring metadata, and execution scheduling.

4. Scope for v0.1

FROG v0.1 standardizes a minimal built-in value type system consisting of:

  • primitive scalar types,
  • array types,
  • canonical type-expression syntax,
  • type identity rules,
  • type compatibility rules,
  • implicit numeric coercion rules,
  • implicit array coercion rules based on element coercion and shape preservation.

FROG v0.1 does not yet standardize:

  • user-defined named types,
  • library-defined custom types,
  • records or structs,
  • enums,
  • class types,
  • sum or variant types,
  • generic type declarations beyond arrays,
  • units-of-measure type systems.

Under the centralized cumulative version model, later source-format versions should normally extend earlier valid type forms rather than silently replace them, unless an explicit breaking boundary is declared in repository-wide version governance.


5. Relation with Other Specifications

This document defines the value type system used by other parts of the FROG specification.

  • Interface.md uses the type system for public input and output ports.
  • Diagram.md uses the type system for graph ports, edges, structure boundaries, and typed configuration fields.
  • Widget.md uses the type system for the value_type of value-carrying widgets.
  • Front panel.md serializes widgets that may declare a value_type, but does not redefine the type system.
  • Widget interaction.md may reference typed widget members, but does not redefine type identity or coercion behavior.
  • Libraries/Core.md relies on this document for primitive port typing and typed configuration compatibility such as frog.core.delay.initial.
  • Versioning/Readme.md defines the centralized distinction between specification corpus version, top-level spec_version, and program artifact versioning.

Ownership boundary:

Type.md owns:
- value type expressions
- value type identity
- value compatibility
- implicit value coercion rules

Type.md does not own:
- widget object semantics
- interface ownership structure
- executable graph semantics
- cycle legality
- primitive-local behavioral semantics
- repository-wide version-transition law

6. Location in a .frog File

Types are represented directly where values are declared or constrained. For example, interface ports and other typed elements use canonical textual type expressions such as:

{
  "id": "input_signal",
  "type": "f64"
}

The top-level .frog file does not require a separate mandatory types section in v0.1. Type declarations are embedded inline through canonical type expressions.

This keeps type usage local to the source object that owns the typed value.

Accordingly:

  • top-level spec_version identifies the source-format compatibility target of the file,
  • inline type fields identify value-type meaning inside that source format,
  • the published specification corpus version remains governed centrally in Versioning/Readme.md.

7. Canonical Type Expressions

FROG v0.1 uses a canonical textual syntax to represent types in source files. This syntax is normative.

7.1 Primitive Type Syntax

Primitive types are written as a single identifier:

bool
i8
i16
i32
i64
u8
u16
u32
u64
f32
f64
string

7.2 Array Type Syntax

Dynamic-size arrays are written as:

array<T>

Fixed-size arrays are written as:

array<T, N>

Where:

  • T is any valid FROG v0.1 type expression,
  • N is a positive integer literal.

7.3 Canonical Formatting Rules

  • Type names are case-sensitive.
  • No alternative aliases are defined in v0.1.
  • float64, int32, double, and similar aliases are not canonical type names.
  • Whitespace inside a type expression is not significant for parsing, but canonical serialized form SHOULD omit unnecessary spaces.

Examples of canonical form:

i32
f64
array<u8>
array<f32, 256>
array<array<i16, 8>, 4>

8. Built-in Types

8.1 Boolean

  • bool — logical true/false value.

8.2 Signed Integer Types

  • i8 — 8-bit signed integer
  • i16 — 16-bit signed integer
  • i32 — 32-bit signed integer
  • i64 — 64-bit signed integer

8.3 Unsigned Integer Types

  • u8 — 8-bit unsigned integer
  • u16 — 16-bit unsigned integer
  • u32 — 32-bit unsigned integer
  • u64 — 64-bit unsigned integer

8.4 Floating-Point Types

  • f32 — 32-bit IEEE 754 floating-point value
  • f64 — 64-bit IEEE 754 floating-point value

8.5 String

  • string — textual value.

The exact internal encoding and memory representation of string are not further standardized in v0.1. Only its identity as a distinct built-in type is defined here.


8.6 Array Types

FROG v0.1 defines two built-in array forms:

  • array<T> — array of element type T with dynamic size,
  • array<T, N> — array of element type T with fixed size N.

Array rules:

  • arrays are homogeneous,
  • nested arrays are allowed,
  • fixed-size length is part of type identity,
  • dynamic-size and fixed-size arrays are distinct types.

Examples:

array<f64>
array<u8, 1024>
array<array<f32, 16>, 8>

9. Type Identity

Two types are identical if and only if their canonical meaning is exactly the same.

9.1 Primitive Identity

  • i32 is identical to i32.
  • i32 is not identical to u32.
  • f32 is not identical to f64.
  • string is not identical to array<u8>.

9.2 Array Identity

  • array<f64> is identical to array<f64>.
  • array<f64, 16> is identical to array<f64, 16>.
  • array<f64, 16> is not identical to array<f64, 32>.
  • array<f64> is not identical to array<f64, 16>.
  • array<i32> is not identical to array<u32>.

9.3 Canonical Equality of Type Expressions

Type identity is based on canonical meaning, not on author formatting choices. Whitespace differences that do not change parsing do not change identity.


10. Type Compatibility Model

Type compatibility in FROG v0.1 is defined by the following categories:

  • Exact match — source and target types are identical.
  • Implicit coercion allowed — source and target types are different, but FROG defines deterministic automatic conversion.
  • Explicit conversion required — no implicit coercion is allowed, but an explicit conversion node may make the connection legal.
  • Incompatible — the types are not compatible under v0.1 rules.

Unless otherwise defined, a typed connection or assignment context is valid when:

  • the source and target types are identical, or
  • an implicit coercion is defined by this specification, or
  • an explicit conversion node is inserted by the author.
Compatibility decision model

source type
    |
    v
target type
    |
    +-- identical? -------------------- yes --> valid
    |
    +-- implicit coercion defined? ---- yes --> valid
    |
    +-- explicit conversion inserted? - yes --> valid
    |
    +-- otherwise --------------------------- invalid

This document defines value-type compatibility only. It does not define widget-reference compatibility, UI sequencing compatibility, or execution ordering semantics.


11. Implicit Numeric Coercions

FROG v0.1 allows implicit coercions between numeric scalar types. These coercions are part of the language-defined value-compatibility rules. They are not user-authored diagram nodes in source form.

An IDE MAY visually indicate an implicit coercion, for example by displaying a coercion marker on the target terminal. Such visualization is an IDE concern and does not require an explicit source node.

11.1 Numeric Built-in Types

For the purpose of implicit coercion, the numeric built-in types are:

  • i8, i16, i32, i64
  • u8, u16, u32, u64
  • f32, f64

The following built-in types are not numeric:

  • bool
  • string

11.2 General Numeric Rule

Any numeric scalar type MAY be implicitly coerced to any other numeric scalar type. The conversion result MUST follow the rules below.


11.3 Integer to Integer

When converting from one integer type to another:

  • if the source value is representable in the target type, the result is the exact converted value,
  • if the source value is below the minimum representable target value, the result is the minimum target value,
  • if the source value is above the maximum representable target value, the result is the maximum target value.

This is a saturating conversion.


11.4 Integer to Float

When converting from an integer type to a floating-point type:

  • the conversion follows IEEE 754 numeric semantics for the target floating-point representation,
  • if the integer magnitude exceeds the representable range of the target floating-point type, the result is +Inf or -Inf as appropriate.

11.5 Float to Float

When converting from one floating-point type to another:

  • the conversion follows IEEE 754 semantics for the target type,
  • finite values are converted to the nearest representable value according to the target representation,
  • NaN remains NaN,
  • +Inf remains +Inf,
  • -Inf remains -Inf.

11.6 Float to Integer

When converting from a floating-point type to an integer type:

  • finite values are first truncated toward zero,
  • the truncated value is then saturated to the representable range of the target integer type,
  • NaN converts to 0,
  • +Inf converts to the maximum representable target value,
  • -Inf converts to the minimum representable target value.

11.7 Non-numeric Built-in Types

No implicit coercion is defined in v0.1 for:

  • bool ↔ numeric
  • string ↔ numeric
  • boolstring

12. Implicit Array Coercions

FROG v0.1 allows implicit coercion between array types when:

  • coercion is valid for the array element type, and
  • array shape remains compatible.

12.1 Element-wise Coercion

If T may be implicitly coerced to U, then:

  • array<T> MAY be implicitly coerced to array<U>,
  • array<T, N> MAY be implicitly coerced to array<U, N>.

The coercion is applied element by element.


12.2 Shape Preservation

Implicit array coercion never changes array shape.

  • array<i32, 16> to array<f64, 16> is allowed.
  • array<i32, 16> to array<f64, 32> is not allowed.
  • array<i32> to array<f64> is allowed.
  • array<i32> to i32 is not allowed.

12.3 Dynamic versus Fixed-Size Arrays

Dynamic and fixed-size arrays are distinct types. No implicit coercion is defined in base v0.1 between:

  • array<T> and array<T, N>,
  • array<T, N> and array<T>.

A stricter profile or future extension MAY define explicit conversion mechanisms for such cases, but they are not implicit in v0.1.


12.4 Nested Arrays

Nested arrays follow the same rule recursively. If the inner element-type coercion is valid and shape is preserved at each fixed-size level, the nested array coercion is valid.


13. Typed Value Compatibility Contexts

The following source contexts rely on type compatibility in v0.1:

13.1 Diagram Edges

A diagram edge connecting a source output port to a destination input port is type-valid only if:

  • the source and destination value types are identical, or
  • an implicit coercion is defined by this document, or
  • an explicit conversion node is inserted.

13.2 Interface Defaults

An interface input default value, when present, MUST be compatible with the declared port type. This document defines that compatibility.


13.3 Widget Primary Values

A value-carrying widget value_type MUST be a valid canonical FROG type expression. When the widget participates naturally in the diagram through widget_value, the carried value MUST follow that declared type.


13.4 Widget Properties and Methods

When widget properties or method parameters or results are typed, those types MUST also use valid FROG type expressions or profile-defined extensions compatible with this document.


13.5 Local-Memory Configuration

For typed stateful primitives such as frog.core.delay:

  • the carried input and output value type MUST be well-defined,
  • the initial value MUST be compatible with that carried type.

This document defines compatibility. The state semantics themselves are defined elsewhere.


13.6 Structure Boundaries

When a structure boundary declares a value type, all boundary crossings MUST satisfy the same compatibility rules defined here.


14. Explicit Conversion Nodes

FROG implementations MAY define explicit conversion nodes such as numeric conversion, cast, or type-adaptation nodes. These nodes are distinct from implicit coercions.

An explicit conversion node:

  • is authored intentionally in the diagram,
  • is represented as a real node in source form,
  • MAY be used when no implicit coercion is defined,
  • MAY also be used to make author intent explicit even when an implicit coercion would be legal.

The exact standardized library of explicit conversion nodes is outside the scope of this document in base v0.1. However, the distinction between:

  • implicit language-defined coercion, and
  • explicit authored conversion

is normative.


15. Validation Rules

A FROG validator MUST apply the following rules:

  • every type expression MUST parse successfully according to this specification,
  • every referenced built-in type name MUST be valid,
  • every fixed array size N MUST be a positive integer literal,
  • connections between typed ports MUST be accepted only if they are exact matches, implicitly coercible, or explicitly converted through a node,
  • implicit numeric coercions MUST follow the deterministic rules defined in this document,
  • implicit array coercions MUST preserve shape,
  • implicit coercion between dynamic and fixed-size arrays MUST be rejected in base v0.1,
  • typed configuration values such as default or initial MUST be compatible with their declared type.

A validator MAY report warnings or informational diagnostics for implicit coercions, but if a coercion is defined by this specification, the typed connection is valid.

Validators SHOULD diagnose at least the following error classes:

  • invalid canonical type expression,
  • unknown built-in type name,
  • invalid fixed array size,
  • shape-changing implicit array coercion,
  • attempted implicit dynamic/fixed array coercion,
  • disallowed implicit coercion between non-numeric scalar types,
  • type-incompatible default value,
  • type-incompatible initial value.

These checks validate canonical value-type form and value-compatibility behavior. They do not, by themselves, redefine top-level spec_version policy or repository-wide corpus-version governance.


16. Out of Scope for v0.1

  • user-defined named types,
  • records or structs,
  • enums,
  • class types,
  • sum or variant types,
  • generic type declarations beyond arrays,
  • standardized custom type registries,
  • ownership and borrowing systems,
  • units-of-measure type systems,
  • implicit coercion between dynamic and fixed-size arrays.

17. Examples

17.1 Valid Primitive Type Expressions

bool
i32
f64
string

17.2 Valid Array Type Expressions

array<f64>
array<u8, 1024>
array<array<i16, 8>, 4>

17.3 Identity Examples

  • i32 and i32 are identical.
  • i32 and u32 are not identical.
  • array<f64, 16> and array<f64, 16> are identical.
  • array<f64, 16> and array<f64, 32> are not identical.
  • array<f64> and array<f64, 16> are not identical.

17.4 Valid Implicit Coercions

  • i32f64
  • u8i16
  • f64i32
  • array<i32, 16>array<f64, 16>
  • array<i32>array<f64>

17.5 Invalid Implicit Coercions

  • booli32
  • stringf64
  • array<i32, 16>array<f64, 32>
  • array<i32>i32
  • array<f64>array<f64, 16>
  • array<u8, 16>array<u8>

17.6 Interface Example

"interface": {
  "inputs": [
    { "id": "signal", "type": "array<f64>" },
    { "id": "gain", "type": "f64" },
    { "id": "enable", "type": "bool", "connection": "optional", "default": true }
  ],
  "outputs": [
    { "id": "scaled", "type": "array<f64>" }
  ]
}

17.7 Widget Example

{
  "id": "ctrl_gain",
  "role": "control",
  "widget": "frog.ui.standard.numeric_control",
  "value_type": "f64"
}

17.8 Delay Example

{
  "id": "delay_1",
  "kind": "primitive",
  "type": "frog.core.delay",
  "initial": 0.0
}

In this example, the initial value is compatible with a floating-point carried value type.


18. Summary

The FROG type system provides the canonical value-type foundation for v0.1.

  • It defines built-in primitive and array types.
  • It defines canonical textual type expressions.
  • It defines exact type identity and deterministic compatibility rules.
  • It allows limited implicit coercions for numeric and shape-preserving array cases.
  • It rejects implicit coercion for non-numeric scalar mixes and for dynamic/fixed array mismatches.
  • It remains separate from widget identity, widget references, and UI object semantics.
  • It does not define source-format compatibility law or published specification corpus versioning.

This gives FROG a simple, explicit, portable, and durable type foundation suitable for graphical programming, validation, and future execution-oriented lowering.