shithub: martian9

Download patch

ref: db23aa72a4d43083867fc28c5ec1664a3442645b
parent: 1554de912987175430a808ad1d949f0567ca44bd
author: McKay Marston <mckay.marston@greymanlabs.com>
date: Wed Sep 16 17:09:03 EDT 2020

macro update

--- a/core.ml
+++ b/core.ml
@@ -1,7 +1,6 @@
 module T = Types.Types
 
 let base = Env.make None
-let kw_macro = T.String "macro"
 
 let number_compare t f =
   Types.proc (function
@@ -55,17 +54,17 @@
   Env.set env (Types.symbol "<=") (simple_compare mk_bool ( <= ));
   Env.set env (Types.symbol ">") (simple_compare mk_bool ( > ));
   Env.set env (Types.symbol ">=") (simple_compare mk_bool ( >= ));
-  Env.set
-    env
-    (Types.symbol "proc?")
-    (Types.proc (function
-        | [ T.Proc { T.meta = T.Map { T.value = meta } } ] ->
-          mk_bool
-            (not
-               (Types.M9map.mem kw_macro meta
-               && Types.to_bool (Types.M9map.find kw_macro meta)))
-        | [ T.Proc _ ] -> T.Bool true
-        | _ -> T.Bool false));
+  (* Env.set
+   *   env
+   *   (Types.symbol "proc?")
+   *   (Types.proc (function
+   *       | [ T.Proc { T.meta = T.Map { T.value = meta } } ] ->
+   *         mk_bool
+   *           (not
+   *              (Types.M9map.mem kw_macro meta
+   *              && Types.to_bool (Types.M9map.find kw_macro meta)))
+   *       | [ T.Proc _ ] -> T.Bool true
+   *       | _ -> T.Bool false)); *)
   Env.set
     env
     (Types.symbol "number?")
--- a/eval.ml
+++ b/eval.ml
@@ -40,6 +40,7 @@
  *       eval foo env
  *     | _ -> ast)
  *   | _ -> ast *)
+
 and eval ast env =
   (* match preparse ast env with *)
   match ast with
@@ -130,10 +131,10 @@
     (match eval_ast ast env with
     | T.List { T.value = T.Proc { T.value = f } :: args } -> f args
     | T.List { T.value = T.Macro { T.value = sym; meta } :: args } ->
-      eval (Macro.expand ast env args sym meta) env
-      (* let foo = Macro.expand ast env args sym meta in
-       * print_endline (":::: " ^ Printer.print foo true);
-       * eval foo env *)
+      (* eval (Macro.expand ast env args sym meta) env *)
+      let foo = Macro.expand ast env args sym meta in
+      print_endline (":::: " ^ Printer.print foo true);
+      eval foo env
     | _ as x ->
       raise (Reader.Syntax_error ("'" ^ Printer.print x true ^ "' not a function")))
   | _ -> eval_ast ast env
--- a/macro.ml
+++ b/macro.ml
@@ -18,14 +18,16 @@
     (* print_endline "    LIST <-> LIST"; *)
     if ph = "_" || (ph = Printer.print sym true && sym = ah)
     then is_matching_pattern sym pt at matched && true
-    else (
+    else
       (* print_endline (" ------> " ^ ph ^ " vs " ^ Printer.print ah true); *)
-      is_matching_pattern sym pt at matched)
+      is_matching_pattern sym pt at matched
   | ph :: pt, [] ->
-    (* print_endline "    LIST <-> []"; *)
+    (* print_endline "    LIST <-> []";
+     * print_endline ("      ph: " ^ ph);
+     * print_endline ("      pt: " ^ String.concat "|" pt); *)
     if ph = "_" || ph = Printer.print sym true
     then is_matching_pattern sym pt [] matched && true
-    else ph = "..."
+    else ph = "..." || List.hd pt = "..."
   | [], ah :: at ->
     (* print_endline "    [] <-> LIST"; *)
     false
