diff options
Diffstat (limited to 'modules/language')
-rw-r--r-- | modules/language/python/compile.scm | 4 | ||||
-rw-r--r-- | modules/language/python/dict.scm | 117 | ||||
-rw-r--r-- | modules/language/python/exceptions.scm | 6 | ||||
-rw-r--r-- | modules/language/python/hash.scm | 12 | ||||
-rw-r--r-- | modules/language/python/list.scm | 9 | ||||
-rw-r--r-- | modules/language/python/module.scm | 16 | ||||
-rw-r--r-- | modules/language/python/module/collections.scm | 113 | ||||
-rw-r--r-- | modules/language/python/module/collections/abc.scm | 19 | ||||
-rw-r--r-- | modules/language/python/module/enum.py | 47 | ||||
-rw-r--r-- | modules/language/python/module/python.scm | 8 | ||||
-rw-r--r-- | modules/language/python/string.scm | 4 |
11 files changed, 225 insertions, 130 deletions
diff --git a/modules/language/python/compile.scm b/modules/language/python/compile.scm index 5df4f3c..00443a9 100644 --- a/modules/language/python/compile.scm +++ b/modules/language/python/compile.scm @@ -1118,7 +1118,7 @@ (let* ((decor (let ((r (fluid-ref decorations))) (fluid-set! decorations '()) r)) - (arg_ (get-args_ vs args)) + (arg_ (get-args_ vs args)) (arg= (get-args= vs args)) (dd= (map cadr arg=)) (c? (fluid-ref is-class?)) @@ -1131,7 +1131,7 @@ (dd** (map cadr **f)) (aa `(,@arg_ ,@*f ,@arg= ,@**f)) (ab (gensym "ab")) - (vs (union dd** (union dd* (union dd= (union args vs))))) + (vs (union dd** (union dd* (union dd= (union arg_ vs))))) (ns (scope code vs)) (df (defs code '())) (ex (gensym "ex")) diff --git a/modules/language/python/dict.scm b/modules/language/python/dict.scm index 0e130d0..18420dd 100644 --- a/modules/language/python/dict.scm +++ b/modules/language/python/dict.scm @@ -191,7 +191,7 @@ (let ((ret (py-hash-ref t key miss))) (if (eq? ret miss) (begin - (py-hash-set! t key val) + (py-hash-set! t key val) (slot-set! o 'n (+ n 1)) (slot-set! o 'hash (logxor (xy (py-hash key) (py-hash val)) h))) (begin @@ -275,7 +275,7 @@ (let ((elseval (match l (() None) ((v) v)))) - (let ((ret (ref o k miss))) + (let ((ret (py-hash-ref o k miss))) (if (eq? ret miss) elseval ret)))) @@ -284,7 +284,7 @@ (let ((elseval (match l (() None) ((v) v)))) - (let ((ret (ref (slot-ref o 't) k miss))) + (let ((ret (py-hash-ref (slot-ref o 't) k miss))) (if (eq? ret miss) elseval ret))))) @@ -545,29 +545,40 @@ (define <dict> `(,<py-hashtable> . _)) -(define dict-set! (resolve-method-g pylist-set! <dict>)) -(define dict-ref (resolve-method-g pylist-ref <dict>)) -(define dict-del! (resolve-method-g pylist-delete! <dict>)) -(define dict-pop! (resolve-method-g pylist-pop! <dict>)) -(define dict-clear! (resolve-method-g py-clear <dict>)) -(define dict-get (resolve-method-g py-get <dict>)) -(define dict-len (resolve-method-g len <dict>)) -(define dict-bool (resolve-method-g bool <dict>)) - - -(define-python-class dict (<py-hashtable>) +(define <in> `(,<top> ,<py-hashtable>)) +(define (resolve a b) (object-method (resolve-method-g a b))) +(define dict-set! (resolve pylist-set! <dict>)) +(define dict-ref (resolve pylist-ref <dict>)) +(define dict-del! (resolve pylist-delete! <dict>)) +(define dict-pop! (resolve pylist-pop! <dict>)) +(define dict-clear! (resolve py-clear <dict>)) +(define dict-get (resolve py-get <dict>)) +(define dict-len (resolve len <dict>)) +(define dict-bool (resolve bool <dict>)) +(define dict-in (resolve in <in> )) +(define dict-items (resolve py-items <dict>)) + +(define-python-class dict (<py> <py-hashtable>) (define __getitem__ dict-ref) - (define __setitem__ dict-set!) + (define __setitem__ + (lambda (self key val) + (dict-set! self key val))) (define __delitem__ dict-del!) (define pop dict-pop!) (define clear dict-clear!) (define get dict-get) (define __len__ dict-len) (define __bool__ dict-bool) + (define items dict-items) + (define __iter__ (lambda (self) + (wrap-in (slot-ref self 't)))) + (define __contains__ + (lambda (self x) (dict-in x self))) (define __format___ (lambda x #f)) (define __setattr__ (@@ (oop pf-objects) __setattr__)) (define __getattribute__ (@@ (oop pf-objects) __getattribute__)) - + + (define __init__ (letrec ((__init__ (case-lambda @@ -591,7 +602,71 @@ __init__))) -(define-python-class weak-key-dict (<py-hashtable>) +(define (norm k) + (if (symbol? k) + (symbol->string k) + k)) + +(define fail (list 'fail)) + +(define-python-class dictNs () + (define __getitem__ + (lambda (self k) + (pylist-ref (ref self '_dict) (norm k)))) + + (define __setitem__ + (lambda (self k v) + (pylist-set! (ref self '_dict) (norm k) v))) + + (define __iter__ + (lambda (self) + (wrap-in (ref self '_dict)))) + + (define pop + (lambda (self k . l) + (apply pylist-pop! (ref self '_dict) (norm k) l))) + + (define clear + (lambda (self) + (py-clear (ref self '_dict)))) + + (define get + (lambda (self key . l) + (apply py-get (ref self '_dict) (norm key) l))) + + (define __len__ + (lambda (self) + (len (ref self '_dict)))) + + (define __bool__ + (lambda (self) + (bool (ref self '_dict)))) + + (define __contains__ + (lambda (self x) + (in (norm x) (ref self '_dict)))) + + (define items + (lambda (self) + (py-items (ref self '_dict)))) + + (define __repr__ + (lambda (self) + (format #f "Ns:~a" (ref (ref self '_dict) '__name__)))) + + (define __getattr__ + (lambda (self key) + (let ((r (ref (ref self '_dict) key fail))) + (if (eq? r fail) + (raise (AttributeError key)) + r)))) + + (define __init__ + (lambda (self d) (set self '_dict d)))) + +(set! (@@ (oop pf-objects) dictNs) dictNs) + +(define-python-class weak-key-dict (<py> <py-hashtable>) (define __init__ (letrec ((__init__ (case-lambda @@ -610,7 +685,7 @@ (slot-ref x 't))))))) __init__))) -(define-python-class weak-value-dict (<py-hashtable>) +(define-python-class weak-value-dict (<py> <py-hashtable>) (define __init__ (letrec ((__init__ (case-lambda @@ -647,6 +722,10 @@ (pylist-sort! l) l)) - +(set! (@@ (oop pf-objects) hash-for-each*) + (lambda (f dict) + (for ((k v : dict)) () + (f k v)))) + (define-method (py-class (o <hashtable>)) dict) (define-method (py-class (o <py-hashtable>)) dict) diff --git a/modules/language/python/exceptions.scm b/modules/language/python/exceptions.scm index 9d51116..0e16e4b 100644 --- a/modules/language/python/exceptions.scm +++ b/modules/language/python/exceptions.scm @@ -22,11 +22,11 @@ (define __repr__ (lambda (self) - (aif it (ref self 'value #f) + (aif it (rawref self 'value #f) (format #f "~a:~a" - (ref self '__name__) it) + (rawref self '__name__) it) (format #f "~a" - (ref self '__name__)))))) + (rawref self '__name__)))))) (define-syntax define-er (syntax-rules () diff --git a/modules/language/python/hash.scm b/modules/language/python/hash.scm index 168cd44..423abb3 100644 --- a/modules/language/python/hash.scm +++ b/modules/language/python/hash.scm @@ -42,7 +42,11 @@ s)))) (define-method (py-hash (x <p>)) - (aif it (ref x '__hash__) - (pk 'hash (it)) - (next-method))) - + (define (next) + (catch #t + (lambda () (next-method)) + (lambda x (hash x N)))) + + (aif it (ref-class x '__hash__ #f) + (it) + (next))) diff --git a/modules/language/python/list.scm b/modules/language/python/list.scm index 1a8374e..91b66b4 100644 --- a/modules/language/python/list.scm +++ b/modules/language/python/list.scm @@ -144,11 +144,6 @@ (define-method (pylist-ref (o <vector>) n) (vector-ref o n)) -(define-method (pylist-ref (o <p>) n) - (aif it (ref o '__getitem__) - (it n) - (next-method))) - ;;; SET (define-method (pylist-set! (o <py-list>) nin val) (define N (slot-ref o 'n)) @@ -164,10 +159,6 @@ (define-method (pylist-set! (o <vector>) n val) (vector-set! o n val)) -(define-method (pylist-set! (o <p>) n val) - (aif it (ref o '__setitem__) - (it n val) - (next-method))) ;;SLICE (define-method (pylist-slice (o <p>) n1 n2 n3) diff --git a/modules/language/python/module.scm b/modules/language/python/module.scm index 6570452..101f62e 100644 --- a/modules/language/python/module.scm +++ b/modules/language/python/module.scm @@ -139,15 +139,13 @@ (lambda (self k) (define (fail) (raise (AttributeError "getattr in Module"))) - (if (rawref self '_module) - (let ((k (_k k)) - (m (_m self))) - (let ((x (module-ref m k e))) - (if (eq? e x) - (fail) - x))) - (fail)))) - + (let ((k (_k k)) + (m (_m self))) + (let ((x (module-ref m k e))) + (if (eq? e x) + (fail) + x))))) + (define __setattr__ (lambda (self k v) (let ((k (_k k)) diff --git a/modules/language/python/module/collections.scm b/modules/language/python/module/collections.scm index 1a158c9..04f7ab6 100644 --- a/modules/language/python/module/collections.scm +++ b/modules/language/python/module/collections.scm @@ -94,20 +94,19 @@ (define-python-class OrderedDict (dict) (define __init__ (lam (self (* args) (** kwds)) + ((ref dict '__init__) self) + (if (> (len args) 1) (raise TypeError (format #f "expected at most 1 arguments, got ~a" (len args)))) - (try - (lambda () (ref self '__root)) - (#:except AttributeError => - (lambda x - (let* ((l (link))) - (set self '__root l) - (set-next! l l) - (set-prev! l l))))) + (if (not (ref self '__root)) + (let* ((l (link))) + (set self '__root l) + (set-next! l l) + (set-prev! l l))) (set self '__map (dict)) (py-apply py-update self (* args) (** kwds)))) @@ -127,7 +126,7 @@ (set-key! link key) (set-next! last link) (set-prev! root link) - (dict_setitem self key value))))) + (dict-set! self key value))))) (define __delitem__ (lam (self key (= dict_delitem dict-del!)) @@ -145,7 +144,7 @@ (lambda (yield) (let ((root (ref self '__root))) (let lp ((curr (get-next root))) - (if ((not (eq? curr root))) + (if (not (eq? curr root)) (let ((key (get-key curr))) (yield key (pylist-ref self key)) (lp (get-next curr))))))))))) @@ -209,11 +208,16 @@ (define __update update) (define keys - (lambda (self) _OrderedDictKeysView(self))) + (lambda (self) + (_OrderedDictKeysView self))) + (define items - (lambda (self) _OrderedDictItemsView(self))) + (lambda (self) + (_OrderedDictItemsView self))) + (define values - (lambda (self) _OrderedDictValuesView(self))) + (lambda (self) + (_OrderedDictValuesView self))) (define __ne__ (ref MutableMapping '__ne__)) @@ -645,51 +649,54 @@ (make-p-class (string->symbol typename) '(()) (lambda (dict) - (pylist-set! dict '__init__ - (eval (v `(lam - (self - ,@(map (lambda (key) `(= ,key #f)) - field_names)) + (pylist-set! dict '__init__ + (object-method + (eval (v `(lam + (self + ,@(map (lambda (key) `(= ,key #f)) + field_names)) - ,@(map (lambda (key) `(set self ',key ,key)) - field_names))) - mod)) + ,@(map (lambda (key) `(set self ',key ,key)) + field_names))) + mod))) - (pylist-set! dict '__getitem__ - (lam (self i) - (if (number? i) - (ref self (list-ref field_names i)) - (ref self (scm-sym i))))) + (pylist-set! dict '__getitem__ + (object-method + (lambda (self i) + (if (number? i) + (ref self (list-ref field_names i)) + (ref self (scm-sym i)))))) - (pylist-set! dict '__setitem__ - (lam (self i val) - (if (number? i) - (set self (list-ref field_names i) val) - (set self (scm-sym i) val)))) - - (pylist-set! dict '__repr__ - (lam (self) - (let ((l (map (lambda (x) - (format #f "~a=~a" - x - (ref self x))) - field_names))) - - (format #f "~a(~a~{,~a~})" - typename - (car l) - (cdr l))))) + (pylist-set! dict '__setitem__ + (object-method + (lambda (self i val) + (if (number? i) + (set self (list-ref field_names i) val) + (set self (scm-sym i) val))))) + + (pylist-set! dict '__repr__ + (object-method + (lambda (self . l) + (let ((l (map (lambda (x) + (format #f "~a=~a" + x + (ref self x))) + field_names))) + (format #f "~a(~a~{,~a~})" + typename + (car l) + (cdr l)))))) - (if (eq? module None) - (set! module (module-name (current-module))) - (if (string? (scm-str module)) - (set! module - (+ '(language python module) - (map scm-sym - (string-split module #\.)))))) - - (if verbose (pretty-print verbose)))))) + (if (eq? module None) + (set! module (module-name (current-module))) + (if (string? (scm-str module)) + (set! module + (+ '(language python module) + (map scm-sym + (string-split module #\.)))))) + + (if verbose (pretty-print verbose)))))) (define UserDict dict) (define UserString pystring) diff --git a/modules/language/python/module/collections/abc.scm b/modules/language/python/module/collections/abc.scm index 4bd242d..4d442d3 100644 --- a/modules/language/python/module/collections/abc.scm +++ b/modules/language/python/module/collections/abc.scm @@ -516,7 +516,10 @@ (define __iter__ (lambda (self) - ((ref (ref self '_mapping) 'items))))) + ((make-generator () + (lambda (yield) + (for ((k v : (ref self '_mapping))) () + (yield (list k v))))))))) (define-python-class KeysView (MappingView Set) ;; Mixins @@ -524,10 +527,13 @@ (lambda (self k) (let ((m (ref self '_mapping))) (in k m)))) - + (define __iter__ (lambda (self) - ((ref (ref self '_mapping) 'keys))))) + ((make-generator () + (lambda (yield) + (for ((k v : (ref self '_mapping))) () + (yield k)))))))) (define-python-class ValuesView (MappingView) ;; Mixins @@ -541,6 +547,7 @@ (define __iter__ (lambda (self) - ((ref (ref self '_mapping) 'values))))) - - + ((make-generator () + (lambda (yield) + (for ((k v : (ref self '_mapping))) () + (yield v)))))))) diff --git a/modules/language/python/module/enum.py b/modules/language/python/module/enum.py index 0f623f0..723fab7 100644 --- a/modules/language/python/module/enum.py +++ b/modules/language/python/module/enum.py @@ -50,14 +50,12 @@ def _make_class_unpicklable(cls): _auto_null = object() - class auto: """ Instances are replaced with an appropriate value in Enum class suites. """ value = _auto_null - class _EnumDict(dict): """Track enum member order and ensure member names are not reused. @@ -90,10 +88,10 @@ class _EnumDict(dict): elif _is_dunder(key): if key == '__order__': key = '_order_' - elif key in self._member_names: + elif (key in self._member_names): # descriptor overwriting an enum? raise TypeError('Attempted to reuse key: %r' % key) - elif not _is_descriptor(value): + elif (not _is_descriptor(value)): if key in self: # enum overwriting a descriptor? raise TypeError('%r already defined as: %r' % (key, self[key])) @@ -105,13 +103,12 @@ class _EnumDict(dict): self._last_values.append(value) super().__setitem__(key, value) - # Dummy value for Enum as EnumMeta explicitly checks for it, but of course # until EnumMeta finishes running the first time the Enum class doesn't exist. # This is also why there are checks in EnumMeta like `if Enum is not None` Enum = None - +pk('EnumMeta') class EnumMeta(type): """Metaclass for Enum""" @classmethod @@ -132,13 +129,15 @@ class EnumMeta(type): # cannot be mixed with other types (int, float, etc.) if it has an # inherited __new__ unless a new __new__ is defined (or the resulting # class will fail). + member_type, first_enum = metacls._get_mixins_(bases) - __new__, save_new, use_args = metacls._find_new_(classdict, member_type, - first_enum) + new, save_new, use_args = metacls._find_new_(classdict, member_type, + first_enum) # save enum items into separate mapping so they don't get baked into # the new class enum_members = {k: classdict[k] for k in classdict._member_names} + for name in classdict._member_names: del classdict[name] @@ -150,21 +149,19 @@ class EnumMeta(type): if invalid_names: raise ValueError('Invalid enum member name: {0}'.format( ','.join(invalid_names))) - + # create a default docstring if one has not been provided if '__doc__' not in classdict: classdict['__doc__'] = 'An enumeration.' # create our new Enum type enum_class = super().__new__(metacls, cls, bases, classdict) - pk(enum_class) enum_class._member_names_ = [] # names in definition order enum_class._member_map_ = OrderedDict() # name->value map enum_class._member_type_ = member_type # save attributes from super classes so we know if we can take # the shortcut of storing members in the class dict - base_attributes = {a for b in enum_class.mro() for a in b.__dict__} # Reverse value->name map for hashable values. @@ -197,14 +194,16 @@ class EnumMeta(type): args = (value, ) else: args = value + if member_type is tuple: # special case for tuple enums args = (args, ) # wrap it one more time + if not use_args: - enum_member = __new__(enum_class) + enum_member = new(enum_class) if not hasattr(enum_member, '_value_'): enum_member._value_ = value else: - enum_member = __new__(enum_class, *args) + enum_member = new(enum_class, *args) if not hasattr(enum_member, '_value_'): if member_type is object: enum_member._value_ = value @@ -214,6 +213,7 @@ class EnumMeta(type): enum_member._name_ = member_name enum_member.__objclass__ = enum_class enum_member.__init__(*args) + # If another member with the same value was already defined, the # new member becomes an alias to the existing one. for name, canonical_member in enum_class._member_map_.items(): @@ -223,11 +223,13 @@ class EnumMeta(type): else: # Aliases don't appear in member names (only in __members__). enum_class._member_names_.append(member_name) + # performance boost for any member that would not shadow # a DynamicClassAttribute if member_name not in base_attributes: setattr(enum_class, member_name, enum_member) # now add to _member_map_ + enum_class._member_map_[member_name] = enum_member try: # This may fail if value is not hashable. We can't add the value @@ -370,8 +372,6 @@ class EnumMeta(type): if name in member_map: raise AttributeError('Cannot reassign members.') - pk('set',name) - super().__setattr__(name, value) @@ -522,6 +522,7 @@ class EnumMeta(type): return __new__, save_new, use_args +pk('enum') class Enum(metaclass=EnumMeta): """Generic enumeration. @@ -529,7 +530,6 @@ class Enum(metaclass=EnumMeta): Derive from this class to define new enumerations. """ - pk(1) def __new__(cls, value): # all enum instances are actually created during class construction @@ -551,8 +551,6 @@ class Enum(metaclass=EnumMeta): # still not found -- try _missing_ hook return cls._missing_(value) - pk(2) - def _generate_next_value_(name, start, count, last_values): for last_value in reversed(last_values): try: @@ -562,8 +560,6 @@ class Enum(metaclass=EnumMeta): else: return start - pk(3) - @classmethod def _missing_(cls, value): raise ValueError("%r is not a valid %s" % (value, cls.__name__)) @@ -583,7 +579,7 @@ class Enum(metaclass=EnumMeta): if m[0] != '_' and m not in self._member_map_ ] return (['__class__', '__doc__', '__module__'] + added_behavior) - pk(4) + def __format__(self, format_spec): # mixed-in Enums should use the mixed-in type's __format__, otherwise # we can get strange results with the Enum name showing up instead of @@ -611,7 +607,7 @@ class Enum(metaclass=EnumMeta): # to have members named `name` and `value`. This works because enumeration # members are not set directly on the enum class -- __getattr__ is # used to look them up. - pk(5) + @DynamicClassAttribute def name(self): """The name of the Enum member.""" @@ -658,6 +654,7 @@ class Enum(metaclass=EnumMeta): module_globals[name] = cls return cls +pk('intenum') class IntEnum(int, Enum): """Enum where members are also (and must be) ints""" @@ -666,6 +663,7 @@ class IntEnum(int, Enum): def _reduce_ex_by_name(self, proto): return self.name +pk('flag') class Flag(Enum): """Support for flags""" @@ -773,7 +771,8 @@ class Flag(Enum): ] inverted = reduce(_or_, inverted_members, self.__class__(0)) return self.__class__(inverted) - + +pk('intflag') class IntFlag(int, Flag): """Support for integer-based Flags""" @@ -837,6 +836,8 @@ class IntFlag(int, Flag): def __invert__(self): result = self.__class__(~self._value_) return result + +pk('rest') def _high_bit(value): """returns index of highest bit, or -1 if value is zero or negative""" diff --git a/modules/language/python/module/python.scm b/modules/language/python/module/python.scm index 1a90757..7b01c93 100644 --- a/modules/language/python/module/python.scm +++ b/modules/language/python/module/python.scm @@ -324,7 +324,13 @@ (define-python-class StaticMethod ()) (define-python-class Funcobj ()) +(define-method (py-mod (s <string>) l) + (let* ((s (py-replace s "%s" "~a")) + (s (py-replace s "%r" "~a")) + (l (for ((x : l)) ((r '())) + (cons x r) + #:final (reverse r)))) + (apply (@ (guile) format) #f s l))) - diff --git a/modules/language/python/string.scm b/modules/language/python/string.scm index f94580c..ff90ef1 100644 --- a/modules/language/python/string.scm +++ b/modules/language/python/string.scm @@ -56,7 +56,9 @@ (define-method (f (o <py-string>) . l) (apply f (slot-ref o 'str) l)))) (define-py0 (pylist-ref s i) - (list->string (list (string-ref s i)))) + (list->string (list (string-ref s (if (< i 0) + (+ (len s) i) + i))))) (define-py0 (bool s) (not (= (len s) 0))) |