Added support for built-in rules. The stability of this change is not guaranteed.
authorimode <immediate.mode@gmail.com>
Tue, 13 Nov 2018 05:08:23 +0000 (21:08 -0800)
committerimode <immediate.mode@gmail.com>
Tue, 13 Nov 2018 05:08:23 +0000 (21:08 -0800)
modal.py

index d45562b..521dbc1 100644 (file)
--- a/modal.py
+++ b/modal.py
@@ -80,7 +80,7 @@ def construct(pattern, context):
             results.append(element);
     return results;
 
-def apply(pattern, replacement, queue):
+def apply(queue, rules, pattern, replacement):
     context = match(pattern, queue);
     if context == None:
         return queue;
@@ -94,9 +94,9 @@ def apply(pattern, replacement, queue):
 
 def applicable(rules, queue):
     results = [];
-    for pattern, replacement in rules:
+    for pattern, operation, parameters in rules:
         if match(pattern, queue) != None:
-            results.append((pattern, replacement));
+            results.append((pattern, operation, parameters));
     return results;
 
 def pick(list):
@@ -167,15 +167,15 @@ def clean(strings):
             results.append(string.strip());
     return results;
 
-def rule(pattern, replacement=""):
-    return (parse(pattern), parse(replacement));
+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(pattern, replacement));
+            results.append(rule(parse(pattern), parse(replacement)));
     return results;
 
 def run(rules, queue, limit=pow(2, 24)):
@@ -188,8 +188,8 @@ def run(rules, queue, limit=pow(2, 24)):
             queue = roll(queue);
             failures = failures + 1;
         else:
-            pattern, replacement = rule;
-            queue = apply(pattern, replacement, queue);
+            pattern, operation, parameters = rule;
+            queue = operation(queue, rules, pattern, *parameters);
             failures = 0;
         steps = steps + 1;
     if steps == limit:
@@ -223,15 +223,25 @@ def help():
     print(prefix + "help  : This message.");
     print(prefix + "quit  : Quit.");
 
+def defrule(queue, rules, pattern):
+    context = match(pattern, queue);
+    if "left" in context.keys() and "right" in context.keys():
+        rules.append(rule(context["left"], context["right"]));
+        return dequeue(queue, len(construct(pattern, context)));
+    return queue;
+
 def main():
+    builtins = [
+                    (parse("def ?left ?right"), defrule, [])
+               ];
     if len(sys.argv) >= 2:
         content = read(sys.argv[1]);
         if content == None:
             print("No such file.");
             return;
-        content = rules(content);
+        content = rules(content) + builtins;
     else:
-        content = [];
+        content = builtins;
     print("Modal v0.01");
     help();
     while True:
@@ -241,8 +251,9 @@ def main():
         elif parse(input) == parse("rules"):
             print("Rules:");
             prefix = ' ' * 4;
-            for pattern, replacement in content:
-                print(prefix + inspect(pattern) + "-> " + inspect(replacement));
+            for pattern, operation, parameters in content:
+                if operation == apply:
+                    print(prefix + inspect(pattern) + "-> " + inspect(parameters[0]));
         elif input.count("->") == 1:
             line = clean(split(input, "->"));
             if len(line) == 1:
@@ -252,7 +263,7 @@ def main():
                 pattern, replacement = line;
                 content              = content + [rule(pattern, replacement)];
         elif parse(input) == parse("clear"):
-            content = [];
+            content = builtins;
         elif parse(input) == parse("help"):
             help();
         elif parse(input) == parse("quit") or parse(input) == parse("exit"):