@@ -33,46 +35,64 @@
 ;;
 
 let rec ellipsis pattern template args =
-    (* print_endline
-     * ("pattern length: "
-     * ^ string_of_int (List.length pattern)
-     * ^ "  arg length: "
-     * ^ string_of_int (List.length args)); *)
-    let has_ellipsis = (try ignore (Str.search_forward (Str.regexp "...") (Printer.stringify pattern true) 0); true
-                        with Not_found -> false) in
+  let has_ellipsis =
+    try
+      ignore (Str.search_forward (Str.regexp "...") (Printer.stringify pattern true) 0);
+      true
+    with
+    | Not_found -> false
+  in
   let ellipsis_substitutions = ref [] in
-  let missing = List.length args - List.length pattern + (if has_ellipsis then 1 else 0) in
+  let missing = List.length args - List.length pattern + if has_ellipsis then 1 else 0 in
+  print_endline ("missing: " ^ string_of_int missing);
   (* print_endline (" NEED TO ADD " ^ string_of_int missing ^ " PLACEHOLDERS"); *)
-  if missing > 0
-  then (
+  match missing with
+  | _ when (missing = 0 || missing > 0) ->
+    (* add arguments *)
+    print_endline ("ADD " ^ string_of_int missing ^ " arguments");
     for i = 1 to missing do
       ellipsis_substitutions := !ellipsis_substitutions @ [ gen_sym "x" ]
-    done);
-  let pattern_str =
-    Str.global_replace
-      (Str.regexp "\\.\\.\\.")
-      (String.concat " " !ellipsis_substitutions)
-      (Printer.stringify pattern true)
-  in
-  let template_str =
-    Str.global_replace
-      (Str.regexp "\\.\\.\\.")
-      (String.concat " " !ellipsis_substitutions)
-      (Printer.print template true)
-  in
-  (* let args_str = Printer.stringify args true in *)
-  (* print_endline ("ellipsis: template: " ^ template_str ^ "  args: " ^ args_str); *)
-  "(" ^ pattern_str ^ ") " ^ template_str ^ ")"
+    done;
+    let pattern_str =
+      Str.global_replace
+        (Str.regexp "\\.\\.\\.")
+        (String.concat " " !ellipsis_substitutions)
+        (Printer.stringify pattern true)
+    in
+    let template_str =
+      Str.global_replace
+        (Str.regexp "\\.\\.\\.")
+        (String.concat " " !ellipsis_substitutions)
+        (Printer.print template true)
+    in
+    (* let args_str = Printer.stringify args true in *)
+    (* print_endline ("ellipsis: template: " ^ template_str ^ "  args: " ^ args_str); *)
+    "(" ^ pattern_str ^ ") " ^ template_str ^ ")"
+  | _ when missing < 0 ->
+    (* remove ellipsis and arg *)
+    print_endline "REMOVE arguments";
+    (* let rgx = Str.regexp "[a-zA-Z0-9]+ \\.\\.\\." in *)
+    let rgx = Str.regexp "[a-zA-Z0-9]+ \\.\\.\\." in
+    let pattern_str = Str.global_replace rgx "" (Printer.stringify pattern true) in
+    let template_str = Str.global_replace rgx "" (Printer.stringify pattern true) in
+    print_endline ("  pattern:  " ^ Printer.dump pattern);
+    print_endline ("    pattern_str:  " ^ pattern_str);
+    print_endline ("  template: " ^ Printer.print template true);
+    print_endline ("    template_str: " ^ template_str);
+    print_endline ("(" ^ pattern_str ^ ") " ^ template_str ^ ")");
+    "(" ^ pattern_str ^ ") " ^ template_str ^ ")"
+  | _ ->
+    "(" ^ Printer.dump pattern ^ ") " ^ Printer.print template true ^ ")"
 ;;
 
 let lambdaize pattern template args =
   match pattern, args with
   | ph :: pt, ah :: at :: rest ->
