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.context.CodeState; 026import org.ocamljava.runtime.context.CurrentContext; 027import org.ocamljava.runtime.values.Value; 028 029/** 030 * The {@code OCamlWrappers} provides utility methods related to wrappers. 031 * 032 * @author <a href="mailto:xclerc@ocamljava.org">Xavier Clerc</a> 033 * @version 2.0 034 * @since 2.0 035 */ 036public final class OCamlWrappers { 037 038 /** Identifier for callback holding object id. */ 039 private static final String OID_CALLBACK = "CamlinternalOO.last_id"; 040 041 /** 042 * No instance of this class. 043 */ 044 private OCamlWrappers() { 045 } // end empty constructor 046 047 /** 048 * Converts a value into a {@code boolean}. 049 * @param v value to convert - should not be {@code null} 050 * @return the passed value, as a {@code boolean} 051 */ 052 public static boolean asBool(final Value v) { 053 assert v != null : "null v"; 054 return v != Value.FALSE; 055 } // end method 'asBool(Value)' 056 057 /** 058 * Returns a value representing a boolean. 059 * @param b boolean value to represent 060 * @return a value representing the passed boolean 061 */ 062 public static Value createBool(final boolean b) { 063 return b ? Value.TRUE : Value.FALSE; 064 } // end method 'createBool(boolean)' 065 066 public static Value getAndIncrementOid() { 067 final CodeState cs = CurrentContext.getCodeState(); 068 Value oid = cs.getCallback(OCamlWrappers.OID_CALLBACK); 069 if (oid == null) { 070 oid = Value.createBlock(0, Value.ZERO); 071 cs.registerCallback(OCamlWrappers.OID_CALLBACK, oid); 072 } // end if 073 final Value old = oid.get0(); 074 oid.set0(Value.createLong(old.asLong() + 1)); 075 return old; 076 } // end method 'getAndIncrementOid()' 077 078 /** 079 * Constructs and return a new closure for a Java virtual method. 080 * @param clazz method class - should not be {@code null} 081 * @param method method name - should not be {@code null} 082 * @param thiz target instance - should not be {@code null} 083 * @param arity method arity 084 */ 085 public static Value createClosure(final Class<?> clazz, 086 final String method, 087 final Object thiz, 088 final int arity) { 089 assert clazz != null : "null clazz"; 090 assert method != null : "null method"; 091 assert thiz != null : "null thiz"; 092 try { 093 final MethodHandles.Lookup lookup = MethodHandles.lookup(); 094 final Class<?>[] parameters = new Class<?>[arity]; 095 for (int i = 0; i < arity; i++) { 096 parameters[i] = Value.class; 097 } // end for 098 final MethodType mt = MethodType.methodType(Value.class, parameters); 099 final MethodHandle mh = lookup.findVirtual(clazz, method, mt); 100 return Value.createClosure(mh.bindTo(thiz), arity); 101 } catch (final NoSuchMethodException | IllegalAccessException e) { 102 return null; 103 } // end try/catch 104 } // end method 'createClosure(Class<?>, String, Object, int)' 105 106} // end class 'OCamlWrappers'