aboutsummaryrefslogtreecommitdiff
path: root/src/ast.c
diff options
context:
space:
mode:
authorMustafa Quraish <[email protected]>2022-01-30 01:19:54 -0500
committerMustafa Quraish <[email protected]>2022-01-30 01:19:54 -0500
commit5b87ec6ef2b84f1d319e5376bcf9eedea9829d79 (patch)
treef1afa80f034a1cd73192510046978435252e1160 /src/ast.c
parentRemove return-0 example (diff)
downloadcup-5b87ec6ef2b84f1d319e5376bcf9eedea9829d79.tar.xz
cup-5b87ec6ef2b84f1d319e5376bcf9eedea9829d79.zip
Rename `cup` directory to `src`
Diffstat (limited to 'src/ast.c')
-rw-r--r--src/ast.c161
1 files changed, 161 insertions, 0 deletions
diff --git a/src/ast.c b/src/ast.c
new file mode 100644
index 0000000..6e33de1
--- /dev/null
+++ b/src/ast.c
@@ -0,0 +1,161 @@
+#include "ast.h"
+#include <assert.h>
+#include <stdio.h>
+
+char *data_type_to_str(DataType type)
+{
+ switch (type)
+ {
+ case TYPE_NONE: return "void";
+ case TYPE_INT: return "int";
+ default: assert(false && "Unreachable");
+ }
+}
+
+void print_type_to_file(FILE *out, Type type)
+{
+ fprintf(out, "%s", data_type_to_str(type.type));
+ for (int i = 0; i < type.indirection; i++) {
+ fprintf(out, "*");
+ }
+}
+
+char *node_type_to_str(NodeType type)
+{
+ switch (type)
+ {
+ #define ENUM_TOKEN(t, name) case t: return name;
+ ENUM_AST_TYPES(ENUM_TOKEN)
+ #undef ENUM_TOKEN
+ default: assert(false && "Unreachable");
+ }
+}
+
+bool is_binary_op(NodeType type)
+{
+ switch (type)
+ {
+ case OP_PLUS:
+ case OP_MINUS:
+ case OP_MUL:
+ case OP_DIV:
+ case OP_MOD:
+ case OP_LSHIFT:
+ case OP_RSHIFT:
+ case OP_AND:
+ case OP_OR:
+ case OP_XOR:
+ case OP_EQ:
+ case OP_NEQ:
+ case OP_LT:
+ case OP_LEQ:
+ case OP_GT:
+ case OP_GEQ:
+ return true;
+ default: return false;
+ }
+}
+
+bool is_unary_op(NodeType type)
+{
+ switch (type)
+ {
+ case OP_NEG:
+ case OP_NOT:
+ case OP_BWINV:
+ return true;
+ default: return false;
+ }
+}
+
+bool is_expression(NodeType type)
+{
+ if (is_unary_op(type) || is_binary_op(type))
+ return true;
+ return type == AST_LITERAL;
+}
+
+void dump_func(Node *, int);
+
+static void do_print_ast(Node *node, int depth)
+{
+ for (int i = 0; i < depth; i++) {
+ printf(" ");
+ }
+ if (node->type == AST_PROGRAM) {
+ for (int i = 0; i < node->block.num_children; i++) {
+ do_print_ast(node->block.children[i], depth);
+ }
+ } else if (node->type == AST_BLOCK) {
+ printf("{\n");
+ for (int i = 0; i < node->block.num_children; i++) {
+ do_print_ast(node->block.children[i], depth + 1);
+ }
+ for (int i = 0; i < depth; i++) {
+ printf(" ");
+ }
+ printf("}\n");
+ } else if (node->type == AST_FUNC) {
+ dump_func(node, depth);
+ } else if (node->type == AST_LITERAL) {
+ printf("%d\n", node->literal.as_int);
+ } else if (node->type == AST_RETURN) {
+ printf("return\n");
+ do_print_ast(node->unary_expr, depth + 1);
+ } else if (is_unary_op(node->type)) {
+ printf("%s\n", node_type_to_str(node->type));
+ do_print_ast(node->unary_expr, depth + 1);
+ } else if (is_binary_op(node->type)) {
+ printf("%s\n", node_type_to_str(node->type));
+ do_print_ast(node->binary.left, depth + 1);
+ do_print_ast(node->binary.right, depth + 1);
+ } else if (node->type == AST_VAR) {
+ assert(node->variable && node->variable->name);
+ printf("%s\n", node->variable->name);
+ } else if (node->type == AST_VARDECL) {
+ printf("var %s (", node->var_decl.var.name);
+ print_type_to_file(stdout, node->var_decl.var.type);
+ printf(")");
+ if (node->var_decl.value != NULL) {
+ printf(" = \n");
+ do_print_ast(node->var_decl.value, depth + 1);
+ } else {
+ printf("\n");
+ }
+ } else if (node->type == AST_FUNCCALL) {
+ printf("CALL %s(\n", node->call.func->func.name);
+ for (int i = 0; i < node->call.num_args; i++) {
+ do_print_ast(node->call.args[i], depth + 1);
+ }
+ for (int i = 0; i < depth; i++) {
+ printf(" ");
+ }
+ printf(")\n");
+ } else {
+ printf("{{ %s }}\n", node_type_to_str(node->type));
+ }
+}
+
+void dump_func(Node *node, int depth)
+{
+ printf("fn %s(", node->func.name);
+ for (int i = 0; i < node->func.num_args; i++) {
+ if (i > 0) printf(", ");
+ printf("%s: ", node->func.args[i].name);
+ print_type_to_file(stdout, node->func.args[i].type);
+ printf("[[%lld]]", node->func.args[i].offset);
+ }
+ printf(")");
+ if (node->func.return_type.type != TYPE_NONE) {
+ // FIXME: Print return type properly
+ printf(" -> ");
+ print_type_to_file(stdout, node->func.return_type);
+ }
+
+ do_print_ast(node->func.body, depth + 1);
+}
+
+void print_ast(Node *node)
+{
+ do_print_ast(node, 0);
+} \ No newline at end of file