Skip to content

Commit

Permalink
extend isbound() to checking for undefined array and struct elements
Browse files Browse the repository at this point in the history
closes #105
  • Loading branch information
JeffBezanson committed Oct 18, 2012
1 parent 8f82ffd commit 07baa31
Show file tree
Hide file tree
Showing 7 changed files with 78 additions and 34 deletions.
23 changes: 4 additions & 19 deletions base/deepcopy.jl
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,8 @@ function _deepcopy_t(x, T::CompositeKind, stackdict::ObjectIdDict)
ret = ccall(:jl_new_struct_uninit, Any, (Any,), T)
stackdict[x] = ret
for f in T.names
try
if isbound(x,f)
ret.(f) = deepcopy_internal(x.(f), stackdict)
catch err
# we ignore undefined references errors
if !isa(err, UndefRefError)
throw(err)
end
end
end
return ret
Expand All @@ -57,19 +52,9 @@ _deepcopy_array_t(x, T::BitsKind, stackdict::ObjectIdDict) = copy(x)
function _deepcopy_array_t(x, T, stackdict::ObjectIdDict)
dest = similar(x)
stackdict[x] = dest
i0 = 1; local i
while true
try
for i=i0:length(x)
arrayset(dest, deepcopy_internal(x[i], stackdict), i)
end
break
catch err
# we ignore undefined references errors
if !isa(err, UndefRefError)
throw(err)
end
i0 = i+1
for i=1:length(x)
if isbound(x,i)
arrayset(dest, deepcopy_internal(x[i], stackdict), i)
end
end
return dest
Expand Down
23 changes: 10 additions & 13 deletions base/show.jl
Original file line number Diff line number Diff line change
Expand Up @@ -568,11 +568,10 @@ function alignment(
for j in cols
l = r = 0
for i in rows
aij = _jl_undef_ref_alignment
try
if isbound(X,i,j)
aij = alignment(X[i,j])
catch err
if !isa(err,UndefRefError) throw(err) end
else
aij = _jl_undef_ref_alignment
end
l = max(l, aij[1])
r = max(r, aij[2])
Expand All @@ -597,14 +596,13 @@ function print_matrix_row(io,
)
for k = 1:length(A)
j = cols[k]
a = _jl_undef_ref_alignment
sx = _jl_undef_ref_str
try
if isbound(X,i,j)
x = X[i,j]
a = alignment(x)
sx = sprint(showcompact, x)
catch err
if !isa(err,UndefRefError) throw(err) end
else
a = _jl_undef_ref_alignment
sx = _jl_undef_ref_str
end
l = repeat(" ", A[k][1]-a[1])
r = repeat(" ", A[k][2]-a[2])
Expand Down Expand Up @@ -768,11 +766,10 @@ whos(pat::Regex) = whos(ccall(:jl_get_current_module, Module, ()), pat)

function show{T}(io, x::AbstractArray{T,0})
println(io, summary(x),":")
sx = _jl_undef_ref_str
try
if isbound(x)
sx = sprint(showcompact, x[])
catch err
if !isa(err,UndefRefError) throw(err) end
else
sx = _jl_undef_ref_str
end
print(io, sx)
end
Expand Down
12 changes: 12 additions & 0 deletions src/alloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,18 @@ jl_value_t *jl_get_nth_field(jl_value_t *v, size_t i)
(char*)v + offs);
}

int jl_field_isassigned(jl_value_t *v, jl_sym_t *fld, int err)
{
jl_struct_type_t *st = (jl_struct_type_t*)jl_typeof(v);
int i = jl_field_index(st, fld, err);
if (i == -1) return 0;
size_t offs = jl_field_offset(st,i) + sizeof(void*);
if (st->fields[i].isptr) {
return *(jl_value_t**)((char*)v + offs) != NULL;
}
return 1;
}

jl_value_t *jl_set_nth_field(jl_value_t *v, size_t i, jl_value_t *rhs)
{
jl_struct_type_t *st = (jl_struct_type_t*)jl_typeof(v);
Expand Down
10 changes: 10 additions & 0 deletions src/array.c
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,16 @@ JL_CALLABLE(jl_f_arrayref)
return jl_arrayref(a, i);
}

