Hi,
I'm experimenting with linj and tried to create some macros which shall help
me working with swing and maybe building up a higher abstraction of
swing :)
But unfortunately using macros in linj isn't that easy.
First of all, I wasn't able to create recursive macros :( thus I had to
write functions doing the recursive expansion.
Here are macros /functions I've written:
(defun strip-type (x)
(values (intern
(let* ((name (symbol-name x))
(pos (position #\/ name)))
(if pos
(subseq name 0 pos)
name)))))
(defun mkstr (&rest args)
(with-output-to-string (s)
(dolist (a args) (princ a s))))
(defun symb (&rest args)
(values (intern (apply #'mkstr args))))
(defmacro def-util (name &key (pkg 'util))
`(def-macro ,(symb pkg "." name) (&rest args)
`(in (the ,',pkg)
(,',name ,@args))))
(defmacro export-utils (pkg &rest names)
`(progn ,@(loop for elem in names
collect `(def-util ,elem :pkg ,pkg))))
(defun my-split-if (fn lst)
(let ((acc ()))
(do ((src lst (cdr src)))
((or (null src) (funcall fn (car src)))
(values (nreverse acc) src))
(push (car src) acc))))
(defun group-list (source n)
(if (endp source)
'()
(let ((rest (nthcdr n source)))
(cons (if (consp rest) (subseq source 0 n) source)
(group-list rest n)))))
(def-macro with-swing ((&rest args) &body body)
(build-swing-let args body))
(def-macro setter-call (setter)
(symb 'set- setter))
(defun build-swing-let (args body)
(if args
(let ((component-def (car args))
(args-rest (cdr args)))
(if (listp component-def)
(build-initializing-swing-let component-def
args-rest
body)
`(let (,component-def)
,(build-swing-let args-rest body))))
`(progn ,@body)))
(defun build-initializing-swing-let (component-def args-rest body)
(multiple-value-bind (constructor keyword-list) (my-split-if #'keywordp
(cadr
component-def))
(let ((setters (mapcar #'(lambda (x)
`(send
,(car component-def) ;class
(setter-call ,(car x))
,@(cdr x)))
(group-list keyword-list 2)))
(constructor `(new ',(car constructor) ,@(cdr constructor))))
`(let ((,(car component-def) ,constructor))
,@setters
,(build-swing-let args-rest body)))))
The macros and functions are loaded via cmucl using (in-package :linj) (load
"macros.linj"), that's why i used (def-macro ... ) instead of
(defmacro ...), since only macros defined with (def-macro ...) are
available when linj is trnaslating the file later.
The Problem is the macro (setter-call ...), which takes a symbol and
prepands 'set-. Thus (setter-call :text) is translated into SET-TEXT.
Now using the macro (with-swing ...) I can write :
(with-swing ((l1 (j-label :text "test"))
(l2 (j-label :text "test2")))
(format t "~A~%" l1))
expands into:
(LET ((L1 (new 'j-label)))
(SEND L1 SET-TEXT "test")
(LET ((l2 (new 'j-label)))
(SEND L2 SET-TEXT "test2")
(PROGN
(FORMAT T "~A~%" L1))))
But when using (linj2java ...) it yields:
Error in function linj-error: Couldn't find declaration for set-TEXT
Any suggestion how to solve this problem are very welcome :P
I've just been running out of ideas :(
bye :)
From: Joe Marshall
Subject: Re: linj macro generating JAVA setter calls using keys
Date:
Message-ID: <8y0klre1.fsf@comcast.net>
parumaru <······@gmx.net> writes:
> The Problem is the macro (setter-call ...), which takes a symbol and
> prepands 'set-. Thus (setter-call :text) is translated into SET-TEXT.
> But when using (linj2java ...) it yields:
> Error in function linj-error: Couldn't find declaration for set-TEXT
Looks like it might have translated it into set-TEXT rather than
SET-TEXT. I'm guessing case-sensitivity issues, but it's just a
guess.
--
~jrm