| I have an interesting idea to make
macros object oriented. Pros: It can shorten the macro names.
It can combine macros with classes.
It can create a shortcut for a big if statment.
Cons: we can not do polymorphism.
It is implemented in the following code: (= class-macro-table* (obj)) ;A hash table of class functions
(= declare-obj-class* (obj)) ;A hash table of temprorary obj annotations
; A variable that exist becouse every macro must return a value.
(= temporary* nil)
; declare an object type
(mac dec (obj types . body)
(let oldtype (declare-obj-class* obj)
(= (declare-obj-class* obj) types)
`(do (= temporary* (do ,@body)) (undec ,obj ,oldtype))))
; remove object declaration
(mac undec (obj oldtype)
(= (declare-obj-class* obj) oldtype)
'temporary*)
; Creating a class macro
(mac cmac (funcname classname args . body)
(with (realName (uniq) args2 (uniq))
(unless class-macro-table*.classname
(= class-macro-table*.classname (obj)))
(= class-macro-table*.classname.funcname realName)
(let realmac `(mac ,realName (,classname ,@args) ,@body)
(if (bound funcname)
realmac
`(do ,realmac (mac ,funcname ,args2
(apply _callmac ',funcname (car ,args2) (cdr ,args2)))) ))))
; Helper function for calling a macro
(def _callmac2 (mac-name obj-name . args)
(if (aand class-macro-table*.obj-name it.mac-name)
(let macro-real-name class-macro-table*.obj-name.mac-name
`(,macro-real-name ,obj-name ,@args))
(err "Undeclare macro for this object")))
(def _callmac (mac-name obj-name . args)
(let obj-class declare-obj-class*.obj-name
(if (no obj-class) (err "Undeclare object")
(acons obj-class)
(let if-expr ()
(each class obj-class
(do
(push (apply _callmac2 mac-name class args) if-expr)
(push `(isa ,obj-name ',class) if-expr)))
`(if ,@if-expr (err "Undeclare object")))
(apply _callmac2 mac-name obj-class args))))
; macro for calling class macros
(mac callmac (mac-name obj-name . args)
(apply _callmac mac-name obj-name args))
Class macro usage: Suppose we have three types of messages:
sms-msg voice-msg and email-msg
we can declare a w/msg macro like this:
(cmac w/msg sms-msg (arg1 arg2 ...) ... )
(cmac w/msg voice-msg (...) ...)
(cmac w/msg email-msg (...) ...)
If we want to call a macro in a function, we write: (dec email-msg-obj email-msg
(w/msg email-msg-obj ...))
If an object can be one of the three messages,
It can generate if statement, in the following way: (dec msg-obj (sms-msg voice-msg email-msg)
(w/msg msg-obj ...))
What do you think about class macros? |