-    (* print_endline "lambdaize: list list"; *)
+    print_endline ("lambdaize: list list: args: " ^ Printer.stringify args true);
     Reader.read
       ("((lambda " ^ ellipsis pt template args ^ Printer.stringify args false ^ ")")
   | ph :: pt, ah :: at ->
-    (* print_endline "lambdaize: list short"; *)
+    print_endline "lambdaize: list short";
     Reader.read
       ("((lambda ("
       ^ Printer.stringify pt true
@@ -82,7 +102,7 @@
       ^ Printer.stringify args true
       ^ ")")
   | ph :: pt, [] ->
-    (* print_endline "lambdaize: list empty"; *)
+    print_endline "lambdaize: list empty";
     Reader.read
       ("((lambda ("
       ^ Printer.stringify pt false
@@ -90,80 +110,85 @@
       ^ Printer.print template true
       ^ "))")
   | _ ->
-    (* print_endline "lambdaize: empty"; *)
+    print_endline "lambdaize: empty";
     Reader.read ("((lambda () " ^ Printer.print template true ^ "))")
 ;;
 
 let rec expand ast env args sym meta =
-  (* print_endline ("\n\nTHIS IS A MACRO: " ^ Printer.print sym true);
-   * print_endline ("   META: " ^ Printer.print meta true);
-   * print_endline ("   ARGS: " ^ Printer.dump args);
-   * print_endline ("  AST:   " ^ Printer.print ast true); *)
+  print_endline ("\n\nTHIS IS A MACRO: " ^ Printer.print sym true);
+  print_endline ("   META: " ^ Printer.print meta true);
+  print_endline ("   ARGS: " ^ Printer.dump args);
+  print_endline ("   AST:   " ^ Printer.print ast true);
   match meta with
   | T.Map { T.value = m } ->
