git » jacl.git » commit 6e57b36

more analysis progress

author Alan Dipert
2019-10-10 04:38:47 UTC
committer Alan Dipert
2019-10-10 04:38:47 UTC
parent 63a0dbf7734a7765849e26cfa4b01b2350b822d5

more analysis progress

index.html +8 -0
jacl.js +56 -29

diff --git a/index.html b/index.html
index bde2a66..1fb1f73 100644
--- a/index.html
+++ b/index.html
@@ -5,6 +5,14 @@
     <meta name="viewport" content="width=device-width">
     <title>JACL tests</title>
     <link rel="stylesheet" href="qunit-2.9.2.css">
+    <style type="text/css">
+    @media (prefers-color-scheme: dark) {
+      body { 
+        color: #ddd;
+        background-color: black;
+      }
+    }
+    </style>
   </head>
   <body>
     <div id="qunit"></div>
diff --git a/jacl.js b/jacl.js
index ec22e30..9f4c13a 100644
--- a/jacl.js
+++ b/jacl.js
@@ -690,18 +690,40 @@ const isLambdaForm = form => {
     && form.car.name === 'LAMBDA';
 }
 
-const assoc = (...objs) => Object.assign({}, ...objs);
+const merge = (...objs) => Object.assign({}, ...objs);
 
 //(def specials '#{if def fn* do let* loop recur new set! ns})
 
+const stringy = x => x instanceof String || typeof x === 'string' || x instanceof LispString;
 const analyzeSpecials = new Map([
+  [JACLPKG.intern("%DOT"), (env, form) => {
+    const [, target, field] = form;
+    if (!(field instanceof LispSymbol || stringy(field)))
+      throw new Error(`%DOT field must be a symbol, JS string, or Lisp string`)
+    return {
+      op: "js-field",
+      env: env,
+      form: form,
+      target: analyze(merge(env, { context: "val" }), target),
+      field: field instanceof LispSymbol ? field.name : field.toString()
+    };
+  }],
   [JACLPKG.intern("%CALL"), (env, form) => {
+    env = merge(env, { context: "val" });
+    const [, func, ...args] = form;
+    return {
+      op: "call",
+      env: env,
+      form: form,
+      f: analyze(env, func),
+      args: args.map(analyze.bind(null, env))
+    }
   }]
 ]);
 
 const parseCall = (env, [func, ...args]) => {
-  env = assoc(env, {context: "expr"});
-  const fenv = assoc(env, {context: "fun"})
+  env = merge(env, { context: "val" });
+  const fenv = merge(env, { context: "fun" })
   return {
     env: env,
     op: "call",
@@ -727,34 +749,37 @@ const analyzeList = (env, form) => {
 };
 
 const analyzeSymbol = (env, form) => {
-  if (env.context === "fun" || env.context === "val") {
-    if (env.locals[env.context].has(form)) {
-      return {
-        op: "local",
-        env: env,
-        form: form,
-        name: env.locals[env.context].get(form)
-      };
-    } else {
-      return {
-        op: "sym",
-        ctx: env.context,
-        env: env,
-        form: form,
-      };
-    }
+  ret = x => merge({ env: env, form: form }, x);
+  if (form.packageName === 'KEYWORD') {
+    return ret({ op: "constant" });
+  } else if (form.packageName === 'JS' && !form.getPackage().isExported(form.name)) {
+    return ret({ op: "js-var", name: form.name });
+  } else if (env.context === "fun" && env.locals.fun.has(form)) {
+    return ret({ op: "local", name: env.locals.fun.get(form) });
+  } else if (env.locals.val.has(form)) {
+    return ret({ op: "local", name: env.locals.val.get(form) });
   } else {
-    throw new Error(`Unknown context: ${env.context}`);
+    return ret({ op: "global" });
   }
 };
 
-const emptyEnv = { 
-  locals: {
-    fun: new Map(),
-    val: new Map()
-  },
-  context: "val"
-};
+class Env {
+  constructor() {
+    this.locals = {
+      fun: new Map(),
+      val: new Map()
+    };
+    this.context = "val";
+  }
+  copy() {
+    const newEnv = new Env();
+    newEnv.locals.fun = new Map(this.locals.fun);
+    newEnv.locals.val = new Map(this.locals.val);
+    return newEnv;
+  }
+}
+
+const emptyEnv = new Env();
 
 const analyze = (env, form) => {
   if (form instanceof LispSymbol) {
@@ -845,9 +870,11 @@ var buf = new BufferedStream(),
 (async function() {
   for await(const obj of rdr) {
     console.log("read:", obj);
-    console.log("compiled:", compile(obj, null));
-    console.log("evaled:", eval(compile(obj, null)));
+    console.log(analyze(emptyEnv, obj));
+    //console.log("compiled:", compile(obj, null));
+    //console.log("evaled:", eval(compile(obj, null)));
   }
 })()
 
 // buf.writeEach(String.raw`(\. (js |window|) (|alert| (to-js "hello, world!")))`)
+// buf.writeEach('(jacl::%call (jacl::%dot js::|window| |alert|) "hi")')