oridb / mc

Myrddin Compiler
MIT License
387 stars 34 forks source link

Formatting a slice of 'void' causes infinite loops #165

Closed typeless closed 6 years ago

typeless commented 6 years ago
const main = {
             const v : (->void)
             const p = (v : void#)
             const s = p[:1]
             std.put("s:{}\n", s)
}

The above program will hang forever.

It seems that it's due to the missing increment of the type cursor. Adding tcnext(&ap.tc) at https://github.com/oridb/mc/blob/master/lib/std/fmt.myr#L281 would make it terminate normally but I am not sure that the shown result [void] is expected/allowed with respect to the spec.

oridb commented 6 years ago

On Tue, 26 Dec 2017 09:50:37 +0000 (UTC) Mura Li notifications@github.com wrote:

const main = {
             const v : (->void)
             const p = (v : void#)
             const s = p[:1]
             std.put("s:{}\n", s)
}

The above program will hang forever.

It seems that it's due to the missing increment of the type cursor. Adding tcnext(&ap.tc) would make it terminate normally but I am not sure that the shown result [void] is expected/allowed with respect to the spec.

This change worked for me:

diff --git a/lib/std/fmt.myr b/lib/std/fmt.myr
index 5266b3e9..cfcc252d 100644
--- a/lib/std/fmt.myr
+++ b/lib/std/fmt.myr
@@ -254,6 +254,7 @@ const fmtval = {sb, ty, ap, params

const fallbackfmt = {sb, params, tyenc, ap : valist# -> void
    /* value types */
+       var v_val : void
    var t_val : bool
    var b_val : int8, ub_val : uint8
    var w_val : int16, uw_val : uint16
@@ -278,6 +279,7 @@ const fallbackfmt = {sb, params, tyenc, ap : valist# -> void
    | `Tynone:
    /* atomic types */
    | `Tyvoid:
+               v_val = vanext(ap)
        sbputs(sb, "void")
    | `Tybool:
        t_val = vanext(ap)

And this program:

const main = {
    var v : void[:] = [void, void, void, void][:]
    for var i = 0; i < v.len; i++
        std.put("{}\n", v[:i])
    ;;
}

And produces the following output:

[]
[void]
[void, void]
[void, void, void]
[void, void, void, void]

Which is what I'd expect. Keep in mind that void is a value, so that you can have arrays of void, return voids, put voids into data structures, etc. So, things like:

var set : std.htab(byte[:], void)

are valid.

I'm going to put this fix together with a bit of extra cleanup. Thanks for the report!

-- Ori Bernstein ori@eigenstate.org

typeless commented 6 years ago

That's amazing (for someone who is used to C/C++ void). By the way, I notice that you use a placeholder variable rather than the gap symbol to bind the return value, is that not possible because vanext is a generic function?

oridb commented 6 years ago

Sort of. Vanext needs to know what type it needs to return, and that information comes through type inference. At the moment, there's no concept of a 'typed gap', so we need a placeholder to propagate the type to the call site.

I've thought a bit about syntax to give type hints when specializing generics, but it actually comes up pretty rarely.