1 // This file defines how to compile debug_log
5 #include "../environment.h"
6 #include "../stdlib/datatypes.h"
7 #include "../stdlib/text.h"
8 #include "../stdlib/util.h"
9 #include "../typecheck.h"
10 #include "compilation.h"
13 Text_t compile_debug_log(env_t *env, ast_t *ast) {
14 DeclareMatch(debug, ast, DebugLog);
15 Text_t code = EMPTY_TEXT;
16 for (ast_list_t *value = debug->values; value; value = value->next) {
17 type_t *expr_t = get_type(env, value->ast);
18 if (!expr_t) code_err(value->ast, "I couldn't figure out the type of this expression");
20 Text_t setup = EMPTY_TEXT;
22 if (value->ast->tag == Declare) {
23 DeclareMatch(decl, value->ast, Declare);
24 type_t *t = decl->type ? parse_type_ast(env, decl->type) : get_type(env, decl->value);
25 if (t->tag == FunctionType) t = Type(ClosureType, t);
26 Text_t var = Texts("_$", Match(decl->var, Var)->name);
27 Text_t val_code = compile_declared_value(env, value->ast);
28 setup = Texts(compile_declaration(t, var), ";\n");
29 value_code = Texts("(", var, " = ", val_code, ")");
31 } else if (value->ast->tag == Assign) {
32 DeclareMatch(assign, value->ast, Assign);
33 if (!assign->targets->next && assign->targets->ast->tag == Var && is_idempotent(assign->targets->ast)) {
34 // Common case: assigning to one variable:
35 type_t *lhs_t = get_type(env, assign->targets->ast);
36 if (assign->targets->ast->tag == Index && lhs_t->tag == OptionalType
37 && value_type(get_type(env, Match(assign->targets->ast, Index)->indexed))->tag == TableType)
38 lhs_t = Match(lhs_t, OptionalType)->type;
39 if (has_stack_memory(lhs_t))
40 code_err(value->ast, "Stack references cannot be assigned "
41 "to variables because the "
42 "variable's scope may outlive the "
43 "scope of the stack memory.");
44 env_t *val_scope = with_enum_scope(env, lhs_t);
45 value_code = Texts("(",
46 compile_assignment(env, assign->targets->ast,
47 compile_to_type(val_scope, assign->values->ast, lhs_t)),
51 // Multi-assign or assignment to potentially non-idempotent
53 value_code = Text("({ // Assignment\n");
56 for (ast_list_t *target = assign->targets, *assign_value = assign->values; target && assign_value;
57 target = target->next, assign_value = assign_value->next) {
58 type_t *lhs_t = get_type(env, target->ast);
59 if (target->ast->tag == Index && lhs_t->tag == OptionalType
60 && value_type(get_type(env, Match(target->ast, Index)->indexed))->tag == TableType)
61 lhs_t = Match(lhs_t, OptionalType)->type;
62 if (has_stack_memory(lhs_t))
63 code_err(ast, "Stack references cannot be assigned to "
64 "variables because the "
65 "variable's scope may outlive the scope "
66 "of the stack memory.");
67 if (target == assign->targets) expr_t = lhs_t;
68 env_t *val_scope = with_enum_scope(env, lhs_t);
69 Text_t val_code = compile_to_type(val_scope, assign_value->ast, lhs_t);
70 value_code = Texts(value_code, compile_type(lhs_t), " $", i, " = ", val_code, ";\n");
74 for (ast_list_t *target = assign->targets; target; target = target->next) {
75 value_code = Texts(value_code, compile_assignment(env, target->ast, Texts("$", i)), ";\n");
79 value_code = Texts(value_code, "$1; })");
81 } else if (is_update_assignment(value->ast)) {
82 binary_operands_t update = UPDATE_OPERANDS(value->ast);
83 type_t *lhs_t = get_type(env, update.lhs);
84 if (update.lhs->tag == Index) {
85 type_t *indexed = value_type(get_type(env, Match(update.lhs, Index)->indexed));
86 if (indexed->tag == TableType && Match(indexed, TableType)->default_value == NULL)
87 code_err(update.lhs, "Update assignments are not currently "
88 "supported for tables");
91 ast_t *update_var = new (ast_t);
92 *update_var = *value->ast;
93 update_var->__data.PlusUpdate.lhs = LiteralCode(Text("(*expr)"), .type = lhs_t); // UNSAFE
95 Texts("({", compile_declaration(Type(PointerType, lhs_t), Text("expr")), " = &(",
96 compile_lvalue(env, update.lhs), "); ", compile_statement(env, update_var), "; *expr; })");
98 } else if (expr_t->tag == VoidType || expr_t->tag == AbortType || expr_t->tag == ReturnType) {
99 value_code = Texts("({", compile_statement(env, value->ast), " NULL;})");
100 } else if (expr_t->tag == FunctionType) {
101 expr_t = Type(ClosureType, expr_t);
102 value_code = Texts("(Closure_t){.fn=", compile(env, value->ast), "}");
104 value_code = compile(env, value->ast);
106 if (expr_t->tag == VoidType || expr_t->tag == AbortType) {
107 value_code = Texts(setup, "inspect_void(", value_code, ", ", compile_type_info(expr_t), ", ",
108 (int64_t)(value->ast->start - value->ast->file->text), ", ",
109 (int64_t)(value->ast->end - value->ast->file->text), ");");
111 value_code = Texts(setup, "inspect(", compile_type(expr_t), ", ", value_code, ", ",
112 compile_type_info(expr_t), ", ", (int64_t)(value->ast->start - value->ast->file->text),
113 ", ", (int64_t)(value->ast->end - value->ast->file->text), ");");
115 code = Texts(code, value_code);