Commit Graph

93 Commits

Author SHA1 Message Date
Richard Feldman
9c72e5e8ed
Remove unnecessary -> () function return types 2022-05-18 08:29:40 -04:00
Anton-4
0f59f3097a
cargo fix --edition 2022-05-16 17:04:17 +02:00
Ayaz Hafiz
f48792a173 Add encoder tests 2022-05-08 15:08:16 -04:00
Folkert
fbbc31855d
update mono tests 2022-05-08 12:18:10 +02:00
Ayaz
dd51479764
Merge pull request #3009 from rtfeldman/list-map-ownership
List map ownership
2022-05-07 19:59:15 -04:00
Folkert de Vries
201d09d9bf
Merge branch 'trunk' into list-map-ownership 2022-05-07 11:59:51 +02:00
ayazhafiz
0626433a14 Sweep unused deps
`cargo +nightly udeps` told me what's good
2022-05-06 22:54:42 -04:00
Folkert
e2b7056e20
add List.sort test 2022-05-06 16:45:50 +02:00
Folkert
0a2a43546c
add List.map RC tests 2022-05-06 16:39:05 +02:00
Richard Feldman
dd460fb818
Use single-threaded builds in tests 2022-05-05 14:42:36 -04:00
Ayaz Hafiz
b41995c213
Ignore failing polymorphic closure test 2022-05-05 11:13:40 -04:00
Jared Cone
bea87d4168
Files generated by test 2022-05-02 04:53:44 -07:00
Ayaz Hafiz
afe49cf570 Cleanup 2022-04-28 20:34:04 -04:00
Anton-4
2b3eef1cbe
mono test output update 2022-04-28 13:03:52 +02:00
Ayaz Hafiz
f1dc9c8298
Opaques take @ : %s/\$\([A-Z]\)/@\1/g 2022-04-25 12:26:38 -04:00
Ayaz Hafiz
5d1dd81e93
Reuse symbol when opaque type wraps a known symbol
Opaques decay immediately into their argument during codegen, so we need
to handle something that's effectively variable aliasing correctly.

This bug popped up while migrating all current private tags to opaques.
2022-04-23 14:37:52 -04:00
Ayaz Hafiz
02d5cd7885
Deal with recursive pointers that pass through non-recursive layouts 2022-04-22 17:57:01 -04:00
Folkert de Vries
2cc8e95198
Merge pull request #2901 from rtfeldman/vec-map
VecMap
2022-04-21 09:16:38 +02:00
Folkert
8b144c446d
remove PartialEq for a bunch of types that we should not compare 2022-04-20 16:58:30 +02:00
Kevin Gillette
6a3fd3a607
rename divFloor to divTrunc 2022-04-18 02:33:31 -06:00
Ayaz Hafiz
b79b351136
The first ability... compiles 2022-04-14 16:50:41 -04:00
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