Fix parsing setters/getters (allow keywords for name).
authorMihai Bazon <mihai@bazon.net>
Wed, 30 Oct 2013 09:50:22 +0000 (11:50 +0200)
committerMihai Bazon <mihai@bazon.net>
Wed, 30 Oct 2013 09:50:22 +0000 (11:50 +0200)
The "key" property was always "set" or "get", which didn't make much sense.
Now it'll be the actual name of the setter/getter (AST_Node), and the
AST_Accessor object itself, which represents the function, won't store any
name.

Close #319

lib/ast.js
lib/output.js
lib/parse.js

index 1e6c836..0fa48e2 100644 (file)
@@ -371,7 +371,7 @@ var AST_Lambda = DEFNODE("Lambda", "name argnames uses_arguments", {
 }, AST_Scope);
 
 var AST_Accessor = DEFNODE("Accessor", null, {
-    $documentation: "A setter/getter function"
+    $documentation: "A setter/getter function.  The `name` property is always null."
 }, AST_Lambda);
 
 var AST_Function = DEFNODE("Function", null, {
@@ -756,7 +756,7 @@ var AST_Object = DEFNODE("Object", "properties", {
 var AST_ObjectProperty = DEFNODE("ObjectProperty", "key value", {
     $documentation: "Base class for literal object properties",
     $propdoc: {
-        key: "[string] the property name; it's always a plain string in our AST, no matter if it was a string, number or identifier in original code",
+        key: "[string] the property name converted to a string for ObjectKeyVal.  For setters and getters this is an arbitrary AST_Node.",
         value: "[AST_Node] property value.  For setters and getters this is an AST_Function."
     },
     _walk: function(visitor) {
index abf57b5..7f88d1f 100644 (file)
@@ -1066,10 +1066,14 @@ function OutputStream(options) {
     });
     DEFPRINT(AST_ObjectSetter, function(self, output){
         output.print("set");
+        output.space();
+        self.key.print(output);
         self.value._do_print(output, true);
     });
     DEFPRINT(AST_ObjectGetter, function(self, output){
         output.print("get");
+        output.space();
+        self.key.print(output);
         self.value._do_print(output, true);
     });
     DEFPRINT(AST_Symbol, function(self, output){
index 3ccdec8..4933649 100644 (file)
@@ -789,7 +789,7 @@ function parse($TEXT, options) {
                 return for_();
 
               case "function":
-                return function_(true);
+                return function_(AST_Defun);
 
               case "if":
                 return if_();
@@ -933,19 +933,12 @@ function parse($TEXT, options) {
         });
     };
 
-    var function_ = function(in_statement, ctor) {
-        var is_accessor = ctor === AST_Accessor;
-        var name = (is("name") ? as_symbol(in_statement
-                                           ? AST_SymbolDefun
-                                           : is_accessor
-                                           ? AST_SymbolAccessor
-                                           : AST_SymbolLambda)
-                    : is_accessor && (is("string") || is("num")) ? as_atom_node()
-                    : null);
+    var function_ = function(ctor) {
+        var in_statement = ctor === AST_Defun;
+        var name = is("name") ? as_symbol(in_statement ? AST_SymbolDefun : AST_SymbolLambda) : null;
         if (in_statement && !name)
             unexpected();
         expect("(");
-        if (!ctor) ctor = in_statement ? AST_Defun : AST_Function;
         return new ctor({
             name: name,
             argnames: (function(first, a){
@@ -1116,7 +1109,9 @@ function parse($TEXT, options) {
         var tok = S.token, ret;
         switch (tok.type) {
           case "name":
-            return as_symbol(AST_SymbolRef);
+          case "keyword":
+            ret = _make_symbol(AST_SymbolRef);
+            break;
           case "num":
             ret = new AST_Number({ start: tok, end: tok, value: tok.value });
             break;
@@ -1167,7 +1162,7 @@ function parse($TEXT, options) {
         }
         if (is("keyword", "function")) {
             next();
-            var func = function_(false);
+            var func = function_(AST_Function);
             func.start = start;
             func.end = prev();
             return subscripts(func, allow_calls);
@@ -1215,8 +1210,8 @@ function parse($TEXT, options) {
                 if (name == "get") {
                     a.push(new AST_ObjectGetter({
                         start : start,
-                        key   : name,
-                        value : function_(false, AST_Accessor),
+                        key   : as_atom_node(),
+                        value : function_(AST_Accessor),
                         end   : prev()
                     }));
                     continue;
@@ -1224,8 +1219,8 @@ function parse($TEXT, options) {
                 if (name == "set") {
                     a.push(new AST_ObjectSetter({
                         start : start,
-                        key   : name,
-                        value : function_(false, AST_Accessor),
+                        key   : as_atom_node(),
+                        value : function_(AST_Accessor),
                         end   : prev()
                     }));
                     continue;
@@ -1273,17 +1268,21 @@ function parse($TEXT, options) {
         }
     };
 
+    function _make_symbol(type) {
+        var name = S.token.value;
+        return new (name == "this" ? AST_This : type)({
+            name  : String(name),
+            start : S.token,
+            end   : S.token
+        });
+    };
+
     function as_symbol(type, noerror) {
         if (!is("name")) {
             if (!noerror) croak("Name expected");
             return null;
         }
-        var name = S.token.value;
-        var sym = new (name == "this" ? AST_This : type)({
-            name  : String(S.token.value),
-            start : S.token,
-            end   : S.token
-        });
+        var sym = _make_symbol(type);
         next();
         return sym;
     };