View Javadoc

1   ////////////////////////////////////////////////////////////////////////////////
2   // MillScript: an Open Spice interpreter and batch website creation tool
3   // Copyright (C) 2001-2004 Open World Ltd
4   // Copyright (C) 2005 Kevin Rogers
5   //
6   // This file is part of MillScript.
7   //
8   // MillScript is free software; you can redistribute it and/or modify it under
9   // the terms of the GNU General Public License as published by the Free
10  // Software Foundation; either version 2 of the License, or (at your option)
11  // any later version.
12  //
13  // MillScript is distributed in the hope that it will be useful, but WITHOUT
14  // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15  // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
16  // more details.
17  //
18  // You should have received a copy of the GNU General Public License along with
19  // MillScript; if not, write to the Free Software Foundation, Inc., 59 Temple
20  // Place, Suite 330, Boston, MA  02111-1307  USA
21  ////////////////////////////////////////////////////////////////////////////////
22  package org.millscript.millscript.functions;
23  
24  import org.millscript.commons.alert.Alert;
25  import org.millscript.commons.util.EMap;
26  import org.millscript.commons.util.IList;
27  import org.millscript.commons.util.ListIterator;
28  import org.millscript.commons.util.MapIterator;
29  import org.millscript.commons.util.Maplet;
30  import org.millscript.commons.util.map.ELinkedHashMap;
31  import org.millscript.millscript.alert.Alerts;
32  import org.millscript.millscript.tools.CastLibrary;
33  import org.millscript.millscript.vm.Machine;
34  
35  /**
36   * This class implements the MillScript <code>mishap</code> function.
37   */
38  public final class MishapFunction extends Function {
39  
40      /**
41       * @see org.millscript.millscript.functions.Function#apply(org.millscript.millscript.vm.Machine, int)
42       */
43      @Override
44      public void apply( final Machine mc, final int nargs ) {
45          EMap< Object, Object > map = new ELinkedHashMap< Object, Object >();
46          initialize( mc, nargs, map );
47          String complaint = (String) map.get( "complaint" );
48          map.removeKey( "complaint" );
49          String reason = (String) map.get( "reason" );
50          map.removeKey( "reason" );
51          final Alert alert = Alerts.eval( complaint, reason );
52          MapIterator< Object, Object > it = map.iterator( true );
53          while ( it.hasNext() ) {
54              alert.culprit( CastLibrary.toString( it.nextKey() ), it.currentValue() );
55          }
56          throw(
57              alert.mishap()
58          );
59      }
60  
61      /**
62       * Initialises the specified map with the mishaps culprits.
63       *
64       * @param mc    the machine to obtain culprit values from
65       * @param nargs the number of culprits/arguments
66       * @param map   the map holding a mapping of culprit to explanation
67       * @return the number of culprit left to process
68       */
69      private static int initialize( final Machine mc, final int nargs, final EMap< Object, Object > map ) {
70          if ( nargs >= 1 ) {
71              final Object obj = mc.popObject();
72              final int anonymous = initialize( mc, nargs - 1, map );
73  
74              if ( obj instanceof String ) {
75                  if ( anonymous == 0 ) {
76                      map.insert( "complaint", obj );
77                  } else if ( anonymous == 1 ) {
78                      map.insert( "reason", obj );
79                  } else {
80                      throw(
81                          Alerts.eval(
82                              "Too many unlabelled arguments",
83                              "Only the first two are valid"
84                          ).culprit( "String", obj ).mishap()
85                      );
86                  }
87                  return anonymous + 1;
88              } else if ( obj instanceof EMap ) {
89                  map.insertAll( (EMap< ?, ? >) obj );
90                  return anonymous;
91              } else if ( obj instanceof Maplet ) {
92                  map.insert( (Maplet< ?, ? >) obj );
93                  return anonymous;
94              } else if ( obj instanceof IList ) {
95                  ListIterator< ? > it = ((IList) obj).iterator( true );
96                  while ( it.hasNext() ) {
97                      Object key = it.nextValue();
98                      Object val = it.nextValue();
99                      map.insert( key, val );
100                 }
101                 return anonymous;
102             } else {
103                 throw(
104                     Alerts.eval(
105                         "Invalid mishap argument",
106                         "Only Strings, Maps, Maplets or Lists allowed"
107                     ).culprit( "object", obj ).mishap()
108                 );
109             }
110         } else {
111             return 0;
112         }
113     }
114 
115 }