From 60314bd235e862819ab4d4bf4ad30a291f8a7dff Mon Sep 17 00:00:00 2001 From: Lucas Kramer Date: Wed, 14 Feb 2024 16:06:43 -0600 Subject: [PATCH 1/6] Handle higher-rank fields in CShow --- src/Libraries/Base1/CShow.bs | 3 +++ testsuite/bsc.lib/CShow/TestCShow.bs | 5 +++++ testsuite/bsc.lib/CShow/sysTestCShow.out.expected | 1 + 3 files changed, 9 insertions(+) diff --git a/src/Libraries/Base1/CShow.bs b/src/Libraries/Base1/CShow.bs index 2017ecb42..f0e8a59e9 100644 --- a/src/Libraries/Base1/CShow.bs +++ b/src/Libraries/Base1/CShow.bs @@ -73,6 +73,9 @@ instance (CShow a) => CShow' (Conc a) where cshow' (Conc x) = cshow x cshowP' (Conc x) = cshowP x +instance CShow' (ConcPoly a) where + cshow' (ConcPoly _) = $format "" + -- Note that below there are more specific instances for -- CShow' (Meta (MetaConsNamed ...)) and CShow' (Meta (MetaConsAnon ...)) instance (CShow' a) => CShow' (Meta m a) where diff --git a/testsuite/bsc.lib/CShow/TestCShow.bs b/testsuite/bsc.lib/CShow/TestCShow.bs index 56d8340f6..ed5785cc7 100644 --- a/testsuite/bsc.lib/CShow/TestCShow.bs +++ b/testsuite/bsc.lib/CShow/TestCShow.bs @@ -19,6 +19,10 @@ struct Bar = data Baz a = Baz a a deriving (FShow) +struct Qux = + x :: a -> a -- Higher rank + y :: Int 8 + sysTestCShow :: Module Empty sysTestCShow = module rules @@ -35,4 +39,5 @@ sysTestCShow = module $display (cshow ((vec (Bar {x=42; foo=C}) (Bar {x=3; foo=B 2323})) :: Vector 2 Bar)) $display (cshow ((Bar {x=42; foo=C}) :> (Bar {x=3; foo=B 2323}) :> ListN.nil)) $display (cshow ("x", ((Left 123) :: Either (UInt 8) Bar, False))) + $display (cshow $ Qux {x = id; y = 42;}) $finish diff --git a/testsuite/bsc.lib/CShow/sysTestCShow.out.expected b/testsuite/bsc.lib/CShow/sysTestCShow.out.expected index 2b57e7626..cf9ee03e5 100644 --- a/testsuite/bsc.lib/CShow/sysTestCShow.out.expected +++ b/testsuite/bsc.lib/CShow/sysTestCShow.out.expected @@ -10,3 +10,4 @@ Baz C (A 12 True (Bar {foo=D {a=0x22; b=C}; x= 42})) [Bar {foo=C; x= 42}, Bar {foo=B 2323; x= 3}] [Bar {foo=C; x= 42}, Bar {foo=B 2323; x= 3}] ("x", Left 123, False) +Qux {x=; y= 42} From 9ca1eafe87a8bf3b3aff2f383faa2154d1024a5a Mon Sep 17 00:00:00 2001 From: Lucas Kramer Date: Sun, 11 Feb 2024 15:48:51 -0600 Subject: [PATCH 2/6] Add docs for string types in language ref manuals --- doc/.gitignore | 3 +++ doc/BH_ref_guide/BH_lang.tex | 21 +++++++++++++++++++++ doc/BSV_ref_guide/BSV_lang.tex | 34 ++++++++++++++++++++++++++++++---- 3 files changed, 54 insertions(+), 4 deletions(-) diff --git a/doc/.gitignore b/doc/.gitignore index 96ea9af7a..d45d1d03c 100644 --- a/doc/.gitignore +++ b/doc/.gitignore @@ -13,3 +13,6 @@ *.out *.pdf *.toc +*.fdb_latexmk +*.fls +*.synctex.gz diff --git a/doc/BH_ref_guide/BH_lang.tex b/doc/BH_ref_guide/BH_lang.tex index 69778b12b..c90b20bb9 100644 --- a/doc/BH_ref_guide/BH_lang.tex +++ b/doc/BH_ref_guide/BH_lang.tex @@ -664,6 +664,18 @@ \section{Types} \end{verbatim} represents the type of unsigned integers that can be represented in 32 bits. +These numeric types are said to have kind \texttt{\#}, +rather than kind \texttt{*} for value types. + +\index{string types} +Strings can also be used as type, having kind \texttt{\$}. +This is less common, but string types are quite useful in the generics library, +described in the \LibRefGuide. +Examples: +\begin{verbatim} + MetaData#("Prelude","Maybe",PrimUnit,2) + MetaConsNamed#("Valid",1,1) +\end{verbatim} % ---------------------------------------------------------------- @@ -2720,6 +2732,15 @@ \subsection{The ``size'' types} The second line binds {\te{logWPlusOne}} to the integer value corresponding to {\te{n}}. +{\index{stringOf@\te{stringOf} (``function'' of string types)}} +A ``function'' {\te{stringOf}} is also available to get the string value +of a type-level string. +\begin{verbatim} + type MyString = "Hello, world!" + x :: String + x = stringOf MyString -- x will have the value "Hello, world!" +\end{verbatim} + % ---------------------------------------------------------------- \subsection{The type \te{Bit}} diff --git a/doc/BSV_ref_guide/BSV_lang.tex b/doc/BSV_ref_guide/BSV_lang.tex index 7b68a2ddc..e760f29b4 100644 --- a/doc/BSV_ref_guide/BSV_lang.tex +++ b/doc/BSV_ref_guide/BSV_lang.tex @@ -1528,6 +1528,16 @@ \section{Types} bits indexed from $m$ (msb/left) down through 0 (lsb/right), for $m \ge 0$. +\index{string types} +Type parameters can also be strings (known as \emph{string} types). +These are not common, but are quite useful in the generics library, +described in the \LibRefGuide. +Examples: +\begin{verbatim} + MetaData#("Prelude","Maybe",PrimUnit,2) + MetaConsNamed#("Valid",1,1) +\end{verbatim} + % ---------------------------------------------------------------- \subsection{Polymorphism} @@ -1719,6 +1729,22 @@ \subsubsection{The pseudo-function \te{valueof} (or \te{valueOf})} described in Section {\ref{sec-sizeof}}, which converts a type to a numeric type. +\subsubsection{The pseudo-function \te{stringof} (or \te{stringOf})} + +A function \texttt{stringof} (or \texttt{stringOf}) +\index{stringOf@\texttt{stringOf} (pseudo-function of string types)} +similar to \te{valueof} +exists to convert a string type to a string value. +Example: +\begin{verbatim} + instance CShow'#(Meta#(MetaConsNamed#(name, idx, nfields), a)) + provisos (CShowSummand#(a)); + function cshow'(tagged Meta {x}); + return $format(stringOf(name), " {", cshowSummandNamed(x), "}"); + endfunction + endinstance +\end{verbatim} + % ---------------------------------------------------------------- \subsection{A brief introduction to \texttt{deriving} clauses} @@ -1919,7 +1945,7 @@ \subsection{Interface declaration} \gram{typeFormals}{\term{\#} \term{(} \nterm{typeFormal} \many{ \term{,} \nterm{typeFormal}}\term{)} }} -\gram{typeFormal}{\opt{\term{numeric}} \term{type} \nterm{typeIde}} +\gram{typeFormal}{\opt{\term{numeric} {\alt} \term{string}} \term{type} \nterm{typeIde}} \gram{interfaceMemberDecl}{ \nterm{methodProto} {\alt} \nterm{subinterfaceDecl} } @@ -3903,7 +3929,7 @@ \subsection{Type synonyms} \gram{typeFormals}{\term{\#} \term{(} \nterm{typeFormal} \many{ \term{,} \nterm{typeFormal}}\term{)} }} -\gram{typeFormal}{\opt{\term{numeric}} \term{type} \nterm{typeIde}} +\gram{typeFormal}{\opt{\term{numeric} {\alt} \term{string}} \term{type} \nterm{typeIde}} % \gram{typeDefType}{\nterm{typeIde} \opt{\term{\#} \term{(} @@ -4138,7 +4164,7 @@ \subsection{Structs and tagged unions} \gram{typeFormals}{\term{\#} \term{(} \nterm{typeFormal} \many{ \term{,} \nterm{typeFormal}}\term{)} }} -\gram{typeFormal}{\opt{\term{numeric}} \term{type} \nterm{typeIde}} +\gram{typeFormal}{\opt{\term{numeric} {\alt} \term{string}} \term{type} \nterm{typeIde}} @@ -4458,7 +4484,7 @@ \subsection{Type class declarations} \gram{typeFormals}{\term{\#} \term{(} \nterm{typeFormal} \many{ \term{,} \nterm{typeFormal}}\term{)} } -\gram{typeFormal}{\opt{\term{numeric}} \term{type} \nterm{typeIde}} +\gram{typeFormal}{\opt{\term{numeric} {\alt} \term{string}} \term{type} \nterm{typeIde}} \gram{typedepends} {\term{dependencies} \term{(} \nterm{typedepend} \many From ec8910f591b56a3f2298e4949a3b2c529b45a4df Mon Sep 17 00:00:00 2001 From: Julie Schwartz Date: Sat, 17 Feb 2024 11:43:50 +1300 Subject: [PATCH 3/6] Docs: Clean up macros and copyright/version info --- doc/BH_ref_guide/BH_lang.tex | 7 ++----- doc/BH_ref_guide/version.tex | 2 +- doc/BSV_ref_guide/BSV_lang.tex | 11 +++++------ doc/BSV_ref_guide/version.tex | 2 +- doc/libraries_ref_guide/LibDoc/BGetPut.tex | 2 +- doc/libraries_ref_guide/LibDoc/Vector.tex | 2 +- doc/libraries_ref_guide/libraries_ref_guide.tex | 9 ++++++++- doc/libraries_ref_guide/version.tex | 8 ++++++-- doc/user_guide/version.tex | 8 ++++++-- src/Libraries/Base1/Fork.bs | 2 +- src/Libraries/Base1/ListN.bs | 2 +- src/Libraries/Base1/Vector.bs | 2 +- src/Libraries/Base2/BGetPut.bs | 2 +- src/Libraries/Base2/EqFunction.bs | 2 +- src/Libraries/Base2/IVec.bs | 2 +- 15 files changed, 37 insertions(+), 26 deletions(-) diff --git a/doc/BH_ref_guide/BH_lang.tex b/doc/BH_ref_guide/BH_lang.tex index c90b20bb9..48576d8b8 100644 --- a/doc/BH_ref_guide/BH_lang.tex +++ b/doc/BH_ref_guide/BH_lang.tex @@ -117,13 +117,10 @@ \newcommand{\BSInc}{Bluespec, Inc.} \newcommand{\BH}{BH} -\newcommand\BHfull{Bluespec Haskell/Classic} +\newcommand{\BHFull}{Bluespec Haskell/Classic} -\newcommand{\blue}{Bluespec SystemVerilog} \newcommand{\BSVFull}{Bluespec SystemVerilog} \newcommand{\BSV}{BSV} -\newcommand{\BSVVersion}{3.8} -\newcommand{\BSVvN}{BSV 3.8} \newcommand{\bsc}{\emph{bsc}} @@ -377,7 +374,7 @@ \section{Introduction} -{\BH} ({\BHfull}) is a language for hardware design. The language borrows its +{\BH} ({\BHFull}) is a language for hardware design. The language borrows its notation, type and package system from an existing general-purpose functional programming language called Haskell {\cite{haskell12}}{\index{Haskell}} where those constructs have been diff --git a/doc/BH_ref_guide/version.tex b/doc/BH_ref_guide/version.tex index 274d873f5..76fe7f1e5 100644 --- a/doc/BH_ref_guide/version.tex +++ b/doc/BH_ref_guide/version.tex @@ -1,4 +1,4 @@ -\author{Revision: 26 July 2022} +\author{Revision: 17 February 2024} \date{ Copyright {\copyright} diff --git a/doc/BSV_ref_guide/BSV_lang.tex b/doc/BSV_ref_guide/BSV_lang.tex index e760f29b4..da82c3210 100644 --- a/doc/BSV_ref_guide/BSV_lang.tex +++ b/doc/BSV_ref_guide/BSV_lang.tex @@ -110,16 +110,16 @@ \newcommand{\LibRefGuide}{\emph{Libraries Reference Guide}} \newcommand{\LibRefGuideFullName}{\emph{Bluespec Compiler (BSC) Libraries Reference Guide}} +\newcommand{\BSCUserGuide}{\emph{BSC User Guide}} +\newcommand{\BSCUserGuideFullName}{\emph{Bluespec Compiler (BSC) User Guide}} + \newcommand{\BS}{Bluespec} \newcommand{\BSInc}{Bluespec, Inc.} \newcommand{\BH}{BH} -\newcommand{\blue}{Bluespec SystemVerilog} \newcommand{\BSVFull}{Bluespec SystemVerilog} \newcommand{\BSV}{BSV} -\newcommand{\BSVVersion}{3.8} -\newcommand{\BSVvN}{BSV 3.8} \newcommand{\bsc}{\emph{bsc}} @@ -264,7 +264,6 @@ \resizebox{2in}{!}{\includegraphics[width=\textwidth]{../common/B-Lang}} \\ \vspace{0.3in} {\BS}$^{\rm{TM}}$ {\SV} \\ -%Version {\BSVVersion} \\ Language Reference Guide \\ \vspace*{1in} \vspace*{1in} @@ -10034,7 +10033,7 @@ \subsubsection{\te{split} and \te{nosplit}} \end{verbatim} To enable rule splitting for an entire design, use the compiler -flag \te{-split-if} at compile time. See the user guide for +flag \te{-split-if} at compile time. See the {\BSCUserGuideFullName} for more information on compiler flags. You can enable rule splitting for an entire design with the \te{-split-if} flag and then disable the effect for specific rules, by specifying the \te{nosplit} attribute @@ -11001,7 +11000,7 @@ \subsubsection{Rules} \end{verbatim} The designer can ensure that the signals will exist in the Verilog by using an appropriate compiler flag, the \te{-keep-fires} flag which -is documented in the {\blue} User Guide. +is documented in the {\BSCUserGuideFullName}. The \te{doc} attribute can be attached to any \te{rule..endrule} expression, such as inside a function or inside a for-loop. diff --git a/doc/BSV_ref_guide/version.tex b/doc/BSV_ref_guide/version.tex index c98221e24..76fe7f1e5 100644 --- a/doc/BSV_ref_guide/version.tex +++ b/doc/BSV_ref_guide/version.tex @@ -1,4 +1,4 @@ -\author{Revision: 26 April 2022} +\author{Revision: 17 February 2024} \date{ Copyright {\copyright} diff --git a/doc/libraries_ref_guide/LibDoc/BGetPut.tex b/doc/libraries_ref_guide/LibDoc/BGetPut.tex index 59a145091..e63fa1dbb 100644 --- a/doc/libraries_ref_guide/LibDoc/BGetPut.tex +++ b/doc/libraries_ref_guide/LibDoc/BGetPut.tex @@ -16,7 +16,7 @@ \subsubsection{BGetPut} \te{Get} and \te{Put}, but the interconnection of them (via \te{Connectable} or in {\veri}) is implemented with a simple protocol that allows all inputs and outputs to be directly connected. -All wires go to registers and have no {\blue} handshaking. +All the ports are directly registered, without the logic of ready/enable handshaking. The protocol makes no assumptions about setup time and hold time for the registers at each end; so these interfaces may be used when the two ends have different clocks. diff --git a/doc/libraries_ref_guide/LibDoc/Vector.tex b/doc/libraries_ref_guide/LibDoc/Vector.tex index 24411d979..06cf9e077 100644 --- a/doc/libraries_ref_guide/LibDoc/Vector.tex +++ b/doc/libraries_ref_guide/LibDoc/Vector.tex @@ -131,7 +131,7 @@ \subsubsection{Creating and Generating Vectors} The following functions are used to create new vectors, with and without defined elements. -There are no {\blue} constructors available for this abstract type +There are no constructors available for this abstract type (and hence no pattern-matching is available for this type) but the following functions may be used to construct values of the \te{Vector} type. diff --git a/doc/libraries_ref_guide/libraries_ref_guide.tex b/doc/libraries_ref_guide/libraries_ref_guide.tex index 9b7d52dbb..c46388066 100644 --- a/doc/libraries_ref_guide/libraries_ref_guide.tex +++ b/doc/libraries_ref_guide/libraries_ref_guide.tex @@ -98,9 +98,16 @@ % ---------------- % Language names +% Name for the company \newcommand{\BS}{Bluespec} +% Name for the languages and tools +\newcommand{\Blue}{Bluespec} + \newcommand{\BSV}{BSV} -\newcommand{\blue}{Bluespec SystemVerilog} +\newcommand{\BSVFull}{Bluespec SystemVerilog} + +\newcommand{\BH}{BH} +\newcommand{\BHFull}{Bluespec Haskell/Classic} \newcommand{\V}{Verilog} \newcommand{\veri}{Verilog} diff --git a/doc/libraries_ref_guide/version.tex b/doc/libraries_ref_guide/version.tex index 5cec1b198..76fe7f1e5 100644 --- a/doc/libraries_ref_guide/version.tex +++ b/doc/libraries_ref_guide/version.tex @@ -1,5 +1,9 @@ -\author{Revision: 25 January 2021} +\author{Revision: 17 February 2024} \date{ -Copyright {\copyright} 2021 Bluespec, Inc. All rights reserved +Copyright {\copyright} +\begin{tabular}[t]{ll} +2000 -- January 2020: & Bluespec, Inc. \\ +January 2020 onwards: & various open-source contributors +\end{tabular} } diff --git a/doc/user_guide/version.tex b/doc/user_guide/version.tex index 5cec1b198..70d86645a 100644 --- a/doc/user_guide/version.tex +++ b/doc/user_guide/version.tex @@ -1,5 +1,9 @@ -\author{Revision: 25 January 2021} +\author{Revision: 3 February 2022} \date{ -Copyright {\copyright} 2021 Bluespec, Inc. All rights reserved +Copyright {\copyright} +\begin{tabular}[t]{ll} +2000 -- January 2020: & Bluespec, Inc. \\ +January 2020 onwards: & various open-source contributors +\end{tabular} } diff --git a/src/Libraries/Base1/Fork.bs b/src/Libraries/Base1/Fork.bs index 558c4a56c..bb54ad93a 100644 --- a/src/Libraries/Base1/Fork.bs +++ b/src/Libraries/Base1/Fork.bs @@ -5,7 +5,7 @@ import Vector --@ \subsubsection{Fork} --@ --@ \index{Enum@\te{Fork} (package)|textbf} ---@ The {\blue} compiler does very aggressive common subexpression +--@ The {\Blue} compiler does very aggressive common subexpression --@ elimination (CSE). If this has to be circumvented it has to be done --@ explicitly. The \te{Fork} package provides various ways to duplicate --@ values to avoid CSE. diff --git a/src/Libraries/Base1/ListN.bs b/src/Libraries/Base1/ListN.bs index fefad7d51..9aaeddd51 100644 --- a/src/Libraries/Base1/ListN.bs +++ b/src/Libraries/Base1/ListN.bs @@ -106,7 +106,7 @@ grabN i n bs = --X \begin{itemize} --X \item{\bf Creating and Generating ListNs} --X ---X There are no {\blue} constructors available for this abstract type +--X There are no constructors available for this abstract type --X (and hence no pattern-matching is available for this type) --X but the following ordinary functions may be used to construct values of --X the \te{ListN} type. diff --git a/src/Libraries/Base1/Vector.bs b/src/Libraries/Base1/Vector.bs index d44519e18..70d410993 100644 --- a/src/Libraries/Base1/Vector.bs +++ b/src/Libraries/Base1/Vector.bs @@ -134,7 +134,7 @@ instance (Bounded a, Bits a sa) => Bounded (Vector n a) --@ \begin{itemize} --@ \item{\bf Creating and Generating Vectors} --@ ---@ There are no {\blue} constructors available for this abstract type +--@ There are no constructors available for this abstract type --@ (and hence no pattern-matching is available for this type) --@ but the following ordinary functions may be used to construct values of --@ the \te{Vector} type. diff --git a/src/Libraries/Base2/BGetPut.bs b/src/Libraries/Base2/BGetPut.bs index 12421f319..871b5bd6e 100644 --- a/src/Libraries/Base2/BGetPut.bs +++ b/src/Libraries/Base2/BGetPut.bs @@ -15,7 +15,7 @@ import ClientServer --@ \te{Get} and \te{Put}, but the interconnection of them --@ (via \te{Connectable} or in {\veri}) is implemented with a simple protocol --@ that allows all inputs and outputs to be directly connected. ---@ Furthermore, all wires go to registers and have no {\blue} handshaking. +--@ All the ports are directly registered, without the logic of ready/enable handshaking. --@ The protocol makes no assumptions about setup time and hold time for the --@ registers at each end; so these interfaces may be used when the two ends --@ have different clocks. In all other circumstances, however, the diff --git a/src/Libraries/Base2/EqFunction.bs b/src/Libraries/Base2/EqFunction.bs index 24b61ea7f..ecd6dbd9a 100644 --- a/src/Libraries/Base2/EqFunction.bs +++ b/src/Libraries/Base2/EqFunction.bs @@ -18,4 +18,4 @@ instance (Bits a sa, Bounded a, Eq b) => Eq (a -> b) (/=) f g = not (f == g) --@ The ability to compare functions for equality can be useful ---@ for compile time verification of properties of the {\blue} code. +--@ for compile time verification of properties of the {\Blue} code. diff --git a/src/Libraries/Base2/IVec.bs b/src/Libraries/Base2/IVec.bs index 370202b1e..9ccba175b 100644 --- a/src/Libraries/Base2/IVec.bs +++ b/src/Libraries/Base2/IVec.bs @@ -11,7 +11,7 @@ import Vector --@ rectified, and this workaround is no longer necessary.) --@ --@ The \te{IVec} package contains some definitions to work around a deficiency ---@ in the {\blue} compiler. The compiler does not allow the type \te{Vector} in +--@ in the {\Blue} compiler. The compiler does not allow the type \te{Vector} in --@ interfaces for which code is generated. To make this almost possible this --@ package contains types that are isomorphic to \te{Vector} of some small number --@ of length (0-16). There are also conversion functions to and from \te{Vector}. From 8d88006021328c506a911b8433a7cd7fc0ccfac3 Mon Sep 17 00:00:00 2001 From: Lucas Kramer Date: Sat, 17 Feb 2024 11:57:10 +1300 Subject: [PATCH 4/6] Add documentation for generics --- doc/libraries_ref_guide/LibDoc/Prelude.tex | 329 ++++++++++++++++++ .../bsc.typechecker/generics/CustomBits.bs | 2 +- 2 files changed, 330 insertions(+), 1 deletion(-) diff --git a/doc/libraries_ref_guide/LibDoc/Prelude.tex b/doc/libraries_ref_guide/LibDoc/Prelude.tex index 5598fd4f5..3b6abd870 100644 --- a/doc/libraries_ref_guide/LibDoc/Prelude.tex +++ b/doc/libraries_ref_guide/LibDoc/Prelude.tex @@ -6909,3 +6909,332 @@ \subsection{Compile-time IO} hClose(hdl); endmodule \end{verbatim} + + +\subsection{Generics} + +\index{Generic@\te{Generic}} +\index[function]{Prelude!to} +\index[function]{Prelude!from} + +Generics is a mechanism permitting users to derive instances of their own custom type classes. +The design of generics in \BS{} is based on the +\href{https://hackage.haskell.org/package/base-4.19.0.0/docs/GHC-Generics.html}{GHC.Generics} +library in Haskell. +Generics provides a way of converting arbitrary struct and tagged union/data types +to and from a generic representation. In this representation product types are represented as tuples/\te{PrimPair}, +and sum types as \te{Either}. The representation types are also tagged with various metadata +about the types, fields and constructors, such as their name, arity and index. +Users can implement a default instance for their type class, using a helper type class over the generic representation. + +Due to the complexity of the types involved, writing generic instances in \BSVFull{} can be rather tedious. +Thus the documentation here is instead given using the \BHFull{} syntax. + +\subsubsection{The \te{Generic} type class} + +The \te{Generic} type class defines a means of converting +values of a datatype \te{a} into a generic representation \te{r}. +The type \te{r} is determined by the type \te{a} as a functional dependency. +The function \te{from} converts a value into its generic representation, +and \te{to} converts a generic representation back into a value. + +\begin{verbatim} + class Generic a r | a -> r where + from :: a -> r + to :: r -> a +\end{verbatim} + +BSC automatically derives an instance of \te{Generic} for all types that +don't have an explicit instance. For libraries that export a type +abstractly (without exporting its internals), an explicit instance is +needed, to avoid exposing the internal implementation; see the source of the \te{Vector} +library for an example of this. + +\subsubsection{Representation types} + +The following types are used in generic representations: + +\begin{center} + \begin{tabular}{|p{2 in}|p{3 in}|} + \hline + \begin{libverbatim} +data Either a b + = Left a | Right b + \end{libverbatim} + & + The standard \te{Either} type is used to represent sum types, + {\it i.e.} tagged unions/data with multiple constructors. \\ + \hline + \begin{libverbatim} +interface PrimPair a b = + fst :: a + snd :: b + \end{libverbatim} + & + The standard \te{PrimPair} type is used to represent product types, + {\it i.e.} structs/interfaces/data constructors with multiple fields. + Since this is also the same underlying representation as tuples, + tuple syntax (as described in the \BH ref guide) may be used for products in generic instances.\\ + \hline + \begin{libverbatim} +interface PrimUnit = { } + \end{libverbatim} + & + The standard \te{PrimUnit} type is used to represent types containing no data, + {\it i.e.} empty structs/interfaces/data constructors.\\ + \hline + \begin{libverbatim} +data (Vector :: # -> * -> *) + n a + \end{libverbatim} + & + The standard \te{Vector} type is used to represent fixed-size collection types -- \te{ListN} and \te{Vector}.\\ + \hline + \begin{libverbatim} +data Conc a = Conc a + \end{libverbatim} + & + The \te{Conc} type is used to wrap the (non-generic) types of fields in the sum of products. \\ + \hline + \begin{libverbatim} +data ConcPrim a = ConcPrim a + \end{libverbatim} + & + The \te{ConcPrim} type is used in \te{Generic} instances for primitive types, {\it e.g.} \te{Bit}. + This type is used instead of \te{Conc} to avoid infinite recursion through a \te{Conc} instance + of the generic version of a type class that defaults back to the non-generic one. + Users of generics typically do not need to define instances for \te{ConcPrim}; this exists to help supply + generic instances for several type classes that are used internally by BSC.\\ + \hline + \begin{libverbatim} +data ConcPoly a = ConcPoly a + \end{libverbatim} + & + The \te{ConcPoly} type exists as a workaround for a limitation of generics in dealing with higher-rank data types; + see below for more details. Users typically should not need to define instances for \te{ConcPoly}. \\ + \hline + \begin{libverbatim} +data Meta m r = Meta r + \end{libverbatim} + & + \te{Meta} is used to tag a representation type with additional type-level metadata. + The \te{m} type parameter must be one of the below metadata types \\ + \hline + \end{tabular} +\end{center} + +{\bf Examples} + +Ignoring metadata, the derived \te{Generic} instance for the \te{PrimPair} type is + +\begin{libverbatim} + instance Generic (PrimPair a b) (Conc a, Conc b) where + from x = (Conc x.fst, Conc x.snd) + to (Conc x, Conc y) = PrimPair { fst=x; snd=y; } +\end{libverbatim} + +The derived \te{Generic} instance for the \te{List} type is + +\begin{libverbatim} + instance Generic (List a) (Either () (Conc a, Conc (List a))) where + from Nil = Left () + from (Cons x y) = Right (Conc x, Conc y) + to (Left ()) = Nil + to (Right (Conc x, Conc y)) = Cons x y +\end{libverbatim} + +In the generic representation for data/tagged unions with more than two constructors, +the \te{Either} types are aranged to form a left-biased, balanced binary tree. +This makes it possible to directly convert between nested left/right constructors, +and a binary tag value corresponding to the constructor index. +An example of this, in implementing a \te{CustomBits} type class, is given below. + +{\bf Higher-rank data} + +Generics is not able to fully handle {\it higher-rank} data, {\it i.e.} structs/interfaces/data constructors +containing type variables that are not bound as type parameters. For example, the following type is higher-rank: + +\begin{libverbatim} + struct Foo = + x :: a -> a -- Higher rank + y :: Int 8 +\end{libverbatim} + +If a \te{Generic} instance were derived for this type in the usual fasion, +then the representation would contain \te{Conc (a -> a)}. +The presence of a type variable in the representation means that it is not uniquely determined by the type \te{Foo}, +as required by the functional dependency. + +Instead, when deriving an instance for a higher-rank struct or data, a ``wrapper'' struct is generated +for each higher-rank field. This is wrapped in the \te{ConcPoly} constructor, to indicate that this +is not the real type of the field: + +\begin{libverbatim} + struct Foo_x = + val :: a -> a + + instance Generic Foo (ConcPoly Foo_x, Conc (Int 8))) where + from a = (ConcPoly (Foo_x { val = a.x; }), Conc a.y) + to (ConcPoly x, Conc y) = Foo { x = x.val; y = y; } +\end{libverbatim} + +Users can omit an instance for \te{ConcPoly} to not support higher-rank data, +or define some useful default behavior. +For example, the \te{CShow} library defines an instance for ConcPoly +to return a placeholder string for higher-rank fields. + +\subsubsection{Metadata types} + +The following types are used to represent metadata in generic representations. +Note that these only appear at the type level tagging a \te{Meta} type; +values of these types are not constructed. + +\begin{center} + \begin{tabular}{|p{2.9 in}|p{2.7 in}|} + \hline + \begin{libverbatim} +data (MetaData :: $ -> $ -> * -> # -> *) + name pkg tyargs ncons + \end{libverbatim} + & + Indicates that a representation is for a type (e.g. struct/data) with a name, + package, tuple of type arguments and number of constructors. + Types of kind \te{*}, \te{\#} or \te{\$} appearing in the type arguments are wrapped + in one of the following type constructors: + \vspace{0.1in} + \begin{libverbatim} + data (StarArg :: * -> *) i + data (NumArg :: # -> *) i + data (StrArg :: $ -> *) i + data ConArg + \end{libverbatim} + \vspace{-0.15in} + Constructor-kinded types arguments cannot be handled in general and + are omitted from the \te{ConArg} representation type. + \\ + \hline + \begin{libverbatim} +data (MetaConsNamed :: $ -> # -> # -> *) + name idx nfields + \end{libverbatim} + & + Indicates that a representation is for a constructor with named fields, + with a name, index in the data's constructors, and number of fields. \\ + \hline + \begin{libverbatim} +data (MetaConsAnon :: $ -> # -> # -> *) + name idx nfields + \end{libverbatim} + & + Indicates that a representation is for a data constructor with anonymous fields, + with a name, index in the data's constructors, and number of fields. \\ + \hline + \begin{libverbatim} +data (MetaField :: $ -> # -> *) name idx + \end{libverbatim} + & + Indicates that a representation is for a field, with a field name (either the + given name for a named field or the generated field name for an anonymous + field) and index in the constructor's fields. \\ + \hline + \end{tabular} +\end{center} + +{\bf Examples} + +Including metadata, the derived \te{Generic} instance for the \te{PrimPair} type is + +\begin{libverbatim} + instance Generic (PrimPair a b) + (Meta (MetaData "PrimPair" "Prelude" (StarArg a, StarArg b) 1) + (Meta (MetaConsNamed "PrimPair" 0 2) + (Meta (MetaField "fst" 0) (Conc a), + Meta (MetaField "snd" 1) (Conc b)))) where + from x = Meta (Meta (Meta (Conc x.fst), Meta (Conc x.snd))) + to (Meta (Meta (PrimPair (Meta (Conc a1)) (Meta (Conc a2))))) = + PrimPair { fst = a1; snd = a2; } +\end{libverbatim} + +The derived \te{Generic} instance for the \te{List} type is + +\begin{libverbatim} + instance Generic (List a) + (Meta (MetaData "List" "Prelude" (StarArg a) 2) + (Either (Meta (MetaConsAnon "Nil" 0 0) ()) + (Meta (MetaConsAnon "Cons" 1 2) + (Meta (MetaField "_1" 0) (Conc a), + Meta (MetaField "_2" 1) (Conc (List a)))))) where + from Nil = Meta (Left (Meta ())) + from (Cons x y) = + Meta (Right (Meta (Meta (Conc x), Meta (Conc y)))) + to (Meta (Left (Meta ()))) = Nil + to (Meta (Right (Meta ((Meta (Conc x)), (Meta (Conc y)))))) = Cons x y +\end{libverbatim} + +\subsubsection{Defining generic instances} + +The typical way for users to define a generic implementation for their type class is to define a helper type class +that works over the generic representation, and then define a default instance for the original type class +using \te{Generic} to convert to and from the generic representation. +For example, one can use generics to implement a custom version of the \te{Bits} type class: + +\begin{libverbatim} + class MyBits a n | a -> n where + mypack :: a -> Bit n + myunpack :: Bit n -> a + + -- Explicit instances for primitive types + instance MyBits (Bit n) n where + mypack = id + myunpack = id + + -- Generic default instance + instance (Generic a r, MyBits' r n) => MyBits a n where + mypack x = mypack' $ from x + myunpack bs = to $ myunpack' bs + + class MyBits' r n | r -> n where + mypack' :: r -> Bit n + myunpack' :: Bit n -> r + + -- Instance for sum types + instance (MyBits' r1 n1, MyBits' r2 n2, Max n1 n2 c, Add 1 c n, + Add p1 n1 c, Add p2 n2 c) => + MyBits' (Either r1 r2) n where + mypack' (Left x) = 1'b0 ++ extend (mypack' x) + mypack' (Right x) = 1'b1 ++ extend (mypack' x) + myunpack' bs = + let (tag, content) = (split bs) :: (Bit 1, Bit c) + in case tag of + 0 -> Left $ myunpack' $ truncate content + 1 -> Right $ myunpack' $ truncate content + + -- Instance for product types + instance (MyBits' r1 n1, MyBits' r2 n2, Add n1 n2 n) => + MyBits' (r1, r2) n where + mypack' (x, y) = mypack' x ++ mypack' y + myunpack' bs = let (bs1, bs2) = split bs + in (myunpack' bs1, myunpack' bs2) + + instance MyBits' () 0 where + mypack' () = 0'b0 + myunpack' _ = () + + instance (MyBits' a m, Bits (Vector n (Bit m)) l) => + MyBits' (Vector n a) l where + mypack' v = pack $ map mypack' v + myunpack' = map myunpack' `compose` unpack + + -- Ignore all types of metadata + instance (MyBits' r n) => MyBits' (Meta m r) n where + mypack' (Meta x) = mypack' x + myunpack' bs = Meta $ myunpack' bs + + -- Conc instance calls back to the non-generic MyBits class + instance (MyBits a n) => MyBits' (Conc a) n where + mypack' (Conc x) = mypack x + myunpack' bs = Conc $ myunpack bs +\end{libverbatim} + +A more sophisticated use of generics, making use of metadata, +can be found in the implementation of the \te{CShow} library. diff --git a/testsuite/bsc.typechecker/generics/CustomBits.bs b/testsuite/bsc.typechecker/generics/CustomBits.bs index e7de3f1ef..ee4c12b47 100644 --- a/testsuite/bsc.typechecker/generics/CustomBits.bs +++ b/testsuite/bsc.typechecker/generics/CustomBits.bs @@ -47,7 +47,7 @@ instance (MyBits' a m, Bits (Vector n (Bit m)) l) => MyBits' (Vector n a) l wher mypack' v = pack $ map mypack' v myunpack' = map myunpack' `compose` unpack --- Ignore other types of metadata +-- Ignore all types of metadata instance (MyBits' r n) => MyBits' (Meta m r) n where mypack' (Meta x) = mypack' x myunpack' bs = Meta $ myunpack' bs From dd0eb245950073f2f36f5b752dc788560e5ea12a Mon Sep 17 00:00:00 2001 From: Lucas Kramer Date: Wed, 14 Feb 2024 23:14:34 -0600 Subject: [PATCH 5/6] Remove experimental warning when using generics --- src/comp/CtxRed.hs | 11 ++--------- .../generics/GenericNegativeTests.bs.bsc-out.expected | 4 ---- 2 files changed, 2 insertions(+), 13 deletions(-) diff --git a/src/comp/CtxRed.hs b/src/comp/CtxRed.hs index abdddea55..b49a7ff13 100644 --- a/src/comp/CtxRed.hs +++ b/src/comp/CtxRed.hs @@ -4,8 +4,8 @@ import Data.List(partition, (\\)) import Control.Monad(when) import PFPrint import Id -import PreIds(tmpTyVarIds, idGeneric) -import Error(internalError, EMsg, ErrorHandle, bsWarning, bsError, ErrMsg(WExperimental)) +import PreIds(tmpTyVarIds) +import Error(internalError, EMsg, ErrorHandle, bsWarning, bsError) import Flags(Flags) import CSyntax import Type @@ -367,13 +367,6 @@ ctxRedCQType = ctxRedCQType' False ctxRedCQType' :: Bool -> CQType -> TI (Subst, CQType) ctxRedCQType' isInstHead cqt = do - -- raise an experimental warning about uses of generics - let CQType cqs _ = cqt - case [p | p@(CPred {cpred_tc = CTypeclass i}) <- cqs, - qualEq i idGeneric] of - p : _ -> twarn (getPosition p, WExperimental "generics") - [] -> return () - -- find out what variables were bound prior to here prev_bound_tvs <- getBoundTVs diff --git a/testsuite/bsc.typechecker/generics/GenericNegativeTests.bs.bsc-out.expected b/testsuite/bsc.typechecker/generics/GenericNegativeTests.bs.bsc-out.expected index 927146084..396373eda 100644 --- a/testsuite/bsc.typechecker/generics/GenericNegativeTests.bs.bsc-out.expected +++ b/testsuite/bsc.typechecker/generics/GenericNegativeTests.bs.bsc-out.expected @@ -1,9 +1,5 @@ checking package dependencies compiling GenericNegativeTests.bs -Warning: "GenericNegativeTests.bs", line 16, column 12: (S0028) - Support for generics in this release is not complete or has not been tested -Warning: "GenericNegativeTests.bs", line 36, column 10: (S0028) - Support for generics in this release is not complete or has not been tested Error: "GenericNegativeTests.bs", line 26, column 10: (T0020) Type error at: refl From 83b71de5c7a71c2af17bb9768566dea2fa4c46ee Mon Sep 17 00:00:00 2001 From: Lucas Kramer Date: Wed, 14 Feb 2024 21:51:12 -0600 Subject: [PATCH 6/6] Update example of how data constructors are translated --- doc/BH_ref_guide/BH_lang.tex | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/doc/BH_ref_guide/BH_lang.tex b/doc/BH_ref_guide/BH_lang.tex index 48576d8b8..dc095cc40 100644 --- a/doc/BH_ref_guide/BH_lang.tex +++ b/doc/BH_ref_guide/BH_lang.tex @@ -1017,25 +1017,22 @@ \subsection{\te{data}} Error messages involving data type definitions sometimes show traces of how they are handled internally. Data type definitions are translated into a data type where each constructor has exactly one -argument. Each argument is a struct type. The types above translate +argument. The types above translate to: \begin{verbatim} data Bool = False PrimUnit | True PrimUnit - data Operand = Register Operand.Register - | Operand.Literal - | Operand.Indexed - struct Operand°Register = { _1 :: Bit 5 } - struct Operand°Literal = { _1 :: Bit 22 } - struct Operand°Indexed = { _1 :: Reg 5; _2 :: Reg 5 } + data Operand = Register (Bit 5) + | Literal (Bit 22) + | Indexed Operand_$Indexed + struct Operand_$Indexed = { _1 :: Reg 5; _2 :: Reg 5 } - data Maybe a = Nothing PrimUnit | Maybe.Just a - struct Maybe.Just a = { _1 :: a } + data Maybe a = Nothing PrimUnit | Just a - data Instruction = Immediate Instruction°Immediate | - Register Instruction°Register - struct Instruction°Immediate = { op::Op; rs::Reg; rt::CPUReg; imm::UInt16; } - struct Instruction°Register = { op::Op; target::UInt26; } + data Instruction = Immediate Instruction_$Immediate + | Register Instruction_$Register + struct Instruction_$Immediate = { op::Op; rs::Reg; rt::CPUReg; imm::UInt16; } + struct Instruction_$Register = { op::Op; target::UInt26; } \end{verbatim} \end{NOTE}