]> git.mdlowis.com Git - proto/sclpl.git/commitdiff
implemented code generation for expressions
authorMichael D. Lowis <mike@mdlowis.com>
Tue, 14 Oct 2014 02:10:31 +0000 (22:10 -0400)
committerMichael D. Lowis <mike@mdlowis.com>
Tue, 14 Oct 2014 02:10:31 +0000 (22:10 -0400)
source/sclpl/codegen.c

index a1575cd4bed698daf3e5909373b300c31fc51ba3..800a3665450893504877d64fe06b559e6eb701ee 100644 (file)
@@ -44,6 +44,11 @@ static bool is_formtype(tree_t* p_tree, const char* val) {
 
 /*****************************************************************************/
 
+static void print_indent(int depth) {
+    for(int i = 0; i < (4 * depth); i++)
+        printf("%c", ' ');
+}
+
 static void emit_header(void) {
     puts("#include <sclpl.h>\n");
 }
@@ -58,23 +63,77 @@ static void emit_fn_signature(char* name, tree_t* fnval) {
     }
     printf(")");
 }
+
 static void emit_def_placeholders(vec_t* prgrm) {
     for (size_t idx = 0; idx < vec_size(prgrm); idx++) {
         tree_t* p_tree = (tree_t*)vec_at(prgrm, idx);
         if (is_formtype(p_tree, "def")) {
-            char* name = (char*)get_child_val(p_tree,1);
-            tree_t* value = get_child(p_tree, 2);
-            if (is_formtype(value, "fn")) {
-                emit_fn_signature(name, value);
-                puts(";");
-            } else {
-                printf("val %s;\n", (char*)get_child_val(p_tree,1));
-            }
+            printf("val %s;\n", (char*)get_child_val(p_tree,1));
         }
     }
     puts("");
 }
 
+static void emit_expression(tree_t* p_tree, int depth) {
+    if (p_tree->tag == ATOM) {
+        lex_tok_t* tok = p_tree->ptr.tok;
+        switch (tok->type) {
+            case T_STRING: printf("'%s'", ((char*)tok->value));              break;
+            case T_CHAR:   printf("\\%c", ((char)(int)tok->value));          break;
+            case T_INT:    printf("%ld",  *((long int*)tok->value));         break;
+            case T_FLOAT:  printf("%f",   *((double*)tok->value));           break;
+            case T_BOOL:   printf("%s",   ((int)tok->value)?"true":"false"); break;
+            case T_VAR:    printf("%s",   ((char*)tok->value));              break;
+        }
+    } else if (is_formtype(p_tree, "if")) {
+        printf("IF(");
+        emit_expression(get_child(p_tree, 1), depth);
+        printf(")\n");
+        print_indent(depth+1);
+        emit_expression(get_child(p_tree, 2), depth+1);
+
+        if (vec_size(p_tree->ptr.vec) > 3) {
+            printf("\n");
+            print_indent(depth);
+            printf("ELSE\n");
+            print_indent(depth+1);
+            emit_expression(get_child(p_tree, 4), depth+1);
+        }
+
+    } else if (is_formtype(p_tree, "fn")) {
+        printf("<func>");
+    } else {
+        vec_t* vec = p_tree->ptr.vec;
+        printf("%s(", (char*)get_val(vec_at(vec,0)));
+        for (size_t idx = 1; idx < vec_size(vec); idx++) {
+            emit_expression((tree_t*)vec_at(vec,idx), depth);
+            if (idx+1 < vec_size(vec))
+                printf(", ");
+        }
+        printf(")");
+    }
+}
+
+static void emit_toplevel(vec_t* prgrm) {
+    puts("void toplevel(void) {");
+    for (size_t idx = 0; idx < vec_size(prgrm); idx++) {
+        tree_t* p_tree = (tree_t*)vec_at(prgrm, idx);
+        if (is_formtype(p_tree, "require")) {
+            printf("    extern void %s_toplevel(void);\n", (char*)get_child_val(p_tree,1));
+            printf("    %s_toplevel();\n", (char*)get_child_val(p_tree,1));
+        } else if (is_formtype(p_tree, "def")) {
+            printf("    %s = ", (char*)get_child_val(p_tree,1));
+            emit_expression(get_child(p_tree, 2), 0);
+            printf(";\n");
+        } else {
+            printf("    ");
+            emit_expression(p_tree, 1);
+            printf(";\n");
+        }
+    }
+    puts("}");
+}
+
 static void emit_footer(void) {
 
 }
@@ -82,5 +141,6 @@ static void emit_footer(void) {
 void codegen_csource(FILE* file, vec_t* program) {
     emit_header();
     emit_def_placeholders(program);
+    emit_toplevel(program);
     emit_footer();
 }