L4 Syntax Reference
L4's syntax is designed to be readable by legal professionals while maintaining the precision needed for computation. This section documents syntax patterns, rules, and special features.
Overview
Key syntax features:
- Layout-sensitive - Uses indentation like Python
- Natural language style - Reads like structured English
- Annotations - Metadata for documentation and generation
- Directives - Compiler commands for testing and evaluation
- Special symbols - Backticks, ditto marks, ellipsis, etc.
Core Syntax Features
Layout Rules
Indentation-based grouping instead of braces.
Key Concepts:
- Blocks defined by indentation level
- Consistent indentation required
- Replaces
{}and;separators - Pythonic style
Example:
-- Example: Layout rules (indentation-based grouping)
-- Demonstrates how indentation defines code blocks
DECLARE Person
HAS name IS A STRING -- Indented: part of declaration
age IS A NUMBER -- Same level: another field
john MEANS Person WITH
name IS "John Doe"
age IS 30
#EVAL john's name
Comments
Documentation and notes in code.
Example:
-- Example: Comments in L4
-- This demonstrates line and block comments
-- This is a line comment
ASSUME age IS A NUMBER -- inline comment
{- This is a
multi-line
block comment -}
ASSUME name IS A STRING
#EVAL age
Note: Both {- -} and /* */ styles work for block comments.
Identifiers
Names for variables, functions, and types.
Example:
-- Example: Identifiers in L4
-- Demonstrates regular and quoted identifiers
-- Regular identifiers
ASSUME age IS A NUMBER
ASSUME taxRate IS A NUMBER
-- Quoted identifiers with spaces
ASSUME `total tax` IS A NUMBER
ASSUME `Section 2(a)` IS A STRING
#EVAL age
Regular: Start with letter, continue with letters/numbers/underscore
Quoted: Use backticks for spaces/special characters
Case Sensitivity:
- Keywords: UPPERCASE only
- Identifiers: Case-sensitive (
age≠Age)
Annotations
Metadata attached to declarations.
@desc
Human-readable descriptions.
Example:
-- Example: Annotations in L4
-- Demonstrates @desc, @nlg, and @ref annotations
@desc "Person's age in years"
ASSUME age IS A NUMBER
@nlg "the applicant's age"
ASSUME applicantAge IS A NUMBER
@ref "Section 4(1)(a) of the Act"
ASSUME eligible IS A BOOLEAN
#EVAL age
@nlg
Natural language generation hints.
Inline form: The applicant [is %age% years old].
See
-- Example: Annotations in L4
-- Demonstrates @desc, @nlg, and @ref annotations
@desc "Person's age in years"
ASSUME age IS A NUMBER
@nlg "the applicant's age"
ASSUME applicantAge IS A NUMBER
@ref "Section 4(1)(a) of the Act"
ASSUME eligible IS A BOOLEAN
#EVAL age
@ref
Cross-references to legal sources.
Inline form: The applicant <<must be at least 18 years old>>.
See
-- Example: Annotations in L4
-- Demonstrates @desc, @nlg, and @ref annotations
@desc "Person's age in years"
ASSUME age IS A NUMBER
@nlg "the applicant's age"
ASSUME applicantAge IS A NUMBER
@ref "Section 4(1)(a) of the Act"
ASSUME eligible IS A BOOLEAN
#EVAL age
@ref-src / @ref-map
Source references and mappings.
See
-- Example: Annotations in L4
-- Demonstrates @desc, @nlg, and @ref annotations
@desc "Person's age in years"
ASSUME age IS A NUMBER
@nlg "the applicant's age"
ASSUME applicantAge IS A NUMBER
@ref "Section 4(1)(a) of the Act"
ASSUME eligible IS A BOOLEAN
#EVAL age
@export
Mark declarations for export.
Example: @export "public_api"
Directives
Compiler commands for testing and evaluation. Directives begin with # and appear at the top level of a file.
#EVAL
Evaluate an expression and display the result. Used for testing functions and inspecting computed values.
Syntax:
#EVAL expression
Examples:
#EVAL `is adult` 21 -- evaluates to TRUE
#EVAL `tax owed` 75000 -- evaluates to the computed number
#EVAL 2 PLUS 2 -- evaluates to 4
See also:
-- Example: Annotations in L4
-- Demonstrates @desc, @nlg, and @ref annotations
ASSUME `person age` IS A NUMBER
@nlg "the applicant's age"
@ref "Section 4(1)(a) of the Act"
#EVAL `person age`
#EVALTRACE
Evaluate an expression and display the full execution trace, showing each step of the evaluation.
Syntax:
#EVALTRACE expression
#TRACE
Evaluate a deontic (regulative) expression and display the obligation trace. Shows the sequence of obligations, which parties must act, deadlines, and the resulting state (FULFILLED or BREACH).
Syntax:
#TRACE deonticExpression AT startTime WITH
PARTY partyName DOES action AT eventTime
...
Examples:
#TRACE paymentObligation AT 0 WITH
PARTY Alice DOES pay 100 AT 15
#TRACE saleContract AT 0 WITH
PARTY Seller DOES delivery AT 2
PARTY Buyer DOES payment 100 AT 5
See also: Regulative Rules for the deontic keywords used with #TRACE
#CHECK
Type check an expression without evaluating it.
Syntax:
#CHECK expression
#ASSERT
Assert that an expression evaluates to TRUE. Used for automated testing.
Syntax:
#ASSERT expression
Example:
#ASSERT 2 PLUS 2 EQUALS 4
Special Syntax
Ditto
Copy from line above using ^.
Example:
-- Example: Ditto (^) syntax
-- Copy tokens from previous line (one ^ per token)
eligible MEANS TRUE
john MEANS eligible
mary ^ ^ -- Copies "MEANS eligible"
alice ^ ^ -- Also copies "MEANS eligible"
#EVAL john
#EVAL mary
#EVAL alice
Rules:
- One
^per token to copy - Copies tokens from line directly above
- Useful for repetitive declarations
OF (Positional Argument Syntax)
Multi-purpose structural keyword that introduces comma-separated argument lists. Without OF, arguments must be space-separated on the same line or indented on subsequent lines.
Contexts where OF appears:
| Context | Example |
|---|---|
| Function application | add OF 3, 4 |
| Sum type declaration | IS ONE OF Red, Green, Blue |
| Type constructor | LIST OF Person |
| Record construction | Pair OF 10, 20 |
| Pattern matching | WHEN Pair OF x, y THEN ... |
Examples:
-- With OF: comma-separated args on one line
result1 MEANS add OF 3, 4
result2 MEANS foldr OF add, 0, numbers
-- Without OF: space-separated on same line
result3 MEANS add 3 4
OF is optional in function application -- add OF 3, 4 and add 3 4 are equivalent. But for multi-argument calls, OF with commas is often clearer than relying on whitespace parsing.
See also: Types reference for OF in type contexts
TO (Function Type Syntax)
Used in function type annotations to separate input types from the return type.
Syntax:
FUNCTION FROM Type1 AND Type2 TO ReturnType
Note: TO is a reserved keyword used only in function type annotations. In deontic rules, to appearing in an action (e.g. deliver goods to buyer) is part of the mixfix expression, not the TO keyword.
Genitive
Record field access using 's.
Example:
-- Example: Genitive ('s) for field access
-- Demonstrates possessive syntax for record fields
DECLARE Person
HAS `full name` IS A STRING
age IS A NUMBER
DECIDE `the applicant` IS Person WITH
`full name` IS "John Doe"
age IS 30
-- Using genitive (reads like English)
DECIDE `applicant age using genitive` IS `the applicant`'s age
-- Equivalent to using THE ... OF
DECIDE `applicant age using THE OF` IS age OF `the applicant`
#EVAL `applicant age using genitive`
#EVAL `applicant age using THE OF`
Section Markers (§)
Organize code into named, nested scopes using §, similar to sections in legislation. Definitions in different sections do not shadow each other; the compiler creates fully qualified name bindings for disambiguation.
Levels:
§-- Top-level section§§-- Subsection§§§-- Sub-subsection
Example:
-- Example: Section markers (§)
-- Demonstrates organizing code into sections
§ `Eligibility Rules`
age MEANS 21
citizen MEANS TRUE
§§ `Age Requirements`
ageEligible MEANS age >= 18
§§ `Citizenship Requirements`
citizenshipEligible MEANS citizen EQUALS TRUE
#EVAL ageEligible
#EVAL citizenshipEligible
Qualified access: When the same name exists in multiple sections, consumers must qualify to disambiguate. This parallels how legislation scopes definitions ("for purposes of subsection 2, X means ...").
§ `Part VII`
§§ `Subsection 2`
`age of majority` MEANS 18
§§ `Subsection 3`
`age of majority` MEANS 21
-- Consumer must qualify:
DECIDE `is adult under sub 2` IF
age >= `Part VII`'s `Subsection 2`'s `age of majority`
Section aliases: Use AKA to create shorter names for qualified references:
§ `Definitions for Part VII` AKA defs
taxableIncome MEANS 50000
result MEANS defs.taxableIncome -- via alias
Literals
Numbers
Integers: 42, -17, 0
Rationals: 3.14, -0.5, 2.718
Strings
Basic: "hello world", "L4 language"
Escape Sequences: \n (newline), \" (quotes), \\ (backslash)
Booleans
TRUE, FALSE
Lists
LIST 1, 2, 3, EMPTY, 1 FOLLOWED BY 2 FOLLOWED BY EMPTY
Symbols
Parentheses
( ) - Grouping and tuples.
Examples: (age PLUS 5) TIMES 2, PAIR OF 1, 2
Brackets
[ ] - Inline NLG annotations.
Example: The applicant [is %age% years old].
Angles
<< >> - Inline reference annotations.
Example: The applicant <<must be 18 or over>>.
Braces
{ } - Block comments (alternative).
Example: {- Block comment -}
Other Symbols
,- Separator;- Statement separator (rarely needed with layout).- Decimal point:- Type signature separator%- Percent numbers, NLG expression delimiter^- Ditto (copy above)...- Asyndetic AND..- Asyndetic OR
Syntax Conventions
Naming Conventions
Variables and Functions:
- camelCase:
taxRate,calculateTotal - snake_case:
tax_rate,calculate_total - Spaces with backticks:
`tax rate`
Types:
- PascalCase:
Person,TaxBracket - Prefer nouns
Constants:
- UPPERCASE:
MAX_AGE,DEFAULT_RATE
Indentation
- 2 spaces or 4 spaces (choose one, be consistent)
- No tabs
- Align related items vertically
Line Length
- Recommended: 80-100 characters
- Legal text may be longer for readability
Style Guide
Readability
- Use whitespace liberally
- Add comments for complex logic
- Prefer textual operators in legal contexts
Consistency
- Follow project conventions
- Use linter/formatter when available
- Be consistent within a file
Legal Isomorphism
- Structure code to mirror legal text
- Use legal terminology in identifiers
- Preserve section/subsection hierarchy
Common Patterns
Type Declarations
Example:
-- Example: Record type declaration
-- Demonstrates product types with named fields
DECLARE Person
HAS `full name` IS A STRING
age IS A NUMBER
-- Example: Creating a person record
`the applicant` MEANS Person WITH
`full name` IS "John Doe"
age IS 30
#EVAL `the applicant`'s `full name`
#EVAL `the applicant`'s age
Function Definitions
Example:
-- Example: Function type
-- Demonstrates function type signature
GIVEN x IS A NUMBER
y IS A NUMBER
GIVETH A NUMBER
add x y MEANS x PLUS y
#EVAL add 5 3
Pattern Matching
Example:
-- Example: Enum type declaration
-- Demonstrates sum types with named constructors
DECLARE Color IS ONE OF
Red
Green
Blue
-- Example usage
`my favorite color` MEANS Red
`name of the color` MEANS
CONSIDER `my favorite color`
WHEN Red THEN "red"
WHEN Green THEN "green"
WHEN Blue THEN "blue"
#EVAL `name of the color`
See Also
- GLOSSARY - Complete feature index
- Functions - Function keywords
- Specifications - Technical specifications