• challenge: insert a literal reader conditional

    From Madhu@21:1/5 to All on Mon Apr 14 07:35:37 2025
    Anyone know of a hack to insert literal reader conditionals in generated
    code?

    (setq $a '(+ 1 2 3))

    assume I want to dump $a to a file, but I want the file to contain the
    text

    "(+ 1 2 3 #+foo 4)"

    is it possible to do this at all without string-replace on the generated
    output file?

    I'm pretty sure it is not possible theoretically, but maybe there is
    some insane hack.

    asdf (and now mk-defsystem) solves this by using :IF-FEATURE constructs
    that handle some features at read time.
    so one can write

    (:FILE "x86_64-pc-linux-gnu" :IF-FEATURE (:AND :X86-64 :LINUX))
    and defsystem will expand this to (:file "x86_64-pc-linux-gnu")
    when processing the form if the features are present and omit the form
    if they are not.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Madhu@21:1/5 to All on Mon Apr 14 10:36:44 2025
    * I, Madhu <m3r01vjy4u.fsf@leonis4.robolove.meer.net> :
    Wrote on Mon, 14 Apr 2025 07:35:37 +0530:

    Anyone know of a hack to insert literal reader conditionals in generated code?

    (setq $a '(+ 1 2 3))

    assume I want to dump $a to a file, but I want the file to contain the
    text

    "(+ 1 2 3 #+foo 4)"

    is it possible to do this at all without string-replace on the generated output file?

    I'm pretty sure it is not possible theoretically, but maybe there is
    some insane hack.

    asdf (and now mk-defsystem) solves this by using :IF-FEATURE constructs
    that handle some features at read time.
    so one can write

    (:FILE "x86_64-pc-linux-gnu" :IF-FEATURE (:AND :X86-64 :LINUX))
    and defsystem will expand this to (:file "x86_64-pc-linux-gnu")
    when processing the form if the features are present and omit the form
    if they are not.

    Answering myself in the best form a crude solution (without bells and
    whistles to handle #+(and) #+(or) combinaions of features) follows
    directly from the above mentioned :if-feature facility. for the limited
    example above

    (defclass feature-hack ()
    ((feature :initarg :feature :type keyword)
    (if-feature-form :initarg :if-feature)
    (if-not-feature-form :initarg :if-not-feature)))

    (defmethod print-object ((obj feature-hack) stream)
    (destructuring-bind (feature-boundp if-feature-form-boundp if-not-feature-form-boundp)
    (mapcar (lambda (x) (slot-boundp obj x))
    '(feature if-feature-form if-not-feature-form))
    (if (or (not feature-boundp)
    (and (not if-feature-form-boundp)
    (not if-not-feature-form-boundp)))
    ;; comments welcome:
    (print-unreadable-object (obj stream :type t :identity t))
    (with-slots (feature if-feature-form if-not-feature-form) obj
    (check-type feature keyword)
    (when if-feature-form-boundp
    (format stream "#+:~A ~S" feature if-feature-form))
    (when if-not-feature-form-boundp
    (format stream "~:[~; ~]#-:~A ~S"
    if-feature-form-boundp feature if-not-feature-form))))))

    (setq $a `(+ 1 2 3
    ,(make-instance 'feature-hack :feature :foo :if-feature 4)))

    (with-output-to-string (s)
    (let ((*print-readably* t))
    (write $a :stream s)))

    ;; => "(+ 1 2 3 #+:FOO 4)"

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)