Tensegritics / ClojureDart

Clojure dialect for Flutter and Dart
1.44k stars 91 forks source link

Dart 3 #190

Open cgrand opened 1 year ago

cgrand commented 1 year ago

https://medium.com/dartlang/dart-3-alpha-f1458fb9d232

We need support to create records, and have it participate in core protocols. #dart (...) for syntax ? We don't need to support pattern matching. Class modifiers:

No modifier: Mostly as today where the class or mixin has no restrictions, except that we no longer allow a class to be used as a mixin by default. So we have to make sure our mixins are declared as pure mixins and not classes.

We should ensure that we don't use any of the things removed https://github.com/dart-lang/sdk/issues/49529

dupuchba commented 1 year ago

Have it participate in core protocol? What do you have in mind?

cgrand commented 1 year ago

@dupuchba I was thinking about having nth and maybe get and assoc to work on records but reading more about records abated my ambitions. Destructuring alone would be great.

cgrand commented 1 year ago

Records:

  1. Positional fields are named $1 to $n so they may clash with our munging scheme. 1.1 Further analysis show that they can't class with the radix part of the munged name (which can't be empty), only with the suffix part, thus no clash ✅. 1.2 We should take care of not mistaking $1 (a clojure symbol) for $1 the record accessor. However $1only occur in interop member lookup so they won't undergo munging. However writing .-$1 to access a positional field is consistent with dart but a bit noisy. Could/should we shorten it to .-1 in ClojureDart?
  2. #dart (1 2 3 .name "z") seems to be a reasonable syntax and reuse arguments parsing in the same way the Dart syntax reuse Dart arguments parsing.
  3. Take care that we can't emit code which can be mistaken for a record https://github.com/dart-lang/language/blob/main/accepted/future-releases/records/records-feature-specification.md#ambiguity-with-on-clauses 3.1 on clauses: on is a reserved word for us so we never emit a function or local named on ✅ 3.2 metadata: we never emit space between a callable or its arguments so we should be safe ✅
  4. The internal representation of record types should try to follow functions types as much as possible since there's a lot of similarities -- but one big differences: records are covariant towards their "arguments" while functions are contravariant. But it draws a lot from classes too (members) 4.1 return it from analyzer
  5. We need a notation for record types in #/(...); we have #/(x y .z -> r) (not sure about optionals) for functions, we have #/(List String) for parametrized types. How do we add records to that? #/(Record x y .z) ? requires special casing the Record class, unlike what we have done for Function but otherwise it means finding a syntax... #/[x y .z] with brackets for records :-/ If we go with #/(Record x y .z) the risk would be that the Record class gets true type parameters. It seems unlikely. Going with Record is explicit (good) but long (slightly bad) and we can still provide syntactic sugar later. Square brackets still have some allure. Another option could be #/($ x y .z) 😱 In truth we never went the last mile and don't have syntax for optionals in function types. Thus the work on records will serve for functions.

Points 1 and 2 should be quick enough. Point 3 is free. The hard work is on inference, type representation and type notation. Notation can be post-poned.

cgrand commented 1 year ago

Notation for functions and records types with optionals

#/(int String (List) -> bool) ; positional
#/(int String .children List -> bool) ; named

Use the same for records

#/[int String (List)] ; positional
#/[int String .children List] ; named