BSV by Example - Computation Structures Group
BSV by Example - Computation Structures Group
BSV by Example - Computation Structures Group
Create successful ePaper yourself
Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.
type-checking environment. Type checking, which occurs before program elaboration or execution,<br />
ensures that object types are compatible and that conversion functions are valid for the context.<br />
Data types in <strong>BSV</strong> are case sensitive. The first character of a type is always uppercase (there are<br />
only two exceptions: the types int and bit, compatibility with Verilog). The first character of a<br />
variable name is always lowercase. A common source of errors for beginners in <strong>BSV</strong> is to use an<br />
uppercase name where <strong>BSV</strong> expects a lower case, and vice versa.<br />
3.2 Uppercase and lowercase in type and value identifiers<br />
In <strong>BSV</strong>, the case of the first letter of an identifier is significant, whether used to describe types<br />
or values. The general principle is that an uppercase first letter introduces a constant, whereas a<br />
lowercase first letter introduces a variable.<br />
A constant type is a particular type, such as Bool, Int, UInt, Server, Action, Module, Rule, and<br />
so on. A type variable is used to represent a polymorphic type, similar to “generic” or “template”<br />
types in other languages (see Section 9 for more on polymorphism).<br />
A constant value is a particular symbolic value, such as True, False, the symbolic labels declared<br />
in all enum types, the constructors associated with any struct or tagged union type, and so on. A<br />
type variable is the familiar identifier bound to some particular value, such as x, foo, mkTb, mkDut,<br />
and so on.<br />
3.3 Typeclasses and overloading<br />
[This section can be skimmed lightly on first reading. Overloading is used in a fairly lightweight<br />
manner in subsequent sections, for which this section provides some intuition and context.]<br />
<strong>BSV</strong> makes very effective use of systematic, user-extensible overloading. For example, instead of<br />
having ad hoc definitions of how various data types are represented in bits, in <strong>BSV</strong> each such data<br />
type has a pair of overloaded functions called pack and unpack that convert from the abstract view<br />
of the type into bits and vice versa. Further, because overloading is user-extensible, the user can<br />
specify the definitions of these functions precisely, and thus specify representations precisely.<br />
In <strong>BSV</strong>, we say that there is a“typeclass”called Bits#(t,n ), which can be regarded as a set of types.<br />
Any type t in this typeclass has definitions for bit representation in n bits, i.e., it has definitions for<br />
the overloaded functions:<br />
function Bit#(n) pack (t x);<br />
function t unpack (Bit#(n) b);<br />
Each member type t in a typeclass is called an instance of the typeclass. The functions pack and<br />
unpack are called overloaded because the same function names are used for different types, and the<br />
compiler figures out the appropriate ones to use based on the actual types of their arguments and<br />
results.<br />
In most cases in the examples below, we will use a shortcut to define bit representations. Instead of<br />
a full-blown instance declaration, you will often see the phrase “deriving (Bits)” appended to a<br />
type definition, indicating to the compiler to pick the obvious, canonical bit representation. Thus,<br />
we only write a full-blown instance declaration for Bits if we need a non-standard representation.<br />
Thus, a typeclass is a construct which implements overloading across related data types. Overloading<br />
is the ability to use a common function name or operator on a collection of types, with the specific<br />
function or operator being selected <strong>by</strong> the compiler based on the types on which it is actually used<br />
(this process is called “overloading resolution”). A typeclass may include multiple data types; all<br />
data types within the typeclass share functions and operators, hence the function names within a<br />
typeclass are overloaded across the various typeclass members.<br />
24