<?xml version="1.0" encoding="UTF-8"?>
<Worksheet><Version major="6" minor="1"/><View-Properties><Zoom percentage="100"/></View-Properties><Styles><Layout alignment="centred" firstindent="0.0" leftmargin="0.0" linebreak="space" linespacing="0.0" name="Author" rightmargin="0.0" spaceabove="8.0" spacebelow="8.0"/><Layout alignment="left" firstindent="0.0" leftmargin="0.0" linebreak="space" linespacing="0.0" name="Heading 1" rightmargin="0.0" spaceabove="8.0" spacebelow="4.0"/><Layout alignment="left" firstindent="0.0" leftmargin="0.0" linebreak="space" linespacing="0.0" name="Normal" rightmargin="0.0" spaceabove="0.0" spacebelow="0.0"/><Layout alignment="centred" firstindent="0.0" leftmargin="0.0" linebreak="space" linespacing="0.0" name="Title" rightmargin="0.0" spaceabove="12.0" spacebelow="12.0"/><Layout alignment="left" bullet="indent" firstindent="0.0" leftmargin="0.0" linebreak="space" linespacing="0.0" name="List Item" rightmargin="0.0" spaceabove="3.0" spacebelow="3.0"/><Font background="[0,0,0]" bold="false" executable="false" family="Times New Roman" foreground="[0,0,0]" italic="false" name="List Item" readonly="false" size="12" underline="false"/><Font background="[0,0,0]" bold="true" executable="false" family="Times New Roman" foreground="[0,0,0]" italic="false" name="Heading 1" readonly="false" size="18" underline="false"/><Font background="[0,0,0]" italic="true" name="_cstyle286"/><Font background="[0,0,0]" bold="true" family="Monospaced" foreground="[255,0,0]" name="_cstyle285"/><Font background="[0,0,0]" bold="true" executable="true" family="Monospaced" foreground="[255,0,0]" name="Maple Input"/><Font background="[0,0,0]" bold="true" family="Monospaced" foreground="[255,0,0]" name="_cstyle284"/><Font background="[0,0,0]" bold="true" family="Monospaced" foreground="[255,0,0]" name="_cstyle283"/><Font background="[0,0,0]" bold="true" family="Monospaced" foreground="[255,0,0]" name="_cstyle282"/><Font background="[0,0,0]" family="Times New Roman" name="Page Number" underline="false"/><Font background="[0,0,0]" bold="true" family="Monospaced" foreground="[255,0,0]" name="_cstyle281"/><Font background="[0,0,0]" bold="true" family="Monospaced" foreground="[255,0,0]" name="_cstyle280"/><Font background="[0,0,0]" bold="false" executable="false" family="Times New Roman" foreground="[0,0,0]" italic="false" name="Normal" readonly="false" size="12" underline="false"/><Font background="[0,0,0]" bold="true" family="Monospaced" foreground="[255,0,0]" name="_cstyle279"/><Font background="[0,0,0]" bold="true" family="Monospaced" foreground="[255,0,0]" name="_cstyle278"/><Font background="[0,0,0]" bold="true" family="Monospaced" foreground="[255,0,0]" name="_cstyle277"/><Font background="[0,0,0]" bold="true" name="_cstyle276"/><Font background="[0,0,0]" bold="true" family="Monospaced" foreground="[255,0,0]" name="_cstyle275"/><Font background="[0,0,0]" bold="true" family="Monospaced" foreground="[255,0,0]" name="_cstyle274"/><Font background="[0,0,0]" bold="true" family="Monospaced" foreground="[255,0,0]" name="_cstyle273"/><Font background="[0,0,0]" bold="true" family="Monospaced" foreground="[255,0,0]" name="_cstyle272"/><Font background="[0,0,0]" bold="true" family="Monospaced" foreground="[255,0,0]" name="_cstyle271"/><Font background="[0,0,0]" bold="true" family="Monospaced" foreground="[255,0,0]" name="_cstyle270"/><Font background="[0,0,0]" bold="false" executable="false" family="Times New Roman" foreground="[0,0,0]" italic="false" name="Author" readonly="false" size="12" underline="false"/><Font background="[0,0,0]" bold="true" executable="false" family="Monospaced" foreground="[0,0,0]" name="_cstyle21"/><Font background="[0,0,0]" bold="true" family="Monospaced" foreground="[255,0,0]" name="_cstyle269"/><Font background="[0,0,0]" bold="true" family="Monospaced" foreground="[255,0,0]" name="_cstyle268"/><Font background="[0,0,0]" bold="true" family="Monospaced" foreground="[255,0,0]" name="_cstyle267"/><Font background="[0,0,0]" bold="true" family="Monospaced" foreground="[255,0,0]" name="_cstyle266"/><Font background="[0,0,0]" bold="true" family="Monospaced" foreground="[255,0,0]" name="_cstyle265"/><Font background="[0,0,0]" bold="true" family="Monospaced" foreground="[255,0,0]" name="_cstyle264"/><Font background="[0,0,0]" bold="true" family="Monospaced" foreground="[255,0,0]" name="_cstyle263"/><Font background="[0,0,0]" bold="true" family="Monospaced" foreground="[255,0,0]" name="_cstyle262"/><Font background="[0,0,0]" bold="true" family="Monospaced" foreground="[255,0,0]" name="_cstyle261"/><Font background="[0,0,0]" bold="true" family="Monospaced" foreground="[255,0,0]" name="_cstyle260"/><Font background="[0,0,0]" bold="true" family="Monospaced" foreground="[255,0,0]" name="_cstyle259"/><Font background="[0,0,0]" bold="true" family="Monospaced" foreground="[255,0,0]" name="_cstyle258"/><Font background="[0,0,0]" bold="true" family="Monospaced" foreground="[255,0,0]" name="_cstyle257"/><Font background="[0,0,0]" bold="true" family="Monospaced" foreground="[255,0,0]" name="_cstyle256"/><Font background="[0,0,0]" bold="true" executable="false" family="Times New Roman" foreground="[0,0,0]" italic="false" name="Title" readonly="false" size="18" underline="true"/></Styles><Page-Numbers enabled="false" first-number="1" first-numbered-page="1" horizontal-location="right" style="Page Number" vertical-location="bottom"/><Group><Input><Text-field layout="Title" style="Title">The Warnings Package</Text-field><Text-field layout="Author" style="Author">Douglas Wilhelm Harder, July 29th, 2002</Text-field></Input></Group><Group><Input><Text-field layout="Normal" prompt="&gt; " style="Maple Input"><Font italic="false" size="12" underline="false">restart;</Font></Text-field></Input></Group><Group><Input><Text-field layout="Normal" style="Normal">Students new to <Font bold="false" family="Times New Roman" foreground="[0,0,0]" size="12" style="_cstyle286" underline="false">Maple</Font> often make mistakes such as:</Text-field></Input></Group><Group><Input><Text-field layout="List Item" style="List Item">1.  Using equals instead of assignment, e.g., <Font italic="false" size="12" style="_cstyle256" underline="false">x = 3;</Font> instead of <Font italic="false" size="12" style="_cstyle257" underline="false">x := 3;</Font>.
2.  Using <Font italic="false" size="12" style="_cstyle258" underline="false">pi</Font> and <Font italic="false" size="12" style="_cstyle259" underline="false">i</Font> instead of <Font italic="false" size="12" style="_cstyle260" underline="false">Pi</Font> and <Font italic="false" size="12" style="_cstyle261" underline="false">I</Font>, respectively.
3.  Using remember table assignment instead of operator assignment, e.g., <Font italic="false" size="12" style="_cstyle262" underline="false">f(x) := x^2;</Font> instead of <Font italic="false" size="12" style="_cstyle263" underline="false">f := x -&gt; x^2;</Font>
4.  Forgetting multiplication signs which do not cause errors, e.g., <Font italic="false" size="12" style="_cstyle264" underline="false">x(x - 1)(x + 1)</Font> instead of <Font italic="false" size="12" style="_cstyle265" underline="false">x*(x - 1)*(x + 1)</Font>.
5.  Using short cuts in entering functions, e.g., <Font italic="false" size="12" style="_cstyle266" underline="false">sinx</Font> instead of <Font italic="false" size="12" style="_cstyle267" underline="false">sin(x)</Font>.
6.  Using matrix and vector instead of Matrix and Vector.</Text-field></Input></Group><Group><Input><Text-field layout="Normal" style="Normal">These mistakes can be difficult to find.  The <Font italic="false" size="12" style="_cstyle268" underline="false">Warnings</Font> package gives feedback to the user immediately after the expression is evaluated.  After saving this package to a library or executing this worksheet, the user can enter:</Text-field></Input></Group><Group><Input><Text-field layout="Normal" style="_cstyle21"><Font italic="false" size="12" underline="false">&gt; Warnings:-StartWarnings();</Font></Text-field></Input></Group><Group><Input><Text-field layout="Normal" style="Normal">Then, when something suspicious arises, a Maplet appears with the warning.  The first text box on the Maplet gives what the expression evaluated to, and the second gives a possible correction.  Each type of correction can be turned off by clicking the check box at the bottom of the Maplet or by using the <Font italic="false" size="12" style="_cstyle269" underline="false">Understood</Font> export of the <Font italic="false" size="12" style="_cstyle270" underline="false">Warnings</Font> package.  <Font italic="false" size="12" style="_cstyle280" underline="false">StopWarnings</Font> turns the warnings off and <Font italic="false" size="12" style="_cstyle281" underline="false">ResetWarnings</Font> turns all warnings back on.

