| package li.cil.oc.util |
| |
| import li.cil.oc.OpenComputers |
| import li.cil.oc.Settings |
| import li.cil.oc.api.machine.Value |
| import li.cil.repack.org.luaj.vm2.LuaString |
| import li.cil.repack.org.luaj.vm2.LuaValue |
| import li.cil.repack.org.luaj.vm2.Varargs |
| import li.cil.repack.org.luaj.vm2.lib.VarArgFunction |
| |
| import scala.collection.convert.WrapAsScala._ |
| import scala.collection.mutable |
| import scala.language.implicitConversions |
| import scala.math.ScalaNumber |
| import scala.runtime.BoxedUnit |
| |
| class ScalaClosure(val f: (Varargs) => Varargs) extends VarArgFunction { |
| override def invoke(args: Varargs) = f(args) |
| } |
| |
| object ScalaClosure { |
| implicit def wrapClosure(f: (Varargs) => LuaValue): ScalaClosure = new ScalaClosure(args => f(args) match { |
| case varargs: Varargs => varargs |
| case LuaValue.NONE => LuaValue.NONE |
| case result => LuaValue.varargsOf(Array(result)) |
| }) |
| |
| implicit def wrapVarArgClosure(f: (Varargs) => Varargs): ScalaClosure = new ScalaClosure(f) |
| |
| def toLuaValue(value: Any): LuaValue = { |
| (value match { |
| case number: ScalaNumber => number.underlying |
| case reference: AnyRef => reference |
| case null => null |
| case primitive => primitive.asInstanceOf[AnyRef] |
| }) match { |
| case null | Unit | _: BoxedUnit => LuaValue.NIL |
| case value: java.lang.Boolean => LuaValue.valueOf(value.booleanValue) |
| case value: java.lang.Byte => LuaValue.valueOf(value.byteValue) |
| case value: java.lang.Character => LuaValue.valueOf(String.valueOf(value)) |
| case value: java.lang.Short => LuaValue.valueOf(value.shortValue) |
| case value: java.lang.Integer => LuaValue.valueOf(value.intValue) |
| case value: java.lang.Long => LuaValue.valueOf(value.longValue) |
| case value: java.lang.Float => LuaValue.valueOf(value.floatValue) |
| case value: java.lang.Double => LuaValue.valueOf(value.doubleValue) |
| case value: java.lang.String => LuaValue.valueOf(value) |
| case value: Array[Byte] => LuaValue.valueOf(value) |
| case value: Array[_] => toLuaList(value) |
| case value: Value if Settings.get.allowUserdata => LuaValue.userdataOf(value) |
| case value: Product => toLuaList(value.productIterator.toIterable) |
| case value: Seq[_] => toLuaList(value) |
| case value: java.util.Map[_, _] => toLuaTable(value.toMap) |
| case value: Map[_, _] => toLuaTable(value) |
| case value: mutable.Map[_, _] => toLuaTable(value.toMap) |
| case _ => |
| OpenComputers.log.warn("Tried to push an unsupported value of type to Lua: " + value.getClass.getName + ".") |
| LuaValue.NIL |
| } |
| } |
| |
| def toLuaList(value: Iterable[Any]): LuaValue = { |
| val table = LuaValue.listOf(value.map(toLuaValue).toArray) |
| table.set("n", table.length()) |
| table |
| } |
| |
| def toLuaTable(value: Map[_, _]): LuaValue = { |
| LuaValue.tableOf(value.flatMap { |
| case (k, v) => Seq(toLuaValue(k), toLuaValue(v)) |
| }.toArray) |
| } |
| |
| def toSimpleJavaObject(value: LuaValue): AnyRef = value.`type`() match { |
| case LuaValue.TBOOLEAN => Boolean.box(value.toboolean()) |
| case LuaValue.TNUMBER => Double.box(value.todouble()) |
| case LuaValue.TSTRING => value match { |
| case s: LuaString => s.m_bytes.slice(s.m_offset, s.m_offset + s.m_length) |
| case _ => value.tojstring() // Waddafaq? |
| } |
| case LuaValue.TTABLE => |
| val table = value.checktable() |
| table.keys.map(key => toSimpleJavaObject(key) -> toSimpleJavaObject(table.get(key))).toMap |
| case LuaValue.TUSERDATA => value.touserdata() |
| case _ => null |
| } |
| |
| def toSimpleJavaObjects(args: Varargs, start: Int = 1) = |
| for (index <- start to args.narg()) yield toSimpleJavaObject(args.arg(index)) |
| } |