To create and manage activities, which are bundles of rules for carrying out tasks.


§1. Introduction. An activity is just a triple of rulebooks with related names, a common focus and a shared set of variables, so this will not be a long section of code.

typedef struct activity {
    struct wording name;  text of the name of the activity
    struct rulebook *before_rules;  rulebooks for when this is followed
    struct rulebook *for_rules;
    struct rulebook *after_rules;
    struct kind *activity_on_what_kind;  or null
    struct shared_variable_set *activity_variables;  activity variables owned here
    struct activity_compilation_data compilation_data;
    int future_action_flag;
    int hide_in_debugging_flag;
    CLASS_DEFINITION
} activity;

§2. Whereas rulebooks can turn values into other values, activities are more like void functions: they work on a value, but produce nothing.

kind *Activities::to_kind(activity *av) {
    return Kinds::unary_con(CON_activity, av->activity_on_what_kind);
}

int Activities::used_by_future_actions(activity *av) {
    return av->future_action_flag;
}

int Activities::hide_in_debugging(activity *av) {
    return av->hide_in_debugging_flag;
}

§3. Activities are much simpler to create than actions. For example,

Announcing something is an activity on numbers.

The object phrase (here "an activity on numbers") matches <k-kind> and needs no special Preform of its own; here is the subject phrase:

<activity-sentence-subject> ::=
    <activity-sentence-subject> ( <activity-note> ) |   ==> { R[1], - }
    <activity-sentence-subject> -- <activity-note> -- | ==> { R[1], - }
    <activity-sentence-subject> ( ...... ) |            ==> Issue PM_ActivityNoteUnknown problem3.1
    <activity-sentence-subject> -- ... -- |             ==> Issue PM_ActivityNoteUnknown problem3.1
    <activity-new-name>                                 ==> { R[1], - }

<activity-note> ::=
    <documentation-symbol> |                            ==> { -, -, <<ds>> = R[1] }
    future action |                                     ==> { -, -, <<future>> = TRUE }
    hidden in RULES command                             ==> { -, -, <<hide>> = TRUE }

<activity-new-name> ::=
    ... of/for something/anything |                     ==> { TRUE, -, <<any>> = TRUE }
    ... something/anything |                            ==> { TRUE, -, <<any>> = TRUE }
    ...                                                 ==> { TRUE, -, <<any>> = FALSE }

§3.1. Issue PM_ActivityNoteUnknown problem3.1 =

    StandardProblems::sentence_problem(Task::syntax_tree(), _p_(PM_ActivityNoteUnknown),
        "one of the notes about this activity makes no sense",
        "and should be either 'documented at SYMBOL', 'hidden in RULES command' "
        "or 'future action'.");
    ==> { FALSE, - };

§4.

activity *Activities::new(kind *K, wording W, int bypassed) {
    kind *on_kind = Kinds::unary_construction_material(K);
    int kind_given = TRUE;
    if (Kinds::eq(on_kind, K_nil)) kind_given = FALSE;
    if (bypassed) { kind_given = FALSE; on_kind = K_object; }
    <<ds>> = -1;
    <<future>> = FALSE;
    <<hide>> = FALSE;
    <activity-sentence-subject>(W);
    W = GET_RW(<activity-new-name>, 1);
    wording doc_symbol = Wordings::one_word(<<ds>>);
    The name can't have been used before4.1;
    The kind the activity is performed on, if there is one, must be definite4.2;
    If it is not of or for something, then it cannot have a kind4.3;

    activity *av = CREATE(activity);
    av->name = W;
    av->compilation_data = RTActivities::new_compilation_data(av, doc_symbol);
    av->activity_on_what_kind = on_kind;
    av->future_action_flag = <<future>>;
    av->hide_in_debugging_flag = <<hide>>;

    LOGIF(ACTIVITY_CREATIONS, "Created activity '%W'\n", av->name);

    Make proper nouns for the activity name4.5;

    av->activity_variables = SharedVariables::new_set(av->compilation_data.variables_id);

    av->before_rules = Activities::make_rulebook(av, 0);
    av->for_rules = Activities::make_rulebook(av, 1);
    av->after_rules = Activities::make_rulebook(av, 2);

    PluginCalls::new_activity_notify(av);
    return av;
}

