aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compile.c3
-rw-r--r--docs/arrays.md8
-rw-r--r--stdlib/arrays.h10
-rw-r--r--typecheck.c2
4 files changed, 14 insertions, 9 deletions
diff --git a/compile.c b/compile.c
index 2cc3284e..373762ce 100644
--- a/compile.c
+++ b/compile.c
@@ -2963,7 +2963,8 @@ CORD compile(env_t *env, ast_t *ast)
.type=Type(ClosureType, .fn=fn_t));
arg_t *arg_spec = new(arg_t, .name="by", .type=Type(ClosureType, .fn=fn_t), .default_val=default_cmp);
CORD arg_code = compile_arguments(env, ast, arg_spec, call->args);
- return CORD_all("Array$heap_pop_value(", self, ", ", arg_code, ", ", padded_item_size, ", ", compile_type(item_t), ")");
+ return CORD_all("Array$heap_pop_value(", self, ", ", arg_code, ", ", compile_type(item_t), ", _, ",
+ promote_to_optional(item_t, "_"), ", ", compile_none(item_t), ", ", padded_item_size, ")");
} else if (streq(call->name, "binary_search")) {
self = compile_to_pointer_depth(env, call->self, 0, call->args != NULL);
type_t *item_ptr = Type(PointerType, .pointed=item_t, .is_stack=true);
diff --git a/docs/arrays.md b/docs/arrays.md
index 3bb15bdf..7cae399a 100644
--- a/docs/arrays.md
+++ b/docs/arrays.md
@@ -456,12 +456,12 @@ func has(arr: [T] -> Bool)
### `heap_pop`
**Description:**
-Removes and returns the top element of a heap. By default, this is the
-*minimum* value in the heap.
+Removes and returns the top element of a heap or `none` if the array is empty.
+By default, this is the *minimum* value in the heap.
**Signature:**
```tomo
-func heap_pop(arr: @[T], by: func(x,y:&T->Int32) = T.compare -> T)
+func heap_pop(arr: @[T], by: func(x,y:&T->Int32) = T.compare -> T?)
```
**Parameters:**
@@ -471,7 +471,7 @@ func heap_pop(arr: @[T], by: func(x,y:&T->Int32) = T.compare -> T)
default comparison function for the item type will be used.
**Returns:**
-The removed top element of the heap.
+The removed top element of the heap or `none` if the array is empty.
**Example:**
```tomo
diff --git a/stdlib/arrays.h b/stdlib/arrays.h
index f8921e0d..cf1f088b 100644
--- a/stdlib/arrays.h
+++ b/stdlib/arrays.h
@@ -107,9 +107,13 @@ void Array$heapify(Array_t *heap, Closure_t comparison, int64_t padded_item_size
void Array$heap_push(Array_t *heap, const void *item, Closure_t comparison, int64_t padded_item_size);
#define Array$heap_push_value(heap, _value, comparison, padded_item_size) ({ __typeof(_value) value = _value; Array$heap_push(heap, &value, comparison, padded_item_size); })
void Array$heap_pop(Array_t *heap, Closure_t comparison, int64_t padded_item_size);
-#define Array$heap_pop_value(heap, comparison, padded_item_size, type) \
- ({ Array_t *_heap = heap; if (_heap->length == 0) fail("Attempt to pop from an empty array"); \
- type value = *(type*)_heap->data; Array$heap_pop(_heap, comparison, padded_item_size); value; })
+#define Array$heap_pop_value(heap, comparison, type, nonnone_var, nonnone_expr, none_expr, padded_item_size) \
+ ({ Array_t *_heap = heap; \
+ (_heap->length > 0) ? ({ \
+ type nonnone_var = *(type*)_heap->data; \
+ Array$heap_pop(_heap, comparison, padded_item_size); \
+ nonnone_expr; \
+ }) : none_expr; })
Int_t Array$binary_search(Array_t array, void *target, Closure_t comparison);
#define Array$binary_search_value(array, target, comparison) \
({ __typeof(target) _target = target; Array$binary_search(array, &_target, comparison); })
diff --git a/typecheck.c b/typecheck.c
index afbc8df4..f6a75ac9 100644
--- a/typecheck.c
+++ b/typecheck.c
@@ -824,7 +824,7 @@ type_t *get_type(env_t *env, ast_t *ast)
else if (streq(call->name, "first")) return Type(OptionalType, .type=INT_TYPE);
else if (streq(call->name, "from")) return self_value_t;
else if (streq(call->name, "has")) return Type(BoolType);
- else if (streq(call->name, "heap_pop")) return item_type;
+ else if (streq(call->name, "heap_pop")) return Type(OptionalType, .type=item_type);
else if (streq(call->name, "heap_push")) return Type(VoidType);
else if (streq(call->name, "heapify")) return Type(VoidType);
else if (streq(call->name, "insert")) return Type(VoidType);