Skip to content

Commit

Permalink
improving method sort order
Browse files Browse the repository at this point in the history
  now a Union is considered more specific than type T if some element of the
  Union is more specific than T, and the other elements are not less specific
  than T.
  fixes issue #22
  • Loading branch information
JeffBezanson committed May 19, 2011
1 parent e91b669 commit 51c28d1
Show file tree
Hide file tree
Showing 6 changed files with 108 additions and 24 deletions.
1 change: 1 addition & 0 deletions README
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ Advantages of julia over other comparable systems are as follows:
- High-level constructs for parallelism
- Free and open source
- Multi-dimensional array comprehensions
- Coroutines and cooperative threading
- Rich type system
- Better handling of numeric types
- Macros
Expand Down
2 changes: 1 addition & 1 deletion j/inference.j
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ function static_convert(to::Tuple, from::Tuple)
pseq = true
end
else
return Union()
return None
end
# tuple conversion calls convert recursively
if isseqtype(ce)
Expand Down
13 changes: 4 additions & 9 deletions j/sparse.j
Original file line number Diff line number Diff line change
Expand Up @@ -224,17 +224,12 @@ macro binary_op_A_sparse_B_sparse_res_sparse(op)
end # quote
end # macro

(+)(A::SparseMatrixCSC, B::Number) = (+)(full(A), B)
(+)(A::Number, B::SparseMatrixCSC) = (+)(A, full(B))
(+)(A::SparseMatrixCSC, B::Array) = (+)(full(A), B)
(+)(A::Array, B::SparseMatrixCSC) = (+)(A, full(B))
(+)(A::SparseMatrixCSC, B::Array) = (+)(full(A), B)
(+)(A::SparseMatrixCSC, B::Union(Array,Number)) = (+)(full(A), B)
(+)(A::Union(Array,Number), B::SparseMatrixCSC) = (+)(A, full(B))
@binary_op_A_sparse_B_sparse_res_sparse (+)

(-)(A::SparseMatrixCSC, B::Number) = (-)(full(A), B)
(-)(A::Number, B::SparseMatrixCSC) = (-)(A, full(B))
(-)(A::SparseMatrixCSC, B::Array) = (-)(full(A), B)
(-)(A::Array, B::SparseMatrixCSC) = (-)(A, full(B))
(-)(A::SparseMatrixCSC, B::Union(Array,Number)) = (-)(full(A), B)
(-)(A::Union(Array,Number), B::SparseMatrixCSC) = (-)(A, full(B))
@binary_op_A_sparse_B_sparse_res_sparse (-)

(.*)(A::SparseMatrixCSC, B::Number) = SparseMatrixCSC(A.m, A.n, A.colptr, A.rowval, A.nzval .* B)
Expand Down
5 changes: 3 additions & 2 deletions src/gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,8 @@ static void *pool_alloc(pool_t *p)

