Examples
The following examples are designed to get you started using Cowl. They are ordered by complexity, so it is recommended that you read them sequentially.
Reading ontologies
Related documentation: ontology reading
1/*
2 * This introductory example shows how to read an ontology
3 * and log its axioms and annotations.
4 *
5 * @note Memory allocation failures are not handled for the sake of simplicity.
6 *
7 * @author Ivano Bilenchi
8 *
9 * @copyright Copyright (c) 2019 SisInf Lab, Polytechnic University of Bari
10 * @copyright <http://swot.sisinflab.poliba.it>
11 * @copyright SPDX-License-Identifier: EPL-2.0
12 */
13#include "cowl.h"
14#include "ulib.h"
15#include <stdio.h>
16#include <stdlib.h>
17
18#define ONTO "example_pizza.owl"
19
20int main(void) {
21 // You must always initialize the library before use.
22 cowl_init();
23
24 // Instantiate a manager and deserialize an ontology from file.
25 CowlManager *manager = cowl_manager();
26 CowlOntology *onto = cowl_manager_read_path(manager, ustring_literal(ONTO));
27
28 if (!onto) {
29 // The ontology could not be read.
30 fprintf(stderr, "Failed to load ontology " ONTO "\n");
31 return EXIT_FAILURE;
32 }
33
34 // Do stuff with the ontology. In this case we are just logging it
35 // to the standard output using the default writer.
36 cowl_manager_write_file(manager, onto, stdout);
37
38 // Release the manager and the ontology.
39 cowl_release(manager);
40 cowl_release(onto);
41
42 return EXIT_SUCCESS;
43}
Handling of errors and imports
Related documentation: error handling, import handling
1/*
2 * This example is the same as the previous one, except all errors are handled
3 * and logged, and ontology imports are resolved.
4 *
5 * @author Ivano Bilenchi
6 *
7 * @copyright Copyright (c) 2019 SisInf Lab, Polytechnic University of Bari
8 * @copyright <http://swot.sisinflab.poliba.it>
9 * @copyright SPDX-License-Identifier: EPL-2.0
10 */
11#include "cowl.h"
12#include "ulib.h"
13#include <stdio.h>
14#include <stdlib.h>
15
16#define ONTO "example_pizza.owl"
17#define IMPORT "import.owl"
18#define LOG "errors.log"
19
20/*
21 * You should return the appropriate ontology given the specified IRI.
22 * This may involve making network requests or simply retrieving
23 * the imported ontology from the local filesystem. In this example
24 * we just return a generic local "import.owl" ontology, disregarding its IRI.
25 */
26static CowlOntology *load_import(cowl_unused void *ctx, cowl_unused CowlIRI *iri) {
27 CowlOntology *import = NULL;
28 CowlManager *manager = cowl_manager();
29
30 if (manager) {
31 import = cowl_manager_read_path(manager, ustring_literal(IMPORT));
32 cowl_release(manager);
33 }
34
35 return import;
36}
37
38/*
39 * In general, it is very reasonable to just check that the ontology returned
40 * by the manager is not NULL. The error handler mechanism is only needed if you wish
41 * to implement more fine-grained error handling. In this example, errors are logged.
42 */
43static void handle_error(void *ctx, CowlError const *error) {
44 cowl_write_error(ctx, error);
45 cowl_write_static(ctx, "\n");
46}
47
48int main(void) {
49 // API initialization can fail due to low memory.
50 if (cowl_init()) {
51 return EXIT_FAILURE;
52 }
53
54 // Setup a global error handler and import loader.
55 CowlImportLoader loader = { NULL, load_import };
56 cowl_set_import_loader(loader);
57
58 UOStream stream;
59 if (uostream_to_path(&stream, LOG)) {
60 fprintf(stderr, "Failed to open " LOG "\n");
61 return EXIT_FAILURE;
62 }
63
64 CowlErrorHandler handler = { &stream, handle_error };
65 cowl_set_error_handler(handler);
66
67 // Read the ontology from file.
68 CowlManager *manager = cowl_manager();
69
70 if (!manager) {
71 return EXIT_FAILURE;
72 }
73
74 CowlOntology *onto = cowl_manager_read_path(manager, ustring_literal(ONTO));
75
76 if (!onto) {
77 fprintf(stderr, "Failed to load ontology " ONTO "\n");
78 return EXIT_FAILURE;
79 }
80
81 // Do stuff with the ontology.
82 cowl_manager_write_file(manager, onto, stdout);
83
84 cowl_release_all(manager, onto);
85 uostream_deinit(&stream);
86
87 return EXIT_SUCCESS;
88}
Querying ontologies
Related documentation: ontology querying
Basic queries
1/*
2 * In this example we will be logging the direct atomic subclasses of a class.
3 *
4 * @note Memory allocation failures are not handled for the sake of simplicity.
5 *
6 * @author Ivano Bilenchi
7 *
8 * @copyright Copyright (c) 2019 SisInf Lab, Polytechnic University of Bari
9 * @copyright <http://swot.sisinflab.poliba.it>
10 * @copyright SPDX-License-Identifier: EPL-2.0
11 */
12#include "cowl.h"
13#include "ulib.h"
14#include <stdio.h>
15#include <stdlib.h>
16
17#define ONTO "example_pizza.owl"
18#define NS "http://www.co-ode.org/ontologies/pizza/pizza.owl#"
19#define CLASS_NAME "Food"
20
21// Iterator body, invoked for each class expression matching the query.
22static bool for_each_cls(void *std_out, CowlAny *cls) {
23 // We are only interested in atomic classes. Note that due to pseudo-inheritance
24 // this check ensures that the concrete type of 'exp' is CowlClass.
25 if (cowl_cls_exp_get_type(cls) != COWL_CET_CLASS) return true;
26
27 // Log the IRI remainder.
28 cowl_write_string(std_out, cowl_iri_get_rem(cowl_class_get_iri(cls)));
29 cowl_write_static(std_out, "\n");
30
31 return true;
32}
33
34int main(void) {
35 cowl_init();
36
37 CowlManager *manager = cowl_manager();
38 CowlOntology *onto = cowl_manager_read_path(manager, ustring_literal(ONTO));
39 cowl_release(manager);
40
41 if (!onto) {
42 fprintf(stderr, "Failed to load ontology " ONTO "\n");
43 return EXIT_FAILURE;
44 }
45
46 // Query the ontology.
47 UOStream *std_out = uostream_std();
48 cowl_write_static(std_out, "Atomic subclasses of " CLASS_NAME ":\n");
49
50 // Get the class whose atomic subclasses we are interested in.
51 CowlClass *cls = cowl_class_from_static(NS CLASS_NAME);
52
53 // Run the query.
54 CowlIterator iter = { std_out, for_each_cls };
55 cowl_ontology_iterate_sub_classes(onto, cls, &iter, false);
56
57 // Cleanup.
58 cowl_release_all(cls, onto);
59
60 return EXIT_SUCCESS;
61}
Recursive queries
1/*
2 * In this example we will be logging the atomic subclasses of a class recursively.
3 *
4 * @note Memory allocation failures are not handled for the sake of simplicity.
5 *
6 * @author Ivano Bilenchi
7 *
8 * @copyright Copyright (c) 2019 SisInf Lab, Polytechnic University of Bari
9 * @copyright <http://swot.sisinflab.poliba.it>
10 * @copyright SPDX-License-Identifier: EPL-2.0
11 */
12#include "cowl.h"
13#include "ulib.h"
14#include <stdio.h>
15#include <stdlib.h>
16
17#define ONTO "example_pizza.owl"
18#define NS "http://www.co-ode.org/ontologies/pizza/pizza.owl#"
19#define CLASS_NAME "Food"
20
21// Custom context struct for the query.
22typedef struct CustomContext {
23 CowlOntology *onto;
24 UOStream *stream;
25} CustomContext;
26
27// Iterator body, invoked for each class expression matching the query.
28static bool for_each_cls(void *ptr, CowlAny *cls) {
29 if (cowl_cls_exp_get_type(cls) != COWL_CET_CLASS) return true;
30
31 // Log the IRI remainder.
32 CustomContext *ctx = ptr;
33 cowl_write_string(ctx->stream, cowl_iri_get_rem(cowl_class_get_iri(cls)));
34 cowl_write_static(ctx->stream, "\n");
35
36 // Recurse.
37 CowlIterator iter = { ctx, for_each_cls };
38 return cowl_ontology_iterate_sub_classes(ctx->onto, cls, &iter, false);
39}
40
41int main(void) {
42 cowl_init();
43
44 CowlManager *manager = cowl_manager();
45 CowlOntology *onto = cowl_manager_read_path(manager, ustring_literal(ONTO));
46 cowl_release(manager);
47
48 if (!onto) {
49 fprintf(stderr, "Failed to load ontology " ONTO "\n");
50 return EXIT_FAILURE;
51 }
52
53 UOStream *std_out = uostream_std();
54 cowl_write_static(std_out, "Recursive atomic subclasses of " CLASS_NAME ":\n");
55 CowlClass *cls = cowl_class_from_static(NS CLASS_NAME);
56
57 // Since we are going to perform a recursive query,
58 // we need the ontology to be part of the context.
59 CustomContext ctx = { onto, std_out };
60 CowlIterator iter = { &ctx, for_each_cls };
61 cowl_ontology_iterate_sub_classes(onto, cls, &iter, false);
62
63 cowl_release_all(cls, onto);
64 return EXIT_SUCCESS;
65}
Advanced queries
1/*
2 * In this example we will be logging axioms of different types referencing
3 * multiple entities.
4 *
5 * @note Memory allocation failures are not handled for the sake of simplicity.
6 *
7 * @author Ivano Bilenchi
8 *
9 * @copyright Copyright (c) 2024 SisInf Lab, Polytechnic University of Bari
10 * @copyright <http://swot.sisinflab.poliba.it>
11 * @copyright SPDX-License-Identifier: EPL-2.0
12 */
13#include "cowl.h"
14#include "cowl_axiom_filter.h"
15#include "cowl_axiom_flags.h"
16#include "cowl_obj_prop.h"
17#include "cowl_writer.h"
18#include "ulib.h"
19#include <stdio.h>
20#include <stdlib.h>
21
22#define ONTO "example_pizza.owl"
23#define NS "http://www.co-ode.org/ontologies/pizza/pizza.owl#"
24#define CLASS_NAME "ThinAndCrispyBase"
25#define PROPERTY_NAME "hasBase"
26
27// Iterator body, invoked for each axiom matching the query.
28static bool for_each_axiom(void *stream, CowlAny *axiom) {
29 cowl_write(stream, axiom);
30 cowl_write_static(stream, "\n");
31 return true;
32}
33
34int main(void) {
35 cowl_init();
36
37 CowlManager *manager = cowl_manager();
38 CowlOntology *onto = cowl_manager_read_path(manager, ustring_literal(ONTO));
39 cowl_release(manager);
40
41 if (!onto) {
42 fprintf(stderr, "Failed to load ontology " ONTO "\n");
43 return EXIT_FAILURE;
44 }
45
46 UOStream *std_out = uostream_std();
47 cowl_write_static(std_out, "Matching axioms:\n");
48 CowlClass *cls = cowl_class_from_static(NS CLASS_NAME);
49 CowlObjProp *prop = cowl_obj_prop_from_static(NS PROPERTY_NAME);
50
51 // We want to log all SubClassOf and EquivalentClasses axioms that reference
52 // both the class and the property.
53
54 // Note that this can be done via other query functions as well, though
55 // using a CowlAxiomFilter is usually more efficient, as it is used
56 // internally to determine the best indexing strategy for the query.
57 CowlAxiomFlags types = COWL_AF_SUB_CLASS | COWL_AF_EQUIV_CLASSES;
58 CowlAxiomFilter filter = cowl_axiom_filter(types);
59 cowl_axiom_filter_add_primitive(&filter, cls);
60 cowl_axiom_filter_add_primitive(&filter, prop);
61
62 CowlIterator iter = { std_out, for_each_axiom };
63 cowl_ontology_iterate_axioms_matching(onto, &filter, &iter, false);
64
65 cowl_axiom_filter_deinit(&filter);
66 cowl_release_all(cls, prop, onto);
67 return EXIT_SUCCESS;
68}
Editing and writing ontologies
Related documentation: ontology editing, ontology writing
1/*
2 * This example demonstrates ontology editing and serialization to file.
3 *
4 * @note Memory allocation failures are not handled for the sake of simplicity.
5 *
6 * @author Ivano Bilenchi
7 *
8 * @copyright Copyright (c) 2022 SisInf Lab, Polytechnic University of Bari
9 * @copyright <http://swot.sisinflab.poliba.it>
10 * @copyright SPDX-License-Identifier: EPL-2.0
11 */
12#include "cowl.h"
13#include "ulib.h"
14#include <stdio.h>
15#include <stdlib.h>
16
17#define IN_PATH "example_pizza.owl"
18#define OUT_PATH "example_pizza_new.owl"
19#define NS "http://www.co-ode.org/ontologies/pizza/pizza.owl#"
20
21int main(void) {
22 cowl_init();
23
24 // We will be editing the pizza ontology by adding the Porcini pizza.
25 printf("Reading ontology " IN_PATH "... ");
26 CowlManager *manager = cowl_manager();
27 CowlOntology *onto = cowl_manager_read_path(manager, ustring_literal(IN_PATH));
28
29 if (onto) {
30 puts("done!");
31 } else {
32 puts("failed");
33 return EXIT_FAILURE;
34 }
35
36 // Declaration(Class(pizza:PorciniTopping))
37 CowlClass *porcini_topping = cowl_class_from_static(NS "PorciniTopping");
38 CowlAnyAxiom *axiom = cowl_decl_axiom(porcini_topping, NULL);
39 cowl_ontology_add_axiom(onto, axiom);
40 cowl_release(axiom);
41
42 // Declaration(Class(pizza:Porcini))
43 CowlClass *porcini = cowl_class_from_static(NS "Porcini");
44 axiom = cowl_decl_axiom(porcini, NULL);
45 cowl_ontology_add_axiom(onto, axiom);
46 cowl_release(axiom);
47
48 // SubClassOf(pizza:PorciniTopping pizza:MushroomTopping)
49 CowlClass *mushroom_topping = cowl_class_from_static(NS "MushroomTopping");
50 axiom = cowl_sub_cls_axiom(porcini_topping, mushroom_topping, NULL);
51 cowl_ontology_add_axiom(onto, axiom);
52 cowl_release_all(axiom, mushroom_topping);
53
54 // SubClassOf(pizza:Porcini pizza:NamedPizza)
55 CowlClass *named_pizza = cowl_class_from_static(NS "NamedPizza");
56 axiom = cowl_sub_cls_axiom(porcini, named_pizza, NULL);
57 cowl_ontology_add_axiom(onto, axiom);
58 cowl_release_all(axiom, named_pizza);
59
60 // SubClassOf(pizza:Porcini
61 // ObjectSomeValuesFrom(pizza:hasTopping pizza:MozzarellaTopping))
62 CowlObjProp *has_topping = cowl_obj_prop_from_static(NS "hasTopping");
63 CowlClass *mozzarella_topping = cowl_class_from_static(NS "MozzarellaTopping");
64 CowlObjQuant *obj_quant = cowl_obj_quant(COWL_QT_SOME, has_topping,
65 mozzarella_topping);
66 axiom = cowl_sub_cls_axiom(porcini, obj_quant, NULL);
67 cowl_ontology_add_axiom(onto, axiom);
68 cowl_release_all(axiom, obj_quant, mozzarella_topping);
69
70 // SubClassOf(pizza:Porcini
71 // ObjectSomeValuesFrom(pizza:hasTopping pizza:PorciniTopping))
72 obj_quant = cowl_obj_quant(COWL_QT_SOME, has_topping, porcini_topping);
73 axiom = cowl_sub_cls_axiom(porcini, obj_quant, NULL);
74 cowl_ontology_add_axiom(onto, axiom);
75 cowl_release_all(axiom, obj_quant);
76
77 // SubClassOf(pizza:Porcini ObjectAllValuesFrom(pizza:hasTopping
78 // ObjectUnionOf(pizza:MozzarellaTopping pizza:PorciniTopping)))
79 UVec(CowlObjectPtr) vec = uvec(CowlObjectPtr);
80 uvec_push(CowlObjectPtr, &vec, mozzarella_topping);
81 uvec_push(CowlObjectPtr, &vec, porcini_topping);
82 CowlVector *operands = cowl_vector(&vec);
83 CowlNAryBool *closure = cowl_nary_bool(COWL_NT_UNION, operands);
84 obj_quant = cowl_obj_quant(COWL_QT_ALL, has_topping, closure);
85 axiom = cowl_sub_cls_axiom(porcini, obj_quant, NULL);
86 cowl_ontology_add_axiom(onto, axiom);
87 cowl_release_all(axiom, obj_quant, closure, operands, porcini_topping, porcini,
88 has_topping);
89
90 // Serialize the edited ontology to a new file.
91 printf("Writing ontology " OUT_PATH "... ");
92
93 if (cowl_manager_write_path(manager, onto, ustring_literal(OUT_PATH))) {
94 puts("failed");
95 } else {
96 puts("done!");
97 }
98
99 cowl_release_all(onto, manager);
100 return EXIT_SUCCESS;
101}
Ontology streams
Related documentation: input streams, output streams
Input streams
1/*
2 * In this example we will be logging the direct atomic subclasses
3 * of a certain class, but we will do so without instantiating a
4 * CowlOntology object.
5 *
6 * @note Memory allocation failures are not handled for the sake of simplicity.
7 *
8 * @author Ivano Bilenchi
9 *
10 * @copyright Copyright (c) 2023 SisInf Lab, Polytechnic University of Bari
11 * @copyright <http://swot.sisinflab.poliba.it>
12 * @copyright SPDX-License-Identifier: EPL-2.0
13 */
14#include "cowl.h"
15#include "ulib.h"
16#include <stdio.h>
17#include <stdlib.h>
18
19#define ONTO "example_pizza.owl"
20#define NS "http://www.co-ode.org/ontologies/pizza/pizza.owl#"
21#define CLASS_NAME "Food"
22
23// Axiom handler, invoked for each axiom in the ontology document.
24static cowl_ret handle_axiom(void *target_class, CowlAnyAxiom *axiom) {
25 // We are only interested in subclass axioms.
26 if (cowl_axiom_get_type(axiom) != COWL_AT_SUB_CLASS) return COWL_OK;
27
28 // We are only interested in axioms where the superclass is the target class.
29 CowlAnyClsExp *cls = cowl_sub_cls_axiom_get_super(axiom);
30 if (!cowl_equals(target_class, cls)) return COWL_OK;
31
32 // We are only interested in axioms where the subclass is atomic.
33 cls = cowl_sub_cls_axiom_get_sub(axiom);
34 if (cowl_cls_exp_get_type(cls) != COWL_CET_CLASS) return COWL_OK;
35
36 // Log the IRI remainder.
37 puts(cowl_string_get_cstring(cowl_iri_get_rem(cowl_class_get_iri(cls))));
38 return COWL_OK;
39}
40
41int main(void) {
42 cowl_init();
43
44 CowlManager *manager = cowl_manager();
45 CowlClass *target_class = cowl_class_from_static(NS CLASS_NAME);
46
47 // Configure the ontology input stream.
48 CowlIStreamHandlers handlers = { .ctx = target_class, .axiom = handle_axiom };
49 CowlIStream *stream = cowl_manager_get_istream(manager, handlers);
50
51 // Process the ontology as a stream.
52 puts("Atomic subclasses of " CLASS_NAME ":");
53 if (cowl_istream_process_path(stream, ustring_literal(ONTO))) {
54 return EXIT_FAILURE;
55 }
56
57 cowl_release_all(manager, target_class, stream);
58 return EXIT_SUCCESS;
59}
Output streams
1/*
2 * In this example we will be creating a new ontology document by using an
3 * ontology output stream.
4 *
5 * @note Memory allocation failures are not handled for the sake of simplicity.
6 *
7 * @author Ivano Bilenchi
8 *
9 * @copyright Copyright (c) 2023 SisInf Lab, Polytechnic University of Bari
10 * @copyright <http://swot.sisinflab.poliba.it>
11 * @copyright SPDX-License-Identifier: EPL-2.0
12 *
13 * @file
14 */
15
16#include "cowl.h"
17#include "ulib.h"
18#include <stdio.h>
19#include <stdlib.h>
20
21#define PATH "porcini_pizza.owl"
22
23#define IMPORT_IRI "http://www.co-ode.org/ontologies/pizza"
24#define IMPORT_NS IMPORT_IRI "/pizza.owl#"
25
26#define IRI "http://foo.com/ontologies/porcini_pizza"
27#define NS IRI "/porcini_pizza.owl#"
28
29int main(void) {
30 cowl_init();
31
32 printf("Generating ontology " PATH "... ");
33
34 UOStream ostream;
35 if (uostream_to_path(&ostream, PATH)) {
36 // Initializing and writing to the stream may fail.
37 // You should handle IO errors as fit for your application.
38 goto err_io;
39 }
40
41 CowlManager *manager = cowl_manager();
42 CowlOStream *stream = cowl_manager_get_ostream(manager, &ostream);
43 cowl_release(manager);
44
45 // Optional: setup prefixes so that IRIs can be rendered in their prefixed form.
46 CowlSymTable *st = cowl_ostream_get_sym_table(stream);
47 cowl_sym_table_register_prefix_raw(st, ustring_literal(""), ustring_literal(NS),
48 false);
49 cowl_sym_table_register_prefix_raw(st, ustring_literal("pizza"),
50 ustring_literal(IMPORT_NS), false);
51
52 // Write the ontology header.
53 CowlIRI *iri = cowl_iri_from_static(IRI);
54 CowlIRI *import_iri = cowl_iri_from_static(IMPORT_IRI);
55 UVec(CowlObjectPtr) imports = uvec(CowlObjectPtr);
56 uvec_push(CowlObjectPtr, &imports, import_iri);
57
58 CowlOntologyHeader header = {
59 .id = { iri },
60 .imports = &imports,
61 };
62
63 if (cowl_ostream_write_header(stream, header)) goto err_io;
64
65 cowl_release_all(iri, import_iri);
66 uvec_deinit(CowlObjectPtr, &imports);
67
68 // Write the axioms.
69 // Declaration(Class(:PorciniTopping))
70 CowlClass *porcini = cowl_class_from_static(NS "PorciniTopping");
71 CowlAnyAxiom *axiom = cowl_decl_axiom(porcini, NULL);
72 if (cowl_ostream_write_axiom(stream, axiom)) goto err_io;
73 cowl_release(axiom);
74
75 // Declaration(Class(:Porcini))
76 CowlClass *porcini_pizza = cowl_class_from_static(NS "Porcini");
77 axiom = cowl_decl_axiom(porcini_pizza, NULL);
78 if (cowl_ostream_write_axiom(stream, axiom)) goto err_io;
79 cowl_release(axiom);
80
81 // SubClassOf(:PorciniTopping pizza:MushroomTopping)
82 CowlClass *mushroom = cowl_class_from_static(IMPORT_NS "MushroomTopping");
83 axiom = cowl_sub_cls_axiom(porcini, mushroom, NULL);
84 if (cowl_ostream_write_axiom(stream, axiom)) goto err_io;
85 cowl_release_all(axiom, mushroom);
86
87 // SubClassOf(:Porcini pizza:NamedPizza)
88 CowlClass *named_pizza = cowl_class_from_static(IMPORT_NS "NamedPizza");
89 axiom = cowl_sub_cls_axiom(porcini_pizza, named_pizza, NULL);
90 if (cowl_ostream_write_axiom(stream, axiom)) goto err_io;
91 cowl_release_all(axiom, named_pizza);
92
93 // SubClassOf(:Porcini
94 // ObjectSomeValuesFrom(pizza:hasTopping pizza:MozzarellaTopping))
95 CowlObjProp *has_topping = cowl_obj_prop_from_static(IMPORT_NS "hasTopping");
96 CowlClass *mozzarella = cowl_class_from_static(IMPORT_NS "MozzarellaTopping");
97 CowlObjQuant *obj_quant = cowl_obj_quant(COWL_QT_SOME, has_topping, mozzarella);
98 axiom = cowl_sub_cls_axiom(porcini_pizza, obj_quant, NULL);
99 if (cowl_ostream_write_axiom(stream, axiom)) goto err_io;
100 cowl_release_all(axiom, obj_quant, mozzarella);
101
102 // SubClassOf(:Porcini
103 // ObjectSomeValuesFrom(pizza:hasTopping :PorciniTopping))
104 obj_quant = cowl_obj_quant(COWL_QT_SOME, has_topping, porcini);
105 axiom = cowl_sub_cls_axiom(porcini_pizza, obj_quant, NULL);
106 if (cowl_ostream_write_axiom(stream, axiom)) goto err_io;
107 cowl_release_all(axiom, obj_quant);
108
109 // SubClassOf(:Porcini ObjectAllValuesFrom(pizza:hasTopping
110 // ObjectUnionOf(pizza:MozzarellaTopping :PorciniTopping)))
111 UVec(CowlObjectPtr) vec = uvec(CowlObjectPtr);
112 uvec_push(CowlObjectPtr, &vec, mozzarella);
113 uvec_push(CowlObjectPtr, &vec, porcini);
114 CowlVector *operands = cowl_vector(&vec);
115 CowlNAryBool *closure = cowl_nary_bool(COWL_NT_UNION, operands);
116 obj_quant = cowl_obj_quant(COWL_QT_ALL, has_topping, closure);
117 axiom = cowl_sub_cls_axiom(porcini_pizza, obj_quant, NULL);
118 if (cowl_ostream_write_axiom(stream, axiom)) goto err_io;
119 cowl_release_all(axiom, obj_quant, closure, operands, porcini, porcini_pizza,
120 has_topping);
121
122 // Finally, write the footer.
123 if (cowl_ostream_write_footer(stream)) goto err_io;
124
125 puts("done!");
126 cowl_release(stream);
127 return EXIT_SUCCESS;
128
129err_io:
130 puts("failed");
131 return EXIT_FAILURE;
132}