Elvelt

EMPL IR

EMPL Types — `mpl::ir::UIRType` and friends

EMPL Types — mpl::ir::UIRType and friends

The type system is declared in MPL_Compiler/core/ir/EMPLTypes.h (88 lines total). It defines the EMPLNodePtr smart-pointer alias, the closed TypeKind enum (32 values), the UIRType struct, the Visibility enum, SourceLocation, and the Parameter struct.

// MPL_Compiler/core/ir/EMPLTypes.h:7
namespace mpl { namespace ir {

class EMPLNode;                                  // fwd decl
using EMPLNodePtr = std::shared_ptr<EMPLNode>;  // line 11

enum class TypeKind { /* … 32 values … */ };    // line 13
struct UIRType { /* … */ };                     // line 50
using UIRTypePtr = std::shared_ptr<UIRType>;    // line 65

enum class Visibility { /* 4 values */ };       // line 67
struct SourceLocation { /* 3 fields */ };       // line 74
struct Parameter { /* 4 fields */ };            // line 80

}}

EMPLNodePtr — the canonical smart-pointer alias

// MPL_Compiler/core/ir/EMPLTypes.h:11
using EMPLNodePtr = std::shared_ptr<EMPLNode>;

Every IR node is heap-allocated and owned via std::shared_ptr. Parent nodes store their children in std::vector<EMPLNodePtr>. Frontends build trees with std::make_shared<ClassDeclNode>() and pass them by value into the appropriate std::vector field.

Convention. Always use the EMPLNodePtr alias — never spell out std::shared_ptr<mpl::ir::EMPLNode> in client code. The legacy alias UIRNodePtr (EMPLNode.h:86) is equivalent.

TypeKind — exhaustive table

TypeKind is the closed tag for UIRType. Each value identifies a kind of type; the actual generic / parameter / return information is carried in the corresponding UIRType fields.

Index TypeKind Meaning Where it lives in UIRType
0 Void No value (return; without expression) kind
1 Bool true / false kind
2 Char Single code unit (rarely used directly) kind
3 Int8 Signed 8-bit kind
4 Int16 Signed 16-bit kind
5 Int32 Signed 32-bit kind
6 Int64 Signed 64-bit kind
7 UInt8 Unsigned 8-bit kind
8 UInt16 Unsigned 16-bit kind
9 UInt32 Unsigned 32-bit kind
10 UInt64 Unsigned 64-bit kind
11 Float32 IEEE-754 single precision kind
12 Float64 IEEE-754 double precision kind
13 BigInt Arbitrary-precision integer (Boost cpp_int in C++) kind
14 String UTF-8 string (std::string in C++) kind
15 Symbol Interned unique value (ES Symbols, etc.) kind
16 Array Fixed-size array elementType, name
17 List Resizable sequence elementType
18 Map Key → value keyType, valueType
19 Set Unique collection elementType
20 Function Callable signature parameterTypes[], returnType
21 Class Class / nominal type name
22 Interface Interface declaration name
23 Enum Enumeration name
24 Optional Nullable wrapper elementType
25 Nullable Like Optional but allows null rather than absent elementType
26 Tuple Heterogeneous fixed-shape typeArguments[]
27 Union Sum of alternatives alternatives[]
28 Intersection Conjoined constraints alternatives[]
29 Any Top type kind
30 Generic Type parameter placeholder name, constraints[]
31 UserDefined Anything else; name carries the source-language identifier name, typeArguments[]
32 Never Bottom type (throw, infinite loop) kind
33 Unknown Default / un-inferred kind

The default value of UIRType::kind is TypeKind::Unknown (line 51) — a freshly-constructed UIRType represents the unknown type and is the appropriate sentinel for "type not yet inferred".

UIRType — the type descriptor struct

// MPL_Compiler/core/ir/EMPLTypes.h:50
struct UIRType {
    TypeKind kind = TypeKind::Unknown;
    std::string name;
    std::vector<std::shared_ptr<UIRType>> typeParameters;  // for generics
    std::vector<std::shared_ptr<UIRType>> typeArguments;   // for instantiations
    std::shared_ptr<UIRType> returnType;                   // Function
    std::vector<std::shared_ptr<UIRType>> parameterTypes;  // Function
    std::shared_ptr<UIRType> keyType;                      // Map
    std::shared_ptr<UIRType> valueType;                    // Map
    std::shared_ptr<UIRType> elementType;                  // Array/List/Set/Optional/Nullable
    std::vector<std::shared_ptr<UIRType>> alternatives;    // Union/Intersection
    std::vector<std::shared_ptr<UIRType>> constraints;     // Generic
    bool isConst = false;
    bool isReadonly = false;
};
using UIRTypePtr = std::shared_ptr<UIRType>;

