unofficial mirror of guile-devel@gnu.org 
 help / color / mirror / Atom feed
* [PATCH 0/4] Support ECMAScript Test262 Assertion Harness
@ 2020-10-28  4:03 Sean Lynch
  2020-10-28  4:03 ` [PATCH 1/4] Support ecmascript return operator with no operand Sean Lynch
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Sean Lynch @ 2020-10-28  4:03 UTC (permalink / raw)
  To: guile-devel; +Cc: Sean Lynch

Hello all,

I've been hacking a bit on the ECMAScript implementation and thought it
might be useful to be able to run the ECMAScript Test262 test suite, so
I implemented just enough to be able to load the assertion harness
required by all tests. I thought I'd check in to see if there was any
interest in merging these changes.

The relevant harness files can be found here:
https://github.com/tc39/test262/blob/main/harness/sta.js
https://github.com/tc39/test262/blob/main/harness/assert.js

I plan to slowly use the test suite as a guide to increasing the
ECMAScript coverage, and as such if anyone has any thoughts about other
improvements to the ECMAScript compiler I would be all ears!

Happy Hacking!
Sean

Sean Lynch (4):
  Support ecmascript return operator with no operand.
  Implement ecmascript try/catch.
  Implement ecmascript function prototype.
  Fix some reserved word usages in ecmascript implementation

 .../language/ecmascript/compile-tree-il.scm   | 39 +++++++--
 module/language/ecmascript/function.scm       |  7 +-
 module/language/ecmascript/impl.scm           | 18 +++-
 module/language/ecmascript/parse.scm          | 51 +++++++++--
 module/language/ecmascript/tokenize.scm       | 84 +++++++------------
 5 files changed, 130 insertions(+), 69 deletions(-)

-- 
2.29.1




^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 1/4] Support ecmascript return operator with no operand.
  2020-10-28  4:03 [PATCH 0/4] Support ECMAScript Test262 Assertion Harness Sean Lynch
@ 2020-10-28  4:03 ` Sean Lynch
  2020-10-28  4:03 ` [PATCH 2/4] Implement ecmascript try/catch Sean Lynch
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Sean Lynch @ 2020-10-28  4:03 UTC (permalink / raw)
  To: guile-devel; +Cc: Sean Lynch

* module/language/ecmascript/compile-tree-il.scm: Support return
  operator with no operand.
---
 module/language/ecmascript/compile-tree-il.scm | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/module/language/ecmascript/compile-tree-il.scm b/module/language/ecmascript/compile-tree-il.scm
index d61f7120d..074674142 100644
--- a/module/language/ecmascript/compile-tree-il.scm
+++ b/module/language/ecmascript/compile-tree-il.scm
@@ -375,6 +375,8 @@
       ((call ,proc ,args)
        `(call ,(comp proc e)                
               ,@(map (lambda (x) (comp x e)) args)))
+      ((return)
+       (return (@implv *undefined*)))
       ((return ,expr)
        (return (comp expr e)))
       ((array . ,args)
-- 
2.29.1




^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 2/4] Implement ecmascript try/catch.
  2020-10-28  4:03 [PATCH 0/4] Support ECMAScript Test262 Assertion Harness Sean Lynch
  2020-10-28  4:03 ` [PATCH 1/4] Support ecmascript return operator with no operand Sean Lynch
@ 2020-10-28  4:03 ` Sean Lynch
  2020-10-28  4:03 ` [PATCH 3/4] Implement ecmascript function prototype Sean Lynch
  2020-10-28  4:03 ` [PATCH 4/4] Fix some reserved word usages in ecmascript implementation Sean Lynch
  3 siblings, 0 replies; 5+ messages in thread
From: Sean Lynch @ 2020-10-28  4:03 UTC (permalink / raw)
  To: guile-devel; +Cc: Sean Lynch

Implement ecmascript try/catch using
with-exception-handler/rais-exception respectively so that it is
straight-forward to interact with ecmascript exceptions from scheme.

* module/language/ecmascript/compile-tree-il.scm: Compile try/catch
* module/language/ecmascript/impl.scm: Provide js-try and js-catch
  procedures
