Major changes have been made. Built-in rules have now made loading and defining rules...
authorimode <immediate.mode@gmail.com>
Tue, 13 Nov 2018 06:36:12 +0000 (22:36 -0800)
committerimode <immediate.mode@gmail.com>
Tue, 13 Nov 2018 06:36:12 +0000 (22:36 -0800)
modal.py
prelude.modal

index 443fcf9..70a158b 100644 (file)
--- a/modal.py
+++ b/modal.py
@@ -56,7 +56,6 @@ def match(pattern, queue, context=None):
                     return None;
                 queue = dequeue(queue, len(context[variable]));
             else:
-                value = extract(queue);
                 if len(value) == 0:
                     return None;
                 context[variable] = value;
@@ -101,7 +100,7 @@ def define(queue, rules, pattern):
             left = left[1:][:-1];
         if len(right) > 1:
             right = right[1:][:-1];
-        rules.append(rule(left, right));
+        rules.append((left, apply, [right]));
         return dequeue(queue, len(construct(pattern, context)));
     return queue;
 
@@ -142,9 +141,6 @@ def reconstruct(pattern):
             yield '?' + element[1];
         yield ' ';
 
-def inspect(pattern):
-    return "".join(reconstruct(pattern));
-
 def literal(string, index=0):
     token = "";
     while index != len(string):
@@ -181,30 +177,7 @@ def parse(string, index=0):
                 results.append(["LIT", token]);
     return results;
 
-def split(string, delimiter):
-    if delimiter in string:
-        return string.strip().split(delimiter);
-    return "";
-
-def clean(strings):
-    results = [];
-    for string in strings:
-        if len(string) > 0:
-            results.append(string.strip());
-    return results;
-
-def rule(pattern, replacement):
-    return (pattern, apply, [replacement]);
-
-def rules(input):
-    results = [];
-    for line in clean(split(input, ';')):
-        if "->" in line:
-            pattern, replacement = clean(split(line, "->"));
-            results.append(rule(parse(pattern), parse(replacement)));
-    return results;
-
-def run(rules, queue, limit=pow(2, 24)):
+def run(rules, queue, limit=pow(2, 16)):
     steps      = 0;
     failures   = 0;
     queue      = [["SRT"]] + queue;
@@ -230,6 +203,9 @@ def read(file):
     except EnvironmentError:
         return None;
 
+def inspect(pattern):
+    return "".join(reconstruct(pattern));
+
 def usage(name):
     print(name + ':', "a programming language based on rewriting.");
     print("Usage:");
@@ -250,18 +226,17 @@ def help():
     print(prefix + "quit  : Quit.");
 
 def main():
