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