1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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 }