/* -*- Mode: Prolog -*- */
/** @copyright
  
  This file is part of PrologDoc (http://prologdoc.sourceforge.net/).

  Copyright (C) 2004 by Salvador Fandino (sfandino@@yahoo.com)

  PrologDoc is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.

  PrologDoc 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 General Public License
  along with PrologDoc; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  
  @/copyright */

:- use_module(library('prologdoc/pd')).
:- use_module(library('prologdoc/pd_format')).

:- multifile
	tag_args_req/2,
	tag_arg_line_is_term/1,
	tag_groups/2,
	tag_id_base/3,
	tag_xml_common/3,
	tag_xml_map/3.

/**

  @s1 PrologDoc Tags defined on this file:

    @s2 Formating tags

      @s3 section tags
        @@s1, @@s2, @@s3, @@s4, @@s5,
        @@s6, @@s7, @@s8 and @@s9

      @s3 quoting tags

        @s4 quote code@: @@c

        @s4 generic quoting@: @@q

        @s4 block quoting@: @@block

      @s3 linking tags

        @s4 predicate reference@: @@p
  
        @s4 library predicate reference@: @@l

        @s4 generic link@: @@link

    @s2 Semantic tags
  
      @s3 copyright declaration@: @@copyright

      @s3 predicate declaration@: @@pred

        @s4 predicate mode@: @@mode

        @s4 predicate argument@: @@arg

        @s4 exceptions@: @@except

        @s4 predicate description@: @@desc
  
  
  @pred tag_args_req(Tag, [Arg, ...])
    predicate used to define which element arguments are mandatory.

    @arg Tag: name of the tag or tag class this rule applies to.
    @arg [Arg, ...]: list containing the names of the required arguments.

  
  @pred tag_arg_line_is_term(Tag)
    some elements require that when line argument is used it being
    parsed as a prolog term. This predicate indicates such condition.

  
  @pred tag_groups/2
    predicate defining how child elements are grouped.

    @mode tag_groups(Tag, [GroupTag/ChildTag, ..., RestTag])
    @mode tag_groups(Tag, [GroupTag/ChildTag, ...])

    @arg Tag: element name or type this rule applies to.
    @arg GroupTag: name of the new group element where matching children are moved to.
    @arg ChildTag: child element name or type children must match to be moved to the group.
    @arg RestTag: remaining childs are moved to a group element with this name when specified.

  
  @pred tag_xml_map(ElementPattern, OpeningMapping, ClosigMapping)
    defines XML generation pattern.

    @arg ElemenPattern=t(Tag, [Arg=Value, ...], [ChildElementPattern, ...])
      rule applies to elements matching this pattern as follows...
    @arg Tag: matchs when equals tag name or type
    @arg Arg=Value: matchs when element has and argument with this name
      and value (@c(Value) is usually an unbound variable)
    @arg ChildElementPattern: element has some child that matches this pattern
  
    @arg OpeningMapping=[FormatPattern, Var1, ...]: pattern defining how to generate
      the opening XML tag.@l(format/2) is called as @c(format(FormatPattern, [Var1, ...])).
    @arg ClosingMapping: similar to @c(OpeningMapping) but for closing XML tag.

  
  @pred tag_xml_common(Tag/XMLTag, [Arg/XMLArg, ...], [Arg/XMLChild, ...])
    predicate defining how to map an element to XML for some simple mappings.

    @arg Tag: rule applies to elements with this tag name or of this type.
    @arg XMLTag: name of the generated XML tag.
    @arg Arg: argument name.
    @arg XMLArg: maps argument as an XML tag argument with this name.
    @arg XMLChild: maps argument as an XML element with this name.
  
*/

:- export(tag_args_req(_,_)).
:- export(tag_arg_line_is_term(_)).
:- export(tag_groups(_,_)).
:- export(tag_id_base(_,_,_)).
:- export(new_ref(_,_,_,_)).
:- export(new_prop(_,_,_)).
:- export(new_consult(_,_,_,_)).
:- export(tag_register(_,_,_,_,_)).
:- export(tag_xml_common(_,_,_,_)).
:- export(tag_xml_map(_,_,_)).
:- export(tag_flatten(_,_)).
:- export(tag_remap_args(_,_,_,_,_)).
:- export(ele_ref(_,_,_,_)).
:- export(ele_prop(_,_,_)).
:- export(ele_consult(_,_,_,_)).
:- export(tag_xref(_,_,_,_)).
:- export(tag_sort_key(_,_)).
:- export(tag_order(_,_)).
:- export(tag_sort_childs(_)).