---
 .../language/ecmascript/compile-tree-il.scm   | 25 +++++++++++++++++++
 module/language/ecmascript/impl.scm           | 18 ++++++++++++-
 2 files changed, 42 insertions(+), 1 deletion(-)

diff --git a/module/language/ecmascript/compile-tree-il.scm b/module/language/ecmascript/compile-tree-il.scm
index 074674142..6f6af5210 100644
--- a/module/language/ecmascript/compile-tree-il.scm
+++ b/module/language/ecmascript/compile-tree-il.scm
@@ -355,6 +355,31 @@
               ,(with-return-prompt
                 (lambda ()
                   (comp-body e body formals syms))))))))
+      ((try (block . ,body)
+            (catch ,err (block . ,catch))
+            ,finally)
+       (let ((err-sym (gensym (symbol->string err))))
+        `(call ,(@implv js-try)
+               (lambda ()
+                 (lambda-case
+                   ((() #f #f #f () ())
+                    (begin ,@(map (lambda (x) (comp x e)) body)))))
+               (lambda ((,err . ,err-sym))
+                 (lambda-case
+                   (((,err) #f #f #f () (,err-sym))
+                    ,(let ((e (econs err err-sym e)))
+                       `(begin ,@(map (lambda (x) (comp x e)) catch))))))
+               (lambda ()
+                 (lambda-case
+                   ((() #f #f #f () ())
+                    ,(pmatch/source finally
+                       ((finally (block . ,finally))
+                        `(begin ,@(map (lambda (x) (comp x e)) finally)))
+                       (#f '(void))
+                       (else (error "syntax error: invalid try statement: " x)))))))))
+      ((throw ,expr)
+       `(call ,(@implv js-throw)
+              ,(comp expr e)))
       ((call/this ,obj ,prop . ,args)
        (@impl call/this*
               obj
diff --git a/module/language/ecmascript/impl.scm b/module/language/ecmascript/impl.scm
index 27c077aed..b1be63403 100644
--- a/module/language/ecmascript/impl.scm
+++ b/module/language/ecmascript/impl.scm
@@ -33,7 +33,9 @@
             shift
             mod
             band bxor bior
-            make-enumerator))
+            make-enumerator
+            js-throw
+            js-try))
 
 
 (define-class <js-module-object> (<js-object>)
@@ -87,6 +89,20 @@
          (fluid-set! *this* (make <js-global-object>))
          (init-js-bindings! (current-module)))))
 
+(define (js-throw obj)
+  (raise-exception obj #:continuable? #t))
+
+(define (js-try body-thunk catch-handler finally-thunk)
+  (with-exception-handler (lambda (e) 
+                            (catch-handler e)
+                            (finally-thunk)
+                            *undefined*)
+                          (lambda ()
+                            (body-thunk)
+                            (finally-thunk)
+                            *undefined*)
+                          #:unwind? #t))
+
 (define (get-this)
   (fluid-ref *this*))
 
-- 
2.29.1




^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 3/4] Implement ecmascript function prototype.
  2020-10-28  4:03 [PATCH 0/4] Support ECMAScript Test262 Assertion Harness Sean Lynch
  2020-10-28  4:03 ` [PATCH 1/4] Support ecmascript return operator with no operand Sean Lynch
  2020-10-28  4:03 ` [PATCH 2/4] Implement ecmascript try/catch Sean Lynch
@ 2020-10-28  4:03 ` Sean Lynch
  2020-10-28  4:03 ` [PATCH 4/4] Fix some reserved word usages in ecmascript implementation Sean Lynch
  3 siblings, 0 replies; 5+ messages in thread
From: Sean Lynch @ 2020-10-28  4:03 UTC (permalink / raw)
  To: guile-devel; +Cc: Sean Lynch

Per section 19.2.4.3 of the 2020 ECMAScript specification, functions
that can be used as a constructor must have a fresh prototype.

* module/language/ecmascript/compile-tree-il.scm: Use make-js-function
  procedure when creating an ecmascript function. This provides the
  function with a fresh prototype.
* module/language/ecmascript/function.scm: Adds a make-js-function
  procedure that given a procedure provides a program-wrapper with a
  fresh prototype object, and optionally a name property.
---
 module/language/ecmascript/compile-tree-il.scm | 12 +++++++-----
 module/language/ecmascript/function.scm        |  7 ++++++-
 2 files changed, 13 insertions(+), 6 deletions(-)

diff --git a/module/language/ecmascript/compile-tree-il.scm b/module/language/ecmascript/compile-tree-il.scm
index 6f6af5210..48dca3166 100644
--- a/module/language/ecmascript/compile-tree-il.scm
+++ b/module/language/ecmascript/compile-tree-il.scm
@@ -19,6 +19,7 @@
 ;;; Code:
 
 (define-module (language ecmascript compile-tree-il)
+  #:use-module (language ecmascript function)
   #:use-module (language tree-il)
   #:use-module (ice-9 receive)
   #:use-module (system base pmatch)
@@ -349,12 +350,13 @@
        (let ((syms (map (lambda (x)
                           (gensym (string-append (symbol->string x) " ")))
                         formals)))
-         `(lambda ()
-            (lambda-case
-             ((() ,formals #f #f ,(map (lambda (x) (@implv *undefined*)) formals) ,syms)
-              ,(with-return-prompt
+         `(call (@ (language ecmascript function) make-js-function)
                 (lambda ()
-                  (comp-body e body formals syms))))))))
+                  (lambda-case
+                    ((() ,formals #f #f ,(map (lambda (x) (@implv *undefined*)) formals) ,syms)
+                     ,(with-return-prompt
+                        (lambda ()
+                          (comp-body e body formals syms)))))))))
       ((try (block . ,body)
             (catch ,err (block . ,catch))
             ,finally)
diff --git a/module/language/ecmascript/function.scm b/module/language/ecmascript/function.scm
index 72edc4e61..fd0b980b6 100644
--- a/module/language/ecmascript/function.scm
+++ b/module/language/ecmascript/function.scm
@@ -21,8 +21,13 @@
 (define-module (language ecmascript function)
   #:use-module (oop goops)
   #:use-module (language ecmascript base)
-  #:export (*function-prototype* *program-wrappers*))
+  #:export (*function-prototype* *program-wrappers*
+            make-js-function))
 
