- [:let idx 0]
+ [:!let idx 0]
[:for cmd ${:@command} {
- [$cmd name]
[incr idx; return]
Index: library/lib/doc-tools.tcl
===================================================================
diff -u -r18ff1444fef5c209dfb40cf2ae694206c0d10309 -r26ce746b45449fbff64f88c6d9e9050a63b89449
--- library/lib/doc-tools.tcl (.../doc-tools.tcl) (revision 18ff1444fef5c209dfb40cf2ae694206c0d10309)
+++ library/lib/doc-tools.tcl (.../doc-tools.tcl) (revision 26ce746b45449fbff64f88c6d9e9050a63b89449)
@@ -36,7 +36,8 @@
#
# @param class Request an instance of a particular entity class (e.g., ...)
# @param name What is the entity name (e.g., nx::doc for a package)
- # @param args A vector of arbitrary arguments, provided to the entity when being constructed
+ # @param args A vector of arbitrary arguments, provided to the
+ # entity when being constructed
# @return The identifier of the newly created entity object
# @subcommand ::nx::doc::@#foo
@@ -94,6 +95,15 @@
return $result
}
+ proc sort_by_value {d} {
+ set haystack [list]
+ dict for {key value} $d {
+ lappend haystack [list $key $value]
+ }
+ return [dict create {*}[concat {*}[lsort -integer -index 1 -decreasing $haystack]]]
+ }
+
+
proc find_asset_path {{subdir library/lib/doc-assets}} {
# This helper tries to identify the file system path of the
# asset ressources.
@@ -113,23 +123,15 @@
:public method apply {} {
foreach mixin [:info children -type [current class]::Mixin] {
set base "${:prefix}::[namespace tail $mixin]"
- puts "TRYING mixin $mixin base $base"
if {[::nsf::isobject $base]} {
set scope [expr {[$mixin scope] eq "object" && [$base info is class]?"class-object":""}]
- puts stderr "APPLYING $base {*}$scope mixin add $mixin"
$base {*}$scope mixin add $mixin
}
}
}
Class create [current]::Mixin -superclass Class {
:attribute {scope class}
- :method init args {
- :public method foo {} {
- puts stderr "[current class]->[current method]";
- next
- }
- }
}
}
@@ -140,15 +142,18 @@
# basic name-generating mechanisms for documentation entities
# based on properties such as entity name, root namespace, etc.
#
- # @param tag Defaults to the tag label to be used in comment tags. It may vary from the auto-generated default!
- # @param root_namespace You may choose your own root-level namespace hosting the namespace hierarchy of entity objects
+ # @param tag Defaults to the tag label to be used in comment
+ # tags. It may vary from the auto-generated default!
+ # @param root_namespace You may choose your own root-level
+ # namespace hosting the namespace hierarchy of entity objects
:attribute {tag {[string trimleft [string tolower [namespace tail [current]]] @]}}
:attribute {root_namespace "::nx::doc::entities"}
namespace eval ::nx::doc::entities {}
:public class-object method normalise {tagpath names} {
+ # puts stderr "tagpath $tagpath names $names"
# 1) verify balancedness of
if {[llength $tagpath] != [llength $names]} {
return [list 1 "Imbalanced tag line spec: '$tagpath' vs. '$names'"]
@@ -188,7 +193,21 @@
set entity_path [list]
foreach axis $tagpath value $names {
if {$entity eq ""} {
- if {[QualifierTag info instances @$axis] eq "" && [Tag info instances @$axis] eq ""} {
+ set cmd [info command @$axis]
+ #
+ # TODO interp-aliasing objects under different command names
+ # is currently not transparent to some ::nsf::* helpers,
+ # such as ::nsf::isobject. Should this be changed?
+ #
+ if {$cmd ne ""} {
+ set cmd [namespace origin $cmd]
+ set target [interp alias {} $cmd]
+ if {$target ne ""} {
+ set cmd $target
+ }
+ }
+
+ if {$cmd eq "" || ![::nsf::isobject $cmd] || ![$cmd info has type Tag]} {
return [list 1 "The entity type '@$axis' is not available."]
}
set entity [@$axis id $value]
@@ -238,7 +257,8 @@
set partof_name [string trimleft $partof_name :]
return [join [list [:root_namespace] $subns $partof_name {*}$scope $name] ::]
} else {
- return "[:root_namespace]::${subns}$name"
+ set name [string trimleft $name :]
+ return "[:root_namespace]::${subns}::$name"
}
}
@@ -495,8 +515,14 @@
# @command nx
#
# @use ::nsf::command
- # @use {Object foo}
- # @use command {Object foo}
+
+ # or
+
+ # class.method {X foo}
+ #
+ # @use {Class foo}
+ # @use object.method {Object foo}
+
lassign $value pathspec pathnames
if {$pathnames eq ""} {
set pathnames $pathspec
@@ -602,12 +628,25 @@
Class create StructuredEntity -superclass Entity {
- :public method owned_parts {} {
+ :public method part_attributes {} {
set slots [:info lookup slots]
- set r [dict create]
-# puts stderr SLOTS=$slots
+ set attrs [list]
foreach s $slots {
if {![$s info has type ::nx::doc::PartAttribute] || ![$s eval {info exists :part_class}]} continue;
+ lappend attrs $s [$s part_class]
+ }
+ return $attrs
+ }
+ :public method owned_parts {} {
+ set r [dict create]
+ foreach {s cls} [:part_attributes] {
+ #
+ # TODO: there is no equivalent to mixinof/has mixin for the
+ # superclass-subclass axis: info superclassof | /cls/ has
+ # superclass | info subclassof | /cls/ has subclass; are info
+ # subclass and superclass sufficient?
+ #
+ # if {![$s info has type ::nx::doc::PartAttribute] || ![$s eval {info exists :part_class}] || [current class] ni [[$s eval {set :part_class}] info superclass -closure]} continue;
set accessor [$s name]
# puts stderr "PROCESSING ACCESSOR $accessor, [info exists :$accessor]"
if {[info exists :$accessor]} {
@@ -637,7 +676,7 @@
Class create [current]::Containable {
# TODO: check the interaction of required, per-object attribute and ::nsf::assertion
#:object attribute container:object,type=[:info parent],required
- :class-object attribute container:object,type=[:info parent]
+ :attribute container:object,type=[:info parent]
:method create args {
#
# Note: preserve the container currently set at this callstack
@@ -655,6 +694,24 @@
next
}
}
+ :method create args {
+ #
+ # Note: preserve the container currently set at this callstack
+ # level. [next] will cause the container to change if another
+ # container entity is initialised in the following!
+ #
+ if {[info exists :container]} {
+ set cont ${:container}
+ set obj [next]
+ if {![$obj eval {info exists :partof}]} {
+ $cont register $obj
+ }
+ return $obj
+ } else {
+ next
+ }
+ }
+
}
# Note: The default "" corresponds to the top-level namespace "::"!
:attribute {@namespace ""}
@@ -690,11 +747,14 @@
:method init {} {
next
+
QualifierTag mixin add [current class]::Resolvable
[current class]::Resolvable container [current]
- QualifierTag mixin add [current class]::Containable
- @package class-object mixin add [current class]::Containable
- [current class]::Containable container [current]
+
+ foreach {attr part_class} [:part_attributes] {
+ $part_class class-object mixin add [current class]::Containable
+ $part_class container [current]
+ }
}
:public method register {containable:object,type=::nx::doc::Entity} {
@@ -710,6 +770,10 @@
:attribute license
:attribute creationdate
:attribute {version ""}
+
+ :attribute @glossary -slotclass ::nx::doc::PartAttribute {
+ set :part_class ::nx::doc::@glossary
+ }
:attribute @package -slotclass ::nx::doc::PartAttribute {
set :part_class ::nx::doc::@package
@@ -747,12 +811,11 @@
:method require_part {domain prop value} {
set value [expr {![string match ":*" $value] ? "__out__: $value": "__out__$value"}]
next [list $domain $prop $value]
- #next $domain $prop "__out__ $value"
}
set :part_class ::nx::doc::@param
}
- :forward @sub-command %self @command
+ :public forward @sub-command %self @command
:attribute @command -slotclass ::nx::doc::PartAttribute {
:pretty_name "Subcommand"
:pretty_plural "Subcommands"
@@ -784,7 +847,7 @@
-mixin ContainerEntity::Containable {
:attribute @author -slotclass ::nx::doc::PartAttribute
- :forward @object %self @child-object
+ :public forward @object %self @child-object
:attribute @child-object -slotclass ::nx::doc::PartAttribute {
set :part_class ::nx::doc::@object
:public method id {domain prop value} {
@@ -798,7 +861,7 @@
}
- :forward @class %self @child-class
+ :public forward @class %self @child-class
:attribute @child-class -slotclass ::nx::doc::PartAttribute {
set :part_class ::nx::doc::@class
:public method id {domain prop value} {
@@ -811,12 +874,12 @@
}
}
- :forward @method %self @object-method
+ :public forward @method %self @object-method
:attribute @class-object-method -slotclass ::nx::doc::PartAttribute {
set :part_class ::nx::doc::@method
}
- :forward @attribute %self @class-object-attribute
+ :public forward @attribute %self @class-object-attribute
#:forward @param %self @object-param
:attribute @class-object-attribute -slotclass ::nx::doc::PartAttribute {
set :part_class ::nx::doc::@param
@@ -840,14 +903,14 @@
-superclass @object {
:attribute @superclass -slotclass ::nx::doc::PartAttribute
- :forward @attribute %self @class-attribute
+ :public forward @attribute %self @class-attribute
:attribute @class-attribute -slotclass ::nx::doc::PartAttribute {
:pretty_name "Per-class attribute"
:pretty_plural "Per-class attributes"
set :part_class ::nx::doc::@param
}
- :forward @method %self @class-method
+ :public forward @method %self @class-method
:attribute @class-method -slotclass ::nx::doc::PartAttribute {
:pretty_name "Per-class method"
:pretty_plural "Per-class methods"
@@ -933,9 +996,9 @@
- :forward @class-method %self @method
- :forward @class-object-method %self @method
- :forward @sub-method %self @method
+ :public forward @class-method %self @method
+ :public forward @class-object-method %self @method
+ :public forward @sub-method %self @method
:attribute @method -slotclass ::nx::doc::PartAttribute {
set :part_class ::nx::doc::@method
:public method id {domain prop name} {
@@ -1123,6 +1186,19 @@
interp alias {} ::nx::doc::@attribute {} ::nx::doc::@param
interp alias {} ::nx::doc::@parameter {} ::nx::doc::@param
+ #
+ # Providing interp-wide aliases for @glossary. For most processing
+ # steps, this is syntactic sugar, however, the aliases cause
+ # different rendering behaviour for glossary references and entries.
+ #
+
+ interp alias {} ::nx::doc::@gls {} ::nx::doc::@glossary
+ interp alias {} ::nx::doc::@Gls {} ::nx::doc::@glossary
+ interp alias {} ::nx::doc::@glspl {} ::nx::doc::@glossary
+ interp alias {} ::nx::doc::@Glspl {} ::nx::doc::@glossary
+ interp alias {} ::nx::doc::@acr {} ::nx::doc::@glossary
+ interp alias {} ::nx::doc::@acrfirst {} ::nx::doc::@glossary
+
namespace export CommentBlockParser @command @object @class @package \
@project @method @attribute @parameter @
}
@@ -1176,11 +1252,16 @@
} {
# Here, we assume the -nonleaf mode being active for {{{[eval]}}}.
set tmplscript [list subst [:read_tmpl $template]]
+ #
+ # TODO: This looks awkward, however, till all requirements are
+ # figured out (as for the origin mechanism) we so keep track
+ # of the actual rendered entity ... review later ...
+ #
+ $entity rendered_entity $entity
$entity eval [subst -nocommands {
$initscript
$tmplscript
}]
- # $entity eval [list subst $template]
}
@@ -1263,28 +1344,38 @@
}
set :markup_map(sub) {
- "{{{" "\[:code \{"
- "}}}" "\}\]"
- "{{" "\[:link "
- "}}" "\]"
+ "'''" "\[:listing \{"
+ "'''" "\}\]"
+ "<<" "\[:link "
+ ">>" "\]"
}
set :markup_map(unescape) {
"\\{" "{"
"\\}" "}"
"\\#" "#"
+ "\\<" "<"
+ "\\>" ">"
+ "\\'" "'"
}
- :method map {line set} {
- set line [string map [[::nsf::current class] eval [list set :markup_map($set)]] $line]
+ :method unescape {line} {
+ set line [string map [[::nsf::current class] eval [list set :markup_map(unescape)]] $line]
}
+ :method map {line} {
+ regsub -all -- {('''([^']+?)''')} $line {[:listing {\2}]} line
+ regsub -all -- {(<<([^<]+?)>>)} $line {[:link \2]} line
+ return $line
+ }
+
+
:method as_list {} {
set preprocessed [list]
set is_code_block 0
foreach line [next] {
- if {[regsub -- {^\s*(\{\{\{)\s*$} $line "\[:code -inline false \{" line] || \
- (${is_code_block} && [regsub -- {^\s*(\}\}\})\s*$} $line "\}\]" line])} {
+ if {(!${is_code_block} && [regsub -- {^\s*(''')\s*$} $line "\[:listing -inline false \{" line]) || \
+ (${is_code_block} && [regsub -- {^\s*(''')\s*$} $line "\}\]" line])} {
set is_code_block [expr {!$is_code_block}]
append line \n
} elseif {${is_code_block}} {
@@ -1305,8 +1396,8 @@
:public method as_text {} {
set preprocessed [join [:as_list] " "]
- set preprocessed [:map $preprocessed sub]
- set preprocessed [:map $preprocessed unescape]
+ set preprocessed [:map $preprocessed]
+ set preprocessed [:unescape $preprocessed]
return [subst $preprocessed]
}
@@ -1334,38 +1425,42 @@
set top_level_entities [:owned_parts]
dict for {feature instances} $top_level_entities {
if {[$feature name] eq "@package"} {
- foreach {entity_type pkg_entities} [$feature owned_parts] {
- dict lappend top_level_entities $entity_type {*}$pkg_entities
+ foreach pkg $instances {
+ dict for {pkg_feature pkg_feature_instances} [$pkg owned_parts] {
+ dict lappend top_level_entities $pkg_feature {*}$pkg_feature_instances
+ }
}
}
}
set init [subst {
- set project [current object]
+ set project \[:current_project\]
set project_entities \[list $top_level_entities\]
}]
set project_path [file join $outdir [string trimleft ${:name} :]]
if {![catch {file mkdir $project_path} msg]} {
- # puts stderr [list file copy -force -- [$renderer find_asset_path] $project_path/assets]
set assets [lsearch -all -inline -glob -not [glob -directory [find_asset_path] *] *.tmpl]
set target $project_path/assets
file mkdir $target
file copy -force -- {*}$assets $target
set values [join [dict values $top_level_entities]]
- # puts stderr "VALUES=$values"
+
+ #
+ # Make sure that the @project entity is processed last.
+ #
+ lappend values [current object]
foreach e $values {
- #puts stderr "PROCESSING=$e render -initscript $init $tmpl"
+ #
+ # TODO: For now, in templates we (silently) assume that we act
+ # upon structured entities only ...
+ #
+ if {![$e info has type ::nx::doc::StructuredEntity]} continue;
+ $e current_project [current object]
set content [$e render -initscript $init $tmpl]
:write_data $content [file join $project_path "[$e filename].$ext"]
puts stderr "$e written to [file join $project_path [$e filename].$ext]"
}
-
- set index [:render -initscript $init $tmpl]
- # puts stderr "we have [llength $entities] documentation entities ($entities)"
- :write_data $index [file join $project_path "index.$ext"]
-
-
}
# 3) TODO: revoke the application of the mixin layer (for the sake of
@@ -1377,6 +1472,30 @@
#
MixinLayer::Mixin create [current]::Entity -superclass TemplateData {
+ #
+ # TODO: Would it be useful to allow attribute slots to describe
+ # a per-class-object state, while the accessor/mutator methods
+ # are defined on the per-class level. It feels like the class
+ # instance variables in Smalltalk ...
+ #
+ # TODO: Why is call protection barfing when the protected target
+ # is called from within a public forward. This should qualify as
+ # a valid call site (from "within" the same object!), shouldn't it?
+ # :protected class-object attribute current_project:object,type=::nx::doc::@project
+ :class-object attribute current_project:object,type=::nx::doc::@project
+ :public forward current_project [current] %method
+
+ #
+ # TODO: For now, this acts as the counterweight to "origin",
+ # when @use aliasing is used, processed_entity can be used to
+ # refer to the actual entity at the upper end of the aliasing
+ # chain. Verify, whether this is an acceptable approach ...
+ #
+ :class-object attribute rendered_entity:object,type=::nx::doc::Entity
+ :public forward rendered_entity [current] %method
+
+ :public forward print_name %current name
+
:method fit {str max {placeholder "..."}} {
if {[llength [split $str ""]] < $max} {
return $str;
@@ -1400,7 +1519,7 @@
# @object instances. Untangle!
set access [expr {[$inst eval {info exists :@modifier}]?[$inst @modifier]:""}]
set host ${:name}
- set name [$inst name]
+ set name [$inst print_name]
set url "[:filename].html#[string trimleft [$feature name] @]_[$inst name]"
set type [$feature name]
lappend entries [subst $entry]
@@ -1409,30 +1528,35 @@
return "\[[join $entries ,\n]\]"
}
- :method code {{-inline true} script} {
+ :method listing {{-inline true} script} {
return [expr {$inline?"$script
":"
$script
"}]
}
:method link {tag names} {
- #puts stderr "RESOLVING tag $tag names $names"
set tagpath [split [string trimleft $tag @] .]
lassign [::nx::doc::Tag normalise $tagpath $names] err res
if {$err} {
- #puts stderr RES=$res
+ puts stderr RES=$res
return "
?";
}
lassign [::nx::doc::Tag find -all -strict {*}$res] err path
if {$err || $path eq ""} {
- #puts stderr "FAILED res $path (err-$err-id-[expr {$path eq ""}])"
+ # puts stderr "FAILED res $path (err-$err-id-[expr {$path eq ""}])"
return "
?";
}
set path [dict create {*}$path]
set entities [dict keys $path]
set id [lindex $entities end]
- return [$id render_link $tag [current] $path]
+ return [$id render_link $tag [:rendered_entity] $path]
}
+ :public method make_link {source} {
+ set path [dict create {*}[:get_upward_path -attribute {set :name}]]
+ set tag [[:info class] tag]
+ return [:render_link $tag $source $path]
+ }
+
:public method render_link {tag source path} {
#puts stderr PATH=$path
set id [current]
@@ -1485,31 +1609,90 @@
}
}; # NxDocTemplating::Entity
+ MixinLayer::Mixin create [current]::@project -superclass [current]::Entity {
+ :public method filename {} {
+ return "index"
+ }
+ }
+
MixinLayer::Mixin create [current]::@glossary -superclass [current]::Entity {
-
+ :public method print_name {} {
+ return [expr {[info exists :@acronym]?${:@acronym}:${:@pretty_name}}]
+ }
+
+ array set :tags {
+ @gls {
+ set print_name [string tolower ${:@pretty_name} 0 0]
+ set title ${:@pretty_name}
+ }
+ @Gls {
+ set print_name [string toupper ${:@pretty_name} 0 0]
+ set title ${:@pretty_name}
+ }
+ @glspl {
+ set print_name [string tolower ${:@pretty_plural} 0 0]
+ set title ${:@pretty_plural}
+ }
+ @Glspl {
+ set print_name [string toupper ${:@pretty_plural} 0 0]
+ set title ${:@pretty_plural}
+ }
+ @acr {
+ set acronym(short) 1
+ }
+ @acrfirst {
+ set acronym(long) 1
+ }
+
+ }
+
+ :public method href {-local:switch top_entity:optional} {
+ set fragments "#${:name}"
+ if {$local} {
+ return $fragments
+ } else {
+ return "[[:current_project] filename].html$fragments"
+ }
+
+ }
+
:public method render_link {tag source path} {
+ # tag-specific rendering
+ set acronym(long) 0
+ set acronym(short) 0
+ set print_name ${:@pretty_name}
+ set title ${:@pretty_name}
+ if {[[current class] eval [list info exists :tags($tag)]]} {
+ eval [[current class] eval [list set :tags($tag)]]
+ }
+ if {[info exists :@acronym]} {
+ #
+ # First occurrance of an acronym entry!
+ #
+ if {!$acronym(short) && ($acronym(long) || ![info exists :refs] || \
+ ![dict exists ${:refs} $source])} {
+ set print_name "$print_name (${:@acronym})"
+ set res "
$print_name"
+ } else {
+ set title $print_name
+ set print_name ${:@acronym}
+ set anchor "
$print_name"
+ set res "
$anchor"
+ }
+ } else {
+ set res "
$print_name"
+ }
+
+ # record for reverse references
if {![info exists :refs]} {
set :refs [dict create]
}
dict incr :refs $source
- # TODO: provide the project context here and render the
- # glossary location accordingly, rather than hard-code "index.html".
- return "
[string tolower ${:@pretty_name}]"
- }
- #
- # TODO: this should go into the appropriate template
- #
- :public method render_refs {} {
- if {[info exists :refs]} {
- dict for {entity count} ${:refs} {
- }
- }
- }
-
+ return $res
+ }
}
-
}; # NxDocTemplating
#
@@ -2047,14 +2230,14 @@
return $parser_obj
}
- :forward has_next expr {${:idx} < [llength ${:comment_block}]}
- :method dequeue {} {
+ :public forward has_next expr {${:idx} < [llength ${:comment_block}]}
+ :public method dequeue {} {
set r [lindex ${:comment_block} ${:idx}]
incr :idx
return $r
}
- :forward rewind incr :idx -1
- :forward fastforward set :idx {% llength ${:comment_block}}
+ :public forward rewind incr :idx -1
+ :public forward fastforward set :idx {% llength ${:comment_block}}
:public method cancel {statuscode {msg ""}} {
:fastforward
@@ -2201,7 +2384,7 @@
}
}
- :forward event=parse %self {% subst {parse@${:current_comment_line_type}}}
+ :public forward event=parse %self {% subst {parse@${:current_comment_line_type}}}
:method event=next {line} {
set next_section [[${:block_parser} processed_section] next_comment_section]
:on_exit $line
@@ -2216,15 +2399,16 @@
# realise the sub-state (a variant of METHOD-FOR-STATES) and their
# specific event handling
+ # set :lineproc {{tag args} {return [concat {*}$args]}}
+ set :lineproc {{tag args} {return [list $tag $args]}}
:method parse@tag {line} {
- set line [split [string trimleft $line]]
- set tag [lindex $line 0]
+ lassign [apply [[current class] eval {set :lineproc}] {*}$line] tag line
if {[:info lookup methods -source application $tag] eq ""} {
set msg "The tag '$tag' is not supported for the entity type '[namespace tail [:info class]]"
${:block_parser} cancel INVALIDTAG $msg
}
-# puts stderr ":$tag [lrange $line 1 end]"
- :$tag [lrange $line 1 end]
+ #:$tag [lrange $line 1 end]
+ :$tag $line
}
:method parse@text {line} {
@@ -2279,61 +2463,9 @@
}
}
- # realise the parse events specific to the substates of description
+ set :lineproc {{tag name args} {return [list $tag $name $args]}}
:method parse@tag {line} {
- #
- # When hitting this parsing step, we have an unresolved
- # entity. The context section specifies the entity to create
- # or to resolve for further processing.
- #
- set line [split [string trimleft $line]]
- set args [lassign $line tag name]
- lassign [:resolve_partof_entity $tag $name] nq_name partof_entity
- if {$partof_entity ne ""} {
- if {[$partof_entity info lookup methods -source application $tag] eq ""} {
- ${:block_parser} cancel INVALIDTAG "The tag '$tag' is not supported for the entity type
- '[namespace tail [$partof_entity info class]]'"
- # [InvalidTag new -message [subst {
- # The tag '$tag' is not supported for the entity type
- # '[namespace tail [$partof_entity info class]]'
- # }]] throw
- }
- # puts stderr "$partof_entity $tag $nq_name {*}$args"
- set current_entity [$partof_entity $tag $nq_name {*}$args]
-
- } else {
- #
- # TODO: @object-method raises some issues (at least when
- # processed without a resolved context = its partof entity).
- # It is not an entity type, because it merely is a "scoped"
- # @method. It won't resolve then as a proper instance of
- # Tag, hence we observe an InvalidTag exception. For
- # now, we just ignore and bypass this issue by allowing
- # InvalidTag exceptions in analyze()
- #
- set qualified_tag [namespace qualifiers [current]]::$tag
- ${:block_parser} cancel INVALIDTAG "The entity type '$tag' is not available"
- # if {[Tag info instances -closure $qualified_tag] eq ""} {
- # [InvalidTag new -message [subst {
- # The entity type '$tag' is not available
- # }]] throw
- # }
- # puts stderr "$tag new -name $nq_name {*}$args"
- set current_entity [$tag new -name $nq_name {*}$args]
- }
- #
- # make sure that the current_entity has parser capabilities
- # and the relevant state of the previous entity before the
- # context switch
- # TODO: refactor later
- ${:block_parser} current_entity $current_entity
- ${:block_parser} processed_section [current class]
- $current_entity current_comment_line_type ${:current_comment_line_type}
- $current_entity block_parser ${:block_parser}
- }
-
- :method parse@tag {line} {
- set args [lassign $line axes names]
+ lassign [apply [[current class] eval {set :lineproc}] {*}$line] axes names args
set entity ${:partof_entity}
set axes [split [string trimleft $axes @] .]
@@ -2368,13 +2500,38 @@
set entity $res
if {$entity eq ""} {
- if {[QualifierTag info instances @$leaf(axis)] eq "" && [Tag info instances @$leaf(axis)] eq ""} {
+ set cmd [info commands @$leaf(axis)]
+
+ # TODO interp-aliasing objects under different command names
+ # is currently not transparent to some ::nsf::* helpers,
+ # such as ::nsf::isobject. Should this be changed?
+ #
+ if {$cmd ne ""} {
+ set cmd [namespace origin $cmd]
+ set target [interp alias {} $cmd]
+ if {$target ne ""} {
+ set cmd $target
+ }
+ }
+
+ if {$cmd eq "" || ![::nsf::isobject $cmd] || \
+ ![$cmd info has type Tag]} {
+
${:block_parser} cancel INVALIDTAG "The entity type '@$leaf(axis)' is not available."
}
+
+ # VERIFY! Still an issue? TODO: @object-method raises some
+ # issues (at least when processed without a resolved
+ # context = its partof entity). It is not an entity type,
+ # because it merely is a "scoped" @method. It won't
+ # resolve then as a proper instance of Tag, hence we
+ # observe an InvalidTag exception. For now, we just ignore
+ # and bypass this issue by allowing InvalidTag exceptions
+ # in analyze()
+
set entity [@$leaf(axis) new -name $leaf(name) {*}$args]
} else {
if {[$entity info lookup methods -source application @$leaf(axis)] eq ""} {
-okup())
${:block_parser} cancel INVALIDTAG "The tag '$leaf(axis)' is not supported for the entity type '[namespace tail [$entity info class]]'"
}
set entity [$entity @$leaf(axis) [list $leaf(name) {*}$args]]
Index: library/nx/nx.nxd
===================================================================
diff -u -r18ff1444fef5c209dfb40cf2ae694206c0d10309 -r26ce746b45449fbff64f88c6d9e9050a63b89449
--- library/nx/nx.nxd (.../nx.nxd) (revision 18ff1444fef5c209dfb40cf2ae694206c0d10309)
+++ library/nx/nx.nxd (.../nx.nxd) (revision 26ce746b45449fbff64f88c6d9e9050a63b89449)
@@ -1,56 +1,61 @@
# -*- Tcl -*-
+
# @package ::nx
#
-# The Next Scripting Language is a compact and expressive object-oriented language
-# extension for Tcl. The object system model is highly influenced by
-# CLOS. This package provides the basic object system for the Next
-# language. It defines the basic language entities {{@class ::nx::Object}} and
-# {{@class ::nx::Class}}, as well as essential language primitives
-# (e.g., {{@command ::nx::next}} and {{@command ::nx::current}}).
+# The <<@glossary nx>> is a compact and expressive object-oriented
+# language extension for <<@Gls tcl>>. The object system model is highly
+# influenced by <<@glossary clos>> and its off-springs (e.g.,
+# <<@glossary flavors>>). This package provides the basic object system for
+# <<@glossary nx>>. It defines the basic language entities <<@class
+# ::nx::Object>> and <<@class ::nx::Class>>, as well as essential
+# language primitives (in particular, <<@command ::nx::next>> and <<@command
+# ::nx::current>>).
#
# @require Tcl
# @version 1.0.0a
# @namespace ::nx
# @class Object
#
-# Next Scripting Language (NSL) programs are constructed out of
+# Programs written in the <<@glossary nx>> are constructed out of
# objects. This class describes common structural and behavioural
-# features for all NSL objects. It is the root object-class in the
-# NSL object system.
+# features for all <<@glossary nx>> objects. It is the root class in the
+# <<@glossary nx>> object system.
# @class Class
#
-# A {{@glossary class}} defines a family of object types which own a common set of
-# attributes (see {{@class ::nx::Attribute}}) and methods. Classes
-# are organised according to their similarities and differences in
-# classification hierarchies. This object represents the root
-# meta-class in the "Next" object system.
+# A <<@gls class>> defines a family of object implementations and
+# <<@glspl objtype>>, sharing a common set of <<@glspl attribute>>
+# attributes (see <<@class ::nx::Attribute>>) and methods. Classes are
+# organised according to their similarities and differences in
+# classification hierarchies. This object represents the root <<@gls
+# metaclass>> in the <<@glossary nx>> object system.
#
# @superclass ::nx::doc::entities::class::nx::Object
# @class.method {Class alloc}
#
-# Creates a bare object or class which is not
-# fully initialized. {{{alloc}}} is used by {{@class.method "::nx::Class create"}} to
-# request a memory object storage. In subsequent steps,
-# {{{create}}} invokes {{{configure}}} and {{{init}}} to further
-# set up the object. Only in rare situations, you may consider
-# bypassing the overall {{{create}}} mechanism by just allocating
-# uninitialized objects using {{{alloc}}}.
+# Creates a bare object or class which is not fully
+# initialized. '''alloc''' is used by <<@class.method "::nx::Class
+# create">> to request a memory object storage. In subsequent steps,
+# '''create''' invokes '''configure''' and '''init''' to further set
+# up the object. Only in rare situations, you may consider bypassing
+# the overall '''create''' mechanism by just allocating uninitialized
+# objects using '''alloc'''.
#
# @properties interally-called
-# @parameter name The object identifier assigned to the object storage to be allocated.
+# @parameter name The object identifier assigned to the object storage
+# to be allocated.
# @return The name of the allocated, uninitialized object
# @class.method {Class create}
#
# Provides for creating application-level classes and objects. If
-# the method receiver is a meta-class, a class will be
-# created. Otherwise, {{{create}}} yields an object. {{{create}}}
+# the method receiver is a <<@gls metaclass>>, a <<@gls class>> will be
+# created. Otherwise, '''create''' yields an object. '''create'''
# is responsible a multi-phase object creation scheme. This
# creation scheme involves three major steps:
-# {{{
+# '''
# [Object create anObject] (1)
# ---------------. .--------------.
# -------------->|Class->create()|-->|Class->alloc()|
@@ -61,34 +66,33 @@
# | (3) .------.
# .........>|init()|
# `------'
-# }}}
-# (1) A call to {{@class.method "::nx::Class alloc"}} to create a raw,
+# '''
+# (1) A call to <<@class.method "::nx::Class alloc">> to create a raw,
# uninitalized object.
#
# (2) The newly allocated object receives a method call upon
-# {{@class.method "::nx::Object configure"}}. This will establish the
-# object's initial state, by applying object parameter values
+# <<@class.method "::nx::Object configure">>. This will establish the
+# object's initial state, by applying <<@gls objparam>> values
# provided at object creation time and default values defined at
# object definition time.
#
-# (3) Finally, {{{create}}} emits a call to the initialization
-# method {{{init}}} (i.e., the actual "constructor"), if
-# available. An {{{init}}} method can be defined by a class on
-# behalf of its objects, to lay out class-specific initialisation
-# behaviour. Alternatively, each single object may define an
-# {{{init}}} method on its own.
+# (3) Finally, '''create''' emits a call to the initialization method
+# '''init''', if available. An '''init''' method can be defined by a
+# class on behalf of its objects, to lay out class-specific
+# initialisation behaviour. Alternatively, each single object may
+# define an '''init''' method on its own.
#
-# By overloading the method in a meta-class, you can refine or
+# By overloading the method in a <<@gls metaclass>>, you can refine or
# replace this default object creation scheme (e.g., for applying
# application-specific naming schemes).
#
-# For creating an object or a class, you must name {{{create}}}
+# For creating an object or a class, you must name '''create'''
# explicitly, i.e.:
-# {{{
+# '''
# ::nx::Object create anObject
# ::nx::Class create AClass
# ::nx::Class AnotherClass; # This fails: "Method 'AnotherClass' unknown for ::nx::Class."
-# }}}
+# '''
#
# @parameter name The designated identifier on the class or the object to be created.
# @parameter args arguments to be passed down to the object creation
@@ -98,14 +102,14 @@
# @class.method {Class dealloc}
#
# Marks objects for physical deletion in memory. Beware the fact
-# that calling {{{dealloc}}} does not necessarily cause the object
+# that calling '''dealloc''' does not necessarily cause the object
# to be deleted immediately. Depending on the lifecycle of the the
-# object's environment (e.g., the {{{interp}}}, the containing
+# object's environment (e.g., the '''interp''', the containing
# namespace) and on call references down the callstack, the actual
# memory freeing operation may occur time-shifted (that is,
-# later). While {{{dealloc}}} itself cannot be redefined for
-# {{{::nx::Class}}}, you may consider refining it in a subclass or
-# mixin class for customizing the destruction process.
+# later). While '''dealloc''' itself cannot be redefined for
+# '''::nx::Class''', you may consider refining it in a subclass or
+# <<@gls mixincls>> for customizing the destruction process.
#
# @properties interally-called
# @parameter object The name of the object to be scheduled for deletion.
@@ -116,28 +120,28 @@
# scheme for resolving object naming conflicts in the dynamic and
# scripted programming environment of "Next": An object or class is
# created while an object or class with an identical object identifier
-# already exists. The method {{{recreate}}} performs standard object
+# already exists. The method '''recreate''' performs standard object
# initialization, per default, after re-setting the state and
# relationships of the object under recreation.
-# {{{
+# '''
# Object create Bar
# \# ...
# Object create Bar; # calls Object->recreate(::Bar, ...)
-# }}}
-# By refining {{{recreate}}} in an application-level subclass or mixin
+# '''
+# By refining '''recreate''' in an application-level subclass or mixin
# class, you can intercept the recreation process. In the pre-part the
-# refined {{{recreate}}} method, the recreated object has its old
-# state, after calling {{@command ::nx::next}} it is cleaned up.
+# refined '''recreate''' method, the recreated object has its old
+# state, after calling <<@command ::nx::next>> it is cleaned up.
#
# If the name conflict occurs between an existing class and a newly
-# created object (or vice versa), {{{recreate}}} is not
-# performed. Rather, a sequence of {{@class.method "::nx::Object
-# destroy"}} and {{@class.method "::nx::Class create"}} is triggered:
-# {{{
+# created object (or vice versa), '''recreate''' is not
+# performed. Rather, a sequence of <<@class.method "::nx::Object
+# destroy">> and <<@class.method "::nx::Class create">> is triggered:
+# '''
# Object create Bar
# \# ...
# Class create Bar; # calls Bar->destroy() + Class->create(::Bar, ...)
-# }}}
+# '''
#
# @properties interally-called
# @parameter name The name (identifier) of the object under recreation
@@ -161,33 +165,34 @@
#
# This method participates in the object creation process. It is
# automatically invoked after having produced a new object by
-# {{@class.method "::nx::Class create"}}. Upon its invocation, the
-# variable argument vector {{{args}}} contains a list of parameters
+# <<@class.method "::nx::Class create">>. Upon its invocation, the
+# variable argument vector '''args''' contains a list of parameters
# and parameter values passed in from the call site of object
-# creation. They are matched against an object parameter
+# creation. They are matched against an <<@gls objparam>>
# definition. This definition, and so the actual method parameter
# definition of this method, is assembled from configuration values of
-# the classes along the precedence order (see also {{@class.method
-# "::nx::Object objectparameter"}}). The method {{{configure}}}
+# the classes along the precedence order (see also <<@class.method
+# "::nx::Object objectparameter">>). The method '''configure'''
# can be called at arbitrary times to "re-set" an object.
#
# @properties interally-called
-# @parameter args The variable argument vector stores the object parameters and their values
+# @parameter args The variable argument vector stores the object
+# parameters and their values
#
#
#
# @class.method {Object destroy}
#
-# The standard destructor for an object. The method {{@class.method
-# "::nx::Object destroy"}} triggers the physical destruction of
-# the object. The method {{{destroy}}} can be refined by subclasses or
-# mixin classes to add additional (class specific) destruction
-# behavior. Note that in most cases, the class specific {{{destroy}}}
-# methods should call {{@command ::nx::next}} to trigger physical
-# destruction.
-# {{{
+# The standard shutdown handler for any object which, finally,
+# commands the physical destruction of the object. The method
+# '''destroy''' can be refined by subclasses or <<@glspl mixincls>> to
+# add additional (class-specific) shutdown behaviour. Note that, in
+# most cases, the class-specific '''destroy''' methods are expected to
+# call <<@command ::nx::next>> to ascertain the the physical
+# destruction is requested.
+# '''
# nx::Class create Foo {
# :method destroy {} {
# puts "destroying [self]"
@@ -196,19 +201,19 @@
# }
# Foo create f1
# f1 destroy
-# }}}
-# Technical details: The method {{@class.method "::nx::Object destroy"}}
-# delegates the actual destruction to {{@class.method "::nx::Class
-# dealloc"}} which clears the memory object storage. Essentially, the
+# '''
+# Technical details: The method <<@class.method "::nx::Object destroy">>
+# delegates the actual destruction to <<@class.method "::nx::Class
+# dealloc">> which clears the memory object storage. Essentially, the
# behaviour could be scripted as:
-# {{{
+# '''
# Object method destroy {} {
# [:info class] dealloc [self]
# }
-# }}}
-# Note, however, that {{{destroy}}} is protected against
+# '''
+# Note, however, that '''destroy''' is protected against
# application-level redefinition. You must refine it in a subclass
-# or mixin class.
+# or a <<@gls mixincls>>.
# @class.method {Object uplevel}
@@ -217,7 +222,7 @@
# another callstack level (i.e., callstack frame).
#
# @parameter level:optional The starting callstack level (defaults to the
-# value of {{{[current callinglevel]}}})
+# value of '''[current callinglevel]''')
# @parameter script:list The script to be evaluated in the targeted
# callstack level
@@ -227,265 +232,233 @@
# residing at a different callstack level (frame).
#
# @parameter level:optional The starting callstack level (defaults to the
-# value of {{{[current callinglevel]}}})
+# value of '''[current callinglevel]''')
#
# @parameter sourceVar A variable which should be linked to a ...
# @parameter targetVar ... which is a local variable in a method scope
# @see ...
# @class.method {Object attribute}
#
-# This is a helper method which provides a convenient facade to
-# definite attribute slots (with standard settings) on the object or
-# class.
+# This is a helper method which provides a convenient facade to define
+# <<@glspl attribute>> (with standard settings) on the given object
+# or the given class.
# @class.method {Object volatile}
#
# By calling on this method, the object is bound in its lifetime to
-# the one of call site (e.g., the given Tcl proc or method scope):
-# {{{
+# the one of the active call site (e.g., the given <<@acr tcl>> proc or method
+# scope):
+# '''
# proc foo {} {
# info vars; # shows ""
# set x [Object create Bar -volatile]
# info vars; # shows "x Bar"
# }
-# }}}
-# Behind the scenes, {{{volatile}}} registers a C-level variable trace
-# ({{{Tcl_TraceVar()}}}) on the hiddenly created local variable (e.g.,
-# {{{Bar}}}), firing upon unset events and deleting the referenced
-# object ({{{Bar}}}). That is, once the callframe context of {{{foo}}}
-# is left, the local variable {{{Bar}}} is unset and so the bound
-# object is destroyed.
+# '''
+# Behind the scenes, '''volatile''' registers a C-level variable trace
+# ('''Tcl_TraceVar()''') on the hiddenly created local variable (e.g.,
+# '''Bar'''), firing upon unset events and deleting the referenced
+# object ('''Bar'''). That is, once the callframe context of '''foo'''
+# is left, the local variable '''Bar''' is unset and so the bound
+# object destruction is triggered.
# @class.method {Class new}
#
-# A convenience method to create auto-named objects and classes. It is
-# a front-end to {{@class.method "::nx::Class create"}}. For instance:
-# {{{
+# A convenience method to create auto-named objects and <<@glspl
+# class>>. It is a front-end to <<@class.method "::nx::Class
+# create">>. For instance:
+# '''
# set obj [Object new]
# set cls [Class new]
-# }}}
+# '''
#
# This will provide object identifiers of the form
-# e.g. {{{::nsf::__#0}}}. The uniqueness of auto-generated identifiers
-# is guaranteed for the scope of the current {{{interp}}}.
+# e.g. '''::nsf::__#0'''. The uniqueness of auto-generated identifiers
+# is guaranteed for the scope of the current '''interp'''.
#
# @parameter -childof If provided, the new object is created as a child of
# the specified object.
-# @parameter args The variable arguments passed down to {{@class.method
-# "::nx::Class create"}}.
+# @parameter args The variable arguments passed down to <<@class.method
+# "::nx::Class create">>.
# @class.method {Class method}
#
-# Defines a per-class method, similarly to Tcl specifying
-# {{{procs}}}. Optionally assertions may be specified by two
-# additional arguments. Therefore, to specify only post-assertions
-# an empty pre-assertion list must be given. All assertions are a
-# list of ordinary Tcl {{{expr}}} statements. When {{{method}}} is
-# called with an empty argument list and an empty body, the
-# specified method is deleted.
-# {{{
+# Defines a per-class method, similarly to <<@acr tcl>> specifying
+# '''procs'''. Optionally, <<@glspl assert>> may be specified by two
+# additional arguments. Therefore, to specify only post-assertions an
+# empty pre-assertion list must be given. All assertions are a list of
+# ordinary <<@Gls tcl>> '''expr''' statements. When '''method''' is called
+# with an empty argument list and an empty body, the specified method,
+# if existing, is deleted.
+# '''
# Class create AClass {
# :method foo args {;}
# }
#
# AClass create anInstance
# anInstance foo; # invokes "foo"
-# }}}
#
+# AClass method foo {} {}; # deletes "foo"
+# '''
+#
# @parameter name The method name
-# @parameter arguments:list A list specifying non-positional and positional parameters
+# @parameter arguments:list A list specifying non-positional and
+# positional parameters
# @parameter body The script which forms the method body
-# @parameter preAssertion Optional assertions that must hold before the proc executes
-# @parameter postAssertion Optional assertions that must hold after the proc executes
+# @parameter preAssertion Optional assertions that must hold before
+# the proc executes
+# @parameter postAssertion Optional assertions that must hold after
+# the proc executes
# @class.method {Object method}
#
-# Defines a per-object method, similarly to Tcl specifying
-# {{{procs}}}. Optionally assertions may be specified by two
+# Defines a per-object method, similarly to creating <<@tcl tcl>>
+# '''procs'''. Optionally, <<@glspl assert>> may be specified by two
# additional arguments. Therefore, to specify only post-assertions
# an empty pre-assertion list must be given. All assertions are a
-# list of ordinary Tcl {{{expr}}} statements. When {{{method}}} is
+# list of ordinary <<@acr tcl>> '''expr''' statements. When '''method''' is
# called with an empty argument list and an empty body, the
# specified method is deleted.
-# {{{
+# '''
# Object create anObject {
# :method foo args {;}
# }
# anObject foo; # invokes "foo"
-# }}}
#
-# @parameter name The method name
-# @parameter arguments:list A list specifying non-positional and positional parameters
-# @parameter body The script which forms the method body
-# @parameter preAssertion Optional assertions that must hold before the proc executes
-# @parameter postAssertion Optional assertions that must hold after the proc executes
+# anObject method foo {} {}; # deletes "foo"
+# '''
+#
+# @parameter name The method name
+# @parameter arguments:list A list specifying non-positional and
+# positional parameters
+# @parameter body The script which forms the method body
+# @parameter preAssertion Optional assertions that must hold before
+# the proc executes
+# @parameter postAssertion Optional assertions that must hold after
+# the proc executes
# @class.method {Object forward}
#
-# Register a per-object method (similar to a {{{proc}}}) for
-# forward-delegating calls to a callee (target Tcl command, other
-# object). When the forwarder method is called, the actual arguments
-# of the invocation are appended to the specified arguments. In
-# callee an arguments certain substitutions can take place:
+# Register a special-purpose per-object method (similar to a
+# '''proc'''), referred to as a <<@gls forwarder>>, for
+# forward-delegating calls to a callee (a <<@acr tcl>> command, a method owned
+# by another object). When the <<@gls forwarder>> method is called,
+# the actual arguments of the invocation are appended to the specified
+# arguments. Certain manipulations can be applied on the
+# forward-passed argument vector:
#
-# {{{%proc}}} substituted by name of the forwarder method
+# '''%proc''' substituted by name of the forwarder method
#
-# {{{%self}}} substitute by name of the object
+# '''%self''' substitute by name of the object
#
-# {{{%1}}} substitute by first argument of the invocation
+# '''%1''' substitute by first argument of the invocation
#
-# {{{ {%@POS value} }}} substitute the specified value in the
+# ''' {%@POS value} ''' substitute the specified value in the
# argument list on position POS, where POS can be a positive or
# negative integer or end. Positive integers specify the position
# from the begin of the list, while negative integer specify the
# position from the end.
#
-# {{{ {%argclindex LIST} }}} take the nth argument of the specified
+# ''' {%argclindex LIST} ''' take the nth argument of the specified
# list as substitution value, where n is the number of arguments
# from the invocation.
#
-# {{{%%}}} a single percent.
+# '''%%''' a single percent.
#
-# {{{%Tcl-command}}} command to be executed; substituted by result.
+# '''%Tcl-command''' The command to be executed; the result of the
+# command evaluation is substituted for the placeholding statement.
#
-# Additionally each argument can be prefixed by the positional prefix
+# Additionally, each argument can be prefixed by the positional prefix
# %@POS (note the delimiting space at the end) that can be used to
# specify an explicit position. POS can be a positive or negative
# integer or the word end. The positional arguments are evaluated from
# left to right and should be used in ascending order.
#
-# @parameter name The name of the delegating or forward method
-# @parameter -objscope:optional Causes the target to be evaluated in the scope of the object.
-# @parameter -methodprefix Prepends the specified prefix to the second argument of the invocation.
-# @parameter -default Is used for default method names (only in connection
-# with %1)
-#
-# @parameter -earlybinding Look up the function pointer of the called Tcl
-# command at definition time of the forwarder instead of invocation
-# time. This option should only be used for calling C-implemented Tcl
-# commands, no scripted procs
-#
-# @parameter -verbose Print the substituted command to stderr before
-# executing
-
-# @parameter callee
-# @parameter args
-
-# @class.method {Class forward}
-#
-# Register a per-class method (similar to a {{{proc}}}) for
-# forward-delegating calls to a callee (target Tcl command, other
-# object). When the forwarder method is called on an instance of the
-# class, the actual arguments of the invocation are appended to the
-# specified arguments. In callee an arguments certain substitutions
-# can take place:
-#
-# {{{%proc}}} substituted by name of the forwarder method
-#
-# {{{%self}}} substitute by name of the object
-#
-# {{{%1}}} substitute by first argument of the invocation
-#
-# {{{ {%@POS value} }}} substitute the specified value in the
-# argument list on position POS, where POS can be a positive or
-# negative integer or end. Positive integers specify the position
-# from the begin of the list, while negative integer specify the
-# position from the end.
-#
-# {{{ {%argclindex LIST} }}} take the nth argument of the specified
-# list as substitution value, where n is the number of arguments
-# from the invocation.
-#
-# {{{%%}}} a single percent.
-#
-# {{{%Tcl-command}}} command to be executed; substituted by result.
-#
-# Additionally each argument can be prefixed by the positional prefix
-# %@POS (note the delimiting space at the end) that can be used to
-# specify an explicit position. POS can be a positive or negative
-# integer or the word end. The positional arguments are evaluated from
-# left to right and should be used in ascending order.
-#
-# @parameter name The name of the delegating or forward method
-# @parameter -objscope:optional Causes the target to be evaluated in the
-# scope of the object.
+# @parameter name The name of the delegating or forwarder method
+# @parameter -objscope:optional Causes the target to be evaluated in
+# the scope of the object.
# @parameter -methodprefix Prepends the specified prefix to the second
# argument of the invocation.
# @parameter -default Is used for default method names (only in
# connection with %1)
-# @parameter -earlybinding Look up the function pointer of the called
-# Tcl command at definition time of the forwarder instead of
-# invocation time. This option should only be used for calling
-# C-implemented Tcl commands, no scripted procs
+# @parameter -earlybinding Look up the function pointer of the called <<@acr tcl>>
+# command at definition time of the forwarder rather than at invocation
+# time. This option should only be used for calling C-implemented
+# commands, e.g., a <<@Gls cim>>, not scripted ones.
# @parameter -verbose Print the substituted command to stderr before
# executing
# @parameter callee
# @parameter args
+# @class.method {Class forward}
+#
+# @use class.method {Object forward}
+
# @class.method {Object info}
#
# Provides introspection on objects. A variety of introspection
-# options exists. {{{info}}} is implemented as en ensemble
-# object. Hence, the introspection options turn into proper
-# sub-methods.
+# options exists. '''info''' is implemented as an <<@gls
+# ensemble>>. Hence, the introspection options turn into proper
+# submethods.
#
-# @sub-method callable
-# @sub-method has
-# @sub-method filter
-# @sub-method is Binds all introspection facilities offered by
-# {{{::nsf::is}}} to the object, i.e., the object is automatically
-# folded in as the first argument passed to {{{::nsf::is}}}
-# @sub-method mixin
+# @sub-method callable
+# @sub-method has
+# @sub-method filter
+# @sub-method is Binds all introspection facilities offered by
+# '''::nsf::is''' to the object, i.e.,
+# the object is automatically folded in
+# as the first argument passed
+# to '''::nsf::is'''
+# @sub-method mixin
# @class.method {Object "info callable method"}
#
-# Verifies whether there is a method under a given name available
-# for invocation upon the object. In case, the introspective call
-# returns the corresponding method handle. If there is no so named
+# Verifies whether there is a method under a given name available for
+# invocation upon the object. In case, the introspective call returns
+# the corresponding <<@gls method_handle>>. If there is no so-named
# method available, an empty string is returned.
# @class.method {Object "info callable filter"}
#
# Search for a method which is currently registered as a filter (in
# the invocation scope of the given object). If found, the
-# corresponding method handle is returned.
+# corresponding <<@gls method_handle>> is returned.
# @class.method {Object "info children"}
#
# Computes the list of aggregated (or nested) objects. The resulting
-# list reports the fully qualified object names. If a name pattern
-# was specified, all matching child objects are returned. Otherwise,
-# all children are reported.
+# list reports the fully qualified object names. If a <<@gls
+# namepattern>> was specified, all matching child objects are
+# returned. Otherwise, all children are reported.
-
# @class.method {Object "info class"}
#
# Gives the name of the class of the current object.
# @class.method {Object "info filter guard"}
#
-# Returns the guards for filter identified by a filter name
+# Returns the guards for filter identified by a <<@gls filter>> name
# @class.method {Object "info filter methods"}
#
-# Returns a list of methods registered as filters.
+# Returns a list of methods registered as <<@glspl filter>>.
# @class.method {Object "info forward"}
#
-# Provides you with the list of forwarders defined for the given
+# Provides you with the list of <<@glspl forwarder>> defined for the given
# object.
# @class.method {Object "info has mixin"}
#
-# Verifies in a boolean test whether the object has the given class
-# registered as a mixin class.
+# Verifies in a boolean test whether the object has the given <<@gls class>>
+# registered as a <<@gls mixincls>>.
-# @class.method {Object "info has namespace"} Some words on info has type
+# @class.method {Object "info has namespace"}
#
-# Tells you whether the object has a companion, per-object Tcl
+# Tells you whether the object has a companion, per-object <<@acr tcl>>
# namespace. Note that the results do not necessarily correspond to
-# those yielded by {{{[namespace exists /obj/]}}}.
+# those yielded by '''[namespace exists /obj/]'''.
# @class.method {Object "info has type"}
#
@@ -500,12 +473,12 @@
# @class.method {Object "info mixin guard"}
#
-# Retrieves the guards applied to the mixin class idenitified by the
-# mixin class name
+# Retrieves the <<@glspl guard>> applied to the mixin class
+# idenitified by the mixin class name
# @class.method {Object "info mixin classes"}
#
-# The list of per-object mixin classes currently registered for the
+# The list of per-object <<@glspl mixincls>> currently registered for the
# object is returned.
# @class.method {Object "info parent"}
@@ -516,29 +489,31 @@
# @class.method {Object "info precedence"}
#
# Presents to you the list of classes the object is inheriting
-# attributes and methods, ordered according to their precedence.
+# attributes and methods, ordered according to their <<@gls
+# precedence>>.
# @class.method {Object "info slotobjects"}
#
# Assembles the list of slot objects which apply the given
-# object. They are resolved by following the class precedence list
-# upward and coercing the lists of slots provided by these classes.
+# object. They are resolved by following the <<@gls class>> <<@gls
+# precedence>> upward and coercing the lists of slots provided by
+# these <<@glspl class>>.
# @class.method {Object "info vars"}
#
# Yields a list of variable names created and defined on the object.
# @class Slot
#
-# A slot is a meta-object that manages property changes of
+# A <<@gls slot>> is a meta-object that manages property changes of
# objects. A property is either an attribute or a role taken by an
# object in an inter-object relation (e.g., in system slots). The
-# predefined system slots are {{{class}}}, {{{superclass}}},
-# {{{mixin}}}, and {{{filter}}}. These slots appear as methods of
-# {{@class ::nx::Object}} or {{@class ::nx::Class}}. The slots
+# predefined system slots are '''class''', '''superclass''',
+# '''mixin''', and '''filter'''. These slots appear as methods of
+# <<@class ::nx::Object>> or <<@class ::nx::Class>>. The slots
# provide a common getter and setter interface. Every multivalued
-# slot provides e.g. a method {{{add}}} to append a value to the
-# list of values, and a method {{{delete}}} which removes it.
+# slot provides e.g. a method '''add''' to append a value to the
+# list of values, and a method '''delete''' which removes it.
#
# @superclass ::nx::doc::entities::class::nx::Object
@@ -548,7 +523,8 @@
# @class.attribute {Slot name}
#
-# Name of the slot which can be used to access the slot from an object
+# Name of the <<@gls slot>> which can be used to access the <<@gls
+# slot>> data from an object
# @class.attribute {Slot multivalued}
#
@@ -564,21 +540,23 @@
# @class.attribute {Slot type}
#
-# You may specify a type constraint on the value range to managed by the slot
+# You may specify a type constraint on the value range to managed by
+# the <<@gls slot>>
# @class.attribute {ObjectParameterSlot name}
#
-# Name of the slot which can be used to access the slot from an
-# object. It defaults to unqualified name of an instance.
+# Name of the <<@gls slot>> which can be used to access the <<@gls
+# slot>> data of an object. It defaults to unqualified name of an
+# instance.
# @class.attribute {ObjectParameterSlot methodname}
#
# The name of the accessor methods to be registed on behalf of the
-# slot object with its domains can vary from the slot name.
+# <<@gls slot>> object with its domains can vary from the slot name.
# @class.attribute {ObjectParameterSlot domain}
#
-# The domain (object or class) of a slot on which it can be used
+# The domain (object or class) of a <<@gls slot>> on which it can be used
# @class.attribute {ObjectParameterSlot defaultmethods}
#
@@ -587,13 +565,13 @@
# @class.attribute {ObjectParameterSlot manager}
#
-# The manager object of the slot (per default, the slot object takes
-# this role, i.e. {{{[self]}}})
+# The manager object of the <<@gls slot>> (per default, the slot object takes
+# this role, i.e. '''[self]''')
# @class.attribute {ObjectParameterSlot per-object}
#
-# If set to {{{true}}}, the accessor methods are registered with the
-# domain object scope only. It defaults to {{{false}}}.
+# If set to '''true''', the accessor methods are registered with the
+# domain object scope only. It defaults to '''false'''.
# @class.method {Object objectparameter}
@@ -603,104 +581,242 @@
# generell: setter kann hier mit der methode namens "setter"
# verwechselt werden; wir sollten hier die parameter syntax
# anfuehren, die allerdings in zwei varianten kommt:
-#{{{
+#'''
# obj superclass ?value?
# obj superclass add|assign|delete|get value
-#}}}
+#'''
# Das gilt allgemein, nicht nur für die relation-slots, sondern
# für alle incremental slots.
-# **** {{{superclass}}} changes the list
+# **** '''superclass''' changes the list
# of superclasses. When used as a getter, the method returns the
# current superclasses.
#
# @return :list If called as a getter (without arguments),
-# {{{superclass}}} returns the current superclasses of the object
+# '''superclass''' returns the current superclasses of the object
# @class.attribute {Object class}
#
-# Sets or retrieves the class of an object. When {{{class}}} is
+# Sets or retrieves the <<@gls class>> of an object. When '''class''' is
# called without arguments, it returns the current class of the
-# object. An introspective alternative is {{@class.method {Object
-# "info class"}}}
+# object. An introspective alternative is <<@class.method {Object
+# "info class"}>>
#
-# @return If called as a getter (without arguments), {{{class}}}
-# returns the current class of the object
+# @return If called as a getter (without arguments), '''class'''
+# returns the current <<@gls class>> of the object
# @class.attribute {Object mixin}
#
-# As a setter, {{{mixin}}} specifies a list of mixins to set. Every
-# mixin must be an existing class. In getter mode, you can retrieve
-# the list of mixins active for the given object. As for introspecting
-# mixin classes, consider {{@class.method {Object "info mixin classes"}}}
+# As a setter, '''mixin''' specifies a list of <<@glspl mixincls>> to
+# set. Every mixin must be an existing class. In getter mode, you can
+# retrieve the list of <<@glspl mixincls>> active for the given object. As for
+# introspecting <<@glspl mixincls>>, consider <<@class.method {Object "info
+# mixin classes"}>>
#
# @return :list If called as a getter (without arguments),
-# {{{mixin}}} returns the list of current mixin classes registered
+# '''mixin''' returns the list of current <<@glspl mixincls>> registered
# with the object
# @class.attribute {Object filter}
#
-# In its setter mode, {{{filter}}} allows you to register methods as
-# per-object filters. Every filter must be an existing method in the
-# scope of the object. When acting as a getter, you can retrieve the
-# list of filter methods active for the given object. See also
-# {{@class.method {Object "info filter methods"}}}.
+# In its setter mode, '''filter''' allows you to register methods as
+# per-object <<@glspl filter>>. Every <<@gls filter>> must be an
+# existing method in the scope of the object. When acting as a getter,
+# you can retrieve the list of filter methods active for the given
+# object. See also <<@class.method {Object "info filter methods"}>>.
#
# @return :list If called as a getter (without arguments),
-# {{{filter}}} returns the list of current filters
+# '''filter''' returns the list of current filters
# registered with the object
# @class.attribute {Class mixin}
#
-# As a setter, {{{mixin}}} specifies a list of mixins to set for
-# the class. Every mixin must be an existing class. In getter
-# mode, you can retrieve the list of mixins active for the given
-# class.
+# As a setter, '''mixin''' specifies a list of <<@glspl mixincls>> to
+# set for the class. Every <<@gls mixincls>> must be an existing
+# class. In getter mode, you can retrieve the list of <<@glspl
+# mixincls>> active for the given class.
#
-# @return :list If called as a getter (without arguments), {{{mixin}}}
-# returns the list of current mixin classes registered with the class
+# @return :list If called as a getter (without arguments), '''mixin'''
+# returns the list of current <<@glspl mixincls>> registered with the class
# @class.attribute {Class filter}
#
-# In its setter mode, {{{filter}}} allows you to register methods
-# as per-class filters. Every filter must be an existing method
+# In its setter mode, '''filter''' allows you to register methods
+# as per-class <<@glspl filter>>. Every filter must be an existing method
# in the scope of the class. When acting as a getter, you can
-# retrieve the list of filter methods active for the given class.
+# retrieve the list of <<@gls filter>> methods active for the given class.
#
# @return :list If called as a getter (without arguments),
-# {{{filter}}} returns the list of current filters
+# '''filter''' returns the list of current filters
# registered with the class
# @class Attribute
#
-# Attribute slots are used to manage the access, mutation, and
-# querying of instance variables. One defines Attribute slots for
-# objects and classes usually via the helper method {{@class.method
-# "::nx::Object attribute"}} **** TODO STEFAN, kein Link? GEPLANT?
-# MIT 2 GESCHWEIFTEN KLAMMER UM SALARY GIBT ES EINEN LAUFZEITFEHLER???
-# ******** The following example defines a class with three attribute
-# slots. The attribute {salary} has a default of {0}, the attribute
-# {projects} has the empty list as default and is defined as
-# multivalued.
-# {{{
+# Attribute <<@glspl slot>> are used to manage the access, mutation,
+# and querying of instance variables. One defines attribute slots for
+# objects and classes usually via the helper method <<@class.method
+# "::nx::Object attribute">> The following example defines a class
+# with three attribute slots. The attribute '''salary''' has a default
+# of '''0''', the attribute '''projects''' has the empty list as
+# default and is defined as multivalued.
+# '''
# Class create Person {
# :attribute name
# :attribute {salary:integer 0}
# :attribute {projects:multivalued ""} {
# set :incremental true
# }
# }
-# }}}
+# '''
#
# @parameter incremental A boolean value, only useful for multivalued
# slots. When set, one can add/delete incrementally values to the
-# multivalued set (e.g., through an incremental {{{add}}})
-# @parameter valuecmd A Tcl command to be executed whenever the managed
+# multivalued set (e.g., through an incremental '''add''')
+# @parameter valuecmd A <<@acr tcl>> command to be executed whenever the managed
# object variable is read
-# @parameter valuechangedcmd A Tcl command to be executed whenever the
+# @parameter valuechangedcmd A <<@acr tcl>> command to be executed whenever the
# value of the managed object variable changes
# @parameter arg
# @superclass ::nx::doc::entities::class::nx::ObjectParameterSlot
+# @glossary tcl
+#
+# @acronym Tcl
+# @pretty_name Tool Command Language
+
+# @glossary clos
+#
+# @pretty_name Common Lisp Object System
+# @acronym CLOS
+
+# @glossary flavors
+#
+# @pretty_name Flavors
+
+# @glossary nx
+#
+# The Next Scripting Language (Nx) is one of the languages hosted by
+# and implemented on top of the Next Scripting Framework (NSF).
+#
+# @pretty_name Next Scripting Language
+# @acronym Nx
+
+# @glossary objtype
+#
+# The type of an object is given by its signature interface. While <<@acr tcl>>
+# and so NSF object systems are mono-typed (i.e., everything has a
+# string representation to the interpreter), object-types are lately
+# checked and verified (e.g., upon method lookup).
+#
+# @pretty_name Object-type
+# @pretty_plural Object-types
+
+
+# @glossary metaclass
+#
+# A meta-class defines a minimal set of shared state structure and
+# behaviour for a family of classes.
+#
+# @pretty_name Meta-class
+# @pretty_plural Meta-classes
+
+# @glossary attribute
+#
+# An attribute describes a structural feature of a class or an
+# object. An attribute has different runtime representations: An
+# attribute slot acts as a managing object, there are same-named
+# accessor and mutator methods and, finally, object variables carrying
+# the actual attribute data.
+#
+# @pretty_name Attribute
+# @pretty_plural Attributes
+
+# @glossary mixincls
+#
+# A mixin is realised by an otherwise ordinary class which is put in a
+# dedicated mixin relation to another object or class. Hence, we refer
+# to such classes as mixin-classes. If the mixing target is another
+# mixin-class, we refer to the source mixin-class as a transitive
+# mixin-class.
+#
+# @pretty_name Mixin-class
+# @pretty_plural Mixin-classes
+
+# @glossary objparam
+#
+# @pretty_name Object parameter
+# @pretty_plural Object parameters
+
+# @glossary assert
+#
+# Following a Design-by-Contract approach, you may define pre- and
+# post-conditions on per-object and per-class methods.
+#
+# @pretty_name Assertion
+# @pretty_plural Assertions
+
+# @glossary forwarder
+#
+# A forwarder is a method-level delegation mechanism to realise a
+# variety of programming techniques (e.g., signature adapters, method
+# decorators). The forward-owning object (or class) exposes the
+# forwarder as a method (e.g., in its signature interface and through
+# method-level introspection). Delegation targets are not limited to
+# other methods, arbitrary <<@acr tcl>> command statements can be
+# used. Forwarders come with a filtering protocol which allows to
+# manipulate the argument vector processed by the forwarder.
+#
+# @pretty_name Forwarder
+# @pretty_plural Forwarders
+
+# @glossary ensemble
+#
+# An ensemble is an auxiliary object which acts as a single method of
+# another object. The ensemble's per-object methods (the so-called
+# ensemble methods), however, so appear as submethods of this
+# top-level method. This ressembles the ideas of subcommands and
+# namespace ensembles in <<@acr tcl>>. When sending a message to an
+# object, methods are identified as message receivers by name. This
+# name can be simple (i.e., a single <<@acr tcl>> word) or composite
+# (i.e., multiple <<@acr tcl>> words) in the case of
+# submethods. Submethods are identified by their composite method
+# names.
+#
+# @pretty_name Ensemble
+# @pretty_plural Ensembles
+
+# @glossary filter
+#
+# An object filter implementes the idea of a composition filters in NSF.
+#
+# @pretty_name Filter
+# @pretty_plural Filters
+
+# @glossary namepattern
+#
+# @pretty_name Name pattern
+# @pretty_plural Name patterns
+
+# @glossary guard
+#
+# A guard acts as ...
+#
+# @pretty_name Guard
+# @pretty_plural Guards
+
+# @glossary precedence
+#
+# ...
+#
+# @pretty_name Precedence order
+# @pretty_plural Precedence orders
+
+# @glossary slot
+#
+# ...
+#
+# @pretty_name Slot
+# @pretty_plural Slots
+
# @glossary class
#
# A class represents a family of object sharing a minimal common
@@ -716,7 +832,6 @@
# @pretty_name Method handle
# @pretty_plural Method handles
-
# @glossary cim
#
# In Tcl/XOTcl/NSF, methods can either be scripted or implemented as a
@@ -725,10 +840,3 @@
# @acronym CIM
# @pretty_name C-implemented method
# @pretty_plural C-implemented methods
-
-# {{@gls class}}
-# {{@Gls class}}
-# {{@glspl class}}
-# {{@Glspl class}}
-# {{@acr cim}} -> CIM
-# {{@acrpl cim}} -> CIMs
\ No newline at end of file