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