chharvey / counterpoint

A robust programming language.
GNU Affero General Public License v3.0
2 stars 0 forks source link

Syntax & Semantics: Type Variables #45

Closed chharvey closed 3 years ago

chharvey commented 4 years ago

Type variables are variables that store types. They are only allowed where type expressions are allowed, e.g. in the type declaration part of a varaible declaration (let x: ‹type-expression› = y;). Type variables are only used at compile-time and discarded before assembly code is built.

An example of a type variable declaration:

type T = int | bool;

Wherever the type variable T is used, it will be resolved to the type int | bool. Setting a variable to type T is equivalent to setting it to the definition of T.

let x: T = 42;    % ok, because 42 is an int
let y: T = false; % ok because bool
let z: T = 4.2;   %> TypeError

In this current version, type declarations are replaced in-line when referenced.

% this:
type T = int | bool;
type U = T | null;
type V = float & T;

    % becomes this:
    type U = int | bool | null;
    type V = float & (int | bool);

% and this:
type T = int | bool;
let x: T | null = null;

    % becomes this:
    let x: int | bool | null = null;

In a future version, resolution may be deferred until assignment, allowing recursive types.

In this current version, type declarations must not be recursive. The following is invalid:

type T = bool | T;

In a future version, this or something similar may be permitted.

Lexicon

Keyword :::=
    // storage
+       | "type"
;

Syntax

DeclarationVariable ::= "let" "unfixed"? IDENTIFIER ":" Type "=" Expression ";";
+DeclarationType    ::= "type"           IDENTIFIER "=" Type                ";";

+Declaration ::=
+   | DeclarationVariable
+   | DeclarationType
+;

Statement ::=
    | Expression? ";"
-   | DeclarationVariable
+   | Declaration
    | StatementAssignment
;

Semantics

SemanticDeclarationType
    ::= SemanticAssignee SemanticType;
Decorate(DeclarationType ::= "type" IDENTIFIER "=" Type ";") -> SemanticDeclarationType
    := (SemanticDeclarationType
        (SemanticAssignee
            (SemanticIdentifier[id=TokenWorth(IDENTIFIER)])
        )
        Decorate(Type)
    );

Semantic Errors

Undeclared Variable Reference

If a type variable is referenced but has not been declared, a ReferenceError will be thrown.

type T = U;    % ReferenceError (U is not declared)
let x: U = 42; % ReferenceError (U is not declared)

Temporal Dead Zone

Similarly, if a type variable is referenced lexically before it is declared (above, in source order), a ReferenceError will be thrown. The zone between where a type variable is referenced and where it is declared below is called a “temporal dead zone”.

type T = U;    % ReferenceError (U is used before it is declared)
let x: U = 42; % ReferenceError (U is used before it is declared)
%%
a temporal dead zone!
%%
type U = int;

Duplicate Declaration

If a type variable is declared more than once, an AssignmentError will be thrown.

type T = int;
type T = float; % AssignmentError (duplicate type declaration)