From: Michael D. Lowis Date: Sun, 20 Dec 2015 21:32:51 +0000 (-0500) Subject: Implemented ANF transformation for function applications X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=da9f24e9ac31c725eb866fdb0d8d39dad8bbf1d2;p=proto%2Fsclpl.git Implemented ANF transformation for function applications --- diff --git a/source/ast.c b/source/ast.c index e545329..460cfa2 100644 --- a/source/ast.c +++ b/source/ast.c @@ -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; diff --git a/source/main.c b/source/main.c index 2d225cc..e8a21a7 100644 --- a/source/main.c +++ b/source/main.c @@ -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) diff --git a/source/sclpl.h b/source/sclpl.h index 274c9fe..92c5a44 100644 --- a/source/sclpl.h +++ b/source/sclpl.h @@ -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 *****************************************************************************/ diff --git a/spec/anf_spec.rb b/spec/anf_spec.rb index 229d8c6..30342ad 100644 --- a/spec/anf_spec.rb +++ b/spec/anf_spec.rb @@ -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