void generate_precondition_satisfier(ast::tree& ast, ast::node* root, formatter& output)
{
    plnnrc_assert(ast::is_op_or(root));

    for (ast::node* child = root->first_child; child != 0; child = child->next_sibling)
    {
        plnnrc_assert(ast::is_op_and(child));
        generate_conjunctive_clause(ast, child, output);
    }
}
void generate_literal_chain_comparison(ast::tree& ast, ast::node* root, ast::node* atom, formatter& output)
{
    ast::node* arg_0 = atom->first_child;
    plnnrc_assert(arg_0 && ast::is_term_variable(arg_0));
    ast::node* arg_1 = arg_0->next_sibling;
    plnnrc_assert(arg_1 && ast::is_term_variable(arg_1) && !arg_1->next_sibling);

    plnnrc_assert(definition(arg_0) && definition(arg_1));

    const char* comparison_op = atom->s_expr->token;

    int var_index_0 = ast::annotation<ast::term_ann>(arg_0)->var_index;
    int var_index_1 = ast::annotation<ast::term_ann>(arg_1)->var_index;

    if (ast::is_op_not(root))
    {
        output.writeln("if (!(state._%d %s state._%d))", var_index_0, comparison_op, var_index_1);
    }
    else
    {
        output.writeln("if (state._%d %s state._%d)", var_index_0, comparison_op, var_index_1);
    }

    {
        scope s(output, root->next_sibling != 0);

        if (root->next_sibling)
        {
            generate_literal_chain(ast, root->next_sibling, output);
        }
        else
        {
            output.writeln("PLNNR_COROUTINE_YIELD(state);");
        }
    }
}
void generate_conjunctive_clause(ast::tree& ast, ast::node* root, formatter& output)
{
    plnnrc_assert(ast::is_op_and(root));

    if (root->first_child)
    {
        generate_literal_chain(ast, root->first_child, output);
    }
    else
    {
        // the formula is trivial: (or (and))
        output.writeln("PLNNR_COROUTINE_YIELD(state);");
        output.newline();
    }
}
void generate_precondition_next(ast::tree& ast, ast::node* root, unsigned branch_index, formatter& output)
{
    plnnrc_assert(is_logical_op(root));

    output.writeln("bool next(p%d_state& state, worldstate& world)", branch_index);
    {
        scope s(output);

        output.writeln("PLNNR_COROUTINE_BEGIN(state);");
        output.newline();

        generate_precondition_satisfier(ast, root, output);

        output.writeln("PLNNR_COROUTINE_END();");
    }
}
Пример #5
0
void generate_worldstate_reflectors(ast::Tree& ast, ast::Node* worldstate, Formatter& output)
{
    ast::Node* worldstate_namespace = worldstate->first_child;
    plnnrc_assert(worldstate_namespace && ast::is_namespace(worldstate_namespace));

    Paste_Fully_Qualified_Namespace paste_world_namespace(worldstate_namespace);

    output.writeln("template <typename V>");
    output.writeln("struct Generated_Type_Reflector<%p::Worldstate, V>", &paste_world_namespace);
    {
        Class_Scope s(output);

        output.writeln("void operator()(const %p::Worldstate& world, V& visitor)", &paste_world_namespace);
        {
            Scope s(output, false);

            for (ast::Node* atom = worldstate_namespace->next_sibling; atom != 0; atom = atom->next_sibling)
            {
                if (!ast::is_atom(atom))
                {
                    continue;
                }

                output.writeln("PLNNR_GENCODE_VISIT_ATOM_LIST(%p, atom_%i, %i_tuple, visitor);", &paste_world_namespace, atom->s_expr->token, atom->s_expr->token);
            }
        }
    }

    for (ast::Node* atom = worldstate_namespace->next_sibling; atom != 0; atom = atom->next_sibling)
    {
        if (!ast::is_atom(atom))
        {
            continue;
        }

        generate_atom_reflector(ast, atom, &paste_world_namespace, "atom_name", "tuple", "atom", output);
    }
}
void generate_preconditions(ast::tree& ast, ast::node* domain, formatter& output)
{
    unsigned branch_index = 0;

    for (ast::node* method = domain->first_child; method != 0; method = method->next_sibling)
    {
        if (!ast::is_method(method))
        {
            continue;
        }

        for (ast::node* branch = method->first_child->next_sibling; branch != 0; branch = branch->next_sibling)
        {
            plnnrc_assert(ast::is_branch(branch));

            ast::node* precondition = branch->first_child;

            generate_precondition_state(ast, precondition, branch_index, output);
            generate_precondition_next(ast, precondition, branch_index, output);

            ++branch_index;
        }
    }
}
    virtual void operator()(formatter& output)
    {
        output.put_id(function_call->s_expr->token);
        output.put_char('(');

        for (ast::node* argument = function_call->first_child; argument != 0; argument = argument->next_sibling)
        {
            switch (argument->type)
            {
            case ast::node_term_variable:
                {
                    int var_index = ast::annotation<ast::term_ann>(argument)->var_index;
                    output.put_str(var_prefix);
                    output.put_int(var_index);
                }
                break;
            case ast::node_term_call:
                {
                    paste_precondition_function_call paste(argument, var_prefix);
                    output.put_str("world.");
                    paste(output);
                }
                break;
            default:
                // unsupported argument type
                plnnrc_assert(false);
            }

            if (!is_last(argument))
            {
                output.put_str(", ");
            }
        }

        output.put_char(')');
    }
