Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Stage 7: AST Translation (lfe_translate.erl)

Purpose: Translate between LFE forms and Erlang Abstract Format.

Module: lfe_translate.erl (2,182 LOC - second largest) - Location: src/lfe_translate.erl

Bidirectional translation:

%% LFE → Erlang
to_expr(LFEForm, Line) -> ErlangAST
to_expr(LFEForm, Line, {Imports, Aliases}) -> ErlangAST

%% Erlang → LFE
from_expr(ErlangAST) -> LFEForm
from_expr(ErlangAST, Line) -> LFEForm

Key translation examples:

%% Data constructors
[quote, E]           → {atom, Line, E}  (for atoms)
[cons, H, T]         → {cons, Line, H', T'}
[list | Es]          → nested cons / {nil, Line}
[tuple | Es]         → {tuple, Line, [E1', ...]}
[binary | Segs]      → {bin, Line, Segments}
[map | KVs]          → {map, Line, Assocs}

%% Functions
[lambda, Args, Body]     → {'fun', Line, {clauses, [Clause]}}
[match-lambda | Clauses] → {'fun', Line, {clauses, Clauses}}

%% Control flow
[if, Test, Then, Else]   → {'case', Line, Test, [...]}
[case, Expr, Clauses]    → {'case', Line, Expr, Clauses}
[receive | Clauses]      → {'receive', Line, Clauses}
[try, Expr, ...]         → {'try', Line, ...}

%% Function calls
[funcall, F | Args]      → {call, Line, F', Args'}
[call, M, F | Args]      → {call, Line, {remote, Line, M', F'}, Args'}
[F | Args]               → {call, Line, {atom, Line, F}, Args'}

Pattern translation:

Patterns use similar syntax but different semantics:

  • Variables become {var, Line, Var}
  • [= Pat1 Pat2] becomes alias patterns
  • Maps become {map_pat, Line, [...]}

Guard translation:

Guards have restricted expressions:

  • BIFs only (no user functions)
  • Comparisons: >, >=, <, =<, ==, =:=, /=, =/=
  • Arithmetic: +, -, *, /, div, rem, band, bor, bxor, bnot, bsl, bsr
  • Boolean: and, or, xor, not, andalso, orelse
  • Type tests: is_atom, is_integer, is_list, etc.

Import/alias resolution:

During translation, the {Imports, Aliases} context resolves:

  • Imported function calls → remote calls
  • Module aliases → full module names

Example:

;; With import: (from lists (map 2))
(map fun list)  →  {call, Line, {remote, Line, {atom, Line, lists}, {atom, Line, map}}, [Fun', List']}