Commit Graph

72 Commits

Author SHA1 Message Date
Ayaz Hafiz
865c1f15d7
Fix test compile errors, and simply load_internal tests 2022-04-12 16:42:51 -04:00
Nikita Mounier
c035900d64
Update test_mono test. 2022-04-12 18:15:19 +00:00
Ayaz Hafiz
a12e40a310
Specialize polymorphic values before binding to pattern
Closes #2811
2022-04-07 14:03:29 -04:00
Ayaz Hafiz
886e5a0c8f
Don't unify real vars when there are no type variables, or nothing changed 2022-04-05 17:51:30 -04:00
Ayaz Hafiz
163c6b39d6
Unify type alias "real variables"
Turns out that we can't always assume that a successful unification of
type alias type variables means that those aliases had the same real
type from the start. Because type variables may contain unbound type
variables and grow during their unification (for example,
`[InvalidNumStr]a ~ [ListWasEmpty]b` unify to give `[InvalidNumStr,
ListWasEmpty]`), the real type may grow as well.

For this reason, continue to explicitly unify alias real types for now.
We can get away with not having to do so when the type variable
unification causes no changes to the unification tree at all, but we
don't have a great way to detect that right now (maybe snapshots?)

Closes #2583
2022-04-05 11:21:52 -04:00
Folkert
311e464b70
add load_internal 2022-03-23 15:18:22 +01:00
Folkert
d8fa2b8d92
stop passing stdlib (use lazy_static) 2022-03-22 19:53:02 +01:00
ayazhafiz
17029cff7e Link aliased lambdas to the partial procs of the original symbol
This ensures that we use the correct specialized variable at the call
site of a function. In #2725 what happened was that a generalized
function was aliased, causing it to undergo generalization again. Then,
we lost the variable used to specialize at the call site. Instead, just
link to the partial proc being aliased directly.

There is an added benefit here, which is that we can avoid the
possibly-quadratic replacement of symbols in the generated statement.

Closes #2725
2022-03-14 16:42:53 -05:00
Folkert
e3e9215578
Merge remote-tracking branch 'origin/trunk' into type-checking-storage-subs 2022-03-12 14:10:43 +01:00
Folkert
01b810266b
test cleanup 2022-03-11 22:15:36 +01:00
Folkert
10b190917b
bump mono tests after List.replace being used in List.set 2022-03-09 16:15:36 +01:00
ayazhafiz
dfc384aa1f Make mono test output prettier 2022-02-21 14:10:45 -05:00
ayazhafiz
e52d427ac8 Hash record field name order in generated layouts
Closes #2535

See the referenced issue for longer discussion - here's the synopsis.
Consider this program

```
app "test" provides [ nums ] to "./platform"

alpha = { a: 1, b: 2 }

nums : List U8
nums =
    [
        alpha.a,
        alpha.b,
    ]
```

Here's its IR:

```
procedure : `#UserApp.alpha` {I64, U8}
procedure = `#UserApp.alpha` ():
    let `#UserApp.5` : Builtin(Int(I64)) = 1i64;
    let `#UserApp.6` : Builtin(Int(U8)) = 2i64;
    let `#UserApp.4` : Struct([Builtin(Int(I64)), Builtin(Int(U8))]) = Struct {`#UserApp.5`, `#UserApp.6`};
    ret `#UserApp.4`;

procedure : `#UserApp.nums` List U8
procedure = `#UserApp.nums` ():
    let `#UserApp.7` : Struct([Builtin(Int(I64)), Builtin(Int(U8))]) = CallByName `#UserApp.alpha`;
    let `#UserApp.1` : Builtin(Int(U8)) = StructAtIndex 1 `#UserApp.7`;
    let `#UserApp.3` : Struct([Builtin(Int(I64)), Builtin(Int(U8))]) = CallByName `#UserApp.alpha`;
    let `#UserApp.2` : Builtin(Int(U8)) = StructAtIndex 1 `#UserApp.3`;
    let `#UserApp.0` : Builtin(List(Builtin(Int(U8)))) = Array [`#UserApp.1`, `#UserApp.2`];
    ret `#UserApp.0`;
