=encoding utf8
=head1 NAME
rdf/schema - RDFS vocabulary helpers and entailment store.
=head1 SYNOPSIS
from rdf/schema import RDFSchemaStore;
from std/db import DB;
let store := new RDFSchemaStore(dbh: DB.temp());
store.install_schema();
let quads := store.find(); // includes inferred RDFS quads
=head1 DESCRIPTION
C<RDFSchemaStore> extends C<RDFStore> with simple RDFS entailment. It
returns explicit and inferred quads for subclass, subproperty, domain,
range, and type relationships. The explicit store content is unchanged;
inferences are computed from stored quads when queried.
=head1 EXPORTS
=head2 Classes
=over
=item C<RDFSchemaStore>
A subclass of C<RDFStore>.
=over
=item C<< explicit_find(subject := null, predicate := null, object := null, graph := null) >>
Returns only stored quads matching the pattern.
=item C<< inferred_quads() >>
Returns inferred quads that are not explicitly stored.
=item C<< find(subject := null, predicate := null, object := null, graph := null) >>
Returns explicit and inferred quads matching the pattern.
=back
=back
=head1 COPYRIGHT AND LICENCE
B<< rdf/schema >> is copyright Toby Inkster.
It is free software; you may redistribute it and/or modify it under
the terms of either the Artistic License 1.0 or the GNU General Public
License version 2.
=cut
from rdf/graph import rdf_quads_unique;
from rdf/store import RDFStore;
from rdf/term import
RDFBlank,
RDFIRI,
RDFLiteral,
RDF_NS,
rdf_iri,
rdf_quad,
rdf_term_equals,
rdf_term_key;
from rdf/vocab import
rdf_type,
rdfs_domain,
rdfs_range,
rdfs_subclass_of,
rdfs_subproperty_of;
function _rdfs_quad_key ( quad ) {
return rdf_term_key(quad.get_subject()) _ "\n" _
rdf_term_key(quad.get_predicate()) _ "\n" _
rdf_term_key(quad.get_object()) _ "\n" _
rdf_term_key(quad.get_graph());
}
function _rdfs_add_quad ( Array out, Dict seen, quad ) {
let key := _rdfs_quad_key(quad);
return false if seen.exists(key);
seen.set( key, true );
out.push(quad);
return true;
}
function _rdfs_pair_key ( left, right ) {
return rdf_term_key(left) _ "\n" _ rdf_term_key(right);
}
function _rdfs_add_pair ( Array pairs, Dict seen, left, right, graph ) {
let key := _rdfs_pair_key( left, right );
return false if seen.exists(key);
seen.set( key, true );
pairs.push({ left: left, right: right, graph: graph });
return true;
}
function _rdfs_pairs_for_predicate ( Array quads, predicate ) {
let pairs := [];
let seen := {};
for ( let quad in quads ) {
next unless rdf_term_equals( quad.get_predicate(), predicate );
_rdfs_add_pair(
pairs,
seen,
quad.get_subject(),
quad.get_object(),
quad.get_graph(),
);
}
return pairs;
}
function _rdfs_array_copy ( Array values ) {
let out := [];
for ( let value in values ) {
out.push(value);
}
return out;
}
function _rdfs_pair_closure ( Array pairs ) {
let out := [];
let seen := {};
for ( let pair in pairs ) {
_rdfs_add_pair( out, seen, pair{left}, pair{right}, pair{graph} );
}
let changed := true;
while ( changed ) {
changed := false;
let snapshot := _rdfs_array_copy(out);
for ( let left in snapshot ) {
for ( let right in snapshot ) {
if ( rdf_term_equals( left{right}, right{left} ) ) {
changed := true if _rdfs_add_pair(
out,
seen,
left{left},
right{right},
left{graph},
);
}
}
}
}
return out;
}
function _rdfs_super_terms ( term, Array closure ) {
let out := [];
let seen := {};
for ( let pair in closure ) {
next unless rdf_term_equals( pair{left}, term );
let key := rdf_term_key(pair{right});
next if seen.exists(key);
seen.set( key, true );
out.push(pair{right});
}
return out;
}
function _rdfs_matches ( quad, subject, predicate, object, graph ) {
return false if not (subject == null) and
not rdf_term_equals( quad.get_subject(), subject );
return false if not (predicate == null) and
not rdf_term_equals( quad.get_predicate(), predicate );
return false if not (object == null) and
not rdf_term_equals( quad.get_object(), object );
return false if not (graph == null) and
not rdf_term_equals( quad.get_graph(), graph );
return true;
}
class RDFSchemaStore extends RDFStore {
method explicit_find ( subject := null, predicate := null,
object := null, graph := null ) {
return super( subject, predicate, object, graph );
}
method inferred_quads () {
let explicit := self.explicit_find();
let inferred := [];
let seen := {};
for ( let quad in explicit ) {
seen.set( _rdfs_quad_key(quad), true );
}
let subclass := _rdfs_pair_closure(_rdfs_pairs_for_predicate(
explicit,
rdfs_subclass_of(),
));
let subproperty := _rdfs_pair_closure(_rdfs_pairs_for_predicate(
explicit,
rdfs_subproperty_of(),
));
for ( let pair in subclass ) {
_rdfs_add_quad(
inferred,
seen,
rdf_quad(
pair{left},
rdfs_subclass_of(),
pair{right},
pair{graph},
),
);
}
for ( let pair in subproperty ) {
_rdfs_add_quad(
inferred,
seen,
rdf_quad(
pair{left},
rdfs_subproperty_of(),
pair{right},
pair{graph},
),
);
}
let data_quads := _rdfs_array_copy(explicit);
for ( let quad in explicit ) {
for ( let super_p in _rdfs_super_terms(
quad.get_predicate(),
subproperty,
) ) {
let inferred_quad := rdf_quad(
quad.get_subject(),
super_p,
quad.get_object(),
quad.get_graph(),
);
if ( _rdfs_add_quad( inferred, seen, inferred_quad ) ) {
data_quads.push(inferred_quad);
}
}
}
for ( let quad in data_quads ) {
for ( let domain in self.explicit_find(
quad.get_predicate(),
rdfs_domain(),
) ) {
_rdfs_add_quad(
inferred,
seen,
rdf_quad(
quad.get_subject(),
rdf_type(),
domain.get_object(),
quad.get_graph(),
),
);
}
if ( quad.get_object() instanceof RDFIRI or
quad.get_object() instanceof RDFBlank
) {
for ( let range in self.explicit_find(
quad.get_predicate(),
rdfs_range(),
) ) {
_rdfs_add_quad(
inferred,
seen,
rdf_quad(
quad.get_object(),
rdf_type(),
range.get_object(),
quad.get_graph(),
),
);
}
}
}
let all_types := [];
for ( let quad in explicit ) {
all_types.push(quad) if rdf_term_equals( quad.get_predicate(), rdf_type() );
}
for ( let quad in inferred ) {
all_types.push(quad) if rdf_term_equals( quad.get_predicate(), rdf_type() );
}
for ( let quad in all_types ) {
for ( let super_class in _rdfs_super_terms(
quad.get_object(),
subclass,
) ) {
_rdfs_add_quad(
inferred,
seen,
rdf_quad(
quad.get_subject(),
rdf_type(),
super_class,
quad.get_graph(),
),
);
}
}
return inferred;
}
method find ( subject := null, predicate := null, object := null,
graph := null ) {
let out := self.explicit_find( subject, predicate, object, graph );
let seen := {};
for ( let quad in out ) {
seen.set( _rdfs_quad_key(quad), true );
}
for ( let quad in self.inferred_quads() ) {
next unless _rdfs_matches( quad, subject, predicate, object, graph );
_rdfs_add_quad( out, seen, quad );
}
return out;
}
}
modules/rdf/schema.zzm
rdf-0.0.3 source code
Package
- Name
- rdf
- Version
- 0.0.3
- Uploaded
- 2026-06-12 23:55:02
- Repository
- https://github.com/tobyink/zuzu-rdf
- Dependencies
-
-
std/data/xml>= 0 -
std/data/xml/escape>= 0 -
std/data/json>= 0 -
std/db>= 0 -
std/digest/sha>= 0 -
std/getopt>= 0 -
std/internals>= 0 -
std/io>= 0 -
std/math>= 0 -
std/proc>= 0 -
std/string>= 0 -
std/time>= 0 -
std/uuid>= 0
-
- Metadata
- zuzu-distribution.json
- Archive
- Download .tar.gz