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