-
Notifications
You must be signed in to change notification settings - Fork 225
/
Checkers.cc
184 lines (156 loc) · 6.04 KB
/
Checkers.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
/*
* opencog/atoms/core/Checkers.cc
*
* Copyright (C) 2017 Linas Vepstas
* All Rights Reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License v3 as
* published by the Free Software Foundation and including the exceptions
* at http://opencog.org/wiki/Licenses
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program; if not, write to:
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <opencog/atoms/base/Atom.h>
#include <opencog/atoms/base/ClassServer.h>
using namespace opencog;
// There is a way for the user to pull a fast one, and crash us here.
// avoid null-ptr deref.
static inline void check_null(const Handle& h)
{
if (nullptr == h)
throw InvalidParamException(TRACE_INFO,
"Outgoing set of Link contains null handle\n");
}
/// Provide static factory-time type checking.
/// This only performs a very simple kind of type checking;
/// it does not check deep types, nor does it check arity.
// XXX FIXME Much of the onfusion below is due to a bug: if the
// types script says something like
// FOOBAR <- FUNCTION_LINK,BOOL_INPUT_LINK,NUMBER_INPUT_LINK
// then the Foobar function will fail if given a boolean input:
// the check for it being a number fails. We want this check to
// be "input this or that", instead of "input this and that".
// Right now, we don't have a syntax for that. We've been too
// sloppy with types to get this right.
/// Check to see if every input atom is of Evaluatable type.
static bool check_evaluatable(const Handle& bool_atom)
{
// Make an exception for AndLink, its used in pattern matcher
// in an unseemly way.
if (bool_atom->get_type() == AND_LINK) return true;
for (const Handle& h: bool_atom->getOutgoingSet())
{
check_null(h);
Type t = h->get_type();
// PutLinks and GetLinks cannot be type-checked statically.
// Checking has to be deferred until runtime.
if (PUT_LINK == t) continue;
if (GET_LINK == t) continue;
if (VARIABLE_NODE == t) continue;
if (GLOB_NODE == t) continue;
if (DEFINED_PREDICATE_NODE == t) continue;
// Allow conjunction, disjunction and negation of
// predicates. Since it cannot inherit from EVALUATABLE_LINK
// (cause it's a Node) we have to add it here.
if (h->is_type(PREDICATE_NODE)) continue;
// Allow conjunction, disjunction and negation of concepts as
// well, in that case these are interpreted as intersection,
// union and complement. Since it cannot inherit from
// EVALUATABLE_LINK (cause it's a Node) we have to add it here.
// XXX FIXME, this is to be removed, because UnionLink,
// IntersectionLink takes the place of OrLink, AndLink.
if (h->is_type(CONCEPT_NODE)) continue;
// Fucking quote links. I hate those with a passion.
if (QUOTE_LINK == t) continue;
if (UNQUOTE_LINK == t) continue;
// Negation, conjunction or disjunction over Implication,
// Equivalence, Inheritance, Similarity and their subtypes is
// currently required by PLN for higher order reasoning. We may
// want to forbid it in the future by maybe introducing a
// specialized operator to explicitly map the higher order into
// the lower order but as of today it is required.
// XXX FIXME ... Perhaps IntersectionLink, UnionLink will
// resolve this?
if (h->is_type(SIMILARITY_LINK) or
h->is_type(MEMBER_LINK))
continue;
// This is used by PLN to avoid type-checking.
if (h->is_type(DIRECTLY_EVALUATABLE_LINK)) continue;
if (not h->is_type(EVALUATABLE_LINK)) return false;
}
return true;
}
static bool check_bool_vect(const Handle& bool_atom)
{
for (const Handle& h: bool_atom->getOutgoingSet())
{
Type t = h->get_type();
// Explcitly allow variables.
if (VARIABLE_NODE == t) continue;
// Allow Lambdas and whatnot.
if (h->is_type(DEFINED_PROCEDURE_NODE)) continue;
if (EXECUTION_OUTPUT_LINK == t) continue;
if (not h->is_type(BOOLEAN_OUTPUT_LINK)) return false;
}
return true;
}
/// Check to see if every input atom is of Numeric type.
static bool check_numeric(const Handle& bool_atom)
{
for (const Handle& h: bool_atom->getOutgoingSet())
{
check_null(h);
Type t = h->get_type();
// PutLinks and GetLinks cannot be type-checked statically.
// Checking has to be deferred until runtime.
if (PUT_LINK == t) continue;
if (h->is_type(SATISFYING_LINK)) continue;
if (EXECUTION_OUTPUT_LINK == t) continue;
if (VARIABLE_NODE == t) continue;
if (GLOB_NODE == t) continue;
// Hmm Should not be needed...
if (NUMBER_NODE == t) continue;
if (h->is_type(BOOL_OP_LINK)) continue;
// TODO - look up the schema, and make sure its numeric, also.
if (h->is_type(DEFINED_PROCEDURE_NODE)) continue;
// Oddly enough, sets of numbers are allowed.
if (SET_LINK == t and check_numeric(h)) continue;
// Allows to add, subtract, etc functions (used by as-moses)
if (SCHEMA_NODE == t) continue;
if (QUOTE_LINK == t) continue;
if (UNQUOTE_LINK == t) continue;
if (not h->is_type(NUMERIC_OUTPUT_LINK)) return false;
}
return true;
}
/// Check the type constructors that expect types as input.
static bool check_type_ctors(const Handle& bool_atom)
{
for (const Handle& h: bool_atom->getOutgoingSet())
{
check_null(h);
Type t = h->get_type();
if (h->is_type(TYPE_NODE)) continue;
// Intervals are commonly used with GlobNodes.
if (INTERVAL_LINK == t) continue;
if (not h->is_type(TYPE_OUTPUT_LINK)) return false;
}
return true;
}
/* This runs when the shared lib is loaded. */
static __attribute__ ((constructor)) void init(void)
{
classserver().addValidator(CRISP_INPUT_LINK, check_evaluatable);
classserver().addValidator(BOOLEAN_INPUT_LINK, check_bool_vect);
classserver().addValidator(NUMERIC_INPUT_LINK, check_numeric);
classserver().addValidator(TYPE_INPUT_LINK, check_type_ctors);
}