aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compile/headers.c2
-rw-r--r--src/compile/integers.c8
-rw-r--r--src/compile/statements.c10
-rw-r--r--src/compile/structs.c8
-rw-r--r--src/compile/types.c4
-rw-r--r--src/stdlib/functiontype.c2
-rw-r--r--src/stdlib/paths.c3
-rw-r--r--src/stdlib/structs.c3
-rw-r--r--src/stdlib/structs.h3
-rw-r--r--src/stdlib/types.h11
-rw-r--r--src/typecheck.c5
-rw-r--r--src/types.c8
12 files changed, 34 insertions, 33 deletions
diff --git a/src/compile/headers.c b/src/compile/headers.c
index bc0156ad..f132b312 100644
--- a/src/compile/headers.c
+++ b/src/compile/headers.c
@@ -106,6 +106,8 @@ static void _make_typedefs(compile_typedef_info_t *info, ast_t *ast) {
DeclareMatch(def, ast, LangDef);
*info->header = Texts(*info->header, "typedef Text_t ",
namespace_name(info->env, info->env->namespace, Texts(def->name, "$$type")), ";\n");
+ *info->header = Texts(*info->header, "typedef Text_t ", "Optional",
+ namespace_name(info->env, info->env->namespace, Texts(def->name, "$$type")), ";\n");
}
}
diff --git a/src/compile/integers.c b/src/compile/integers.c
index 41c2b78a..78d48b70 100644
--- a/src/compile/integers.c
+++ b/src/compile/integers.c
@@ -22,11 +22,13 @@ Text_t compile_int_to_type(env_t *env, ast_t *ast, type_t *target) {
return code;
}
- if (target->tag == BigIntType) return compile(env, ast);
+ if (non_optional(target)->tag == BigIntType) return compile(env, ast);
- if (target->tag == OptionalType && Match(target, OptionalType)->type)
+ if (target->tag == OptionalType && Match(target, OptionalType)->type) {
return Texts("((", compile_type(target),
- "){.value=", compile_int_to_type(env, ast, Match(target, OptionalType)->type), "})");
+ "){.value=", compile_int_to_type(env, ast, Match(target, OptionalType)->type),
+ ", .has_value=true})");
+ }
const char *literal = Match(ast, Int)->str;
OptionalInt_t int_val = Int$from_str(literal);
diff --git a/src/compile/statements.c b/src/compile/statements.c
index a9ec4327..0cd85b5d 100644
--- a/src/compile/statements.c
+++ b/src/compile/statements.c
@@ -117,7 +117,15 @@ static Text_t _compile_statement(env_t *env, ast_t *ast) {
code = Texts(code, compile_statement(deferred->defer_env, deferred->block));
}
- type_t *ret_type = get_function_return_type(env, env->fn);
+ type_t *ret_type;
+ if (env->fn->tag == Lambda) {
+ if (Match(env->fn, Lambda)->ret_type != NULL)
+ ret_type = parse_type_ast(env, Match(env->fn, Lambda)->ret_type);
+ else ret_type = ret ? get_type(env, ret) : Type(VoidType);
+ } else {
+ ret_type = get_function_return_type(env, env->fn);
+ }
+
if (ret) {
if (ret_type->tag == VoidType || ret_type->tag == AbortType)
code_err(ast, "This function is not supposed to return any values, "
diff --git a/src/compile/structs.c b/src/compile/structs.c
index 2e7217f6..3f443c44 100644
--- a/src/compile/structs.c
+++ b/src/compile/structs.c
@@ -70,12 +70,14 @@ Text_t compile_struct_header(env_t *env, ast_t *ast) {
Text_t struct_code = def->external ? EMPTY_TEXT : Texts(type_code, " {\n", fields, "};\n");
type_t *t = Table$str_get(*env->types, def->name);
- Text_t unpadded_size = def->opaque ? Texts("sizeof(", type_code, ")") : Texts((int64_t)unpadded_struct_size(t));
Text_t typeinfo_code = Texts("extern const TypeInfo_t ", typeinfo_name, ";\n");
Text_t optional_code = EMPTY_TEXT;
if (!def->opaque) {
- optional_code = Texts("DEFINE_OPTIONAL_TYPE(", compile_type(t), ", ", unpadded_size, ", ",
- namespace_name(env, env->namespace, Texts("$Optional", def->name, "$$type")), ");\n");
+ optional_code = Texts("typedef struct {\n", compile_type(t),
+ " value;\n"
+ "Bool_t has_value;\n"
+ "} ",
+ namespace_name(env, env->namespace, Texts("$Optional", def->name, "$$type")), ";\n");
}
return Texts(struct_code, optional_code, typeinfo_code);
}
diff --git a/src/compile/types.c b/src/compile/types.c
index 58a0260b..2b345b41 100644
--- a/src/compile/types.c
+++ b/src/compile/types.c
@@ -135,8 +135,8 @@ Text_t compile_type_info(type_t *t) {
}
case OptionalType: {
type_t *non_optional = Match(t, OptionalType)->type;
- return Texts("Optional$info(sizeof(", compile_type(non_optional), "), __alignof__(", compile_type(non_optional),
- "), ", compile_type_info(non_optional), ")");
+ return Texts("Optional$info(", (int64_t)type_size(t), ", ", (int64_t)type_align(t), ", ",
+ compile_type_info(non_optional), ")");
}
case TypeInfoType: return Texts("Type$info(", quoted_text(type_to_text(Match(t, TypeInfoType)->type)), ")");
case MemoryType: return Text("&Memory$info");
diff --git a/src/stdlib/functiontype.c b/src/stdlib/functiontype.c
index 3270e0ca..6fc0d6bf 100644
--- a/src/stdlib/functiontype.c
+++ b/src/stdlib/functiontype.c
@@ -19,5 +19,5 @@ Text_t Func$as_text(const void *fn, bool colorize, const TypeInfo_t *type) {
public
PUREFUNC bool Func$is_none(const void *obj, const TypeInfo_t *info) {
(void)info;
- return *(void **)obj == NULL;
+ return ((Closure_t *)obj)->fn == NULL;
}
diff --git a/src/stdlib/paths.c b/src/stdlib/paths.c
index d630ad7d..74526f7d 100644
--- a/src/stdlib/paths.c
+++ b/src/stdlib/paths.c
@@ -690,10 +690,11 @@ OptionalClosure_t Path$by_line(Path_t path) {
// be closed by GC finalizers.
GC_gcollect();
f = fopen(path_str, "r");
- if (f == NULL) return NONE_CLOSURE;
}
}
+ if (f == NULL) return NONE_CLOSURE;
+
FILE **wrapper = GC_MALLOC(sizeof(FILE *));
*wrapper = f;
GC_register_finalizer(wrapper, (void *)_line_reader_cleanup, NULL, NULL, NULL);
diff --git a/src/stdlib/structs.c b/src/stdlib/structs.c
index b08d7967..885b903c 100644
--- a/src/stdlib/structs.c
+++ b/src/stdlib/structs.c
@@ -160,9 +160,8 @@ PUREFUNC public Text_t Struct$as_text(const void *obj, bool colorize, const Type
return Text$concat(text, Text(")"));
}
-PUREFUNC public bool Struct$is_none(const void *obj, const TypeInfo_t *type) { return *(bool *)(obj + type->size); }
-
public
+
void Struct$serialize(const void *obj, FILE *out, Table_t *pointers, const TypeInfo_t *type) {
ptrdiff_t byte_offset = 0;
ptrdiff_t bit_offset = 0;
diff --git a/src/stdlib/structs.h b/src/stdlib/structs.h
index 368a670a..a582e9fb 100644
--- a/src/stdlib/structs.h
+++ b/src/stdlib/structs.h
@@ -13,7 +13,6 @@ PUREFUNC int32_t Struct$compare(const void *x, const void *y, const TypeInfo_t *
PUREFUNC bool Struct$equal(const void *x, const void *y, const TypeInfo_t *type);
PUREFUNC bool PackedData$equal(const void *x, const void *y, const TypeInfo_t *type);
PUREFUNC Text_t Struct$as_text(const void *obj, bool colorize, const TypeInfo_t *type);
-PUREFUNC bool Struct$is_none(const void *obj, const TypeInfo_t *type);
void Struct$serialize(const void *obj, FILE *out, Table_t *pointers, const TypeInfo_t *type);
void Struct$deserialize(FILE *in, void *outval, List_t *pointers, const TypeInfo_t *type);
@@ -23,7 +22,6 @@ void Struct$deserialize(FILE *in, void *outval, List_t *pointers, const TypeInfo
.compare = Struct$compare, \
.equal = Struct$equal, \
.as_text = Struct$as_text, \
- .is_none = Struct$is_none, \
.serialize = Struct$serialize, \
.deserialize = Struct$deserialize, \
}
@@ -34,7 +32,6 @@ void Struct$deserialize(FILE *in, void *outval, List_t *pointers, const TypeInfo
.compare = Struct$compare, \
.equal = PackedData$equal, \
.as_text = Struct$as_text, \
- .is_none = Struct$is_none, \
.serialize = Struct$serialize, \
.deserialize = Struct$deserialize, \
}
diff --git a/src/stdlib/types.h b/src/stdlib/types.h
index 85567815..bd2474fa 100644
--- a/src/stdlib/types.h
+++ b/src/stdlib/types.h
@@ -102,14 +102,3 @@ Text_t Type$as_text(const void *typeinfo, bool colorize, const TypeInfo_t *type)
.tag = TypeInfoInfo, \
.TypeInfoInfo.type_str = typestr, \
.metamethods = {.serialize = cannot_serialize, .deserialize = cannot_deserialize, .as_text = Type$as_text}})
-
-#define DEFINE_OPTIONAL_TYPE(t, unpadded_size, name) \
- typedef struct { \
- union { \
- t value; \
- struct { \
- char _padding[unpadded_size]; \
- Bool_t has_value; \
- }; \
- }; \
- } name
diff --git a/src/typecheck.c b/src/typecheck.c
index b21fa40f..906236c3 100644
--- a/src/typecheck.c
+++ b/src/typecheck.c
@@ -1067,7 +1067,10 @@ type_t *get_type(env_t *env, ast_t *ast) {
}
case Return: {
ast_t *val = Match(ast, Return)->value;
- if (env->fn) env = with_enum_scope(env, get_function_return_type(env, env->fn));
+ if (env->fn && (env->fn->tag != Lambda || Match(env->fn, Lambda)->ret_type != NULL)) {
+ type_t *ret_type = get_function_return_type(env, env->fn);
+ env = with_enum_scope(env, ret_type);
+ }
return Type(ReturnType, .ret = (val ? get_type(env, val) : Type(VoidType)));
}
case Stop:
diff --git a/src/types.c b/src/types.c
index 900588f5..bf986c80 100644
--- a/src/types.c
+++ b/src/types.c
@@ -476,11 +476,9 @@ PUREFUNC size_t type_size(type_t *t) {
default: errx(1, "Invalid integer bit size");
}
case StructType: {
- size_t size = unpadded_struct_size(nonnull);
- size += sizeof(bool); // is_null flag
- size_t align = type_align(nonnull);
- if (align > 0 && (size % align) > 0) size = (size + align) - (size % align);
- return size;
+ arg_t *fields = new (arg_t, .name = "value", .type = nonnull,
+ .next = new (arg_t, .name = "has_value", .type = Type(BoolType)));
+ return type_size(Type(StructType, .fields = fields));
}
default: return type_size(nonnull);
}