§4.1. The name can't have been used before4.1 =

    if (<s-value>(W)) {
        parse_node *spec = <<rp>>;
        if (!(Node::is(spec, UNKNOWN_NT)) && (!(Node::is(spec, PROPERTY_VALUE_NT)))) {
            StandardProblems::sentence_problem(Task::syntax_tree(),
                _p_(PM_BadActivityName),
                "this already has a meaning",
                "and so cannot be the name of a newly created activity.");
            return NULL;
        }
    }

§4.2. The kind the activity is performed on, if there is one, must be definite4.2 =

    if (Kinds::Behaviour::definite(on_kind) == FALSE) {
        LOG("I'm reading the kind as: %u\n", on_kind);
        StandardProblems::sentence_problem(Task::syntax_tree(),
            _p_(PM_ActivityIndefinite),
            "this is an activity on a kind which isn't definite",
            "and doesn't tell me enough about what sort of value the activity should work "
            "on. For example, 'Divining is an activity on numbers' is fine because "
            "'numbers' is definite, but 'Divining is an activity on values' is not "
            "allowed.");
        return NULL;
    }

§4.3. If it is not of or for something, then it cannot have a kind4.3 =

    if ((<<any>> == FALSE) && (kind_given)) {
        StandardProblems::sentence_problem(Task::syntax_tree(),
            _p_(PM_ActivityMisnamed),
            "the name of this activity implies that it acts on nothing",
            "which doesn't fit with what you say about it. For example, 'Painting is an "
            "activity on brushes' isn't allowed because the activity's name doesn't end "
            "with 'something': it should be 'Painting something is an activity on brushes'.");
        return NULL;
    }

§4.4. Once a new activity has been created, the following is used to make a noun for it; actually two — for example, both "announcing" and "announcing activity".

<activity-name-construction> ::=
    ... activity

§4.5. Make proper nouns for the activity name4.5 =

    Nouns::new_proper_noun(W, NEUTER_GENDER, ADD_TO_LEXICON_NTOPT,
        ACTIVITY_MC, Rvalues::from_activity(av), Task::language_of_syntax());
    word_assemblage wa =
        PreformUtilities::merge(<activity-name-construction>, 0,
            WordAssemblages::from_wording(av->name));
    wording AW = WordAssemblages::to_wording(&wa);
    Nouns::new_proper_noun(AW, NEUTER_GENDER, ADD_TO_LEXICON_NTOPT,
        ACTIVITY_MC, Rvalues::from_activity(av), Task::language_of_syntax());

§5. And its rulebooks are named with these constructions:

<activity-rulebook-construction> ::=
    before ... |
    for ... |
    after ...

§6.

rulebook *Activities::make_rulebook(activity *av, int N) {
    int def = NO_OUTCOME;
    if (N == 1) def = SUCCESS_OUTCOME;
    word_assemblage wa = PreformUtilities::merge(<activity-rulebook-construction>, N,
        WordAssemblages::from_wording(av->name));
    wording RW = WordAssemblages::to_wording(&wa);
    rulebook *R = Rulebooks::new_automatic(RW, av->activity_on_what_kind,
        def, FALSE, TRUE, 0, RTActivities::rulebook_package(av, N));
    Rulebooks::grant_access_to_variables(R, av->activity_variables);
    return R;
}

§7. And this nonterminal parses individual activity names.

<activity-name> internal {
    parse_node *p = Lexicon::retrieve(ACTIVITY_MC, W);
    if (Rvalues::is_CONSTANT_construction(p, CON_activity)) {
        ==> { -, Rvalues::to_activity(p) };
        return TRUE;
    }
    ==> { fail nonterminal }
}

§8. The author can demand with a "translates as" sentence that a given rulebook should have an identifier given to it which is accessible to Inter:

void Activities::translates(wording W, parse_node *p2) {
    if (<activity-name>(W)) {
        activity *av = (activity *) <<rp>>;
        RTActivities::translate(av, Node::get_text(p2));
    } else {
        LOG("Tried %W\n", W);
        StandardProblems::sentence_problem(Task::syntax_tree(),
            _p_(PM_TranslatesNonActivity),
            "this is not the name of an activity",
            "so cannot be translated.");
    }
}

