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.action;
23  
24  import org.millscript.millscript.alert.Alerts;
25  import org.millscript.millscript.functions.Function;
26  import org.millscript.millscript.vm.Machine;
27  
28  /**
29   * This class represents the action for a compound function expression. A
30   * compound function is made from two separate functions, where the second is
31   * called with it's arguments returned by the first. The first function's
32   * arguments are the arguments passed to the compound function. e.g. it's like
33   * defining the following function in millscript:
34   * <pre>
35   * function compound( args... ) =>
36   *   second(
37   *     first(
38   *       args...
39   *     )
40   *   );
41   * endfunction;
42   * </pre>
43   */
44  public final class FnCompAction extends BinaryOpAction {
45  
46      /**
47       * This class implements the underlying function for the compound function
48       * action.
49       */
50      private static final class FnCompFunction extends Function {
51  
52          /**
53           * The first function.
54           */
55          private final Function fx;
56  
57          /**
58           * The second function, whose arguments are the results of the first
59           * function.
60           */
61          private final Function fy;
62  
63          /**
64           * Constructs a new compound function with the specified first and
65           * second functions.
66           *
67           * @param x the first function
68           * @param y the second function
69           */
70          private FnCompFunction( final Function x, final Function y ) {
71              this.fx = x;
72              this.fy = y;
73          }
74  
75          /**
76           * @see org.millscript.millscript.functions.Function#apply(org.millscript.millscript.vm.Machine, int)
77           */
78          @Override
79          public void apply( final Machine mc, final int nargs ) {
80              int n = mc.getCount() - nargs;
81              fx.apply( mc, nargs );
82              fy.apply( mc, mc.getCount() - n );
83          }
84  
85      }
86  
87      /**
88       * The name for this compound function.
89       */
90      private final String name;
91  
92      /**
93       * Constructs a new compound function action with the specified name, first
94       * and second functions.
95       *
96       * @param n the name for the compound function
97       * @param a the first function to be executed
98       * @param b the second/subsequent function to be executed
99       */
100     public FnCompAction( final String n, final Action a, final Action b ) {
101         super( a, b );
102         this.name = n;
103     }
104 
105     /**
106      * @see org.millscript.millscript.action.BinaryOpAction#perform(java.lang.Object, java.lang.Object)
107      */
108     @Override
109     public Object perform( final Object x, final Object y ) {
110         try {
111             return (
112                 new FnCompFunction( (Function) x, (Function) y ).modName( name )
113             );
114         } catch ( ClassCastException ex ) {
115             throw(
116                 Alerts.eval(
117                     "Non-function argument",
118                     "Both arguments must be functions"
119                 ).
120                 culprit( "arg(1)", x ).
121                 culprit( "arg(2)", y ).
122                 mishap()
123             );
124         }
125     }
126 
127 }