aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ast.h1
-rw-r--r--src/compile/conditionals.c15
-rw-r--r--src/compile/expressions.c4
-rw-r--r--src/stdlib/cli.c2
-rw-r--r--src/typecheck.c3
5 files changed, 17 insertions, 8 deletions
diff --git a/src/ast.h b/src/ast.h
index aaa2a993..c01ba68a 100644
--- a/src/ast.h
+++ b/src/ast.h
@@ -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)