001/*
002 * This file is part of OCaml-Java runtime.
003 * Copyright (C) 2007-2013 Xavier Clerc.
004 *
005 * OCaml-Java runtime is free software; you can redistribute it and/or modify
006 * it under the terms of the GNU Lesser General Public License as published by
007 * the Free Software Foundation; either version 3 of the License, or
008 * (at your option) any later version.
009 *
010 * OCaml-Java runtime is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
013 * GNU Lesser General Public License for more details.
014 *
015 * You should have received a copy of the GNU Lesser General Public License
016 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
017 */
018
019package org.ocamljava.runtime.wrappers;
020
021import java.lang.invoke.MethodHandle;
022import java.lang.invoke.MethodHandles;
023import java.lang.invoke.MethodType;
024
025import org.ocamljava.runtime.values.Value;
026
027/**
028 * The {@code OCamlFunction7} class represent an OCaml function taking seven
029 * parameter.
030 *
031 * @author <a href="mailto:xclerc@ocamljava.org">Xavier Clerc</a>
032 * @version 2.0
033 * @since 2.0
034 */
035public abstract class OCamlFunction7<T0 extends OCamlValue,
036                                     T1 extends OCamlValue,
037                                     T2 extends OCamlValue,
038                                     T3 extends OCamlValue,
039                                     T4 extends OCamlValue,
040                                     T5 extends OCamlValue,
041                                     T6 extends OCamlValue,
042                                     TR extends OCamlValue> extends OCamlValue {
043
044    /** Wrapper for first parameter. */
045    protected final Wrapper<T0> wrapper0;
046
047    /** Wrapper for second parameter. */
048    protected final Wrapper<T1> wrapper1;
049
050    /** Wrapper for third parameter. */
051    protected final Wrapper<T2> wrapper2;
052
053    /** Wrapper for fourth parameter. */
054    protected final Wrapper<T3> wrapper3;
055
056    /** Wrapper for fifth parameter. */
057    protected final Wrapper<T4> wrapper4;
058
059    /** Wrapper for sixth parameter. */
060    protected final Wrapper<T5> wrapper5;
061
062    /** Wrapper for seventh parameter. */
063    protected final Wrapper<T6> wrapper6;
064
065    /** Wrapper for return value. */
066    protected final Wrapper<TR> wrapperr;
067
068    /** Method handle for function actually called from the OCaml runtime. */
069    private static final MethodHandle METHOD_HANDLE;
070
071    static {
072        MethodHandle mh;
073        try {
074            final MethodHandles.Lookup lookup = MethodHandles.lookup();
075            final MethodType mt = MethodType.methodType(Value.class,
076                                                        Value.class,
077                                                        Value.class,
078                                                        Value.class,
079                                                        Value.class,
080                                                        Value.class,
081                                                        Value.class,
082                                                        Value.class);
083            mh = lookup.findVirtual(OCamlFunction7Caller.class, "called", mt);
084        } catch (final NoSuchMethodException | IllegalAccessException e) {
085            assert false : "OCamlFunction7: unable to get method handle";
086            mh = null;
087        } // end try/catch
088        METHOD_HANDLE = mh;
089    } // end static block
090
091    /**
092     * Constructs a new instance. <br/>
093     * To be used by Java implementations.
094     * @param w0 wrapper for first parameter - should not be {@code null}
095     * @param w1 wrapper for second parameter - should not be {@code null}
096     * @param w2 wrapper for third parameter - should not be {@code null}
097     * @param w3 wrapper for fourth parameter - should not be {@code null}
098     * @param w4 wrapper for fifth parameter - should not be {@code null}
099     * @param w5 wrapper for sixth parameter - should not be {@code null}
100     * @param w6 wrapper for seventh parameter - should not be {@code null}
101     * @param wr wrapper for result - should not be {@code null}
102     */
103    public OCamlFunction7(final Wrapper<T0> w0,
104                          final Wrapper<T1> w1,
105                          final Wrapper<T2> w2,
106                          final Wrapper<T3> w3,
107                          final Wrapper<T4> w4,
108                          final Wrapper<T5> w5,
109                          final Wrapper<T6> w6,
110                          final Wrapper<TR> wr) {
111        super(Value.UNIT);
112        assert w0 != null : "null w0";
113        assert w1 != null : "null w1";
114        assert w2 != null : "null w2";
115        assert w3 != null : "null w3";
116        assert w4 != null : "null w4";
117        assert w5 != null : "null w5";
118        assert w6 != null : "null w6";
119        assert wr != null : "null wr";
120        this.wrapper0 = w0;
121        this.wrapper1 = w1;
122        this.wrapper2 = w2;
123        this.wrapper3 = w3;
124        this.wrapper4 = w4;
125        this.wrapper5 = w5;
126        this.wrapper6 = w6;
127        this.wrapperr = wr;
128    } // end constructor(Wrapper<T0>, Wrapper<T1>, Wrapper<T2>, Wrapper<T3>, Wrapper<T4>, Wrapper<T5>, Wrapper<T6>, Wrapper<TR>)
129
130    /**
131     * Constructs a new instance. <br/>
132     * To be used by Java implementations.
133     */
134    @SuppressWarnings("unchecked")
135    public OCamlFunction7() {
136        this((Wrapper<T0>) OCamlValue.WRAPPER,
137             (Wrapper<T1>) OCamlValue.WRAPPER,
138             (Wrapper<T2>) OCamlValue.WRAPPER,
139             (Wrapper<T3>) OCamlValue.WRAPPER,
140             (Wrapper<T4>) OCamlValue.WRAPPER,
141             (Wrapper<T5>) OCamlValue.WRAPPER,
142             (Wrapper<T6>) OCamlValue.WRAPPER,
143             (Wrapper<TR>) OCamlValue.WRAPPER);
144    } // end empty constructor
145
146    /**
147     * Constructs a new instance from a value. <br/>
148     * To be used by OCaml implementations.
149     * @param w0 wrapper for first parameter - should not be {@code null}
150     * @param w1 wrapper for second parameter - should not be {@code null}
151     * @param w2 wrapper for third parameter - should not be {@code null}
152     * @param w3 wrapper for fourth parameter - should not be {@code null}
153     * @param w4 wrapper for fifth parameter - should not be {@code null}
154     * @param w5 wrapper for fifth parameter - should not be {@code null}
155     * @param w6 wrapper for fifth parameter - should not be {@code null}
156     * @param wr wrapper for result - should not be {@code null}
157     */
158    OCamlFunction7(final Value v,
159                   final Wrapper<T0> w0,
160                   final Wrapper<T1> w1,
161                   final Wrapper<T2> w2,
162                   final Wrapper<T3> w3,
163                   final Wrapper<T4> w4,
164                   final Wrapper<T5> w5,
165                   final Wrapper<T6> w6,
166                   final Wrapper<TR> wr) {
167        super(v);
168        assert w0 != null : "null w0";
169        assert w1 != null : "null w1";
170        assert w2 != null : "null w2";
171        assert w3 != null : "null w3";
172        assert w4 != null : "null w4";
173        assert w5 != null : "null w5";
174        assert w6 != null : "null w6";
175        assert wr != null : "null wr";
176        this.wrapper0 = w0;
177        this.wrapper1 = w1;
178        this.wrapper2 = w2;
179        this.wrapper3 = w3;
180        this.wrapper4 = w4;
181        this.wrapper5 = w5;
182        this.wrapper6 = w6;
183        this.wrapperr = wr;
184    } // end constructor(Value, Wrapper<T0>, Wrapper<T1>, Wrapper<T2>, Wrapper<T3>, Wrapper<T4>, Wrapper<T5>, Wrapper<T6>, Wrapper<TR>)
185
186    /**
187     * {@inheritDoc}
188     */
189    @Override
190    public final Wrapper<? extends OCamlFunction7<T0, T1, T2, T3, T4, T5, T6, TR>> getWrapper() {
191        return OCamlFunction7.wrapper(this.wrapper0,
192                                      this.wrapper1,
193                                      this.wrapper2,
194                                      this.wrapper3,
195                                      this.wrapper4,
196                                      this.wrapper5,
197                                      this.wrapper6,
198                                      this.wrapperr);
199    } // end method 'getWrapper()'
200
201    /**
202     * {@inheritDoc}
203     */
204    @Override
205    public Wrapper<? extends OCamlValue> getWrapper(final int idx) {
206        switch (idx) {
207        case 0: return this.wrapper0;
208        case 1: return this.wrapper1;
209        case 2: return this.wrapper2;
210        case 3: return this.wrapper3;
211        case 4: return this.wrapper4;
212        case 5: return this.wrapper5;
213        case 6: return this.wrapper6;
214        case 7: return this.wrapperr;
215        default: return OCamlUnit.WRAPPER;
216        } // end switch
217    } // end method 'getWrapper(int)'
218
219    /**
220     * Returns the closure to be executed from the OCaml runtime.
221     * @param w0 wrapper for first parameter - should not be {@code null}
222     * @param w1 wrapper for second parameter - should not be {@code null}
223     * @param w2 wrapper for third parameter - should not be {@code null}
224     * @param w3 wrapper for fourth parameter - should not be {@code null}
225     * @param w4 wrapper for fifth parameter - should not be {@code null}
226     * @param w5 wrapper for sixth parameter - should not be {@code null}
227     * @param w6 wrapper for seventh parameter - should not be {@code null}
228     * @return the closure to be executed on the OCaml side
229     */
230    public Value getClosure(final Wrapper<T0> w0,
231                            final Wrapper<T1> w1,
232                            final Wrapper<T2> w2,
233                            final Wrapper<T3> w3,
234                            final Wrapper<T4> w4,
235                            final Wrapper<T5> w5,
236                            final Wrapper<T6> w6) {
237        assert w0 != null : "null w0";
238        assert w1 != null : "null w1";
239        assert w2 != null : "null w2";
240        assert w3 != null : "null w3";
241        assert w4 != null : "null w4";
242        assert w5 != null : "null w5";
243        assert w6 != null : "null w6";
244        final OCamlFunction7Caller<T0, T1, T2, T3, T4, T5, T6, TR> ofc = new OCamlFunction7Caller<>(w0, w1, w2, w3, w4, w5, w6, this);
245        return Value.createClosure(OCamlFunction7.METHOD_HANDLE.bindTo(ofc), 7);
246    } // end method 'getClosure(Wrapper<T0>, Wrapper<T1>, Wrapper<T2>, Wrapper<T3>, Wrapper<T4>, Wrapper<T5>, Wrapper<T6>)'
247
248    /**
249     * The actual implementation of the function
250     * @param p0 first parameter - should not be {@code null}
251     * @param p1 second parameter - should not be {@code null}
252     * @param p2 third parameter - should not be {@code null}
253     * @param p3 fourth parameter - should not be {@code null}
254     * @param p4 fifth parameter - should not be {@code null}
255     * @param p5 sixth parameter - should not be {@code null}
256     * @param p6 seventh parameter - should not be {@code null}
257     * @throws OCamlException if function fails
258     */
259    public abstract TR execute(final T0 p0,
260                               final T1 p1,
261                               final T2 p2,
262                               final T3 p3,
263                               final T4 p4,
264                               final T5 p5,
265                               final T6 p6)
266        throws OCamlException;
267
268    /**
269     * {@inheritDoc}
270     */
271    @Override
272    public final int hashCode() {
273        return super.hashCode();
274    } // end method 'hashCode()'
275
276    /**
277     * {@inheritDoc}
278     */
279    @Override
280    public final boolean equals(final Object obj) {
281        if (obj instanceof OCamlFunction7) {
282            final OCamlFunction7<?, ?, ?, ?, ?, ?, ?, ?> that = (OCamlFunction7) obj;
283            return this == that;
284        } else {
285            return false;
286        } // end if/else
287    } // end method 'equals(Object)'
288
289    /**
290     * {@inheritDoc}
291     */
292    @Override
293    public final String toString() {
294        return "OCamlFunction7(...)";
295    } // end method 'toString()'
296
297    /**
298     * Wraps the passed value.
299     * @param w0 wrapper for first parameter - should not be {@code null}
300     * @param w1 wrapper for second parameter - should not be {@code null}
301     * @param w2 wrapper for third parameter - should not be {@code null}
302     * @param w3 wrapper for fourth parameter - should not be {@code null}
303     * @param w4 wrapper for fifth parameter - should not be {@code null}
304     * @param w5 wrapper for sixth parameter - should not be {@code null}
305     * @param w6 wrapper for seventh parameter - should not be {@code null}
306     * @param wr wrapper for result - should not be {@code null}
307     * @param v value to wrap - should not be {@code null}
308     * @return a new {@code OCamlFunction7} instance wrapping the passed value
309     */
310    public static <T0 extends OCamlValue,
311                   T1 extends OCamlValue,
312                   T2 extends OCamlValue,
313                   T3 extends OCamlValue,
314                   T4 extends OCamlValue,
315                   T5 extends OCamlValue,
316                   T6 extends OCamlValue,
317                   TR extends OCamlValue>
318        OCamlFunction7<T0, T1, T2, T3, T4, T5, T6, TR> wrap(final Wrapper<T0> w0,
319                                                            final Wrapper<T1> w1,
320                                                            final Wrapper<T2> w2,
321                                                            final Wrapper<T3> w3,
322                                                            final Wrapper<T4> w4,
323                                                            final Wrapper<T5> w5,
324                                                            final Wrapper<T6> w6,
325                                                            final Wrapper<TR> wr,
326                                                            final Value v) {
327        assert w0 != null : "null w0";
328        assert w1 != null : "null w1";
329        assert w2 != null : "null w2";
330        assert w3 != null : "null w3";
331        assert w4 != null : "null w4";
332        assert w5 != null : "null w5";
333        assert w6 != null : "null w6";
334        assert wr != null : "null wr";
335        assert v != null : "null v";
336        return new OCamlFunction7Impl<T0, T1, T2, T3, T4, T5, T6, TR>(w0, w1, w2, w3, w4, w5, w6, wr, v);
337    } // end method 'wrap(Wrapper<T0>, Wrapper<T1>, Wrapper<T2>, Wrapper<T3>, Wrapper<T4>, Wrapper<T5>, Wrapper<T6>, Wrapper<TR>, Value)'
338
339    /**
340     * Returns a wrapper for {@code OCamlFunction7} values.
341     * @param w0 wrapper for first parameter - should not be {@code null}
342     * @param w1 wrapper for second parameter - should not be {@code null}
343     * @param w2 wrapper for third parameter - should not be {@code null}
344     * @param w3 wrapper for fourth parameter - should not be {@code null}
345     * @param w4 wrapper for fifth parameter - should not be {@code null}
346     * @param w5 wrapper for sixth parameter - should not be {@code null}
347     * @param w6 wrapper for seventh parameter - should not be {@code null}
348     * @param wr wrapper for result - should not be {@code null}
349     * @return a wrapper for {@code OCamlFunction5} values
350     */
351    @SuppressWarnings("unchecked")
352    public static <T0 extends OCamlValue,
353                   T1 extends OCamlValue,
354                   T2 extends OCamlValue,
355                   T3 extends OCamlValue,
356                   T4 extends OCamlValue,
357                   T5 extends OCamlValue,
358                   T6 extends OCamlValue,
359                   TR extends OCamlValue>
360        Wrapper<? extends OCamlFunction7<T0, T1, T2, T3, T4, T5, T6, TR>> wrapper(final Wrapper<T0> w0,
361                                                                                  final Wrapper<T1> w1,
362                                                                                  final Wrapper<T2> w2,
363                                                                                  final Wrapper<T3> w3,
364                                                                                  final Wrapper<T4> w4,
365                                                                                  final Wrapper<T5> w5,
366                                                                                  final Wrapper<T6> w6,
367                                                                                  final Wrapper<TR> wr) {
368        assert w0 != null : "null w0";
369        assert w1 != null : "null w1";
370        assert w2 != null : "null w2";
371        assert w3 != null : "null w3";
372        assert w4 != null : "null w4";
373        assert w5 != null : "null w5";
374        assert w6 != null : "null w6";
375        assert wr != null : "null wr";
376        return new ComposedWrapper<OCamlFunction7<T0, T1, T2, T3, T4, T5, T6, TR>>(w0, w1, w2, w3, w4, w5, w6, wr) {
377            /**
378             * {@inheritDoc}
379             */
380            @Override
381                public OCamlFunction7<T0, T1, T2, T3, T4, T5, T6, TR> wrap(final Value v) {
382                return new OCamlFunction7Impl<T0, T1, T2, T3, T4, T5, T6, TR>(w0, w1, w2, w3, w4, w5, w6, wr, v);
383            } // end method 'wrap(Value)'
384        }; // end anonymous inner-class
385    } // end method 'wrapper(Wrapper<T0>, Wrapper<T1>, Wrapper<T2>, Wrapper<T3>, Wrapper<T4>, Wrapper<T5>, Wrapper<T6>, Wrapper<TR>)'
386
387} // end class 'OCamlFunction7'