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