]> git.mdlowis.com Git - proto/sclpl.git/commitdiff
Started implementing the anf conversion phase
authorMichael D. Lowis <mike@mdlowis.com>
Fri, 18 Dec 2015 02:28:23 +0000 (21:28 -0500)
committerMichael D. Lowis <mike@mdlowis.com>
Fri, 18 Dec 2015 02:28:23 +0000 (21:28 -0500)
Makefile
source/ast.c
source/main.c
source/pprint.c
source/sclpl.h
spec/anf_spec.rb
spec/spec_helper.rb

index c924ccbb32b59f661a1b203c6a538df62abfa7f6..654a84d013b0107b4324fe5d1671c533c66574ab 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -10,7 +10,7 @@ LD = ${CC}
 # flags
 INCS      = -Isource/
 CPPFLAGS  = -D_XOPEN_SOURCE=700
-CFLAGS   += ${INCS} ${CPPFLAGS}
+CFLAGS   += ${INCS} ${CPPFLAGS} -g
 LDFLAGS  += ${LIBS}
 
 #------------------------------------------------------------------------------
index 7185904bdf090822f970d0333346ab095d88f6cb..e54532919acf5d1190700d774e097bd7fae04906 100644 (file)
@@ -113,6 +113,13 @@ intptr_t integer_value(AST* val)
     return val->value.integer;
 }
 
+intptr_t temp_value(AST* val)
+{
+    assert(val != NULL);
+    assert(val->type == AST_TEMP);
+    return val->value.integer;
+}
+
 AST* Float(Tok* val)
 {
     AST* node = ast(AST_FLOAT);
@@ -284,6 +291,13 @@ AST* FnApp(AST* fnapp)
     return node;
 }
 
+void fnapp_set_fn(AST* fnapp, AST* fn)
+{
+    AST* old = fnapp->value.fnapp.fn;
+    fnapp->value.fnapp.fn = (AST*)gc_addref(fn);
+    gc_delref(old);
+}
+
 AST* fnapp_fn(AST* fnapp)
 {
     return fnapp->value.fnapp.fn;
@@ -307,3 +321,26 @@ AST* Let(AST* temp, AST* val, AST* body)
     node->value.let.body  = (AST*)gc_addref(body);
     return node;
 }
+
+AST* let_var(AST* let)
+{
+    return let->value.let.temp;
+}
+
+AST* let_val(AST* let)
+{
+    return let->value.let.value;
+}
+
+AST* let_body(AST* let)
+{
+    return let->value.let.body;
+}
+
+AST* TempVar(void)
+{
+    static intptr_t val = 0;
+    AST* node = ast(AST_TEMP);
+    node->value.integer = val++;
+    return node;
+}
index de5700ca3f4359fbc016c66b77bbecbfc9f34957..2d225cc069b6cf09319c3fe8129bf5672c8db952 100644 (file)
@@ -21,9 +21,24 @@ bool isatomic(AST* tree)
     }
 }
 
+AST* normalize_fnapp(AST* tree)
+{
+    AST* fn = fnapp_fn(tree);
+    if (!isatomic(fn)) {
+        AST* temp = TempVar();
+        fnapp_set_fn(tree, temp);
+        return Let(temp, fn, tree);
+    } else {
+        return tree;
+    }
+}
+
 AST* normalize(AST* tree)
 {
-    return tree;
+    if (tree->type == AST_FNAPP)
+        return normalize_fnapp(tree);
+    else
+        return tree;
 }
 
 /* Driver Modes
index 2758203e75513a68c0271917831e932b49a3a722..0cc839d595263a813e9d17f94c4dca4370c62e7c 100644 (file)
@@ -93,6 +93,7 @@ static const char* tree_type_to_string(ASTType type) {
         case AST_INT:    return "T_INT";
         case AST_FLOAT:  return "T_FLOAT";
         case AST_BOOL:   return "T_BOOL";
+        case AST_TEMP:   return "$";
         default:         return "???";
     }
 }
@@ -107,6 +108,7 @@ static void pprint_literal(FILE* file, AST* tree, int depth)
         case AST_CHAR:   printf("%c",     char_value(tree));    break;
         case AST_INT:    printf("%ld",    integer_value(tree)); break;
         case AST_FLOAT:  printf("%lf",    float_value(tree));   break;
+        case AST_TEMP:   printf("%ld",    temp_value(tree));    break;
         case AST_BOOL:
             printf("%s", bool_value(tree) ? "true" : "false");
             break;
@@ -174,7 +176,13 @@ void pprint_tree(FILE* file, AST* tree, int depth)
             break;
 
         case AST_LET:
-            printf("(let)");
+            printf("(let (");
+            pprint_tree(file, let_var(tree), depth);
+            printf(" ");
+            pprint_tree(file, let_val(tree), depth);
+            printf(") ");
+            pprint_tree(file, let_body(tree), depth);
+            printf(")");
             break;
 
         default:
index 92acc642adbe717def87f964d91d4dd8db3e2da9..274c9fe4131528fcfac068b56d6540a88ffb8b0b 100644 (file)
@@ -149,6 +149,10 @@ bool bool_value(AST* val);
 AST* Ident(Tok* val);
 char* ident_value(AST* val);
 
+/* Temp Variable */
+AST* TempVar(void);
+intptr_t temp_value(AST* val);
+
 /* Require */
 AST* Require(Tok* name);
 char* require_name(AST* req);
