Skip to main content

Morph Language Reference

Status: Living document. This page is a normative sketch of surface syntax. Step-by-step tutorials and runnable patterns live under Docs/learnmorph/.

Morph source files use the .mx extension. Documentation examples use the mx fenced-block tag for .mx surface snippets (same convention as Learn Morph).


Lexical and structure

  • Statements usually end with ;.
  • Modules: module Name; at the top of a file imports another module (resolution searches src/, package modules/, then the standard library). This is not a nested module { } declaration block.
  • Entry point: Init method() { ... } in src/Main.mx is the program entry (no parameters, no return type required).
  • One class per file is enforced when configured (class name matches filename); see Learn Morph Class declaration.

Names and declarations

Variables

Bind with is (recommended for variables). A shorthand without is exists; see Variable declaration.

count is 10;
name is "Morph" as string;
ratio is 0.5; // inferred float

Type annotations use as type after the value:

x is 42 as int;

Bare names can introduce dynamic or typed uninitialized slots; the tutorials spell out the exact forms.

Methods (all functions)

Functions are Name method(params) [as ReturnType] { ... }. Method names are PascalCase (see Method declaration).

Add method(a as int, b as int) as int {
return a + b;
}

Init method() {
Print("hello");
}

Parameters: identifier as Type, comma-separated. Return type: as Type after ); omit for no value (void).

Types: class, struct, enum

Class — reference-style object:

Player class {
health is 100 as int;
}

Struct — value-style aggregate:

Point struct {
x is 0 as int;
y is 0 as int;
}

Enum — named constants; branch with switch / case, not Rust-style match:

Color enum {
Red,
Green
}
switch (c) {
case Color.Red:
Print("red");
break;
default:
break;
}

Generics (classes): Name class<T> { ... } — see Generic classes.

Instantiation: call the type like a method — Player(), Box<int>().


Primitive types (user-facing)

The primary scalar types documented for users are int, float, string, bool. Inference rules: integer literals → int, decimal literals → float, etc. See Primitive types.

There is also dynamic for late-bound or uninitialized slots (tutorial section).


Operators and control flow

  • Arithmetic and comparison: familiar +, -, *, /, ==, !=, <, >, &&, ||, etc., inside ( ... ) where the grammar requires it.
  • if / else / else if: C-style with parentheses around the condition.
  • Loops: for (init; cond; step) { }, while (cond) { }, and range-style / parallel forms described in Learn Morph Control flow.

There is no fn keyword, let bindings, or match expr { pat => ... } surface syntax as in Rust.


Tensors and GPU

  • Import tensor support with module Tensor; (and use Tensor<float> etc.) — see Tensor creation.
  • Element-wise ops: +, -, *, / on tensors.
  • Matrix multiply: binary @.
  • gpu { } blocks: only inside methods; tensor-oriented work; no arbitrary control flow inside the block. See GPU blocks.

Do not use placeholder syntax like tensor<f32, [h, w]> or gpu fn ... in real Morph sources; that is not the taught or documented surface language.


Pointers

Morph uses readable keywords instead of & / *:

p is address of x;
Print(value of p);
value of p is 99;

See Pointers.


Ownership highlights

  • is — bind / alias (shared view of data per language rules).
  • another — deep / independent copy when copying is intended.
  • move — transfer ownership; prior name must not be used afterward.

See Ownership.


Project configuration (morph.toml)

Package dependencies and native (modulecpp) configuration are described in Morph TOML. Typical dependency form:

[dependencies]
example = { github = "owner/repo", version = "^1.0.0" }

Use module PackageName; in .mx sources to consume installed packages — not import as in other languages.


  • Compiler IR: NIR specification — SSA IR and pipeline (implementation-oriented; not a substitute for surface syntax above).