Hi,
I haven't touched ATS3 yet just because it mostly targeted JS (well and python), which are not in my interest list yet. Imho, the main selling point for ATS2 is: C target (and some other translators), linear types, refinement-types and dependent-types. All in one box.
But, it comes with a price of requirement to know how to: 1. satisfy the compiler; 2. satisfy linker (because, for example, there are C-compiler constraints that should be satisfied as well, which are missing for other targets); 3. cook templates right
ATS3's template resolution had been reworked and now #3 seems to be solved (I haven't tested yet), but it is missing C compiler yet, which means that it won't be drop-in replacement for ATS2 just yet for anyone wanted "advanced types for low level target".
I use ATS2. At this particular point, I am using it for a hobby project targeting the SQF language (Arma 3 scripting language). (This stuff is not yet published in git yet, just because I am not sure that it is in a final state). For this purpose, I had to:
1. greatly modify atscc2erl Erlang translator (to get 'atscc2sqf' translator );
2. patch parsemit library;
3. provide 'base' library libatscc2sqf with primitives from SQF-world (arrays, 'spawn', 'waitUntil' and so on);
4. (my background is Haskell) so there is an additional step of providing haskell-like libraries around (like Foldable, ByteString/Text, Either and so on), which I miss a lot.
+ I have started to think about best practices for libraries in context of multiple targets. Libraries like Foldable/Either are target-independent but not ByteString and Text.
Add there an absence of the 'standard package system'. (ie, "how to organize libraries to use them for multiple targets"). I use nix. It allowes to split libraries and provide CFLAGS but it has limitations for some people.
I have "testing ATS3" in my todo list alongside with "translator from ATS3 to C", but this is quite an ambitious tasks for me at the moment and I hope HX will be faster than me in this regard)
My experience with modifications to 'parsemit' library showed me, that HX likes to use shortened names for types, which requires some experience to get used to :)
I have restarted to want a language server during those modifications as well, but it seems even more difficult task than "ATS3 to C translator" as requires to understand how to use compiler as a library
So TLDR here: if your goal is a low level target, then currently ATS3 is not there yet.
ATS2 is fine, but it will require some early-adopters headache (like there is no best practice to organize your libraries in a future-proof way) and some quirks (like using templates right).
(just in advance) what I mean about 'using templates right' in ATS2: if you recall `show` function in haskell
```
class Show a where
show :: a -> String
```
which the only goal is to provide a printable view of some value. Then, when you want to use it for a value of type '[String]` you need to provide instances for `String` and `[a]`:
```
instance Show String where
show v = v
instance (Show a) => Show [a] where
show xs = loop "[" 0 xs
where
loop acc _idx [] = acc ++ "]"
loop acc idx (first: rest) = loop newacc newidx rest
where
newidx = idx + 1
separated = if idx > 0 then acc ++ ", " else acc
newacc = separated + show head
```
and it is simple enough to be useful:
```
putStrLn (show ["hello", "world"]) -- for [String]
putStrLn (show [ ["hello"], ["world"] ]) -- and even for [ [ String ] ] (ie, list of list of String)
```
and if you will miss the Show instance for String ( `instance Show String`) compiler will tell you that you need to provide it
But in ATS2 the same example is bit more complicated:
```
extern fn
{a:t@ype}
show
( a
):
String
```
and appropriate instances:
```
implement show<String>(v) = v
```
then we can try to implement similar to Haskell's version for list:
```
implement show<[a:t@ype]List0(a)>(xs) = loop( "[", 0, xs) where {
extern fn append_String( String, String): String //
overload ++ with append_String
fn
{a:t@ype}
loop
{n:nat}
.<n>.
( acc: String
, idx: int
, xs: list( a, n)
): String =
( case xs of
| list_nil() => acc ++ "]"
| list_cons( first, rest) => loop (newacc, newidx, rest) where {
val newidx = idx + 1
val separated = if idx > 0 then acc ++ ", " else acc
val newacc = separated ++ show<a>(head)
}
)
}
```
and then use it:
```
implement main0() = {
val v = list_cons( "hello", list_cons( "world", list_nil()))
val () = println!(show<List0(String)>(v))
}
```
and it will be compiled, but will fail during link time as template resolution will not resolve `List0(String)` into `[a:t@ype]List0(a)` even if `String` of sort `t@ype`. Instead, you will have to provide workaround by providing more specialised implementations like this:
```
extern fn
{a:t@ype}
show_list
{n:nat}
( list(a, n)
): String = loop( "[", 0, xs) where {
extern fn append_String( String, String): String //
overload ++ with append_String
fn
{a:t@ype}
loop
{n:nat}
.<n>.
( acc: String
, idx: int
, xs: list( a, n)
): String =
( case xs of
| list_nil() => acc ++ "]"
| list_cons( first, rest) => loop (newacc, newidx, rest) where {
val newidx = idx + 1
val separated = if idx > 0 then acc ++ ", " else acc
val newacc = separated ++ show<a>(head)
}
)
}
```
then 'main0' will be changed to
```
implement main0() = {
val v = list_cons( "hello", list_cons( "world", list_nil()))
val () = println!(show<List0(String)>(v)) where {
implement show<List0(String)>(xs) = show_list(xs)
}
}
```
then, when you want show for value of type `List0(List0(String))` you need to specialize such implementation as well:
```
implement main0() = {
val v = list_cons( "hello", list_cons( "world", list_nil()))
val v1 = list_cons( v, list_nil())
val () = println!(show<List0(List0(String))>(v1)) where {
implement show<List0(String)>(xs) = show_list(xs) -- provide specialized template implementation for List0(String)
implement show<List0(List0(String))>(xs) = show_list(xs) -- provide specialized template implementation for List0(List0(String))
}
}
```
those last 2 examples will be compiled and linked successfully, but, as you can see, there is a boilerplate to walkaround template resolution and that is probably the biggest headache in ATS2 at the start.