www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - I've made a language! \o/ Introducing Neat

reply FeepingCreature <feepingcreature gmail.com> writes:
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
next sibling parent Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
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
prev sibling next sibling parent reply Tejas <notrealemail gmail.com> writes:
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
parent FeepingCreature <feepingcreature gmail.com> writes:
On Monday, 19 September 2022 at 04:54:38 UTC, Tejas wrote:
 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**
Thank you! ♥
Sep 19 2022
prev sibling next sibling parent Max Samukha <maxsamukha gmail.com> writes:
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
prev sibling next sibling parent reply React <react react.js> writes:
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
Nice! I hope that the underscores instead of spaces are just a rendering issue.
Sep 19 2022
parent FeepingCreature <feepingcreature gmail.com> writes:
On Monday, 19 September 2022 at 15:31:03 UTC, React wrote:
 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
Nice! I hope that the underscores instead of spaces are just a rendering issue.
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:
 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
prev sibling next sibling parent Abdulhaq <alynch4048 gmail.com> writes:
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
prev sibling next sibling parent Daniel N <no public.email> writes:
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
Finally a language that "gets it". Impressive.
Sep 19 2022
prev sibling next sibling parent Dukc <ajieskola gmail.com> writes:
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
prev sibling parent reply Quirin Schroll <qs.il.paperinik gmail.com> writes:
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
Can 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
parent FeepingCreature <feepingcreature gmail.com> writes:
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:
 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
Can 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).
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)`.
 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