Copilot-Language / copilot

A stream-based runtime-verification framework for generating hard real-time C code.
http://copilot-language.github.io
629 stars 50 forks source link

`copilot-prettyprinter`: Support pretty-printing struct updates #526

Closed RyanGlScott closed 1 week ago

RyanGlScott commented 2 months ago

Copilot 3.20 added support for struct updates via the new UpdateField operation. At the moment, there is no support in the copilot-prettyprinter package for pretty-printing UpdateField operations. For example, this means that the following Copilot specification will fail when executed:

{-# LANGUAGE DataKinds #-}
{-# LANGUAGE NoImplicitPrelude #-}
module Main (main) where

import Data.Foldable (for_)
import Data.Functor (void)
import Data.Word (Word32)

import qualified Copilot.PrettyPrint as PP
import Language.Copilot

data S = S
  { unS :: Field "unS" Word32
  }

instance Struct S where
  typeName _ = "s"
  toValues s = [Value typeOf (unS s)]

instance Typed S where
  typeOf = Struct (S (Field 0))

spec :: Spec
spec = do
  let externS :: Stream S
      externS = extern "extern_s" Nothing

      example :: Stream Word32
      example = (externS ## unS =: 42) # unS

  trigger "example" (example == example) [arg externS, arg example]

main :: IO ()
main = do
  spec' <- reify spec
  putStrLn $ PP.prettyPrint spec'
$ runghc UpdateFieldPP.hs 
UpdateFieldPP.hs: src/Copilot/PrettyPrint.hs:(79,12)-(102,31): Non-exhaustive patterns in case

I have a prototype fix available in this branch, which could be used as a starting point for a patch.

ivanperez-keera commented 3 weeks ago

Description

Copilot currently supports modifying values from streams of structs, but not pretty-printing them using copilot-prettyprinter.

Type

Additional context

Requester

Method to check presence of bug

Running the following specification that pretty-prints a spec with a struct update:

{-# LANGUAGE DataKinds #-}
{-# LANGUAGE NoImplicitPrelude #-}
module Main (main) where

import Data.Foldable (for_)
import Data.Functor (void)
import Data.Word (Word32)

import qualified Copilot.PrettyPrint as PP
import Language.Copilot

data S = S
  { unS :: Field "unS" Word32
  }

instance Struct S where
  typeName _ = "s"
  toValues s = [Value typeOf (unS s)]

instance Typed S where
  typeOf = Struct (S (Field 0))

spec :: Spec
spec = do
  let externS :: Stream S
      externS = extern "extern_s" Nothing

      example :: Stream Word32
      example = (externS ## unS =: 42) # unS

  trigger "example" (example == example) [arg externS, arg example]

main :: IO ()
main = do
  spec' <- reify spec
  putStrLn $ PP.prettyPrint spec'

produces an error message:

$ runghc UpdateFieldPP.hs 
UpdateFieldPP.hs: src/Copilot/PrettyPrint.hs:(79,12)-(102,31): Non-exhaustive patterns in case

when it should instead execute correctly and pretty-print the spec.

Expected result

Copilot allows pretty-printing struct updates in copilot-prettyprinter.

Desired result

Copilot allows pretty-printing struct updates in copilot-prettyprinter.

Proposed solution

Introduce a case for pretty-printing struct updates.

Further notes

None.

ivanperez-keera commented 3 weeks ago

Change Manager: Confirmed that the issue exists.

ivanperez-keera commented 3 weeks ago

Technical Lead: Confirmed that the issue should be addressed.

ivanperez-keera commented 3 weeks ago

Technical Lead: Issue scheduled for fixing in Copilot 4.

Fix assigned to: @RyanGlScott .

RyanGlScott commented 3 weeks ago

Implementor: Solution implemented, review requested.

ivanperez-keera commented 1 week ago

Change Manager: Verified that:

ivanperez-keera commented 1 week ago

Change Manager: Implementation ready to be merged.