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);
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;
}
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;
+}
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) {
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)))
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;
}
} 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();
printf(")");
break;
- case AST_ANN:
- break;
-
case AST_FUNC:
printf("(fn (");
for (size_t i = 0; i < vec_size(func_args(tree)); i++) {
printf(")");
break;
+ case AST_LET:
+ printf("(let)");
+ break;
+
default:
pprint_literal(file, tree, depth);
break;
/* 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;
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 */
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 {
--- /dev/null
+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