-    (try
-       (* let literals = Types.M9map.find Types.macro_literals m in *)
-       let transformers = Types.M9map.find Types.macro_transformers m in
-       (* print_endline
-        *   ("  -- EVAL_MACRO: literals: "
-        *   ^ Printer.print literals true
-        *   ^ "     transformers: "
-        *   ^ Printer.print transformers true); *)
-       (* print_endline ("    args: " ^ Printer.dump args); *)
-       let rec match_transform transforms =
-         match transforms with
-         | hd :: tl ->
-           (* print_endline ("      transform: " ^ Printer.print hd true); *)
-           (match hd with
-           | T.List
-               { T.value = [ T.List { T.value = pattern }; T.List { T.value = template } ]
-               } ->
-             (* print_endline "   MULTI";
-              * print_endline ("     - template: " ^ Printer.dump template);
-              * print_endline
-              *   ("      matched?: "
-              *   ^ (if is_matching_pattern
-              *           sym
-              *           (List.map (fun x -> Printer.print x true) pattern)
-              *           (Core.seq ast)
-              *           true
-              *     then "yes"
-              *     else "no")
-              *   ^ " ::> "
-              *   ^ Printer.dump pattern); *)
-             if is_matching_pattern
-                  sym
-                  (List.map (fun x -> Printer.print x true) pattern)
-                  (Core.seq ast)
-                  true
-             then lambdaize pattern (Types.list template) args
-             else match_transform tl
-           | T.List { T.value = [ T.List { T.value = pattern }; atom ] } ->
-             (* print_endline "   SINGLE";
-              * print_endline
-              *   ("      matched?: "
-              *   ^ (if is_matching_pattern
-              *           sym
-              *           (List.map (fun x -> Printer.print x true) pattern)
-              *           (Core.seq ast)
-              *           true
-              *     then "yes"
-              *     else "no")
-              *   ^ " ::> "
-              *   ^ Printer.dump pattern); *)
-             if is_matching_pattern
-                  sym
-                  (List.map (fun x -> Printer.print x true) pattern)
-                  (Core.seq ast)
-                  true
-             then lambdaize pattern atom args
-             else match_transform tl
-           | _ -> T.Nil)
-           (* errors? *)
-         | [] -> T.Nil
-       in
-       match_transform (Core.seq transformers)
-     with
-    | Not_found -> T.Nil)
-  | _ -> T.Nil
+    ((* let literals = Types.M9map.find Types.macro_literals m in *)
+    try
+      let transformers = Types.M9map.find Types.macro_transformers m in
+      print_endline
+        ("  -- EVAL_MACRO: "
+        (*  ^ " literals: "
+         * ^ Printer.print literals true *)
+        ^ "     transformers: "
+        ^ Printer.print transformers true);
+      let rec match_transform transforms =
+        match transforms with
+        | hd :: tl ->
+          (* print_endline ("      transform: " ^ Printer.print hd true); *)
+          (match hd with
+          | T.List
+              { T.value = [ T.List { T.value = pattern }; T.List { T.value = template } ]
+              } ->
+            (* print_endline "   MULTI";
+             * print_endline ("     - template: " ^ Printer.dump template); *)
+            print_endline
+              ("      matched (m)?: "
+              ^ (if is_matching_pattern
+                      sym
+                      (List.map (fun x -> Printer.print x true) pattern)
+                      (Core.seq ast)
+                      true
+                then "yes"
+                else "no")
+              ^ " ::> "
+              ^ Printer.dump pattern);
+            if is_matching_pattern
+                 sym
+                 (List.map (fun x -> Printer.print x true) pattern)
+                 (Core.seq ast)
+                 true
+            then lambdaize pattern (Types.list template) args
+            else match_transform tl
+          | T.List { T.value = [ T.List { T.value = pattern }; atom ] } ->
+            (* print_endline "   SINGLE"; *)
+            print_endline
+              ("      matched (s)?: "
+              ^ (if is_matching_pattern
+                      sym
+                      (List.map (fun x -> Printer.print x true) pattern)
+                      (Core.seq ast)
+                      true
+                then "yes"
+                else "no")
+              ^ " ::> "
+              ^ Printer.dump pattern);
+            if is_matching_pattern
+                 sym
+                 (List.map (fun x -> Printer.print x true) pattern)
+                 (Core.seq ast)
+                 true
+            then lambdaize pattern atom args
+            else match_transform tl
+          | _ -> raise (Reader.Syntax_error "Unknown"))
+          (* errors? *)
+        | [] ->
+          raise
+            (Reader.Syntax_error
+               ("No matching transform for macro: '" ^ Printer.print sym true))
+      in
+      match_transform (Core.seq transformers)
+    with
+    | Not_found ->
+      raise
+        (Reader.Syntax_error ("'" ^ Printer.print sym true ^ "' is not a known macro")))
+  | _ -> raise (Reader.Syntax_error "syntax error with defined macro")
 ;;
--- a/notes.org
+++ b/notes.org
@@ -1,5 +1,5 @@
 * First things:
-** TODO Remove kw_macro
+** DONE Remove kw_macro
 We determine what's a macro based on "syntax-rules" (so we need to make sure that's always there)
 ** DONE (let) doesn't work at all
 ** Should (let) include an implicit (begin)?
@@ -9,7 +9,7 @@
 ** TODO implement (pair)
 Pairs should be preserved, I think
 Also, it should _only_ be pairs, nothing more.
-** TODO (define) needs to support function definitions
+** PROGRESSING (define) needs to support function definitions
 Right now you need to use lambda
 ** DONE (cons) doesn't work
 This appears to work, now, but not with a pair
@@ -37,3 +37,9 @@
 ...but what about ellipsis??
 ** Thoughts
 Eval seems too late to handle it, so maybe try to do expansion at read?
+* Macros
+** and
+(define-syntax and (syntax-rules ()
+  ((and) #t)
+  ((and test) test) ((and test1 test2 ...)
+    (if test1 (and test2 ...) #f))))