+(define* (make-js-function proc #:optional name)
+ (pput proc 'prototype (make <js-object>))
+ (pput proc 'name (or name ""))
+ proc)
 
 (define-class <js-program-wrapper> (<js-object>))
 
-- 
2.29.1




^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 4/4] Fix some reserved word usages in ecmascript implementation
  2020-10-28  4:03 [PATCH 0/4] Support ECMAScript Test262 Assertion Harness Sean Lynch
                   ` (2 preceding siblings ...)
  2020-10-28  4:03 ` [PATCH 3/4] Implement ecmascript function prototype Sean Lynch
@ 2020-10-28  4:03 ` Sean Lynch
  3 siblings, 0 replies; 5+ messages in thread
From: Sean Lynch @ 2020-10-28  4:03 UTC (permalink / raw)
  To: guile-devel; +Cc: Sean Lynch

Reserved words are valid ecmascript in certain contexts, referred to
by the IdentifierName syntax rule. For example, while throw is a
keyword, using throw as a property accessor such as foo.throw is valid.
While this implementation isn't quite correct, it is an improvement. For
an example of how this might be incorrect, it will reject the expression
super.foo uncoditionally, however, that expression is valid inside a
member function of a class.

Further, the *keywords* alist is now updated to the that specified by
ECMAScript 2020, and *future-reserved-words* is merged into *keywords*
because in the end the only item that wouldn't be a keyword seems to be
enum.

* module/language/ecmascript/parse.scm: Add IdentifierName production
  that includes reserved word list.
* module/language/ecmascript/tokenize.scm: Update reserved word list and
  do not error upon encountering one. The parser will be responsible for
  rejecting an illegal usage of a reserved word.
---
 module/language/ecmascript/parse.scm    | 51 +++++++++++++--
 module/language/ecmascript/tokenize.scm | 84 +++++++++----------------
 2 files changed, 73 insertions(+), 62 deletions(-)

diff --git a/module/language/ecmascript/parse.scm b/module/language/ecmascript/parse.scm
index be41e4b9c..8fff96f54 100644
--- a/module/language/ecmascript/parse.scm
+++ b/module/language/ecmascript/parse.scm
@@ -55,9 +55,9 @@
     > <= >= == != === !== + - * % ++ -- << >> >>> & bor ^ ! ~ && or ? 
     colon = += -= *= %= <<= >>= >>>= &= bor= ^= / /=
 
-    break else new var case finally return void catch for switch while
-    continue function this with default if throw delete in try do
-    instanceof typeof null true false
+    await break case catch class const continue debugger default delete do else
+    enum export extends false finally for function if import in instanceof new
+    null return super switch this throw true try typeof var void while with yield
 
     Identifier StringLiteral NumericLiteral RegexpLiteral)
 
@@ -65,6 +65,45 @@
    (Program (SourceElements) : $1
             (*eoi*) : *eof-object*)
 
+   (IdentifierName (Identifier) : $1
+                   (await) : $1 
+                   (break) : $1
+                   (case) : $1
+                   (catch) : $1
+                   (class) : $1
+                   (const) : $1
+                   (continue) : $1
+                   (debugger) : $1
+                   (default) : $1
+                   (delete) : $1
+                   (do) : $1
+                   (else) : $1
+                   (enum) : $1
+                   (export) : $1
+                   (extends) : $1
+                   (false) : $1
+                   (finally) : $1
+                   (for) : $1
+                   (function) : $1
+                   (if) : $1
+                   (import) : $1
+                   (in) : $1
+                   (instanceof) : $1
+                   (new) : $1
+                   (null) : $1
+                   (return) : $1
+                   (super) : $1
+                   (switch) : $1
+                   (this) : $1
+                   (throw) : $1
+                   (true) : $1
+                   (try) : $1
+                   (typeof) : $1
+                   (var) : $1
+                   (void) : $1
+                   (while) : $1
+                   (with) : $1
+                   (yield) : $1)
    ;;
    ;; Verily, here we define statements. Expressions are defined
    ;; afterwards.
@@ -218,14 +257,14 @@
                   (lbrace PropertyNameAndValueList rbrace) : `(object ,@$2))
    (PropertyNameAndValueList (PropertyName colon AssignmentExpression) : `((,$1 ,$3))
                              (PropertyNameAndValueList comma PropertyName colon AssignmentExpression) : `(,@$1 (,$3 ,$5)))
-   (PropertyName (Identifier) : $1
+   (PropertyName (IdentifierName) : $1
                  (StringLiteral) : (string->symbol $1)
                  (NumericLiteral) : $1)
 
    (MemberExpression (PrimaryExpression) : $1
                      (FunctionExpression) : $1
                      (MemberExpression lbracket Expression rbracket) : `(aref ,$1 ,$3)
-                     (MemberExpression dot Identifier) : `(pref ,$1 ,$3)
+                     (MemberExpression dot IdentifierName) : `(pref ,$1 ,$3)
                      (new MemberExpression Arguments) : `(new ,$2 ,$3))
 
    (NewExpression (MemberExpression) : $1
@@ -234,7 +273,7 @@
    (CallExpression (MemberExpression Arguments) : `(call ,$1 ,$2)
                    (CallExpression Arguments) : `(call ,$1 ,$2)
                    (CallExpression lbracket Expression rbracket) : `(aref ,$1 ,$3)
-                   (CallExpression dot Identifier) : `(pref ,$1 ,$3))
+                   (CallExpression dot IdentifierName) : `(pref ,$1 ,$3))
    (Arguments (lparen rparen) : '()
               (lparen ArgumentList rparen) : $2)
    (ArgumentList (AssignmentExpression) : `(,$1)
diff --git a/module/language/ecmascript/tokenize.scm b/module/language/ecmascript/tokenize.scm
index 8289b950c..cbae3bbe4 100644
--- a/module/language/ecmascript/tokenize.scm
+++ b/module/language/ecmascript/tokenize.scm
@@ -173,69 +173,44 @@
                           loc str))))))))
 
 (define *keywords*
-  '(("break" . break)
-    ("else" . else)
-    ("new" . new)
-    ("var" . var)
+  '(("await" . await) 
+    ("break" . break)
     ("case" . case)
-    ("finally" . finally)
-    ("return" . return)
-    ("void" . void)
     ("catch" . catch)
-    ("for" . for)
-    ("switch" . switch)
-    ("while" . while)
+    ("class" . class)
+    ("const" . const)
     ("continue" . continue)
-    ("function" . function)
-    ("this" . this)
-    ("with" . with)
+    ("debugger" . debugger)
     ("default" . default)
-    ("if" . if)
-    ("throw" . throw)
     ("delete" . delete)
-    ("in" . in)
-    ("try" . try)
     ("do" . do)
-    ("instanceof" . instanceof)
-    ("typeof" . typeof)
-
-    ;; these aren't exactly keywords, but hey
-    ("null" . null)
-    ("true" . true)
-    ("false" . false)))
-
-(define *future-reserved-words*
-  '(("abstract" . abstract)
+    ("else" . else)
     ("enum" . enum)
-    ("int" . int)
-    ("short" . short)
-    ("boolean" . boolean)
     ("export" . export)
-    ("interface" . interface)
-    ("static" . static)
-    ("byte" . byte)
     ("extends" . extends)
-    ("long" . long)
-    ("super" . super)
-    ("char" . char)
-    ("final" . final)
-    ("native" . native)
-    ("synchronized" . synchronized)
-    ("class" . class)
-    ("float" . float)
-    ("package" . package)
-    ("throws" . throws)
-    ("const" . const)
-    ("goto" . goto)
-    ("private" . private)
-    ("transient" . transient)
-    ("debugger" . debugger)
-    ("implements" . implements)
-    ("protected" . protected)
-    ("volatile" . volatile)
-    ("double" . double)
+    ("false" . false)
+    ("finally" . finally)
+    ("for" . for)
+    ("function" . function)
+    ("if" . if)
     ("import" . import)
-    ("public" . public)))
+    ("in" . in)
+    ("instanceof" . instanceof)
+    ("new" . new)
+    ("null" . null)
+    ("return" . return)
+    ("super" . super)
+    ("switch" . switch)
+    ("this" . this)
+    ("throw" . throw)
+    ("true" . true)
+    ("try" . try)
+    ("typeof" . typeof)
+    ("var" . var)
+    ("void" . void)
+    ("while" . while)
+    ("with" . with)
+    ("yield" . yield)))
 
 (define (read-identifier port loc)
   (let lp ((c (peek-char port)) (chars '()))
@@ -247,9 +222,6 @@
         (let ((word (list->string (reverse chars))))
           (cond ((assoc-ref *keywords* word)
                  => (lambda (x) (make-lexical-token x loc #f)))
-                ((assoc-ref *future-reserved-words* word)
-                 (syntax-error "word is reserved for the future, dude."
-                               loc word))
                 (else (make-lexical-token 'Identifier loc
                                           (string->symbol word)))))
         (begin (read-char port)
-- 
2.29.1




^ permalink raw reply related	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2020-10-28  4:03 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-10-28  4:03 [PATCH 0/4] Support ECMAScript Test262 Assertion Harness Sean Lynch
2020-10-28  4:03 ` [PATCH 1/4] Support ecmascript return operator with no operand Sean Lynch
2020-10-28  4:03 ` [PATCH 2/4] Implement ecmascript try/catch Sean Lynch
2020-10-28  4:03 ` [PATCH 3/4] Implement ecmascript function prototype Sean Lynch
2020-10-28  4:03 ` [PATCH 4/4] Fix some reserved word usages in ecmascript implementation Sean Lynch

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).