Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Only inline into active positions #695

Open
wants to merge 49 commits into
base: master
Choose a base branch
from
Open

Conversation

b-studios
Copy link
Collaborator

No description provided.

b-studios and others added 30 commits November 14, 2024 18:43
Co-authored-by: Jonathan Brachthäuser <[email protected]>
'stream' got slightly refactored (using `Any` everywhere now),
fixed a few bugs, added a few examples of push streams, pull streams,
their infinite variants, `limit`, `zip`, ...

---------

Co-authored-by: Philipp Schuster <[email protected]>
This special flag annoyed me, so here is a version with pointer
comparisons instead.
As discussed in
#561 (comment),
there's a missing rewrite.
This fix is necessary for the `map` and `set` examples, as well as some
of my AoC solutions using them, so I'd like to upstream it, if possible.

Co-authored-by: Marvin <[email protected]>
## Motivation
Resolves #723 
Expanded the `stdlib` by adding a function on lists which counts how
often a given predicate evaluates `true`. The Effekt Working group
decided on the name `count`

## Changes
Implemented the `count[A](list: List[A]){ predicate: A => Bool }: Int `
function in libraries/common/list.effekt with fitting Documentation
including Examples.
Implemented a test and check file file in the examples/stdlib/list
directory

## Testing
I locally ran the `sbt:effekt>test` successfully and tested some
examples.
It can be tested the same way 