:- dynamic ele_ref/4.
:- dynamic ele_prop/3.
:- dynamic ele_consult/4.

% ele_ref(Type, Name, Id, File)
new_ref(Type, Name, Id, File) :-
	assert(ele_ref(Type, Name, Id, File)).
% ele_prop(Type, Name, Prop)
new_prop(Type, Id, Prop) :-
	assert(ele_prop(Type, Id, Prop)).
% ele_consult(File, Type, Name, Target)
new_consult(File, Type, Name, Target) :-
	assert(ele_consult(File, Type, Name, Target)).

tag_class($content, $first).
tag_class($para, $content).
tag_class($inp, $content).
tag_class(list, $content).
tag_class(block, $content).
tag_class(desc, $first).
tag_class(s1, $first).
tag_class(s1, $section).
tag_class(s2, $section).
tag_class(s3, $section).
tag_class(s4, $section).
tag_class(s5, $section).
tag_class(s6, $section).
tag_class(s7, $section).
tag_class(s8, $section).
tag_class(s9, $section).

tag_class(link, $inp).
tag_class(figure, $inp).
tag_class(q, $inp).
tag_class(p, $inp).
tag_class(l, $inp).
tag_class(c, $inp).
tag_class(k, $inp).
tag_class(m, $inp).

tag_class($container, $no_empty).
tag_class($para, $container).

tag_class(pred, $decl).
tag_class(method, $decl).

tag_class($section, $container).
tag_class(mode, $container).
tag_class(arg, $container).
tag_class(except, $container).
tag_class(li, $container).
tag_class(desc, $container).

tag_inside($top, $first).
tag_inside(copyright, $first).
tag_inside($decl, $first).
tag_inside($container, $content).
tag_inside($top, copyright).
tag_inside($top, pred).
tag_inside($top, class).
tag_inside(class, method).
tag_inside(class, superclass).
tag_inside(class, metaclass).
tag_inside(class, $first).
tag_inside($decl, prop).
tag_inside($decl, mode).
tag_inside($decl, arg).
tag_inside($decl, except).
tag_inside(list, li).
tag_inside(s1, s2).
tag_inside(s2, s3).
tag_inside(s3, s4).
tag_inside(s4, s5).
tag_inside(s5, s6).
tag_inside(s6, s7).
tag_inside(s7, s8).
tag_inside(s8, s9).

tag_args(link, [url]).
tag_args(figure, [url]).
tag_args(li, [head]).
tag_args(except, [exception]).
tag_args($decl, [form]).
tag_args(mode, [form]).
tag_args(arg, [name]).
tag_args(prop, [name]).
tag_args($section, [head]).
tag_args(class, [name]).
tag_args(superclass, [name]).
tag_args(metaclass, [name]).
tag_args(q, [text]).
tag_args(c, [code]).
tag_args(p, [pred]).
tag_args(l, [pred]).
tag_args(k, [class]).
tag_args(m, [method]).

tag_args_req($decl, [name, arity]).
tag_args_req(mode, [form]).
tag_args_req(arg, [name]).
tag_args_req(link, [url]).
tag_args_req(class, [name]).
tag_args_req(superclass, [name]).
tag_args_req(metaclass, [name]).

tag_arg_line_is_term($decl).
tag_arg_line_is_term(mode).

tag_id_base(t(class, [name=N], []), [], N).
tag_id_base(t(pred, [name=N, arity=A], []), [], N/A).
tag_id_base(t(method, [name=N, arity=A], []), [$id(class)=C], C/N/A).
tag_id_base(t($file, [$unique=U], []), [], U).
tag_id_base(t($top, [$module=M], []), [], M).

tag_register(t($file, [$id=Id, $abs=N], []), [], file, N, Id).
tag_register(t($top, [$id=Id, $module=M], []), [], module, M, Id).
tag_register(t(pred, [$id=Id, name=N, arity=A], []), [], pred, N/A, Id).
tag_register(t(class, [$id=Id, name=N], []), [], class, N, Id).
tag_register(t(method, [$id=Id, name=N, arity=A], []), [$id(class)=CId], method, CN/N/A, Id) :-
	ele_ref(class, CN, CId, _).

