From 249a68da840db21caeaffb0ef947995fbcd32490 Mon Sep 17 00:00:00 2001 From: "Michael D. Lowis" Date: Wed, 16 Dec 2015 21:46:57 -0500 Subject: [PATCH] Started laying the groundwork for a-normalization pass --- source/ast.c | 31 +++++++++++++++++++++--------- source/main.c | 49 ++++++++++++++++++++++++++++++++++++++++-------- source/pprint.c | 7 ++++--- source/sclpl.h | 22 +++++++++++----------- spec/anf_spec.rb | 29 ++++++++++++++++++++++++++++ 5 files changed, 107 insertions(+), 31 deletions(-) create mode 100644 spec/anf_spec.rb diff --git a/source/ast.c b/source/ast.c index dd76487..7185904 100644 --- a/source/ast.c +++ b/source/ast.c @@ -2,27 +2,22 @@ static void ast_free(void* ptr) { +// AST_LET AST_TEMP + AST* ast = (AST*)ptr; switch(ast->type) { + case AST_REQ: case AST_IDENT: case AST_STRING: + case AST_SYMBOL: gc_delref(ast->value.text); break; - case AST_REQ: - gc_delref(ast->value.req.name); - break; - case AST_DEF: gc_delref(ast->value.def.name); gc_delref(ast->value.def.value); break; - case AST_ANN: - gc_delref(ast->value.ann.name); - gc_delref(ast->value.ann.value); - break; - case AST_IF: gc_delref(ast->value.ifexpr.cond); gc_delref(ast->value.ifexpr.bthen); @@ -39,6 +34,16 @@ static void ast_free(void* ptr) vec_deinit(&(ast->value.fnapp.args)); break; + case AST_BLOCK: + vec_deinit(&(ast->value.exprs)); + break; + + case AST_LET: + break; + + case AST_TEMP: + break; + default: break; } @@ -294,3 +299,11 @@ void fnapp_add_arg(AST* fnapp, AST* arg) vec_push_back(&(fnapp->value.fnapp.args), gc_addref(arg)); } +AST* Let(AST* temp, AST* val, AST* body) +{ + AST* node = ast(AST_LET); + node->value.let.temp = (AST*)gc_addref(temp); + node->value.let.value = (AST*)gc_addref(val); + node->value.let.body = (AST*)gc_addref(body); + return node; +} diff --git a/source/main.c b/source/main.c index 114dac0..de5700c 100644 --- a/source/main.c +++ b/source/main.c @@ -4,6 +4,28 @@ char* ARGV0; bool Verbose = false; char* Artifact = "bin"; +bool isatomic(AST* tree) +{ + switch (tree->type) { + case AST_STRING: + case AST_SYMBOL: + case AST_IDENT: + case AST_CHAR: + case AST_INT: + case AST_FLOAT: + case AST_BOOL: + case AST_FUNC: + return true; + default: + return false; + } +} + +AST* normalize(AST* tree) +{ + return tree; +} + /* Driver Modes *****************************************************************************/ static int emit_tokens(void) { @@ -14,7 +36,7 @@ static int emit_tokens(void) { return 0; } -static int emit_tree(void) { +static int emit_ast(void) { AST* tree = NULL; Parser* ctx = parser_new(NULL, stdin); while(NULL != (tree = toplevel(ctx))) @@ -22,6 +44,14 @@ static int emit_tree(void) { return 0; } +static int emit_anf(void) { + AST* tree = NULL; + Parser* ctx = parser_new(NULL, stdin); + while(NULL != (tree = toplevel(ctx))) + pprint_tree(stdout, normalize(tree), 0); + return 0; +} + static int emit_csource(void) { return 0; } @@ -58,16 +88,19 @@ int user_main(int argc, char **argv) { } OPTEND; /* Execute the main compiler process */ - if (0 == strcmp("bin", Artifact)) { + + if (0 == strcmp("tok", Artifact)) { + return emit_tokens(); + } else if (0 == strcmp("ast", Artifact)) { + return emit_ast(); + } else if (0 == strcmp("anf", Artifact)) { + return emit_anf(); + } else if (0 == strcmp("src", Artifact)) { + return emit_csource(); + } else if (0 == strcmp("bin", Artifact)) { return emit_program(); } else if (0 == strcmp("lib", Artifact)) { return emit_staticlib(); - } else if (0 == strcmp("src", Artifact)) { - return emit_csource(); - } else if (0 == strcmp("ast", Artifact)) { - return emit_tree(); - } else if (0 == strcmp("tok", Artifact)) { - return emit_tokens(); } else { fprintf(stderr, "Unknonwn artifact type: '%s'\n\n", Artifact); usage(); diff --git a/source/pprint.c b/source/pprint.c index 2dea5c7..2758203 100644 --- a/source/pprint.c +++ b/source/pprint.c @@ -149,9 +149,6 @@ void pprint_tree(FILE* file, AST* tree, int depth) printf(")"); break; - case AST_ANN: - break; - case AST_FUNC: printf("(fn ("); for (size_t i = 0; i < vec_size(func_args(tree)); i++) { @@ -176,6 +173,10 @@ void pprint_tree(FILE* file, AST* tree, int depth) printf(")"); break; + case AST_LET: + printf("(let)"); + break; + default: pprint_literal(file, tree, depth); break; diff --git a/source/sclpl.h b/source/sclpl.h index 18bdd1c..92acc64 100644 --- a/source/sclpl.h +++ b/source/sclpl.h @@ -72,27 +72,18 @@ typedef struct { /* AST Types *****************************************************************************/ typedef enum ASTType { - AST_STRING = 0, AST_SYMBOL, AST_CHAR, AST_INT, AST_FLOAT, AST_BOOL, AST_IDENT, - AST_REQ, AST_DEF, AST_ANN, AST_IF, AST_FUNC, AST_FNAPP, AST_BLOCK + AST_STRING, AST_SYMBOL, AST_CHAR, AST_INT, AST_FLOAT, AST_BOOL, AST_IDENT, + AST_REQ, AST_DEF, AST_IF, AST_FUNC, AST_FNAPP, AST_BLOCK, AST_LET, AST_TEMP } ASTType; typedef struct AST { ASTType type; union { - /* Require Node */ - struct { - char* name; - } req; /* Definition Node */ struct { char* name; struct AST* value; } def; - /* Annotation Node */ - struct { - char* name; - struct AST* value; - } ann; /* If Expression */ struct { struct AST* cond; @@ -109,6 +100,12 @@ typedef struct AST { struct AST* fn; vec_t args; } fnapp; + /* Let Expression */ + struct { + struct AST* temp; + struct AST* value; + struct AST* body; + } let; /* Code Block */ vec_t exprs; /* String, Symbol, Identifier */ @@ -189,6 +186,9 @@ AST* fnapp_fn(AST* fnapp); vec_t* fnapp_args(AST* fnapp); void fnapp_add_arg(AST* func, AST* arg); +/* Let Expression */ +AST* Let(AST* temp, AST* val, AST* body); + /* Lexer and Parser Types *****************************************************************************/ typedef struct { diff --git a/spec/anf_spec.rb b/spec/anf_spec.rb new file mode 100644 index 0000000..0f70771 --- /dev/null +++ b/spec/anf_spec.rb @@ -0,0 +1,29 @@ +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"']) + end + + it "characters should remain untouched" do + expect(ast('\\c')).to eq(['T_CHAR:c']) + end + + it "integers should remain untouched" do + expect(ast('123')).to eq(['T_INT:123']) + end + + it "floats should remain untouched" do + expect(ast('123.0')).to eq(['T_FLOAT:123.000000']) + end + + it "booleans should remain untouched" do + expect(ast('true')).to eq(['T_BOOL:true']) + end + + it "ids should remain untouched" do + expect(ast('foo')).to eq(['T_ID:foo']) + end + end +end -- 2.52.0