-    builtins = [
-                    (parse("define ?left ?right"), define,   []),
-                    (parse("undefine ?left"),      undefine, [])
+    defaults = [
+                   (parse("define ?left ?right"), define,   []),
+                   (parse("undefine ?left"),      undefine, [])
                ];
+    rules = defaults;
     if len(sys.argv) >= 2:
         content = read(sys.argv[1]);
         if content == None:
             print("No such file.");
             return;
-        content = rules(content) + builtins;
-    else:
-        content = builtins;
+        run(rules, parse(content));
     print("Modal v0.01");
     help();
     while True:
@@ -271,25 +246,17 @@ def main():
         elif parse(input) == parse("rules"):
             print("Rules:");
             prefix = ' ' * 4;
-            for pattern, operation, parameters in content:
+            for pattern, operation, parameters in rules:
                 if operation == apply:
                     print(prefix + inspect(pattern) + "-> " + inspect(parameters[0]));
-        elif input.count("->") == 1:
-            line = clean(split(input, "->"));
-            if len(line) == 1:
-                pattern = line[0];
-                content = content + [rule(line)];
-            else:
-                pattern, replacement = line;
-                content              = content + [rule(pattern, replacement)];
         elif parse(input) == parse("clear"):
-            content = builtins;
+            rules = defaults;
         elif parse(input) == parse("help"):
             help();
         elif parse(input) == parse("quit") or parse(input) == parse("exit"):
             break;
         else:
-            print(inspect(seek(run(content, parse(input)), ["SRT"])));
+            print(inspect(seek(run(rules, parse(input)), ["SRT"])));
     return;
 
 if __name__ == "__main__":
index b2b2f0a..5452f5c 100644 (file)
-1 -> (s (0));
+define (?x -> ?y)  (define ?x ?y)
+define (def ?x ?y) (define ?x ?y)
 
+Now, anything can be a comment! And it'll be ignored.
+Provided you don't use any keywords.
 
-neg (neg ?x) -> ?x;
-neg (0)      -> 0;
+(add (s ?x) (s ?y)) -> (s (add ?x (s ?y)))
+(add (0)    (s ?x)) -> (s ?x)
+(add (s ?x) (0))    -> (s ?x)
+(add (0)    (0))    -> (0)
 
-
-add (s ?x) (s ?y) -> s (add ?x (s ?y));
-add (0)    (s ?x) -> s ?x;
-add (s ?x) (0)    -> s ?x;
-add (0)    (0)    -> 0;
-
-
-?x + ?y + ?z -> (?x + ?y) + ?z;
-
-
-?x + ?y -> add ?x ?y;
-
-
-sub (s ?x) (s ?y) -> sub ?x ?y;
-sub (s ?x) (0)    -> s ?x;
-sub (0)    (s ?x) -> neg (s ?x);
-sub (0)    (0)    -> 0;
-
-
-?x - ?y -> sub ?x ?y;
-
-
-mul (s ?x) (s ?y)  -> (s ?x) + (mul (s ?x) ((s ?y) - 1));
-mul (s ?x) (s (0)) -> s ?x;
-mul (s ?x) (0)     -> 0;
-mul (0)    (s ?x)  -> 0;
-
-
-?x * ?y -> mul ?x ?y;
-
-
-Ensures that a list or a number has been reduced to its normal form. ;
-
-reduced (0)       -> true;
-reduced (nil)     -> true;
-reduced (s ?x)    -> reduced ?x;
-reduced (?h : ?t) -> reduced ?t;
-reduced ?x        -> false;
-
-
-Because there may be conflicts with expressions that
-are currently being reduced, we need to fold over reduced
-lists, i.e ones that have already been fully generated. ;
-
-fold       (?f) ?i ?l           -> fold reduced ?l (?f) ?i ?l;
-fold true  (?f) ?i (nil)        -> ?i;
-fold true  (?f) ?i (?h : (nil)) -> ?f ?i ?h;
-fold true  (?f) ?i (?h : ?t)    -> ?f ?i (fold (?f) ?h ?t);
-fold false (?f) ?i ?l           -> fold (?f) ?i ?l;
-
-
-factorial (s (0)) -> s (0);
-factorial (s ?x)  -> (s ?x) * (factorial ((s ?x) - 1));
-
-
-sum (?h : ?t) -> fold (add) (0) (?h : ?t);
-
-
-range ?x (s (0)) -> ?x : (nil);
-range ?x (s ?y)  -> ?x : (range (?x + 1) ((s ?y) - 1));
-
-
-Disgusting (yet valid) hack for currying.
-We need lambdas. ;
-
-unpack (?h : nil) -> ?h;
-unpack (?h : ?t)  -> ?h unpack ?t;
-unpack (?x)       -> ?x;
-unpack (?x .      -> ?x unpack (;
-
-
-:: (?f) ?a -> ?f unpack ?a;
-
-
-mapp (?f) ?a (nil)        -> nil;
-mapp (?f) ?a (?h : (nil)) -> (?f unpack ?a ?h) : (nil);
-mapp (?f) ?a (?h : ?t)    -> (?f unpack ?a ?h) : (mapp (?f) ?a ?t);
-
-
-map (?f) (nil)      -> nil;
-map (?f) (?h : nil) -> (?f ?h) : (nil);
-map (?f) (?h : ?t)  -> (?f ?h) : (map (?f) ?t);
-
-
-product ?x -> fold (mul) 1 ?x;
-
-
-factorial2 ?x -> product (range 1 ?x);
-
-
-contains ?x (nil)     -> false;
-contains ?x (?x : ?t) -> true;
-contains ?x (?h : ?t) -> contains ?x ?t;
-
-
-unique       (nil)     -> nil;
-unique false (?h : ?t) -> ?h : (unique ?t);
-unique true  (?h : ?t) -> unique ?t;
-unique       (?h : ?t) -> unique contains ?h ?t (?h : ?t);
-
-
-length (nil)     -> 0;
-length (?h : ?t) -> s (length ?t);
-
-
-zipWith (?f) (nil)       (nil)       -> nil;
-zipWith (?f) (?h : ?t)   (nil)       -> nil;
-zipWith (?f) (nil)       (?h : ?t)   -> nil;
-zipWith (?f) (?h1 : ?t1) (?h2 : ?t2) -> (?f ?h1 ?h2) : (zipWith (?f) ?t1 ?t2);
-
-
-evens ?x -> zipWith (add) (range (0) ?x) (range (0) ?x);
-
-
-not (not ?x) -> ?x;
-not true     -> false;
-not false    -> true;
-
-
-any ?x -> contains true ?x;
-
-
-all ?x -> not contains false ?x;
-
-
-none ?x -> not any ?x;
-
-
-add1 ?x -> add ?x 1;
-
-
-square ?x -> ?x * ?x;
-
-
-reduce (s ?x)    -> s (reduce ?x);
-reduce (0)       -> (0);
-reduce (?h : ?t) -> ?h : (reduce ?t);
-reduce (nil)     -> nil;
+(?x + ?y) -> (add ?x ?y)