diff --git a/README.md b/README.md index 43caef5..56b42f4 100644 --- a/README.md +++ b/README.md @@ -4,11 +4,11 @@
![Status](https://img.shields.io/badge/status-proof--of--concept-orange) -![Parser](https://img.shields.io/badge/parser-complete-brightgreen) +![Parser](https://img.shields.io/badge/parser-M0-brightgreen) ![Execution](https://img.shields.io/badge/execution-not--implemented-red) ![License](https://img.shields.io/badge/license-AGPLv3-blue) -**βˆ€ child ∈ world : programming.accessible = true** +**βˆ€ child ∈ world : canCode(child)** [πŸŽ“ For Educators](#for-educators) | [πŸ’» For Developers](#for-developers) | [🌍 For Humanity](#for-humanity) @@ -18,14 +18,16 @@ ## 🚨 Project Status: Proof of Concept -**Important**: MPL is currently a research prototype demonstrating that programming languages can be built from mathematical notation. We have implemented a complete parser that validates the concept, but **programs cannot yet be executed**. This is a vision project seeking contributors to help build the interpreter and runtime. +**Important**: MPL is currently a research prototype demonstrating that programming languages can be built from mathematical notation. We have implemented a working M0 parser that validates the concept, but **programs cannot yet be executed**. This is a vision project seeking contributors to help build the interpreter and runtime. ### What Works Today βœ… -- Complete ANTLR 4 grammar with 70+ mathematical symbols -- Parser that successfully processes all major programming paradigms -- Zero grammar ambiguities -- Comprehensive test suite validating syntax -- ASCII escape sequences for every Unicode symbol + +Every item below is enforced by [CI](.github/workflows/ci.yml) on every push: + +- An ANTLR 4 grammar built from mathematical symbols that compiles with zero errors and zero warnings (warnings are treated as errors) +- All 10 [example programs](examples/) parse (`./gradlew parseExamples`) +- A test suite covering the lexer, the parser, the examples, and every ```` ```mpl ```` code block in this README (`./gradlew test`) +- An ASCII escape sequence for every Unicode symbol ([glyph-escapes.md](glyph-escapes.md)) ### What Doesn't Work Yet 🚧 - **No interpreter** - Programs parse but don't run @@ -51,16 +53,14 @@ Every design decision in MPL must pass one simple test: **Can a 10-year-old non- ### Traditional programming ```python # English required: -for i in range(10): - if i % 2 == 0: - print(i) +for n in [1, 2, 3, 4, 5]: + print(n * n) ``` ### MPL - Universal understanding ```mpl -# Mathematical symbols only: -βˆ€ i ∈ [0,10) : - i % 2 = 0 ? πŸ“€(i) +-- Mathematical symbols only: +βˆ€ n ∈ [1, 2, 3, 4, 5] : ✎(n Γ— n) ``` If Fatima can't understand it with her basic math knowledge, we redesign it. No exceptions. @@ -98,14 +98,14 @@ print("Hello, World!") ```mpl -πŸ“€("Hello, World!") +✎"Hello, World!" ``` English words: print -Universal symbol: πŸ“€ (output) +Universal symbol: ✎ (output/trace) @@ -121,7 +121,7 @@ Write code using mathematical symbols instead of English words. It's that simple ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Mathematical Notation β”‚ -β”‚ Ξ»n: n > 0 ? n Γ— fact(n-1) : 1 β”‚ +β”‚ Ξ»n: (n ≀ 1 ⟹ 1) | (n Γ— fact(n-1)) β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β–Ό @@ -139,30 +139,30 @@ Write code using mathematical symbols instead of English words. It's that simple ### Five ways to write Ξ» (lambda) -1. **πŸ‘† Click** β€” Visual symbol palette -2. **⌨️ Type** β€” `\lambda` transforms automatically -3. **🎀 Speak** β€” "Lambda" in ANY language (Ψ§Ω„ΨΉΨ±Ψ¨ΩŠΨ©, δΈ­ζ–‡, EspaΓ±ol...) -4. **✍️ Draw** β€” Handwriting recognition on tablets -5. **⚑ Shortcut** β€” Platform shortcuts (Cmd+L, Alt+L) +Today the parser accepts two spellings of every symbol: the Unicode glyph (Ξ») and its ASCII escape (`\lambda`). The rest are the input methods we envision tooling for: + +1. **⌨️ Type** β€” `\lambda` (works today, in any editor) +2. **πŸ‘† Click** β€” Visual symbol palette (envisioned) +3. **🎀 Speak** β€” "Lambda" in ANY language (envisioned) +4. **✍️ Draw** β€” Handwriting recognition on tablets (envisioned) +5. **⚑ Shortcut** β€” Platform shortcuts (envisioned)
πŸ”§ Technical details (click to expand) ### Unicode implementation -- Full UTF-8 support with 70+ mathematical operators -- Bidirectional text support for RTL languages -- Font fallback system ensuring symbol visibility +- Full Unicode support, including supplementary-plane symbols (π“œ, 𝔹, πŸ–«) +- Every glyph has exactly one ASCII escape ([glyph-escapes.md](glyph-escapes.md)) ### Parser architecture ``` -Input Methods β†’ Unicode Stream β†’ ANTLR 4 Lexer β†’ AST β†’ - β†’ Type Checker β†’ Optimizer β†’ Code Generation +Input Methods β†’ Unicode Stream β†’ ANTLR 4 Lexer β†’ Parse Tree ``` +Type checking, optimization and code generation are planned, not built. ### Grammar specification -- Zero shift/reduce conflicts -- Validated operator precedence -- Complete coverage of programming paradigms +- Compiles with zero ANTLR errors and warnings (enforced in CI) +- Operator precedence documented in [precedence.csv](precedence.csv) - [View full ANTLR grammar](src/main/antlr4/MPL.g4)
@@ -178,37 +178,40 @@ Input Methods β†’ Unicode Stream β†’ ANTLR 4 Lexer β†’ AST β†’ - **Cultural neutrality** β€” No linguistic imperialism - **Instant comprehension** β€” Symbols map to concepts directly -### 🎨 Multi-modal input +### 🎨 Multi-modal input (envisioned) **Meet learners where they are** +Only ASCII escapes exist today; the rest is the tooling we want to build: + ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Visual β”‚ Voice β”‚ Keyboard β”‚ Handwriting β”‚ -β”‚ Palette β”‚ Input β”‚ Shortcuts β”‚ Recognition β”‚ +β”‚ Palette β”‚ Input β”‚ Escapes β”‚ Recognition β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ Click Ξ» β”‚ Say "lambda"β”‚ Type \lambdaβ”‚ Draw Ξ» β”‚ -β”‚ from menu β”‚ in any lang β”‚ β†’ Ξ» appears β”‚ on screen β”‚ +β”‚ from menu β”‚ in any lang β”‚ (works now) β”‚ on screen β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` -- **Visual palette** β€” Click symbols like emoji -- **Voice input** β€” Speak in your native language -- **Handwriting** β€” Natural for mathematical notation -- **Smart shortcuts** β€” For power users +- **ASCII escapes** β€” `\lambda`, `\forall`, … work in any editor today +- **Visual palette** β€” Click symbols like emoji (envisioned) +- **Voice input** β€” Speak in your native language (envisioned) +- **Handwriting** β€” Natural for mathematical notation (envisioned) ### πŸ“ˆ Progressive complexity **From arithmetic to algorithms** ```mpl -# Level 1: Basic math (everyone knows this!) -x ← 5 + 3 -y ← x Γ— 2 +-- Level 1: Basic math (everyone knows this!) +x ← 5 + 3; +y ← x Γ— 2; -# Level 2: Logic (learned in school) -x > 10 ∧ y < 20 ? πŸ“€("Success!") +-- Level 2: Logic (learned in school) +x > 10 ∧ y < 20 ⟹ ✎"Success!"; -# Level 3: Advanced (natural progression) -βˆ‘(i ∈ [1,100] : iΒ²) β†’ result +-- Level 3: Advanced (natural progression) +squares ← 0; +βˆ€ n ∈ [1, 2, 3, 4, 5] : squares ← squares + n Γ— n; ``` --- @@ -255,16 +258,18 @@ We envision students could progress like this: **Starting point**: Basic math knowledge, no English ```mpl -# Month 1: First program using familiar symbols -πŸ“€("Jambo!") # Hello in their language +-- Month 1: First program using familiar symbols +✎"Jambo!" -- Hello in their language ``` **Growing skills**: Applying math knowledge to programming ```mpl -# Month 6: Using mathematical concepts they know -data ← [23, 45, 67, 34, 89, 12] -average ← (βˆ‘ x ∈ data : x) Γ· |data| -πŸ“€("Average: " + average) +-- Month 6: Using mathematical concepts they know +data ← [23, 45, 67, 34, 89, 12]; +total ← 0; +βˆ€ x ∈ data : total ← total + x; +average ← total Γ· 6; +✎("Average: " + average) ``` **Sharing knowledge**: Teaching others in their community @@ -277,72 +282,66 @@ average ← (βˆ‘ x ∈ data : x) Γ· |data| ## πŸ’» Code examples (Syntax Demonstration) -**Note**: These examples show valid MPL syntax that our parser accepts. However, since we haven't built an interpreter yet, they cannot be executed. +**Note**: These examples show valid MPL syntax that our parser accepts (a test extracts every code block on this page and parses it). However, since we haven't built an interpreter yet, they cannot be executed. + +Some notation you might expect from math class β€” βˆ‘, √, Β², `%` (modulo), |x|, ranges like [1..10] β€” is deliberately absent: it is deferred to milestone M1, where each symbol will arrive together with defined semantics (see [DECISIONS.md](DECISIONS.md)). ### Level 1: Arithmetic thinking πŸ”’ *What every child knows* ```mpl -# Store values (like math class!) -# This syntax is valid and will parse βœ“ -length ← 5 -width ← 3 -area ← length Γ— width -πŸ“€("Area = " + area) +-- Store values (like math class!) +length ← 5; +width ← 3; +area ← length Γ— width; +✎("Area = " + area); -# Make decisions -# Parser accepts this, execution not implemented βœ— -age ← 15 -age β‰₯ 18 ? πŸ“€("Adult") : πŸ“€("Minor") +-- Make decisions: (condition ⟹ result) | fallback +age ← 15; +(age β‰₯ 18 ⟹ ✎"Adult") | ✎"Minor"; ``` ### Level 2: Logical reasoning 🧩 *Natural progression from math* ```mpl -# Find all even numbers (βˆ€ = "for all") -βˆ€ n ∈ [1,20] : - n % 2 = 0 ? πŸ“€(n) +-- Do something for every element (βˆ€ = "for all") +βˆ€ n ∈ [1, 2, 3, 4, 5] : ✎(n Γ— n); -# Sum of squares (just like βˆ‘ in math!) -total ← βˆ‘(i ∈ [1,10] : iΒ²) -πŸ“€("Sum of squares: " + total) +-- Accumulate a running total +total ← 0; +βˆ€ n ∈ [1, 2, 3, 4, 5] : total ← total + n; +✎("Total: " + total); ``` ### Level 3: Real-world applications 🌍 *Solving community problems* ```mpl -# Weather data analysis -temperatures ← [28, 30, 27, 31, 29, 33, 28] -ΞΌ ← (βˆ‘ t ∈ temperatures : t) Γ· |temperatures| -Οƒ ← √((βˆ‘ t ∈ temperatures : (t - ΞΌ)Β²) Γ· |temperatures|) +-- Weather data analysis +temperatures ← [28, 30, 27, 31, 29, 33, 28]; +total ← 0; +βˆ€ t ∈ temperatures : total ← total + t; +ΞΌ ← total Γ· 7; +✎("Average: " + ΞΌ + "Β°C"); -πŸ“€("Average: " + ΞΌ + "Β°C") -πŸ“€("Std Dev: " + Οƒ) - -# Parallel processing (βˆ₯ = parallel) -results ← βˆ₯ { - Ξ±: analyzeRegionNorth() - Ξ²: analyzeRegionSouth() - Ξ³: analyzeRegionEast() -} +-- Parallel processing (β€– = parallel) +results ← analyzeNorth() β€– analyzeSouth() β€– analyzeEast(); ``` ### Level 4: Advanced concepts πŸš€ *For those ready to go deeper* ```mpl -# Neural network layer (yes, AI in symbols!) -layer ← Ξ»(W, b, x): - Οƒ(W Γ— x + b) # Matrix multiplication! - where Οƒ ← Ξ»z: 1 Γ· (1 + e^(-z)) +-- Function composition (∘, straight from math class) +double β‰œ Ξ»n: n Γ— 2; +addOne β‰œ Ξ»n: n + 1; +transform β‰œ double ∘ addOne; +✎(transform(5)); -# Functional programming -map ← Ξ»(f, list): - |list| = 0 ? [] : [f(list[0])] + map(f, list[1:]) - -βˆ€ x ∈ map(Ξ»n: nΒ², [1,2,3,4,5]) : πŸ“€(x) +-- Higher-order functions +apply β‰œ Ξ»f, x: f(x); +✎(apply(Ξ»n: n Γ— n, 6)); ``` --- @@ -352,9 +351,9 @@ map ← Ξ»(f, list): We believe the core innovation of MPL is proving that mathematical notation can replace English keywords. By releasing the parser, we demonstrate this is grammatically possible and invite the community to help build the rest. The parser alone proves several key points: -- Mathematical symbols can express all programming constructs -- A language without English keywords is technically feasible -- The grammar handles real complexity with zero ambiguities +- Mathematical symbols can express the core programming constructs (see the ten [examples](examples/)) +- A language without English keywords is technically feasible +- The grammar compiles with zero ANTLR errors and warnings, enforced in CI - ASCII fallbacks make it universally typeable Sometimes the idea is more important than the implementation. By sharing MPL now, we hope to inspire others to think differently about programming languages and who they exclude. @@ -365,9 +364,10 @@ Sometimes the idea is more important than the implementation. By sharing MPL now ### Grammar specification -- **70+ operators** across 15 categories -- **Zero ambiguities** in ANTLR 4 grammar -- **Proven precedence** through 1000+ test cases +- Every symbol has exactly one meaning and one ASCII escape ([glyph-escapes.md](glyph-escapes.md)) +- Operator precedence is documented in [precedence.csv](precedence.csv) and exercised by the test suite +- The grammar compiles with zero ANTLR errors and warnings (`-Werror`, enforced in CI) +- 200+ syntax assertions across the lexer, parser, example, and documentation test suites - [Full grammar specification](src/main/antlr4/MPL.g4) ### Implementation stack @@ -389,22 +389,17 @@ Sometimes the idea is more important than the implementation. By sharing MPL now β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” -β”‚ Semantic Analysis β”‚ +β”‚ Semantic Analysis (planned) β”‚ β”‚ Type Checking β†’ Effect Analysis β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” -β”‚ Code Generation β”‚ +β”‚ Code Generation (planned) β”‚ β”‚ LLVM β”‚ JVM β”‚ JavaScript β”‚ Python β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` -### Performance metrics - -- **Parse time**: <10ms for 1000 LOC -- **Memory usage**: O(n) with input size -- **Unicode handling**: Zero-copy string processing -- **Error recovery**: Continues parsing after errors +Only the parser stage exists today; the lower stages are the planned architecture. We publish no performance numbers until CI measures them. --- @@ -455,7 +450,7 @@ Sometimes the idea is more important than the implementation. By sharing MPL now ```bash # Clone and build -git clone https://github.com/mpl-lang/mpl +git clone https://github.com/developtheweb/mpl.git cd mpl ./gradlew build @@ -473,7 +468,7 @@ cd mpl - πŸ”§ Language features - πŸ“± Mobile applications -[Contributing guidelines](CONTRIBUTING.md) | [Architecture docs](docs/ARCHITECTURE.md) | [Discord community](https://discord.gg/mpl-lang) +[Contributing guidelines](CONTRIBUTING.md) | [Architecture docs](docs/ARCHITECTURE.md) | [GitHub issues](https://github.com/developtheweb/mpl/issues) ### For researchers πŸ”¬ diff --git a/src/test/java/com/mpl/test/DocumentationTest.java b/src/test/java/com/mpl/test/DocumentationTest.java new file mode 100644 index 0000000..0a6d3fb --- /dev/null +++ b/src/test/java/com/mpl/test/DocumentationTest.java @@ -0,0 +1,42 @@ +package com.mpl.test; + +import org.junit.Assert; +import org.junit.Test; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Documentation-consistency test: every fenced ```mpl code block in the + * project documentation must parse with the shipped grammar. This keeps the + * docs and the grammar from describing different languages. + */ +public class DocumentationTest extends MPLTestBase { + + private static final Pattern MPL_BLOCK = + Pattern.compile("```mpl\\R(.*?)```", Pattern.DOTALL); + + @Test + public void testReadmeCodeBlocksParse() throws IOException { + assertAllMplBlocksParse(Paths.get("README.md")); + } + + private void assertAllMplBlocksParse(Path doc) throws IOException { + String content = Files.readString(doc); + Matcher m = MPL_BLOCK.matcher(content); + int count = 0; + while (m.find()) { + count++; + String code = m.group(1); + ParseResult result = parseWithDiagnostics(code); + if (!result.errors.isEmpty()) { + Assert.fail(doc + " ```mpl block #" + count + " does not parse:\n" + + code + "\nErrors:\n" + String.join("\n", result.errors)); + } + } + Assert.assertTrue("No ```mpl blocks found in " + doc, count > 0); + } +}