;; @module ObjNL ;; @description Objective newLISP - Real Object Oriented Programming for newLISP ;; @version 1.0 ;; @author Greg Slepak ;; @location http://www.taoeffect.com/newlisp/ObjNL.lsp.txt ;;
It supports most of the object oriented concepts you'll find ;; in other languages. It supports inheritance, interfaces (aka protocols), ;; as well as class and instance variables.
;;Objects are passed by reference, so there's no problem with passing ;; an object through multiple user-defined functions and modifying it.
;;Accessing instance variables no longer requires a function call plus a ;; list traversal. Simply access the symbol directly.
;;Objective newLISP also enhances newLISP by providing convenient and safe ;; macros for deep reference access.
;;With Objective newLISP it is possible to take full advantage of everything ;; object-oriented programming has to offer.
;;'ObjNL' is the root class for Objective newLISP. All other classes ultimately ;; inherit from it. It defines several instance and class variables:
;;The constructor is the default function. It is called by 'instantiate'.
;;The default implementation simply returns 'true'.
(define (ObjNL:ObjNL) true) ;; @syntax (ObjNL:dealloc) ;;Called by 'deallocate' to give the object an opportunity to release resources and objects.
(define (ObjNL:dealloc)) ;; @syntax (ObjNL:equalsProvides a method for classes to define what it means for objects to be equal.
;;The default implementation returns 'true' if two objects are the same instance.
(define (ObjNL:equals obj) (= obj @self)) (context MAIN) ; it's possible to even implement reference counting :-p ;; @syntax (new-classReturns a new instance of
The returned object must be deallocated using the 'deallocate' ;; function.
(define (instantiate class) (letn ( obj-sym (sym (string class "#" (inc class:@instance-counter))) obj (new class obj-sym) ) ; set these prior to calling the constructor (set 'obj:@self obj 'obj:@self-sym obj-sym) (if (apply obj $args) obj (begin (deallocate obj) nil) ) ) ) ;; @syntax (add-interfaceUses the function 'new' to add
Calls the objects 'dealloc' method and then 'delete''s the object.
;;NOTE: On versions of newLISP prior to 10.1.9 this is a fairly slow ;; operation, make sure to use at least version 10.1.9 with Objective newLISP.
(define (deallocate obj) (obj:dealloc) (let (obj-sym obj:@self-sym) (delete obj-sym nil) ; delete the context (delete obj-sym nil) ; delete the symbol in MAIN ) ) ;; @syntax (implements?Increment's
Decrement's
Adds
Pushes a new autorelease pool onto the 'MAIN:@autorelease' stack.
(define (push-autorelease-pool) (push '() @autorelease) ) ;; @syntax (pop-autorelease-pool) ;;Pops the current 'MAIN:@autorelease' pool and releases the objects in it.
(define (pop-autorelease-pool , obj) (dolist (obj (pop @autorelease)) (release obj) ) ) (global 'new-class 'instantiate 'deallocate 'implements? 'retain 'release 'autorelease 'push-autorelease-pool 'pop-autorelease-pool '@autorelease) ;; @syntax (.The dot macro is used for "deep value access":
;; example: ;;;; (new-class 'Foo) ;; (new-class 'Bar) ;; (context Bar) ;; (define (Bar:Bar f) ;; (setf foo f) ;; true ; -> do not deallocate us if 'f' is nil ;; ) ;; (context Foo) ;; (define (Foo:Foo b) ;; (setf bar b) ;; true ; -> do not deallocate us if 'b' is nil ;; ) ;; (context MAIN) ;; (setf f (instantiate Foo (instantiate Bar))) ;; (set (.& f bar foo) f) ; => Foo#1 ;; (. f bar foo bar) ; => Bar#1(context '.) (define-macro (.:. obj) (doargs (field) (setf obj (eval (sym field (eval obj) nil))) ) ) ;; @syntax (.&
The dot-reference macro is similar to the dot macro, except it returns the ;; context-qualified symbol for the final field instead of its value ("deep symbol access"). ;; This allows you to combine it with 'set'.
;; @see '.' macro for example usage. (context '.&) (define-macro (.&:.& obj) (doargs (field) (setf obj (sym field (eval obj))) ) ) (context MAIN)