;;; ECMAScript for Guile ;; Copyright (C) 2009 Free Software Foundation, Inc. ;;;; This library is free software; you can redistribute it and/or ;;;; modify it under the terms of the GNU Lesser General Public ;;;; License as published by the Free Software Foundation; either ;;;; version 3 of the License, or (at your option) any later version. ;;;; ;;;; This library is distributed in the hope that it will be useful, ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;;;; Lesser General Public License for more details. ;;;; ;;;; You should have received a copy of the GNU Lesser General Public ;;;; License along with this library; if not, write to the Free Software ;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ;;; Code: (define-module (language ecmascript impl) #:use-module (oop goops) #:use-module (language ecmascript base) #:use-module (language ecmascript function) #:use-module (language ecmascript array) #:re-export (*undefined* *this* call/this* pget pput pdel has-property? ->boolean ->number new-object new new-array) #:export (js-init get-this typeof bitwise-not logical-not shift mod band bxor bior make-enumerator)) (define-class () (module #:init-form (current-module) #:init-keyword #:module #:getter js-module)) (define-method (pget (o ) (p )) (pget o (string->symbol p))) (define-method (pget (o ) (p )) (let ((v (module-variable (js-module o) p))) (if v (variable-ref v) (next-method)))) (define-method (pput (o ) (p ) v) (pput o (string->symbol p) v)) (define-method (pput (o ) (p ) v) (module-define! (js-module o) p v)) (define-method (prop-attrs (o ) (p )) (cond ((module-local-variable (js-module o) p) '()) ((module-variable (js-module o) p) '(DontDelete ReadOnly)) (else (next-method)))) (define-method (prop-attrs (o ) (p )) (prop-attrs o (string->symbol p))) (define-method (prop-keys (o )) (append (hash-map->list (lambda (k v) k) (module-obarray (js-module o))) (next-method))) ;; we could make a renamer, but having obj['foo-bar'] should be enough (define (js-require modstr) (make #:module (resolve-interface (map string->symbol (string-split modstr #\.))))) (define-class ()) (define-method (js-module (o )) (current-module)) (define (init-js-bindings! mod) (module-define! mod 'NaN +nan.0) (module-define! mod 'Infinity +inf.0) (module-define! mod 'undefined *undefined*) (module-define! mod 'require js-require) ;; isNAN, isFinite, parseFloat, parseInt, eval ;; decodeURI, decodeURIComponent, encodeURI, encodeURIComponent ;; Object Function Array String Boolean Number Date RegExp Error EvalError ;; RangeError ReferenceError SyntaxError TypeError URIError (module-define! mod 'Object *object-prototype*) (module-define! mod 'Array *array-prototype*)) (define (js-init) (cond ((get-this)) (else (fluid-set! *this* (make )) (init-js-bindings! (current-module))))) (define (get-this) (fluid-ref *this*)) (define (typeof x) (cond ((eq? x *undefined*) "undefined") ((null? x) "object") ((boolean? x) "boolean") ((number? x) "number") ((string? x) "string") ((procedure? x) "function") ((is-a? x ) "object") (else "scm"))) (define bitwise-not lognot) (define (logical-not x) (not (->boolean (->primitive x)))) (define shift ash) (define band logand) (define bxor logxor) (define bior logior) (define mod modulo) (define-method (+ (a ) (b )) (string-append a b)) (define-method (+ (a ) b) (string-append a (->string b))) (define-method (+ a (b )) (string-append (->string a) b)) (define-method (+ a b) (+ (->number a) (->number b))) (define-method (- a b) (- (->number a) (->number b))) (define-method (* a b) (* (->number a) (->number b))) (define-method (/ a b) (/ (->number a) (->number b))) (define-method (< a b) (< (->number a) (->number b))) (define-method (< (a ) (b )) (string< a b)) (define-method (<= a b) (<= (->number a) (->number b))) (define-method (<= (a ) (b )) (string<= a b)) (define-method (>= a b) (>= (->number a) (->number b))) (define-method (>= (a ) (b )) (string>= a b)) (define-method (> a b) (> (->number a) (->number b))) (define-method (> (a ) (b )) (string> a b)) (define (obj-and-prototypes o) (if o (cons o (obj-and-prototypes (js-prototype o))) '())) (define (make-enumerator obj) (let ((props (make-hash-table 23))) (for-each (lambda (o) (for-each (lambda (k) (hashq-set! props k #t)) (prop-keys o))) (obj-and-prototypes obj)) (apply new-array (filter (lambda (p) (not (prop-has-attr? obj p 'DontEnum))) (hash-map->list (lambda (k v) k) props)))))