array.scm 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. ;;; ECMAScript for Guile
  2. ;; Copyright (C) 2009, 2010 Free Software Foundation, Inc.
  3. ;;;; This library is free software; you can redistribute it and/or
  4. ;;;; modify it under the terms of the GNU Lesser General Public
  5. ;;;; License as published by the Free Software Foundation; either
  6. ;;;; version 3 of the License, or (at your option) any later version.
  7. ;;;;
  8. ;;;; This library is distributed in the hope that it will be useful,
  9. ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. ;;;; Lesser General Public License for more details.
  12. ;;;;
  13. ;;;; You should have received a copy of the GNU Lesser General Public
  14. ;;;; License along with this library; if not, write to the Free Software
  15. ;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  16. ;;; Code:
  17. (define-module (language ecmascript array)
  18. #:use-module (oop goops)
  19. #:use-module (language ecmascript base)
  20. #:use-module (language ecmascript function)
  21. #:export (*array-prototype* new-array))
  22. (define-class <js-array-object> (<js-object>)
  23. (vector #:init-value #() #:accessor js-array-vector #:init-keyword #:vector))
  24. (define (new-array . vals)
  25. (let ((o (make <js-array-object> #:class "Array"
  26. #:prototype *array-prototype*)))
  27. (pput o 'length (length vals))
  28. (let ((vect (js-array-vector o)))
  29. (let lp ((i 0) (vals vals))
  30. (cond ((not (null? vals))
  31. (vector-set! vect i (car vals))
  32. (lp (1+ i) (cdr vals)))
  33. (else o))))))
  34. (define *array-prototype* (make <js-object> #:class "Array"
  35. #:value new-array
  36. #:constructor new-array))
  37. (hashq-set! *program-wrappers* new-array *array-prototype*)
  38. (pput *array-prototype* 'prototype *array-prototype*)
  39. (pput *array-prototype* 'constructor new-array)
  40. (define-method (pget (o <js-array-object>) p)
  41. (cond ((and (integer? p) (exact? p) (>= p 0))
  42. (let ((v (js-array-vector o)))
  43. (if (< p (vector-length v))
  44. (vector-ref v p)
  45. (next-method))))
  46. ((or (and (symbol? p) (eq? p 'length))
  47. (and (string? p) (string=? p "length")))
  48. (vector-length (js-array-vector o)))
  49. (else (next-method))))
  50. (define-method (pput (o <js-array-object>) p v)
  51. (cond ((and (integer? p) (exact? p) (>= 0 p))
  52. (let ((vect (js-array-vector o)))
  53. (if (< p (vector-length vect))
  54. (vector-set! vect p v)
  55. ;; Fixme: round up to powers of 2?
  56. (let ((new (make-vector (1+ p) 0)))
  57. (vector-move-left! vect 0 (vector-length vect) new 0)
  58. (set! (js-array-vector o) new)
  59. (vector-set! new p v)))))
  60. ((or (and (symbol? p) (eq? p 'length))
  61. (and (string? p) (string=? p "length")))
  62. (let ((vect (js-array-vector o)))
  63. (let ((new (make-vector (->uint32 v) 0)))
  64. (vector-move-left! vect 0 (min (vector-length vect) (->uint32 v))
  65. new 0)
  66. (set! (js-array-vector o) new))))
  67. (else (next-method))))
  68. (define-js-method *array-prototype* (toString)
  69. (format #f "~A" (js-array-vector this)))
  70. (define-js-method *array-prototype* (concat . rest)
  71. (let* ((len (apply + (->uint32 (pget this 'length))
  72. (map (lambda (x) (->uint32 (pget x 'length)))
  73. rest)))
  74. (rv (make-vector len 0)))
  75. (let lp ((objs (cons this rest)) (i 0))
  76. (cond ((null? objs) (make <js-array-object> #:class "Array"
  77. #:prototype *array-prototype*
  78. #:vector rv))
  79. ((is-a? (car objs) <js-array-object>)
  80. (let ((v (js-array-vector (car objs))))
  81. (vector-move-left! v 0 (vector-length v)
  82. rv i)
  83. (lp (cdr objs) (+ i (vector-length v)))))
  84. (else
  85. (error "generic array concats not yet implemented"))))))
  86. (define-js-method *array-prototype* (join . separator)
  87. (let lp ((i (1- (->uint32 (pget this 'length)))) (l '()))
  88. (if (< i 0)
  89. (string-join l (if separator (->string (car separator)) ","))
  90. (lp (1+ i)
  91. (cons (->string (pget this i)) l)))))
  92. (define-js-method *array-prototype* (pop)
  93. (let ((len (->uint32 (pget this 'length))))
  94. (if (zero? len)
  95. *undefined*
  96. (let ((ret (pget this (1- len))))
  97. (pput this 'length (1- len))
  98. ret))))
  99. (define-js-method *array-prototype* (push . args)
  100. (let lp ((args args))
  101. (if (null? args)
  102. (->uint32 (pget this 'length))
  103. (begin (pput this (->uint32 (pget this 'length)) (car args))
  104. (lp (cdr args))))))