PreviousUpNext

15.4.833  src/lib/prettyprint/big/src/core-prettyprinter-types-g.pkg

## core-prettyprinter-types-g.pkg
#
# Define the core datastructures used by
#
#     src/lib/prettyprint/big/src/core-prettyprinter-g.pkg
#
# and related packages.  We need to externalize these so
# that we can reduce clutter in core-prettyprinter-g.pkg by
# moving debug stuff etc to support packages.

# Compiled by:
#     src/lib/prettyprint/big/prettyprinter.lib


stipulate
herein

    # This generic is invoked (only) from
    #
    #     src/lib/prettyprint/big/src/core-prettyprinter-g.pkg
    #
    generic package  core_prettyprinter_types_g    (
        #            ==========================
        #
        package out:    Prettyprint_Output_Stream;                                      # Prettyprint_Output_Stream                                             is from   src/lib/prettyprint/big/src/out/prettyprint-output-stream.api
    )
    : (weak)    Core_Prettyprinter_Types                                                # Core_Prettyprinter_Types                                              is from   src/lib/prettyprint/big/src/core-prettyprinter-types.api
    {
        package out = out;

        Left_Margin_Is                                                                  # How should we compute the left margin for a box?
          = BOX_RELATIVE        { blanks: Int, tab_to: Int, tabstops_are_every: Int }   # Indent left margin relative to left margin of containing box.
          | CURSOR_RELATIVE     { blanks: Int, tab_to: Int, tabstops_are_every: Int }   # Set left margin by tabbing from cursor, where tabstops are every 'Int' chars.
          ;

        Phase1_Token
            #
            = NEWLINE
            | BOX       Box
            | TAB     { blanks:                         Int,
                        tab_to:                         Int,
                        tabstops_are_every:             Int
                      }

            | INDENT    Int                                                             # Change left margin for duration of box. Int == i:  if (i != 0)   box.left_margin += i;
                                                                                        #                                                    else          box.left_margin = original_left_margin_for_box;
                                                                                        #                                                    fi;
            | BREAK     Break

            | BLANKS    Int
                                                                                        # "LIT" == "LITERAL (text)" -- text printed exactly as presented, without interpretation.
            | LIT       String                                                          # Raw text.  This includes traitful_text.  The width and texttraits information is taken care of when they are inserted into output stream.
            | ENDLIT    String                                                          # A special hack so that (e.g.) semicolons can appear at the end of a preceding box instead of getting a line of their own, which usually we don't want.

            | PUSH_TT   out::Texttraits
            | POP_TT
            | CONTROL  (out::Prettyprint_Output_Stream -> Void)                         # Device control operation. This provides an escape for ejecting a page or selecting a pen or any other unanticipated stuff.





        withtype
        Break =   { wrap:       Ref Bool,                                               # This controls whether we take the 'ifwrap' or 'ifnotwrap' action.
                    #
                    ifnotwrap:  { blanks:               Int,                            # Start by printing this many blanks.
                                  tabstops_are_every:   Int,                            # 0 == nop, n > 0 means tabs are set every n columns.
                                  tab_to:               Int                             # Print blanks until  (column % tabstops_are_every) == tab_to.  This may result in zero blanks printing.
                                },      
                    ifwrap:     { blanks:               Int,                            # Start by printing this many blanks.
                                  tabstops_are_every:   Int,                            # 0 == nop, n > 0 means tabs are set every n columns.
                                  tab_to:               Int                             # Print blanks until  (column % tabstops_are_every) == tab_to.  This may result in zero blanks printing.
                                }
                  }

        also
        Wrap_Policy    = { name:        String,
                          #
                          code: { target_width:         Int,
                                  box_contents:         List Phase1_Token
                                }
                                ->
                                { actual_box_width:     Int,
                                  is_multiline:         Bool
                                }
                        }

        also
        Box = { left_margin_is:         Left_Margin_Is,                                 # The left margin for the box is computed by adding an int to either the cursor or the previous left margin.
                target_width:           Int,                                            # We try to fit box contents into this width. We can break only where allowed (possibly nowhere), so we cannot guarantee success.
                actual_width:           Ref Int,                                        # Length of contents if newline free, else length of first line.
                #
                id:                     Int,                                            # Unique id number per box.  Only used for debugging/display.
                rulename:               Ref(String),                                    # Name of rule generating box, set via   pp.rulename "T1"   defaulting to "". Used only for debugging/display.
                #
                is_multiline:           Ref Bool,                                       # TRUE iff there's a NEWLINE somewhere inside.
                contents:               Ref List Phase1_Token,                          # This is empty until box is closed, after that it == reverse (*reversed_contents).
                reversed_contents:      Ref List Phase1_Token,                          # We accumulate tokens in this while constructing box, by successively prepending them.
                #
                wrap_policy:            Wrap_Policy
              };

        Prettyprinter_Configuration_Args                                                # Futureproofing -- args which code clients can pass to us to customize the prettyprinter.
          #                                                                             # We can add more cases here in future as needed, without breaking backward compatibility.
          = DEFAULT_TARGET_BOX_WIDTH    Int
          | DEFAULT_LEFT_MARGIN_IS      Left_Margin_Is
          | DEFAULT_WRAP_POLICY         Wrap_Policy
          | TABSTOPS_ARE_EVERY          Int                                             # Usually 4.
          ;

        Prettyprinter
          =
          {
            output_stream:              out::Prettyprint_Output_Stream,                 # Where to send formatted output.
            output_stream_is_closed:    Ref( Bool ),                                    # TRUE iff the stream is closed. 

            box:                        Ref Box,
            nested_boxes:               Ref (List(Box)),
            box_nesting:                Ref Int,                                        # Current depth of 'nested_boxes'. Used only to catch infinite loops.

            next_box_id:                Ref Int,

            texttraits_stack:           Ref( List(out::Texttraits) )
        };


        package b {
            #
            Phase2_Token                                                                # Same as Phase1_Token except without BOX, TAB or BREAK.
                #
                = NEWLINE
                | BLANKS        Int
                | LIT           String
                | ENDLIT        String
                | PUSH_TT       out::Texttraits
                | POP_TT
                | CONTROL      (out::Prettyprint_Output_Stream -> Void)
                ;
        };

        package c {
            #
            Phase3_Token                                                                # Same as Phase2_Token except without ENDLIT.
                #
                = NEWLINE
                | BLANKS        Int
                | LIT           String
                | PUSH_TT       out::Texttraits
                | POP_TT
                | CONTROL      (out::Prettyprint_Output_Stream -> Void)
                ;
        };

        package d {
            #
            Phase4_Token                                                                # Same as Phase3_Token except without NEWLINE.
                #
                = BLANKS        Int
                | LIT           String
                | PUSH_TT       out::Texttraits
                | POP_TT
                | CONTROL      (out::Prettyprint_Output_Stream -> Void)
                ;
        };
    };
end;

## COPYRIGHT (c) 2005 John Reppy (http://www.cs.uchicago.edu/~jhr)
## All rights reserved.
## Subsequent changes by Jeff Prothero Copyright (c) 2010-2015,
## released per terms of SMLNJ-COPYRIGHT.


Comments and suggestions to: bugs@mythryl.org

PreviousUpNext