|
| 1 | +# Design New MDL Syntax |
| 2 | + |
| 3 | +This skill provides guardrails for designing new MDL statements. Read this **before** writing grammar rules, AST types, or executor code for any new MDL feature. |
| 4 | + |
| 5 | +## When to Use This Skill |
| 6 | + |
| 7 | +- Adding a new document type to MDL (e.g., scheduled events, message definitions, REST services) |
| 8 | +- Adding a new action type to microflows (e.g., new activity, new operation) |
| 9 | +- Extending existing syntax with new clauses or keywords |
| 10 | +- Reviewing a PR that adds or modifies MDL syntax |
| 11 | +- Resolving a syntax design disagreement |
| 12 | + |
| 13 | +## Core Principles (Priority Order) |
| 14 | + |
| 15 | +When principles conflict, higher-priority ones win. |
| 16 | + |
| 17 | +### 1. Read Like English |
| 18 | + |
| 19 | +MDL targets citizen developers and business analysts, not software engineers. Statements should read as natural English sentences. |
| 20 | + |
| 21 | +- Use keyword words (`FROM`, `WHERE`, `IN`), not symbols (`->`, `|>`, `=>`) |
| 22 | +- Spell out full words (`MICROFLOW`, `ASSOCIATION`), not abbreviations (`MF`, `ASSOC`) |
| 23 | +- Use prepositions to clarify relationships: `GRANT READ ON Entity TO Role` |
| 24 | + |
| 25 | +**Test**: Read it aloud. A business analyst should understand on first hearing. |
| 26 | + |
| 27 | +### 2. One Way to Do Each Thing |
| 28 | + |
| 29 | +Reuse existing patterns. Never create a second syntax for the same concept. |
| 30 | + |
| 31 | +| Operation | Pattern | Example | |
| 32 | +|-----------|---------|---------| |
| 33 | +| Create | `CREATE [MODIFIERS] <TYPE> Module.Name (...)` | `CREATE PERSISTENT ENTITY Shop.Product (...)` | |
| 34 | +| Modify | `ALTER <TYPE> Module.Name <OPERATION>` | `ALTER ENTITY Shop.Product ADD (...)` | |
| 35 | +| Remove | `DROP <TYPE> Module.Name` | `DROP ENTITY Shop.Product` | |
| 36 | +| List | `SHOW <TYPE>S [IN Module]` | `SHOW ENTITIES IN Shop` | |
| 37 | +| Inspect | `DESCRIBE <TYPE> Module.Name` | `DESCRIBE ENTITY Shop.Product` | |
| 38 | +| Security | `GRANT/REVOKE <perm> ON <target> TO/FROM <role>` | `GRANT READ ON Shop.Product TO Shop.User` | |
| 39 | + |
| 40 | +Do NOT use alternative verbs: `ADD` instead of `CREATE`, `REMOVE` instead of `DROP`, `LIST` instead of `SHOW`, `VIEW` instead of `DESCRIBE`. |
| 41 | + |
| 42 | +### 3. Optimize for LLMs |
| 43 | + |
| 44 | +- Keep patterns regular so one example is sufficient for generation |
| 45 | +- Statements must be self-contained (no implicit state from prior statements) |
| 46 | +- Use consistent keyword order: `<VERB> [MODIFIERS] <TYPE> <NAME> [CLAUSES] [BODY]` |
| 47 | +- Prefer flat statement sequences over deeply nested structures |
| 48 | + |
| 49 | +### 4. Make Diffs Reviewable |
| 50 | + |
| 51 | +- One property per line in multi-property constructs |
| 52 | +- Allow trailing commas |
| 53 | +- `DESCRIBE` output uses deterministic property order |
| 54 | +- Default values omitted unless non-obvious |
| 55 | + |
| 56 | +### 5. Token Efficiency (Without Sacrificing Clarity) |
| 57 | + |
| 58 | +- Omit noise words: `CREATE ENTITY` not `CREATE A NEW ENTITY` |
| 59 | +- Support `OR MODIFY` to avoid check-then-create |
| 60 | +- Allow type inference for obvious cases: `DECLARE $Count = 0` |
| 61 | +- Do NOT use symbols to save tokens at the cost of readability |
| 62 | + |
| 63 | +## Design Workflow |
| 64 | + |
| 65 | +Follow these steps when designing syntax for a new MDL feature. |
| 66 | + |
| 67 | +### Step 1: Check Existing Patterns |
| 68 | + |
| 69 | +Read the MDL Quick Reference: `docs/01-project/MDL_QUICK_REFERENCE.md` |
| 70 | + |
| 71 | +Does an existing pattern cover this? If yes, extend it. Don't invent new syntax. |
| 72 | + |
| 73 | +``` |
| 74 | +New feature: "image collections" |
| 75 | +Existing pattern: CREATE/ALTER/DROP/SHOW/DESCRIBE |
| 76 | +Design: CREATE IMAGE COLLECTION Module.Name (...) |
| 77 | + DESCRIBE IMAGE COLLECTION Module.Name |
| 78 | + SHOW IMAGE COLLECTIONS [IN Module] |
| 79 | +``` |
| 80 | + |
| 81 | +### Step 2: Pick the Statement Shape |
| 82 | + |
| 83 | +Every MDL statement fits one of these shapes: |
| 84 | + |
| 85 | +``` |
| 86 | +DDL: <VERB> [MODIFIERS] <TYPE> <QualifiedName> [CLAUSES] [BODY]; |
| 87 | +DML: <ACTION> <TARGET> [CLAUSES]; |
| 88 | +DQL: <QUERY-VERB> <TYPE>S [FILTERS]; |
| 89 | +``` |
| 90 | + |
| 91 | +If your feature doesn't fit any shape, it may belong as a CLI command (`mxcli <subcommand>`) rather than MDL syntax. |
| 92 | + |
| 93 | +### Step 3: Choose Keywords |
| 94 | + |
| 95 | +1. Reuse existing keywords first (check reserved words in grammar) |
| 96 | +2. Use SQL/DDL verbs: `CREATE`, `ALTER`, `DROP`, `SHOW`, `DESCRIBE`, `GRANT`, `REVOKE`, `SET` |
| 97 | +3. Use Mendix terminology: `ENTITY` not `TABLE`, `MICROFLOW` not `FUNCTION`, `PAGE` not `VIEW` |
| 98 | +4. Prepositions clarify structure: `FROM`, `TO`, `IN`, `ON`, `BY`, `WITH`, `AS`, `WHERE`, `INTO` |
| 99 | + |
| 100 | +### Step 4: Write the Property List |
| 101 | + |
| 102 | +All property-bearing constructs use this format: |
| 103 | + |
| 104 | +```mdl |
| 105 | +CREATE <TYPE> Module.Name ( |
| 106 | + Property1: value, |
| 107 | + Property2: value, |
| 108 | +); |
| 109 | +``` |
| 110 | + |
| 111 | +Rules: |
| 112 | +- Parentheses `()` delimit property lists |
| 113 | +- Colon `:` separates key from value |
| 114 | +- Comma `,` separates properties |
| 115 | +- Trailing comma allowed |
| 116 | +- One property per line (single line acceptable for 1-2 properties) |
| 117 | + |
| 118 | +### Step 5: Validate |
| 119 | + |
| 120 | +Run these checks before finalizing syntax design: |
| 121 | + |
| 122 | +1. **Read aloud test** — Does it read as English? Can a business analyst understand it? |
| 123 | +2. **LLM generation test** — Give one example to an LLM, ask for a variant. Does it get it right? |
| 124 | +3. **Diff test** — Change one property. Is the diff exactly one line? |
| 125 | +4. **Pattern test** — Does it follow CREATE/ALTER/DROP/SHOW/DESCRIBE? If not, why? |
| 126 | +5. **Roundtrip test** — Can `DESCRIBE` output be fed back as input? |
| 127 | + |
| 128 | +## Anti-Patterns (DO NOT) |
| 129 | + |
| 130 | +### Custom Verbs for Standard Operations |
| 131 | + |
| 132 | +```mdl |
| 133 | +-- WRONG: custom verb |
| 134 | +SCHEDULE EVENT Shop.Cleanup ... |
| 135 | +REGISTER WEBHOOK Shop.OnOrder ... |
| 136 | +
|
| 137 | +-- RIGHT: standard CREATE |
| 138 | +CREATE SCHEDULED EVENT Shop.Cleanup (...) |
| 139 | +CREATE WEBHOOK Shop.OnOrder (...) |
| 140 | +``` |
| 141 | + |
| 142 | +### Implicit Module Context |
| 143 | + |
| 144 | +```mdl |
| 145 | +-- WRONG: implicit state |
| 146 | +USE MODULE Shop; |
| 147 | +CREATE ENTITY Customer (...); |
| 148 | +
|
| 149 | +-- RIGHT: explicit qualified name |
| 150 | +CREATE ENTITY Shop.Customer (...); |
| 151 | +``` |
| 152 | + |
| 153 | +### Symbolic Syntax |
| 154 | + |
| 155 | +```mdl |
| 156 | +-- WRONG: requires learning symbol meanings |
| 157 | +$items |> filter($.active) |> map($.name) |
| 158 | +
|
| 159 | +-- RIGHT: keyword-based |
| 160 | +FILTER $Items WHERE Active = true |
| 161 | +``` |
| 162 | + |
| 163 | +### Positional Arguments |
| 164 | + |
| 165 | +```mdl |
| 166 | +-- WRONG: meaning unclear without docs |
| 167 | +CREATE RULE Shop Process Order ACT_ProcessOrder |
| 168 | +
|
| 169 | +-- RIGHT: labeled properties |
| 170 | +CREATE RULE Shop.ProcessOrder ( |
| 171 | + Type: Validation, |
| 172 | + Microflow: Shop.ACT_ProcessOrder, |
| 173 | +); |
| 174 | +``` |
| 175 | + |
| 176 | +### Keyword Overloading |
| 177 | + |
| 178 | +```mdl |
| 179 | +-- CAUTION: SET already means variable assignment in microflows |
| 180 | +-- Don't reuse it to mean property modification elsewhere unless established |
| 181 | +``` |
| 182 | + |
| 183 | +## Checklist |
| 184 | + |
| 185 | +Before merging any PR that adds new MDL syntax, verify: |
| 186 | + |
| 187 | +- [ ] Follows `CREATE`/`ALTER`/`DROP`/`SHOW`/`DESCRIBE` pattern |
| 188 | +- [ ] Uses `Module.Element` qualified names (no bare names) |
| 189 | +- [ ] Property lists use `( Key: value, ... )` format |
| 190 | +- [ ] Keywords are full English words (no abbreviations) |
| 191 | +- [ ] Statement reads as English (aloud test passed) |
| 192 | +- [ ] One example sufficient for LLM generation |
| 193 | +- [ ] Small change = one-line diff |
| 194 | +- [ ] No new keyword overloading |
| 195 | +- [ ] No implicit context dependency |
| 196 | +- [ ] `DESCRIBE` roundtrips to valid MDL |
| 197 | +- [ ] Grammar regenerated (`make grammar`) |
| 198 | +- [ ] Quick reference updated (`docs/01-project/MDL_QUICK_REFERENCE.md`) |
| 199 | +- [ ] Full-stack wired: grammar, AST, visitor, executor, DESCRIBE |
| 200 | + |
| 201 | +## Related Resources |
| 202 | + |
| 203 | +- Full design rationale: `docs/11-proposals/PROPOSAL_mdl_syntax_design_guidelines.md` |
| 204 | +- MDL Quick Reference: `docs/01-project/MDL_QUICK_REFERENCE.md` |
| 205 | +- Implementation workflow: `.claude/skills/implement-mdl-feature.md` |
| 206 | +- Existing syntax proposals: `docs/11-proposals/PROPOSAL_mdl_syntax_improvements.md` |
| 207 | +- Grammar file: `mdl/grammar/MDLParser.g4` |
0 commit comments