===
Generic Type Declaration
===

type
  generic a<b> = x;
  generic a<b: constraint> = x;
  generic a<b,c> = x;
  generic a<b,c: constraint> = x;
  generic a<b; c: constraint> = x;
  generic a<b, c: constraint; d,e: constraint> = x;

---

(root
  (declTypes (kType)
    (declType (kGeneric)
      (genericTpl 
        (identifier)
        (kLt)
        (genericArgs
          (genericArg
            (identifier)))
        (kGt))
      (kEq)
      (type (typeref (identifier))))
    (declType (kGeneric)
      (genericTpl
        (identifier)
        (kLt)
        (genericArgs
          (genericArg
            (identifier) (typeref (identifier))))
        (kGt))
      (kEq)
      (type (typeref (identifier))))
    (declType (kGeneric)
      (genericTpl
        (identifier)
        (kLt)
        (genericArgs
          (genericArg (identifier) (identifier)))
        (kGt))
      (kEq)
      (type (typeref (identifier))))
    (declType (kGeneric)
      (genericTpl
        (identifier)
        (kLt)
        (genericArgs
          (genericArg (identifier) (identifier) (typeref (identifier))))
        (kGt))
      (kEq)
      (type (typeref (identifier))))
    (declType (kGeneric)
      (genericTpl
        (identifier)
        (kLt)
        (genericArgs
          (genericArg (identifier))
          (genericArg (identifier) (typeref (identifier))))
        (kGt))
      (kEq)
      (type (typeref (identifier))))
    (declType (kGeneric)
      (genericTpl
        (identifier)
        (kLt)
        (genericArgs
          (genericArg (identifier) (identifier) (typeref (identifier)))
          (genericArg (identifier) (identifier) (typeref (identifier))))
        (kGt))
      (kEq)
      (type (typeref (identifier))))))

===
Generic Specialization
===

type
  a = specialize b<c>;
  a = specialize b<c,d>;
  a = specialize b<c, d<e, f> >;

var
  a: specialize b<c>;
  a: specialize b<c,d>;
  a: specialize b<c, d<e, f> >;

---

(root
  (declTypes (kType)
    (declType (identifier) (kEq)
      (type
        (typeref (kSpecialize)
          (typerefTpl
            (identifier)
            (kLt)
            (typerefArgs
              (identifier))
            (kGt)))))
    (declType (identifier) (kEq)
      (type
        (typeref (kSpecialize)
          (typerefTpl
            (identifier)
            (kLt)
            (typerefArgs
              (identifier)
              (identifier))
            (kGt)))))
    (declType (identifier) (kEq)
      (type
        (typeref (kSpecialize)
          (typerefTpl
            (identifier)
            (kLt)
            (typerefArgs
              (identifier)
              (typerefTpl
                (identifier)
                (kLt)
                (typerefArgs
                  (identifier)
                  (identifier))
                (kGt)))
            (kGt))))))
  (declVars (kVar)
    (declVar
      (identifier)
      (type
        (typeref (kSpecialize)
          (typerefTpl
            (identifier)
            (kLt)
            (typerefArgs
              (identifier))
            (kGt)))))
    (declVar
      (identifier)
      (type
        (typeref (kSpecialize)
          (typerefTpl
            (identifier)
            (kLt)
            (typerefArgs
              (identifier)
              (identifier))
            (kGt)))))
    (declVar
      (identifier)
      (type
        (typeref (kSpecialize)
          (typerefTpl
            (identifier)
            (kLt)
            (typerefArgs
              (identifier)
              (typerefTpl
                (identifier)
                (kLt)
                (typerefArgs
                  (identifier)
                  (identifier))
                (kGt)))
            (kGt)))))))

===
Generic Routines
===

generic procedure a<b>(c: b); forward;

generic procedure a<b,c>.d<e>.Main<f>;
begin
end;

---

(root
  (declProc (kGeneric) (kProcedure)
    (genericTpl
      (identifier)
      (kLt)
      (genericArgs
        (genericArg 
          (identifier)))
      (kGt))
    (declArgs
      (declArg
        (identifier)
        (type (typeref (identifier)))))
    (kForward))
  (defProc
    (declProc (kGeneric) (kProcedure)
      (genericDot
        (genericDot
          (genericTpl
            (identifier)
            (kLt)
            (genericArgs
              (genericArg
                (identifier)
                (identifier)))
            (kGt))
          (kDot)
          (genericTpl
            (identifier)
            (kLt)
            (genericArgs
              (genericArg
                (identifier)))
            (kGt)))
        (kDot)
        (genericTpl
          (identifier)
          (kLt)
          (genericArgs
            (genericArg
              (identifier)))
          (kGt))))
    (block
      (kBegin)
      (kEnd))))

===
Generic Expressions
===

procedure a;
begin
  if specialize b<c>(d) < specialize e<f,g> then
    ;
end;

---

(root
  (defProc
    (declProc (kProcedure) (identifier))
    (block
      (kBegin)
      (if
        (kIf)
        (exprBinary
          (exprCall
            (exprTpl (kSpecialize)
              (identifier)
              (kLt)
              (identifier)
              (kGt))
            (exprArgs
              (identifier)))
          (kLt)
          (exprTpl (kSpecialize)
            (identifier)
            (kLt)
            (identifier)
            (identifier)
            (kGt)))
        (kThen))
      (kEnd))))

===
"specialize" as an identifier
===

procedure specialize;
begin
  specialize();
end;

---

(root
  (defProc
    (declProc (kProcedure) (identifier))
    (block
      (kBegin)
      (statement (exprCall (identifier)))
      (kEnd))))

