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