diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/ast.h | 1 | ||||
| -rw-r--r-- | src/compile/conditionals.c | 15 | ||||
| -rw-r--r-- | src/compile/expressions.c | 4 | ||||
| -rw-r--r-- | src/stdlib/cli.c | 2 | ||||
| -rw-r--r-- | src/typecheck.c | 3 |
5 files changed, 17 insertions, 8 deletions
@@ -287,6 +287,7 @@ struct ast_s { struct { } Unknown; struct { + struct type_s *type; } None; struct { bool b; diff --git a/src/compile/conditionals.c b/src/compile/conditionals.c index caebdbde..64be29fa 100644 --- a/src/compile/conditionals.c +++ b/src/compile/conditionals.c @@ -126,17 +126,22 @@ Text_t compile_if_expression(env_t *env, ast_t *ast) { } type_t *true_type = get_type(truthy_scope, if_->body); - type_t *false_type = get_type(falsey_scope, if_->else_body); + ast_t *else_body = if_->else_body; + if (else_body && else_body->tag == Block && Match(else_body, Block)->statements + && !Match(else_body, Block)->statements->next) + else_body = Match(else_body, Block)->statements->ast; + if (else_body == NULL || else_body->tag == None) else_body = WrapAST(ast, None, .type = true_type); + type_t *false_type = get_type(falsey_scope, else_body); if (true_type->tag == AbortType || true_type->tag == ReturnType) return Texts("({ ", decl_code, "if (", condition_code, ") ", compile_statement(truthy_scope, if_->body), "\n", - compile(falsey_scope, if_->else_body), "; })"); + compile(falsey_scope, else_body), "; })"); else if (false_type->tag == AbortType || false_type->tag == ReturnType) - return Texts("({ ", decl_code, "if (!(", condition_code, ")) ", compile_statement(falsey_scope, if_->else_body), + return Texts("({ ", decl_code, "if (!(", condition_code, ")) ", compile_statement(falsey_scope, else_body), "\n", compile(truthy_scope, if_->body), "; })"); else if (decl_code.length > 0) return Texts("({ ", decl_code, "(", condition_code, ") ? ", compile(truthy_scope, if_->body), " : ", - compile(falsey_scope, if_->else_body), ";})"); + compile(falsey_scope, else_body), ";})"); else return Texts("((", condition_code, ") ? ", compile(truthy_scope, if_->body), " : ", - compile(falsey_scope, if_->else_body), ")"); + compile(falsey_scope, else_body), ")"); } diff --git a/src/compile/expressions.c b/src/compile/expressions.c index 108bda80..130a267c 100644 --- a/src/compile/expressions.c +++ b/src/compile/expressions.c @@ -66,7 +66,9 @@ Text_t compile_empty(type_t *t) { Text_t compile(env_t *env, ast_t *ast) { switch (ast->tag) { case None: { - code_err(ast, "I can't figure out what this `none`'s type is!"); + type_t *type = Match(ast, None)->type; + if (type == NULL) code_err(ast, "I can't figure out what this `none`'s type is!"); + return compile_none(non_optional(type)); } case Bool: return Match(ast, Bool)->b ? Text("yes") : Text("no"); case Var: { diff --git a/src/stdlib/cli.c b/src/stdlib/cli.c index 08260171..359220e9 100644 --- a/src/stdlib/cli.c +++ b/src/stdlib/cli.c @@ -216,7 +216,7 @@ static List_t parse_arg_list(List_t args, const char *flag, void *dest, const Ty } else { args = parse_arg_list(args, flag, dest, nonnull, allow_dashes); if (nonnull == &Int$info || nonnull == &Path$info || nonnull == &Num$info || nonnull == &Num32$info - || nonnull->tag == TextInfo) + || nonnull->tag == TextInfo || nonnull->tag == EnumInfo) return args; else if (nonnull == &Int64$info) ((OptionalInt64_t *)dest)->has_value = true; else if (nonnull == &Int32$info) ((OptionalInt32_t *)dest)->has_value = true; diff --git a/src/typecheck.c b/src/typecheck.c index 07c3acf9..a0e55a88 100644 --- a/src/typecheck.c +++ b/src/typecheck.c @@ -1376,7 +1376,6 @@ type_t *get_type(env_t *env, ast_t *ast) { case If: { DeclareMatch(if_, ast, If); - if (!if_->else_body) return Type(VoidType); env_t *truthy_scope = env; env_t *falsey_scope = env; @@ -1401,6 +1400,8 @@ type_t *get_type(env_t *env, ast_t *ast) { } type_t *true_t = get_type(truthy_scope, if_->body); + ast_t *else_body = if_->else_body; + if (!else_body) else_body = WrapAST(ast, None, .type = true_t); type_t *false_t = get_type(falsey_scope, if_->else_body); type_t *t_either = type_or_type(true_t, false_t); if (!t_either) |
