digitalmars.D - I've made a language! \o/ Introducing Neat
- FeepingCreature (50/50) Sep 18 2022 Alright, since I've ran out of critical issues on my TODO, here's
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (3/5) Sep 18 2022 Congratulations! This sounds like a fun project!
- Tejas (4/7) Sep 18 2022 Looks pretty... **Neat**
- FeepingCreature (2/10) Sep 19 2022 Thank you! ♥
- Max Samukha (5/10) Sep 19 2022 Too easy. Programmers should live in pain, and their evil
- React (5/9) Sep 19 2022 Nice!
- FeepingCreature (20/39) Sep 19 2022 Yes, it's an issue with the dark mode rendering of Sphinx's RTD
- Abdulhaq (5/22) Sep 19 2022 Very interesting :-) and congratulations on getting this far. Can
- Daniel N (3/7) Sep 19 2022 Finally a language that "gets it". Impressive.
- Dukc (6/9) Sep 19 2022 The definitely do look epic, and I'd be happy to have them in D.
- Quirin Schroll (29/33) Sep 21 2022 Can you show a little bit of your sum types? They can be
- FeepingCreature (18/48) Sep 22 2022 It's 3, but implicitly convertible with 2. I disambiguate int+int
Alright, since I've ran out of critical issues on my TODO, here's Neat! https://neat-lang.github.io/ https://github.com/neat-lang/neat The syntax will seem very familiar to people here. :) It's sort of like D1 circa 2003 but with macros instead of CTFE and a very underpowered template engine. Note that while all the features I want are in there, some (such as templates) are only 10% there. Still, it's usable as it stands, and it's self-hosting. The biggest divergences to D are probably that it's reference-counted rather than GC, the macro support, and variables being (head) immutable and unreferenceable by default. It also has built-in: tuple types, sumtypes with implicit conversion, named parameters and format strings. But D will have all of those eventually. (Any year now...!!) So how about I show you something cool that will probably never be in D: How do you encode two structs to JSON? ``` module test; macro import std.json.macro; macro import std.macro.assert; import std.json; struct B { A first, second; } struct A { int v; } JSONValue encode(B b) { return JSONValue({ "first": encode(b.first), "second": encode(b.second) }); } JSONValue encode(A a) { return JSONValue({ "v": a.v }); } void main() { assert(encode(B(A(2), A(3))) == JSONValue({ "first": {"v": 2}, "second": {"v": 3} })); } ``` "So you have hashmap literal syntax, like D?" No, I don't. Look again. The parameter passed to JSONValue is a genuine JSON expression, with embedded Neat expressions. No `JSONValue()` spam required. If it were XMLValue, it could just as easily be `XMLValue(<tag attribute=$variable>$(encode(body))</tag>)`. Macros, fuck yes!
Sep 18 2022
On Sunday, 18 September 2022 at 20:28:58 UTC, FeepingCreature wrote:Alright, since I've ran out of critical issues on my TODO, here's Neat!Congratulations! This sounds like a fun project!
Sep 18 2022
On Sunday, 18 September 2022 at 20:28:58 UTC, FeepingCreature wrote:Alright, since I've ran out of critical issues on my TODO, here's Neat! [...]Looks pretty... **Neat**
Sep 18 2022
On Monday, 19 September 2022 at 04:54:38 UTC, Tejas wrote:On Sunday, 18 September 2022 at 20:28:58 UTC, FeepingCreature wrote:Thank you! ♥Alright, since I've ran out of critical issues on my TODO, here's Neat! [...]Looks pretty... **Neat**
Sep 19 2022
On Sunday, 18 September 2022 at 20:28:58 UTC, FeepingCreature wrote:return JSONValue({ "first": encode(b.first), "second": encode(b.second) }); }Too easy. Programmers should live in pain, and their evil intentions should be exposed. What about `__evil(JSONValue(q{{...}}))`?
Sep 19 2022
On Sunday, 18 September 2022 at 20:28:58 UTC, FeepingCreature wrote:Alright, since I've ran out of critical issues on my TODO, here's Neat! https://neat-lang.github.io/ https://github.com/neat-lang/neatNice! I hope that the underscores instead of spaces are just a rendering issue.
Sep 19 2022
On Monday, 19 September 2022 at 15:31:03 UTC, React wrote:On Sunday, 18 September 2022 at 20:28:58 UTC, FeepingCreature wrote:Yes, it's an issue with the dark mode rendering of Sphinx's RTD theme. I have no idea how to fix that, so patches welcome. On Monday, 19 September 2022 at 16:20:38 UTC, Abdulhaq wrote:Alright, since I've ran out of critical issues on my TODO, here's Neat! https://neat-lang.github.io/ https://github.com/neat-lang/neatNice! I hope that the underscores instead of spaces are just a rendering issue.Very interesting :-) and congratulations on getting this far. Can you tell me what is a macro in this context, I'm not getting it from the code?Basically, there's locations in the compiler that allow hooks to be loaded. There's a syntax construct that tells the compiler, "stop what you're doing, and instead of compiling for the target platform, compile everything up to here for the *current* platform. Then take the function I gave you from the object you just compiled, load it with dlopen, and execute it with the module macro state object." (Or, abbreviated, `macro(someFun);`.) Then the function adds some object to the macro state, which changes the behavior of the compiler (via the hook system) for that module and others that import it. So it's a compiletime plugin. On Monday, 19 September 2022 at 17:25:21 UTC, Dukc wrote:The definitely do look epic, and I'd be happy to have them in D. Though I do prefer `int[4]` to `(int, int, int, int)` that I think I saw somewhere (hopefully they will be the one and the same someday!).Yes, that is definitely a placeholder. I don't have a non-tagged union type right now, so the C import macro doesn't know what to make of them. I don't have a static-array type either, because I never use them myself. So I make do with that hack. TODO!
Sep 19 2022
On Sunday, 18 September 2022 at 20:28:58 UTC, FeepingCreature wrote:Alright, since I've ran out of critical issues on my TODO, here's Neat! https://neat-lang.github.io/ https://github.com/neat-lang/neat The syntax will seem very familiar to people here. :) It's sort of like D1 circa 2003 but with macros instead of CTFE and a very underpowered template engine. Note that while all the features I want are in there, some (such as templates) are only 10% there. Still, it's usable as it stands, and it's self-hosting. The biggest divergences to D are probably that it's reference-counted rather than GC, the macro support, and variables being (head) immutable and unreferenceable by default. It also has built-in: tuple types, sumtypes with implicit conversion, named parameters and format strings. But D will have all of those eventually. (Any year now...!!) So how about I show you something cool that will probably never be in D:Very interesting :-) and congratulations on getting this far. Can you tell me what is a macro in this context, I'm not getting it from the code?
Sep 19 2022
On Sunday, 18 September 2022 at 20:28:58 UTC, FeepingCreature wrote:Alright, since I've ran out of critical issues on my TODO, here's Neat! https://neat-lang.github.io/ https://github.com/neat-lang/neatFinally a language that "gets it". Impressive.
Sep 19 2022
On Sunday, 18 September 2022 at 20:28:58 UTC, FeepingCreature wrote:It also has built-in: tuple types, sumtypes with implicit conversion, named parameters and format strings. But D will have all of those eventually. (Any year now...!!)The definitely do look epic, and I'd be happy to have them in D. Though I do prefer `int[4]` to `(int, int, int, int)` that I think I saw somewhere (hopefully they will be the one and the same someday!).
Sep 19 2022
On Sunday, 18 September 2022 at 20:28:58 UTC, FeepingCreature wrote:Alright, since I've ran out of critical issues on my TODO, here's Neat! https://neat-lang.github.io/ https://github.com/neat-lang/neatCan you show a little bit of your sum types? They can be implemented in four ways: 1. Stupid union (like `union` in C, C++, and D) 2. Type union or soft discriminated union (`int+string+int` = `int+string` = `string+int`) 3. Indexed union or hard discriminated union (`int+int` ≠ `int`) For 2., you effectively ask: Which types are in? Order and repetition don’t matter. And 3. is effectively an algebraic type with unary constructors that are referred to by index (instead of by name). There are even more options like `int+string` ≠ `string+int`, but int+int is not allowed, i.e. you can always uniquely ask “Does it contain an `int`?” Without ambiguity about *which* `int`. What is your take on qualifiers? Is `int+const(int)` allowed and/or the same as `int`? Do your sum types nest or are they flat? As an example, D’s alias sequences are flat: `AliasSeq!(a, AliasSeq!(b, c), d)` = `AliasSeq!(a, b, c, d)`. A sum type implementation can make `int+(char+string)+double` be `int+char+string+double` or keep the nesting. As alias sequences show, flattening is not that bad and if not desired, can be mitigated using wrappers. Does it support the empty sum? It would naturally be a bottom type. Does a unary sum exist? It would naturally be equivalent to the only type argument. You had to make these decisions (even if unaware of the options). What did you decide for Neat?
Sep 21 2022
On Wednesday, 21 September 2022 at 10:53:56 UTC, Quirin Schroll wrote:On Sunday, 18 September 2022 at 20:28:58 UTC, FeepingCreature wrote:It's 3, but implicitly convertible with 2. I disambiguate int+int cases with zero-sized "identifier types": for instance, `alias Point = (:x, int | :y, int)`.Alright, since I've ran out of critical issues on my TODO, here's Neat! https://neat-lang.github.io/ https://github.com/neat-lang/neatCan you show a little bit of your sum types? They can be implemented in four ways: 1. Stupid union (like `union` in C, C++, and D) 2. Type union or soft discriminated union (`int+string+int` = `int+string` = `string+int`) 3. Indexed union or hard discriminated union (`int+int` ≠ `int`) For 2., you effectively ask: Which types are in? Order and repetition don’t matter. And 3. is effectively an algebraic type with unary constructors that are referred to by index (instead of by name).What is your take on qualifiers? Is `int+const(int)` allowed and/or the same as `int`?I don't have qualifiers at the moment. But I'd probably make it "allowed and different from int".Do your sum types nest or are they flat? As an example, D’s alias sequences are flat: `AliasSeq!(a, AliasSeq!(b, c), d)` = `AliasSeq!(a, b, c, d)`. A sum type implementation can make `int+(char+string)+double` be `int+char+string+double` or keep the nesting. As alias sequences show, flattening is not that bad and if not desired, can be mitigated using wrappers.They're nested right now. I think that's the correct behavior; otherwise, things like aliasing sumtypes are going to lead to odd behavior (`alias foo = (int | float)`, now if you stick it in another sumtype you need either "subset matching" in `case()`, or `.case(foo f: ...)` doesn't work.Does it support the empty sum? It would naturally be a bottom type.You could manually create that type with a macro, but you can't declare one in the syntax right now.Does a unary sum exist? It would naturally be equivalent to the only type argument.Likewise. To note, sumtypes started out as a macro before I integrated them in the compiler so I could use them in the macro API. So users who don't like the way this works can always define their own. :)
Sep 22 2022