tag_groups($top, [$desc/ $first, $consults/ $consult, $classes/class, $preds/pred, $classes/class]).
tag_groups($class, [$methods/method, $superclasses/superclass, $metaclasses/metaclass, $props/prop, $desc]).
tag_groups(pred, [$props/prop, $modes/mode, $args/arg, $excepts/except, $desc]).
tag_groups(mode, [$desc]).
tag_groups(arg, [$desc]).
tag_groups(li, [$body]).
tag_groups(copyright, [$desc/ $first, $rest]).
tag_groups($section, [$body]).

tag_order($top, [copyright, $desc, $consults, $classes, $preds]).
tag_order($class, [$metaclasses, $superclasses, $props, $desc, $methods]).
tag_order($decl, [$props, $modes, $except, $args, $desc]).

tag_sort_childs($methods).
tag_sort_childs($preds).

tag_sort_key(t($decl, [name=N, arity=A],[]), N/A).

tag_remap_args(p, [pred=M:N/A], [], [pred=N/A, $module=M, $user=M:N/A], []).
tag_remap_args(p, [pred=F*N/A], [], [pred=N/A, $file=F, $user=N/A], []).
tag_remap_args(p, [pred=N/A], [], [pred=N/A, $user=N/A], []).
tag_remap_args(m, [method=(C->M/A)], [], [method=M/A, $class=C, $user=(C->M/A)], []).
tag_remap_args(m, [method=M/A], [C = $id($class)], [method=M/A, $class=C, $user=(C->M/A)], []).

tag_flatten($desc, desc).

tag_xml_common($consults/ consults, [], [], []).
tag_xml_common($consult/ consult, [$name/ name, $type/ type], [], []).
tag_xml_common(pred/predicate, [name/name, arity/arity, $id/id], [], []).
tag_xml_common($preds/predicates, [], [], []).
tag_xml_common(mode/mode, [], [form/form], []).
tag_xml_common($props/properties, [], [], []).
tag_xml_common(prop/property, [name/name], [], []).
tag_xml_common(li/li, [], [head/head], []).
tag_xml_common($desc/description, [], [], []).
tag_xml_common($body/body, [], [], []).
tag_xml_common($para/paragraph, [], [], []).
tag_xml_common(list/list, [], [], []).
tag_xml_common($args/arguments, [], [], []).
tag_xml_common($modes/modes, [], [], []).
tag_xml_common(arg/argument, [], [name/name], []).
tag_xml_common($classes/classes, [], [], []).
tag_xml_common($superclasses/superclasses, [], [], []).
tag_xml_common($metaclasses/metaclases, [], [], []).
tag_xml_common(class/class, [name/name, $id/id], [], []).
tag_xml_common(superclass/superclass, [name/name], [], []).
tag_xml_common(metaclass/metaclass, [name/name], [], []).
tag_xml_common(class/class, [name/name], [], []).
tag_xml_common($methods/methods, [], [], []).
tag_xml_common(method/method, [name/name, arity/arity, $id/id], [], []).
tag_xml_common(copyright/copyright, [], [], []).
tag_xml_common(s1/section1, [], [head/head], []).
tag_xml_common(s2/section2, [], [head/head], []).
tag_xml_common(s3/section3, [], [head/head], []).
tag_xml_common(s4/section4, [], [head/head], []).
tag_xml_common(s5/section5, [], [head/head], []).
tag_xml_common(s6/section6, [], [head/head], []).
tag_xml_common(s7/section7, [], [head/head], []).
tag_xml_common(s8/section8, [], [head/head], []).
tag_xml_common(s9/section9, [], [head/head], []).
tag_xml_common(q/quote, [], [], [text]).
tag_xml_common(c/code, [], [], [code]).
tag_xml_common(p/predicate_ref, [], [], [$user]).
tag_xml_common(p/class_ref, [], [], [name]).
tag_xml_common(m/method_ref, [], [], [$user]).

