public Object coerce(LuaValue value) {
   if (value.isnil()) return null;
   if (targetType == TARGET_TYPE_STRING) return value.tojstring();
   LuaString s = value.checkstring();
   byte[] b = new byte[s.m_length];
   s.copyInto(0, b, 0, b.length);
   return b;
 }
 public int score(LuaValue value) {
   switch (value.type()) {
     case LuaValue.TTABLE:
       return value.length() == 0 ? 0 : componentCoercion.score(value.get(1));
     case LuaValue.TUSERDATA:
       return inheritanceLevels(componentType, value.touserdata().getClass().getComponentType());
     case LuaValue.TNIL:
       return SCORE_NULL_VALUE;
     default:
       return SCORE_UNCOERCIBLE;
   }
 }
 public int score(LuaValue value) {
   switch (value.type()) {
     case LuaValue.TSTRING:
       return value.checkstring().isValidUtf8()
           ? (targetType == TARGET_TYPE_STRING ? 0 : 1)
           : (targetType == TARGET_TYPE_BYTES ? 0 : SCORE_WRONG_TYPE);
     case LuaValue.TNIL:
       return SCORE_NULL_VALUE;
     default:
       return targetType == TARGET_TYPE_STRING ? SCORE_WRONG_TYPE : SCORE_UNCOERCIBLE;
   }
 }
 public int score(LuaValue value) {
   switch (value.type()) {
     case LuaValue.TBOOLEAN:
       return 0;
   }
   return 1;
 }
 public int score(LuaValue value) {
   switch (value.type()) {
     case LuaValue.TNUMBER:
       return inheritanceLevels(targetType, value.isint() ? Integer.class : Double.class);
     case LuaValue.TBOOLEAN:
       return inheritanceLevels(targetType, Boolean.class);
     case LuaValue.TSTRING:
       return inheritanceLevels(targetType, String.class);
     case LuaValue.TUSERDATA:
       return inheritanceLevels(targetType, value.touserdata().getClass());
     case LuaValue.TNIL:
       return SCORE_NULL_VALUE;
     default:
       return inheritanceLevels(targetType, value.getClass());
   }
 }
 public Object coerce(LuaValue value) {
   switch (value.type()) {
     case LuaValue.TTABLE:
       {
         int n = value.length();
         Object a = Array.newInstance(componentType, n);
         for (int i = 0; i < n; i++) Array.set(a, i, componentCoercion.coerce(value.get(i + 1)));
         return a;
       }
     case LuaValue.TUSERDATA:
       return value.touserdata();
     case LuaValue.TNIL:
       return null;
     default:
       return null;
   }
 }
 public Object coerce(LuaValue value) {
   switch (value.type()) {
     case LuaValue.TNUMBER:
       return value.isint()
           ? (Object) new Integer(value.toint())
           : (Object) new Double(value.todouble());
     case LuaValue.TBOOLEAN:
       return value.toboolean() ? Boolean.TRUE : Boolean.FALSE;
     case LuaValue.TSTRING:
       return value.tojstring();
     case LuaValue.TUSERDATA:
       return value.optuserdata(targetType, null);
     case LuaValue.TNIL:
       return null;
     default:
       return value;
   }
 }
 public Object coerce(LuaValue value) {
   switch (targetType) {
     case TARGET_TYPE_BYTE:
       return new Byte((byte) value.toint());
     case TARGET_TYPE_CHAR:
       return new Character((char) value.toint());
     case TARGET_TYPE_SHORT:
       return new Short((short) value.toint());
     case TARGET_TYPE_INT:
       return new Integer((int) value.toint());
     case TARGET_TYPE_LONG:
       return new Long((long) value.todouble());
     case TARGET_TYPE_FLOAT:
       return new Float((float) value.todouble());
     case TARGET_TYPE_DOUBLE:
       return new Double((double) value.todouble());
     default:
       return null;
   }
 }
 public Object coerce(LuaValue value) {
   return value.toboolean() ? Boolean.TRUE : Boolean.FALSE;
 }
 public int score(LuaValue value) {
   int fromStringPenalty = 0;
   if (value.type() == LuaValue.TSTRING) {
     value = value.tonumber();
     if (value.isnil()) {
       return SCORE_UNCOERCIBLE;
     }
     fromStringPenalty = 4;
   }
   if (value.isint()) {
     switch (targetType) {
       case TARGET_TYPE_BYTE:
         {
           int i = value.toint();
           return fromStringPenalty + ((i == (byte) i) ? 0 : SCORE_WRONG_TYPE);
         }
       case TARGET_TYPE_CHAR:
         {
           int i = value.toint();
           return fromStringPenalty
               + ((i == (byte) i) ? 1 : (i == (char) i) ? 0 : SCORE_WRONG_TYPE);
         }
       case TARGET_TYPE_SHORT:
         {
           int i = value.toint();
           return fromStringPenalty
               + ((i == (byte) i) ? 1 : (i == (short) i) ? 0 : SCORE_WRONG_TYPE);
         }
       case TARGET_TYPE_INT:
         {
           int i = value.toint();
           return fromStringPenalty
               + ((i == (byte) i) ? 2 : ((i == (char) i) || (i == (short) i)) ? 1 : 0);
         }
       case TARGET_TYPE_FLOAT:
         return fromStringPenalty + 1;
       case TARGET_TYPE_LONG:
         return fromStringPenalty + 1;
       case TARGET_TYPE_DOUBLE:
         return fromStringPenalty + 2;
       default:
         return SCORE_WRONG_TYPE;
     }
   } else if (value.isnumber()) {
     switch (targetType) {
       case TARGET_TYPE_BYTE:
         return SCORE_WRONG_TYPE;
       case TARGET_TYPE_CHAR:
         return SCORE_WRONG_TYPE;
       case TARGET_TYPE_SHORT:
         return SCORE_WRONG_TYPE;
       case TARGET_TYPE_INT:
         return SCORE_WRONG_TYPE;
       case TARGET_TYPE_LONG:
         {
           double d = value.todouble();
           return fromStringPenalty + ((d == (long) d) ? 0 : SCORE_WRONG_TYPE);
         }
       case TARGET_TYPE_FLOAT:
         {
           double d = value.todouble();
           return fromStringPenalty + ((d == (float) d) ? 0 : SCORE_WRONG_TYPE);
         }
       case TARGET_TYPE_DOUBLE:
         {
           double d = value.todouble();
           return fromStringPenalty + (((d == (long) d) || (d == (float) d)) ? 1 : 0);
         }
       default:
         return SCORE_WRONG_TYPE;
     }
   } else {
     return SCORE_UNCOERCIBLE;
   }
 }