```

What's happening is that we need to specialize `alpha` twice - once for the
type of a narrowed to a U8, another time for the type of b narrowed to a U8.

We do the specialization for alpha.b first - record fields are sorted by
layout, so we generate a record of type {i64, u8}. But then we go to
specialize alpha.a, but this has the same layout - {i64, u8} - so we reuse
the existing one! So (at least for records), we need to include record field
order associated with the sorted layout fields, so that we don't reuse
monomorphizations like this incorrectly!
2022-02-21 14:10:45 -05:00
Folkert
04adbe75ca fix test compilation 2022-02-14 21:09:51 +01:00
ayazhafiz
5943873654 Inline polymorphic calls at usage sites
This is a bit.. ugly, or at least seems suboptimal, but I can't think of
a better way to do it currently aside from demanding a uniform
representation, which we probably don't want to do.

Another option is something like the defunctionalization we perform
today, except also capturing potential uses of nested functions in the
closure tag of an encompassing lambda. So for example,

```
f = \x -> \y -> 1
```

would now record a lambdaset with the data `[Test.f
[TypeOfInnerClos1]]`, where `TypeOfInnerClos1` is e.g.
`[Test.f.innerClos1 I8, Test.f.innerClos1 I16]`, symbolizing that the
inner closure may be specialized to take an I8 or I16. Then at the time
that we create the capture set for `f`, we create a tag noting what
specialization should be used for the inner closure, and apply the
current defunctionalization algorithm. So effectively, the type of the
inner closure becomes a capture.

I'm not sure if this is any better, or if it has more problems.
@folkertdev any thoughts?

Closes #2322
2022-01-28 23:49:19 -05:00
Folkert
afd11e1cb1 move target -> roc_target 2022-01-26 23:33:29 +01:00
Folkert
b9c318e9fb update the tests 2022-01-26 15:59:21 +01:00
Richard Feldman
0c5f9ffd2a
Merge pull request #2401 from rtfeldman/tea-example
Our first elm architecture example
2022-01-25 21:26:41 -05:00
Folkert
062846b7ee fix test compilation 2022-01-25 09:23:42 +01:00
Folkert
8698ea3c72 update mono tests 2022-01-23 15:46:53 +01:00
ayazhafiz
a5de224626 Specialize polymorphic non-function expressions
This commit fixes a long-standing bug wherein bindings to polymorphic,
non-function expressions would be lowered at binding site, rather than
being specialized at the call site.

Concretely, consider the program

```
main =
    n = 1

    idU8 : U8 -> U8
    idU8 = \m -> m

    idU8 n
```

Prior to this commit, we would lower `n = 1` as part of the IR, and the
`n` at the call site `idU8 n` would reference the lowered definition.
However, at the definition site, `1` has the polymorphic type `Num *` -
it is not until the the call site that we are able to refine the type
bound by `n`, but at that point it's too late. Since the default layout
for `Num *` is a signed 64-bit int, we would generate IR like

```
procedure main():
    let App.n : Builtin(Int(I64)) = 1i64;
    ...
    let App.5 : Builtin(Int(U8)) = CallByName Add.idU8 App.n;
    ret App.5;
```

But we know `idU8` expects a `u8`; giving it an `i64` is nonsense.
Indeed this would trigger LLVM miscompilations later on.

To remedy this, we now keep a sidecar table that maps symbols to the
polymorphic expression they reference, when they do so. We then
specialize references to symbols on the fly at usage sites, similar to
how we specialize function usages.

Looking at our example, the definition `n = 1` is now never lowered to
the IR directly. We only generate code for `1` at each place `n` is
referenced. As a larger example, you can imagine that

```
main =
    n = 1

    asU8 : U8 -> U8
    asU32 : U32 -> U8

    asU8 n + asU32 n
```

is lowered to the moral equivalent of

```
main =
    asU8 : U8 -> U8
    asU32 : U32 -> U8

    asU8 1 + asU32 1
```

Moreover, transient usages of polymorphic expressions are lowered
successfully with this approach. See for example the
`monomorphized_tag_with_polymorphic_arg_and_monomorphic_arg` test in
this commit, which checks that

```
main =
    mono : U8
    mono = 15
    poly = A
    wrap = Wrapped poly mono

    useWrap1 : [Wrapped [A] U8, Other] -> U8
    useWrap1 =
        \w -> when w is
            Wrapped A n -> n
            Other -> 0

    useWrap2 : [Wrapped [A, B] U8] -> U8
    useWrap2 =
        \w -> when w is
            Wrapped A n -> n
            Wrapped B _ -> 0

    useWrap1 wrap * useWrap2 wrap