§9. Activity variables. Any new activity variable name is vetted by being run through this:

void Activities::add_variable(activity *av, parse_node *cnode) {
    if (Node::get_type(cnode) == UNPARSED_NOUN_NT) {
        Problems::quote_source(1, current_sentence);
        StandardProblems::handmade_problem(Task::syntax_tree(),
            _p_(PM_ActivityVariableNameless));
        Problems::issue_problem_segment(
            "You wrote %1, which I am reading as a request to make a new named variable "
            "for an activity - a value associated with a activity and which has a name. "
            "Here, though, there seems to be no name for the variable as such, only an "
            "indication of its kind. Try something like 'The printing the banner text "
            "activity has a number called the accumulated vanity'.");
        Problems::issue_problem_end();
        return;
    }

    wording SW = Node::get_text(cnode->down);
    wording VW = Node::get_text(cnode->down->next);

    parse_node *spec = NULL; if (<s-type-expression>(SW)) spec = <<rp>>;

    The name of the variable must be fortunate9.1;
    The specification must not be qualified9.2;
    The specification must be just a kind9.3;
    That kind must be definite9.4;

    SharedVariables::new(av->activity_variables, VW, Specifications::to_kind(spec), FALSE);
}

§9.1. The name of the variable must be fortunate9.1 =

    if (<unfortunate-name>(VW)) {
        Problems::quote_source(1, current_sentence);
        Problems::quote_wording(2, VW);
        StandardProblems::handmade_problem(Task::syntax_tree(),
            _p_(PM_ActivityVarAnd));
        Problems::issue_problem_segment(
            "You wrote %1, which I am reading as a request to make a new named variable "
            "for an activity - a value associated with a activity and which has a name. "
            "The request seems to say that the name in question is '%2', but I'd prefer "
            "to avoid 'and', 'or', 'with', or 'having' in such names, please.");
        Problems::issue_problem_end();
        return;
    }

§9.2. The specification must not be qualified9.2 =

    if ((Specifications::is_kind_like(spec) == FALSE) &&
        (Specifications::is_description(spec))) {
        Problems::quote_source(1, current_sentence);
        Problems::quote_wording(2, SW);
        StandardProblems::handmade_problem(Task::syntax_tree(),
            _p_(PM_ActivityVarOverspecific));
        Problems::issue_problem_segment(
            "You wrote %1, which I am reading as a request to make a new named variable "
            "for an activity - a value associated with a activity and which has a name. "
            "The request seems to say that the value in question is '%2', but this is too "
            "specific a description. (Instead, a kind of value (such as 'number') or a "
            "kind of object (such as 'room' or 'thing') should be given. To get a property "
            "whose contents can be any kind of object, use 'object'.)");
        Problems::issue_problem_end();
        return;
    }

§9.3. The specification must be just a kind9.3 =

    if (Specifications::is_kind_like(spec) == FALSE) {
        LOG("Offending SP: $T", spec);
        Problems::quote_source(1, current_sentence);
        Problems::quote_wording(2, SW);
        StandardProblems::handmade_problem(Task::syntax_tree(),
            _p_(PM_ActivityVarUnknownKOV));
        Problems::issue_problem_segment(
            "You wrote %1, but '%2' is not the name of a kind of value which I know "
            "(such as 'number' or 'text').");
        Problems::issue_problem_end();
        return;
    }

§9.4. That kind must be definite9.4 =

    if (Kinds::Behaviour::definite(Specifications::to_kind(spec)) == FALSE) {
        Problems::quote_source(1, current_sentence);
        Problems::quote_wording(2, SW);
        StandardProblems::handmade_problem(Task::syntax_tree(),
            _p_(PM_ActivityVarValue));
        Problems::issue_problem_segment(
            "You wrote %1, but this does not give me a clear enough idea what it will hold. "
            "You need to say what kind of value: for instance, 'A door has a number called "
            "street address.' is allowed because 'number' is specific about the kind of "
            "value.");
        Problems::issue_problem_end();
        return;
    }