Skip to content

copilot-c99: Allow multiple triggers with the same name. Refs #296. #572

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

Merged

Conversation

fdedden
Copy link
Member

@fdedden fdedden commented Dec 20, 2024

Extends the C99 backend to allow multiple references to the same trigger:

spec = do
  trigger "f" guard0 [arg $ constI8 10]
  trigger "f" guard1 [arg $ constI8 12]

Note that the guards may overlap, which will mean the trigger is called twice in that iteration.

As C99 does not allow multiple function definitions sharing the same name, we can only allow a single type per trigger function. The following is explicitly disallowed by the backend:

spec = do
  trigger "f" guard0 [arg $ constI8 10]
  trigger "f" guard1 [arg $ constI8 12, arg $ constI8 15]

Upon compilation, the user gets an error message:

Copilot error: attempt at compiling specification with conflicting trigger definitions.
Multiple triggers have the same name, but different argument types.

Feel free to make any modification necessary to my commits.

@ivanperez-keera ivanperez-keera changed the title copilot-c99: Allow multiple triggers with the same name copilot-c99: Allow multiple triggers with the same name. Refs #296. Dec 27, 2024
@Copilot-Language Copilot-Language deleted a comment from fdedden Jan 2, 2025
@ivanperez-keera
Copy link
Member

ivanperez-keera commented Jan 2, 2025

Change Manager: Can you please:

  • Rebase the branch on top of master.
  • Align the internal imports in CodeGen.hs.
  • Align the internal imports in Compile.hs.
  • Align the following block of definitions in Compile.hs:
     streams  = specStreams spec
     triggers = specTriggers spec
+    uniqueTriggers = mkUniqueTriggers triggers
     exts     = gatherExts streams triggers
  • Change the first commit message to:
copilot-c99: Add specific `Trigger` representation. Refs #296.
    
The current implementation of Copilot does not allow using the same
trigger handler name multiple times, since the C99 backend produces
multiple repeated declarations, which is invalid. Consequently, the code
generator assumes that trigger names are unique.

To allow for multiple triggers that trigger the same handler, we need
to introduce a separate construct in triggers that acts as a unique identifier.

This commit introduces a datatype to represent a `Trigger` with a unique
name that is different from that of the function it calls when triggered.
  • Change the second commit message to:
copilot-c99: Adapt `mkStep` to use unique triggers. Refs #296.
    
The current implementation of Copilot does not allow using the same
trigger handler name multiple times, since the C99 backend produces
multiple repeated declarations, which is invalid.

A prior commit has introduced a representation of triggers with unique
IDs, which allow us to distinguish between an use of a handler function
vs the declaration or name of the function being called when a monitor
becomes true.

This commit update the generation of the `step` function to use unique
names for the triggers.
  • Change the third commit message to:
copilot-c99: Adapt top-level compilation functions to use unique triggers. Refs #296.
    
The current implementation of Copilot does not allow using the same
trigger handler name multiple times, since the C99 backend produces
multiple repeated declarations, which is invalid.

Prior commits have introduced a representation of triggers with unique
IDs (which allow us to distinguish between an use of a handler function
vs the name of the function being called when a monitor becomes true),
and have adapted low-level functions accordingly.

This commit adapts the top-level compilation functions in the same way,
by generating trigger guards and argument functions using the unique
names.
  • Change the fourth commit message to:
copilot-c99: Remove duplicate trigger declarations in .h output. Refs #296.

The current implementation of Copilot's C99 backend produces
multiple repeated declarations when the same trigger is used multiple
times, which is invalid C code.

This commit modifies the code that generates the header file to prevent
the same trigger from being declared multiple times.
  • Change the fifth commit message to:
copilot-c99: Disallow conflicting trigger definitions. Refs #296.

The current implementation of Copilot does not allow using the same
trigger handler name multiple times, since the C99 backend produces
multiple repeated declarations, which is invalid.

Prior commits have modified the C99 backend to now allow for
multiple triggers with the same handler. However, the resulting code
is only valid in C if the triggers always have the same type signatures,
since C does not support polymorphism.

This commit adds an additional check to the compilation step to
ensure that triggers used multiple times are always used with the
same types (and, consequently, the same arity).
  • In the CHANGELOG, put your entry last in the block instead of first.

@fdedden fdedden force-pushed the develop-multiple-triggers branch from 304313c to 442d842 Compare January 2, 2025 19:06
@ivanperez-keera
Copy link
Member

Change Manager: Can you please modify the Representation.hs module to have the opening parenthesis in the export list in the same line as the first element being exported?

…uage#296.

The current implementation of Copilot does not allow using the same
trigger handler name multiple times, since the C99 backend produces
multiple repeated declarations, which is invalid. Consequently, the code
generator assumes that trigger names are unique.

To allow for multiple triggers that trigger the same handler, we need to
introduce a separate construct in triggers that acts as a unique
identifier.

This commit introduces an internal datatype to represent a `Trigger`
with a unique name that is different from that of the function called
when triggered.
…uage#296.

The current implementation of Copilot does not allow using the same
trigger handler name multiple times, since the C99 backend produces
multiple repeated declarations, which is invalid.

A prior commit has introduced a representation of triggers with unique
IDs, allowing us to distinguish between a monitor for one condition
within a Copilot spec vs the external C function being called when the
condition becomes true.

This commit updates the generation of the `step` function to use unique
names for the triggers.
…gers. Refs Copilot-Language#296.

