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