pike.git/
src/
pike_types.cmod
Branch:
Tag:
Non-build tags
All tags
No tags
2020-08-29
2020-08-29 13:54:35 by Henrik Grubbström (Grubba) <grubba@grubba.org>
474d9e3d4e76c35bf51d2c4d3a17f9bc667ba1d6 (
132
lines) (+
132
/-
0
)
[
Show
|
Annotate
]
Branch:
master
Compiler
[Typechecker]
: Improve matching against transitive types.
3795:
return ret; }
+
static void push_expand_transitive_type(struct pike_type *cont,
+
struct pike_type *trans,
+
struct pike_type **markers,
+
int num_args)
+
{
+
struct pike_type *tmp;
+
TYPE_STACK_DEBUG("expand_transitive");
+
switch(cont->type) {
+
case T_OR: case T_AND:
+
push_expand_transitive_type(cont->cdr, trans, markers, num_args);
+
push_expand_transitive_type(cont->car, trans, markers, num_args);
+
push_type(cont->type);
+
break;
+
case PIKE_T_FUNCTION:
+
/*
+
* transitive(function(a, b, ...:c), X)
+
*
+
* ==>
+
*
+
* function(a, @transitive(function(b, ...:c), X)
+
*/
+
push_expand_transitive_type(cont->cdr, trans, markers, num_args + 1);
+
push_finished_type(cont->car);
+
push_type(cont->type);
+
break;
+
case T_MANY:
+
if (num_args) {
+
/* No need to expand futher for now. */
+
push_finished_type(trans);
+
push_finished_type(cont);
+
push_type(PIKE_T_TRANSITIVE);
+
} else {
+
/* Two cases:
+
*
+
* transitive(function(:x), function(x, a, b, ...: c))
+
*
+
* ==>
+
*
+
* function(:x) | expand(transitive(function(a, b, ...: c),
+
* function(x, a, b, ...:c)))
+
*
+
* And
+
*
+
* transitive(function(t...:x), function(x, a, b, ...: c))
+
*
+
* ==>
+
*
+
* function(t...:x) |
+
* function(t, @transitive(function(t...:x),
+
* function(x, a, b, c, ...:c)))) |
+
* expand(transitive(function(a, b, ...: c),
+
* function(x, a, b, ...:c)))
+
*/
+
DECLARE_CYCLIC();
+
+
push_finished_type(cont);
+
+
if (!BEGIN_CYCLIC(cont, trans)) {
+
SET_CYCLIC_RET(1);
+
+
/* Check many arg. */
+
push_finished_type_with_markers(cont->car, markers, 0);
+
if (peek_type_stack()->type != T_VOID) {
+
push_finished_type(trans);
+
push_finished_type(cont);
+
push_type(PIKE_T_TRANSITIVE);
+
push_reverse_type(PIKE_T_FUNCTION);
+
push_type(T_OR);
+
} else {
+
compiler_discard_top_type();
+
}
+
+
push_finished_type_with_markers(cont->cdr, markers, 0);
+
tmp = low_new_check_call(trans, peek_type_stack(), 0, NULL);
+
compiler_discard_top_type();
+
+
if (tmp) {
+
/* Valid recursion. */
+
push_expand_transitive_type(tmp, trans, markers, 0);
+
free_type(tmp);
+
push_type(T_OR);
+
}
+
}
+
END_CYCLIC();
+
}
+
break;
+
case PIKE_T_MIXED:
+
push_type(PIKE_T_MIXED);
+
break;
+
default:
+
/* Unsupported. */
+
fprintf(stderr, "Attempting to expand unsupported type: ");
+
simple_describe_type(cont);
+
fprintf(stderr, "\n");
+
push_finished_type(function_type_string);
+
Pike_fatal("Attempt to expand unsupported type: %d\n", cont->type);
+
break;
+
}
+
}
+
+
/* Partially expand transitive types, so that eg matching
+
* against function types works as expected.
+
*/
+
static struct pike_type *expand_transitive(struct pike_type *fun,
+
struct pike_type **markers,
+
int flags)
+
{
+
struct pike_type *ret_type;
+
struct pike_type *cont_type;
+
assert(fun->type == PIKE_T_TRANSITIVE);
+
+
type_stack_mark();
+
push_expand_transitive_type(fun->car, fun->cdr, markers, 0);
+
+
return pop_unfinished_type();
+
}
+
static struct pike_type *low_match_types2(struct pike_type *a, struct pike_type *b, int flags)
3934:
case PIKE_T_TRANSITIVE: {
+
#if 1
+
struct pike_type *t = expand_transitive(a, a_markers, flags);
+
ret = low_match_types(t, b, flags);
+
free_type(t);
+
return ret;
+
#else
/* FIXME */ add_ref(a); return a;
-
+
#endif
} }
4057:
case PIKE_T_TRANSITIVE: {
+
#if 1
+
struct pike_type *t = expand_transitive(b, b_markers, flags);
+
ret = low_match_types(a, t, flags);
+
free_type(t);
+
return ret;
+
#else
/* FIXME */ add_ref(a); return a;
-
+
#endif
} }