lout-users
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: defs problem


From: Valeriy E. Ushakov
Subject: Re: defs problem
Date: Fri, 15 Aug 1997 15:20:40 +0400

On Thu, Aug 14, 1997 at 04:35:26PM -0500, David Middleton wrote:

> Consider the following two examples:

[uwe: I have squeezed whitespace and don't quote lout output]

> i)  A lout file:
>
> @SysInclude {doc}
> @Doc @Text @Begin
> @Display {test}
> @Display {test}
> @End @Text

> ii) A mydefs file:
> 
> import @DocumentLayout
> def @Title right x { @Display x }
> 
> and a lout file:
>
> @SysInclude {doc}
> @Doc @Text @Begin
> @Title {test}
> @Title {test}
> @End @Text

> Why the difference?

A good question for a FAQ list it seems.

The trap is that @Display is a macro.

    macro @D { @DP @G @DispPlace | @DP // @Disp }
    macro @Display { @D }        # just a verbose notation

Now consider the @D.  It packs together a textually incomplete
invocation of sending symbol @Disp and a target symbol for it --
@DispPlace.  Consider what happens when @D { test } is processed.

    @D { test }

=>  @DP @G @DispPlace | @DP // @Disp { test }  # @Disp invocation is
                                               # complete now

    # Now let's rewrite it a bit and expand gap macros

=>  //@DisplayGap       # @DP: vertical space before the display
    |@DefaultIndent     # @G:  Indent the display horizontally (0.5rt)
                        #      i.e. center by default
        @DispPlace      # Here the display will appear
    |                   # not shure, some @Null protection perhaps
    //DisplayGap        # @DP: vertical space after the display
    //                  # Eat @Null (after @Disp is sent to its target)
    @Disp {test}        # Send its argument to @DispPlace


    # After galley is sent to its target

=>  //@DisplayGap   # @DP
    |@DefaultIndent @DispPlace | # @DispPlace is now filled with actual display
    //@DisplayGap   # @DP


Since @D is a macro, @DP (vertical gap before and after the display)
appears as if it was typed in the body text.  Thus two invocation of
@Display actually results in twice @DisplayGap *VERTICAL* gap between
display matters

When you package @D into a definition, the @DP appears in the body
of the definition and only affects its vertical size, not the flow of
the body text.  So when you put 

    @Title { test }
    @Title { test }

the @DP contributes to the height of each object created by @Title.
But the two invocations of @Title are separated by implicit &1s
*HORIZONTAL* concatenation (the number can vary depending upon what
spacing mode it happens to be and amount of literal whitespace between
the two invocations).

I won't get into why @Display is actually written that way, but
there're very strong reasons why it is.

> Another query:  when I put multiple definitions in the same file
> why is it necessary to put an "import @DocumentLayout" line before each.
> For example, lout complains about
> 
> import @DocumentLayout
> def @Title right x { @Display x }
> def @SubTitle right x { @Display x }
> 
> but accepts
> 
> import @DocumentLayout
> def @Title right x { @Display x }
> import @DocumentLayout
> def @SubTitle right x { @Display x }

Because import affects the set of names visible in the body of the
definition, it's not a file scope directive.  Lout has no file scope
directives, if you open something - you have to close it. The only
exception is the @Use which is just an @Open that stays open till the
end of the input (not the end of file).  See the section on ``Nested
definitions, body parameters, extend, import, and export'' in the
expert's guide that discuss scoping rules.

The syntax (as accepted by the parser) is

  definition_or_macro ::=
    [{ import_spec | extend_spec }] [export_spec] {def_spec | macro_spec}

`export' specifies a list of nested definitions whose names will be
visible in the body parameter and/or can be `import'ed.

`import' imports the `export' list of specified definition into the
scope of the body of the current definition.

`extend' has the same effect as if the current definition was written
as additional nested definition in the body of the specified
definition after all nested definitions that are already there, either
written textually, or inserted through `extend'.  The complete scope
in effect in the body of the specified symbol is imported and the
scope of the body of the specified definition is extended with the
named of the current definition.

For macros only `extend' makes sense as MACRO IS A LIST OF TOKENS,
it's purely lexical device, it's not parsed and should not be
syntactically legal at the time it's defined.  The balanced curlies is
the only requirement (see @D above, where @Disp is part of the macro
and its right argument is not).

`export' makes no sense for macros as macros doesn't have any nested
definitions.

Macro does not constitute a scope.  `import' affects the scope of the
definition body (and macro has no body whose scope to extend) and so
makes no sense for macros as well.

But `extend' affects another scope as well, the scope being extended -
and it's perfectly ok to extend it with a new macro.

Hope it helps.


PS: Jeff, as I read through z05.c (parser), I can see that for a
macro the `export' list is ignored with a warning, but for `import' no
warning is issued.  Am I missing something here?

SY, Uwe
-- 
address@hidden                         |       Zu Grunde kommen
http://www.ptc.spbu.ru/~uwe/            |       Ist zu Grunde gehen


reply via email to

[Prev in Thread] Current Thread [Next in Thread]