Fix source indentation.
authorMatthijs Kooijman <matthijs@stdin.nl>
Wed, 11 Nov 2009 19:03:22 +0000 (20:03 +0100)
committerMatthijs Kooijman <matthijs@stdin.nl>
Wed, 11 Nov 2009 19:03:22 +0000 (20:03 +0100)
Chapters/Prototype.tex

index d5ae72f..fa0b54a 100644 (file)
     Each Core expression consists of one of these possible expressions.
 
     \startdesc{Variable reference}
-\startlambda
-a
-\stoplambda
+      \startlambda
+      a
+      \stoplambda
       This is a simple reference to a binder. It's written down as the
       name of the binder that is being referred to, which should of course be
       bound in a containing scope (including top level scope, so a reference
@@ -281,19 +281,21 @@ a
       cast expressions. This minimize the amount of bookkeeping needed to keep
       the typing consistent.
     \stopdesc
+
     \startdesc{Literal}
-\startlambda
-10
-\stoplambda
+      \startlambda
+      10
+      \stoplambda
       This is a simple literal. Only primitive types are supported, like
       chars, strings, ints and doubles. The types of these literals are the
       \quote{primitive} versions, like \lam{Char\#} and \lam{Word\#}, not the
       normal Haskell versions (but there are builtin conversion functions).
     \stopdesc
+
     \startdesc{Application}
-\startlambda
-func arg
-\stoplambda
+      \startlambda
+      func arg
+      \stoplambda
       This is simple function application. Each application consists of two
       parts: The function part and the argument part. Applications are used
       for normal function \quote{calls}, but also for applying type
@@ -302,10 +304,11 @@ func arg
       The value of an application is the value of the function part, with the
       first argument binder bound to the argument part.
     \stopdesc
+
     \startdesc{Lambda abstraction}
-\startlambda
-λbndr.body
-\stoplambda
+      \startlambda
+      λbndr.body
+      \stoplambda
       This is the basic lambda abstraction, as it occurs in labmda calculus.
       It consists of a binder part and a body part.  A lambda abstraction
       creates a function, that can be applied to an argument. 
@@ -318,10 +321,11 @@ func arg
       The value of an application is the value of the body part, with the
       binder bound to the value the entire lambda abstraction is applied to.
     \stopdesc
+
     \startdesc{Non-recursive let expression}
-\startlambda
-let bndr = value in body
-\stoplambda
+      \startlambda
+      let bndr = value in body
+      \stoplambda
       A let expression allows you to bind a binder to some value, while
       evaluating to some other value (where that binder is in scope). This
       allows for sharing of subexpressions (you can use a binder twice) and
@@ -334,9 +338,9 @@ let bndr = value in body
       calculus, it is easily translated to a lambda abstraction. The let
       expression above would then become:
 
-\startlambda
-(λbndr.body) value
-\stoplambda
+      \startlambda
+      (λbndr.body) value
+      \stoplambda
 
       This notion might be useful for verifying certain properties on
       transformations, since a lot of verification work has been done on
@@ -345,16 +349,16 @@ let bndr = value in body
       The value of a let expression is the value of the body part, with the
       binder bound to the value. 
     \stopdesc
-    \startdesc{Recursive let expression}
-\startlambda
-letrec
-  bndr1 = value1
-  \vdots
-  bndrn = valuen
-in 
-  body
-\stoplambda
 
+    \startdesc{Recursive let expression}
+      \startlambda
+      letrec
+        bndr1 = value1
+        \vdots
+        bndrn = valuen
+      in 
+        body
+      \stoplambda
       This is the recursive version of the let expression. In \small{GHC}'s
       Core implementation, non-recursive and recursive lets are not so
       distinct as we present them here, but this provides a clearer overview.
@@ -367,134 +371,138 @@ in
       lambda calculus, if we use the \emph{least fixed-point operator},
       \lam{Y}.
     \stopdesc
+
     \startdesc{Case expression}
-\startlambda
-  case scrut of bndr
-    DEFAULT -> defaultbody
-    C0 bndr0,0 ... bndr0,m -> body0
-    \vdots
-    Cn bndrn,0 ... bndrn,m -> bodyn
-\stoplambda
-
-TODO: Define WHNF
-
-    A case expression is the only way in Core to choose between values. A case
-    expression evaluates its scrutinee, which should have an algebraic
-    datatype, into weak head normal form (\small{WHNF}) and (optionally) binds
-    it to \lam{bndr}. It then chooses a body depending on the constructor of
-    its scrutinee. If none of the constructors match, the \lam{DEFAULT}
-    alternative is chosen. 
-    
-    Since we can only match the top level constructor, there can be no overlap
-    in the alternatives and thus order of alternatives is not relevant (though
-    the \lam{DEFAULT} alternative must appear first for implementation
-    efficiency).
-    
-    Any arguments to the constructor in the scrutinee are bound to each of the
-    binders after the constructor and are in scope only in the corresponding
-    body.
-
-    To support strictness, the scrutinee is always evaluated into WHNF, even
-    when there is only a \lam{DEFAULT} alternative. This allows a strict
-    function argument to be written like:
-
-\startlambda
-function (case argument of arg
-  DEFAULT -> arg)
-\stoplambda
-
-    This seems to be the only use for the extra binder to which the scrutinee
-    is bound. When not using strictness annotations (which is rather pointless
-    in hardware descriptions), \small{GHC} seems to never generate any code
-    making use of this binder. The current prototype does not handle it
-    either, which probably means that code using it would break.
-
-    Note that these case statements are less powerful than the full Haskell
-    case statements. In particular, they do not support complex patterns like
-    in Haskell. Only the constructor of an expression can be matched, complex
-    patterns are implemented using multiple nested case expressions.
-
-    Case statements are also used for unpacking of algebraic datatypes, even
-    when there is only a single constructor. For examples, to add the elements
-    of a tuple, the following Core is generated:
-
-\startlambda
-sum = λtuple.case tuple of
-  (,) a b -> a + b
-\stoplambda
-  
-    Here, there is only a single alternative (but no \lam{DEFAULT}
-    alternative, since the single alternative is already exhaustive). When
-    it's body is evaluated, the arguments to the tuple constructor \lam{(,)}
-    (\eg, the elements of the tuple) are bound to \lam{a} and \lam{b}.
-  \stopdesc
-  \startdesc{Cast expression}
-\startlambda
-body :: targettype
-\stoplambda
-    A cast expression allows you to change the type of an expression to an
-    equivalent type. Note that this is not meant to do any actual work, like
-    conversion of data from one format to another, or force a complete type
-    change. Instead, it is meant to change between different representations
-    of the same type, \eg switch between types that are provably equal (but
-    look different).
-    
-    In our hardware descriptions, we typically see casts to change between a
-    Haskell newtype and its contained type, since those are effectively
-    different representations of the same type.
-
-    More complex are types that are proven to be equal by the typechecker,
-    but look different at first glance. To ensure that, once the typechecker
-    has proven equality, this information sticks around, explicit casts are
-    added. In our notation we only write the target type, but in reality a
-    cast expressions carries around a \emph{coercion}, which can be seen as a
-    proof of equality. TODO: Example
-
-    The value of a cast is the value of its body, unchanged. The type of this
-    value is equal to the target type, not the type of its body.
-
-    Note that this syntax is also used sometimes to indicate that a particular
-    expression has a particular type, even when no cast expression is
-    involved. This is then purely informational, since the only elements that
-    are explicitely typed in the Core language are the binder references and
-    cast expressions, the types of all other elements are determined at
-    runtime.
-  \stopdesc
-  \startdesc{Note}
-
-    The Core language in \small{GHC} allows adding \emph{notes}, which serve
-    as hints to the inliner or add custom (string) annotations to a core
-    expression. These shouldn't be generated normally, so these are not
-    handled in any way in the prototype.
-  \stopdesc
-  \startdesc{Type}
-\startlambda
-@type
-\stoplambda
-    It is possibly to use a Core type as a Core expression. This is done to
-    allow for type abstractions and applications to be handled as normal
-    lambda abstractions and applications above. This means that a type
-    expression in Core can only ever occur in the argument position of an
-    application, and only if the type of the function that is applied to
-    expects a type as the first argument. This happens for all polymorphic
-    functions, for example, the \lam{fst} function:
-
-\startlambda
-fst :: \forall a. \forall b. (a, b) -> a
-fst = λtup.case tup of (,) a b -> a
-
-fstint :: (Int, Int) -> Int
-fstint = λa.λb.fst @Int @Int a b
-\stoplambda
+      \startlambda
+        case scrut of bndr
+          DEFAULT -> defaultbody
+          C0 bndr0,0 ... bndr0,m -> body0
+          \vdots
+          Cn bndrn,0 ... bndrn,m -> bodyn
+      \stoplambda
+
+      TODO: Define WHNF
+
+      A case expression is the only way in Core to choose between values. A case
+      expression evaluates its scrutinee, which should have an algebraic
+      datatype, into weak head normal form (\small{WHNF}) and (optionally) binds
+      it to \lam{bndr}. It then chooses a body depending on the constructor of
+      its scrutinee. If none of the constructors match, the \lam{DEFAULT}
+      alternative is chosen. 
+      
+      Since we can only match the top level constructor, there can be no overlap
+      in the alternatives and thus order of alternatives is not relevant (though
+      the \lam{DEFAULT} alternative must appear first for implementation
+      efficiency).
+      
+      Any arguments to the constructor in the scrutinee are bound to each of the
+      binders after the constructor and are in scope only in the corresponding
+      body.
+
+      To support strictness, the scrutinee is always evaluated into WHNF, even
+      when there is only a \lam{DEFAULT} alternative. This allows a strict
+      function argument to be written like:
+
+      \startlambda
+      function (case argument of arg
+        DEFAULT -> arg)
+      \stoplambda
+
+      This seems to be the only use for the extra binder to which the scrutinee
+      is bound. When not using strictness annotations (which is rather pointless
+      in hardware descriptions), \small{GHC} seems to never generate any code
+      making use of this binder. The current prototype does not handle it
+      either, which probably means that code using it would break.
+
+      Note that these case statements are less powerful than the full Haskell
+      case statements. In particular, they do not support complex patterns like
+      in Haskell. Only the constructor of an expression can be matched, complex
+      patterns are implemented using multiple nested case expressions.
+
+      Case statements are also used for unpacking of algebraic datatypes, even
+      when there is only a single constructor. For examples, to add the elements
+      of a tuple, the following Core is generated:
+
+      \startlambda
+      sum = λtuple.case tuple of
+        (,) a b -> a + b
+      \stoplambda
     
-    The type of \lam{fst} has two universally quantified type variables. When
-    \lam{fst} is applied in \lam{fstint}, it is first applied to two types.
-    (which are substitued for \lam{a} and \lam{b} in the type of \lam{fst}, so
-    the type of \lam{fst} actual type of arguments and result can be found:
-    \lam{fst @Int @Int :: (Int, Int) -> Int}).
-  \stopdesc
+      Here, there is only a single alternative (but no \lam{DEFAULT}
+      alternative, since the single alternative is already exhaustive). When
+      it's body is evaluated, the arguments to the tuple constructor \lam{(,)}
+      (\eg, the elements of the tuple) are bound to \lam{a} and \lam{b}.
+    \stopdesc
+
+    \startdesc{Cast expression}
+      \startlambda
+      body :: targettype
+      \stoplambda
+      A cast expression allows you to change the type of an expression to an
+      equivalent type. Note that this is not meant to do any actual work, like
+      conversion of data from one format to another, or force a complete type
+      change. Instead, it is meant to change between different representations
+      of the same type, \eg switch between types that are provably equal (but
+      look different).
+      
+      In our hardware descriptions, we typically see casts to change between a
+      Haskell newtype and its contained type, since those are effectively
+      different representations of the same type.
+
+      More complex are types that are proven to be equal by the typechecker,
+      but look different at first glance. To ensure that, once the typechecker
+      has proven equality, this information sticks around, explicit casts are
+      added. In our notation we only write the target type, but in reality a
+      cast expressions carries around a \emph{coercion}, which can be seen as a
+      proof of equality. TODO: Example
+
+      The value of a cast is the value of its body, unchanged. The type of this
+      value is equal to the target type, not the type of its body.
+
+      Note that this syntax is also used sometimes to indicate that a particular
+      expression has a particular type, even when no cast expression is
+      involved. This is then purely informational, since the only elements that
+      are explicitely typed in the Core language are the binder references and
+      cast expressions, the types of all other elements are determined at
+      runtime.
+    \stopdesc
+
+    \startdesc{Note}
+
+      The Core language in \small{GHC} allows adding \emph{notes}, which serve
+      as hints to the inliner or add custom (string) annotations to a core
+      expression. These shouldn't be generated normally, so these are not
+      handled in any way in the prototype.
+    \stopdesc
 
-  TODO: Core type system
+    \startdesc{Type}
+      \startlambda
+      @type
+      \stoplambda
+      It is possibly to use a Core type as a Core expression. This is done to
+      allow for type abstractions and applications to be handled as normal
+      lambda abstractions and applications above. This means that a type
+      expression in Core can only ever occur in the argument position of an
+      application, and only if the type of the function that is applied to
+      expects a type as the first argument. This happens for all polymorphic
+      functions, for example, the \lam{fst} function:
+
+      \startlambda
+      fst :: \forall a. \forall b. (a, b) -> a
+      fst = λtup.case tup of (,) a b -> a
+
+      fstint :: (Int, Int) -> Int
+      fstint = λa.λb.fst @Int @Int a b
+      \stoplambda
+          
+      The type of \lam{fst} has two universally quantified type variables. When
+      \lam{fst} is applied in \lam{fstint}, it is first applied to two types.
+      (which are substitued for \lam{a} and \lam{b} in the type of \lam{fst}, so
+      the type of \lam{fst} actual type of arguments and result can be found:
+      \lam{fst @Int @Int :: (Int, Int) -> Int}).
+    \stopdesc
+
+    TODO: Core type system
 
   \section[sec:prototype:statetype]{State annotations in Haskell}
       Ideal: Type synonyms, since there is no additional code overhead for
@@ -508,18 +516,20 @@ fstint = λa.λb.fst @Int @Int a b
       (un)packing substates. This will result in many nested State constructors
       in a nested state type. \eg: 
 
-  \starttyping
-  State (State Bit, State (State Word, Bit), Word)
-  \stoptyping
+      \starttyping
+      State (State Bit, State (State Word, Bit), Word)
+      \stoptyping
 
       Alternative: Provide different newtypes for input and output state. This
       makes the code even more explicit, and typechecking can find even more
       errors. However, this requires defining two type synomyms for each
       stateful function instead of just one. \eg:
-  \starttyping
-  type AccumStateIn = StateIn Bit
-  type AccumStateOut = StateOut Bit
-  \stoptyping
+
+      \starttyping
+      type AccumStateIn = StateIn Bit
+      type AccumStateOut = StateOut Bit
+      \stoptyping
+
       This also increases the possibility of having different input and output
       states. Checking for identical input and output state types is also
       harder, since each element in the state must be unpacked and compared
@@ -528,9 +538,9 @@ fstint = λa.λb.fst @Int @Int a b
       Alternative: Provide a type for the entire result type of a stateful
       function, not just the state part. \eg:
 
-  \starttyping
-  newtype Result state result = Result (state, result)
-  \stoptyping
+      \starttyping
+      newtype Result state result = Result (state, result)
+      \stoptyping
       
       This makes it easy to say "Any stateful function must return a
       \type{Result} type, without having to sort out result from state. However,
@@ -684,19 +694,19 @@ fstint = λa.λb.fst @Int @Int a b
       look at the whole, we can conclude the following:
 
       \startitemize
-      \item A state unpack operation should not generate any \small{VHDL}. The binder
-      to which the unpacked state is bound should still be declared, this signal
-      will become the register and will hold the current state.
-      \item A state pack operation should not generate any \small{VHDL}. The binder th
-      which the packed state is bound should not be declared. The binder that is
-      packed is the signal that will hold the new state.
-      \item Any values of a State type should not be translated to \small{VHDL}. In
-      particular, State elements should be removed from tuples (and other
-      datatypes) and arguments with a state type should not generate ports.
-      \item To make the state actually work, a simple \small{VHDL} proc should be
-      generated. This proc updates the state at every clockcycle, by assigning
-      the new state to the current state. This will be recognized by synthesis
-      tools as a register specification.
+        \item A state unpack operation should not generate any \small{VHDL}. The binder
+        to which the unpacked state is bound should still be declared, this signal
+        will become the register and will hold the current state.
+        \item A state pack operation should not generate any \small{VHDL}. The binder th
+        which the packed state is bound should not be declared. The binder that is
+        packed is the signal that will hold the new state.
+        \item Any values of a State type should not be translated to \small{VHDL}. In
+        particular, State elements should be removed from tuples (and other
+        datatypes) and arguments with a state type should not generate ports.
+        \item To make the state actually work, a simple \small{VHDL} proc should be
+        generated. This proc updates the state at every clockcycle, by assigning
+        the new state to the current state. This will be recognized by synthesis
+        tools as a register specification.
       \stopitemize