diff options
| author | Bruce Hill <bruce@bruce-hill.com> | 2025-08-24 20:55:29 -0400 |
|---|---|---|
| committer | Bruce Hill <bruce@bruce-hill.com> | 2025-08-24 20:55:29 -0400 |
| commit | f5b2281084d31700690916c6dd250e2da927e566 (patch) | |
| tree | 067f566a72fab976feccdb92f5bc26c16736e3f3 | |
| parent | bb1af5c7b5e76ddd3e76ff75e62c0f0a65026ded (diff) | |
Clean up and fix issue with `if var := val` statements. Previous
implementation was kinda janky, but the new one is more robust and
simple.
| -rw-r--r-- | examples/http-server/http-server.tm | 2 | ||||
| -rw-r--r-- | src/compile/conditionals.c | 39 | ||||
| -rw-r--r-- | src/compile/optionals.c | 21 | ||||
| -rw-r--r-- | src/stdlib/util.h | 11 |
4 files changed, 40 insertions, 33 deletions
diff --git a/examples/http-server/http-server.tm b/examples/http-server/http-server.tm index 89141c32..8e8aff7e 100644 --- a/examples/http-server/http-server.tm +++ b/examples/http-server/http-server.tm @@ -52,7 +52,7 @@ func serve(port:Int32, handler:func(request:HTTPRequest -> HTTPResponse), num_th int opt = 1; if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) err(1, "Couldn't set socket option"); - + struct sockaddr_in addr = {AF_INET, htons(@port), INADDR_ANY}; if (bind(s, (struct sockaddr*)&addr, sizeof(addr)) < 0) err(1, "Couldn't bind to socket"); diff --git a/src/compile/conditionals.c b/src/compile/conditionals.c index 6071b6c4..23d2a177 100644 --- a/src/compile/conditionals.c +++ b/src/compile/conditionals.c @@ -36,19 +36,38 @@ Text_t compile_if_statement(env_t *env, ast_t *ast) { DeclareMatch(if_, ast, If); ast_t *condition = if_->condition; if (condition->tag == Declare) { - if (Match(condition, Declare)->value == NULL) code_err(condition, "This declaration must have a value"); + DeclareMatch(decl, condition, Declare); + if (decl->value == NULL) code_err(condition, "This declaration must have a value"); + env_t *truthy_scope = fresh_scope(env); - Text_t code = Texts("IF_DECLARE(", compile_statement(truthy_scope, condition), ", "); + ast_t *var = decl->var; + type_t *var_type = get_type(truthy_scope, decl->value); + + const char *name = Match(var, Var)->name; bind_statement(truthy_scope, condition); - ast_t *var = Match(condition, Declare)->var; - code = Texts(code, compile_condition(truthy_scope, var), ", "); - type_t *cond_t = get_type(truthy_scope, var); - if (cond_t->tag == OptionalType) { - set_binding(truthy_scope, Match(var, Var)->name, Match(cond_t, OptionalType)->type, - optional_into_nonnone(cond_t, compile(truthy_scope, var))); + + Text_t code = Texts("if (true) {\n", compile_statement(env, condition), // + "if (", compile_condition(truthy_scope, var), ")"); + + env_t *nonnull_scope = truthy_scope; + if (var_type->tag == OptionalType) { + nonnull_scope = fresh_scope(truthy_scope); + set_binding(nonnull_scope, name, Match(var_type, OptionalType)->type, + optional_into_nonnone(var_type, compile(truthy_scope, var))); } - code = Texts(code, compile_statement(truthy_scope, if_->body), ")"); - if (if_->else_body) code = Texts(code, "\nelse ", compile_statement(env, if_->else_body)); + + code = Texts(code, compile_block(nonnull_scope, if_->body)); + + if (if_->else_body) { + Text_t label = Texts("_falsey_", String((int64_t)(ast->start - ast->file->text))); + code = Texts(code, "else goto ", label, + ";\n" + "} else {\n", + label, ":;\n", compile_inline_block(env, if_->else_body), "}\n"); + } else { + code = Texts(code, "}\n"); + } + return code; } else { Text_t code = Texts("if (", compile_condition(env, condition), ")"); diff --git a/src/compile/optionals.c b/src/compile/optionals.c index 1cd86c29..b3d94005 100644 --- a/src/compile/optionals.c +++ b/src/compile/optionals.c @@ -92,21 +92,20 @@ Text_t check_none(type_t *t, Text_t value) { t = Match(t, OptionalType)->type; // NOTE: these use statement expressions ({...;}) because some compilers // complain about excessive parens around equality comparisons - if (t->tag == PointerType || t->tag == FunctionType || t->tag == CStringType) - return Texts("({", value, " == NULL;})"); - else if (t == PATH_TYPE) return Texts("({(", value, ").type.$tag == PATH_NONE;})"); - else if (t == PATH_TYPE_TYPE) return Texts("({(", value, ").$tag == PATH_NONE;})"); - else if (t->tag == BigIntType) return Texts("({(", value, ").small == 0;})"); - else if (t->tag == ClosureType) return Texts("({(", value, ").fn == NULL;})"); + if (t->tag == PointerType || t->tag == FunctionType || t->tag == CStringType) return Texts("(", value, " == NULL)"); + else if (t == PATH_TYPE) return Texts("((", value, ").type.$tag == PATH_NONE)"); + else if (t == PATH_TYPE_TYPE) return Texts("((", value, ").$tag == PATH_NONE)"); + else if (t->tag == BigIntType) return Texts("((", value, ").small == 0)"); + else if (t->tag == ClosureType) return Texts("((", value, ").fn == NULL)"); else if (t->tag == NumType) return Texts(Match(t, NumType)->bits == TYPE_NBITS64 ? "Num$isnan(" : "Num32$isnan(", value, ")"); - else if (t->tag == ListType) return Texts("({(", value, ").length < 0;})"); - else if (t->tag == TableType || t->tag == SetType) return Texts("({(", value, ").entries.length < 0;})"); - else if (t->tag == BoolType) return Texts("({(", value, ") == NONE_BOOL;})"); - else if (t->tag == TextType) return Texts("({(", value, ").length < 0;})"); + else if (t->tag == ListType) return Texts("((", value, ").length < 0)"); + else if (t->tag == TableType || t->tag == SetType) return Texts("((", value, ").entries.length < 0)"); + else if (t->tag == BoolType) return Texts("((", value, ") == NONE_BOOL)"); + else if (t->tag == TextType) return Texts("((", value, ").length < 0)"); else if (t->tag == IntType || t->tag == ByteType || t->tag == StructType) return Texts("(", value, ").is_none"); else if (t->tag == EnumType) { - if (enum_has_fields(t)) return Texts("({(", value, ").$tag == 0;})"); + if (enum_has_fields(t)) return Texts("((", value, ").$tag == 0)"); else return Texts("((", value, ") == 0)"); } print_err("Optional check not implemented for: ", type_to_str(t)); diff --git a/src/stdlib/util.h b/src/stdlib/util.h index a789c5f0..1530bd9e 100644 --- a/src/stdlib/util.h +++ b/src/stdlib/util.h @@ -21,17 +21,6 @@ &var; \ }) -#define IF_DECLARE(decl, expr, block) \ - if (({ \ - decl; \ - expr ? ({ \ - block; \ - 1; \ - }) \ - : 0; \ - })) { \ - } - #define WHEN(type, subj, var, body) \ { \ type var = subj; \ |
