2019-02-05 02:44:07 +02:00
|
|
|
[VerbMeanings::] Verb Meanings.
|
|
|
|
|
|
|
|
To abstract the meaning of a verb.
|
|
|
|
|
2020-07-04 16:17:00 +03:00
|
|
|
@h What we abstract.
|
|
|
|
Because this module is concerned with the structure of sentences and not
|
|
|
|
their meanings, we don't really want to get into what verbs "mean". Instead,
|
|
|
|
we assume that the tool using this module will assign meanings in some way
|
|
|
|
that it understands and we do not: the data for the meaning of a verb will
|
|
|
|
be a pointer to |VERB_MEANING_LINGUISTICS_TYPE|. (In Inform, this will be
|
|
|
|
a binary predicate.)
|
2020-03-28 21:42:53 +02:00
|
|
|
|
2020-07-04 16:17:00 +03:00
|
|
|
By default, there's no meaning at all:
|
2020-03-28 21:42:53 +02:00
|
|
|
|
2020-05-26 01:46:01 +03:00
|
|
|
@default VERB_MEANING_LINGUISTICS_TYPE void
|
2020-03-28 21:42:53 +02:00
|
|
|
|
2020-07-04 16:17:00 +03:00
|
|
|
@ The "reversal" of a verb is the meaning which exchanges its object and
|
|
|
|
subject. So the reverse meaning to "A likes B" is "A is liked by B", or
|
|
|
|
equivalent, "B likes A". We use the |VERB_MEANING_REVERSAL_LINGUISTICS_CALLBACK|
|
|
|
|
to ask for a reversal to be performed when needed.
|
|
|
|
|
2020-03-28 21:42:53 +02:00
|
|
|
=
|
2020-05-26 01:46:01 +03:00
|
|
|
VERB_MEANING_LINGUISTICS_TYPE *VerbMeanings::reverse_VMT(VERB_MEANING_LINGUISTICS_TYPE *recto) {
|
|
|
|
#ifdef VERB_MEANING_REVERSAL_LINGUISTICS_CALLBACK
|
|
|
|
return VERB_MEANING_REVERSAL_LINGUISTICS_CALLBACK(recto);
|
2020-03-28 21:42:53 +02:00
|
|
|
#endif
|
2020-05-26 01:46:01 +03:00
|
|
|
#ifndef VERB_MEANING_REVERSAL_LINGUISTICS_CALLBACK
|
2020-03-28 21:42:53 +02:00
|
|
|
return recto;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2020-07-04 16:17:00 +03:00
|
|
|
@h How this module stores verb meanings.
|
|
|
|
We can now define an object to wrap up this abstracted idea of verb meaning:
|
|
|
|
|
2019-02-05 02:44:07 +02:00
|
|
|
=
|
|
|
|
typedef struct verb_meaning {
|
2020-07-04 16:17:00 +03:00
|
|
|
int take_meaning_reversed; /* |TRUE| if this has been reversed */
|
2020-05-26 01:46:01 +03:00
|
|
|
VERB_MEANING_LINGUISTICS_TYPE *regular_meaning; /* in I7, this will be a binary predicate */
|
2020-07-26 18:09:24 +03:00
|
|
|
struct special_meaning_holder *special_meaning;
|
2020-07-04 16:17:00 +03:00
|
|
|
struct verb *take_meaning_from;
|
2019-02-05 02:44:07 +02:00
|
|
|
struct parse_node *where_assigned; /* at which sentence this is assigned to a form */
|
|
|
|
} verb_meaning;
|
|
|
|
|
|
|
|
@ All VMs begin as meaningless, which indicates (e.g.) that no meaning
|
|
|
|
has been specified.
|
|
|
|
|
|
|
|
=
|
|
|
|
verb_meaning VerbMeanings::meaninglessness(void) {
|
|
|
|
verb_meaning vm;
|
|
|
|
vm.regular_meaning = NULL;
|
|
|
|
vm.special_meaning = NULL;
|
2020-07-04 16:17:00 +03:00
|
|
|
vm.take_meaning_reversed = FALSE;
|
2019-02-05 02:44:07 +02:00
|
|
|
vm.take_meaning_from = NULL;
|
|
|
|
vm.where_assigned = current_sentence;
|
|
|
|
return vm;
|
|
|
|
}
|
|
|
|
|
|
|
|
int VerbMeanings::is_meaningless(verb_meaning *vm) {
|
2020-07-04 16:17:00 +03:00
|
|
|
vm = VerbMeanings::follow_indirection(vm);
|
2019-02-05 02:44:07 +02:00
|
|
|
if (vm == NULL) return TRUE;
|
|
|
|
if ((vm->regular_meaning == NULL) && (vm->special_meaning == NULL)) return TRUE;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2020-07-04 16:17:00 +03:00
|
|
|
@ In practice, we create VMs here. Note that regular and special meanings are
|
|
|
|
alternatives to each other: you can't have both.
|
|
|
|
|
|
|
|
=
|
|
|
|
verb_meaning VerbMeanings::regular(VERB_MEANING_LINGUISTICS_TYPE *rel) {
|
2019-02-05 02:44:07 +02:00
|
|
|
verb_meaning vm = VerbMeanings::meaninglessness();
|
|
|
|
vm.regular_meaning = rel;
|
|
|
|
return vm;
|
|
|
|
}
|
|
|
|
|
2020-07-26 18:09:24 +03:00
|
|
|
verb_meaning VerbMeanings::special(special_meaning_holder *sm) {
|
2019-02-05 02:44:07 +02:00
|
|
|
verb_meaning vm = VerbMeanings::meaninglessness();
|
2020-07-26 18:09:24 +03:00
|
|
|
vm.special_meaning = sm;
|
2019-02-05 02:44:07 +02:00
|
|
|
return vm;
|
|
|
|
}
|
|
|
|
|
2020-07-04 16:17:00 +03:00
|
|
|
@ You can, however, have neither one, if you instead choose to "indirect" the
|
|
|
|
meaning -- this means saying "the same meaning as the regular sense of the base
|
|
|
|
form of a given verb", possibly reversed. Note that
|
|
|
|
(a) An indirected VM must never be used as the meaning for the base form of a
|
|
|
|
verb, and therefore
|
|
|
|
(b) We can never have a situation where a VM indirects to a verb whose meaning
|
|
|
|
then indirects to something else.
|
|
|
|
|
2020-07-04 16:20:40 +03:00
|
|
|
This might be used, for example, to set the meaning of "liked by" to be the
|
|
|
|
same as the meaning of "likes", but with subject and object reversed. The
|
|
|
|
indirection then ensures that if the meaning of "likes" changes, its associated
|
|
|
|
usages "is liking" and "is liked by" automatically change with it.
|
|
|
|
|
2020-07-04 16:17:00 +03:00
|
|
|
=
|
|
|
|
verb_meaning VerbMeanings::indirected(verb *from, int reversed) {
|
2019-02-05 02:44:07 +02:00
|
|
|
verb_meaning vm = VerbMeanings::meaninglessness();
|
2020-07-04 16:17:00 +03:00
|
|
|
vm.take_meaning_reversed = reversed;
|
2019-02-05 02:44:07 +02:00
|
|
|
vm.take_meaning_from = from;
|
|
|
|
return vm;
|
|
|
|
}
|
|
|
|
|
2020-07-04 16:17:00 +03:00
|
|
|
@ So the following function only needs to be used once.
|
2019-02-05 02:44:07 +02:00
|
|
|
|
2020-07-04 16:17:00 +03:00
|
|
|
=
|
|
|
|
verb_meaning *VerbMeanings::follow_indirection(verb_meaning *vm) {
|
|
|
|
if ((vm) && (vm->take_meaning_from))
|
|
|
|
return VerbMeanings::first_unspecial_meaning_of_verb_form(
|
|
|
|
Verbs::base_form(
|
|
|
|
vm->take_meaning_from));
|
|
|
|
return vm;
|
2019-02-05 02:44:07 +02:00
|
|
|
}
|
|
|
|
|
2020-07-04 16:17:00 +03:00
|
|
|
@ The following function may seem curious -- what's so great about the first
|
|
|
|
regular sense of a verb? The answer is that Inform generally gives a verb at
|
|
|
|
most one regular sense.
|
|
|
|
|
|
|
|
=
|
|
|
|
verb_meaning *VerbMeanings::first_unspecial_meaning_of_verb_form(verb_form *vf) {
|
|
|
|
if (vf)
|
|
|
|
for (verb_sense *vs = vf->list_of_senses; vs; vs = vs->next_sense)
|
2020-07-27 19:44:29 +03:00
|
|
|
if (VerbMeanings::get_special_meaning(&(vs->vm)) == NULL)
|
2020-07-04 16:17:00 +03:00
|
|
|
return &(vs->vm);
|
|
|
|
return NULL;
|
2019-02-05 02:44:07 +02:00
|
|
|
}
|
|
|
|
|
2020-07-04 16:17:00 +03:00
|
|
|
@h Recording where assigned.
|
|
|
|
This helps Inform with correctly locating problem messages.
|
|
|
|
|
|
|
|
=
|
2019-02-05 02:44:07 +02:00
|
|
|
parse_node *VerbMeanings::get_where_assigned(verb_meaning *vm) {
|
|
|
|
if (vm) return vm->where_assigned;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void VerbMeanings::set_where_assigned(verb_meaning *vm, parse_node *pn) {
|
|
|
|
if (vm) vm->where_assigned = pn;
|
|
|
|
else internal_error("assigned location to null meaning");
|
|
|
|
}
|
|
|
|
|
2020-07-04 16:17:00 +03:00
|
|
|
@h The regular meaning.
|
|
|
|
This is not as simple as returning the |regular_meaning| field, because we
|
|
|
|
have to follow any indirection, and reverse if necessary.
|
|
|
|
|
|
|
|
=
|
|
|
|
VERB_MEANING_LINGUISTICS_TYPE *VerbMeanings::get_regular_meaning(verb_meaning *vm) {
|
|
|
|
if (vm == NULL) return NULL;
|
|
|
|
int rev = vm->take_meaning_reversed;
|
|
|
|
vm = VerbMeanings::follow_indirection(vm);
|
|
|
|
if (vm == NULL) return NULL;
|
|
|
|
VERB_MEANING_LINGUISTICS_TYPE *rel = vm->regular_meaning;
|
|
|
|
if ((rev) && (rel)) return VerbMeanings::reverse_VMT(rel);
|
|
|
|
return rel;
|
|
|
|
}
|
|
|
|
|
|
|
|
VERB_MEANING_LINGUISTICS_TYPE *VerbMeanings::get_regular_meaning_of_form(verb_form *vf) {
|
|
|
|
return VerbMeanings::get_regular_meaning(
|
|
|
|
VerbMeanings::first_unspecial_meaning_of_verb_form(vf));
|
|
|
|
}
|
|
|
|
|
|
|
|
@h The special meaning.
|
|
|
|
This is also not as simple as returning the |regular_meaning| field, because
|
|
|
|
again we have to follow any indirection. Since we have no good way to modify
|
|
|
|
a special meaning function, we have to provide a function to tell the user
|
|
|
|
whether to reverse what that function does.
|
|
|
|
|
|
|
|
=
|
2020-07-27 19:44:29 +03:00
|
|
|
special_meaning_holder *VerbMeanings::get_special_meaning(verb_meaning *vm) {
|
2020-07-04 16:17:00 +03:00
|
|
|
vm = VerbMeanings::follow_indirection(vm);
|
|
|
|
if (vm == NULL) return NULL;
|
|
|
|
return vm->special_meaning;
|
|
|
|
}
|
|
|
|
|
|
|
|
int VerbMeanings::get_reversal_status_of_smf(verb_meaning *vm) {
|
|
|
|
if (vm == NULL) return FALSE;
|
|
|
|
return vm->take_meaning_reversed;
|
|
|
|
}
|
|
|
|
|
|
|
|
@h Logging.
|
|
|
|
|
|
|
|
=
|
2019-02-05 02:44:07 +02:00
|
|
|
void VerbMeanings::log(OUTPUT_STREAM, void *vvm) {
|
|
|
|
verb_meaning *vm = (verb_meaning *) vvm;
|
|
|
|
if (vm == NULL) { WRITE("<none>"); return; }
|
2020-07-04 16:17:00 +03:00
|
|
|
if (vm->take_meaning_reversed) WRITE("reversed-");
|
2019-02-05 02:44:07 +02:00
|
|
|
if (vm->take_meaning_from) WRITE("<$w>=", vm->take_meaning_from);
|
2020-07-04 16:17:00 +03:00
|
|
|
VERB_MEANING_LINGUISTICS_TYPE *m = VerbMeanings::get_regular_meaning(vm);
|
|
|
|
if (m) {
|
2019-02-05 02:44:07 +02:00
|
|
|
#ifdef CORE_MODULE
|
2020-07-04 16:17:00 +03:00
|
|
|
WRITE("(%S)", m->debugging_log_name);
|
2019-02-05 02:44:07 +02:00
|
|
|
#else
|
2020-07-04 16:17:00 +03:00
|
|
|
WRITE("(regular)");
|
2019-02-05 02:44:07 +02:00
|
|
|
#endif
|
2020-07-04 16:17:00 +03:00
|
|
|
} else if (vm->special_meaning) WRITE("(special)");
|
|
|
|
else WRITE("(meaningless)");
|
2020-06-29 22:08:47 +03:00
|
|
|
}
|