diff options
Diffstat (limited to 'src/compile')
| -rw-r--r-- | src/compile/README.md | 2 | ||||
| -rw-r--r-- | src/compile/compilation.h | 2 | ||||
| -rw-r--r-- | src/compile/debuglog.c | 115 | ||||
| -rw-r--r-- | src/compile/debuglog.h (renamed from src/compile/doctests.h) | 4 | ||||
| -rw-r--r-- | src/compile/doctests.c | 118 | ||||
| -rw-r--r-- | src/compile/expressions.c | 2 | ||||
| -rw-r--r-- | src/compile/functions.c | 5 | ||||
| -rw-r--r-- | src/compile/statements.c | 2 |
8 files changed, 124 insertions, 126 deletions
diff --git a/src/compile/README.md b/src/compile/README.md index df76d648..7a841231 100644 --- a/src/compile/README.md +++ b/src/compile/README.md @@ -11,7 +11,7 @@ This directory contains the source files for actual cross-compilation - Comparisons (`a == b`, `a > b`, etc): [comparisons.c](comparisons.c) - Conditionals (`if` statements): [conditionals.c](conditionals.c) - Variable declarations: [declarations.c](declarations.c) -- Doctests (`>> test`): [doctests.c](doctests.c) +- Debug logs (`>> expr`): [debuglog.c](debuglog.c) - Enums (`enum`): [enums.c](enums.c) - General logic for compiling expressions: [expressions.c](expressions.c) - Field accesses (`foo.baz`) [fieldaccess.c](fieldaccess.c) diff --git a/src/compile/compilation.h b/src/compile/compilation.h index d881684b..5c949836 100644 --- a/src/compile/compilation.h +++ b/src/compile/compilation.h @@ -10,8 +10,8 @@ #include "comparisons.h" // IWYU pragma: export #include "compilation.h" // IWYU pragma: export #include "conditionals.h" // IWYU pragma: export +#include "debuglog.h" // IWYU pragma: export #include "declarations.h" // IWYU pragma: export -#include "doctests.h" // IWYU pragma: export #include "enums.h" // IWYU pragma: export #include "expressions.h" // IWYU pragma: export #include "fieldaccess.h" // IWYU pragma: export diff --git a/src/compile/debuglog.c b/src/compile/debuglog.c new file mode 100644 index 00000000..498820ee --- /dev/null +++ b/src/compile/debuglog.c @@ -0,0 +1,115 @@ +// This file defines how to compile debug_log + +#include "../ast.h" +#include "../config.h" +#include "../environment.h" +#include "../stdlib/datatypes.h" +#include "../stdlib/text.h" +#include "../stdlib/util.h" +#include "../typecheck.h" +#include "compilation.h" + +public +Text_t compile_debug_log(env_t *env, ast_t *ast) { + DeclareMatch(debug, ast, DebugLog); + Text_t code = EMPTY_TEXT; + for (ast_list_t *value = debug->values; value; value = value->next) { + type_t *expr_t = get_type(env, value->ast); + if (!expr_t) code_err(value->ast, "I couldn't figure out the type of this expression"); + + Text_t setup = EMPTY_TEXT; + Text_t value_code; + if (value->ast->tag == Declare) { + DeclareMatch(decl, value->ast, Declare); + type_t *t = decl->type ? parse_type_ast(env, decl->type) : get_type(env, decl->value); + if (t->tag == FunctionType) t = Type(ClosureType, t); + Text_t var = Texts("_$", Match(decl->var, Var)->name); + Text_t val_code = compile_declared_value(env, value->ast); + setup = Texts(compile_declaration(t, var), ";\n"); + value_code = Texts("(", var, " = ", val_code, ")"); + expr_t = t; + } else if (value->ast->tag == Assign) { + DeclareMatch(assign, value->ast, Assign); + if (!assign->targets->next && assign->targets->ast->tag == Var && is_idempotent(assign->targets->ast)) { + // Common case: assigning to one variable: + type_t *lhs_t = get_type(env, assign->targets->ast); + if (assign->targets->ast->tag == Index && lhs_t->tag == OptionalType + && value_type(get_type(env, Match(assign->targets->ast, Index)->indexed))->tag == TableType) + lhs_t = Match(lhs_t, OptionalType)->type; + if (has_stack_memory(lhs_t)) + code_err(value->ast, "Stack references cannot be assigned " + "to variables because the " + "variable's scope may outlive the " + "scope of the stack memory."); + env_t *val_scope = with_enum_scope(env, lhs_t); + value_code = Texts("(", + compile_assignment(env, assign->targets->ast, + compile_to_type(val_scope, assign->values->ast, lhs_t)), + ")"); + expr_t = lhs_t; + } else { + // Multi-assign or assignment to potentially non-idempotent + // targets + value_code = Text("({ // Assignment\n"); + + int64_t i = 1; + for (ast_list_t *target = assign->targets, *assign_value = assign->values; target && assign_value; + target = target->next, assign_value = assign_value->next) { + type_t *lhs_t = get_type(env, target->ast); + if (target->ast->tag == Index && lhs_t->tag == OptionalType + && value_type(get_type(env, Match(target->ast, Index)->indexed))->tag == TableType) + lhs_t = Match(lhs_t, OptionalType)->type; + if (has_stack_memory(lhs_t)) + code_err(ast, "Stack references cannot be assigned to " + "variables because the " + "variable's scope may outlive the scope " + "of the stack memory."); + if (target == assign->targets) expr_t = lhs_t; + env_t *val_scope = with_enum_scope(env, lhs_t); + Text_t val_code = compile_to_type(val_scope, assign_value->ast, lhs_t); + value_code = Texts(value_code, compile_type(lhs_t), " $", i, " = ", val_code, ";\n"); + i += 1; + } + i = 1; + for (ast_list_t *target = assign->targets; target; target = target->next) { + value_code = Texts(value_code, compile_assignment(env, target->ast, Texts("$", i)), ";\n"); + i += 1; + } + + value_code = Texts(value_code, "$1; })"); + } + } else if (is_update_assignment(value->ast)) { + binary_operands_t update = UPDATE_OPERANDS(value->ast); + type_t *lhs_t = get_type(env, update.lhs); + if (update.lhs->tag == Index) { + type_t *indexed = value_type(get_type(env, Match(update.lhs, Index)->indexed)); + if (indexed->tag == TableType && Match(indexed, TableType)->default_value == NULL) + code_err(update.lhs, "Update assignments are not currently " + "supported for tables"); + } + + ast_t *update_var = new (ast_t); + *update_var = *value->ast; + update_var->__data.PlusUpdate.lhs = LiteralCode(Text("(*expr)"), .type = lhs_t); // UNSAFE + value_code = + Texts("({", compile_declaration(Type(PointerType, lhs_t), Text("expr")), " = &(", + compile_lvalue(env, update.lhs), "); ", compile_statement(env, update_var), "; *expr; })"); + expr_t = lhs_t; + } else if (expr_t->tag == VoidType || expr_t->tag == AbortType || expr_t->tag == ReturnType) { + value_code = Texts("({", compile_statement(env, value->ast), " NULL;})"); + } else { + value_code = compile(env, value->ast); + } + if (expr_t->tag == VoidType || expr_t->tag == AbortType) { + value_code = Texts(setup, "inspect_void(", value_code, ", ", compile_type_info(expr_t), ", ", + (int64_t)(value->ast->start - value->ast->file->text), ", ", + (int64_t)(value->ast->end - value->ast->file->text), ");"); + } else { + value_code = Texts(setup, "inspect(", compile_type(expr_t), ", ", value_code, ", ", + compile_type_info(expr_t), ", ", (int64_t)(value->ast->start - value->ast->file->text), + ", ", (int64_t)(value->ast->end - value->ast->file->text), ");"); + } + code = Texts(code, value_code); + } + return code; +} diff --git a/src/compile/doctests.h b/src/compile/debuglog.h index 06603e1a..30b14776 100644 --- a/src/compile/doctests.h +++ b/src/compile/debuglog.h @@ -1,4 +1,4 @@ -// This file defines how to compile doctests +// This file defines how to compile debug logs #pragma once @@ -6,4 +6,4 @@ #include "../environment.h" #include "../stdlib/datatypes.h" -Text_t compile_doctest(env_t *env, ast_t *ast); +Text_t compile_debug_log(env_t *env, ast_t *ast); diff --git a/src/compile/doctests.c b/src/compile/doctests.c deleted file mode 100644 index 20081ae7..00000000 --- a/src/compile/doctests.c +++ /dev/null @@ -1,118 +0,0 @@ -// This file defines how to compile doctests - -#include "../ast.h" -#include "../config.h" -#include "../environment.h" -#include "../stdlib/datatypes.h" -#include "../stdlib/text.h" -#include "../stdlib/util.h" -#include "../typecheck.h" -#include "compilation.h" - -public -Text_t compile_doctest(env_t *env, ast_t *ast) { - DeclareMatch(test, ast, DocTest); - type_t *expr_t = get_type(env, test->expr); - if (!expr_t) code_err(test->expr, "I couldn't figure out the type of this expression"); - - Text_t setup = EMPTY_TEXT; - Text_t test_code; - if (test->expr->tag == Declare) { - DeclareMatch(decl, test->expr, Declare); - type_t *t = decl->type ? parse_type_ast(env, decl->type) : get_type(env, decl->value); - if (t->tag == FunctionType) t = Type(ClosureType, t); - Text_t var = Texts("_$", Match(decl->var, Var)->name); - Text_t val_code = compile_declared_value(env, test->expr); - setup = Texts(compile_declaration(t, var), ";\n"); - test_code = Texts("(", var, " = ", val_code, ")"); - expr_t = t; - } else if (test->expr->tag == Assign) { - DeclareMatch(assign, test->expr, Assign); - if (!assign->targets->next && assign->targets->ast->tag == Var && is_idempotent(assign->targets->ast)) { - // Common case: assigning to one variable: - type_t *lhs_t = get_type(env, assign->targets->ast); - if (assign->targets->ast->tag == Index && lhs_t->tag == OptionalType - && value_type(get_type(env, Match(assign->targets->ast, Index)->indexed))->tag == TableType) - lhs_t = Match(lhs_t, OptionalType)->type; - if (has_stack_memory(lhs_t)) - code_err(test->expr, "Stack references cannot be assigned " - "to variables because the " - "variable's scope may outlive the " - "scope of the stack memory."); - env_t *val_scope = with_enum_scope(env, lhs_t); - Text_t value = compile_to_type(val_scope, assign->values->ast, lhs_t); - test_code = Texts("(", compile_assignment(env, assign->targets->ast, value), ")"); - expr_t = lhs_t; - } else { - // Multi-assign or assignment to potentially non-idempotent - // targets - if (test->expected && assign->targets->next) - code_err(ast, "Sorry, but doctesting with '=' is not " - "supported for " - "multi-assignments"); - - test_code = Text("({ // Assignment\n"); - - int64_t i = 1; - for (ast_list_t *target = assign->targets, *value = assign->values; target && value; - target = target->next, value = value->next) { - type_t *lhs_t = get_type(env, target->ast); - if (target->ast->tag == Index && lhs_t->tag == OptionalType - && value_type(get_type(env, Match(target->ast, Index)->indexed))->tag == TableType) - lhs_t = Match(lhs_t, OptionalType)->type; - if (has_stack_memory(lhs_t)) - code_err(ast, "Stack references cannot be assigned to " - "variables because the " - "variable's scope may outlive the scope " - "of the stack memory."); - if (target == assign->targets) expr_t = lhs_t; - env_t *val_scope = with_enum_scope(env, lhs_t); - Text_t val_code = compile_to_type(val_scope, value->ast, lhs_t); - test_code = Texts(test_code, compile_type(lhs_t), " $", i, " = ", val_code, ";\n"); - i += 1; - } - i = 1; - for (ast_list_t *target = assign->targets; target; target = target->next) { - test_code = Texts(test_code, compile_assignment(env, target->ast, Texts("$", i)), ";\n"); - i += 1; - } - - test_code = Texts(test_code, "$1; })"); - } - } else if (is_update_assignment(test->expr)) { - binary_operands_t update = UPDATE_OPERANDS(test->expr); - type_t *lhs_t = get_type(env, update.lhs); - if (update.lhs->tag == Index) { - type_t *indexed = value_type(get_type(env, Match(update.lhs, Index)->indexed)); - if (indexed->tag == TableType && Match(indexed, TableType)->default_value == NULL) - code_err(update.lhs, "Update assignments are not currently " - "supported for tables"); - } - - ast_t *update_var = new (ast_t); - *update_var = *test->expr; - update_var->__data.PlusUpdate.lhs = LiteralCode(Text("(*expr)"), .type = lhs_t); // UNSAFE - test_code = Texts("({", compile_declaration(Type(PointerType, lhs_t), Text("expr")), " = &(", - compile_lvalue(env, update.lhs), "); ", compile_statement(env, update_var), "; *expr; })"); - expr_t = lhs_t; - } else if (expr_t->tag == VoidType || expr_t->tag == AbortType || expr_t->tag == ReturnType) { - test_code = Texts("({", compile_statement(env, test->expr), " NULL;})"); - } else { - test_code = compile(env, test->expr); - } - if (test->expected) { - return Texts(setup, "test(", compile_type(expr_t), ", ", test_code, ", ", - compile_to_type(env, test->expected, expr_t), ", ", compile_type_info(expr_t), ", ", - (int64_t)(test->expr->start - test->expr->file->text), ", ", - (int64_t)(test->expr->end - test->expr->file->text), ");"); - } else { - if (expr_t->tag == VoidType || expr_t->tag == AbortType) { - return Texts(setup, "inspect_void(", test_code, ", ", compile_type_info(expr_t), ", ", - (int64_t)(test->expr->start - test->expr->file->text), ", ", - (int64_t)(test->expr->end - test->expr->file->text), ");"); - } - return Texts(setup, "inspect(", compile_type(expr_t), ", ", test_code, ", ", compile_type_info(expr_t), ", ", - (int64_t)(test->expr->start - test->expr->file->text), ", ", - (int64_t)(test->expr->end - test->expr->file->text), ");"); - } -} diff --git a/src/compile/expressions.c b/src/compile/expressions.c index f4326b00..a4603cd5 100644 --- a/src/compile/expressions.c +++ b/src/compile/expressions.c @@ -249,7 +249,7 @@ Text_t compile(env_t *env, ast_t *ast) { case Stop: case Pass: case Return: - case DocTest: + case DebugLog: case Assert: code_err(ast, "This is not a valid expression"); case Unknown: default: code_err(ast, "Unknown AST: ", ast_to_sexp_str(ast)); diff --git a/src/compile/functions.c b/src/compile/functions.c index 5f6f7e91..eea46ebf 100644 --- a/src/compile/functions.c +++ b/src/compile/functions.c @@ -556,8 +556,9 @@ static void add_closed_vars(Table_t *closed_vars, env_t *enclosing_scope, env_t add_closed_vars(closed_vars, enclosing_scope, env, Match(ast, NonOptional)->value); break; } - case DocTest: { - add_closed_vars(closed_vars, enclosing_scope, env, Match(ast, DocTest)->expr); + case DebugLog: { + for (ast_list_t *value = Match(ast, DebugLog)->values; value; value = value->next) + add_closed_vars(closed_vars, enclosing_scope, env, value->ast); break; } case Assert: { diff --git a/src/compile/statements.c b/src/compile/statements.c index a7705adc..37eff680 100644 --- a/src/compile/statements.c +++ b/src/compile/statements.c @@ -36,7 +36,7 @@ static Text_t compile_simple_update_assignment(env_t *env, ast_t *ast, const cha static Text_t _compile_statement(env_t *env, ast_t *ast) { switch (ast->tag) { case When: return compile_when_statement(env, ast); - case DocTest: return compile_doctest(env, ast); + case DebugLog: return compile_debug_log(env, ast); case Assert: return compile_assertion(env, ast); case Declare: { DeclareMatch(decl, ast, Declare); |
