53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
|
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
-
-
|
print_indent(indent);
printf("%s", node->name);
break;
case NODE_LITERAL_INT:
print_indent(indent);
printf("%s", node->name);
break;
case NODE_VAR_DECL:
break; /* is handled seperately at beginning of function */
default:
printf("(UNKNOWN TOKEN)");
}
}
void
print_function_variables(struct function* fun) {
for(int i = 0; i < fun->var_count; ++i) {
struct function_variable* var = &fun->vars[i];
print_indent(1);
printf("%s %s;\n", var->data_type->name, var->name);
}
}
void
print_functions() {
for(int i = 0; i < function_count; ++i) {
struct function* fun = functions[i];
print_data_type(fun->return_type);
printf(" ");
print_mangled_function_name(fun);
printf("(");
for(int i = 0; i < fun->param_count; ++i) {
print_data_type(fun->params[i].data_type);
printf(" %s", fun->params[i].name);
if(i < fun->param_count-1)
printf(", ");
}
printf(") {\n");
print_function_variables(fun);
for(int j = 0; j < fun->body->child_count; ++j) {
print_tree(fun->body->childs[j], 1);
printf(";\n");
}
printf("}\n\n");
}
}
int
main() {
tokenise();
parse();
init_data_types();
annotate();
print_functions();
return 0;
}
/* NEXT STEP:
/* NEXT STEP: */
annotate variable declaration
*/
/* TODO:
- variable declaration
- variable usage
- variable assignment
- if
- while
*/
/* NOTES:
- value types can be stack or heap allocated behind the scenes,
having the compiler insert malloc/free style syscalls where needed.
- function level scopes good enough? easier and faster to implement...
*/
|