static void sweep_pool(pool_t *p)
{
int empty, freedall;
//int empty;
int freedall;
gcval_t **prev_pfl;
gcval_t *v;
gcpage_t *pg = p->pages;
Expand All @@ -287,7 +288,7 @@ static void sweep_pool(pool_t *p)
while (pg != NULL) {
char *lim = (char*)pg + GC_PAGE_SZ - p->osize;
v = (gcval_t*)&pg->data[0];
empty = 1;
//empty = 1;
freedall = 1;
prev_pfl = pfl;
while ((char*)v <= lim) {
Expand Down
39 changes: 39 additions & 0 deletions src/gf.c
Original file line number Diff line number Diff line change
Expand Up @@ -687,6 +687,18 @@ static jl_tuple_t *find_tvars(jl_value_t *v, jl_tuple_t *env)
return env;
}

static int has_unions(jl_tuple_t *type)
{
int i;
for(i=0; i < type->length; i++) {
jl_value_t *t = jl_tupleref(type,i);
if (jl_is_union_type(t) ||
(jl_is_seq_type(t) && jl_is_union_type(jl_tparam0(t))))
return 1;
}
return 0;
}

static
jl_methlist_t *jl_method_list_insert(jl_methlist_t **pml, jl_tuple_t *type,
jl_function_t *method, int check_amb)
Expand Down Expand Up @@ -733,6 +745,33 @@ jl_methlist_t *jl_method_list_insert(jl_methlist_t **pml, jl_tuple_t *type,
newrec->next = l;
*pl = newrec;
JL_GC_POP();
// if this contains Union types, methods after it might actually be
// more specific than it. we need to re-sort them.
if (has_unions(type)) {
jl_methlist_t *item = newrec->next, *next;
jl_methlist_t **pitem = &newrec->next, **pnext;
while (item != NULL) {
pl = pml;
l = *pml;
next = item->next;
pnext = &item->next;
while (l != newrec->next) {
if (args_morespecific((jl_value_t*)item->sig,
(jl_value_t*)l->sig)) {
// reinsert item earlier in the list
*pitem = next;
item->next = l;
*pl = item;
pnext = pitem;
break;
}
pl = &l->next;
l = l->next;
}
item = next;
pitem = pnext;
}
}
return newrec;
}

Expand Down
72 changes: 60 additions & 12 deletions src/jltypes.c
Original file line number Diff line number Diff line change
Expand Up @@ -1338,7 +1338,11 @@ int jl_subtype_le(jl_value_t *a, jl_value_t *b, int ta, int morespecific)
return jl_subtype_le(a, jl_tparam0(b), 0, morespecific);
}
}
size_t i;
else if (a == b) {
// None <: None
return 1;
}
size_t i, j;
if (jl_is_tuple(a)) {
if ((jl_tuple_t*)b == jl_tuple_type) return 1;
if (jl_is_tag_type(b) &&
Expand All @@ -1356,16 +1360,34 @@ int jl_subtype_le(jl_value_t *a, jl_value_t *b, int ta, int morespecific)

if (!ta && jl_is_union_type(a)) {
jl_tuple_t *ap = ((jl_uniontype_t*)a)->types;
for(i=0; i < ap->length; i++) {
if (!jl_subtype_le(jl_tupleref(ap,i), b, 0, morespecific))
return 0;
if (morespecific) {
// Union a is more specific than b if some element of a is
// more specific than b, and b is not more specific than any
// element of a.
for(i=0; i < ap->length; i++) {
if (jl_subtype_le(jl_tupleref(ap,i), b, 0, 1) &&
!jl_subtype_le(b, jl_tupleref(ap,i), 0, 1)) {
for(j=0; j < ap->length; j++) {
if (jl_subtype_le(b, jl_tupleref(ap,j), 0, 1) &&
!jl_subtype_le(jl_tupleref(ap,j), b, 0, 1)) {
return 0;
}
}
return 1;
}
}
return 0;
}
else {
for(i=0; i < ap->length; i++) {
if (!jl_subtype_le(jl_tupleref(ap,i), b, 0, morespecific))
return 0;
}
}
return 1;
}

if (jl_is_union_type(b)) {
// None <: None
if (!ta && a == b && b==(jl_value_t*)jl_bottom_type) return 1;
jl_tuple_t *bp = ((jl_uniontype_t*)b)->types;
for(i=0; i < bp->length; i++) {
if (jl_subtype_le(a, jl_tupleref(bp,i), ta, morespecific))
Expand Down Expand Up @@ -1510,7 +1532,7 @@ static jl_value_t *tuple_match(jl_tuple_t *child, jl_tuple_t *parent,
if (pseq) pe = jl_tparam0(pe);

*env = (jl_tuple_t*)type_match_(ce, pe, env, morespecific);
if ((jl_value_t*)*env == jl_false) return (jl_value_t*)*env;
if ((jl_value_t*)*env == jl_false) return jl_false;

if (cseq && pseq) return (jl_value_t*)*env;
if (!cseq) ci++;
Expand All @@ -1535,7 +1557,7 @@ static jl_value_t *type_match_(jl_value_t *child, jl_value_t *parent,
child = (jl_value_t*)((jl_typector_t*)child)->body;
if (jl_is_typector(parent))
parent = (jl_value_t*)((jl_typector_t*)parent)->body;
size_t i;
size_t i, j;
if (jl_is_typevar(parent)) {
// make sure type is within this typevar's bounds
if (!jl_subtype_le(child, parent, 0, 0))
Expand Down Expand Up @@ -1593,10 +1615,36 @@ static jl_value_t *type_match_(jl_value_t *child, jl_value_t *parent,

if (jl_is_union_type(child)) {
jl_tuple_t *t = ((jl_uniontype_t*)child)->types;
for(i=0; i < t->length; i++) {
*env = (jl_tuple_t*)type_match_(jl_tupleref(t,i), parent, env,
morespecific);
if ((jl_value_t*)*env == jl_false) return (jl_value_t*)*env;
if (morespecific) {
for(i=0; i < t->length; i++) {
jl_value_t *tmp, *tmp2;
jl_tuple_t *tenv = jl_null;
tmp = type_match_(jl_tupleref(t,i), parent, env, 1);
if (tmp != jl_false) {
*env = (jl_tuple_t*)tmp;
tmp2 = type_match_(parent, jl_tupleref(t,i), &tenv, 1);
if (tmp2 == jl_false) {
for(j=0; j < t->length; j++) {
tenv = jl_null;
if (type_match_(parent, jl_tupleref(t,j),
&tenv, 1) != jl_false &&
type_match_(jl_tupleref(t,j), parent,
env, 1) == jl_false) {
return jl_false;
}
}
return (jl_value_t*)*env;
}
}
}
return jl_false;
}
else {
for(i=0; i < t->length; i++) {
*env = (jl_tuple_t*)type_match_(jl_tupleref(t,i), parent, env,
morespecific);
if ((jl_value_t*)*env == jl_false) return jl_false;
}
}
return (jl_value_t*)*env;
}
Expand Down

0 comments on commit 51c28d1

Please sign in to comment.