wordplaydev / wordplay

An accessible, language-inclusive programming language and IDE for creating interactive typography on the web.
Other
63 stars 44 forks source link

Number ranges #398

Open amyjko opened 8 months ago

amyjko commented 8 months ago

What's the problem?

There are many places where ranges are helpful to have syntactically:

Because there is no concept of a range in the language, these are harder to express.

What's the design idea?

Add syntactic sugar for a range constraint and link it to various places in the language to make expression easier.

Design specification

Add range syntactic sugar for types and matches. We would do this by mirroring mathematical range syntax using parentheses and brackets to include ([, ]) or exclude boundaries ((, )), but declaring a unique symbol for a range: , which borrows from the integer interval syntax in math notation.

Here are some examples:

The grammar for a range would be:

RANGE :: ( \( | \[ ) EXPRESSION? , EXPRESSION? ( \ ) | \] )

We can disambiguate this from lists and evaluations by the comma after the first expression.

Ranges are typed as infinite sets of numbers. They can be used as a number type, in a match expression to match on a range, and they have functions like ∋ that check set containment, or conversions to lists or finite sets.

One limitation on type checking is that it would only work for number literals. Generic numbers would always fail to be in the range, and most computation would generally compute unbounded numbers, since they could be anything. We could generate range types on inequality statements when there are literal bounds, to preserve some type information.

jfm2003 commented 6 months ago

Hi Amy! Where should we get started?

amyjko commented 6 months ago

Building this has a pretty long list of implementation tasks:

I'm probably forgetting something.

There's a lot to learn about programming language implementation to make this work; but there are also lots of existing design patterns in the implementation that you could follow. So it's a big project, but possible!

NushaS commented 5 months ago

We began the lengthy process of incorporating number ranges. As you can see this is a multi-step task and we were able to get the first three completed. There are commits made to the 398-number-ranges branch under my account. We did not pull request since we did not complete Number Ranges, but next steps would be to create the Range file that extends Node. Jessica and I have unassigned ourselves, thank you for everything!

ericazqyy commented 5 months ago

Status Upadte

Tasks We Finshed

  1. Updating Tokenizer.ts and Sym.ts to define new token types for the parentheses, square brackets, and commas. Those are already used for other symbol types, so we'd need to define new symbol types and include them in
  2. Tokenizer.ts's list of symbols on the patterns that match for them.

We define new token types to represent range symbols in Sym.ts: NumberExcludeOpen, NumberExcludeClose, NumberIncludeOpen, and NumberIncludeClose.

And we updated Tokenizer.ts accordingly:

const ListOpenPattern = { pattern: LIST_OPEN_SYMBOL, types: [Sym.ListOpen, Sym.NumberIncludeOpen] };
const ListClosePattern = { pattern: LIST_CLOSE_SYMBOL, types: [Sym.ListClose, Sym.NumberIncludeClose] };
{ pattern: EVAL_OPEN_SYMBOL, types: [Sym.EvalOpen, Sym.NumberExcludeOpen] },
{ pattern: EVAL_CLOSE_SYMBOL, types: [Sym.EvalClose, Sym.NumberExcludeClose] },
  1. Adding tests to Tokenizer.test.ts to verify correct tokenization We verified correct tokenization of ranges by adding tests to ensure the tokenizer correctly identifies range expressions. Tests included various range expressions, such as:

    ['(0, 1)', '(|0|,|1|)|'],
    ['(-1, 1)', '(|-1|,|1|)|'],
    ['[0, 1]', '[|0|,|1|]|'],
    ['[-1, 1]', '[|-1|,|1|]|'],
    ['(0.5, 1.5)', '(|0.5|,|1.5|)|'],
    ['[-1.5, 1.5]', '[|-1.5|,|1.5|]|'],
    ['(0,∞)', '(|0|,|∞|)|'],
    ['[0,∞]', '[|0|,|∞|]|'],
    ['(-∞,∞)', '(|-∞|,|∞|)|'],
    ['[-∞,∞]', '[|-∞|,|∞|]|'],

Tasks Remains

  1. Defining a new Range that extends Node to represent a parsed range
  2. Updating parseType.ts to parse a Range where a number type might be expected
  3. Updating parseExpression.ts to parse a Range
  4. Adding unit tests to Parser.test.ts to check range parsing correctness
  5. Defining a new RangeType that extends Type and defining its acceptsAll method to implement number range checking semantics described in the design
  6. Defining functions for Range in a new RangeBasis.ts file, like NumberBasis.ts, including functions like ∋ described in the design spec.
  7. Updating Match.ts to account for ranges
  8. Defining a new RangeValue type that extends Value, since those need to be checked when a Match is being evaluated
  9. Writing all documentation for Range, RangeType, and RangeValue in en-US.json, and placeholders in all other supported locales, giving examples of how to use them.

Contributor:

@NushaS @ericazqyy @jfm2003

amyjko commented 5 months ago

@NushaS @ericazqyy Thank you for the extensive update! Where does your progress live? I don't see a reference to a branch anywhere in your comment or in the issue body. Please provide that, so others can build on your work.

NushaS commented 5 months ago

Hey Amy! As I briefly mentioned above, the branch that we worked on was the 398-number-ranges branch. Here is the link to its page: https://github.com/wordplaydev/wordplay/tree/398-number-ranges . Please let us know if there are any issues with accessing it or if anything else is needed from us in order for others to continue working. Thank you!