I can't say about linear types, but I've dealt with types for concatenative
languages. There is an exceptionally good dissertation by Kleffner
https://repository.library.northeastern.edu/files/neu:4f186p17k/fulltext.pdf
It is useful to read Diggins' sketch before it
https://citeseerx.ist.psu.edu/document?repid=rep1&type=pdf&doi=17e9322160dc1e26cc85bb26f8ef7b8a560cb07c
Factor has a rudimentary type check (stack effect check), it is done by the
'stack-checker' dictionary. The algorithm itself is taken from the Java
stack machine,
 so it does not always work (there are no quotations in Java). I thought
about rewriting it according to Kleffner, but it is built into the compiler
as the first stage,
 and part of the compiler needs to be rewritten along with it (I'm not
ready yet).

пт, 13 июн. 2025 г. в 12:24, toastal <toas...@posteo.net>:

> Wanting to understand how safety is handled in Factor being an absolute
> concenative novice… Last year I went out to learn ATS2
> <https://www.cs.bu.edu/~hwxi/atslangweb/> in the ML family (those
> familar with OCaml or SML would be familar with the syntax). One of the
> standout features was linear types for safe resource tracking (closing
> file handles, always calling free, disallowing double free—where affine
> types only assert can be used at most once vs. linear types *must* be
> used exactly once). While the ATS2 language is a bit obtuse &
> unconventional, it felt very safe to use it due to explicit typing. For
> a ‘trivial’ example:
>
> ------------------------------------------------------------------------
>
> #include "share/atspre_define.hats"
> #include "share/atspre_staload.hats"
>
> implement main0 (): void = {
>         (* allocate for an integer, returning a tuple with proofs for
> values
>         & token for garbage collection | the pointer address *)
>         val (pfval, pfgc | ptr) = ptr_alloc<int>()
>
>         (* set pointer value to 42 (! is sugar to dereference @ address) *)
>         val () = !ptr := 42
>
>         (* get pointer value assiging to x *)
>         val x = !ptr
>
>         (* prints “x = 42” to console *)
>         val () = println!("x = ", x)
>
>         (* frees pointer using consuming both linear types *)
>         val () = ptr_free(pfgc, pfval | ptr)
> }
>
> ------------------------------------------------------------------------
>
> If I skip the ``ptr_free(…)`` I will get a compiler error:
>
> > the linear dynamic variable [pfval$8389(-1)] needs to be consumed but
> > it is preserved with the type [S2Eat(S2Eapp(S2Ecst(g1int_int_t0ype);
> > S2Eextkind(atstype_int), S2Eintinf(42)),
> > S2Evar(l$14498$14499$14500(23073)))] instead.
>
> If duplicate the ``ptr_free(…)`` line, I will get this compiler error:
>
> > the linear dynamic variable [pfgc$8390(-1)] is no longer available.
>
> It’s a lot of manual code, but these linear types prevent leaks & enforce
> cleanup at the compiler level. These types are not limited to
> hardware-level resource tracking in the sense that you could use this to
> model in the type system of a game that you can’t unlock already
> unlocked door & unlocking a door consumes a key.
>
> I understand Factor does not have these sorts of types (almost no
> languages do) & is dynamically typed (ignoring ``TYPED:``), but I am
> curious, especially from the C FFI side of things where freeing is
> normally a manual/error-prone task, how would the Factor language, or
> concatenative languages in general, model resource tracking. Is there
> some sort of stack mechanism to sort of enforce cleanup or other
> contracts?
>
> — toastal
>
>
> _______________________________________________
> Factor-talk mailing list
> Factor-talk@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/factor-talk
>
_______________________________________________
Factor-talk mailing list
Factor-talk@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/factor-talk

Reply via email to