Correct implementations of orderby, limit, let, various fixes in AQLExpression core
diff --git a/asterix-app/src/main/resources/sdk/static/example/js/demo.js b/asterix-app/src/main/resources/sdk/static/example/js/demo.js
index 40ee0ad..9911844 100644
--- a/asterix-app/src/main/resources/sdk/static/example/js/demo.js
+++ b/asterix-app/src/main/resources/sdk/static/example/js/demo.js
@@ -205,8 +205,28 @@
                             alert(JSON.stringify(res));
                             $('#result10').html(res["results"]);
                           }
-        });
-        alert("EXPRESSION 10 " + expression10.val());
+        })
+        .bind( new ForClause("t", null, new AsterixExpression().set(["dataset TweetMessages"])))
+        //.bind( new GroupClause() );
+        .bind( new LetClause(
+            "c", 
+            new FunctionExpression(
+                { 
+                    "function" : "count",
+                    "expression" : new AsterixExpression().set(["$t"])
+                }
+            )
+        ))
+        .bind( new OrderbyClause( new AExpression().set("$c"), "desc" ) )
+        .bind( new LimitClause(new AsterixExpression().set(["3"])) )
+        .bind( new ReturnClause(
+            {
+                "user" : "$uid",
+                "count" : "$c"
+            }
+        ));
+
+        alert("EXPRESSION 10 \n" + expression10.val());
     });
 
     // 11 - Left Outer Fuzzy Join
diff --git a/asterix-app/src/main/resources/sdk/static/js/asterix-sdk-stable.js b/asterix-app/src/main/resources/sdk/static/js/asterix-sdk-stable.js
index 5197e6d..5392722 100644
--- a/asterix-app/src/main/resources/sdk/static/js/asterix-sdk-stable.js
+++ b/asterix-app/src/main/resources/sdk/static/js/asterix-sdk-stable.js
@@ -129,13 +129,42 @@
 };
 
 
+// Functions that can be used to call core expressions/clauses more cleanly
+function AFLWOGR () {
 
+}
 
+function AClause () {
 
+}
 
+function ALetClause () {
 
+}
 
