diff options
Diffstat (limited to 'modules/oop')
-rw-r--r-- | modules/oop/pf-objects.scm | 328 |
1 files changed, 200 insertions, 128 deletions
diff --git a/modules/oop/pf-objects.scm b/modules/oop/pf-objects.scm index d42865f..64ad776 100644 --- a/modules/oop/pf-objects.scm +++ b/modules/oop/pf-objects.scm @@ -17,7 +17,7 @@ py-super-mac py-super py-equal? *class* *self* pyobject? pytype? type object pylist-set! pylist-ref tr - resolve-method-g rawref rawset + resolve-method-g rawref rawset py-dict )) #| @@ -34,6 +34,26 @@ The datastructure is functional but the objects mutate. So one need to explicitly tell it to not update etc. |# +(define-syntax-rule (aif it p x y) (let ((it p)) (if it x y))) + +(define (pk-obj o) + (pk 'start-pk-obj) + (let ((h (slot-ref o 'h))) + (hash-for-each (lambda (k v) (pk k)) h) + (pk 'finished-obj) + (aif cl (hash-ref h '__class__) + (if (is-a? cl <p>) + (if (hash-table? (slot-ref cl 'h)) + (hash-for-each (lambda (k v) + (if (member k '(__name__ __qualname__)) + (pk k v) + (pk k))) + (slot-ref cl 'h)) + (pk 'no-hash-table)) + (pk 'no-class)) + (pk 'false-class))) + (pk 'end-pk-obj)) + (define fail (cons 'fail '())) (define-syntax-rule (kif it p x y) @@ -52,7 +72,6 @@ explicitly tell it to not update etc. (define (is-acl? a b) (member a (cons b (class-subclasses b)))) -(define-syntax-rule (aif it p x y) (let ((it p)) (if it x y))) (define-class <p> (<applicable-struct> <object>) h) (define-class <pf> (<p>) size n) ; the pf object consist of a functional ; hashmap it's size and number of live @@ -88,6 +107,27 @@ explicitly tell it to not update etc. (define-method (rawset (o <procedure>) key val) (set-procedure-property! o key val)) +(define-method (find-in-class (klass <pf>) key fail) + (let ((r (vhash-assoc key (slot-ref klass 'h)))) + (if r + (cdr r) + fail))) + +(define-syntax-rule (find-in-class-and-parents klass key fail-) + (aif parents (find-in-class klass '__mro__ #f) + (let lp ((parents parents)) + (if (pair? parents) + (kif r (find-in-class (car parents) key fail) + r + (lp (cdr parents))) + fail-)) + (kif r (find-in-class klass key fail) + r + fail-))) + +(define-inlinable + (ficap klass key fail) (find-in-class-and-parents klass key fail)) + (define (mk-getter-object f) (lambda (obj cls) (if (pytype? obj) @@ -95,10 +135,10 @@ explicitly tell it to not update etc. (if (pyclass? obj) (if (pytype? cls) (lambda x (apply f obj x)) - (lambda x (apply f x))) + f) (if (pyclass? cls) (lambda x (apply f obj x)) - (lambda x (apply f x))))))) + f))))) (define (mk-getter-class f) (lambda (obj cls) @@ -158,20 +198,17 @@ explicitly tell it to not update etc. (define (resolve-method-o o pattern) (resolve-method-g (class-of o) pattern)) -(define (get-dict self name parents) - (aif it (ref self '__prepare__) - (it self name parents) - (make-hash-table))) - (define (hashforeach a b) (values)) (define (new-class0 meta name parents dict . kw) (let* ((goops (pylist-ref dict '__goops__)) - (p (kwclass->class kw meta)) + (p (kwclass->class kw meta)) (class (make-p p))) + (pk 'new-class0) (slot-set! class 'procedure (lambda x (create-object class meta goops x))) + (if (hash-table? dict) (hash-for-each (lambda (k v) k (set class k v)) @@ -194,7 +231,7 @@ explicitly tell it to not update etc. class)) (define (new-class meta name parents dict kw) - (aif it (ref meta '__new__) + (aif it (and meta (ficap meta '__new__ #f)) (apply it meta name parents dict kw) (apply new-class0 meta name parents dict kw))) @@ -205,31 +242,55 @@ explicitly tell it to not update etc. #f) class)) -(define (create-class meta name parents gen-methods . keys) - (let ((dict (gen-methods (get-dict meta name keys)))) + +(define (the-create-object class x) + (let* ((meta (ref class '__class__)) + (goops (ref class '__goops__)) + (obj (aif it (ficap class '__new__ #f) + (it) + (make-object class meta goops)))) + (aif it (ref obj '__init__) + (apply it x) + #f) + + (slot-set! obj 'procedure + (lambda x + (aif it (ref obj '__call__) + (apply it x) + (error "not a callable object")))) + + obj)) + +(define (create-object class meta goops x) + (with-fluids ((*make-class* #t)) + (aif it (ficap meta '__call__ #f) + (apply it class x) + (the-create-object class x)))) + +(define type-call + (lambda (class . l) + (if (pytype? class) + (apply (case-lambda + ((meta obj) + (ref obj '__class__ 'None)) + ((meta name bases dict . keys) + (type- meta name bases dict keys))) + class l) + (the-create-object class l)))) + +(define (get-dict self name parents) + (aif it (and self (ficap self '__prepare__ #f)) + (it self name parents) + (make-hash-table))) + +(define (create-class meta name parents gen-methods keys) + (let ((dict (gen-methods (get-dict meta name parents)))) (aif it (ref meta '__class__) - (aif it (find-in-class (ref meta '__class__) '__call__ #f) + (aif it (find-in-class it '__call__ #f) (apply it meta name parents dict keys) (type- meta name parents dict keys)) (type- meta name parents dict keys)))) -(define (create-object class meta goops x) - (with-fluids ((*make-class* #t)) - (aif it #f - (apply it x) - (let ((obj (aif it (find-in-class class '__new__ #f) - (it) - (make-object class meta goops)))) - (aif it (ref obj '__init__) - (apply it x) - #f) - (slot-set! obj 'procedure - (lambda x - (aif it (ref obj '__call__) - (apply it x) - (error "not a callable object")))) - obj)))) - (define (make-object class meta goops) (let ((obj (make-p goops))) (set obj '__class__ class) @@ -272,6 +333,11 @@ explicitly tell it to not update etc. (f obj class) it))) +(define-inlinable (gokx obj class it) + (aif f (rawref it '__get__) + (f obj class) + it)) + (define *location* (make-fluid #f)) (define-syntax-rule (mrefx x key l) (let () @@ -304,30 +370,12 @@ explicitly tell it to not update etc. (define-method (find-in-class (klass <p>) key fail) (hash-ref (slot-ref klass 'h) key fail)) - -(define-method (find-in-class (klass <pf>) key fail) - (let ((r (vhash-assoc key (slot-ref klass 'h)))) - (if r - (cdr r) - fail))) - -(define-syntax-rule (find-in-class-and-parents klass key fail) - (kif r (find-in-class klass key fail) - r - (aif parents (find-in-class klass '__mro__ #f) - (let lp ((parents (cdr parents))) - (if (pair? parents) - (kif r (find-in-class (car parents) key fail) - r - (lp (cdr parents))) - fail)) - fail))) - + (define-syntax-rule (mrefx klass key l) (let () (define (end) (if (pair? l) (car l) #f)) (fluid-set! *location* klass) - (kif it (find-in-class klass key fail) + (kif it (find-in-class-and-parents klass key fail) it (aif klass (find-in-class klass '__class__ #f) (begin @@ -341,26 +389,17 @@ explicitly tell it to not update etc. (define-syntax-rule (mrefx-py x key l) (let ((xx x)) - (let* ((g (mrefx xx '__fget__ '(#t))) - (f (if g - (if (eq? g #t) - (aif it (mrefx xx '__getattribute__ '()) - (let ((f (gox xx it))) - (rawset xx '__fget__ it) - f) - (begin - (if (mc?) - (rawset xx '__fget__ #f)) - #f)) - g) - #f))) - (if (or (not f) (eq? f not-implemented)) - (gox xx (mrefx xx key l)) - (catch #t - (lambda () - (f xx key)) - (lambda x - (gox xx (mrefx xx key l)))))))) + (let* ((f (aif it (or (mrefx xx '__getattribute__ '()) + (mrefx xx '__getattr__ '())) + (gox xx it) + #f))) + (if (or (not f) (eq? f not-implemented)) + (gox xx (mrefx xx key l)) + (catch #t + (lambda () + (f xx key)) + (lambda x + (gox xx (mrefx xx key l)))))))) (define-syntax-rule (mref x key l) @@ -372,7 +411,15 @@ explicitly tell it to not update etc. (let ((res (mrefx-py xx key l))) res))) -(define-method (ref x key . l) (if (pair? l) (car l) #f)) +(define-method (ref x key . l) + (cond + ((eq? x 'None) + (apply ref NoneObj key l)) + ((pair? l) + (car l)) + (else + #f))) + (define-method (ref (x <pf> ) key . l) (mref x key l)) (define-method (ref (x <p> ) key . l) (mref x key l)) (define-method (ref (x <pyf>) key . l) (mref-py x key l)) @@ -712,28 +759,32 @@ explicitly tell it to not update etc. ((name supers.kw methods) (make-p-class name "" supers.kw methods)) ((name doc supers.kw methods) - (define kw (cdr supers.kw)) - (define supers (car supers.kw)) + (define s.kw supers.kw) + (define kw (cdr s.kw)) + (define supers (car s.kw)) (define goopses (map (lambda (sups) (aif it (ref sups '__goops__ #f) it sups)) supers)) + (define parents (let ((p (filter-parents supers))) - (if (null? p) - (if object - (list object) - '()) - p))) + p)) + + (define cparents (if (null? parents) + (if object + (list object) + '()) + parents)) (define meta (aif it (memq #:metaclass kw) (cadr it) - (if (null? parents) + (if (null? cparents) type - (let* ((p (car parents)) + (let* ((p (car cparents)) (m (ref p '__class__)) (mro (reverse (ref m '__mro__ '())))) - (let lp ((l (cdr parents)) + (let lp ((l (cdr cparents)) (max mro) (min mro)) (if (pair? l) @@ -753,7 +804,8 @@ explicitly tell it to not update etc. (lp (cdr l) mro min))))) (car (reverse min)))))))) - (define goops (make-class (append goopses (list (kw->class kw meta))) + (define goops (make-class (append goopses + (list (kw->class kw meta))) '() #:name name)) (define (make-module) @@ -766,33 +818,42 @@ explicitly tell it to not update etc. (map symbol->string (cdddr l)) ".") l))) - + (define (gen-methods dict) + (define (filt-bases x) + (let lp ((x x)) + (if (pair? x) + (let ((y (car x))) + (if (is-a? y <p>) + (cons y (lp (cdr x))) + (lp (cdr x)))) + '()))) + (methods dict) (pylist-set! dict '__goops__ goops) (pylist-set! dict '__class__ meta) (pylist-set! dict '__zub_classes__ (make-weak-key-hash-table)) (pylist-set! dict '__module__ (make-module)) - (pylist-set! dict '__bases__ parents) + (pylist-set! dict '__bases__ (filt-bases parents)) (pylist-set! dict '__fget__ #t) (pylist-set! dict '__fset__ #t) (pylist-set! dict '__name__ name) (pylist-set! dict '__qualname__ name) (pylist-set! dict '__class__ meta) - (pylist-set! dict '__mro__ (get-mro parents)) + (pylist-set! dict '__mro__ (get-mro cparents)) (pylist-set! dict '__doc__ doc) dict) (let ((cl (with-fluids ((*make-class* #t)) - (create-class meta name parents gen-methods kw)))) + (create-class meta name parents gen-methods kw)))) (aif it (ref meta '__init_subclass__) - (let lp ((ps parents)) + (let lp ((ps cparents)) (if (pair? ps) (let ((super (car ps))) (it cl super) (lp (cdr ps))))) #f) - + cl)))) @@ -867,8 +928,8 @@ explicitly tell it to not update etc. (lambda (x) (syntax-case x () ((_ name parents ((ddef dname dval) ...) body) - #'(mk-p-class name parents "" (ddef dname dval) ...)) - ((_ name parents doc (ddef dname dval) ...) + #'(mk-p-class2 name parents "" ((ddef dname dval) ...) body)) + ((_ name parents doc ((ddef dname dval) ...) body) (with-syntax (((ddname ...) (map (lambda (dn) (datum->syntax @@ -894,13 +955,13 @@ explicitly tell it to not update etc. #'(let () (define name (letruc ((dname (make-up dval)) ...) - body - (make-p-class 'name doc - parents - (lambda (dict) - (pylist-set! dict 'dname dname) - ... - (values))))) + body + (make-p-class 'name doc + parents + (lambda (dict) + (pylist-set! dict 'dname dname) + ... + (values))))) (begin (module-define! (current-module) 'ddname (ref name 'dname)) @@ -1001,11 +1062,15 @@ explicitly tell it to not update etc. code ...))) cl))))) - +(define type-goops #f) (define (kind x) + (if (not type-goops) (set! type-goops (ref type '__goops__))) (and (is-a? x <p>) (aif it (find-in-class x '__goops__ #f) - (if (is-a? (make it) (ref type '__goops__)) + (if (or + (not type-goops) + (eq? it type-goops) + (member it (class-subclasses type-goops))) 'type 'class) 'object))) @@ -1028,25 +1093,23 @@ explicitly tell it to not update etc. (define (not-a-super) 'not-a-super) (define (py-super class obj) (define (make cl parents) - (if (or (pyclass? obj) (pytype? obj)) - cl - (let ((c (make-p <p>)) - (o (make-p <p>))) - (set c '__super__ #t) - (set c '__mro__ parents) - (set c '__getattribute__ (lambda (self key . l) - (aif it (ref c key) - (if (procedure? it) - (if (eq? (procedure-property - it - 'py-special) - 'class) - (it cl) - (it obj)) - it) - (error "no attribute")))) - (set o '__class__ c) - o))) + (if (not cl) + #f + (if (or (pyclass? obj) (pytype? obj)) + cl + (let ((c (make-p <py>)) + (o (make-p <py>))) + (set c '__class__ type) + (set c '__mro__ (cons c parents)) + (set c '__getattribute__ (lambda (self key . l) + (aif it (ficap c key #f) + (if (procedure? it) + (gokx obj cl it) + it) + (error "no attribute")))) + (set c '__name__ "**super**") + (set o '__class__ c) + o)))) (call-with-values (lambda () @@ -1222,17 +1285,16 @@ explicitly tell it to not update etc. (define __init_subclass__ (lambda x (values))) (define ___zub_classes__ (make-weak-key-hash-table)) (define __subclasses__ subclasses) - (define __call__ - (case-lambda - ((meta obj) - (ref obj '__class__ 'None)) - ((meta name bases dict . keys) - (type- meta name bases dict keys)))))) + (define __call__ type-call) + (define mro (lambda (self) (ref self '__mro__))))) + (set type '__class__ type) (set! object (make-python-class object () - (define __subclasses__ subclasses) - (define __weakref__ (lambda (self) self)))) + (define __init__ (lambda x (values))) + (define __subclasses__ subclasses) + (define __weakref__ (lambda (self) self)))) + (name-object type) (name-object object) @@ -1242,4 +1304,14 @@ explicitly tell it to not update etc. it (next-method))) - + +(define-method (py-dict (o <p>)) + (aif it (ref o '__dict__) + it + (slot-ref o 'h))) + +(define-python-class NoneObj () + (define __new__ + (lambda x 'None))) + + |