
Modules
-------

  $(root)/A/Foo.agda:

  module Foo (A:Set)(op:A -> A -> A) where

    f : A -> A
    f = ..

    module Bar (x:A) where
      ...

    import .Baz	  -- looks for $(root)/A/Baz.agda
    import B.Baz  -- looks for $(include_dirs)/B/Baz.agda

  Observations:
    - You can only import actual files.
    - The name of the top level module in a file as to match the file name.

  Local ::= ... | open m es [ as x | (xs) | ε ]

  D ::= ... | import x.x.x.x [ as x | ε ]

  open Foo Nat eq as FooNat (f, g)  -- import f and g into the new name
				    -- space FooNat.
  open FooNat (f)		    -- import f into the current name space
  open FooNat			    -- import everything from FooNat into
				    -- the current name space

  At the moment there is a distinction between modules and name spaces.
  Above

    Foo Nat eq	  is a module
    FooNat	  is a name space

  You can refer to things using name spaces, as in FooNat.f. You cannot do
  this with modules. A name space is a sequence of names separated by dot.
  Not allowed:

    (Foo Nat eq).f

  You can open both name spaces and modules. For each non-parameterised
  module there is a name space with the same name.

  What does abstract and private mean?

    abstract takes a list of definitions:

      abstract Stack : Set
	       Stack = List

	       empty : Stack
	       empty = []

	       ...
    
    Outside the abstract block the definitions are not known (even inside
    the same module).

    private just means that the user cannot refer to the name outside the
    module. You can still compute with private things.

  How to translate to core?

    We can just forget about private and abstract. For abstract this means
    that the core type checker has more information than the full language
    checker. This shouldn't be a problem.

    Note: make sure that the type of something in an abstract block doesn't
    depend on the value of one of the earlier definitions (the type is
    exported).

Typing rules
------------

       Γ ⊢ M : Set_i
    -------------------
    Γ ⊢ El_i M : type^i

    Also for prop.

  Algorithm

    Judgement forms:

      Γ ⊢ A s --> V	  check that A is a type and infer the sort
      Γ ⊢ e ↑ V --> v	  check that e has type V
      Γ ⊢ e ↓ V --> v	  infer the type of e

    Rules:

      Γ ⊢ M ↓ V --> v    v = Sort ?s
      ------------------------------
	   Γ ⊢ M ?s --> El_?s v

      Γ ⊢ f ↓ V -> v   V = (x : ?A) -> ?B   Γ ⊢ e ↑ ?A --> w
      ------------------------------------------------------
		      Γ ⊢ f e ↓ ?B w --> v w

  We need sort meta variables: Γ ⊢ ? ? --> ?

    data Type = ... | Sort Sort
    data Sort = Type Nat | Prop | Meta MId | Lub Sort Sort

  So this means that we don't need the Maybe in the metainfo

    data MetaInfo = InstantiatedV Value
		  | InstantiatedT Type
		  | Underscore [ConstraintId]
		  | QuestionmarkV Signature Context Type [ConstraintId]
		  | QuestionmarkT Signature Context Sort [ConstraintId]

  Important observation:

    We don't have subtyping, only subsorting.

    Γ ⊢ e ↓ W --> v   W = V
    -----------------------
       Γ ⊢ e ↑ V --> v

Plan
----

  Things to do/figure out

    - Typing rules for the full language
    - Translation to Core
    - Explanations
    - User interactions
    - Testing
    - Plug-ins
    - Documentation
    - ( Classes )

    This will be done mainly at Chalmers

  Things we know how to do

    C - concrete and abstract syntax, translation
    C - parser, lexer
    C - pretty printing
    C - infrastructure (Makefile, directories)
    J - internal syntax
    J - unification and constraints
    J - monad and state (partially)

  C = Chalmers (Ulf)
  J = Japan (Jeff)

  Time plan

    Sep
	  Fix signature datatype.
	  Final version of typing rules.
	  Finish(ing) infrastructure code ("Things we know how to do").
    Oct
	  Start implementing type checker.

	  Finish(ing) first version.
    Nov
	  Have a running system.

File organisation
-----------------

  src
    Syntax
      Lexer
      Parser
      ParseMonad
      Position

      Concrete
      Abstract
      Internal

      Pretty
      ConcreteToAbstract
    TypeChecker
      Monad
      Unification
      (MetaVariables, Computation, .. ?)
    Testing
      ... fine grained testing
    Interaction
      ... interaction protocol, ...
    Plugins
      ...

The Haddock trick
-----------------

  Haddock doesn't handle circular module dependencies.
  Solution: Use a preprocessor before calling Haddock which removes lines
	    containing REMOVE_IF_HADDOCK.
  Example:

  import {-# SOURCE #-} Foo (foo) -- REMOVE_IF_HADDOCK

  {- REMOVE_IF_HADDOCK
  -- | This function is really 'Foo.foo'. It's here to fool Haddock into
  --   accept circular module dependencies.
  foo :: Int -> Int
     REMOVE_IF_HADDOCK -}

Coding conventions
------------------

  - Write typesignatures and haddock comments.
  - Never use booleans.
  - Datatypes should be abstract and accessed by views.
  - Scrap boilerplate locally. That is, define useful combinators using
    generics, but export non-generic functions. Another way of saying it:
    only use generics in close proximity to the definition of the datatype.

The keeping-abstraction-when-splitting-a-module trick
-----------------------------------------------------

  You have:

  --- A.hs ---
  module A ( Foo -- abstract type
	   , foo
	   ) where
  data Foo = Foo Int
  foo :: Foo -> Int
  foo (Foo n) = n
  ------------

  You want to split this module into two (because it's too big), without
  breaking the abstraction of Foo.

  Solution: You split the module into three, with the added advantage that
	    you don't have to change modules importing A.

  --- A.hs ---
  module A ( Foo, foo ) where
  import A.Implementation
  import A.Foo
  ------------

  --- A/Implementation.hs ---
  module A.Implementation ( Foo(..) ) where -- exports definition of Foo
  data Foo = Foo Int
  ---------------------------

  --- A/Foo.hs ---
  module A.Foo (foo) where
  import A.Implementation
  foo :: Foo -> Int
  foo (Foo n) = n
  ----------------

vim: sts=2 sw=2 tw=75
