Skip to main content

Phase 13.0. Builtins

FieldValue
MEPMEP-46 (extension sub-phase)
StatusLANDED
Started2026-05-26 15:30 (GMT+7)
Landed2026-05-26 15:35 (GMT+7)
Tracking issue
Tracking PR

Goal-alignment audit

String operations, math builtins, numeric casts, and list aggregates are used in virtually every real Mochi program. Without them, programs that manipulate text, compute with abs/floor/ceil, cast float to int, or aggregate lists (min, max, sum) cannot compile to BEAM. This phase unblocks a wide class of programs that already pass the vm3 backend.


Sub-phase 13.0: string, math, list aggregate builtins

String operations

Mochi builtinBEAM lowering
len(s)string:length(S)
upper(s)string:uppercase(S)
lower(s)string:lowercase(S)
s.contains(sub)binary:match(S, Sub) =/= nomatch
s[i]mochi_str:index(S, I)
substring(s, start, end)mochi_str:substring(S, Start, End)
reverse(s)mochi_str:reverse(S)
str(x)mochi_str:convert(X)
split(s, sep)mochi_str:split(S, Sep)
join(xs, sep)mochi_str:join(Xs, Sep)

string:length/1 counts Unicode codepoints (same semantics as Mochi's len on strings).

mochi_str:index/2 and mochi_str:substring/3 use string:to_graphemes/1 + lists:nth/2 / lists:sublist/3 to operate on codepoint sequences, then re-encode via unicode:characters_to_binary/1.

mochi_str:convert/1 dispatches on the runtime type: integer_to_binary/1 for integers, float_to_binary/1 for floats, atom_to_binary/2 for booleans.

s.contains(sub) uses binary:match/2 which returns nomatch or {Start, Length}. The lowerer wraps this in erlang:'=/='/2 to produce a boolean, consistent with vm3 semantics (no start index returned).

Math builtins

Mochi builtinBEAM lowering
abs(n) (int)erlang:abs(N)
abs(f) (float)erlang:abs(F)
floor(f)erlang:floor(F)
ceil(f)erlang:ceil(F)

All four are OTP BIFs inlined by the BEAM JIT on OTP 27. erlang:abs/1 is overloaded for both integer and float; the BEAM dispatcher selects the correct implementation at runtime based on tag bits.

Numeric cast

Mochi builtinBEAM lowering
int(f)erlang:trunc(F)

erlang:trunc/1 truncates toward zero, matching vm3's int(f) semantics (which uses Go's int(f) conversion, also truncation toward zero).

List aggregates

Mochi builtinBEAM lowering
min(xs)lists:min(Xs)
max(xs)lists:max(Xs)
sum(xs)lists:sum(Xs)
val in xslists:member(Val, Xs)

lists:min/1, lists:max/1, lists:sum/1 are standard OTP functions. lists:member/2 takes (Elem, List) (note order), which is opposite to the aotir ListContainsExpr{Value, List} field order; the lowerer passes them as [Val, List] accordingly.


Runtime modules

mochi_str.erl (extended) adds: index/2, substring/3, reverse/1, convert/1, split/2, join/2.

No new runtime modules were needed for math builtins (all OTP BIFs) or list aggregates (all standard lists module functions).


Test set

5 fixtures under tests/transpiler3/beam/fixtures/phase13/; TestPhase13Builtins runs all and diffs vs expected output.

#FileDescription
11001100_str_lenlen/1 on strings
11011101_str_upper_lowerupper/1, lower/1
11021102_str_containss.contains(sub)
11031103_math_builtinsabs, int cast
11041104_list_aggregatesmin, max, sum, in