int jl_array_isassigned(jl_value_t **args, int nargs)
{
assert(jl_is_array(args[0]));
jl_array_t *a = (jl_array_t*)args[0];
size_t i = array_nd_index(a, &args[1], nargs-1, "isbound");
if (a->ptrarray)
return ((jl_value_t**)jl_array_data(a))[i] != NULL;
return 1;
}

void jl_arrayset(jl_array_t *a, jl_value_t *rhs, size_t i)
{
jl_value_t *el_type = jl_tparam0(jl_typeof(a));
Expand Down
15 changes: 13 additions & 2 deletions src/builtins.c
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,10 @@ JL_CALLABLE(jl_f_isbound)
{
jl_module_t *m = jl_current_module;
jl_sym_t *s=NULL;
JL_NARGSV(isbound, 1);
if (jl_is_array(args[0])) {
return jl_array_isassigned(args, nargs) ? jl_true : jl_false;
}
if (nargs == 1) {
JL_TYPECHK(isbound, symbol, args[0]);
s = (jl_sym_t*)args[0];
Expand All @@ -316,10 +320,17 @@ JL_CALLABLE(jl_f_isbound)
JL_NARGS(isbound, 1, 1);
}
else {
JL_TYPECHK(isbound, module, args[0]);
JL_TYPECHK(isbound, symbol, args[1]);
m = (jl_module_t*)args[0];
s = (jl_sym_t*)args[1];
if (!jl_is_module(args[0])) {
jl_value_t *vt = (jl_value_t*)jl_typeof(args[0]);
if (!jl_is_struct_type(vt)) {
jl_type_error("isbound", (jl_value_t*)jl_struct_kind, args[0]);
}
return jl_field_isassigned(args[0], s, 1) ? jl_true : jl_false;
}
JL_TYPECHK(isbound, module, args[0]);
m = (jl_module_t*)args[0];
}
assert(s);
return jl_boundp(m, s) ? jl_true : jl_false;
Expand Down
2 changes: 2 additions & 0 deletions src/julia.h
Original file line number Diff line number Diff line change
Expand Up @@ -717,6 +717,7 @@ void jl_compute_struct_offsets(jl_struct_type_t *st);
int jl_field_index(jl_struct_type_t *t, jl_sym_t *fld, int err);
DLLEXPORT jl_value_t *jl_get_nth_field(jl_value_t *v, size_t i);
jl_value_t *jl_set_nth_field(jl_value_t *v, size_t i, jl_value_t *rhs);
int jl_field_isassigned(jl_value_t *v, jl_sym_t *fld, int err);

// arrays
DLLEXPORT jl_array_t *jl_new_array(jl_type_t *atype, jl_tuple_t *dims);
Expand All @@ -740,6 +741,7 @@ DLLEXPORT jl_value_t *jl_array_to_string(jl_array_t *a);
DLLEXPORT jl_array_t *jl_alloc_cell_1d(size_t n);
DLLEXPORT jl_value_t *jl_arrayref(jl_array_t *a, size_t i); // 0-indexed
DLLEXPORT void jl_arrayset(jl_array_t *a, jl_value_t *v, size_t i); // 0-indexed
int jl_array_isassigned(jl_value_t **args, int nargs);
DLLEXPORT void *jl_array_ptr(jl_array_t *a);
DLLEXPORT void jl_array_grow_end(jl_array_t *a, size_t inc);
DLLEXPORT void jl_array_del_end(jl_array_t *a, size_t dec);
Expand Down
27 changes: 27 additions & 0 deletions test/core.jl
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,33 @@ glotest()
# syntax
@assert (true ? 1 : false ? 2 : 3) == 1

type UndefField
field
UndefField() = new()
end

# undefinedness
begin
local a
a = cell(2)
@assert !isbound(a,1) && !isbound(a,2)
a[1] = 1
@assert isbound(a,1) && !isbound(a,2)
a = Array(Float64,1)
@assert isbound(a,1)
@assert isbound(a)
@assert_fails isbound(a,2)

@assert isbound("a",:data)
a = UndefField()
@assert !isbound(a, :field)
@assert_fails isbound(a, :foo)

@assert_fails isbound(2)
@assert_fails isbound(2, :a)
@assert_fails isbound("a", 2)
end

# dispatch
begin
local foo, bar, baz
Expand Down

2 comments on commit 07baa31

@StefanKarpinski
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we call this isdefined instead? I feel like isbound is unnecessarily language-weenieish.

@JeffBezanson
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, bound only really makes sense to me for variables anyway.

Please sign in to comment.