+function AWhereClause () {
 
+}
+
+function AOrderbyClause () {
+
+}
+
+function AGroupClause () {
+
+}
+
+function ALimitClause () {
+
+}
+
+function ADistinctClause () {
+
+}
+
+function AVariable () {
+
+}
 
 // Temporary AsterixExpression Placeholder
 function AExpression () {
@@ -182,23 +211,24 @@
 
 AExpression.prototype.val = function() { 
 
+    var value = "";
+
     // If there is a dataverse defined, provide it.
     if (this._properties.hasOwnProperty("dataverse")) {
-        return "use dataverse " + this._properties["dataverse"] + ";\n";
-    } else {
-        return this.error("Missing dataverse.");
+        value += "use dataverse " + this._properties["dataverse"] + ";\n";
+    };
+
+    if (this._properties.hasOwnProperty("value")) {
+        value += this._properties["value"];
     }
+
+    return value;
 };
 
-
-AExpression.prototype.onReturn = function() {
-    var ret = "";    
-
-    if (this._properties.hasOwnProperty("return")) {
-        ret += this._properties["return"] + ";";
-    }
-
-    return ret;
+// @param expressionValue [String]
+AExpression.prototype.set = function(expressionValue) {
+    this._properties["value"] = expressionValue; 
+    return this;
 };
 
 
@@ -248,10 +278,7 @@
 };
 
 FunctionExpression.prototype.val = function () { 
-
-    var value = AExpression.prototype.val.call(this);
-
-    return value + this._properties["function"] + "(" + this._properties["expression"].val() + ");" + AExpression.prototype.onReturn.call(this); 
+    return this._properties["function"] + "(" + this._properties["expression"].val() + ")";
 };
 
 
@@ -308,13 +335,15 @@
 FLWOGRExpression.prototype.val = function() {
     var value = AExpression.prototype.val.call(this);
 
+    var clauseValues = [];
     for (var c in this._properties["clauses"]) {
-        value += this._properties["clauses"][c].val() + " ";
+        clauseValues.push(this._properties["clauses"][c].val());
     }
 
-    return value + AExpression.prototype.onReturn.call(this);
+    return value + clauseValues.join("\n") + ";";
 };
 
+
 // AQLClause
 //
 // Base Clause  ::= ForClause | LetClause | WhereClause | OrderbyClause | GroupClause | LimitClause | DistinctClause
@@ -405,6 +434,21 @@
     this._properties["clause"] = "return ";
     if (expression instanceof AExpression) {
         this._properties["clause"] += expression.val();
+    } else if ( Object.getPrototypeOf( expression ) === Object.prototype ) {
+        
+        this._properties["clause"] += "{";
+        var returnStatements = [];
+        for (returnValue in expression) {
+           
+            if (expression[returnValue] instanceof AExpression) { 
+                returnStatements.push(returnValue + " : " + expression[returnValue].val());            
+            } else if (typeof expression[returnValue] == "string") {          
+                returnStatements.push(returnValue + " : " + expression[returnValue]);   
+            }
+        }
+        this._properties["clause"] += returnStatements.join(",\n");
+        this._properties["clause"] += "}";  
+    
     } else {
         this._properties["clause"] += new AsterixExpression().set([expression]).val();
     }
@@ -415,14 +459,17 @@
 ReturnClause.prototype = Object.create(AQLClause.prototype);
 ReturnClause.prototype.constructor = ReturnClause;
 
+ReturnClause.prototype.val = function () {
+    return this._properties["clause"];  
+};
+
+
 // WhereClause
 //
 // Grammar: 
 // ::= "where" Expression
 // 
 // @param expression [BooleanExpression], pushes this expression onto the stack
-//
-// TODO Error fixing
 function WhereClause(expression) {
     AQLClause.call(this);
 
@@ -458,6 +505,80 @@
 }
 
 
+// LimitClause
+// Grammar:
+// LimitClause    ::= "limit" Expression ( "offset" Expression )?
+// 
+// @param   limitExpression [REQUIRED, AQLExpression]
+// @param   offsetExpression [OPTIONAL, AQLExpression]
+function LimitClause(limitExpression, offsetExpression) {
+
+    AQLClause.call(this);
+  
+    // limitExpression required
+    this._properties["clause"] = "limit " + limitExpression.val();
+
+    // Optional: Offset
+    var offset = typeof offsetExpression ? offsetExpression : null;
+    if (offset != null) {
+        this._properties["clause"] += " offset " + offsetExpression.val();
+    }
+
+    return this;
+}
+
+LimitClause.prototype = Object.create(AQLClause.prototype);
+LimitClause.prototype.constructor = LimitClause;
+
+
+// OrderbyClause
+//
+// Grammar:
+// OrderbyClause  ::= "order" "by" Expression ( ( "asc" ) | ( "desc" ) )? ( "," Expression ( ( "asc" ) | ( "desc" ) )? )*
+//
+// @params AQLExpressions and asc/desc strings, in any quantity. At least one required. 
+function OrderbyClause() {
+    
+    AQLClause.call(this);
+
+    // At least one argument expression is required, and first should be expression
+    if (arguments.length == 0 || !(arguments[0] instanceof AExpression)) {
+        // TODO Not sure which error to throw for an empty OrderBy but this should fail.
+        alert("Order By Error");
+        this._properties["clause"] = null;
+        return this;    
+    } 
+
+    var expc = 0;
+    var expressions = [];    
+
+    while (expc < arguments.length) {
+      
+        var expression = "";
+
+        if (arguments[expc] instanceof AExpression) {
+            expression += arguments[expc].val();
+        }
+
+        var next = expc + 1;
+        if (next < arguments.length && (arguments[next] == "asc" || arguments[next] == "desc")) {
+            expc++;
+            expression += " " + arguments[expc];
+        }
+        
+        expressions.push(expression);
+      
+        expc++;
+    }
+
+    this._properties["clause"] = "order by " + expressions.join(", ");
+    return this;
+}
+
+OrderbyClause.prototype = Object.create(AQLClause.prototype);
+OrderbyClause.prototype.constructor = OrderbyClause;
+
+
 // BooleanExpression
 // 
 // TODO