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

SCP-1751: Keep simulation state after compilation error #4081

Closed
wants to merge 6 commits into from

Conversation

sjoerdvisscher
Copy link
Contributor

@sjoerdvisscher sjoerdvisscher commented Oct 8, 2021

Pre-submit checklist:

  • Branch
    • Tests are provided (if possible)
    • Commit sequence broadly makes sense
    • Key commits have useful messages
    • Relevant tickets are mentioned in commit messages
    • Formatting, materialized Nix files, PNG optimization, etc. are updated
  • PR
    • Self-reviewed the diff
    • Useful pull request description
    • Reviewer requested

@sjoerdvisscher sjoerdvisscher changed the title Keep simulation state after compilation error SCP-1751: Keep simulation state after compilation error Oct 8, 2021
Copy link
Contributor

@jhbertra jhbertra left a comment

Choose a reason for hiding this comment

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

Looks like a reasonable approach, but keeping these two values in sync seems a bit fragile... I would suggest creating a helper to updated them both, and replacing all instances of assign _compilationResult x with it:

assignCompilationRestul :: forall m. MonadState State m => WebCompilationResult -> m Unit
assignCompilationRestul newResult =
  assign _compilationResult newResult
  oldSuccesfulResult <- use _lastSuccessfulCompilationResult
  case newResult, oldSuccesfulResult of
    Success (Right _), _ -> assign _lastSuccessfulCompilationResult newResult
    _, Success (Right _) -> pure unit
    _, _ -> assign _lastSuccessfulCompilationResult newResult

I believe that should take care of all possible cases, and now you only need to call one function to update both in a consistent manner!

@@ -332,6 +334,7 @@ handleAction CompileProgram = do
Nothing -> pure unit
Just contents -> do
oldCompilationResult <- use _compilationResult
oldSuccessfulCompilationResult <- use _lastSuccessfulCompilationResult
assign _compilationResult Loading
Copy link
Contributor

Choose a reason for hiding this comment

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

Here, I think we should also set oldSuccessfulCompilationResult to Loading if it is currently NotAsked or Failure

Suggested change
assign _compilationResult Loading
assign _compilationResult Loading
case _lastSuccessfulCompilationResult of
NotAsked -> assign _lastSuccessfulCompilationResult Loading
Failure _ -> assign _lastSuccessfulCompilationResult Loading
_ -> pure unit

@@ -342,6 +345,7 @@ handleAction CompileProgram = do
when (isSuccess newCompilationResult) do
Copy link
Contributor

Choose a reason for hiding this comment

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

can we add a pattern to set the _lastSuccessfulCompilationResult to Failure if it is currently Loading?

Failure error ->  case oldSuccessfulCompilationResult of
  Loading -> assign _lastSuccessfulCompilationResult $ Failure error
  _ -> pure unit

@sjoerdvisscher
Copy link
Contributor Author

Thanks! That reminded me of a blogpost I read recently (can't find it rn) that you can do this in the setter of a lens.

I don't get your other suggestions. I think they would break the fix again. The point is that the check starting from line 367 only goes through if there are 2 successful compilations and the second one is different from the first.

_compilationResult = _Newtype <<< prop (SProxy :: SProxy "compilationResult")
_compilationResult = _Newtype <<< lens g s
where
g r = r.compilationResult
Copy link
Contributor

Choose a reason for hiding this comment

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

grrr 🐯

Choose a reason for hiding this comment

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

🚼Learning about plutus @jhbertra .
Are you waiting for SProxy compliationResult class to update and therefore you must rely on a local var declaration?

Copy link
Contributor

@jhbertra jhbertra left a comment

Choose a reason for hiding this comment

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

LGTM. I just have a question about the logic still

Comment on lines 98 to 102
s r c =
if is (_Success <<< _Right) c then
r { compilationResult = c, lastSuccessfulCompilationResult = c }
else
r { compilationResult = c }
Copy link
Contributor

Choose a reason for hiding this comment

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

This will still only update the field if the result is a success - is this what you want? If so, maybe it would be better to make lastSuccessfulCompilationResult field a Maybe instead of a WebData. Otherwise, you might want to consider this instead:

Suggested change
s r c =
if is (_Success <<< _Right) c then
r { compilationResult = c, lastSuccessfulCompilationResult = c }
else
r { compilationResult = c }
s r c =
case r. ^. _lastSuccessfulCompilationResult, c of
_, Sucess (Right _) -> -- assign if it is a successful result
r { compilationResult = c, lastSuccessfulCompilationResult = c }
Sucess (Right _), _ -> -- else do not assign if the last result was a success
r { compilationResult = c }
_, _ -> -- else assign regardless (for initial loading, failure states to display)
r { compilationResult = c, lastSuccessfulCompilationResult = c }

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is actually what I want. But the Maybe suggestion is a good one, that cleaned up (and clarified) the code a bit.


_successfulCompilationResult :: Traversal' State CompilationResult
_successfulCompilationResult = _compilationResult <<< _Success <<< _Right <<< _InterpreterResult <<< _result

_lastSuccessfulCompilationResult :: Lens' State (WebData (Either InterpreterError (InterpreterResult CompilationResult)))
Copy link
Contributor

Choose a reason for hiding this comment

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

To discourage setting this field directly, I'd suggest making it a Getter instead

Suggested change
_lastSuccessfulCompilationResult :: Lens' State (WebData (Either InterpreterError (InterpreterResult CompilationResult)))
_lastSuccessfulCompilationResult :: Getter' State (WebData (Either InterpreterError (InterpreterResult CompilationResult)))

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I actually tried this, but this caused a runtime error! Not sure why...

Copy link
Contributor

Choose a reason for hiding this comment

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

Yikes... that shouldn't happen. I've seen runtime errors happen when switching branches and my webpack cache got stale. I can't think of another reason why that would happen though.

@michaelpj
Copy link
Contributor

plutus-apps has split off from plutus. Apologies for the inconvenience, but this needs to be ported to the new repository here: https://github.com/input-output-hk/plutus-apps

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.

4 participants