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 OCamlFunction9} class represent an OCaml function taking nine
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 OCamlFunction9<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                                     T7 extends OCamlValue,
043                                     T8 extends OCamlValue,
044                                     TR extends OCamlValue> extends OCamlValue {
045
046    /** Wrapper for first parameter. */
047    protected final Wrapper<T0> wrapper0;
048
049    /** Wrapper for second parameter. */
050    protected final Wrapper<T1> wrapper1;
051
052    /** Wrapper for third parameter. */
053    protected final Wrapper<T2> wrapper2;
054
055    /** Wrapper for fourth parameter. */
056    protected final Wrapper<T3> wrapper3;
057
058    /** Wrapper for fifth parameter. */
059    protected final Wrapper<T4> wrapper4;
060
061    /** Wrapper for sixth parameter. */
062    protected final Wrapper<T5> wrapper5;
063
064    /** Wrapper for seventh parameter. */
065    protected final Wrapper<T6> wrapper6;
066
067    /** Wrapper for eighth parameter. */
068    protected final Wrapper<T7> wrapper7;
069
070    /** Wrapper for ninth parameter. */
071    protected final Wrapper<T8> wrapper8;
072
073    /** Wrapper for return value. */
074    protected final Wrapper<TR> wrapperr;
075
076    /** Method handle for function actually called from the OCaml runtime. */
077    private static final MethodHandle METHOD_HANDLE;
078
079    static {
080        MethodHandle mh;
081        try {
082            final MethodHandles.Lookup lookup = MethodHandles.lookup();
083            final MethodType mt = MethodType.methodType(Value.class,
084                                                        Value.class,
085                                                        Value.class,
086                                                        Value.class,
087                                                        Value.class,
088                                                        Value.class,
089                                                        Value.class,
090                                                        Value.class,
091                                                        Value.class,
092                                                        Value.class);
093            mh = lookup.findVirtual(OCamlFunction9Caller.class, "called", mt);
094        } catch (final NoSuchMethodException | IllegalAccessException e) {
095            assert false : "OCamlFunction9: unable to get method handle";
096            mh = null;
097        } // end try/catch
098        METHOD_HANDLE = mh;
099    } // end static block
100
101    /**
102     * Constructs a new instance. <br/>
103     * To be used by Java implementations.
104     * @param w0 wrapper for first parameter - should not be {@code null}
105     * @param w1 wrapper for second parameter - should not be {@code null}
106     * @param w2 wrapper for third parameter - should not be {@code null}
107     * @param w3 wrapper for fourth parameter - should not be {@code null}
108     * @param w4 wrapper for fifth parameter - should not be {@code null}
109     * @param w5 wrapper for sixth parameter - should not be {@code null}
110     * @param w6 wrapper for seventh parameter - should not be {@code null}
111     * @param w7 wrapper for eigth parameter - should not be {@code null}
112     * @param w8 wrapper for ninth parameter - should not be {@code null}
113     * @param wr wrapper for result - should not be {@code null}
114     */
115    public OCamlFunction9(final Wrapper<T0> w0,
116                          final Wrapper<T1> w1,
117                          final Wrapper<T2> w2,
118                          final Wrapper<T3> w3,
119                          final Wrapper<T4> w4,
120                          final Wrapper<T5> w5,
121                          final Wrapper<T6> w6,
122                          final Wrapper<T7> w7,
123                          final Wrapper<T8> w8,
124                          final Wrapper<TR> wr) {
125        super(Value.UNIT);
126        assert w0 != null : "null w0";
127        assert w1 != null : "null w1";
128        assert w2 != null : "null w2";
129        assert w3 != null : "null w3";
130        assert w4 != null : "null w4";
131        assert w5 != null : "null w5";
132        assert w6 != null : "null w6";
133        assert w7 != null : "null w7";
134        assert w8 != null : "null w8";
135        assert wr != null : "null wr";
136        this.wrapper0 = w0;
137        this.wrapper1 = w1;
138        this.wrapper2 = w2;
139        this.wrapper3 = w3;
140        this.wrapper4 = w4;
141        this.wrapper5 = w5;
142        this.wrapper6 = w6;
143        this.wrapper7 = w7;
144        this.wrapper8 = w8;
145        this.wrapperr = wr;
146    } // end constructor(Wrapper<T0>, Wrapper<T1>, Wrapper<T2>, Wrapper<T3>, Wrapper<T4>, Wrapper<T5>, Wrapper<T6>, Wrapper<T7>, Wrapper<T8>, Wrapper<TR>)
147
148    /**
149     * Constructs a new instance. <br/>
150     * To be used by Java implementations.
151     */
152    @SuppressWarnings("unchecked")
153    public OCamlFunction9() {
154        this((Wrapper<T0>) OCamlValue.WRAPPER,
155             (Wrapper<T1>) OCamlValue.WRAPPER,
156             (Wrapper<T2>) OCamlValue.WRAPPER,
157             (Wrapper<T3>) OCamlValue.WRAPPER,
158             (Wrapper<T4>) OCamlValue.WRAPPER,
159             (Wrapper<T5>) OCamlValue.WRAPPER,
160             (Wrapper<T6>) OCamlValue.WRAPPER,
161             (Wrapper<T7>) OCamlValue.WRAPPER,
162             (Wrapper<T8>) OCamlValue.WRAPPER,
163             (Wrapper<TR>) OCamlValue.WRAPPER);
164    } // end empty constructor
165
166    /**
167     * Constructs a new instance from a value. <br/>
168     * To be used by OCaml implementations.
169     * @param w0 wrapper for first parameter - should not be {@code null}
170     * @param w1 wrapper for second parameter - should not be {@code null}
171     * @param w2 wrapper for third parameter - should not be {@code null}
172     * @param w3 wrapper for fourth parameter - should not be {@code null}
173     * @param w4 wrapper for fifth parameter - should not be {@code null}
174     * @param w5 wrapper for fifth parameter - should not be {@code null}
175     * @param w6 wrapper for fifth parameter - should not be {@code null}
176     * @param w7 wrapper for fifth parameter - should not be {@code null}
177     * @param w8 wrapper for fifth parameter - should not be {@code null}
178     * @param wr wrapper for result - should not be {@code null}
179     */
180    OCamlFunction9(final Value v,
181                   final Wrapper<T0> w0,
182                   final Wrapper<T1> w1,
183                   final Wrapper<T2> w2,
184                   final Wrapper<T3> w3,
185                   final Wrapper<T4> w4,
186                   final Wrapper<T5> w5,
187                   final Wrapper<T6> w6,
188                   final Wrapper<T7> w7,
189                   final Wrapper<T8> w8,
190                   final Wrapper<TR> wr) {
191        super(v);
192        assert w0 != null : "null w0";
193        assert w1 != null : "null w1";
194        assert w2 != null : "null w2";
195        assert w3 != null : "null w3";
196        assert w4 != null : "null w4";
197        assert w5 != null : "null w5";
198        assert w6 != null : "null w6";
199        assert w7 != null : "null w7";
200        assert w8 != null : "null w8";
201        assert wr != null : "null wr";
202        this.wrapper0 = w0;
203        this.wrapper1 = w1;
204        this.wrapper2 = w2;
205        this.wrapper3 = w3;
206        this.wrapper4 = w4;
207        this.wrapper5 = w5;
208        this.wrapper6 = w6;
209        this.wrapper7 = w7;
210        this.wrapper8 = w8;
211        this.wrapperr = wr;
212    } // end constructor(Value, Wrapper<T0>, Wrapper<T1>, Wrapper<T2>, Wrapper<T3>, Wrapper<T4>, Wrapper<T5>, Wrapper<T6>, Wrapper<T7>, Wrapper<T8>, Wrapper<TR>)
213
214    /**
215     * {@inheritDoc}
216     */
217    @Override
218    public final Wrapper<? extends OCamlFunction9<T0, T1, T2, T3, T4, T5, T6, T7, T8, TR>> getWrapper() {
219        return OCamlFunction9.wrapper(this.wrapper0,
220                                      this.wrapper1,
221                                      this.wrapper2,
222                                      this.wrapper3,
223                                      this.wrapper4,
224                                      this.wrapper5,
225                                      this.wrapper6,
226                                      this.wrapper7,
227                                      this.wrapper8,
228                                      this.wrapperr);
229    } // end method 'getWrapper()'
230
231    /**
232     * {@inheritDoc}
233     */
234    @Override
235    public Wrapper<? extends OCamlValue> getWrapper(final int idx) {
236        switch (idx) {
237        case 0: return this.wrapper0;
238        case 1: return this.wrapper1;
239        case 2: return this.wrapper2;
240        case 3: return this.wrapper3;
241        case 4: return this.wrapper4;
242        case 5: return this.wrapper5;
243        case 6: return this.wrapper6;
244        case 7: return this.wrapper7;
245        case 8: return this.wrapper8;
246        case 9: return this.wrapperr;
247        default: return OCamlUnit.WRAPPER;
248        } // end switch
249    } // end method 'getWrapper(int)'
250
251    /**
252     * Returns the closure to be executed from the OCaml runtime.
253     * @param w0 wrapper for first parameter - should not be {@code null}
254     * @param w1 wrapper for second parameter - should not be {@code null}
255     * @param w2 wrapper for third parameter - should not be {@code null}
256     * @param w3 wrapper for fourth parameter - should not be {@code null}
257     * @param w4 wrapper for fifth parameter - should not be {@code null}
258     * @param w5 wrapper for sixth parameter - should not be {@code null}
259     * @param w6 wrapper for seventh parameter - should not be {@code null}
260     * @param w7 wrapper for eighth parameter - should not be {@code null}
261     * @param w8 wrapper for ninth parameter - should not be {@code null}
262     * @return the closure to be executed on the OCaml side
263     */
264    public Value getClosure(final Wrapper<T0> w0,
265                            final Wrapper<T1> w1,
266                            final Wrapper<T2> w2,
267                            final Wrapper<T3> w3,
268                            final Wrapper<T4> w4,
269                            final Wrapper<T5> w5,
270                            final Wrapper<T6> w6,
271                            final Wrapper<T7> w7,
272                            final Wrapper<T8> w8) {
273        assert w0 != null : "null w0";
274        assert w1 != null : "null w1";
275        assert w2 != null : "null w2";
276        assert w3 != null : "null w3";
277        assert w4 != null : "null w4";
278        assert w5 != null : "null w5";
279        assert w6 != null : "null w6";
280        assert w7 != null : "null w7";
281        assert w8 != null : "null w8";
282        final OCamlFunction9Caller<T0, T1, T2, T3, T4, T5, T6, T7, T8, TR> ofc = new OCamlFunction9Caller<>(w0, w1, w2, w3, w4, w5, w6, w7, w8, this);
283        return Value.createClosure(OCamlFunction9.METHOD_HANDLE.bindTo(ofc), 9);
284    } // end method 'getClosure(Wrapper<T0>, Wrapper<T1>, Wrapper<T2>, Wrapper<T3>, Wrapper<T4>, Wrapper<T5>, Wrapper<T6>, Wrapper<T7>, Wrapper<T8>)'
285
286    /**
287     * The actual implementation of the function
288     * @param p0 first parameter - should not be {@code null}
289     * @param p1 second parameter - should not be {@code null}
290     * @param p2 third parameter - should not be {@code null}
291     * @param p3 fourth parameter - should not be {@code null}
292     * @param p4 fifth parameter - should not be {@code null}
293     * @param p5 sixth parameter - should not be {@code null}
294     * @param p6 seventh parameter - should not be {@code null}
295     * @param p7 eighth parameter - should not be {@code null}
296     * @param p8 ninth parameter - should not be {@code null}
297     * @throws OCamlException if function fails
298     */
299    public abstract TR execute(final T0 p0,
300                               final T1 p1,
301                               final T2 p2,
302                               final T3 p3,
303                               final T4 p4,
304                               final T5 p5,
305                               final T6 p6,
306                               final T7 p7,
307                               final T8 p8)
308        throws OCamlException;
309
310    /**
311     * {@inheritDoc}
312     */
313    @Override
314    public final int hashCode() {
315        return super.hashCode();
316    } // end method 'hashCode()'
317
318    /**
319     * {@inheritDoc}
320     */
321    @Override
322    public final boolean equals(final Object obj) {
323        if (obj instanceof OCamlFunction9) {
324            final OCamlFunction9<?, ?, ?, ?, ?, ?, ?, ?, ?, ?> that = (OCamlFunction9) obj;
325            return this == that;
326        } else {
327            return false;
328        } // end if/else
329    } // end method 'equals(Object)'
330
331    /**
332     * {@inheritDoc}
333     */
334    @Override
335    public final String toString() {
336        return "OCamlFunction9(...)";
337    } // end method 'toString()'
338
339    /**
340     * Wraps the passed value.
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 w7 wrapper for eighth parameter - should not be {@code null}
349     * @param w8 wrapper for ninth parameter - should not be {@code null}
350     * @param wr wrapper for result - should not be {@code null}
351     * @param v value to wrap - should not be {@code null}
352     * @return a new {@code OCamlFunction9} instance wrapping the passed value
353     */
354    public static <T0 extends OCamlValue,
355                   T1 extends OCamlValue,
356                   T2 extends OCamlValue,
357                   T3 extends OCamlValue,
358                   T4 extends OCamlValue,
359                   T5 extends OCamlValue,
360                   T6 extends OCamlValue,
361                   T7 extends OCamlValue,
362                   T8 extends OCamlValue,
363                   TR extends OCamlValue>
364        OCamlFunction9<T0, T1, T2, T3, T4, T5, T6, T7, T8, TR> wrap(final Wrapper<T0> w0,
365                                                                    final Wrapper<T1> w1,
366                                                                    final Wrapper<T2> w2,
367                                                                    final Wrapper<T3> w3,
368                                                                    final Wrapper<T4> w4,
369                                                                    final Wrapper<T5> w5,
370                                                                    final Wrapper<T6> w6,
371                                                                    final Wrapper<T7> w7,
372                                                                    final Wrapper<T8> w8,
373                                                                    final Wrapper<TR> wr,
374                                                                    final Value v) {
375        assert w0 != null : "null w0";
376        assert w1 != null : "null w1";
377        assert w2 != null : "null w2";
378        assert w3 != null : "null w3";
379        assert w4 != null : "null w4";
380        assert w5 != null : "null w5";
381        assert w6 != null : "null w6";
382        assert w7 != null : "null w7";
383        assert w8 != null : "null w8";
384        assert wr != null : "null wr";
385        assert v != null : "null v";
386        return new OCamlFunction9Impl<T0, T1, T2, T3, T4, T5, T6, T7, T8, TR>(w0, w1, w2, w3, w4, w5, w6, w7, w8, wr, v);
387    } // end method 'wrap(Wrapper<T0>, Wrapper<T1>, Wrapper<T2>, Wrapper<T3>, Wrapper<T4>, Wrapper<T5>, Wrapper<T6>, Wrapper<T7>, Wrapper<T8>, Wrapper<TR>, Value)'
388
389    /**
390     * Returns a wrapper for {@code OCamlFunction9} values.
391     * @param w0 wrapper for first parameter - should not be {@code null}
392     * @param w1 wrapper for second parameter - should not be {@code null}
393     * @param w2 wrapper for third parameter - should not be {@code null}
394     * @param w3 wrapper for fourth parameter - should not be {@code null}
395     * @param w4 wrapper for fifth parameter - should not be {@code null}
396     * @param w5 wrapper for sixth parameter - should not be {@code null}
397     * @param w6 wrapper for seventh parameter - should not be {@code null}
398     * @param w7 wrapper for eighth parameter - should not be {@code null}
399     * @param w8 wrapper for ninth parameter - should not be {@code null}
400     * @param wr wrapper for result - should not be {@code null}
401     * @return a wrapper for {@code OCamlFunction5} values
402     */
403    @SuppressWarnings("unchecked")
404    public static <T0 extends OCamlValue,
405                   T1 extends OCamlValue,
406                   T2 extends OCamlValue,
407                   T3 extends OCamlValue,
408                   T4 extends OCamlValue,
409                   T5 extends OCamlValue,
410                   T6 extends OCamlValue,
411                   T7 extends OCamlValue,
412                   T8 extends OCamlValue,
413                   TR extends OCamlValue>
414        Wrapper<? extends OCamlFunction9<T0, T1, T2, T3, T4, T5, T6, T7, T8, TR>> wrapper(final Wrapper<T0> w0,
415                                                                                          final Wrapper<T1> w1,
416                                                                                          final Wrapper<T2> w2,
417                                                                                          final Wrapper<T3> w3,
418                                                                                          final Wrapper<T4> w4,
419                                                                                          final Wrapper<T5> w5,
420                                                                                          final Wrapper<T6> w6,
421                                                                                          final Wrapper<T7> w7,
422                                                                                          final Wrapper<T8> w8,
423                                                                                          final Wrapper<TR> wr) {
424        assert w0 != null : "null w0";
425        assert w1 != null : "null w1";
426        assert w2 != null : "null w2";
427        assert w3 != null : "null w3";
428        assert w4 != null : "null w4";
429        assert w5 != null : "null w5";
430        assert w6 != null : "null w6";
431        assert w7 != null : "null w7";
432        assert w8 != null : "null w8";
433        assert wr != null : "null wr";
434        return new ComposedWrapper<OCamlFunction9<T0, T1, T2, T3, T4, T5, T6, T7, T8, TR>>(w0, w1, w2, w3, w4, w5, w6, w7, w8, wr) {
435            /**
436             * {@inheritDoc}
437             */
438            @Override
439                public OCamlFunction9<T0, T1, T2, T3, T4, T5, T6, T7, T8, TR> wrap(final Value v) {
440                return new OCamlFunction9Impl<T0, T1, T2, T3, T4, T5, T6, T7, T8, TR>(w0, w1, w2, w3, w4, w5, w6, w7, w8, wr, v);
441            } // end method 'wrap(Value)'
442        }; // end anonymous inner-class
443    } // end method 'wrapper(Wrapper<T0>, Wrapper<T1>, Wrapper<T2>, Wrapper<T3>, Wrapper<T4>, Wrapper<T5>, Wrapper<T6>, Wrapper<T7>, Wrapper<T8>, Wrapper<TR>)'
444
445} // end class 'OCamlFunction9'