tag_xml_map(t($file, [$unique=F], []), ['<?xml version="1.0" encoding="ISO-8859-1"?>~n<?xml-stylesheet href="~Cprologdoc-2.0.xsl" type="text/xsl"?>~n<!DOCTYPE prologdoc SYSTEM "~Cprologdoc-2.0.dtd">~n<prologdoc file="~H">', prefix/'', prefix/'', F], ['</prologdoc>']).

tag_xref(t(p, [pred=P, $file=F], []), pred, P, file(F)).
tag_xref(t(p, [pred=P, $module=M], []), pred, P, module(M)).
tag_xref(t(p, [pred=P], []), pred, P, none).
tag_xref(t(c, [name=N], []), class, N, none).
tag_xref(t(m, [method=M, $class=C], []), class, C/M, none).
tag_xref(t(metaclass, [name=N], []), class, N, none).
tag_xref(t(superclass, [name=N], []), class, N, none).




% callback(Phase, Element, Name, Priority).
% name(Phase, TreeIn, TreeOut, ArgIn, ArgOut).

% process phase:
% call callbacks on children
tag_callback(process, children_cb, 0, t(_,_,_)).
% get number of lines on file to calculate element line positions
tag_callback(process, line_pos_top_cb, 1000, t($top,_,_)).
% calculate element line positions
tag_callback(process, line_pos_cb, 1000, t(_,_,_)).
% convert line arg to args
tag_callback(process, line_to_args_cb, 960, t(_,_,_)).
% add arg name to arguments missing it
tag_callback(process, set_arg_names_cb, 950, t(_,_,_)).
% parse predicate and method arguments
tag_callback(process, pred_args_cb, 910, t(pred,_,_)).
tag_callback(process, pred_args_cb, 910, t(method,_,_)).
% check all required arguments are in place
tag_callback(process, args_check_cb, 900, t(_,_,_)).

% parse_prolog phase
tag_callback(autodoc, children_cb, 0, t($file,_,_)).
tag_callback(autodoc, children_cb, 0, t($all,_,_)).
tag_callback(autodoc, open_source_cb, 500, t($file,_,_)).
tag_callback(autodoc, close_source_cb, -500, t($file,_,_)).
tag_callback(autodoc, auto_doc_cb, 500, t($top,_,_)).

% arrange phase
tag_callback(arrange, children_cb, 0, t(_,_,_)).
tag_callback(arrange, remap_args_cb, 600, t(_,_,_)).
tag_callback(arrange, make_groups_cb, 500, t(_,_,_)).
tag_callback(arrange, flatten_cb, -500, t(_,_,_)).
tag_callback(arrange, sort_cb, 300, t(_,_,_)).

% assignid phase
tag_callback(assignid, children_cb, 0, t(_,_,_)).
tag_callback(assignid, assign_id_cb, 500, t(_,_,_)).
tag_callback(assignid, register_properties_cb, 400, t(_,_,_)).
tag_callback(assignid, push_current_id_cb, 200, t(_,_,_)).
tag_callback(assignid, register_entity_cb, 100, t(_,_,_)).
tag_callback(assignid, pop_current_id_cb, -200, t(_,_,_)).

% consults phase
tag_callback(consults, children_cb, 0, t($top,_,_)).
tag_callback(consults, children_cb, 0, t($file,_,_)).
tag_callback(consults, children_cb, 0, t($all,_,_)).
tag_callback(consults, push_current_id_cb, 200, t(_,_,_)).
tag_callback(consults, pop_current_id_cb, -200, t(_,_,_)).
tag_callback(consults, resolve_consult_cb, 100, t($consult,_,_)).

%generate phase
tag_callback(generate, children_cb, 0, t(_,_,_)).
tag_callback(generate, open_target_file_cb, 1000, t($file,_,_)).
tag_callback(generate, close_target_file_cb, -1000, t($file,_,_)).
tag_callback(generate, push_current_id_cb, 200, t(_,_,_)).
tag_callback(generate, print_open_tags_cb, 100, t(_,_,_)).
tag_callback(generate, print_text_cb, 100, text(_)).
tag_callback(generate, print_close_tags_cb, -100, t(_,_,_)).
tag_callback(generate, pop_current_id_cb, -200, t(_,_,_)).

% declarations for auto-generation of prolog
% documentation from prolog source code
:- consult(pd_default_autodoc).

% default callbacks are in a different module.
:- use_module(library('prologdoc/pd_default_callbacks')).