## Notes
This is my first contribution to the effekt-lang, so I am happy to hear
feedback and change things if there's need for it:)
- regards Jakub
…mespace (#728)

I've been sitting on these changes for a good while now, so let's upstream 'em.

Among others adds:
- ANSI256 colours
- all sorts of combinators for manipulating the terminal: change title,
move cursor, clear line, clear screen, hyperlink, ...

Be warned, this might break some users who rely on escapes and/or the 'string/tty' module directly.
Currently, it's not possible to import, say, `mutable/map` when working
on the `jsWeb` backend.
This PR fixes that.
This fixes the failing program on effekt plots and fixes #732
Reverts #730 as it seems like an incorrect fix,
judging both by the Effekt Working Group meeting, and the graphs after
merging it:


![image](https://github.com/user-attachments/assets/67f28d10-ef57-4529-b47d-4df1d342bd63)

![image](https://github.com/user-attachments/assets/e6de9240-d9fd-4aeb-8f45-79a225307811)
Adds a quick regression test for a handler in tail position that uses a
mutable variable (minimised reproduction of the underlying issue).

The test passes on current `master` after #692.
Crashes the compiler on `v0.9.0`, but works on `v0.8.0`.
Resolves #717

I am fully aware that this is not the best way to do things, a larger
refactor would be needed (see the TODO in code). However, it's a
somewhat pressing issue as we have users trying to work with `js-web`
blocked on this...

As a bonus, I added a `id=app` div to the generated HTML.
Based on #622.
This adds:
- Some (minimal) features in the effekt stdlib and the subset of #527
that it depends on
- A simple Scanner library (lexing string literals and numbers for now)
- A library to parse and print (minified, not pretty) json

---------

Co-authored-by: Philipp Schuster <[email protected]>
Update kiama to support LSP notebooks
…of old ones (#754)

See discussion in #733 for how I traced down the bug. Summary:


At the point where we dealias the binding `l = m`, the core tree looks
like:

```
let l = m;
def b_k_1(r, xs) =
  // note the l here:
  let v_3 = run {link(k, v, l, r)}
  go(bitwiseShl225(level, 1), v_3, xs);
...
```
As it can be clearly seen, `l` is used in the join points `b_k_...`.
The bindings, after rewriting look like this. 
```
let l = m;
def b_k_1(r, xs) =
  // note the m here:
  let v_3 = run {link(k, v, m, r)}
  go(bitwiseShl225(level, 1), v_3, xs);
...
```
It appears the renaming was successful. However, the rewritten defs are
updated in the `InlineContext`, which can be seen by inspecting
`rewrite(List[Definition])`


https://github.com/effekt-lang/effekt/blob/9007b059291153c7d9279ec729d62803a7b47275/effekt/shared/src/main/scala/effekt/core/Inline.scala#L88C7-L97

and its callsite:


https://github.com/effekt-lang/effekt/blob/9007b059291153c7d9279ec729d62803a7b47275/effekt/shared/src/main/scala/effekt/core/Inline.scala#L124-L126

So, the next time a `def` is inlined, the old `def` is inlined. It still
refers to the old, aliased but now removed, binding... Hence causing the
error.

In this PR, I update the defs in the context to now contain the
rewritten (dealiased) right hand sides.

---------

Co-authored-by: Jiří Beneš <[email protected]>
@b-studios b-studios changed the title Start micropasses by binding subexpressions Only inline into active positions Dec 25, 2024
@b-studios b-studios marked this pull request as ready for review December 25, 2024 13:30
@b-studios
Copy link
Collaborator Author

This PR is now ready for review, some minor cleanup changes might be pending.

It would be great if we could test it with all the problematic examples that caused the previous inliner to fail, before merging.

Comment on lines +18 to +22
case Reset(body) =>
rewrite(body) match {
case BlockLit(tparams, cparams, vparams, List(prompt), body) if !reachable.isDefinedAt(prompt.id) => body
case b => Stmt.Reset(b)
}
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure, but we could also move this to a separate phase.

in favor:

  • deadcode would really only do deadcode elimination

against:

  • removing an unused reset is a bit like removing a dead binding, so it does fit
  • a separate phase would potentially cost us some time and conceptual overhead.

}

// (3) normalize once and remove beta redexes
tree = Context.timed("normalize-1", source.name) { normalize(tree) }
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@marvinborner will these new timings cause problems with plots?

dropStatic(staticT, targs),
dropStatic(staticV, vargs).map(rewrite),
dropStatic(staticB, bargs).map(rewrite))
case _ => app(rewrite(b), targs, vargs.map(rewrite), bargs.map(rewrite))
case _ => Stmt.App(rewrite(b), targs, vargs.map(rewrite), bargs.map(rewrite))
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here we do not perform beta reduction as this will be done later by Normalizer.

@@ -120,22 +123,22 @@ object StaticArguments {

def rewrite(s: Stmt)(using C: StaticArgumentsContext): Stmt = s match {
case Stmt.Scope(definitions, body) =>
scope(rewrite(definitions), rewrite(body))
normal.Scope(rewrite(definitions), rewrite(body))
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This regularly is the only smart constructor we use since it is stupid to accidentally create a scope with no bindings.

case Region(body) => chez.Builtin("with-region", toChez(body))

case other => chez.Let(Nil, toChez(other))
case s: Scope => chez.Let(Nil, toChez(s))
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Annotated since otherwise we might be missing cases (which happened) and then loop during code gen.

@@ -168,7 +170,7 @@ object Transformer {
transform(vargs, bargs).run { (values, blocks) =>
callee match {
case Block.BlockVar(id, annotatedTpe, annotatedCapt) =>
BPC.info.getOrElse(id, sys.error(s"Cannot find block info for ${id}.\n${BPC.info}")) match {
BPC.info.getOrElse(id, sys.error(pp"In ${stmt}. Cannot find block info for ${id}: ${annotatedTpe}.\n${BPC.info}")) match {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This shouldn't happen, but it does (sadly quite frequently), so I dump a bit of additional info here.

@b-studios
Copy link
Collaborator Author

Before the last (two) commit(s), product_early was much better on LLVM. This might be worth investigating.

@b-studios
Copy link
Collaborator Author

Turns out in d44618f I removed some of the normalization functions from core.Tree. In turn, some empty continuation pushes of the form"

val x = STMT
x

were not removed anymore.

Instead of adding this back, 84f1db6 now only removes empty continuations.

The reasoning is that some the previous "normalization" also performed commuting conversions of val x = { val y = stmt1 }; stmt2. However, this extends the lifetime and is not "conservative".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants