Opened 6 years ago

Closed 6 years ago

#1319 closed defect (fixed)

Unexpected behaviour of dynamic extent variable

Reported by: Ernst Owned by:
Priority: normal Milestone:
Component: ANSI CL Compliance Version: trunk
Keywords: Cc:

Description

Using Clozure Common Lisp-Version 1.11-RC1-r16620 (DarwinX8664) to define functions within function groups, the functions defined must have unique names that can be traced back to the group in which they were defined. In the code snippet below the macro defop-environment sets up a name as a special variable that is used in defop, partly to get the intended name, partly to ensure defop was used within a defop-environment. The code below is as short as I could make it. It works in Clisp and ABCL but does not work in CCL (or SBCL for that matter).

(unless (find-package :wondering)
  (defpackage wondering
    (:use :cl)))

(in-package :wondering)

(defvar *environments*
  (make-hash-table :test 'eq))

(let ((defop-prefix "OP-FN%"))

  (defmacro defop-environment (name &rest defops)
    "(defop-environment <name> &rest <defops>)
 Define a new operator environment with name <name> and operators
 defined by <defops>."
    (let ((new-table (make-hash-table :test 'eq)))
      `(let ((*name-prefix* ,(concatenate 'string defop-prefix (string name) "%"))
	     (*operator-table* ,new-table))
	 (declare (special *environments* *operator-table* *name-prefix*))
	 (format *trace-output* "Before defop *name-prefix* ~S~%" *name-prefix*)
	 ,@defops
	 (setf (gethash ',name *environments*) *operator-table*)
	 ',name)))

  (defmacro defop (name lambda-list &body body)
    "Define an operator.  Error unless used within a
 defop-environment."
    (declare (special *name-prefix*))
    (format *trace-output* "(defwalk ~A ~A~%  ~{~S~})~%"name lambda-list body)
    (unless (and (boundp '*name-prefix*) (stringp *name-prefix*))
      (error "Only use defop inside a defop-environmemt."))
    (let ((fname (values (intern
			  (concatenate 'string *name-prefix*
				       (string (if (symbolp name) name (car name))))
			  *package*))))
      (format *trace-output* "In defop *name-prefix* ~S, fname: ~S~%"
	      *name-prefix* fname)
      `(locally
	   (declare (special *operator-table*))
	 (defun ,fname ,lambda-list ,@body)
	 (setf (gethash ',name *operator-table*) ',fname)
	 ',name))))

Evaluating (defop-environment env0 (defop fn0 (x y) (fn x y))) directly makes CCL unhappy:

Only use defop inside a defop-environmemt.

[Condition of type SIMPLE-ERROR]

Could you please look into this? A workaround is also very welcome.

Thank you very much,

Ernst van Waning

Change History (2)

comment:1 Changed 6 years ago by gb

As I read the code. the DEFOP macro will signal an error unless it is invoked (expanded) when *NAME-TABLE* is bound to a string. The expansion of DEFOP should be executed in the context established by the surrounding DEFOP-ENVIRONMENT (in the execution context in which the macro calls to DEFOP appear) , but I am not certain that the context in which the expansion is produced is specified or predictable.

If you are seeing two different behaviors in four different implementations, I think that both behaviors are equally correct.

comment:2 Changed 6 years ago by Ernst

  • Resolution set to fixed
  • Status changed from new to closed

Thank you for your reply.

The problem I did not describe was (probably) a symptom of my lack of intuition for the different environments described in http://www.lispworks.com/documentation/HyperSpec/Body/03_ba.htm.

Following suggestions, alternative now works with macrolet. So please consider this problem closed.

Kind regards,

Ernst

Note: See TracTickets for help on using tickets.