```

has proper code generated for it, in the presence of the polymorphic
`wrap` which references the polymorphic `poly`.

https://github.com/rtfeldman/roc/pull/2347 had a different approach to
this - polymorphic expressions would be converted to (possibly capturing) thunks.
This has the benefit of reducing code size if there are many polymorphic
usages, but may make the generated code slower and makes integration
with the existing IR implementation harder. In practice I think the
average number of polymorphic usages of an expression will be very
small.

Closes https://github.com/rtfeldman/roc/issues/2336
Closes https://github.com/rtfeldman/roc/issues/2254
Closes https://github.com/rtfeldman/roc/issues/2344
2022-01-19 22:52:15 -05:00
Folkert
202a8438ce change UserApp -> Test in mono tests 2022-01-19 23:22:19 +01:00
Folkert
2adcbecf8a update mono tests 2022-01-19 21:01:18 +01:00
Jan Van Bruggen
1e9d2d1239 Remove accidental trailing spaces 2022-01-18 22:25:46 -07:00
Folkert de Vries
e1d990896a
Merge branch 'trunk' into mono-display 2022-01-14 13:55:52 +01:00
ayazhafiz
9f78eb2e01 Fix bug that caused extraneous assignment in IR generation
Previously we would expand optional record fields to assignments when
converting record patterns to "when" expressions. This resulted in
incorrect code being generated.
2022-01-13 18:34:25 -05:00
ayazhafiz
e655ab7d3b Module comments for reset-reuse
Figuring out what this module was doing, and why, took me a bit less
than half an hour. We should document what's happening for others in the
future so they don't need to follow up on Zulip necessarily.
2022-01-13 16:33:23 -05:00
Folkert
79d5c82dfb cleanup 2021-11-27 16:36:43 +01:00
Folkert
19de25426c update mono test 2021-11-19 19:01:03 +01:00
Brendan Hansknecht
89781ec50d Stop building test crates as part of non-test builds 2021-11-07 16:28:17 -08:00
Brendan Hansknecht
73e2cbcb1e Make versions numbers consistent and matching the lock files 2021-11-06 13:24:45 -07:00
Brendan Hansknecht
d49ac68bcc Update dep with major version changes 2021-11-05 19:19:37 -07:00
Brendan Hansknecht
bddc08c977 Remove unused dependencies 2021-11-05 16:58:11 -07:00
Richard Feldman
ac42470c81 Drop unused libc deps 2021-11-02 19:37:38 -04:00
Richard Feldman
bb49593c2e Move test_mono deps into dev deps 2021-11-02 19:37:05 -04:00
Richard Feldman
abe0da2eb0 Drop some unused deps 2021-11-02 19:37:05 -04:00
Richard Feldman
ffbf2b4276 Move some things to dev deps 2021-11-02 19:37:05 -04:00
Folkert
b7f26baf95 add mono test 2021-09-24 15:44:09 +02:00
Brendan Hansknecht
0c6f8f308f Remove f16. It is not really supported by modern CPU hardware. 2021-09-21 16:51:47 -07:00
Folkert
77911cb68a store closure data for bool/byte again 2021-09-18 01:01:38 +02:00
Folkert
5b2661e394 update mono tests 2021-09-08 19:59:30 +02:00
Folkert
b97c2d5d84 store literals in lists directly 2021-09-05 21:23:08 +02:00
Folkert
36fc9b5f1f update target-lexicon 2021-08-26 21:39:33 +02:00
Folkert
de2f1c808b update mono tests 2021-08-16 21:03:58 +02:00
Folkert
8effd19ff9 stop emitting invoke again 2021-08-16 21:03:26 +02:00
Folkert
441eb02ca3 represent bool closure as unit 2021-08-14 15:54:05 +02:00
Folkert
d4896d3ed2 remove inlinable_string dependency 2021-08-03 21:24:19 +02:00
Folkert
899cbeabd7 fix extra ampersands 2021-07-29 17:32:08 +02:00
Folkert
9b8f8b3c16 AppliedTag don't unroll recursive layouts 2021-07-16 18:23:57 +02:00
Folkert
743e8bd86f stop defining the tag id when it is not used 2021-07-16 18:17:21 +02:00