]> git.mdlowis.com Git - proto/sclpl.git/commitdiff
Implemented ANF transformation for function applications
authorMichael D. Lowis <mike@mdlowis.com>
Sun, 20 Dec 2015 21:32:51 +0000 (16:32 -0500)
committerMichael D. Lowis <mike@mdlowis.com>
Sun, 20 Dec 2015 21:32:51 +0000 (16:32 -0500)
source/ast.c
source/main.c
source/sclpl.h
spec/anf_spec.rb

index e54532919acf5d1190700d774e097bd7fae04906..460cfa23627600560bd59666acc7ae0d32613607 100644 (file)
@@ -337,6 +337,11 @@ AST* let_body(AST* let)
     return let->value.let.body;
 }
 
+void let_set_body(AST* let, AST* body)
+{
+    let->value.let.body = (AST*)gc_addref(body);
+}
+
 AST* TempVar(void)
 {
     static intptr_t val = 0;
index 2d225cc069b6cf09319c3fe8129bf5672c8db952..e8a21a7cb9d45c0171e90624e7821f536ff8e645 100644 (file)
@@ -21,16 +21,40 @@ bool isatomic(AST* tree)
     }
 }
 
+//AST* normalize_fnapp_args(AST* tree)
+//{
+//}
+
 AST* normalize_fnapp(AST* tree)
 {
+    AST* normalized = tree;
     AST* fn = fnapp_fn(tree);
+    /* Normalize the function */
     if (!isatomic(fn)) {
         AST* temp = TempVar();
         fnapp_set_fn(tree, temp);
-        return Let(temp, fn, tree);
-    } else {
-        return tree;
+        normalized = Let(temp, fn, tree);
+    }
+    /* Normalize the function arguments */
+    vec_t temps;
+    vec_init(&temps);
+    vec_t* args = fnapp_args(tree);
+    for (int i = 0; i < vec_size(args); i++) {
+        AST* arg = (AST*)vec_at(args, i);
+        if (!isatomic(arg)) {
+            AST* temp = TempVar();
+            vec_push_back(&temps, Let(temp, arg, NULL));
+            vec_set(args, i, temp);
+        }
+    }
+    /* Nest all the scopes and return the new form */
+    for (int i = vec_size(&temps); i > 0; i--) {
+        AST* let = (AST*)vec_at(&temps,i-1);
+        let_set_body(let, normalized);
+        normalized = let;
     }
+    vec_deinit(&temps);
+    return normalized;
 }
 
 AST* normalize(AST* tree)
index 274c9fe4131528fcfac068b56d6540a88ffb8b0b..92c5a44a9aeed5c8c4536ce7df7376468b908efe 100644 (file)
@@ -45,6 +45,7 @@ void vec_clear(vec_t* vec);
 size_t vec_size(vec_t* vec);
 void* vec_at(vec_t* vec, size_t index);
 void vec_push_back(vec_t* vec, void* data);
+void vec_set(vec_t* vec, size_t index, void* data);
 
 /* Token Types
  *****************************************************************************/
@@ -196,6 +197,7 @@ AST* Let(AST* temp, AST* val, AST* body);
 AST* let_var(AST* let);
 AST* let_val(AST* let);
 AST* let_body(AST* let);
+void let_set_body(AST* let, AST* body);
 
 /* Lexer and Parser Types
  *****************************************************************************/
index 229d8c6d590a91086eedb60f0cc2f87a5ad6b035..30342ad153540cc43cb4b64268db2ea1914fe32b 100644 (file)
@@ -39,5 +39,45 @@ describe "sclpl a-normal form" do
     it "should normalize an application with a complex function" do
       expect(anf('(foo())()')).to eq([['let', ['$:0', ['T_ID:foo']], ['$:0']]])
     end
+
+    it "should normalize an application with a complex arg" do
+      expect(anf('foo(bar())')).to eq([['let', ['$:0', ['T_ID:bar']], ['T_ID:foo', '$:0']]])
+    end
+
+    it "should normalize an application with two complex args" do
+      expect(anf('foo(bar(),baz())')).to eq([
+          ['let', ['$:0', ['T_ID:bar']],
+            ['let', ['$:1', ['T_ID:baz']],
+              ['T_ID:foo', '$:0', '$:1']]]])
+    end
+
+    it "should normalize an application with three complex args" do
+      expect(anf('foo(bar(),baz(),boo())')).to eq([
+          ['let', ['$:0', ['T_ID:bar']],
+            ['let', ['$:1', ['T_ID:baz']],
+              ['let', ['$:2', ['T_ID:boo']],
+                ['T_ID:foo', '$:0', '$:1', '$:2']]]]])
+    end
+
+    it "should normalize an application with simple and complex args (s,c,c)" do
+      expect(anf('foo(a,bar(),baz())')).to eq([
+          ['let', ['$:0', ['T_ID:bar']],
+            ['let', ['$:1', ['T_ID:baz']],
+              ['T_ID:foo', 'T_ID:a', '$:0', '$:1']]]])
+    end
+
+    it "should normalize an application with simple and complex args (c,s,c)" do
+      expect(anf('foo(bar(),a,baz())')).to eq([
+          ['let', ['$:0', ['T_ID:bar']],
+            ['let', ['$:1', ['T_ID:baz']],
+              ['T_ID:foo', '$:0', 'T_ID:a', '$:1']]]])
+    end
+
+    it "should normalize an application with simple and complex args (c,c,s)" do
+      expect(anf('foo(bar(),baz(),a)')).to eq([
+          ['let', ['$:0', ['T_ID:bar']],
+            ['let', ['$:1', ['T_ID:baz']],
+              ['T_ID:foo', '$:0', '$:1', 'T_ID:a']]]])
+    end
   end
 end