For efficiency purposes, if the output is a 2D or 3D plot, the evaluated object is not inspected.

When the user presses <Font family="Times New Roman" foreground="[0,0,0]" italic="false" size="12" style="_cstyle276" underline="false">Enter</Font>, the evaluated result is inspected for problems like those listed above.  While it is possible to make changes to the evaluation, it is probably better to alert the user to the problem and have them go back and manually check it.  Otherwise, they will continue to use this feature instead of learning the correct syntax.

The package is aware of all the errors listed above by using the <Font italic="false" size="12" style="_cstyle271" underline="false">AddWarning</Font> export of the package.  The package can be extended using the same routine.  <Font italic="false" size="12" style="_cstyle277" underline="false">AddWarning</Font> takes two arguments, the first is a symbol which must be unique, and the second is a procedure which takes as input one argument which is a list of the result of the user's evaluation.  The output must be an expression sequence of two strings if a problem was found or <Font italic="false" size="12" style="_cstyle282" underline="false">false</Font> otherwise.  For example, the following routine returns a warning if the user uses <Font italic="false" size="12" style="_cstyle272" underline="false">f</Font> instead of <Font italic="false" size="12" style="_cstyle273" underline="false">F</Font>:</Text-field></Input></Group><Group><Input><Text-field layout="Normal" style="_cstyle21"><Font italic="false" size="12" underline="false">Warnings[AddWarning](
  useF,
  proc(input)
    if has( input, 'f' ) then
      "You used the varible f.  You should use F:",
      sprintf( "%q;", op( subs( 'f' = 'F', [args] ) ) );
    else
      'false';
    end if;
  end proc
);</Font></Text-field></Input></Group><Group><Input><Text-field layout="Normal" style="Normal">This routine also takes a few additional options:
You may select a non-default title using the <Font italic="false" size="12" style="_cstyle274" underline="false">title = "...."</Font> option.
A check is made to ensure you do not add a warning with the same unique identifier as one already in the database.  You can turn this check off by explicitly giving the option <Font italic="false" size="12" style="_cstyle275" underline="false">check = false</Font>.</Text-field></Input></Group><Group><Input><Text-field layout="Normal" style="Normal">Note, since warnings are suppose to help the student, if the procedure included with <Font italic="false" size="12" style="_cstyle283" underline="false">AddWarning</Font> ever generates an error or invalid output, that problem is silently ignored.  The student is having enough problems as it is without having to deal with problems caused by the author.  In order to see these errors, you can use the option <Font italic="false" size="12" style="_cstyle285" underline="false">report_errors = true</Font> when you call <Font italic="false" size="12" style="_cstyle284" underline="false">StartWarnings</Font>.</Text-field></Input></Group><Group><Input><Text-field layout="Normal" style="Normal">The exports <Font italic="false" size="12" style="_cstyle278" underline="false">UserNames</Font> and <Font italic="false" size="12" style="_cstyle279" underline="false">UserFunctions</Font> return a set of all non-library names and function names which have been used up until that point.</Text-field></Input></Group><Section><Title><Text-field layout="Heading 1" style="Heading 1">Warnings Source Code</Text-field></Title><Group><Input><Text-field layout="Normal" prompt="&gt; " style="Maple Input"><Font italic="false" size="12" underline="false">Warnings := module()
  option `Copyright (c) 2002 by Douglas Wilhelm Harder.  All rights reserved.`;

  export AddWarning, StartWarnings, StopWarnings, ResetWarnings,
    Understood, UserNames, UserFunctions;

  local
    isWarning::truefalse,
    reportErrors::truefalse,
    userNameSet::set(name),
    userFunctionSet::set(name),
    tmpEval,

    fixTab::table,
    titleTab::table,
    warningTab::table,

    warning::procedure,

    # Process Option Default Tables
    AddWarningDefaults::table,
    StartWarningsDefaults::table;

  isWarning := 'false';
  reportErrors := 'false';
  userNameSet := {};
  userFunctionSet := {};

  AddWarningDefaults := table( [
    OptionParms = table( [
      'title' = ["Warning", {'string', 'symbol'}],
      'check' = ['true', 'truefalse']
    ] ), PositionalParms = table()
  ] );

  AddWarning := proc( key::symbol, fix::procedure )
    local others, Options;

    others := [ProcessOptions( 2, [args], AddWarningDefaults, Options )];

    if others &lt;&gt; [] then
      error "unexpected option(s): %0", op( others );
    end if;

    # Normally, do not allow the user to use a key already used by
    # another warning.  This can be overridden by the use of the
    # option 'check' = 'false'.  'Check' is 'true' by default.

    if Options['check'] and assigned( warningTab[key] ) then
      error "the key %1 is already assigned", key;
    end if;

    # Check the routine for two simple cases which are bound
    # to come up.

    try
      fix([]);
    catch:
      error "the 2nd argument fails with NULL user input";
    end try;

    try
      fix([1, 2]);
    catch:
      error "the 2nd argument fails with an expression sequence";
    end try;

    # Assign to the tables

    warningTab[key] := 'true';
    fixTab[key] := fix;
    titleTab[key] := sprintf( "%s (%a)", convert( Options['title'], 'string' ), key );

    NULL;
  end proc;

  Understood := proc()
    local i, unknowns;

    # All warning keywords are symbols, and this takes no other
    # options

    if not type( [args], 'list'('symbol') ) then
      error "unexpected option(s): %0",
        seq( `if`( i::'symbol', NULL, i ), i = [args] );
    end if;

    # For each symbol, check if it's a valid warning.
    # If so, no longer issue any related warnings.
    # At the end, any invalid warnings are returned as
    # an error.  Note, this is quadradic is space if and
    # only if the user makes an error. :)

    unknowns := NULL;

    for i in [args] do
      if assigned( warningTab[i] ) then
        warningTab[i] := 'false';
      else
        unknowns := unknowns, i;
      end if;
    end do;

    if unknowns = NULL then
      NULL;
    else
      error "unknown warning(s): %0", unknowns;
    end if;
  end proc;

  StartWarningsDefaults := table( [
    OptionParms = table( [
      report_errors = [false, truefalse]
    ] ), PositionalParms = table()
  ] );

  StartWarnings := proc()
    local others, Options;

    others := [ProcessOptions( 0, [args], StartWarningsDefaults, Options )];

    if others &lt;&gt; [] then
      error "unexpected option(s): %0", op( others );
    end if;

    # The user can indicate that errors in the warning
    # procedures be reported.

    reportErrors := Options['report_errors'];

    # If warnings are already turned on, do nothing.
    # Save any old evaluator.

    if not isWarning then
      tmpEval := kernelopts( Evaluator );

      Maplets:-Tools:-StartEngine();

      if tmpEval = NULL then
        tmpEval := proc() args end proc;
      end if;

      kernelopts( Evaluator = warning@tmpEval );

      isWarning := 'true';
    end if;

    NULL;
  end proc;

  StopWarnings := proc()
    # If warnings are already off, do nothing

    if iswarning then
      kernelopts( Evaluator = eval( tmpEval, 1 ) );
      isWarning := 'false';
    end if;

    NULL;
  end proc;

  ResetWarnings := proc()
    local i;

    # Reset so that warnings are given for all cases

    for i in {indices( warningTab )} do
      warningTab[op( i )] := 'true';
    end do;

    NULL; 
  end proc;

  UserNames := proc()
    userNameSet;
  end proc;

  UserFunctions := proc()
    userFunctionSet;
  end proc;

  warning := proc()
    local i, maplet, result, fix, largs, problem_found;

    largs := [args];
    problem_found := 'false';

    # Do not check plots (for now)

    if type( largs, ['specfunc'('anything', {'PLOT', 'PLOT3D'} )] ) then
      return args;
    end if;

    for i in {indices( warningTab )} do
      if warningTab[op( i )] then
        # Try calling the routine fixTab[op( i )].
        # If an error occurs, if such errors are to be reported
        # (reportErrors = true) then issue an error, otherwise
        # silently ignore the problem (you don't want to annoy
        # students with errors caused by the programmer.)

        try
          fix := fixTab[op( i )]( largs );
        catch:
          if reportErrors = 'true' then
            error "error from warning `%1`: %2",
              op( i ),
              StringTools:-FormatMessage( lastexception[2..-1] );
          else
            next;
          end if;
        end try;

        if fix = 'false' then
          next;
        elif not type( [fix], ['string', 'string'] ) then
          error "warning `%1` did not return `false` or a pair of strings: %2",
            op( i ), [fix];
        end if;

        problem_found := 'true';

        use Maplets:-Elements in
          maplet := Maplet(
            'onstartup' = "A0",

            Action( 'reference' = "A0", RunWindow( 'window' = "W1" ) ),

            Window( 'reference' = "W1",
              'title' = titleTab[op( i )],
              'layout' = "BL1"
            ),

            BoxLayout( 'reference' = "BL1",
              BoxColumn(
                BoxCell( 'value' = "L1" ),
                BoxCell( 'value' = "TB1" ),
                BoxCell( 'value' = "L2" ),
                BoxCell( 'value' = "TB2" ),
                BoxCell( 'value' = "ChB" ),
                BoxCell( 'value' = "B" )
              ) 
            ),

            Label( 'reference' = "L1", 'caption' = "The expression you entered evaluated to:" ),
            TextBox( 'reference' = "TB1", 'value' = sprintf( "%q;", args ) ),
            Label( 'reference' = "L2", 'caption' = fix[1] ),
            TextBox( 'reference' = "TB2", 'value' = fix[2] ),
            CheckBox( 'reference' = "ChB", 'value' = 'false',
              'caption' = "Do not show this warning again."
            ),
            Button( 'reference' = "B", 'caption' = "OK", 'onclick' = "A1" ),

            Action( 'reference' = "A1",
              Shutdown( '`return`' = "R1" )
            ),

            Return( 'reference' = "R1", ReturnItem( 'item' = "ChB" ) )
          );
        end use;

        result := Maplets:-Display( maplet );

        # If the user clicked on 'Do not show this warning again.'
        # then turn that warning off.

        if result = ["true"] then
          warningTab[op( i )] := 'false';
        end if;
      end if;
    end do;

    # Only add new names or functions to the sets if
    # no problems were found.

    if not problem_found then
      userNameSet := userNameSet union remove(
        'type',
        indets( largs, 'name' ),
        'stdlib'
      );
      userFunctionSet := userFunctionSet union remove(
        'type',
        map2( 'op', 0, indets( largs, 'typefunc'('anything', 'name') ) ),
        'stdlib'
      );
    end if;

    args;
  end proc;
