From 27763495bcfe265507ca98aedc1c7064bf1e0e4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emmanuel=20M=2E=20Smith=F0=9F=94=B8?= Date: Wed, 5 Aug 2026 16:12:17 +0200 Subject: [PATCH] lexer: add seven more unicode operators (#26074) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit closes nim-lang/RFCs#571 Adds `⟑ ⟇ ⩓ ⩔ ■ □ ☆` with the same priority as `*`. Co-authored-by: Claude Co-authored-by: Andreas Rumpf --- changelog.md | 5 +++++ compiler/lexer.nim | 17 ++++++++++++++--- doc/manual.md | 4 ++-- tests/lexer/tunicode_operators.nim | 23 +++++++++++++++++++++++ 4 files changed, 44 insertions(+), 5 deletions(-) diff --git a/changelog.md b/changelog.md index 172769b820..024d607dee 100644 --- a/changelog.md +++ b/changelog.md @@ -137,6 +137,11 @@ parameter and result types, not just their source-level shape. Use See the [experimental manual](https://nim-lang.github.io/Nim/manual_experimental.html#typeminusbound-overloads) for more information. +- Seven more Unicode characters are now parsed as operators, implementing the RFC + https://github.com/nim-lang/RFCs/issues/571: `⟑ ⟇ ⩓ ⩔ ■ □ ☆`. They all have the + same priority as `*` (multiplication). As with the other Unicode operators, Nim + only lexes them; their meaning is up to user code. + ## Compiler changes - Fixed a bug where `sizeof(T)` inside a `typedesc` template called from a generic type's diff --git a/compiler/lexer.nim b/compiler/lexer.nim index 9c0b803602..bc94542cc2 100644 --- a/compiler/lexer.nim +++ b/compiler/lexer.nim @@ -845,8 +845,8 @@ proc getCharacter(L: var Lexer; tok: var Token) = const UnicodeOperatorStartChars = {'\226', '\194', '\195'} - # the allowed unicode characters ("∙ ∘ × ★ ⊗ ⊘ ⊙ ⊛ ⊠ ⊡ ∩ ∧ ⊓ ± ⊕ ⊖ ⊞ ⊟ ∪ ∨ ⊔") - # all start with one of these. + # the allowed unicode characters ("∙ ∘ × ★ ☆ ⊗ ⊘ ⊙ ⊛ ⊠ ⊡ ∩ ∧ ⊓ ⟑ ⟇ ⩓ ⩔ ■ □ + # ± ⊕ ⊖ ⊞ ⊟ ∪ ∨ ⊔") all start with one of these. type UnicodeOprPred = enum @@ -878,7 +878,18 @@ proc unicodeOprLen(buf: cstring; pos: int): (int8, UnicodeOprPred) = elif buf[pos+2] == '\159': result = 3.a # ⊟ elif buf[pos+2] == '\160': result = 3.m # ⊠ elif buf[pos+2] == '\161': result = 3.m # ⊡ - elif buf[pos+1] == '\152' and buf[pos+2] == '\133': result = 3.m # ★ + elif buf[pos+1] == '\150': + if buf[pos+2] == '\160': result = 3.m # ■ + elif buf[pos+2] == '\161': result = 3.m # □ + elif buf[pos+1] == '\152': + if buf[pos+2] == '\133': result = 3.m # ★ + elif buf[pos+2] == '\134': result = 3.m # ☆ + elif buf[pos+1] == '\159': + if buf[pos+2] == '\135': result = 3.m # ⟇ + elif buf[pos+2] == '\145': result = 3.m # ⟑ + elif buf[pos+1] == '\169': + if buf[pos+2] == '\147': result = 3.m # ⩓ + elif buf[pos+2] == '\148': result = 3.m # ⩔ of '\194': if buf[pos+1] == '\177': result = 2.a # ± of '\195': diff --git a/doc/manual.md b/doc/manual.md index 5732947133..2d7618f1d1 100644 --- a/doc/manual.md +++ b/doc/manual.md @@ -712,8 +712,8 @@ Unicode Operators These Unicode operators are also parsed as operators: - ∙ ∘ × ★ ⊗ ⊘ ⊙ ⊛ ⊠ ⊡ ∩ ∧ ⊓ # same priority as * (multiplication) - ± ⊕ ⊖ ⊞ ⊟ ∪ ∨ ⊔ # same priority as + (addition) + ∙ ∘ × ★ ☆ ⊗ ⊘ ⊙ ⊛ ⊠ ⊡ ∩ ∧ ⊓ ⟑ ⟇ ⩓ ⩔ ■ □ # same priority as * (multiplication) + ± ⊕ ⊖ ⊞ ⊟ ∪ ∨ ⊔ # same priority as + (addition) Unicode operators can be combined with non-Unicode operator diff --git a/tests/lexer/tunicode_operators.nim b/tests/lexer/tunicode_operators.nim index 6ad40beab6..93e430fcb9 100644 --- a/tests/lexer/tunicode_operators.nim +++ b/tests/lexer/tunicode_operators.nim @@ -14,3 +14,26 @@ var y = 45 y *= 9 + 4 * 3 assert x == y + +proc `⟑`(x, y: int): int = x * y +proc `⟇`(x, y: int): int = x * y +proc `⩓`(x, y: int): int = x * y +proc `⩔`(x, y: int): int = x * y +proc `■`(x, y: int): int = x * y +proc `□`(x, y: int): int = x * y +proc `☆`(x, y: int): int = x * y +proc `★`(x, y: int): int = x * y + +assert 2 + 3 ⟑ 4 ⟇ 5 ⩓ 6 ⩔ 7 ■ 8 □ 9 ☆ 10 ★ 11 == 2 + 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11 + +proc `⟑=`(x: var int, y: int) = x *= y + +proc `⩓++`(x, y: int): int = x * y + +var z = 45 +z ⟑= a⩓++4⟑3 + +var w = 45 +w *= 9 * 4 * 3 + +assert z == w