RON uses parentheses to represent structs. "This is not Rusty at all!", I thought to myself. This is where the story begins, a project written out of OCD. Eventually, KEON is different from RON in the following ways:
- Use braces `{}` to represent structs and maps.
- `macro_rules!` tells us, "`expr` and `stmt` may only be followed by one of: `=>`, `,`, or `;`". RON uses only `:` even though the left-hand can be arbitrary. KEON has added `=>`, now we have two ways to represent key-to-value. This is why structs and maps can be unified: structs can be regarded as maps with strings as keys. `ident: ...` is basically syntactic sugar for `"ident" => ...`.
- Since parentheses are saved, we can use `()` to represent tuples and `[]` to represent vectors. Although they are all `seq` in Serde, in the output, this certainty reassures me: the length of a tuple is immutable relative to a vector.
- Serde allows some weird structures, such as `struct AwfulNullary()`, which must `visit_tuple` rather than `visit_unit`. And `enum Foo { AwfulNullary() }`. Even though these never happened, I insisted on getting it sorted out.
- In RON, both types output `AwfulNullary()` when showing struct names, and only the backend knows whether it is an enum or a struct, that's unsettling to me.
- In KEON, pretty outputs `(AwfulNullary)()` and `Foo::AwfulNullary()`, or minimal outputs `()()` and `AwfulNullary()` respectively. You can tell what's going on at a glance.
- Variants can be written anywhere as `Enum::Variant` or just `Variant`, exactly as happens in Rust. Redundant annotations help to quickly figure out what's there, and jump to the corresponding location without relying too much on LSP?
- The type annotation of structs is done by `(TheStruct)`, like type conversions in C, implying the backend doesn't care what's in... If the parentheses were omitted, `TheStruct` would be treated as a variant in most places (refer to Turbofish), and I would not be able to write a usable parser at all. Although this isn't Rusty, it shouldn't be too obtrusive.
- RON doesn't guarantee work with `deserialize_any` may have to do with these details. I believe KEON can support this, but more comprehensive tests are needed.
Some other less Rusty things: - `Option<T>` doesn't accept `visit_enum`, it only accepts `visit_some`/`none`. I didn't want to provide exceptions for `Some(..)` and `None`, so I had to find the question mark `?` from the keyboard for it to use.
- Serde provides `visit_newtype_struct`, I think this *must* have its purpose, so we'd better have the corresponding syntactic sugar, that is `>`. Of course things like `Item::IdCard(101)` are also legal.
- Raw strings. KEON uses Backtick-Quote instead of r-Pound-Quote. This is because, when I want to turn a string to a raw string, after selecting them, I can't wrap them by simply hitting `#` -- they will be directly overwritten, this annoys me. But Backtick can almost always automatically enclose the selection without worrying about ambiguity, requires less typing, and is just as intuitive.
- Correspondingly, raw identifier uses Backtick instead of r-Pound.
- Paragraphs, added purely out of preference. I wanted to try out how much handwriting would be benefited by providing this syntax for a language that is indent-insensitive.
- BaseXX. Well, they're free.
I didn't expect that KEON would spark some interest. (Reply a bit late due to time difference :P)(Edit: formatting)