#include "../include/ast.h" #include "../include/parser.h" #include "../include/std/log.h" #include "../include/std/hash.h" #include #define throw(result) do { longjmp(context->env, (result)); } while(0) #define throw_if_error(result) \ do { \ int return_if_result; \ return_if_result = (result); \ if((return_if_result) != 0) \ throw(return_if_result); \ } while(0) static void ast_resolve(Ast *self, AstCompilerContext *context); Ast ast_none() { Ast ast; ast.value.func_decl = NULL; ast.type = AST_NONE; return ast; } void ast_init(Ast *self, AstValue value, AstType type) { self->value = value; self->type = type; self->resolve_status = AST_NOT_RESOLVED; } BufferView ast_get_name(Ast *self) { BufferView name; switch(self->type) { case AST_NONE: case AST_FUNCTION_DECL: case AST_IMPORT: case AST_STRING: case AST_NUMBER: case AST_BINOP: name = create_buffer_view_null(); break; case AST_LHS: name = self->value.lhs_expr->var_name; break; case AST_FUNCTION_CALL: name = self->value.func_call->name; break; case AST_VARIABLE: name = self->value.variable->name; break; } return name; } int funcdecl_init(FunctionDecl *self, ScopedAllocator *allocator) { return scope_init(&self->body, allocator); } int funccall_init(FunctionCall *self, BufferView name, ScopedAllocator *allocator) { self->name = name; return buffer_init(&self->args, allocator); } void lhsexpr_init(LhsExpr *self, int isConst, BufferView var_name) { self->is_const = isConst; self->type_name = create_buffer_view_null(); self->var_name = var_name; self->rhs_expr = ast_none(); } void import_init(Import *self, BufferView path) { self->path = path; } int string_init(String *self, BufferView str) { /* TODO: Convert special characters. For example \n should be converted to binary newline etc */ self->str = str; return 0; } void number_init(Number *self, i64 value, bool is_integer) { self->value.integer = value; self->is_integer = is_integer; } void variable_init(Variable *self, BufferView name) { self->name = name; self->resolved_variable = ast_none(); } void binop_init(Binop *self) { self->lhs = ast_none(); self->rhs = ast_none(); self->type = BINOP_ADD; self->grouped = bool_false; } int scope_init(Scope *self, ScopedAllocator *allocator) { return_if_error(buffer_init(&self->ast_objects, allocator)); return_if_error(hash_map_init(&self->named_objects, allocator, sizeof(Ast), hash_compare_string, amal_hash_string)); return 0; } int scope_add_child(Scope *self, Ast *child) { BufferView child_name; Ast existing_child; bool child_already_exists; child_name = ast_get_name(child); if(child_name.data) { child_already_exists = hash_map_get(&self->named_objects, child_name, &existing_child); if(child_already_exists) return AST_ERR_DEF_DUP; cleanup_if_error(hash_map_insert(&self->named_objects, child_name, child)); } cleanup_if_error(buffer_append(&self->ast_objects, child, sizeof(Ast))); return 0; cleanup: return AST_ERR; } void scope_resolve(Scope *self, AstCompilerContext *context) { Ast *ast; Ast *ast_end; ast = buffer_start(&self->ast_objects); ast_end = buffer_end(&self->ast_objects); for(; ast != ast_end; ++ast) { ast_resolve(ast, context); } } static void lhs_resolve(LhsExpr *self, AstCompilerContext *context) { /* TODO: Implement */ amal_log_debug("Lhs resolve %s name: %.*s, type: %.*s", self->is_const ? "const" : "var", self->var_name.size, self->var_name.data, self->type_name.size, self->type_name.data); ast_resolve(&self->rhs_expr, context); } static void funcdecl_resolve(FunctionDecl *self, AstCompilerContext *context) { /* TODO: Implement */ amal_log_debug("funcdecl resolve"); scope_resolve(&self->body, context); } static void funccall_resolve(FunctionCall *self, AstCompilerContext *context) { /* TODO: Implement */ Ast *ast; Ast *ast_end; ast = buffer_start(&self->args); ast_end = buffer_end(&self->args); amal_log_debug("funccall resolve, func name: %.*s", self->name.size, self->name.data); for(; ast != ast_end; ++ast) { ast_resolve(ast, context); } } static void variable_resolve(Variable *self, AstCompilerContext *context) { /* TODO: Implement */ amal_log_debug("variable resolve, var name: %.*s", self->name.size, self->name.data); (void)context; } static void binop_resolve(Binop *self, AstCompilerContext *context) { /* TODO: Implement */ ast_resolve(&self->lhs, context); ast_resolve(&self->rhs, context); } static BufferView ast_get_code_reference(Ast *self) { return ast_get_name(self); } void ast_resolve(Ast *self, AstCompilerContext *context) { if(self->resolve_status == AST_RESOLVED) { return; } else if(self->resolve_status == AST_RESOLVING) { tokenizer_get_code_reference_index(&context->parser->tokenizer, ast_get_code_reference(self).data); tokenizer_print_error(&context->parser->tokenizer, tokenizer_get_code_reference_index(&context->parser->tokenizer, ast_get_code_reference(self).data), "Found recursive declaration"); throw(AST_ERR); } self->resolve_status = AST_RESOLVING; switch(self->type) { case AST_NONE: case AST_NUMBER: /* Nothing to resolve for numbers */ break; case AST_FUNCTION_DECL: funcdecl_resolve(self->value.func_decl, context); break; case AST_FUNCTION_CALL: funccall_resolve(self->value.func_call, context); break; case AST_LHS: lhs_resolve(self->value.lhs_expr, context); break; case AST_IMPORT: /* TODO: When @import(...).data syntax is added, implement the resolve for it */ break; case AST_STRING: /* TODO: Convert special combinations. For example \n to newline */ break; case AST_VARIABLE: variable_resolve(self->value.variable, context); break; case AST_BINOP: binop_resolve(self->value.binop, context); break; } self->resolve_status = AST_RESOLVED; }