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