impl.scm 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. ;;; ECMAScript for Guile
  2. ;; Copyright (C) 2009 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 impl)
  18. #:use-module (oop goops)
  19. #:use-module (language ecmascript base)
  20. #:use-module (language ecmascript function)
  21. #:use-module (language ecmascript array)
  22. #:re-export (*undefined* *this* call/this*
  23. pget pput pdel has-property?
  24. ->boolean ->number
  25. new-object new new-array)
  26. #:export (js-init get-this
  27. typeof
  28. bitwise-not logical-not
  29. shift
  30. mod
  31. band bxor bior
  32. make-enumerator))
  33. (define-class <js-module-object> (<js-object>)
  34. (module #:init-form (current-module) #:init-keyword #:module
  35. #:getter js-module))
  36. (define-method (pget (o <js-module-object>) (p <string>))
  37. (pget o (string->symbol p)))
  38. (define-method (pget (o <js-module-object>) (p <symbol>))
  39. (let ((v (module-variable (js-module o) p)))
  40. (if v
  41. (variable-ref v)
  42. (next-method))))
  43. (define-method (pput (o <js-module-object>) (p <string>) v)
  44. (pput o (string->symbol p) v))
  45. (define-method (pput (o <js-module-object>) (p <symbol>) v)
  46. (module-define! (js-module o) p v))
  47. (define-method (prop-attrs (o <js-module-object>) (p <symbol>))
  48. (cond ((module-local-variable (js-module o) p) '())
  49. ((module-variable (js-module o) p) '(DontDelete ReadOnly))
  50. (else (next-method))))
  51. (define-method (prop-attrs (o <js-module-object>) (p <string>))
  52. (prop-attrs o (string->symbol p)))
  53. (define-method (prop-keys (o <js-module-object>))
  54. (append (hash-map->list (lambda (k v) k) (module-obarray (js-module o)))
  55. (next-method)))
  56. ;; we could make a renamer, but having obj['foo-bar'] should be enough
  57. (define (js-require modstr)
  58. (make <js-module-object> #:module
  59. (resolve-interface (map string->symbol (string-split modstr #\.)))))
  60. (define-class <js-global-object> (<js-module-object>))
  61. (define-method (js-module (o <js-global-object>))
  62. (current-module))
  63. (define (init-js-bindings! mod)
  64. (module-define! mod 'NaN +nan.0)
  65. (module-define! mod 'Infinity +inf.0)
  66. (module-define! mod 'undefined *undefined*)
  67. (module-define! mod 'require js-require)
  68. ;; isNAN, isFinite, parseFloat, parseInt, eval
  69. ;; decodeURI, decodeURIComponent, encodeURI, encodeURIComponent
  70. ;; Object Function Array String Boolean Number Date RegExp Error EvalError
  71. ;; RangeError ReferenceError SyntaxError TypeError URIError
  72. (module-define! mod 'Object *object-prototype*)
  73. (module-define! mod 'Array *array-prototype*))
  74. (define (js-init)
  75. (cond ((get-this))
  76. (else
  77. (fluid-set! *this* (make <js-global-object>))
  78. (init-js-bindings! (current-module)))))
  79. (define (get-this)
  80. (fluid-ref *this*))
  81. (define (typeof x)
  82. (cond ((eq? x *undefined*) "undefined")
  83. ((null? x) "object")
  84. ((boolean? x) "boolean")
  85. ((number? x) "number")
  86. ((string? x) "string")
  87. ((procedure? x) "function")
  88. ((is-a? x <js-object>) "object")
  89. (else "scm")))
  90. (define bitwise-not lognot)
  91. (define (logical-not x)
  92. (not (->boolean (->primitive x))))
  93. (define shift ash)
  94. (define band logand)
  95. (define bxor logxor)
  96. (define bior logior)
  97. (define mod modulo)
  98. (define-method (+ (a <string>) (b <string>))
  99. (string-append a b))
  100. (define-method (+ (a <string>) b)
  101. (string-append a (->string b)))
  102. (define-method (+ a (b <string>))
  103. (string-append (->string a) b))
  104. (define-method (+ a b)
  105. (+ (->number a) (->number b)))
  106. (define-method (- a b)
  107. (- (->number a) (->number b)))
  108. (define-method (* a b)
  109. (* (->number a) (->number b)))
  110. (define-method (/ a b)
  111. (/ (->number a) (->number b)))
  112. (define-method (< a b)
  113. (< (->number a) (->number b)))
  114. (define-method (< (a <string>) (b <string>))
  115. (string< a b))
  116. (define-method (<= a b)
  117. (<= (->number a) (->number b)))
  118. (define-method (<= (a <string>) (b <string>))
  119. (string<= a b))
  120. (define-method (>= a b)
  121. (>= (->number a) (->number b)))
  122. (define-method (>= (a <string>) (b <string>))
  123. (string>= a b))
  124. (define-method (> a b)
  125. (> (->number a) (->number b)))
  126. (define-method (> (a <string>) (b <string>))
  127. (string> a b))
  128. (define (obj-and-prototypes o)
  129. (if o
  130. (cons o (obj-and-prototypes (js-prototype o)))
  131. '()))
  132. (define (make-enumerator obj)
  133. (let ((props (make-hash-table 23)))
  134. (for-each (lambda (o)
  135. (for-each (lambda (k) (hashq-set! props k #t))
  136. (prop-keys o)))
  137. (obj-and-prototypes obj))
  138. (apply new-array (filter (lambda (p)
  139. (not (prop-has-attr? obj p 'DontEnum)))
  140. (hash-map->list (lambda (k v) k) props)))))