Added support for definfix and non-reserved operators. Fixed operator precedence bugs.

This commit is contained in:
waldemar%netscape.com 2003-02-18 00:28:37 +00:00
Родитель 5c36db5bd1
Коммит bce5683f9b
2 изменённых файлов: 137 добавлений и 50 удалений

Просмотреть файл

@ -1202,6 +1202,8 @@
;;; identifier is a type constructor like '->, 'vector, 'range-set, 'tag, or 'union
;;; :deftype type if this identifier is a type; nil if this identifier is a forward-referenced type
;;;
;;; :non-reserved true if this symbol is usable as an identifier despite being a :special-form, :condition, :primitive, or :type-constructor
;;;
;;; <value> value of this identifier if it is a variable of type other than ->
;;; <function> value of this identifier if it is a variable of type ->
;;; :value-expr unparsed expression defining the value of this identifier if it is a variable
@ -1321,7 +1323,12 @@
(fields nil :type list :read-only t) ;List of fields after eval-tags-types or (field-name field-type-expression [:const|:var|:opt-const|:opt-var]) before eval-tags-types
(=-name nil :type symbol) ;Lazily computed name of a function that compares two values of this tag for equality; nil if not known yet
(link nil :type (or null keyword) :read-only t) ;:reference if this is a local tag, :external if it's a predefined tag, or nil for no cross-references to this tag
(base nil :type integer :read-only t)) ;Position of first field in the list; -1 if it's special
(base nil :type integer :read-only t) ;Position of first field in the list; -1 if it's special
(appearance nil)) ;One of the following:
; ; nil to display the constructor normally
; ; (:suffix . markup) to display the constructor as a suffix (the constructor must be unary)
; ; (:infix . markup) to display the constructor as an infix (the constructor must be binary)
; Return four values:
; the one-based position of the tag's field corresponding to the given label or nil if the label is not present;
@ -2660,7 +2667,8 @@
(unless (identifier? name)
(error "~S should be an identifier" name))
(let ((symbol (world-intern world name)))
(when (get-properties (symbol-plist symbol) '(:special-form :condition :primitive :type-constructor))
(when (and (get-properties (symbol-plist symbol) '(:special-form :condition :primitive :type-constructor))
(not (get symbol :non-reserved)))
(error "~A is reserved" symbol))
symbol))
@ -5458,6 +5466,21 @@
(export-symbol symbol)))
; (definfix <type> <markup> <param1> <param2>)
; <type> must be a tuple or record tag. Define the syntax for depicting its constructor to be the infix operator
; depicted by <markup>. <param1> and <param2> are used as parameter names for depicting the definfix definition itself.
(defun scan-definfix (world grammar-info-var type-name markup param1 param2)
(declare (ignore grammar-info-var param1 param2))
(let* ((symbol (scan-name world type-name))
(type (get-type symbol nil)))
(unless (eq (type-kind type) :tag)
(error "~A should be a tag type" (print-type-to-string type)))
(let ((tag (type-tag type)))
(when (tag-appearance tag)
(error "Duplicate appearance on tag ~S" tag))
(setf (tag-appearance tag) (cons :infix markup)))))
; (set-grammar <name>)
; Set the current grammar to the grammar or lexer with the given name.
(defun scan-set-grammar (world grammar-info-var name)
@ -5561,6 +5584,7 @@
(defun scan-define depict-defun) ;Occurs from desugaring a function define
(defprimitive scan-defprimitive depict-defprimitive)
(defvar scan-defvar depict-defvar)
(definfix scan-definfix depict-definfix)
(set-grammar scan-set-grammar depict-set-grammar)
(clear-grammar scan-clear-grammar depict-clear-grammar)
(declare-action scan-declare-action depict-declare-action)
@ -5683,19 +5707,22 @@
(writable-cell scan-writable-cell depict-writable-cell))))
(defparameter *default-non-reserved* '(length))
(defparameter *default-primitives*
'((neg (-> (integer) integer) #'- :unary :minus nil %prefix% %prefix%)
(abs (-> (integer) integer) #'abs :unary "|" "|" %primary% %expr%)
(* (-> (integer integer) integer) #'* :infix :cartesian-product-10 nil %factor% %factor% %factor%)
(mod (-> (integer integer) integer) #'mod :infix ((:semantic-keyword "mod")) t %factor% %factor% %unary%)
(mod (-> (integer integer) integer) #'mod :infix ((:semantic-keyword "mod")) t %factor% %factor% %prefix%)
(+ (-> (integer integer) integer) #'+ :infix "+" t %term% %term% %term%)
(- (-> (integer integer) integer) #'- :infix :minus t %term% %term% %factor%)
;(rational-compare (-> (rational rational) order) #'rational-compare)
(rat-neg (-> (rational) rational) #'- :unary "-" nil %suffix% %suffix%)
(rat-neg (-> (rational) rational) #'- :unary :minus nil %prefix% %prefix%)
(rat-abs (-> (rational) rational) #'abs :unary "|" "|" %primary% %expr%)
(rat* (-> (rational rational) rational) #'* :infix :cartesian-product-10 nil %factor% %factor% %factor%)
(rat/ (-> (rational rational) rational) #'/ :infix "/" nil %factor% %factor% %unary%)
(rat/ (-> (rational rational) rational) #'/ :infix "/" nil %factor% %factor% %prefix%)
(rat+ (-> (rational rational) rational) #'+ :infix "+" t %term% %term% %term%)
(rat- (-> (rational rational) rational) #'- :infix :minus t %term% %term% %factor%)
(floor (-> (rational) integer) #'floor :unary :left-floor-10 :right-floor-10 %primary% %expr%)
@ -5746,13 +5773,12 @@
;;; Partial order of primitives for deciding when to depict parentheses.
(defparameter *primitive-level* (make-partial-order))
(def-partial-order-element *primitive-level* %primary%) ;id, constant, (e), tag<...>, |e|, action
(def-partial-order-element *primitive-level* %suffix% %primary%) ;f(...), a[i], a[i...j], a[i<-v], a.l
(def-partial-order-element *primitive-level* %prefix% %primary%) ;-e, new tag<...>, a^b
(def-partial-order-element *primitive-level* %primary%) ;id, constant, (e), tag<...>, |e|
(def-partial-order-element *primitive-level* %suffix% %primary%) ;f(...), a[i], a[i...j], a[i<-v], a.l, action
(def-partial-order-element *primitive-level* %prefix% %suffix%) ;-e, new tag<...>, a^b
(def-partial-order-element *primitive-level* %min-max% %prefix%) ;min, max
(def-partial-order-element *primitive-level* %unary% %suffix% %prefix%) ;
(def-partial-order-element *primitive-level* %not% %unary%) ;not
(def-partial-order-element *primitive-level* %factor% %unary%) ;/, *, intersection
(def-partial-order-element *primitive-level* %not% %prefix%) ;not
(def-partial-order-element *primitive-level* %factor% %prefix%) ;/, *, intersection, tuple-infix
(def-partial-order-element *primitive-level* %term% %factor%) ;+, -, append, union, set difference
(def-partial-order-element *primitive-level* %relational% %term% %min-max% %not%) ;<, <=, >, >=, =, /=, is, member, ...
(def-partial-order-element *primitive-level* %logical% %relational%) ;and, or, xor
@ -5803,6 +5829,11 @@
property
(world-intern world (first special-spec))
(rest special-spec)))))
(dolist (non-reserved *default-non-reserved*)
(let ((symbol (world-intern world non-reserved)))
(assert (get-properties (symbol-plist symbol) '(:special-form :condition :primitive :type-constructor)))
(setf (get symbol :non-reserved) t)
(export-symbol symbol)))
(dolist (primitive-spec *default-primitives*)
(let ((name (world-intern world (first primitive-spec))))
(apply #'declare-primitive
@ -5869,6 +5900,8 @@
(add-type-name world finite-float64-type (world-intern world 'finite-float64) nil)
(let ((long-type (scan-deftuple-or-defrecord world nil 'long '((value (integer-range (neg (expt 2 63)) (- (expt 2 63) 1)))) nil))
(u-long-type (scan-deftuple-or-defrecord world nil 'u-long '((value (integer-range 0 (- (expt 2 64) 1)))) nil)))
(setf (tag-appearance (type-tag long-type)) '(:suffix (:subscript (:tag-name "long"))))
(setf (tag-appearance (type-tag u-long-type)) '(:suffix (:subscript (:tag-name "ulong"))))
(add-type-name world (make-union-type world float32-type float64-type long-type u-long-type) (world-intern world 'general-number) nil)
(add-type-name world (make-union-type world finite-float32-type finite-float64-type long-type u-long-type)
(world-intern world 'finite-general-number) nil))))

Просмотреть файл

@ -187,13 +187,13 @@
(:-zero32 "MinusZero32" (:minus "zero" (:subscript "f32")))
(:+infinity32 "PlusInfinity32" ("+" :infinity (:subscript "f32")))
(:-infinity32 "MinusInfinity32" (:minus :infinity (:subscript "f32")))
(:nan32 "NaN" ("NaN32" (:subscript "f32")))
(:nan32 "NaN" ("NaN" (:subscript "f32")))
(:+zero64 "PlusZero64" ("+zero" (:subscript "f64")))
(:-zero64 "MinusZero64" (:minus "zero" (:subscript "f64")))
(:+infinity64 "PlusInfinity64" ("+" :infinity (:subscript "f64")))
(:-infinity64 "MinusInfinity64" (:minus :infinity (:subscript "f64")))
(:nan64 "NaN" ("NaN64" (:subscript "f64")))
(:nan64 "NaN" ("NaN" (:subscript "f64")))
(:+infinity "PlusInfinity" ("+" :infinity))
(:-infinity "MinusInfinity" (:minus :infinity))))
@ -531,14 +531,15 @@
; Emit markup for the reference to the action on the given general grammar symbol.
(defun depict-action-reference (markup-stream action-name general-grammar-symbol &optional index)
(let ((action-default (default-action? action-name)))
(unless action-default
(depict-action-name markup-stream action-name)
(depict markup-stream :action-begin))
(depict-general-grammar-symbol markup-stream general-grammar-symbol :reference index)
(unless action-default
(depict markup-stream :action-end))))
(defun depict-action-reference (markup-stream level action-name general-grammar-symbol &optional index)
(cond
((default-action? action-name)
(depict-general-grammar-symbol markup-stream general-grammar-symbol :reference index))
(t (depict-expr-parentheses (markup-stream level %suffix%)
(depict-action-name markup-stream action-name)
(depict markup-stream :action-begin)
(depict-general-grammar-symbol markup-stream general-grammar-symbol :reference index)
(depict markup-stream :action-end)))))
; Emit markup for the given annotated value expression. level indicates the binding level imposed
@ -553,7 +554,7 @@
(expr-annotation:local (depict-local-variable markup-stream (first args)))
(expr-annotation:global (depict-global-variable markup-stream (first args) :reference))
(expr-annotation:call (apply #'depict-call markup-stream world level args))
(expr-annotation:action (apply #'depict-action-reference markup-stream args))
(expr-annotation:action (apply #'depict-action-reference markup-stream level args))
(expr-annotation:special-form
(apply (get (first args) :depict-special-form) markup-stream world level (rest args))))))
@ -947,39 +948,55 @@
; A <field-expr> may be :uninit to indicate an uninitialized field, which must have kind :opt-const or :opt-var.
(defun depict-new (markup-stream world level type type-name &rest annotated-exprs)
(let* ((tag (type-tag type))
(mutable (tag-mutable tag)))
(appearance (tag-appearance tag))
(mutable (tag-mutable tag))
(fields (tag-fields tag))
(n-fields (length fields)))
(flet
((depict-tag-and-args (markup-stream)
(let ((fields (tag-fields tag)))
(assert-true (= (length fields) (length annotated-exprs)))
(depict-type-name markup-stream type-name (if (symbol-type-user-defined (world-intern world type-name)) :reference :external))
(if (tag-keyword tag)
(assert-true (null annotated-exprs))
(let ((fields-and-parameters (mapcan #'(lambda (field parameter)
(and (not (eq parameter :uninit))
(list (cons field parameter))))
fields annotated-exprs)))
(depict-list markup-stream
#'(lambda (markup-stream field-and-parameter)
(depict-logical-block (markup-stream 4)
(depict-label-name markup-stream world type (field-label (car field-and-parameter)) nil)
(depict markup-stream ":")
(depict-break markup-stream 1)
(depict-expression markup-stream world (cdr field-and-parameter) %expr%)))
fields-and-parameters
:indent 4
:prefix (if mutable :record-begin :tuple-begin)
:suffix (if mutable :record-end :tuple-end)
:separator ","
:break 1
:empty nil))))))
(depict-type-name markup-stream type-name (if (symbol-type-user-defined (world-intern world type-name)) :reference :external))
(if (tag-keyword tag)
(assert-true (null annotated-exprs))
(let ((fields-and-parameters (mapcan #'(lambda (field parameter)
(and (not (eq parameter :uninit))
(list (cons field parameter))))
fields annotated-exprs)))
(depict-list markup-stream
#'(lambda (markup-stream field-and-parameter)
(depict-logical-block (markup-stream 4)
(depict-label-name markup-stream world type (field-label (car field-and-parameter)) nil)
(depict markup-stream ":")
(depict-break markup-stream 1)
(depict-expression markup-stream world (cdr field-and-parameter) %expr%)))
fields-and-parameters
:indent 4
:prefix (if mutable :record-begin :tuple-begin)
:suffix (if mutable :record-end :tuple-end)
:separator ","
:break 1
:empty nil)))))
(if mutable
(assert-true (= n-fields (length annotated-exprs)))
(cond
(appearance
(ecase (first appearance)
(:suffix
(assert-true (= n-fields 1))
(depict-expr-parentheses (markup-stream level %suffix%)
(depict-expression markup-stream world (first annotated-exprs) %primary%)
(depict-item-or-group-list markup-stream (rest appearance))))
(:infix
(assert-true (= n-fields 2))
(depict-expr-parentheses (markup-stream level %factor%)
(depict-expression markup-stream world (first annotated-exprs) %primary%)
(depict-item-or-group-list markup-stream (rest appearance))
(depict-expression markup-stream world (second annotated-exprs) %primary%)))))
(mutable
(depict-expr-parentheses (markup-stream level %prefix%)
(depict-logical-block (markup-stream 4)
(depict-semantic-keyword markup-stream 'new :after)
(depict-tag-and-args markup-stream)))
(depict-tag-and-args markup-stream)))))
(depict-tag-and-args markup-stream))))
(t (depict-tag-and-args markup-stream))))))
; (& <label> <record-expr>)
@ -1210,7 +1227,7 @@
; (&const= <label> <record-expr> <value-expr>)
(defun depict-&= (markup-stream world semicolon last-paragraph-style record-type label record-annotated-expr value-annotated-expr)
(depict-paragraph (markup-stream last-paragraph-style)
(depict-& markup-stream world %unary% record-type label record-annotated-expr)
(depict-& markup-stream world %prefix% record-type label record-annotated-expr)
(depict markup-stream " " :assign-10)
(depict-logical-block (markup-stream 6)
(depict-break markup-stream 1)
@ -1707,6 +1724,43 @@
(depict-equals-and-value markup-stream world value-annotated-expr :assign-10)))))))
; (definfix <type> <markup> <param1> <param2>)
(defun depict-definfix (markup-stream world depict-env type-name markup param1 param2)
(let* ((symbol (scan-name world type-name))
(type (get-type symbol nil))
(tag (type-tag type))
(mutable (tag-mutable tag))
(fields (tag-fields tag)))
(unless (= (length (tag-fields tag)) 2)
(error "definfix ~S is used on a tag with other than two fields" symbol))
(depict-semantics (markup-stream depict-env)
(depict-text-environment world depict-env
(depict-logical-block (markup-stream 0)
(depict markup-stream "The notation")
(depict-break markup-stream 1)
(depict-local-variable markup-stream param1)
(depict-item-or-group-list markup-stream markup)
(depict-local-variable markup-stream param2)
(depict-break markup-stream 1)
(depict markup-stream "is a shorthand for")
(depict-break markup-stream 1)
(when mutable
(depict-semantic-keyword markup-stream 'new :after))
(depict-type-name markup-stream type-name (if (symbol-type-user-defined symbol) :reference :external))
(depict markup-stream (if mutable :record-begin :tuple-begin))
(depict-label-name markup-stream world type (field-label (first fields)) nil)
(depict markup-stream ":")
(depict-break markup-stream 1)
(depict-local-variable markup-stream param1)
(depict markup-stream ",")
(depict-break markup-stream 1)
(depict-label-name markup-stream world type (field-label (second fields)) nil)
(depict markup-stream ":")
(depict-break markup-stream 1)
(depict-local-variable markup-stream param2)
(depict markup-stream (if mutable :record-end :tuple-end) "."))))))
; (defun <name> (-> (<type1> ... <typen>) <result-type>) (lambda ((<arg1> <type1>) ... (<argn> <typen>)) <result-type> . <statements>))
(defun depict-defun (markup-stream world depict-env name type-expr value-expr)
(assert-true (eq (first type-expr) '->))