@@ -183,11 +187,15 @@ void func_set_body(AST* func, AST* body);
 /* Function Application */
 AST* FnApp(AST* fn);
 AST* fnapp_fn(AST* fnapp);
+void fnapp_set_fn(AST* fnapp, AST* fn);
 vec_t* fnapp_args(AST* fnapp);
 void fnapp_add_arg(AST* func, AST* arg);
 
 /* Let Expression */
 AST* Let(AST* temp, AST* val, AST* body);
+AST* let_var(AST* let);
+AST* let_val(AST* let);
+AST* let_body(AST* let);
 
 /* Lexer and Parser Types
  *****************************************************************************/
index 0f70771682d444f1aec7fca8ae5262d90c288f17..229d8c6d590a91086eedb60f0cc2f87a5ad6b035 100644 (file)
@@ -3,27 +3,41 @@ require 'open3'
 describe "sclpl a-normal form" do
   context "literals" do
     it "strings should remain untouched" do
-      expect(ast('"foo"')).to eq(['T_STRING:"foo"'])
+      expect(anf('"foo"')).to eq(['T_STRING:"foo"'])
     end
 
     it "characters should remain untouched" do
-      expect(ast('\\c')).to eq(['T_CHAR:c'])
+      expect(anf('\\c')).to eq(['T_CHAR:c'])
     end
 
     it "integers should remain untouched" do
-      expect(ast('123')).to eq(['T_INT:123'])
+      expect(anf('123')).to eq(['T_INT:123'])
     end
 
     it "floats should remain untouched" do
-      expect(ast('123.0')).to eq(['T_FLOAT:123.000000'])
+      expect(anf('123.0')).to eq(['T_FLOAT:123.000000'])
     end
 
     it "booleans should remain untouched" do
-      expect(ast('true')).to eq(['T_BOOL:true'])
+      expect(anf('true')).to eq(['T_BOOL:true'])
     end
 
     it "ids should remain untouched" do
-      expect(ast('foo')).to eq(['T_ID:foo'])
+      expect(anf('foo')).to eq(['T_ID:foo'])
+    end
+  end
+
+  context "function applications" do
+    it "should leave an application with no args alone" do
+      expect(anf('foo()')).to eq([['T_ID:foo']])
+    end
+
+    it "should leave an application with one arg alone" do
+      expect(anf('foo(a)')).to eq([['T_ID:foo', 'T_ID:a']])
+    end
+
+    it "should normalize an application with a complex function" do
+      expect(anf('(foo())()')).to eq([['let', ['$:0', ['T_ID:foo']], ['$:0']]])
     end
   end
 end
index b931a7343c00c6ade325b0d4cc65e5ec3844aed6..142c88f15a9b1941b2aa17e083c4697be373fb16 100644 (file)
@@ -29,8 +29,8 @@ def re_structure( token_array, offset = 0 )
   return [offset, struct]
 end
 
-def ast(input)
-  out = cli(['-Aast'], input)
+def ast(input, pass="ast")
+  out = cli(["-A#{pass}"], input)
   # Prep the parens for reading
   out.gsub!(/([()])|tree/,' \1 ')
   # Replace string literals so we can tokenize on spaces
@@ -55,3 +55,8 @@ end
 def ccode(input)
   cli(['-Asrc'], input)
 end
+
+def anf(input)
+  ast(input, "anf")
+end
+