Permalink
Browse files

day 1 wip

  • Loading branch information...
0 parents commit 6902cd4e9382e2da58fb9d43f8069256e8fe1ded @ujihisa committed Dec 31, 2012
Showing with 133 additions and 0 deletions.
  1. +78 −0 README.md
  2. +39 −0 runtime.clj
  3. +16 −0 sample.js
@@ -0,0 +1,78 @@
+# JavaScript in a week
+
+## Day 1 defining a subset of JavaScript
+
+The implementation should execute the following JavaScript code.
+
+```js
+var acc = 'dummy';
+var f = function() {
+ var acc = [];
+ return function(x) {
+ return x ? acc.push(x)&&f(x - 1) : acc;
+ };
+ console.log("this won't show up!");
+}();
+
+String.prototype.ujihisa = function() {
+ var x = 10;
+ return this + f(x);
+}
+
+console.log("hello".ujihisa());
+console.log(acc == 'dummy');
+console.log({'a': 2}.a == 2);
+```
+
+ hello10,9,8,7,6,5,4,3,2,1
+ true
+
+That code covers the following important aspects.
+
+* statements and expressions
+* literals (String, Number, Function, Array and Object)
+* function call, method call, operators, and index/key access of Object
+* implicit convertion (String + Number)
+* lexical scope (see `acc` var)
+* method addition by prototype
+* `return` exits from the current function
+
+The implementation consists of
+
+* parser (JS code to internal representation in S-expression)
+* runtime
+
+I'll work on runtime first in Clojure, then work on parser in Haskell with parsec.
+
+### parsing
+
+I don't implement the parser for now but I simply parse the sample code by hand. the first 2 statements will be like the below.
+
+before:
+
+```js
+var acc = 'dummy';
+var f = function() {
+ var acc = [];
+ return function(x) {
+ return x ? acc.push(x)&&f(x - 1) : acc;
+ };
+}();
+```
+
+after:
+
+```clojure
+'[(var 'acc "dummy")
+ (var 'f
+ (call
+ (function []
+ [[(var 'acc (array))
+ (return
+ (function ['x]
+ [[(return (if 'x
+ (and (mcall 'push 'acc ['x])
+ (call 'f [(minus 'x 1)]))
+ 'acc))]]))]])
+ []))]
+```
@@ -0,0 +1,39 @@
+(def sample-parsed
+ '[(var acc "dummy")
+ (var f
+ (fcall
+ (function []
+ [[(var acc (array))
+ (return
+ (function ['x]
+ [[(return (if 'x
+ (and (mcall 'push 'acc ['x])
+ (fcall 'f [(minus 'x 1)]))
+ 'acc))]]))]])
+ []))])
+
+(defn evaluate [expr env]
+ "assumption: env won't change"
+ (if (= 'quote (first expr))
+ (get env (second expr))
+ expr))
+
+(defn run [exprs]
+ (loop [[expr & exprs] exprs env {'console.log 'console.log}]
+ (when expr
+ (if-let [[car & cdr] expr]
+ (do
+ #_(prn car cdr env)
+ (condp = car
+ 'var (let [vname (first cdr)
+ vvalue (evaluate (second cdr) env)]
+ (recur exprs (assoc env vname vvalue)))
+ 'fcall (let [func (evaluate (first cdr) env)
+ args (map #(evaluate % env) (second cdr))]
+ (condp = func
+ 'console.log (println (first args))
+ (prn 'must-not-happen 'missing-function)))
+ (prn 'must-not-happen expr)))
+ expr))))
+
+(run '[(var x "hello") (fcall 'console.log ['x])])
@@ -0,0 +1,16 @@
+var acc = 'dummy';
+var f = function() {
+ var acc = [];
+ return function(x) {
+ return x ? acc.push(x)&&f(x - 1) : acc;
+ };
+}();
+
+String.prototype.ujihisa = function() {
+ var x = 10;
+ return this + f(x);
+}
+
+console.log("hello".ujihisa());
+console.log(acc == 'dummy');
+console.log({'a': 2}.a == 2);

0 comments on commit 6902cd4

Please sign in to comment.