The current implementation of Copilot does not allow using the same
trigger handler name multiple times, since the C99 backend produces
multiple repeated declarations, which is invalid.

Prior commits have introduced a representation of triggers with unique
IDs (allowing us to distinguish between a monitor for one condition
within a Copilot spec vs the external C function being called when the
condition becomes true), and have adapted low-level functions
accordingly.

This commit adapts the top-level compilation functions in the same way,
by generating trigger guards and argument functions using the unique
names.
…opilot-Language#296.

The current implementation of Copilot's C99 backend produces
multiple repeated declarations when the same trigger is used multiple
times, which is invalid C code.

This commit modifies the code that generates the header file to prevent
the same trigger from being declared multiple times.
…anguage#296.

The current implementation of Copilot does not allow using the same
trigger handler name multiple times, since the C99 backend produces
multiple repeated declarations, which is invalid.

Prior commits have modified the C99 backend to now allow for
multiple triggers with the same handler. However, the resulting code
is only valid in C if the triggers always have the same type signatures,
since C does not support polymorphism.

This commit adds a check to the compilation step to ensure that triggers
used multiple times are always used with the same types (and,
consequently, the same arity).
@fdedden fdedden force-pushed the develop-multiple-triggers branch from 442d842 to 1d38949 Compare January 2, 2025 19:11
@fdedden
Copy link
Member Author

fdedden commented Jan 2, 2025

Implementor: Fix implemented, review requested.

@ivanperez-keera
Copy link
Member

ivanperez-keera commented Jan 3, 2025

Change Manager: Verified that:

  • Solution is implemented:
    • The code proposed compiles and passes all tests. Details:
      Build log: https://app.travis-ci.com/github/Copilot-Language/copilot/builds/273723103
    • The solution proposed produces the expected result. Details:
      The following dockerfile checks that a spec with the same trigger name used multiple times can be compiled correctly, and the resulting C code also compiles, after which it prints the message "Success":
      --- Dockerfile-verify-296
      FROM ubuntu:trusty
      
      RUN apt-get update
      
      RUN apt-get install --yes software-properties-common
      RUN add-apt-repository ppa:hvr/ghc
      RUN apt-get update
      
      RUN apt-get install --yes ghc-8.6.5 cabal-install-2.4
      RUN apt-get install --yes libz-dev
      
      ENV PATH=/opt/ghc/8.6.5/bin:/opt/cabal/2.4/bin:$PWD/.cabal-sandbox/bin:$PATH
      
      RUN cabal update
      RUN cabal v1-sandbox init
      RUN cabal v1-install alex happy
      RUN apt-get install --yes git
      
      ADD MultipleTriggers.hs /tmp/MultipleTriggers.hs
      
      SHELL ["/bin/bash", "-c"]
      CMD git clone $REPO && cd $NAME && git checkout $COMMIT && cd .. \
        && cabal v1-install $NAME/copilot**/ \
        && cabal v1-exec -- runhaskell /tmp/MultipleTriggers.hs \
        && gcc -c triggers.c \
        && echo "Success"
      
      --- MultipleTriggers.hs
      import Language.Copilot
      import Copilot.Compile.C99
      
      import Prelude hiding ((>), (<), div)
      
      -- External temperature as a byte, range of -50C to 100C
      temp :: Stream Word8
      temp = extern "temperature" Nothing
      
      spec = do
        -- Triggers that fire when the temp is too low or too high, pass the current
        -- temp as an argument.
        trigger "adjust" (temp < 18) [arg temp]
        trigger "adjust" (temp > 21) [arg temp]
      
      -- Compile the spec
      main = reify spec >>= compile "triggers"
      
      Command (substitute variables based on new path after merge):
      $ docker run -e "REPO=https://github.com/fdedden/copilot" -e "NAME=copilot" -e "COMMIT=1d389490d6e1017932679bb7a639dd9856bd04f8" -it copilot-verify-296
      
  • Implementation is documented. Details:
    All new top-level definitions have haddock comments, and any sizeable new local definitions or substantial changes have associated comments.
  • Change history is clear.
  • Commit messages are clear.
  • Changelogs are updated.
  • Examples are updated. Details:
    No updates needed.
  • Required version bumps are evaluated. Details:
    Bump not needed; API remains backwards compatible.

@ivanperez-keera ivanperez-keera merged commit 86a9ce0 into Copilot-Language:master Jan 3, 2025
1 check passed
RyanGlScott added a commit to Copilot-Language/copilot-bluespec that referenced this pull request Jan 20, 2025
`copilot-c99-4.2` (part of the overall Copilot 4.2 release) now allows multiple
triggers with the same handler, provided that the triggers always have the same
type signatures. See Copilot-Language/copilot#296 (as
well as the fix in Copilot-Language/copilot#572). Since
`copilot-bluespec` wishes to achieve feature parity with `copilot-c99`, we
would like to add this ability to `copilot-bluespec` as well.

This commit adds multiple triggers support for `copilot-bluespec`, piggybacking
off of the implementation in
Copilot-Language/copilot#572.
RyanGlScott added a commit to Copilot-Language/copilot-verifier that referenced this pull request Jan 20, 2025
Although `copilot-c99` added the ability to invoke multiple triggers with the
same name in Copilot-Language/copilot#572, it is not
yet clear how best to support this in `copilot-verifier`.

In the meantime, this adds an explicit check that rules out specifications that
use multiple triggers with the same name to prevent the verifier from becoming
confused by them. The remaining task of fully supporting such specifications is
tracked in #74.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

2 participants