Field-by-field

Field Type Used when kind is Description
kind TypeKind always The discriminator.
name std::string Class, Interface, Enum, Generic, UserDefined, Array The bare identifier ("Array" for the built-in, "MyClass" for a user class).
typeParameters vector<UIRTypePtr> Class, Interface (declaration sites) The generic parameters, e.g. <T extends Comparable> → one entry with kind=Generic, name="T", constraints=[…].
typeArguments vector<UIRTypePtr> instantiation sites The concrete types bound at instantiation.
returnType UIRTypePtr Function Return type. nullptr for void-returning functions (use kind=Void).
parameterTypes vector<UIRTypePtr> Function Positional parameter types.
keyType UIRTypePtr Map Type of keys.
valueType UIRTypePtr Map Type of values.
elementType UIRTypePtr Array, List, Set, Optional, Nullable Type of elements / wrapped value.
alternatives vector<UIRTypePtr> Union, Intersection Constituent types.
constraints vector<UIRTypePtr> Generic Upper bounds (e.g. T extends number & Comparable).
isConst bool any true for compile-time constants (const X = 42).
isReadonly bool any true for read-only references (readonly T[], const &).

Examples

// "number[]"
UIRType listOfNumber;
listOfNumber.kind = TypeKind::List;
listOfNumber.elementType = std::make_shared<UIRType>();
listOfNumber.elementType->kind = TypeKind::Float64;

// "Map<string, number>"
UIRType mapStringNumber;
mapStringNumber.kind = TypeKind::Map;
mapStringNumber.keyType   = std::make_shared<UIRType>(UIRType{TypeKind::String});
mapStringNumber.valueType = std::make_shared<UIRType>(UIRType{TypeKind::Float64});

// "(x: number) => string"
UIRType arrowType;
arrowType.kind = TypeKind::Function;
auto param = std::make_shared<UIRType>(UIRType{TypeKind::Float64});
arrowType.parameterTypes = { param };
arrowType.returnType = std::make_shared<UIRType>(UIRType{TypeKind::String});

// "string | undefined"
UIRType optString;
optString.kind = TypeKind::Union;
optString.alternatives = {
    std::make_shared<UIRType>(UIRType{TypeKind::String}),
    std::make_shared<UIRType>(UIRType{TypeKind::Void})  // 'undefined'
};

Visibility

// MPL_Compiler/core/ir/EMPLTypes.h:67
enum class Visibility {
    Public,
    Private,
    Protected,
    Internal,
};
Value Meaning
Public Accessible everywhere.
Private Accessible only within the declaring class (or module, in module-internal contexts).
Protected Accessible within the declaring class and its subclasses.
Internal Accessible within the declaring module / assembly / package.

The IR does not store Visibility as a field on declarations directly; rather, the source-language frontend encodes visibility into the type system (e.g. as a Private field on a TS-style declaration) or stores it as metadata on the enclosing node.

SourceLocation

// MPL_Compiler/core/ir/EMPLTypes.h:74
struct SourceLocation {
    std::string filename;
    int line = 0;
    int column = 0;
};
Field Meaning
filename Path of the source file. May be empty if the node is synthesized.
line 1-based line number. 0 if unknown.
column 1-based column number. 0 if unknown.

Every EMPLNode inherits SourceLocation location as a public field (EMPLNode.h:75). Backends use this for diagnostic emission (std::cerr << loc.filename << ":" << loc.line << ": error: …).

Parameter

// MPL_Compiler/core/ir/EMPLTypes.h:80
struct Parameter {
    std::string name;
    UIRTypePtr type;
    EMPLNodePtr defaultValue;
    bool isVariadic = false;
};
Field Meaning
name Parameter identifier. May be empty for positional / variadic parameters.
type Annotated type, or nullptr if un-annotated.
defaultValue A LiteralNode / BinaryOpNode / etc. for the default expression, or nullptr if the parameter is required.
isVariadic true for rest parameters (...args).

Parameter is the typed parameter representation used by FunctionDeclNode::typedParameters (EMPLNode.h:168). Frontends populate BOTH the un-typed parameters: vector<pair<string,string>> (line 167 — (name, sourceText)) and the typed typedParameters: vector<Parameter> (line 168 — full type + default). The C++ backend prefers the typed list; the un-typed list is preserved for fallback name recovery.

See also