Пример #8
0
void generate_domain_reflectors(ast::Tree& ast, ast::Node* domain, Formatter& output)
{
    ast::Node* domain_namespace = domain->first_child;
    plnnrc_assert(domain_namespace && ast::is_namespace(domain_namespace));

    Paste_Fully_Qualified_Namespace paste_domain_namespace(domain_namespace);

    for (Id_Table_Values operators = ast.operators.values(); !operators.empty(); operators.pop())
    {
        ast::Node* atom = operators.value()->first_child;

        if (!atom->first_child)
        {
            continue;
        }

        generate_atom_reflector(ast, atom, &paste_domain_namespace, "task_name", "args", "task", output);
    }

    for (ast::Node* method = domain->first_child; method != 0; method = method->next_sibling)
    {
        if (!ast::is_method(method))
        {
            continue;
        }

        ast::Node* atom = method->first_child;

        if (!atom->first_child)
        {
            continue;
        }

        generate_atom_reflector(ast, atom, &paste_domain_namespace, "task_name", "args", "task", output);
    }
}
void generate_literal_chain(ast::tree& ast, ast::node* root, formatter& output)
{
    plnnrc_assert(ast::is_op_not(root) || ast::is_term_call(root) || is_atom(root) || is_comparison_op(root));

    ast::node* atom = root;

    if (ast::is_op_not(root))
    {
        atom = root->first_child;
    }

    if (ast::is_comparison_op(atom))
    {
        generate_literal_chain_comparison(ast, root, atom, output);
        return;
    }

    if (ast::is_term_call(atom))
    {
        generate_literal_chain_call_term(ast, root, atom, output);
        return;
    }

    const char* atom_id = atom->s_expr->token;
    int atom_index = ast::annotation<ast::atom_ann>(atom)->index;

    if (ast::is_op_not(root) && all_unbound(atom))
    {
        output.writeln("if (!tuple_list::head<%i_tuple>(world.atoms[atom_%i]))", atom_id, atom_id);
        {
            scope s(output);

            if (root->next_sibling)
            {
                generate_literal_chain(ast, root->next_sibling, output);
            }
            else
            {
                output.writeln("PLNNR_COROUTINE_YIELD(state);");
            }
        }
    }
    else if (ast::is_op_not(root) && all_bound(atom))
    {
        output.writeln("for (state.%i_%d = tuple_list::head<%i_tuple>(world.atoms[atom_%i]); state.%i_%d != 0; state.%i_%d = state.%i_%d->next)",
            atom_id, atom_index,
            atom_id,
            atom_id,
            atom_id, atom_index,
            atom_id, atom_index,
            atom_id, atom_index);
        {
            scope s(output);

            int atom_param_index = 0;

            for (ast::node* term = atom->first_child; term != 0; term = term->next_sibling)
            {
                if (ast::is_term_variable(term))
                {
                    int var_index = ast::annotation<ast::term_ann>(term)->var_index;

                    output.writeln("if (state.%i_%d->_%d == state._%d)", atom_id, atom_index, atom_param_index, var_index);
                    {
                        scope s(output, !is_last(term));
                        output.writeln("break;");
                    }
                }

                if (ast::is_term_call(term))
                {
                    paste_precondition_function_call paste(term, "state._");

                    output.writeln("if (state.%i_%d->_%d == world.%p)", atom_id, atom_index, atom_param_index, &paste);
                    {
                        scope s(output, !is_last(term));
                        output.writeln("break;");
                    }
                }

                ++atom_param_index;
            }
        }

        output.writeln("if (state.%i_%d == 0)", atom_id, atom_index);
        {
            scope s(output, is_first(root));

            if (root->next_sibling)
            {
                generate_literal_chain(ast, root->next_sibling, output);
            }
            else
            {
                output.writeln("PLNNR_COROUTINE_YIELD(state);");
            }
        }
    }
    else
    {
        output.writeln("for (state.%i_%d = tuple_list::head<%i_tuple>(world.atoms[atom_%i]); state.%i_%d != 0; state.%i_%d = state.%i_%d->next)",
            atom_id, atom_index,
            atom_id,
            atom_id,
            atom_id, atom_index,
            atom_id, atom_index,
            atom_id, atom_index);
        {
            scope s(output, is_first(root));

            const char* comparison_op = "!=";

            if (ast::is_op_not(root))
            {
                comparison_op = "==";
            }

            int atom_param_index = 0;

            for (ast::node* term = atom->first_child; term != 0; term = term->next_sibling)
            {
                if (ast::is_term_variable(term) && definition(term))
                {
                    int var_index = ast::annotation<ast::term_ann>(term)->var_index;

                    output.writeln("if (state.%i_%d->_%d %s state._%d)", atom_id, atom_index, atom_param_index, comparison_op, var_index);
                    {
                        scope s(output);
                        output.writeln("continue;");
                    }
                }

                if (ast::is_term_call(term))
                {
                    paste_precondition_function_call paste(term, "state._");

                    output.writeln("if (state.%i_%d->_%d %s world.%p)", atom_id, atom_index, atom_param_index, comparison_op, &paste);
                    {
                        scope s(output);
                        output.writeln("continue;");
                    }
                }

                ++atom_param_index;
            }

            atom_param_index = 0;

            for (ast::node* term = atom->first_child; term != 0; term = term->next_sibling)
            {
                if (ast::is_term_variable(term) && !definition(term))
                {
                    int var_index = ast::annotation<ast::term_ann>(term)->var_index;
                    output.writeln("state._%d = state.%i_%d->_%d;", var_index, atom_id, atom_index, atom_param_index);
                    output.newline();
                }

                ++atom_param_index;
            }

            if (root->next_sibling)
            {
                generate_literal_chain(ast, root->next_sibling, output);
            }
            else
            {
                output.writeln("PLNNR_COROUTINE_YIELD(state);");
            }
        }
    }
}
Пример #10
0
void generate_task_type_dispatcher(ast::Tree& ast, ast::Node* domain, Formatter& output)
{
    ast::Node* domain_namespace = domain->first_child;
    plnnrc_assert(domain_namespace && ast::is_namespace(domain_namespace));

    Paste_Fully_Qualified_Namespace paste_namespace(domain_namespace);

    output.writeln("template <typename V>");
    output.writeln("struct Task_Type_Dispatcher<%p::Task_Type, V>", &paste_namespace);
    {
        Class_Scope s(output);
        output.writeln("void operator()(const %p::Task_Type& task_type, void* args, V& visitor)", &paste_namespace);
        {
            Scope s(output, false);
            output.writeln("switch (task_type)");
            {
                Scope s(output, false);

                for (ast::Node* method = domain->first_child; method != 0; method = method->next_sibling)
                {
                    if (!ast::is_method(method))
                    {
                        continue;
                    }

                    ast::Node* method_atom = method->first_child;
                    plnnrc_assert(method_atom);

                    output.writeln("case %p::task_%i:", &paste_namespace, method_atom->s_expr->token);
                    {
                        Indented s(output);

                        const char* atom_id = method_atom->s_expr->token;

                        if (method_atom->first_child)
                        {
                            output.writeln("PLNNR_GENCODE_VISIT_TASK_WITH_ARGS(visitor, %p, task_%i, %i_args);", &paste_namespace, atom_id, atom_id);
                        }
                        else
                        {
                            output.writeln("PLNNR_GENCODE_VISIT_TASK_NO_ARGS(visitor, %p, task_%i);", &paste_namespace, atom_id);
                        }

                        output.writeln("break;");
                    }
                }

                for (Id_Table_Values operators = ast.operators.values(); !operators.empty(); operators.pop())
                {
                    ast::Node* operatr = operators.value();
                    ast::Node* operator_atom = operatr->first_child;

                    output.writeln("case %p::task_%i:", &paste_namespace, operator_atom->s_expr->token);
                    {
                        Indented s(output);

                        const char* atom_id = operator_atom->s_expr->token;

                        if (operator_atom->first_child)
                        {
                            output.writeln("PLNNR_GENCODE_VISIT_TASK_WITH_ARGS(visitor, %p, task_%i, %i_args);", &paste_namespace, atom_id, atom_id);
                        }
                        else
                        {
                            output.writeln("PLNNR_GENCODE_VISIT_TASK_NO_ARGS(visitor, %p, task_%i);", &paste_namespace, atom_id);
                        }

                        output.writeln("break;");
                    }
                }

                output.writeln("default:");
                {
                    Indented s(output);
                    output.writeln("plnnr_assert(false);");
                    output.writeln("break;");
                }
            }
        }
    }
}
Пример #11
0
void format_error(Error_Ann* annotation, Writer& stream)
{
    Formatter output(stream);
    output.init(2048);

    const char* format = error_format_string(annotation->id);

    output.put_str("error: ");
    output.put_char('[');
    output.put_int(annotation->line);
    output.put_char(':');
    output.put_int(annotation->column);
    output.put_str("] ");

    while (*format)
    {
        if (*format == '$')
        {
            move(format);
            char digit = *format;
            plnnrc_assert(isdigit(digit));
            int slot = digit - '0';
            plnnrc_assert(slot < annotation->argument_count);
            Error_Argument_Type arg_type = annotation->argument_type[slot];
            plnnrc_assert(arg_type != error_argument_none);

            switch (arg_type)
            {
            case error_argument_node_token:
                {
                    sexpr::Node* s_expr = annotation->argument_node[slot];
                    output.put_str(s_expr->token);
                }
                break;
            case error_argument_node_location:
                {
                    Location arg = annotation->argument_location[slot];
                    output.put_char('[');
                    output.put_int(arg.line);
                    output.put_char(':');
                    output.put_int(arg.column);
                    output.put_char(']');
                }
                break;
            case error_argument_node_string:
                {
                    const char* arg = annotation->argument_string[slot];
                    output.put_str(arg);
                }
                break;
            case error_argument_selection:
                {
                    move(format);
                    plnnrc_assert(*format == '{');
                    move(format);
                    int selection = annotation->argument_selection[slot];

                    for (int i = 0; i < selection; ++i)
                    {
                        skip(format, '|');
                        move(format);
                    }

                    while (*format != '|' && *format != '}')
                    {
                        plnnrc_assert(format);
                        output.put_char(*format);
                        move(format);
                    }

                    skip(format, '}');
                }
                break;
            default:
                break;
            }
        }
        else
        {
            output.put_char(*format);
        }

        move(format);
    }

    output.put_char('\n');
}
Пример #12
0
void deallocate(void* ptr)
{
    plnnrc_assert(dealloc_f != 0);
    dealloc_f(ptr);
}
Пример #13
0
void* allocate(size_t size)
{
    plnnrc_assert(alloc_f != 0);
    return alloc_f(size);
}