git.fiddlerwoaroof.com
parser/typedecl-parser.scm
4e987026
 ;;; File: parser/typedecl-parser     Author: John
 
 (define (parse-type-decl interface?)
  (save-parser-context
   (let* ((sig (parse-signature))
 	 (contexts (signature-context sig))
 	 (simple (signature-type sig))
 	 (deriving '())
 	 (constrs '()))
     ;; #t = builtins ([] (,,) ->) not allowed
     (check-simple simple '#t "type declaration")
     (let ((annotations (parse-constr-annotations)))
      (token-case
       (= (setf constrs (parse-constrs))
 	 (token-case
 	  (|deriving|
 	   (setf deriving
 	     (token-case
 		 (\( 
 		  (token-case
 		   (\) '())
 		   (else (parse-class-list))))
 		 (tycon (list (class->ast)))
 		 (else (signal-invalid-syntax "a deriving clause")))))))
       (else
        (when (not interface?)
 	 (signal-missing-constructors))))
     (make data-decl (context contexts) (simple simple)
 		    (constrs constrs) (deriving deriving)
 		    (annotations annotations))))))
 
 (define (signal-missing-constructors)
   (parser-error 'missing-constructors
 		"Data type definition requires constructors"))
 
 (define (check-simple simple fresh? where)
   (when (not (tycon? simple))
     (signal-not-simple where))
   (when (and fresh? (not (eq? (tycon-def simple) *undefined-def*)))
     (signal-not-simple where))
   (let ((tyvars (map (lambda (arg)
 		       (when (not (tyvar? arg))
 			     (signal-not-simple where))
 		       (tyvar-name arg))
 		     (tycon-args simple))))
     (when (not (null? (find-duplicates tyvars)))
       (signal-unique-tyvars-required))))
 
 (define (signal-unique-tyvars-required)
   (parser-error 'unique-tyvars-required
 		"Duplicate type variables appear in simple."))
 
 (define (signal-not-simple where)
   (parser-error 'not-simple "Simple type required in ~a." where))
 
 (define (parse-constrs)
   (let ((constr (parse-constr)))
     (token-case
      (\| (cons constr (parse-constrs)))
      (else (list constr)))))
 
 (define (parse-constr)
  (save-parser-context
   (let ((saved-excursion (save-scanner-state)))
     (token-case
      (consym/paren
       (parse-prefix-constr))
      (else
       (let ((type1 (parse-btype))
 	    (anns (parse-constr-annotations)))
 	(token-case
 	 (conop
 	  (parse-infix-constr (tuple type1 anns)))
 	 (else
 	  (restore-excursion saved-excursion)
 	  (parse-prefix-constr)))))))))
 
 (define (parse-prefix-constr)
   (token-case
    (con
     (let* ((con (con->ast))
 	   (types (parse-constr-type-list)))
       (make constr (constructor con) (types types))))
    (else
     (signal-missing-token "<con>" "constrs list"))))
 
 (define (parse-constr-type-list)
   (token-case
     (atype-start
      (let* ((atype (parse-atype))
 	    (anns (parse-constr-annotations)))
        (cons (tuple atype anns)
 	     (parse-constr-type-list))))
     (else '())))
 
 (define (parse-infix-constr t+a1)
   (let* ((con (conop->ast))
 	 (type2 (parse-btype))
 	 (anns (parse-constr-annotations)))
     (make constr (constructor con) (types (list t+a1 (tuple type2 anns))))))
 
 (define (parse-class-list)
   (token-case
    (tycon (let ((class (class->ast)))
 	     (token-case
 	      (\, (cons class (parse-class-list)))
 	      (\) (list class))
 	      (else (signal-missing-token "`)' or `,'" "deriving clause")))))
    (else (signal-missing-token "<tycon>" "deriving clause"))))
 
 (define (parse-constr-annotations)
   (token-case
    ((begin-annotation no-advance)
     (let ((annotations (parse-annotations)))
       (append annotations (parse-constr-annotations))))
    (else '())))
 
 (define (parse-synonym-decl)
  (save-parser-context
   (let* ((sig (parse-signature))
 	 (contexts (signature-context sig))
 	 (simple (signature-type sig)))
     (check-simple simple '#t "type synonym declaration")
     (when (not (null? contexts))
       (signal-no-context-in-synonym))
     (require-token = (signal-missing-token "`='" "type synonym declaration"))
     (let ((body (parse-type)))
       (make synonym-decl (simple simple) (body body))))))
 
 (define (signal-no-context-in-synonym)
   (parser-error 'no-context-in-synonym
 		"Context is not permitted in type synonym declaration."))
 
 (define (parse-class-decl)
  (save-parser-context
   (let ((supers (parse-optional-context)))
     (token-case
      (tycon
       (let ((class (class->ast)))
 	(token-case
 	 (tyvar
 	  (let* ((class-var (token->symbol))
 		 (decls (parse-where-decls)))
 	    (make class-decl (class class) (super-classes supers)
 		             (class-var class-var) (decls decls))))
 	 (else
 	  (signal-missing-token "<tyvar>" "class declaration")))))
      (else (signal-missing-token "<tycon>" "class declaration"))))))
 
 (define (parse-instance-decl interface?)
  (save-parser-context
   (let ((contexts (parse-optional-context))
 	(decls '()))
     (token-case
      (tycon
       (let* ((class (class->ast))
 	     (simple (parse-type)))
 	(when (not interface?)
 	   (setf decls (parse-where-decls)))
 	(check-simple simple '#f "instance declaration")
 	(make instance-decl (context contexts) (class class)
 	                    (simple simple) (decls decls))))
      (else (signal-missing-token "<tycon>" "instance declaration"))))))