end module:</Font></Text-field></Input></Group></Section><Group><Input><Text-field layout="Normal" prompt="&gt; " style="Maple Input"><Font italic="false" size="12" underline="false">with(Warnings);</Font></Text-field></Input></Group><Section><Title><Text-field layout="Heading 1" style="Heading 1">p = x^2 + 2*x + 3</Text-field></Title><Group><Input><Text-field layout="Normal" prompt="&gt; " style="Maple Input"><Font italic="false" size="12" underline="false">AddWarning(
  'assignment',
  proc(input)
    local n, i, format;

    if type( input, ['name' = 'anything'] ) then
      "Perhaps you meant to use assignment:",
      sprintf( "%a := %q;", op( [1, 1], input ), op( [1, 2], input ) );
    else
      false;
    end if;
  end proc
):</Font></Text-field></Input></Group></Section><Section><Title><Text-field layout="Heading 1" style="Heading 1">f(x) = x^2 + 3;</Text-field></Title><Group><Input><Text-field layout="Normal" prompt="&gt; " style="Maple Input"><Font italic="false" size="12" underline="false">AddWarning(
  function_assignment,
  proc(input)
    local n, i, format;

    if type( input, ['function'('name') = 'anything'] ) then
      n := nops( lhs( input[1] ) );

      if n = 0 then
        format := "%a := () -&gt; %a";
      else
        format := cat( "%a := (%a", seq( ", %a", i = 1..n - 1 ), ") -&gt; %a;" );
      end if;

      "Perhaps you meant operator assignment:",
      sprintf( format, op([1,1,0], input), op([1,1,1..-1], input), op([1,2], input) );
    else
      false;
    end if;
  end proc
):</Font></Text-field></Input></Group></Section><Section><Title><Text-field layout="Heading 1" style="Heading 1">x (x + 3)</Text-field></Title><Group><Input><Text-field layout="Normal" prompt="&gt; " style="Maple Input"><Font italic="false" size="12" underline="false">AddWarning(
  multiplication,
  proc(input)
    local nms, fns, oddfns;

    nms := indets( input, 'name' ) union Warnings:-UserNames();
    fns := indets( input, 'function' );
    fns, oddfns := selectremove( 'type', fns, 'typefunc'('anything', 'name') );

    fns := select(
      proc(x) member( op( 0, x ), nms ) end proc,
      fns
    );

    fns := map( x -&gt; x = op( 0, x ) * op( x ), fns union oddfns );

    if nops( fns ) = 0 then
      'false';
    else
      "Did you forget to use the multiplication sign?",
      sprintf( "%q", op( subs( fns, input ) ) );
    end if;
  end proc,
  check = false
):</Font></Text-field></Input></Group></Section><Section><Title><Text-field layout="Heading 1" style="Heading 1">sin^3(x + 1), sin^n(x + 1)</Text-field></Title><Group><Input><Text-field layout="Normal" prompt="&gt; " style="Maple Input"><Font italic="false" size="12" underline="false">AddWarning(
  function_powers,
  proc(input)
    local mfs, sT;

    mfs := indets( input, 'mathfunc'^'algebraic' );

    if nops( mfs ) &gt; 0 then
      if type( op( [1, 2], mfs ), 'typefunc'('anything', 'algebraic') ) then
        sT := sprintf( "%q", op( [1, 2, 1..-1], mfs ) );

        sT := sprintf( "%a(%s)^%a", op( [1, 1], mfs ), sT, op( [1, 2, 0], mfs ) );
      else
        sT := sprintf( "%a(t)^%a", op( [1, 1], mfs ), op( [1, 2], mfs ) );
      end if;

      "Functions should be raised to a power as follows:", sT;
    else
      'false';
    end if;
  end proc
);</Font></Text-field></Input></Group></Section><Section><Title><Text-field layout="Heading 1" style="Heading 1">f(x) := x^2;</Text-field></Title><Group><Input><Text-field layout="Normal" prompt="&gt; " style="Maple Input"><Font italic="false" size="12" underline="false">AddWarning(
  'remember_table_assignment',
  proc(input)
    local fns, ifns, i4fns, p, nm, var, expr, varS, exprS;

    fns := [op( indets( input, 'typefunc'('anything', 'name') ) )];
    fns := map2( 'op', 0, fns );
    fns := remove( 'type', fns, 'mathfunc' );
    fns := select( 'type', fns, 'procedure' );
    ifns := map( 'ToInert'@'eval', fns );
    i4fns := map2( subsop, 4 = NULL, ifns );

    if not member( _Inert_PROC(
      _Inert_PARAMSEQ(),
      _Inert_LOCALSEQ(),
      _Inert_OPTIONSEQ(
        _Inert_NAME("remember")
      ),
      _Inert_STATSEQ(
        _Inert_UNEVAL(
          _Inert_FUNCTION(
            _Inert_PROCNAME(),
            _Inert_EXPSEQ(_Inert_ARGS())
          )
        )
      ),
      _Inert_DESCRIPTIONSEQ(),
      _Inert_GLOBALSEQ(),
      _Inert_LEXICALSEQ()
    ), i4fns, p ) then
      return 'false';
    end if;

    nm := op( p, fns );
    var := FromInert( op( [p, 4, 1, 2, 1], ifns ) );
    expr := FromInert( op( [p, 4, 1, 2, 2], ifns ) );

    varS := sprintf( "(%q)", var );
    exprS := sprintf( "%q", expr );

    "Some evaluation did not occur.  Perhaps you previously meant to do:",
    sprintf( "%a := %s -&gt; %s;", nm, varS, exprS );
  end proc,
  check = false
):    </Font></Text-field></Input></Group></Section><Section><Title><Text-field layout="Heading 1" style="Heading 1">pi</Text-field></Title><Group><Input><Text-field layout="Normal" prompt="&gt; " style="Maple Input"><Font italic="false" size="12" underline="false">AddWarning(
  pi,
  proc(input)
    if has( input, 'pi' ) then
      "You used pi, perhaps you meant to use Pi (= 3.1415...).",
      sprintf( "%q;", op( subs( 'pi' = 'Pi', input ) ) );
    else
      'false';
    end if;
  end proc
): </Font></Text-field></Input></Group></Section><Section><Title><Text-field layout="Heading 1" style="Heading 1">i</Text-field></Title><Group><Input><Text-field layout="Normal" prompt="&gt; " style="Maple Input"><Font italic="false" size="12" underline="false">AddWarning(
  imaginary,
  proc(input)
    local i, iu, au, aus;

    i := interface( 'imaginaryunit' );

    iu := convert( i, 'string' );

    if member( iu, {"I", "J"} ) then
      au := StringTools:-LowerCase( iu );
    elif member( iu, {"i", "j"} ) then
      au := StringTools:-UpperCase( iu );
    else
      return 'false';
    end if;       

    aus := convert( au, 'symbol' );

    if has( input, aus ) then
      sprintf( "You used %s, perhaps you meant to use %s (= sqrt(-1)).", au, iu ),
      sprintf( "%q;", op( subs( aus = i, input ) ) );
    else
      'false';
    end if;
  end proc,
  check = false
):</Font></Text-field></Input></Group></Section><Section><Title><Text-field layout="Heading 1" style="Heading 1">sinx, cosx, etc.</Text-field></Title><Group><Input><Text-field layout="Normal" prompt="&gt; " style="Maple Input"><Font italic="false" size="12" underline="false">AddWarning(
  sinx,
  proc(input)
    local syms, mfns, i, j, si, A, B;

    syms := indets( input, 'symbol' );

    mfns := NULL; 

    for i in syms do
      for j from length( i ) - 1 to 2 by -1 do
        si := substring( i, 1..j );

        if type( si, 'mathfunc' ) then
          mfns := mfns, i = subs(
            [A = si, B = substring( i, length( si ) + 1.. -1 )],
            A(B)
          );

          next;
        end if;
      end do;
    end do;

    if mfns = NULL then
      'false';
    else
      sprintf(
        "Did you mean to use, for example, %a instead of `%a`:",
        op( [1, 2], [mfns] ), op( [1, 1], [mfns] )
      ),
      sprintf( "%q;", op( subs( mfns, input ) ) );
    end if;
  end proc,
  'check' = 'false'
):</Font></Text-field></Input></Group></Section><Section><Title><Text-field layout="Heading 1" style="Heading 1">matrix and vector</Text-field></Title><Group><Input><Text-field layout="Normal" prompt="&gt; " style="Maple Input"><Font italic="false" size="12" underline="false">AddWarning(
  linalg,
  proc(input)
    local matrices, vectors;

    matrices := indets( input, 'matrix' );
    vectors := indets( input, 'vector' );

    if hastype( input, 'matrix' ) or hastype( input, 'vector' ) then
      "You may have meant to use `Matrix` and `Vector` instead of `matrix` and `vector`.",
      sprintf(
        "%q;",
        op( subsindets( input, {'matrix', 'vector'}, proc(x)
          if type( x, 'matrix' ) then
            'Matrix'( convert( x, 'listlist' ) );
          else
            'Vector'( convert( x, 'list' ) );
          end if;
        end proc ) )
      );
    else
      'false';
    end if;
  end proc,
  'check' = 'false'
):</Font></Text-field></Input></Group></Section><Group><Input><Text-field layout="Normal" prompt="&gt; " style="Maple Input"><Font italic="false" size="12" underline="false">StartWarnings():</Font></Text-field></Input></Group><Group><Input><Text-field layout="Normal" prompt="&gt; " style="Maple Input"><Font italic="false" size="12" underline="false">t = 3;</Font></Text-field></Input></Group><Group><Input><Text-field layout="Normal" prompt="&gt; " style="Maple Input"><Font italic="false" size="12" underline="false">f(x) = t^2;</Font></Text-field></Input></Group><Group><Input><Text-field layout="Normal" prompt="&gt; " style="Maple Input"><Font italic="false" size="12" underline="false">x(x + 3);</Font></Text-field></Input></Group><Group><Input><Text-field layout="Normal" prompt="&gt; " style="Maple Input"><Font italic="false" size="12" underline="false">(3+x)(x + 3);</Font></Text-field></Input></Group><Group><Input><Text-field layout="Normal" prompt="&gt; " style="Maple Input"><Font italic="false" size="12" underline="false">y(x + y + 3);</Font></Text-field></Input></Group><Group><Input><Text-field layout="Normal" prompt="&gt; " style="Maple Input"><Font italic="false" size="12" underline="false">y(x); # Okay</Font></Text-field></Input></Group><Group><Input><Text-field layout="Normal" prompt="&gt; " style="Maple Input"><Font italic="false" size="12" underline="false">x(x+3)(x+5);</Font></Text-field></Input></Group><Group><Input><Text-field layout="Normal" prompt="&gt; " style="Maple Input"><Font italic="false" size="12" underline="false">(sin^3)(x); # Okay</Font></Text-field></Input></Group><Group><Input><Text-field layout="Normal" prompt="&gt; " style="Maple Input"><Font italic="false" size="12" underline="false">sin^2(x);</Font></Text-field></Input></Group><Group><Input><Text-field layout="Normal" prompt="&gt; " style="Maple Input"><Font italic="false" size="12" underline="false">sin^n(x + 3);</Font></Text-field></Input></Group><Group><Input><Text-field layout="Normal" style="Normal">This cannot be caught:</Text-field></Input></Group><Group><Input><Text-field layout="Normal" prompt="&gt; " style="Maple Input"><Font italic="false" size="12" underline="false">f(t) := t^2;</Font></Text-field></Input></Group><Group><Input><Text-field layout="Normal" style="Normal">But the aftershocks can:</Text-field></Input></Group><Group><Input><Text-field layout="Normal" prompt="&gt; " style="Maple Input"><Font italic="false" size="12" underline="false">f(3); # Probably unexpected</Font></Text-field></Input></Group><Group><Input><Text-field layout="Normal" prompt="&gt; " style="Maple Input"><Font italic="false" size="12" underline="false">3 + pi * i^2;</Font></Text-field></Input></Group><Group><Input><Text-field layout="Normal" prompt="&gt; " style="Maple Input"><Font italic="false" size="12" underline="false">sinx + cosx;</Font></Text-field></Input></Group><Group><Input><Text-field layout="Normal" prompt="&gt; " style="Maple Input"><Font italic="false" size="12" underline="false">matrix( [[3,2],[5,3]] );</Font></Text-field></Input></Group><Group><Input><Text-field layout="Normal" prompt="&gt; " style="Maple Input"/></Input></Group><Group><Input><Text-field layout="Normal" prompt="&gt; " style="Maple Input"/></Input></Group><Text-field/></Worksheet>