asc-community / asc-community/AngouriMath

π is a free variable, Cyrillic е is a different variable from e, and х + x has two variables that print identically

Open
#1,260 2 comments 0 reactions 0 assignees View on GitHub
Accepted Proposal
Dominant language
C#
Stars
831
Forks
79
Avg merge
3h 23m
Merged PRs (30d)
309

Description

Split out of the discussion on #1242, because it is true today and independent of whether Unicode printing is ever added.

The `VARIABLE` lexer rule admits Greek, Greek Extended and Cyrillic alongside Latin:

```
VARIABLE: ('a'..'z'|'A'..'Z'|'Ͱ'..'Ͽ'|'ἀ'..'῿'|'Ѐ'..'ӿ')+ ('_' (…))? ;
```

Named constants are matched by **name** (`Variable.ConstantList`, keyed `pi` and `e`). The two facts together produce three traps, measured on `2dbeedf7`:

```
simplify(sin(pi)) => 0 simplify(sin(π)) => sin(π) -- π is U+03C0, a free variable
simplify(ln(e)) => 1 simplify(ln(е)) => ln(е) -- е is U+0435, Cyrillic
vars(х + x) => х, x -- х is U+0445; two variables
```

1. **`π` is not `pi`.** Typing or pasting the character every source of mathematics uses for the constant gives a free variable, and the expression simply does not simplify. No error, no warning — `sin(π)` is a perfectly good expression about an unknown.
2. **Cyrillic `е` is not `e`.** Same shape, and this one is not even a deliberate choice by the person typing it: `е` and `e` are indistinguishable in every font.
3. **`х + x` has two variables and prints as `х + x`.** The printed form round-trips correctly — that is not the problem. The problem is that a human reading it, or comparing two expressions by eye, cannot tell them apart, and `Solve` on one of them silently treats the other as a parameter.

None of this is a round-trip defect (`StringizeRoundTripTest` is satisfied throughout) and none of it is a parser bug in the strict sense — every case follows the documented rules exactly. It is a case where the rules compose into something surprising.

### Why raise it separately from #1242

#1242 asks whether the *printer* should emit Unicode. That proposal can only be answered after deciding what the parser should do with `π`, because a printer emitting `π` for the constant would produce a string that reads back as a free variable — but the reverse is not true. The reading question stands on its own and is worth settling whether or not anything ever prints Unicode.

### Options, none of which is obviously right

* **Alias the spellings.** `π` → the `pi` constant, `е`/`ℯ` → `e`. Cheap, and it is what most systems do. It costs anyone currently using `π` as a free variable, and it does nothing for `х` vs `x`.
* **Diagnose confusables.** Warn (or refuse under a setting) when one expression contains two identifiers that are confusable under [UTS #39](https://www.unicode.org/reports/tr39/) — which catches `х + x` and, as a side effect, `sin(π)` if `π` is aliased. There is no diagnostic channel for parsing today, which is the real cost.
* **Narrow the identifier rule.** Drop the Cyrillic and Greek Extended ranges. Cheapest, and the most likely to break someone.
* **Nothing, and document it.** `Syntax.md` currently does not mention that non-Latin identifiers are accepted at all, so even this option is a change.

I do not have a recommendation. The question I would want answered first is **why the Cyrillic range is in the grammar** — if it is there for Russian-language variable names then aliasing Greek and leaving Cyrillic is inconsistent, and if it arrived by copying a character-class it may simply be removable.

Measured on `2dbeedf7`; every line above is reproducible from a fresh parse.

Contributor guide

Open the contributing guide

Research direction

Start by locating the VARIABLE lexer rule and Variable.ConstantList, then reproduce the π, Cyrillic е, and х + x examples from a fresh parse. Read Syntax.md, StringizeRoundTripTest, and the discussion in #1242, while investigating why the Cyrillic range is accepted. Done means the project has a decided policy for these identifiers, documented behavior, and tests that preserve round-trip expectations.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp
Domain
compilers
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Needs clarification
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.