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.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.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 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;
   }
 }