Decompiled source of Lumod v1.1.0

Mods/lumod.dll

Decompiled 3 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BoneLib;
using BoneLib.BoneMenu;
using BoneLib.Notifications;
using Il2CppSLZ.Marrow;
using Il2CppSLZ.Marrow.Data;
using Il2CppSLZ.Marrow.SceneStreaming;
using Il2CppSLZ.Marrow.Warehouse;
using LabFusion.RPC;
using MelonLoader;
using MelonLoader.Utils;
using MoonSharp.Interpreter;
using MoonSharp.Interpreter.Interop;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.InputSystem.Utilities;
using UnityEngine.SceneManagement;
using lumod;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("Lua modding!!!")]
[assembly: AssemblyDescription("Lua modding!!!")]
[assembly: AssemblyCompany("mc")]
[assembly: AssemblyProduct("Lumod")]
[assembly: AssemblyCopyright("Developed by dc@mei_dot_com")]
[assembly: AssemblyTrademark("mc")]
[assembly: AssemblyFileVersion("1.0.0")]
[assembly: MelonInfo(typeof(Main), "Lumod", "1.0.0", "dc@mei_dot_com", "Link")]
[assembly: MelonColor(0, 255, 255, 255)]
[assembly: MelonGame("Stress Level Zero", "BONELAB")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace lumod;

internal class Main : MelonMod
{
	internal static class LumodMenu
	{
		public static void CreateElements()
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			Page val = Page.Root.CreatePage("_Lumod", Color.cyan, 0, true);
			Page val2 = val.CreatePage("How do I use this?", Color.white, 0, true);
			val2.CreateFunction("RIGHT MENU + RIGHT A + LEFT MENU to reload lua.", Color.white, (Action)null);
			val2.CreateFunction("If on flatplayer, press L to reload lua.", Color.white, (Action)null);
			string text = Path.Combine(MelonEnvironment.UserDataDirectory, "Lumod");
			Directory.CreateDirectory(text);
			string[] files = Directory.GetFiles(text, "*.lua");
			foreach (string text2 in files)
			{
				scriptPages[text2] = val.CreatePage(text2.Replace(text, ""), Color.white, 0, true);
			}
		}
	}

	public static class Vec
	{
		public static Table ToTable(Script s, Vector3 v)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Expected O, but got Unknown
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Invalid comparison between Unknown and I4
			Table val = new Table(s);
			val[(object)"x"] = v.x;
			val[(object)"y"] = v.y;
			val[(object)"z"] = v.z;
			DynValue val2 = s.Globals.Get("_VEC_MT");
			if ((int)val2.Type == 6)
			{
				val.MetaTable = val2.Table;
			}
			return val;
		}

		public static Vector3 ToVector(Table v)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			return new Vector3((float)v[(object)"x"], (float)v[(object)"y"], (float)v[(object)"z"]);
		}
	}

	[MoonSharpUserData]
	public class RigidBodyApi
	{
		private readonly Script script;

		private readonly Rigidbody rb;

		public bool isKinematic
		{
			get
			{
				return !((Object)(object)rb == (Object)null) && rb.isKinematic;
			}
			set
			{
				if ((Object)(object)rb != (Object)null)
				{
					rb.isKinematic = value;
				}
			}
		}

		public Table Velocity
		{
			get
			{
				//IL_001c: Unknown result type (might be due to invalid IL or missing references)
				if ((Object)(object)rb == (Object)null)
				{
					return null;
				}
				return ToVecTable(rb.velocity);
			}
			set
			{
				//IL_0055: Unknown result type (might be due to invalid IL or missing references)
				if (!((Object)(object)rb == (Object)null) && value != null)
				{
					rb.velocity = new Vector3((float)value.Get("x").Number, (float)value.Get("y").Number, (float)value.Get("z").Number);
				}
			}
		}

		public Table AngVel
		{
			get
			{
				//IL_001c: Unknown result type (might be due to invalid IL or missing references)
				if ((Object)(object)rb == (Object)null)
				{
					return null;
				}
				return ToVecTable(rb.angularVelocity);
			}
			set
			{
				//IL_0055: Unknown result type (might be due to invalid IL or missing references)
				if (!((Object)(object)rb == (Object)null) && value != null)
				{
					rb.angularVelocity = new Vector3((float)value.Get("x").Number, (float)value.Get("y").Number, (float)value.Get("z").Number);
				}
			}
		}

		public RigidBodyApi(Script script, Rigidbody rb)
		{
			this.script = script;
			this.rb = rb;
		}

		public void Destroy()
		{
			if (!((Object)(object)rb == (Object)null))
			{
				Object.Destroy((Object)(object)rb);
			}
		}

		private Table ToVecTable(Vector3 v)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			return Vec.ToTable(script, v);
		}
	}

	[MoonSharpUserData]
	public class ObjectApi
	{
		private readonly Script script;

		private readonly GameObject go;

		public string Name
		{
			get
			{
				return ((Object)(object)go == (Object)null) ? null : ((Object)go).name;
			}
			set
			{
				if ((Object)(object)go != (Object)null)
				{
					((Object)go).name = value;
				}
			}
		}

		public int Layer
		{
			get
			{
				return ((Object)(object)go == (Object)null) ? (-1) : go.layer;
			}
			set
			{
				if ((Object)(object)go != (Object)null)
				{
					go.layer = value;
				}
			}
		}

		public string LayerName => LayerMask.LayerToName(go.layer);

		public RigidBodyApi Rigidbody => ((Object)(object)go.GetComponent<Rigidbody>() == (Object)null) ? null : new RigidBodyApi(script, go.GetComponent<Rigidbody>());

		public Table MatColor
		{
			get
			{
				//IL_0037: Unknown result type (might be due to invalid IL or missing references)
				//IL_0047: Unknown result type (might be due to invalid IL or missing references)
				//IL_0057: Unknown result type (might be due to invalid IL or missing references)
				//IL_0061: Unknown result type (might be due to invalid IL or missing references)
				if ((Object)(object)go == (Object)null)
				{
					return null;
				}
				Renderer component = go.GetComponent<Renderer>();
				if ((Object)(object)component == (Object)null)
				{
					return null;
				}
				return ToVecTable(new Vector3(component.material.color.r, component.material.color.g, component.material.color.b));
			}
			set
			{
				//IL_006a: Unknown result type (might be due to invalid IL or missing references)
				if (!((Object)(object)go == (Object)null))
				{
					Renderer component = go.GetComponent<Renderer>();
					if (!((Object)(object)component == (Object)null))
					{
						component.material.color = new Color((float)value.Get("x").Number, (float)value.Get("y").Number, (float)value.Get("z").Number, 1f);
					}
				}
			}
		}

		public ObjectApi Parent
		{
			get
			{
				if ((Object)(object)go == (Object)null || (Object)(object)go.transform.parent == (Object)null)
				{
					return null;
				}
				return new ObjectApi(script, ((Component)go.transform.parent).gameObject);
			}
		}

		public ObjectApi Root
		{
			get
			{
				if ((Object)(object)go == (Object)null)
				{
					return null;
				}
				return new ObjectApi(script, ((Component)go.transform.root).gameObject);
			}
		}

		public Table Children
		{
			get
			{
				//IL_001b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0021: Expected O, but got Unknown
				if ((Object)(object)go == (Object)null)
				{
					return null;
				}
				Table val = new Table(script);
				for (int i = 0; i < go.transform.childCount; i++)
				{
					val.Append(DynValue.FromObject(script, (object)new ObjectApi(script, ((Component)go.transform.GetChild(i)).gameObject)));
				}
				return val;
			}
		}

		public Table Forward => ((Object)(object)go == (Object)null) ? null : ToVecTable(go.transform.forward);

		public Table Right => ((Object)(object)go == (Object)null) ? null : ToVecTable(go.transform.right);

		public Table Position
		{
			get
			{
				//IL_001a: Unknown result type (might be due to invalid IL or missing references)
				return ((Object)(object)go == (Object)null) ? null : ToVecTable(go.transform.position);
			}
			set
			{
				//IL_0060: Unknown result type (might be due to invalid IL or missing references)
				if (!((Object)(object)go == (Object)null) && value != null)
				{
					float num = (float)value.Get("x").Number;
					float num2 = (float)value.Get("y").Number;
					float num3 = (float)value.Get("z").Number;
					go.transform.position = new Vector3(num, num2, num3);
				}
			}
		}

		public Table Rotation
		{
			get
			{
				//IL_001a: Unknown result type (might be due to invalid IL or missing references)
				return ((Object)(object)go == (Object)null) ? null : ToVecTable(go.transform.eulerAngles);
			}
			set
			{
				//IL_0060: Unknown result type (might be due to invalid IL or missing references)
				if (!((Object)(object)go == (Object)null) && value != null)
				{
					float num = (float)value.Get("x").Number;
					float num2 = (float)value.Get("y").Number;
					float num3 = (float)value.Get("z").Number;
					go.transform.eulerAngles = new Vector3(num, num2, num3);
				}
			}
		}

		public Table LocalScale
		{
			get
			{
				//IL_001a: Unknown result type (might be due to invalid IL or missing references)
				return ((Object)(object)go == (Object)null) ? null : ToVecTable(go.transform.localScale);
			}
			set
			{
				//IL_0060: Unknown result type (might be due to invalid IL or missing references)
				if (!((Object)(object)go == (Object)null) && value != null)
				{
					float num = (float)value.Get("x").Number;
					float num2 = (float)value.Get("y").Number;
					float num3 = (float)value.Get("z").Number;
					go.transform.localScale = new Vector3(num, num2, num3);
				}
			}
		}

		public override string ToString()
		{
			return ((Object)(object)go == (Object)null) ? "ObjectApi(dead)" : ("ObjectApi(" + ((Object)go).name + ")");
		}

		public ObjectApi(Script script, GameObject go)
		{
			this.script = script;
			this.go = go;
		}

		public void Destroy()
		{
			if (!((Object)(object)go == (Object)null))
			{
				Object.Destroy((Object)(object)go);
			}
		}

		public ObjectApi FindChild(string name)
		{
			return new ObjectApi(script, ((Component)go.transform.Find(name)).gameObject);
		}

		private Table ToVecTable(Vector3 v)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			return Vec.ToTable(script, v);
		}
	}

	[MoonSharpUserData]
	public class CameraApi
	{
		private readonly Script script;

		private readonly Camera camera;

		public ObjectApi GameObject => new ObjectApi(script, ((Component)camera).gameObject);

		public int CullingMask
		{
			get
			{
				return camera.cullingMask;
			}
			set
			{
				camera.cullingMask = value;
			}
		}

		public Table BackgroundColor
		{
			get
			{
				//IL_0007: Unknown result type (might be due to invalid IL or missing references)
				//IL_0012: Unknown result type (might be due to invalid IL or missing references)
				//IL_001a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0035: Unknown result type (might be due to invalid IL or missing references)
				//IL_003d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0058: Unknown result type (might be due to invalid IL or missing references)
				//IL_0060: Unknown result type (might be due to invalid IL or missing references)
				//IL_0076: Expected O, but got Unknown
				return new Table(script)
				{
					[(object)"x"] = camera.backgroundColor.r,
					[(object)"y"] = camera.backgroundColor.g,
					[(object)"z"] = camera.backgroundColor.b
				};
			}
			set
			{
				//IL_004a: Unknown result type (might be due to invalid IL or missing references)
				if (value != null)
				{
					float num = (float)value.Get("x").Number;
					float num2 = (float)value.Get("y").Number;
					float num3 = (float)value.Get("z").Number;
					camera.backgroundColor = new Color(num, num2, num3);
				}
			}
		}

		public int ClearFlags
		{
			get
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_000c: Expected I4, but got Unknown
				return (int)camera.clearFlags;
			}
			set
			{
				camera.clearFlags = (CameraClearFlags)value;
			}
		}

		public CameraApi(Script script, Camera camera)
		{
			this.script = script;
			this.camera = camera;
		}
	}

	[MoonSharpUserData]
	public class PlayerApi
	{
		private readonly Script script;

		public CameraApi MainCamera
		{
			get
			{
				Camera componentInChildren = ((Component)Player.ControllerRig).gameObject.GetComponentInChildren<Camera>();
				if ((Object)(object)componentInChildren == (Object)null)
				{
					return null;
				}
				return new CameraApi(script, componentInChildren);
			}
		}

		public CameraApi SpectatorCamera
		{
			get
			{
				Camera componentInChildren = GameObject.Find("GameplaySystems [0]/DisabledContainer/Spectator Camera/").GetComponentInChildren<Camera>();
				if ((Object)(object)componentInChildren == (Object)null)
				{
					return null;
				}
				return new CameraApi(script, componentInChildren);
			}
		}

		public ObjectApi RigManager => new ObjectApi(script, ((Component)Player.RigManager).gameObject);

		public ObjectApi PhysicsRig => new ObjectApi(script, ((Component)Player.PhysicsRig).gameObject);

		public float Health
		{
			get
			{
				if ((Object)(object)Player.RigManager.health == (Object)null)
				{
					return 1f;
				}
				return Player.RigManager.health.curr_Health;
			}
			set
			{
				if (value > 0f)
				{
					Player.RigManager.health.alive = true;
					Player.RigManager.health.deathIsImminent = false;
					Player.RigManager.health.Respawn();
				}
				Player.RigManager.health.curr_Health = value;
			}
		}

		public float MaxHealth
		{
			get
			{
				if ((Object)(object)Player.RigManager.health == (Object)null)
				{
					return 1f;
				}
				return Player.RigManager.health.max_Health;
			}
			set
			{
				Player.RigManager.health.max_Health = value;
			}
		}

		public ObjectApi RightHand
		{
			get
			{
				Hand rightHand = Player.RightHand;
				if ((Object)(object)rightHand == (Object)null)
				{
					return null;
				}
				return new ObjectApi(script, ((Component)rightHand).gameObject);
			}
		}

		public ObjectApi LeftHand
		{
			get
			{
				Hand leftHand = Player.LeftHand;
				if ((Object)(object)leftHand == (Object)null)
				{
					return null;
				}
				return new ObjectApi(script, ((Component)leftHand).gameObject);
			}
		}

		public ObjectApi Head
		{
			get
			{
				Transform head = Player.Head;
				if ((Object)(object)head == (Object)null)
				{
					return null;
				}
				return new ObjectApi(script, ((Component)head).gameObject);
			}
		}

		public ObjectApi Chest
		{
			get
			{
				Transform chest = Player.Chest;
				if ((Object)(object)chest == (Object)null)
				{
					return null;
				}
				return new ObjectApi(script, ((Component)chest).gameObject);
			}
		}

		public ObjectApi Pelvis
		{
			get
			{
				Transform pelvis = ((Rig)Player.PhysicsRig).m_pelvis;
				if ((Object)(object)pelvis == (Object)null)
				{
					return null;
				}
				return new ObjectApi(script, ((Component)pelvis).gameObject);
			}
		}

		public ObjectApi Feet
		{
			get
			{
				GameObject feet = Player.PhysicsRig.feet;
				if ((Object)(object)feet == (Object)null)
				{
					return null;
				}
				return new ObjectApi(script, feet.gameObject);
			}
		}

		public ObjectApi LeftShoulder
		{
			get
			{
				Transform shoulderLf = ((Rig)Player.PhysicsRig).m_shoulderLf;
				if ((Object)(object)shoulderLf == (Object)null)
				{
					return null;
				}
				return new ObjectApi(script, ((Component)shoulderLf).gameObject);
			}
		}

		public ObjectApi RightShoulder
		{
			get
			{
				Transform shoulderRt = ((Rig)Player.PhysicsRig).m_shoulderRt;
				if ((Object)(object)shoulderRt == (Object)null)
				{
					return null;
				}
				return new ObjectApi(script, ((Component)shoulderRt).gameObject);
			}
		}

		public ObjectApi LeftElbow
		{
			get
			{
				Transform elbowLf = ((Rig)Player.PhysicsRig).m_elbowLf;
				if ((Object)(object)elbowLf == (Object)null)
				{
					return null;
				}
				return new ObjectApi(script, ((Component)elbowLf).gameObject);
			}
		}

		public ObjectApi RightElbow
		{
			get
			{
				Transform elbowRt = ((Rig)Player.PhysicsRig).m_elbowRt;
				if ((Object)(object)elbowRt == (Object)null)
				{
					return null;
				}
				return new ObjectApi(script, ((Component)elbowRt).gameObject);
			}
		}

		public ObjectApi LeftHip
		{
			get
			{
				Transform hipLf = ((Rig)Player.PhysicsRig).m_hipLf;
				if ((Object)(object)hipLf == (Object)null)
				{
					return null;
				}
				return new ObjectApi(script, ((Component)hipLf).gameObject);
			}
		}

		public ObjectApi RightHip
		{
			get
			{
				Transform hipRt = ((Rig)Player.PhysicsRig).m_hipRt;
				if ((Object)(object)hipRt == (Object)null)
				{
					return null;
				}
				return new ObjectApi(script, ((Component)hipRt).gameObject);
			}
		}

		public ObjectApi LeftKnee
		{
			get
			{
				Transform kneeLf = ((Rig)Player.PhysicsRig).m_kneeLf;
				if ((Object)(object)kneeLf == (Object)null)
				{
					return null;
				}
				return new ObjectApi(script, ((Component)kneeLf).gameObject);
			}
		}

		public ObjectApi RightKnee
		{
			get
			{
				Transform kneeRt = ((Rig)Player.PhysicsRig).m_kneeRt;
				if ((Object)(object)kneeRt == (Object)null)
				{
					return null;
				}
				return new ObjectApi(script, ((Component)kneeRt).gameObject);
			}
		}

		public ObjectApi LeftFoot
		{
			get
			{
				Transform footLf = ((Rig)Player.PhysicsRig).m_footLf;
				if ((Object)(object)footLf == (Object)null)
				{
					return null;
				}
				return new ObjectApi(script, ((Component)footLf).gameObject);
			}
		}

		public ObjectApi RightFoot
		{
			get
			{
				Transform footRt = ((Rig)Player.PhysicsRig).m_footRt;
				if ((Object)(object)footRt == (Object)null)
				{
					return null;
				}
				return new ObjectApi(script, ((Component)footRt).gameObject);
			}
		}

		public PlayerApi(Script script)
		{
			this.script = script;
		}

		public void Revive()
		{
			Player.RigManager.health.Respawn();
		}

		public void Teleport(Table pos)
		{
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			if (pos != null && !((Object)(object)Player.RigManager == (Object)null))
			{
				float num = (float)pos.Get("x").Number;
				float num2 = (float)pos.Get("y").Number;
				float num3 = (float)pos.Get("z").Number;
				Player.RigManager.Teleport(new Vector3(num, num2, num3), true);
			}
		}
	}

	[MoonSharpUserData]
	public class InputApi
	{
		private readonly Script script;

		public InputApi(Script script)
		{
			this.script = script;
		}

		public bool KeyDown(string name)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			Keyboard current = Keyboard.current;
			if (current == null)
			{
				return false;
			}
			if (!Enum.TryParse<Key>(name, ignoreCase: true, out Key result))
			{
				return false;
			}
			return ((ButtonControl)current[result]).wasPressedThisFrame;
		}

		public bool KeyHeld(string name)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			Keyboard current = Keyboard.current;
			if (current == null)
			{
				return false;
			}
			if (!Enum.TryParse<Key>(name, ignoreCase: true, out Key result))
			{
				return false;
			}
			return ((ButtonControl)current[result]).isPressed;
		}

		public string CurrentKey()
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			Keyboard current = Keyboard.current;
			if (current == null)
			{
				return null;
			}
			Enumerator<KeyControl> enumerator = current.allKeys.GetEnumerator();
			while (enumerator.MoveNext())
			{
				KeyControl current2 = enumerator.Current;
				if (((ButtonControl)current2).isPressed)
				{
					return ((object)current2.keyCode/*cast due to .constrained prefix*/).ToString();
				}
			}
			return null;
		}

		public bool RightMenuDown()
		{
			return (Object)(object)Player.RightHand != (Object)null && Player.RightController.GetBButtonDown();
		}

		public bool RightMenuHeld()
		{
			return (Object)(object)Player.RightController != (Object)null && Player.RightController.GetBButton();
		}

		public bool LeftMenuDown()
		{
			return (Object)(object)Player.LeftController != (Object)null && Player.LeftController.GetBButtonDown();
		}

		public bool LeftMenuHeld()
		{
			return (Object)(object)Player.LeftController != (Object)null && Player.LeftController.GetBButton();
		}

		public bool RightADown()
		{
			return (Object)(object)Player.RightController != (Object)null && Player.RightController.GetAButtonDown();
		}

		public bool RightAHeld()
		{
			return (Object)(object)Player.RightController != (Object)null && Player.RightController.GetAButton();
		}

		public bool LeftADown()
		{
			return (Object)(object)Player.LeftController != (Object)null && Player.LeftController.GetAButtonDown();
		}

		public bool LeftAHeld()
		{
			return (Object)(object)Player.LeftController != (Object)null && Player.LeftController.GetAButton();
		}

		public bool RightStickDown()
		{
			return (Object)(object)Player.RightController != (Object)null && Player.RightController.GetThumbStickDown();
		}

		public bool LeftStickDown()
		{
			return (Object)(object)Player.LeftController != (Object)null && Player.LeftController.GetThumbStickDown();
		}

		public Table RightStickAxis()
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Expected O, but got Unknown
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Player.RightController == (Object)null)
			{
				return null;
			}
			Vector2 thumbStickAxis = Player.RightController.GetThumbStickAxis();
			Table val = new Table(script);
			val[(object)"x"] = thumbStickAxis.x;
			val[(object)"y"] = thumbStickAxis.y;
			return val;
		}

		public Table LeftStickAxis()
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Expected O, but got Unknown
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Player.LeftController == (Object)null)
			{
				return null;
			}
			Vector2 thumbStickAxis = Player.LeftController.GetThumbStickAxis();
			Table val = new Table(script);
			val[(object)"x"] = thumbStickAxis.x;
			val[(object)"y"] = thumbStickAxis.y;
			return val;
		}

		public bool RightTriggerDown()
		{
			return (Object)(object)Player.RightController != (Object)null && Player.RightHand._indexButtonDown;
		}

		public bool LeftTriggerDown()
		{
			return (Object)(object)Player.LeftController != (Object)null && Player.LeftHand._indexButtonDown;
		}

		public float RightTriggerValue()
		{
			return ((Object)(object)Player.RightController != (Object)null) ? Player.RightHand._indexTriggerAxis : 0f;
		}

		public float LeftTriggerValue()
		{
			return ((Object)(object)Player.LeftController != (Object)null) ? Player.LeftHand._indexTriggerAxis : 0f;
		}
	}

	[MoonSharpUserData]
	public class DebugApi
	{
		private readonly Script script;

		public DebugApi(Script script)
		{
			this.script = script;
		}

		public ObjectApi DrawLine(Table fromt, Table tot, Table color, float alpha = 1f, float startWidth = 0.01f, float endWidth = 0.01f)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Expected O, but got Unknown
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Expected O, but got Unknown
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = ToVector3(fromt);
			Vector3 val2 = ToVector3(tot);
			Color val3 = default(Color);
			((Color)(ref val3))..ctor((float)color.Get("x").Number, (float)color.Get("y").Number, (float)color.Get("z").Number, alpha);
			GameObject val4 = new GameObject("DebugLine");
			LineRenderer val5 = val4.AddComponent<LineRenderer>();
			val5.positionCount = 2;
			val5.useWorldSpace = true;
			val5.startWidth = startWidth;
			val5.endWidth = endWidth;
			((Renderer)val5).material = new Material(Shader.Find("Sprites/Default"));
			Color startColor = (val5.endColor = val3);
			val5.startColor = startColor;
			val5.SetPosition(0, val);
			val5.SetPosition(1, val2);
			return new ObjectApi(script, val4);
		}

		public ObjectApi DrawSphere(Table pos, Table size, Table color, float alpha = 1f)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Expected O, but got Unknown
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = GameObject.CreatePrimitive((PrimitiveType)0);
			((Collider)val.GetComponent<SphereCollider>()).enabled = false;
			val.transform.position = ToVector3(pos);
			val.transform.localScale = ToVector3(size);
			Renderer component = val.GetComponent<Renderer>();
			component.material = new Material(Shader.Find("UI/Default"));
			component.material.color = new Color((float)color.Get("x").Number, (float)color.Get("y").Number, (float)color.Get("z").Number, alpha);
			return new ObjectApi(script, val);
		}
	}

	[MoonSharpUserData]
	public class CrateApi
	{
		private readonly Script script;

		public CrateApi(Script script)
		{
			this.script = script;
		}

		public void Spawn(string barcode, Table pos, Table rotation, DynValue spawnCallback = null)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			//IL_003b: Expected O, but got Unknown
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			Action<ObjectApi> onSpawned = delegate(ObjectApi obj)
			{
				//IL_004a: Expected O, but got Unknown
				//IL_000f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0015: Invalid comparison between Unknown and I4
				if (spawnCallback == null || (int)spawnCallback.Type != 5)
				{
					return;
				}
				try
				{
					script.Call(spawnCallback, new object[1] { obj });
				}
				catch (ScriptRuntimeException ex)
				{
					ScriptRuntimeException ex2 = ex;
					MelonLogger.Error(((InterpreterException)ex2).DecoratedMessage);
				}
			};
			Spawnable spawnable = new Spawnable
			{
				crateRef = new SpawnableCrateReference(barcode)
			};
			NetworkAssetSpawner.Spawn(new SpawnRequestInfo
			{
				Spawnable = spawnable,
				Position = ToVector3(pos),
				Rotation = Quaternion.Euler(ToVector3(rotation)),
				SpawnCallback = delegate(SpawnCallbackInfo info)
				{
					//IL_0009: Unknown result type (might be due to invalid IL or missing references)
					//IL_004c: Unknown result type (might be due to invalid IL or missing references)
					if (onSpawned != null && (Object)(object)info.Spawned != (Object)null)
					{
						script.Call((object)onSpawned, new object[1] { DynValue.FromObject(script, (object)new ObjectApi(script, info.Spawned)) });
					}
				}
			});
		}
	}

	[MoonSharpUserData]
	public class MelonPageApi
	{
		private readonly Script script;

		private readonly Page page;

		public MelonPageApi(Script script, Page page)
		{
			this.script = script;
			this.page = page;
		}

		public void CreateFunction(string name, Table color, DynValue callback)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Invalid comparison between Unknown and I4
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			if (callback == null || (int)callback.Type != 5)
			{
				return;
			}
			Color val = default(Color);
			((Color)(ref val))..ctor((float)color.Get("x").Number, (float)color.Get("y").Number, (float)color.Get("z").Number);
			page.CreateFunction(name, val, (Action)delegate
			{
				//IL_001d: Expected O, but got Unknown
				try
				{
					script.Call(callback);
				}
				catch (ScriptRuntimeException ex)
				{
					ScriptRuntimeException ex2 = ex;
					MelonLogger.Error(((InterpreterException)ex2).DecoratedMessage);
				}
			});
			if (page.Color == Color.white)
			{
				page.Color = Color.cyan;
			}
		}
	}

	internal const string Name = "Lumod";

	internal const string Description = "Lua modding!!!";

	internal const string Author = "dc@mei_dot_com";

	internal const string Company = "mc";

	internal const string Version = "1.0.0";

	internal const string DownloadLink = "Link";

	private List<DynValue> updateHandlers = new List<DynValue>();

	private List<DynValue> fixedUpdateHandlers = new List<DynValue>();

	private List<DynValue> sceneHandlers = new List<DynValue>();

	private List<DynValue> keyHandlers = new List<DynValue>();

	private static Dictionary<string, Page> scriptPages = new Dictionary<string, Page>();

	private bool done = false;

	public static Vector3 ToVector3(Table t)
	{
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		return new Vector3((float)t.Get("x").Number, (float)t.Get("y").Number, (float)t.Get("z").Number);
	}

	public override void OnEarlyInitializeMelon()
	{
		((MelonBase)this).OnEarlyInitializeMelon();
	}

	private void LoadScripts()
	{
		//IL_005e: Expected O, but got Unknown
		string path = Path.Combine(MelonEnvironment.UserDataDirectory, "Lumod");
		Directory.CreateDirectory(path);
		string[] files = Directory.GetFiles(path, "*.lua");
		foreach (string text in files)
		{
			MelonLogger.Msg("Loading " + text);
			Script val = MakeScript(text);
			try
			{
				val.DoString(File.ReadAllText(text), (Table)null, text);
			}
			catch (InterpreterException ex)
			{
				InterpreterException ex2 = ex;
				MelonLogger.Error("[" + text + "]\n" + ex2.DecoratedMessage);
			}
		}
	}

	public Table Raycast(Script s, Vector3 origin, Vector3 direction, float distance, int layerMask = -1)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: Expected O, but got Unknown
		//IL_005e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0099: Unknown result type (might be due to invalid IL or missing references)
		RaycastHit val = default(RaycastHit);
		if (Physics.Raycast(origin, direction, ref val, distance, layerMask))
		{
			ObjectApi objectApi = new ObjectApi(s, ((Component)((RaycastHit)(ref val)).collider).gameObject);
			Table val2 = new Table(s);
			val2[(object)"obj"] = objectApi;
			val2[(object)"distance"] = ((RaycastHit)(ref val)).distance;
			val2[(object)"point"] = Vec.ToTable(s, ((RaycastHit)(ref val)).point);
			val2[(object)"layer"] = ((Component)((RaycastHit)(ref val)).collider).gameObject.layer;
			val2[(object)"normal"] = Vec.ToTable(s, ((RaycastHit)(ref val)).normal);
			return val2;
		}
		return null;
	}

	public override void OnInitializeMelon()
	{
		((MelonBase)this).OnInitializeMelon();
	}

	private Script MakeScript(string file)
	{
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Expected O, but got Unknown
		Script scr = new Script();
		scr.Globals[(object)"player"] = new PlayerApi(scr);
		scr.Globals[(object)"page"] = new MelonPageApi(scr, scriptPages[file]);
		scr.Globals[(object)"crate"] = new CrateApi(scr);
		scr.Globals[(object)"debug"] = new DebugApi(scr);
		scr.Globals[(object)"input"] = new InputApi(scr);
		scr.Globals[(object)"player"] = new PlayerApi(scr);
		scr.Globals[(object)"onUpdate"] = (Action<DynValue>)delegate(DynValue fn)
		{
			updateHandlers.Add(fn);
		};
		scr.Globals[(object)"onKeyDown"] = (Action<DynValue>)delegate(DynValue fn)
		{
			keyHandlers.Add(fn);
		};
		scr.Globals[(object)"onSceneWasLoaded"] = (Action<DynValue>)delegate(DynValue fn)
		{
			sceneHandlers.Add(fn);
		};
		scr.Globals[(object)"print"] = DynValue.NewCallback((Func<ScriptExecutionContext, CallbackArguments, DynValue>)delegate(ScriptExecutionContext ctx, CallbackArguments args)
		{
			List<string> list = new List<string>();
			string oldValue = Path.Combine(MelonEnvironment.UserDataDirectory, "Lumod");
			for (int i = 0; i < args.Count; i++)
			{
				list.Add(args[i].ToPrintString());
			}
			MelonLogger.Msg("[" + file.Replace(oldValue, "") + "] " + string.Join("\t", list));
			return DynValue.Nil;
		}, (string)null);
		scr.Globals[(object)"error"] = (Action<string>)delegate(string s)
		{
			MelonLogger.Error(s);
		};
		scr.Globals[(object)"warn"] = (Action<string>)delegate(string s)
		{
			MelonLogger.Warning(s);
		};
		scr.Globals[(object)"loadSceneBarcode"] = (Action<string>)delegate(string s)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			SceneStreamer.Load(new Barcode(s), (Barcode)null);
		};
		scr.Globals[(object)"loadSceneDirect"] = (Action<string>)delegate(string s)
		{
			SceneManager.LoadScene(s);
		};
		scr.Globals[(object)"notify"] = (Action<string, string, NotificationType, float>)delegate(string msg, string title, NotificationType type, float len)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			Notify(msg, title, type, len);
		};
		scr.Globals[(object)"raycast"] = (Func<Table, Table, float, Table>)delegate(Table originTable, Table directionTable, float distance)
		{
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			Vector3 origin = default(Vector3);
			((Vector3)(ref origin))..ctor((float)originTable.Get("x").Number, (float)originTable.Get("y").Number, (float)originTable.Get("z").Number);
			Vector3 direction = default(Vector3);
			((Vector3)(ref direction))..ctor((float)directionTable.Get("x").Number, (float)directionTable.Get("y").Number, (float)directionTable.Get("z").Number);
			return Raycast(scr, origin, direction, distance);
		};
		scr.Globals[(object)"time"] = (Func<long>)(() => DateTimeOffset.UtcNow.ToUnixTimeMilliseconds());
		scr.Globals[(object)"filepath"] = (Func<string, string>)((string f) => Path.Combine(MelonEnvironment.UserDataDirectory, "Lumod", f));
		scr.Globals[(object)"vec"] = (Func<float, float, float, Table>)delegate(float x, float y, float z)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Expected O, but got Unknown
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Invalid comparison between Unknown and I4
			Table val = new Table(scr);
			val[(object)"x"] = x;
			val[(object)"y"] = y;
			val[(object)"z"] = z;
			DynValue val2 = scr.Globals.Get("VectorMetatable");
			val.MetaTable = ((val2 != null && (int)val2.Type == 6) ? val2.Table : null);
			return val;
		};
		scr.Globals[(object)"import"] = (Func<string, DynValue>)((string name) => UserData.CreateStatic((from a in AppDomain.CurrentDomain.GetAssemblies()
			select a.GetType(name)).FirstOrDefault((Type t) => t != null)));
		scr.Globals[(object)"getScene"] = (Func<string>)delegate
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			Scene activeScene = SceneManager.GetActiveScene();
			return ((Scene)(ref activeScene)).name;
		};
		scr.Globals[(object)"_NOTIFY_SUCCESS"] = (object)(NotificationType)3;
		scr.Globals[(object)"_NOTIFY_ERROR"] = (object)(NotificationType)2;
		scr.Globals[(object)"_NOTIFY_INFO"] = (object)(NotificationType)0;
		scr.Globals[(object)"_NOTIFY_WARNING"] = (object)(NotificationType)1;
		scr.DoString("\r\n    local mt = {}\r\n    mt.__index = mt\r\n\r\n    function vec(x, y, z)\r\n        return setmetatable({x = x or 0, y = y or 0, z = z or 0}, mt)\r\n    end\r\n\r\n    mt.__add = function(a, b) return vec(a.x + b.x, a.y + b.y, a.z + b.z) end\r\n    mt.__sub = function(a, b) return vec(a.x - b.x, a.y - b.y, a.z - b.z) end\r\n    mt.__unm = function(a) return vec(-a.x, -a.y, -a.z) end\r\n    mt.__mul = function(a, b)\r\n        if type(a) == 'number' then return vec(a * b.x, a * b.y, a * b.z) end\r\n        if type(b) == 'number' then return vec(a.x * b, a.y * b, a.z * b) end\r\n        return vec(a.x * b.x, a.y * b.y, a.z * b.z)\r\n    end\r\n    mt.__eq = function(a, b) return a.x == b.x and a.y == b.y and a.z == b.z end\r\n    mt.__tostring = function(a) return '(' .. a.x .. ', ' .. a.y .. ', ' .. a.z .. ')' end\r\n\r\n    function mt:length() return math.sqrt(self.x^2 + self.y^2 + self.z^2) end\r\n    function mt:dot(b) return self.x * b.x + self.y * b.y + self.z * b.z end\r\n\r\n    _VEC_MT = mt\r\n", (Table)null, (string)null);
		return scr;
	}

	public override void OnLateInitializeMelon()
	{
		((MelonBase)this).OnLateInitializeMelon();
		UserData.RegistrationPolicy = InteropRegistrationPolicy.Automatic;
		UserData.RegisterType<InputApi>((InteropAccessMode)7, (string)null);
		UserData.RegisterType<PlayerApi>((InteropAccessMode)7, (string)null);
		UserData.RegisterType<Vector3>((InteropAccessMode)7, (string)null);
		UserData.RegisterType<ObjectApi>((InteropAccessMode)7, (string)null);
		UserData.RegisterType<CameraApi>((InteropAccessMode)7, (string)null);
		UserData.RegisterType<RigidBodyApi>((InteropAccessMode)7, (string)null);
		UserData.RegisterType<DebugApi>((InteropAccessMode)7, (string)null);
		UserData.RegisterType<CrateApi>((InteropAccessMode)7, (string)null);
		UserData.RegisterType<MelonPageApi>((InteropAccessMode)7, (string)null);
		LumodMenu.CreateElements();
		LoadScripts();
	}

	public override void OnSceneWasLoaded(int buildIndex, string sceneName)
	{
		//IL_0040: Expected O, but got Unknown
		((MelonMod)this).OnSceneWasLoaded(buildIndex, sceneName);
		foreach (DynValue sceneHandler in sceneHandlers)
		{
			try
			{
				sceneHandler.Function.Call(new object[2] { sceneHandler, sceneName });
			}
			catch (ScriptRuntimeException ex)
			{
				ScriptRuntimeException ex2 = ex;
				MelonLogger.Error(((InterpreterException)ex2).DecoratedMessage);
			}
		}
	}

	private void Notify(string msg, string title, NotificationType type, float len)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_001f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Expected O, but got Unknown
		Notification val = new Notification
		{
			Title = NotificationText.op_Implicit(title),
			Message = NotificationText.op_Implicit(msg),
			Type = type,
			ShowTitleOnPopup = true,
			PopupLength = len
		};
		Notifier.Send(val);
	}

	public override void OnUpdate()
	{
		//IL_00b1: Expected O, but got Unknown
		//IL_028b: Expected O, but got Unknown
		//IL_0238: Unknown result type (might be due to invalid IL or missing references)
		//IL_023d: Unknown result type (might be due to invalid IL or missing references)
		((MelonBase)this).OnUpdate();
		if (!done)
		{
			GameObject val = GameObject.Find("GameplaySystems [0]/DisabledContainer/[UIRig]/PLAYERUI/UI_PREFERENCES/scaleOffset/canvas_UI/group_Options/panel_Preferences/[BoneMenu] - Canvas(Clone)");
			if ((Object)(object)val != (Object)null)
			{
				foreach (Transform componentsInChild in val.GetComponentsInChildren<Transform>(true))
				{
					((Component)componentsInChild).gameObject.layer = 5;
				}
				done = true;
			}
		}
		foreach (DynValue updateHandler in updateHandlers)
		{
			try
			{
				updateHandler.Function.Call((DynValue[])(object)new DynValue[1] { updateHandler });
			}
			catch (ScriptRuntimeException ex)
			{
				ScriptRuntimeException ex2 = ex;
				MelonLogger.Error(((InterpreterException)ex2).DecoratedMessage);
			}
		}
		if ((Keyboard.current != null && ((ButtonControl)Keyboard.current.lKey).wasPressedThisFrame) || (Player.HandsExist && Player.RightController.GetAButton() && Player.RightController.GetBButton() && Player.LeftController.GetBButtonDown()))
		{
			MelonLogger.Msg("Reloading lua");
			for (int i = 0; i < scriptPages.Count; i++)
			{
				Page value = scriptPages.ElementAt(i).Value;
				value.RemoveAll();
			}
			updateHandlers = new List<DynValue>();
			sceneHandlers = new List<DynValue>();
			keyHandlers = new List<DynValue>();
			try
			{
				LoadScripts();
				Notify("Reloaded Lua scripts", "Lumod", (NotificationType)3, 0.55f);
			}
			catch (Exception ex3)
			{
				MelonLogger.Error(ex3.ToString());
				Notify("Error reloading lua: " + ex3.Message, "Lumod", (NotificationType)2, 2f);
			}
		}
		Keyboard current3 = Keyboard.current;
		if (current3 == null)
		{
			return;
		}
		ReadOnlyArray<KeyControl> allKeys = current3.allKeys;
		for (int j = 0; j < allKeys.Count; j++)
		{
			KeyControl val2 = allKeys[j];
			if (!((ButtonControl)val2).wasPressedThisFrame)
			{
				continue;
			}
			string text = ((object)val2.keyCode/*cast due to .constrained prefix*/).ToString();
			foreach (DynValue keyHandler in keyHandlers)
			{
				try
				{
					keyHandler.Function.Call(new object[2] { keyHandler, text });
				}
				catch (ScriptRuntimeException ex4)
				{
					ScriptRuntimeException ex5 = ex4;
					MelonLogger.Error(((InterpreterException)ex5).DecoratedMessage);
				}
			}
		}
	}

	public override void OnFixedUpdate()
	{
		//IL_003a: Expected O, but got Unknown
		((MelonBase)this).OnFixedUpdate();
		foreach (DynValue fixedUpdateHandler in fixedUpdateHandlers)
		{
			try
			{
				fixedUpdateHandler.Function.Call((DynValue[])(object)new DynValue[1] { fixedUpdateHandler });
			}
			catch (ScriptRuntimeException ex)
			{
				ScriptRuntimeException ex2 = ex;
				MelonLogger.Error(((InterpreterException)ex2).DecoratedMessage);
			}
		}
	}

	public override void OnLateUpdate()
	{
		((MelonBase)this).OnLateUpdate();
	}
}

UserLibs/MoonSharp.Interpreter.dll

Decompiled 3 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using MoonSharp.Interpreter.Compatibility;
using MoonSharp.Interpreter.Compatibility.Frameworks;
using MoonSharp.Interpreter.CoreLib;
using MoonSharp.Interpreter.CoreLib.IO;
using MoonSharp.Interpreter.CoreLib.StringLib;
using MoonSharp.Interpreter.DataStructs;
using MoonSharp.Interpreter.Debugging;
using MoonSharp.Interpreter.Diagnostics;
using MoonSharp.Interpreter.Diagnostics.PerformanceCounters;
using MoonSharp.Interpreter.Execution;
using MoonSharp.Interpreter.Execution.Scopes;
using MoonSharp.Interpreter.Execution.VM;
using MoonSharp.Interpreter.IO;
using MoonSharp.Interpreter.Interop;
using MoonSharp.Interpreter.Interop.BasicDescriptors;
using MoonSharp.Interpreter.Interop.Converters;
using MoonSharp.Interpreter.Interop.LuaStateInterop;
using MoonSharp.Interpreter.Interop.RegistrationPolicies;
using MoonSharp.Interpreter.Interop.StandardDescriptors;
using MoonSharp.Interpreter.Interop.UserDataRegistries;
using MoonSharp.Interpreter.Loaders;
using MoonSharp.Interpreter.Platforms;
using MoonSharp.Interpreter.REPL;
using MoonSharp.Interpreter.Serialization.Json;
using MoonSharp.Interpreter.Tree;
using MoonSharp.Interpreter.Tree.Expressions;
using MoonSharp.Interpreter.Tree.Fast_Interface;
using MoonSharp.Interpreter.Tree.Statements;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("MoonSharp.Interpreter")]
[assembly: AssemblyDescription("An interpreter for the Lua language")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("http://www.moonsharp.org")]
[assembly: AssemblyProduct("MoonSharp.Interpreter")]
[assembly: AssemblyCopyright("Copyright © 2014-2015, Marco Mastropaolo")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("c971e5a8-dbec-4408-8046-86e4fdd1b2e3")]
[assembly: AssemblyFileVersion("2.0.0.0")]
[assembly: InternalsVisibleTo("MoonSharp.Interpreter.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100F704C50BBDC3F2F011CC26A8C6C4797A40E0B4BC94CFB1335E9BA208326340696B686DC13099F10D3054544532F5E3E66C26A13FF260AEA2343E0410511FE56EDCC2AFB898AAA1BC21DA33C0D0AE60824EB441D02A0E6B7AE251CDE0946BFC748209C12B062573ECDB008A3D10CC40534B314847591CE5342A3BC6AA83CE23B8")]
[assembly: InternalsVisibleTo("MoonSharp.Interpreter.Tests.net40-client, PublicKey=0024000004800000940000000602000000240000525341310004000001000100F704C50BBDC3F2F011CC26A8C6C4797A40E0B4BC94CFB1335E9BA208326340696B686DC13099F10D3054544532F5E3E66C26A13FF260AEA2343E0410511FE56EDCC2AFB898AAA1BC21DA33C0D0AE60824EB441D02A0E6B7AE251CDE0946BFC748209C12B062573ECDB008A3D10CC40534B314847591CE5342A3BC6AA83CE23B8")]
[assembly: InternalsVisibleTo("MoonSharp.Interpreter.Tests.portable40, PublicKey=0024000004800000940000000602000000240000525341310004000001000100F704C50BBDC3F2F011CC26A8C6C4797A40E0B4BC94CFB1335E9BA208326340696B686DC13099F10D3054544532F5E3E66C26A13FF260AEA2343E0410511FE56EDCC2AFB898AAA1BC21DA33C0D0AE60824EB441D02A0E6B7AE251CDE0946BFC748209C12B062573ECDB008A3D10CC40534B314847591CE5342A3BC6AA83CE23B8")]
[assembly: InternalsVisibleTo("MoonSharp.Interpreter.Tests.net35-client, PublicKey=0024000004800000940000000602000000240000525341310004000001000100F704C50BBDC3F2F011CC26A8C6C4797A40E0B4BC94CFB1335E9BA208326340696B686DC13099F10D3054544532F5E3E66C26A13FF260AEA2343E0410511FE56EDCC2AFB898AAA1BC21DA33C0D0AE60824EB441D02A0E6B7AE251CDE0946BFC748209C12B062573ECDB008A3D10CC40534B314847591CE5342A3BC6AA83CE23B8")]
[assembly: TargetFramework(".NETFramework,Version=v4.0,Profile=Client", FrameworkDisplayName = ".NET Framework 4 Client Profile")]
[assembly: AssemblyVersion("2.0.0.0")]
namespace MoonSharp.Interpreter
{
	public static class AsyncExtensions
	{
		private static Task<T> ExecAsync<T>(Func<T> func)
		{
			return Task.Factory.StartNew(func);
		}

		private static Task ExecAsyncVoid(Action func)
		{
			return Task.Factory.StartNew(func);
		}

		public static Task<DynValue> CallAsync(this Closure function)
		{
			return ExecAsync(() => function.Call());
		}

		public static Task<DynValue> CallAsync(this Closure function, params object[] args)
		{
			return ExecAsync(() => function.Call(args));
		}

		public static Task<DynValue> CallAsync(this Closure function, params DynValue[] args)
		{
			return ExecAsync(() => function.Call(args));
		}

		public static Task<DynValue> DoStringAsync(this Script script, string code, Table globalContext = null, string codeFriendlyName = null)
		{
			return ExecAsync(() => script.DoString(code, globalContext, codeFriendlyName));
		}

		public static Task<DynValue> DoStreamAsync(this Script script, Stream stream, Table globalContext = null, string codeFriendlyName = null)
		{
			return ExecAsync(() => script.DoStream(stream, globalContext, codeFriendlyName));
		}

		public static Task<DynValue> DoFileAsync(this Script script, string filename, Table globalContext = null, string codeFriendlyName = null)
		{
			return ExecAsync(() => script.DoFile(filename, globalContext, codeFriendlyName));
		}

		public static Task<DynValue> LoadFunctionAsync(this Script script, string code, Table globalTable = null, string funcFriendlyName = null)
		{
			return ExecAsync(() => script.LoadFunction(code, globalTable, funcFriendlyName));
		}

		public static Task<DynValue> LoadStringAsync(this Script script, string code, Table globalTable = null, string codeFriendlyName = null)
		{
			return ExecAsync(() => script.LoadString(code, globalTable, codeFriendlyName));
		}

		public static Task<DynValue> LoadStreamAsync(this Script script, Stream stream, Table globalTable = null, string codeFriendlyName = null)
		{
			return ExecAsync(() => script.LoadStream(stream, globalTable, codeFriendlyName));
		}

		public static Task DumpAsync(this Script script, DynValue function, Stream stream)
		{
			return ExecAsyncVoid(delegate
			{
				script.Dump(function, stream);
			});
		}

		public static Task<DynValue> LoadFileAsync(this Script script, string filename, Table globalContext = null, string friendlyFilename = null)
		{
			return ExecAsync(() => script.LoadFile(filename, globalContext, friendlyFilename));
		}

		public static Task<DynValue> CallAsync(this Script script, DynValue function)
		{
			return ExecAsync(() => script.Call(function));
		}

		public static Task<DynValue> CallAsync(this Script script, DynValue function, params DynValue[] args)
		{
			return ExecAsync(() => script.Call(function, args));
		}

		public static Task<DynValue> CallAsync(this Script script, DynValue function, params object[] args)
		{
			return ExecAsync(() => script.Call(function, args));
		}

		public static Task<DynValue> CallAsync(this Script script, object function)
		{
			return ExecAsync(() => script.Call(function));
		}

		public static Task<DynValue> CallAsync(this Script script, object function, params object[] args)
		{
			return ExecAsync(() => script.Call(function, args));
		}

		public static Task<DynamicExpression> CreateDynamicExpressionAsync(this Script script, string code)
		{
			return ExecAsync(() => script.CreateDynamicExpression(code));
		}

		public static Task<DynValue> EvaluateAsync(this ReplInterpreter interpreter, string input)
		{
			return ExecAsync(() => interpreter.Evaluate(input));
		}

		public static Task<DynValue> ResumeAsync(this Coroutine cor, params DynValue[] args)
		{
			return ExecAsync(() => cor.Resume(args));
		}

		public static Task<DynValue> ResumeAsync(this Coroutine cor, ScriptExecutionContext context, params DynValue[] args)
		{
			return ExecAsync(() => cor.Resume(context, args));
		}

		public static Task<DynValue> ResumeAsync(this Coroutine cor)
		{
			return ExecAsync(() => cor.Resume());
		}

		public static Task<DynValue> ResumeAsync(this Coroutine cor, ScriptExecutionContext context)
		{
			return ExecAsync(() => cor.Resume(context));
		}

		public static Task<DynValue> ResumeAsync(this Coroutine cor, params object[] args)
		{
			return ExecAsync(() => cor.Resume(args));
		}

		public static Task<DynValue> ResumeAsync(this Coroutine cor, ScriptExecutionContext context, params object[] args)
		{
			return ExecAsync(() => cor.Resume(context, args));
		}
	}
	[AttributeUsage(AttributeTargets.Property, Inherited = true, AllowMultiple = true)]
	public sealed class MoonSharpPropertyAttribute : Attribute
	{
		public string Name { get; private set; }

		public MoonSharpPropertyAttribute()
		{
		}

		public MoonSharpPropertyAttribute(string name)
		{
			Name = name;
		}
	}
	[AttributeUsage(AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
	public sealed class MoonSharpUserDataMetamethodAttribute : Attribute
	{
		public string Name { get; private set; }

		public MoonSharpUserDataMetamethodAttribute(string name)
		{
			Name = name;
		}
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, Inherited = true, AllowMultiple = true)]
	public sealed class MoonSharpHideMemberAttribute : Attribute
	{
		public string MemberName { get; private set; }

		public MoonSharpHideMemberAttribute(string memberName)
		{
			MemberName = memberName;
		}
	}
	[AttributeUsage(AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event, Inherited = true, AllowMultiple = false)]
	public sealed class MoonSharpHiddenAttribute : Attribute
	{
	}
	public delegate object ScriptFunctionDelegate(params object[] args);
	public delegate T ScriptFunctionDelegate<T>(params object[] args);
	[Flags]
	public enum TypeValidationFlags
	{
		None = 0,
		AllowNil = 1,
		AutoConvert = 2,
		Default = 2
	}
	[Serializable]
	public class DynamicExpressionException : ScriptRuntimeException
	{
		public DynamicExpressionException(string format, params object[] args)
			: base("<dynamic>: " + format, args)
		{
		}

		public DynamicExpressionException(string message)
			: base("<dynamic>: " + message)
		{
		}
	}
	public class DynamicExpression : IScriptPrivateResource
	{
		private DynamicExprExpression m_Exp;

		private DynValue m_Constant;

		public readonly string ExpressionCode;

		public Script OwnerScript { get; private set; }

		internal DynamicExpression(Script S, string strExpr, DynamicExprExpression expr)
		{
			ExpressionCode = strExpr;
			OwnerScript = S;
			m_Exp = expr;
		}

		internal DynamicExpression(Script S, string strExpr, DynValue constant)
		{
			ExpressionCode = strExpr;
			OwnerScript = S;
			m_Constant = constant;
		}

		public DynValue Evaluate(ScriptExecutionContext context = null)
		{
			context = context ?? OwnerScript.CreateDynamicExecutionContext();
			this.CheckScriptOwnership(context.GetScript());
			if (m_Constant != null)
			{
				return m_Constant;
			}
			return m_Exp.Eval(context);
		}

		public SymbolRef FindSymbol(ScriptExecutionContext context)
		{
			this.CheckScriptOwnership(context.GetScript());
			if (m_Exp != null)
			{
				return m_Exp.FindDynamic(context);
			}
			return null;
		}

		public bool IsConstant()
		{
			return m_Constant != null;
		}

		public override int GetHashCode()
		{
			return ExpressionCode.GetHashCode();
		}

		public override bool Equals(object obj)
		{
			if (!(obj is DynamicExpression dynamicExpression))
			{
				return false;
			}
			return dynamicExpression.ExpressionCode == ExpressionCode;
		}
	}
	internal static class Extension_Methods
	{
		public static TValue GetOrDefault<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, TKey key)
		{
			if (dictionary.TryGetValue(key, out var value))
			{
				return value;
			}
			return default(TValue);
		}

		public static TValue GetOrCreate<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, TKey key, Func<TValue> creator)
		{
			if (!dictionary.TryGetValue(key, out var value))
			{
				value = creator();
				dictionary.Add(key, value);
			}
			return value;
		}
	}
	public class Coroutine : RefIdObject, IScriptPrivateResource
	{
		public enum CoroutineType
		{
			Coroutine,
			ClrCallback,
			ClrCallbackDead
		}

		private CallbackFunction m_ClrCallback;

		private Processor m_Processor;

		public CoroutineType Type { get; private set; }

		public CoroutineState State
		{
			get
			{
				if (Type == CoroutineType.ClrCallback)
				{
					return CoroutineState.NotStarted;
				}
				if (Type == CoroutineType.ClrCallbackDead)
				{
					return CoroutineState.Dead;
				}
				return m_Processor.State;
			}
		}

		public Script OwnerScript { get; private set; }

		public long AutoYieldCounter
		{
			get
			{
				return m_Processor.AutoYieldCounter;
			}
			set
			{
				m_Processor.AutoYieldCounter = value;
			}
		}

		internal Coroutine(CallbackFunction function)
		{
			Type = CoroutineType.ClrCallback;
			m_ClrCallback = function;
			OwnerScript = null;
		}

		internal Coroutine(Processor proc)
		{
			Type = CoroutineType.Coroutine;
			m_Processor = proc;
			m_Processor.AssociatedCoroutine = this;
			OwnerScript = proc.GetScript();
		}

		internal void MarkClrCallbackAsDead()
		{
			if (Type != CoroutineType.ClrCallback)
			{
				throw new InvalidOperationException("State must be CoroutineType.ClrCallback");
			}
			Type = CoroutineType.ClrCallbackDead;
		}

		public IEnumerable<DynValue> AsTypedEnumerable()
		{
			if (Type != 0)
			{
				throw new InvalidOperationException("Only non-CLR coroutines can be resumed with this overload of the Resume method. Use the overload accepting a ScriptExecutionContext instead");
			}
			while (State == CoroutineState.NotStarted || State == CoroutineState.Suspended || State == CoroutineState.ForceSuspended)
			{
				yield return Resume();
			}
		}

		public IEnumerable<object> AsEnumerable()
		{
			foreach (DynValue item in AsTypedEnumerable())
			{
				yield return item.ToScalar().ToObject();
			}
		}

		public IEnumerable<T> AsEnumerable<T>()
		{
			foreach (DynValue item in AsTypedEnumerable())
			{
				yield return item.ToScalar().ToObject<T>();
			}
		}

		public IEnumerator AsUnityCoroutine()
		{
			foreach (DynValue item in AsTypedEnumerable())
			{
				_ = item;
				yield return null;
			}
		}

		public DynValue Resume(params DynValue[] args)
		{
			this.CheckScriptOwnership(args);
			if (Type == CoroutineType.Coroutine)
			{
				return m_Processor.Coroutine_Resume(args);
			}
			throw new InvalidOperationException("Only non-CLR coroutines can be resumed with this overload of the Resume method. Use the overload accepting a ScriptExecutionContext instead");
		}

		public DynValue Resume(ScriptExecutionContext context, params DynValue[] args)
		{
			this.CheckScriptOwnership(context);
			this.CheckScriptOwnership(args);
			if (Type == CoroutineType.Coroutine)
			{
				return m_Processor.Coroutine_Resume(args);
			}
			if (Type == CoroutineType.ClrCallback)
			{
				DynValue result = m_ClrCallback.Invoke(context, args);
				MarkClrCallbackAsDead();
				return result;
			}
			throw ScriptRuntimeException.CannotResumeNotSuspended(CoroutineState.Dead);
		}

		public DynValue Resume()
		{
			return Resume(new DynValue[0]);
		}

		public DynValue Resume(ScriptExecutionContext context)
		{
			return Resume(context, new DynValue[0]);
		}

		public DynValue Resume(params object[] args)
		{
			if (Type != 0)
			{
				throw new InvalidOperationException("Only non-CLR coroutines can be resumed with this overload of the Resume method. Use the overload accepting a ScriptExecutionContext instead");
			}
			DynValue[] array = new DynValue[args.Length];
			for (int i = 0; i < array.Length; i++)
			{
				array[i] = DynValue.FromObject(OwnerScript, args[i]);
			}
			return Resume(array);
		}

		public DynValue Resume(ScriptExecutionContext context, params object[] args)
		{
			DynValue[] array = new DynValue[args.Length];
			for (int i = 0; i < array.Length; i++)
			{
				array[i] = DynValue.FromObject(context.GetScript(), args[i]);
			}
			return Resume(context, array);
		}

		public WatchItem[] GetStackTrace(int skip, SourceRef entrySourceRef = null)
		{
			if (State != CoroutineState.Running)
			{
				entrySourceRef = m_Processor.GetCoroutineSuspendedLocation();
			}
			return m_Processor.Debugger_GetCallStack(entrySourceRef).Skip(skip).ToArray();
		}
	}
	public interface IScriptPrivateResource
	{
		Script OwnerScript { get; }
	}
	internal static class ScriptPrivateResource_Extension
	{
		public static void CheckScriptOwnership(this IScriptPrivateResource containingResource, DynValue[] values)
		{
			foreach (DynValue value in values)
			{
				containingResource.CheckScriptOwnership(value);
			}
		}

		public static void CheckScriptOwnership(this IScriptPrivateResource containingResource, DynValue value)
		{
			if (value != null)
			{
				IScriptPrivateResource asPrivateResource = value.GetAsPrivateResource();
				if (asPrivateResource != null)
				{
					containingResource.CheckScriptOwnership(asPrivateResource);
				}
			}
		}

		public static void CheckScriptOwnership(this IScriptPrivateResource resource, Script script)
		{
			if (resource.OwnerScript != null && resource.OwnerScript != script && script != null)
			{
				throw new ScriptRuntimeException("Attempt to access a resource owned by a script, from another script");
			}
		}

		public static void CheckScriptOwnership(this IScriptPrivateResource containingResource, IScriptPrivateResource itemResource)
		{
			if (itemResource != null)
			{
				if (containingResource.OwnerScript != null && containingResource.OwnerScript != itemResource.OwnerScript && itemResource.OwnerScript != null)
				{
					throw new ScriptRuntimeException("Attempt to perform operations with resources owned by different scripts.");
				}
				if (containingResource.OwnerScript == null && itemResource.OwnerScript != null)
				{
					throw new ScriptRuntimeException("Attempt to perform operations with a script private resource on a shared resource.");
				}
			}
		}
	}
	public class RefIdObject
	{
		private static int s_RefIDCounter;

		private int m_RefID = ++s_RefIDCounter;

		public int ReferenceID => m_RefID;

		public string FormatTypeString(string typeString)
		{
			return $"{typeString}: {m_RefID:X8}";
		}
	}
	public class TailCallData
	{
		public DynValue Function { get; set; }

		public DynValue[] Args { get; set; }

		public CallbackFunction Continuation { get; set; }

		public CallbackFunction ErrorHandler { get; set; }

		public DynValue ErrorHandlerBeforeUnwind { get; set; }
	}
	public class UserData : RefIdObject
	{
		public DynValue UserValue { get; set; }

		public object Object { get; private set; }

		public IUserDataDescriptor Descriptor { get; private set; }

		public static IRegistrationPolicy RegistrationPolicy
		{
			get
			{
				return TypeDescriptorRegistry.RegistrationPolicy;
			}
			set
			{
				TypeDescriptorRegistry.RegistrationPolicy = value;
			}
		}

		public static InteropAccessMode DefaultAccessMode
		{
			get
			{
				return TypeDescriptorRegistry.DefaultAccessMode;
			}
			set
			{
				TypeDescriptorRegistry.DefaultAccessMode = value;
			}
		}

		private UserData()
		{
		}

		static UserData()
		{
			RegistrationPolicy = InteropRegistrationPolicy.Default;
			RegisterType<EventFacade>(InteropAccessMode.NoReflectionAllowed);
			RegisterType<AnonWrapper>(InteropAccessMode.HideMembers);
			RegisterType<EnumerableWrapper>(InteropAccessMode.NoReflectionAllowed);
			RegisterType<JsonNull>(InteropAccessMode.Reflection);
			DefaultAccessMode = InteropAccessMode.LazyOptimized;
		}

		public static IUserDataDescriptor RegisterType<T>(InteropAccessMode accessMode = InteropAccessMode.Default, string friendlyName = null)
		{
			return TypeDescriptorRegistry.RegisterType_Impl(typeof(T), accessMode, friendlyName, null);
		}

		public static IUserDataDescriptor RegisterType(Type type, InteropAccessMode accessMode = InteropAccessMode.Default, string friendlyName = null)
		{
			return TypeDescriptorRegistry.RegisterType_Impl(type, accessMode, friendlyName, null);
		}

		public static IUserDataDescriptor RegisterProxyType(IProxyFactory proxyFactory, InteropAccessMode accessMode = InteropAccessMode.Default, string friendlyName = null)
		{
			return TypeDescriptorRegistry.RegisterProxyType_Impl(proxyFactory, accessMode, friendlyName);
		}

		public static IUserDataDescriptor RegisterProxyType<TProxy, TTarget>(Func<TTarget, TProxy> wrapDelegate, InteropAccessMode accessMode = InteropAccessMode.Default, string friendlyName = null) where TProxy : class where TTarget : class
		{
			return RegisterProxyType(new DelegateProxyFactory<TProxy, TTarget>(wrapDelegate), accessMode, friendlyName);
		}

		public static IUserDataDescriptor RegisterType<T>(IUserDataDescriptor customDescriptor)
		{
			return TypeDescriptorRegistry.RegisterType_Impl(typeof(T), InteropAccessMode.Default, null, customDescriptor);
		}

		public static IUserDataDescriptor RegisterType(Type type, IUserDataDescriptor customDescriptor)
		{
			return TypeDescriptorRegistry.RegisterType_Impl(type, InteropAccessMode.Default, null, customDescriptor);
		}

		public static IUserDataDescriptor RegisterType(IUserDataDescriptor customDescriptor)
		{
			return TypeDescriptorRegistry.RegisterType_Impl(customDescriptor.Type, InteropAccessMode.Default, null, customDescriptor);
		}

		public static void RegisterAssembly(Assembly asm = null, bool includeExtensionTypes = false)
		{
			if (asm == null)
			{
				asm = Assembly.GetCallingAssembly();
			}
			TypeDescriptorRegistry.RegisterAssembly(asm, includeExtensionTypes);
		}

		public static bool IsTypeRegistered(Type t)
		{
			return TypeDescriptorRegistry.IsTypeRegistered(t);
		}

		public static bool IsTypeRegistered<T>()
		{
			return TypeDescriptorRegistry.IsTypeRegistered(typeof(T));
		}

		public static void UnregisterType<T>()
		{
			TypeDescriptorRegistry.UnregisterType(typeof(T));
		}

		public static void UnregisterType(Type t)
		{
			TypeDescriptorRegistry.UnregisterType(t);
		}

		public static DynValue Create(object o, IUserDataDescriptor descr)
		{
			return DynValue.NewUserData(new UserData
			{
				Descriptor = descr,
				Object = o
			});
		}

		public static DynValue Create(object o)
		{
			IUserDataDescriptor descriptorForObject = GetDescriptorForObject(o);
			if (descriptorForObject == null)
			{
				if (o is Type)
				{
					return CreateStatic((Type)o);
				}
				return null;
			}
			return Create(o, descriptorForObject);
		}

		public static DynValue CreateStatic(IUserDataDescriptor descr)
		{
			if (descr == null)
			{
				return null;
			}
			return DynValue.NewUserData(new UserData
			{
				Descriptor = descr,
				Object = null
			});
		}

		public static DynValue CreateStatic(Type t)
		{
			return CreateStatic(GetDescriptorForType(t, searchInterfaces: false));
		}

		public static DynValue CreateStatic<T>()
		{
			return CreateStatic(GetDescriptorForType(typeof(T), searchInterfaces: false));
		}

		public static void RegisterExtensionType(Type type, InteropAccessMode mode = InteropAccessMode.Default)
		{
			ExtensionMethodsRegistry.RegisterExtensionType(type, mode);
		}

		public static List<IOverloadableMemberDescriptor> GetExtensionMethodsByNameAndType(string name, Type extendedType)
		{
			return ExtensionMethodsRegistry.GetExtensionMethodsByNameAndType(name, extendedType);
		}

		public static int GetExtensionMethodsChangeVersion()
		{
			return ExtensionMethodsRegistry.GetExtensionMethodsChangeVersion();
		}

		public static IUserDataDescriptor GetDescriptorForType<T>(bool searchInterfaces)
		{
			return TypeDescriptorRegistry.GetDescriptorForType(typeof(T), searchInterfaces);
		}

		public static IUserDataDescriptor GetDescriptorForType(Type type, bool searchInterfaces)
		{
			return TypeDescriptorRegistry.GetDescriptorForType(type, searchInterfaces);
		}

		public static IUserDataDescriptor GetDescriptorForObject(object o)
		{
			return TypeDescriptorRegistry.GetDescriptorForType(o.GetType(), searchInterfaces: true);
		}

		public static Table GetDescriptionOfRegisteredTypes(bool useHistoricalData = false)
		{
			DynValue dynValue = DynValue.NewPrimeTable();
			foreach (KeyValuePair<Type, IUserDataDescriptor> item in useHistoricalData ? TypeDescriptorRegistry.RegisteredTypesHistory : TypeDescriptorRegistry.RegisteredTypes)
			{
				if (item.Value is IWireableDescriptor wireableDescriptor)
				{
					DynValue dynValue2 = DynValue.NewPrimeTable();
					dynValue.Table.Set(item.Key.FullName, dynValue2);
					wireableDescriptor.PrepareForWiring(dynValue2.Table);
				}
			}
			return dynValue.Table;
		}

		public static IEnumerable<Type> GetRegisteredTypes(bool useHistoricalData = false)
		{
			return (useHistoricalData ? TypeDescriptorRegistry.RegisteredTypesHistory : TypeDescriptorRegistry.RegisteredTypes).Select((KeyValuePair<Type, IUserDataDescriptor> p) => p.Value.Type);
		}
	}
	public static class WellKnownSymbols
	{
		public const string VARARGS = "...";

		public const string ENV = "_ENV";
	}
	public class YieldRequest
	{
		public DynValue[] ReturnValues;

		public bool Forced { get; internal set; }
	}
	[Serializable]
	public class ScriptRuntimeException : InterpreterException
	{
		public ScriptRuntimeException(Exception ex)
			: base(ex)
		{
		}

		public ScriptRuntimeException(ScriptRuntimeException ex)
			: base(ex, ex.DecoratedMessage)
		{
			base.DecoratedMessage = Message;
			base.DoNotDecorateMessage = true;
		}

		public ScriptRuntimeException(string message)
			: base(message)
		{
		}

		public ScriptRuntimeException(string format, params object[] args)
			: base(format, args)
		{
		}

		public static ScriptRuntimeException ArithmeticOnNonNumber(DynValue l, DynValue r = null)
		{
			if (l.Type != DataType.Number && l.Type != DataType.String)
			{
				return new ScriptRuntimeException("attempt to perform arithmetic on a {0} value", l.Type.ToLuaTypeString());
			}
			if (r != null && r.Type != DataType.Number && r.Type != DataType.String)
			{
				return new ScriptRuntimeException("attempt to perform arithmetic on a {0} value", r.Type.ToLuaTypeString());
			}
			if (l.Type == DataType.String || (r != null && r.Type == DataType.String))
			{
				return new ScriptRuntimeException("attempt to perform arithmetic on a string value");
			}
			throw new InternalErrorException("ArithmeticOnNonNumber - both are numbers");
		}

		public static ScriptRuntimeException ConcatOnNonString(DynValue l, DynValue r)
		{
			if (l.Type != DataType.Number && l.Type != DataType.String)
			{
				return new ScriptRuntimeException("attempt to concatenate a {0} value", l.Type.ToLuaTypeString());
			}
			if (r != null && r.Type != DataType.Number && r.Type != DataType.String)
			{
				return new ScriptRuntimeException("attempt to concatenate a {0} value", r.Type.ToLuaTypeString());
			}
			throw new InternalErrorException("ConcatOnNonString - both are numbers/strings");
		}

		public static ScriptRuntimeException LenOnInvalidType(DynValue r)
		{
			return new ScriptRuntimeException("attempt to get length of a {0} value", r.Type.ToLuaTypeString());
		}

		public static ScriptRuntimeException CompareInvalidType(DynValue l, DynValue r)
		{
			if (l.Type.ToLuaTypeString() == r.Type.ToLuaTypeString())
			{
				return new ScriptRuntimeException("attempt to compare two {0} values", l.Type.ToLuaTypeString());
			}
			return new ScriptRuntimeException("attempt to compare {0} with {1}", l.Type.ToLuaTypeString(), r.Type.ToLuaTypeString());
		}

		public static ScriptRuntimeException BadArgument(int argNum, string funcName, string message)
		{
			return new ScriptRuntimeException("bad argument #{0} to '{1}' ({2})", argNum + 1, funcName, message);
		}

		public static ScriptRuntimeException BadArgumentUserData(int argNum, string funcName, Type expected, object got, bool allowNil)
		{
			return new ScriptRuntimeException("bad argument #{0} to '{1}' (userdata<{2}>{3} expected, got {4})", argNum + 1, funcName, expected.Name, allowNil ? "nil or " : "", (got != null) ? ("userdata<" + got.GetType().Name + ">") : "null");
		}

		public static ScriptRuntimeException BadArgument(int argNum, string funcName, DataType expected, DataType got, bool allowNil)
		{
			return BadArgument(argNum, funcName, expected.ToErrorTypeString(), got.ToErrorTypeString(), allowNil);
		}

		public static ScriptRuntimeException BadArgument(int argNum, string funcName, string expected, string got, bool allowNil)
		{
			return new ScriptRuntimeException("bad argument #{0} to '{1}' ({2}{3} expected, got {4})", argNum + 1, funcName, allowNil ? "nil or " : "", expected, got);
		}

		public static ScriptRuntimeException BadArgumentNoValue(int argNum, string funcName, DataType expected)
		{
			return new ScriptRuntimeException("bad argument #{0} to '{1}' ({2} expected, got no value)", argNum + 1, funcName, expected.ToErrorTypeString());
		}

		public static ScriptRuntimeException BadArgumentIndexOutOfRange(string funcName, int argNum)
		{
			return new ScriptRuntimeException("bad argument #{0} to '{1}' (index out of range)", argNum + 1, funcName);
		}

		public static ScriptRuntimeException BadArgumentNoNegativeNumbers(int argNum, string funcName)
		{
			return new ScriptRuntimeException("bad argument #{0} to '{1}' (not a non-negative number in proper range)", argNum + 1, funcName);
		}

		public static ScriptRuntimeException BadArgumentValueExpected(int argNum, string funcName)
		{
			return new ScriptRuntimeException("bad argument #{0} to '{1}' (value expected)", argNum + 1, funcName);
		}

		public static ScriptRuntimeException IndexType(DynValue obj)
		{
			return new ScriptRuntimeException("attempt to index a {0} value", obj.Type.ToLuaTypeString());
		}

		public static ScriptRuntimeException LoopInIndex()
		{
			return new ScriptRuntimeException("loop in gettable");
		}

		public static ScriptRuntimeException LoopInNewIndex()
		{
			return new ScriptRuntimeException("loop in settable");
		}

		public static ScriptRuntimeException LoopInCall()
		{
			return new ScriptRuntimeException("loop in call");
		}

		public static ScriptRuntimeException TableIndexIsNil()
		{
			return new ScriptRuntimeException("table index is nil");
		}

		public static ScriptRuntimeException TableIndexIsNaN()
		{
			return new ScriptRuntimeException("table index is NaN");
		}

		public static ScriptRuntimeException ConvertToNumberFailed(int stage)
		{
			return stage switch
			{
				1 => new ScriptRuntimeException("'for' initial value must be a number"), 
				2 => new ScriptRuntimeException("'for' step must be a number"), 
				3 => new ScriptRuntimeException("'for' limit must be a number"), 
				_ => new ScriptRuntimeException("value must be a number"), 
			};
		}

		public static ScriptRuntimeException ConvertObjectFailed(object obj)
		{
			return new ScriptRuntimeException("cannot convert clr type {0}", obj.GetType());
		}

		public static ScriptRuntimeException ConvertObjectFailed(DataType t)
		{
			return new ScriptRuntimeException("cannot convert a {0} to a clr type", t.ToString().ToLowerInvariant());
		}

		public static ScriptRuntimeException ConvertObjectFailed(DataType t, Type t2)
		{
			return new ScriptRuntimeException("cannot convert a {0} to a clr type {1}", t.ToString().ToLowerInvariant(), t2.FullName);
		}

		public static ScriptRuntimeException UserDataArgumentTypeMismatch(DataType t, Type clrType)
		{
			return new ScriptRuntimeException("cannot find a conversion from a MoonSharp {0} to a clr {1}", t.ToString().ToLowerInvariant(), clrType.FullName);
		}

		public static ScriptRuntimeException UserDataMissingField(string typename, string fieldname)
		{
			return new ScriptRuntimeException("cannot access field {0} of userdata<{1}>", fieldname, typename);
		}

		public static ScriptRuntimeException CannotResumeNotSuspended(CoroutineState state)
		{
			if (state == CoroutineState.Dead)
			{
				return new ScriptRuntimeException("cannot resume dead coroutine");
			}
			return new ScriptRuntimeException("cannot resume non-suspended coroutine");
		}

		public static ScriptRuntimeException CannotYield()
		{
			return new ScriptRuntimeException("attempt to yield across a CLR-call boundary");
		}

		public static ScriptRuntimeException CannotYieldMain()
		{
			return new ScriptRuntimeException("attempt to yield from outside a coroutine");
		}

		public static ScriptRuntimeException AttemptToCallNonFunc(DataType type, string debugText = null)
		{
			string text = type.ToErrorTypeString();
			if (debugText != null)
			{
				return new ScriptRuntimeException("attempt to call a {0} value near '{1}'", text, debugText);
			}
			return new ScriptRuntimeException("attempt to call a {0} value", text);
		}

		public static ScriptRuntimeException AccessInstanceMemberOnStatics(IMemberDescriptor desc)
		{
			return new ScriptRuntimeException("attempt to access instance member {0} from a static userdata", desc.Name);
		}

		public static ScriptRuntimeException AccessInstanceMemberOnStatics(IUserDataDescriptor typeDescr, IMemberDescriptor desc)
		{
			return new ScriptRuntimeException("attempt to access instance member {0}.{1} from a static userdata", typeDescr.Name, desc.Name);
		}

		public override void Rethrow()
		{
			if (Script.GlobalOptions.RethrowExceptionNested)
			{
				throw new ScriptRuntimeException(this);
			}
		}
	}
	[Serializable]
	public class InternalErrorException : InterpreterException
	{
		internal InternalErrorException(string message)
			: base(message)
		{
		}

		internal InternalErrorException(string format, params object[] args)
			: base(format, args)
		{
		}
	}
	[Serializable]
	public class InterpreterException : Exception
	{
		public int InstructionPtr { get; internal set; }

		public IList<WatchItem> CallStack { get; internal set; }

		public string DecoratedMessage { get; internal set; }

		public bool DoNotDecorateMessage { get; set; }

		protected InterpreterException(Exception ex, string message)
			: base(message, ex)
		{
		}

		protected InterpreterException(Exception ex)
			: base(ex.Message, ex)
		{
		}

		protected InterpreterException(string message)
			: base(message)
		{
		}

		protected InterpreterException(string format, params object[] args)
			: base(string.Format(format, args))
		{
		}

		internal void DecorateMessage(Script script, SourceRef sref, int ip = -1)
		{
			if (string.IsNullOrEmpty(DecoratedMessage))
			{
				if (DoNotDecorateMessage)
				{
					DecoratedMessage = Message;
				}
				else if (sref != null)
				{
					DecoratedMessage = $"{sref.FormatLocation(script)}: {Message}";
				}
				else
				{
					DecoratedMessage = $"bytecode:{ip}: {Message}";
				}
			}
		}

		public virtual void Rethrow()
		{
		}
	}
	[Serializable]
	public class SyntaxErrorException : InterpreterException
	{
		internal Token Token { get; private set; }

		public bool IsPrematureStreamTermination { get; set; }

		internal SyntaxErrorException(Token t, string format, params object[] args)
			: base(format, args)
		{
			Token = t;
		}

		internal SyntaxErrorException(Token t, string message)
			: base(message)
		{
			Token = t;
		}

		internal SyntaxErrorException(Script script, SourceRef sref, string format, params object[] args)
			: base(format, args)
		{
			DecorateMessage(script, sref);
		}

		internal SyntaxErrorException(Script script, SourceRef sref, string message)
			: base(message)
		{
			DecorateMessage(script, sref);
		}

		private SyntaxErrorException(SyntaxErrorException syntaxErrorException)
			: base(syntaxErrorException, syntaxErrorException.DecoratedMessage)
		{
			Token = syntaxErrorException.Token;
			base.DecoratedMessage = Message;
		}

		internal void DecorateMessage(Script script)
		{
			if (Token != null)
			{
				DecorateMessage(script, Token.GetSourceRef(isStepStop: false));
			}
		}

		public override void Rethrow()
		{
			if (Script.GlobalOptions.RethrowExceptionNested)
			{
				throw new SyntaxErrorException(this);
			}
		}
	}
	public class CallbackArguments
	{
		private IList<DynValue> m_Args;

		private int m_Count;

		private bool m_LastIsTuple;

		public int Count => m_Count;

		public bool IsMethodCall { get; private set; }

		public DynValue this[int index] => RawGet(index, translateVoids: true) ?? DynValue.Void;

		public CallbackArguments(IList<DynValue> args, bool isMethodCall)
		{
			m_Args = args;
			if (m_Args.Count > 0)
			{
				DynValue dynValue = m_Args[m_Args.Count - 1];
				if (dynValue.Type == DataType.Tuple)
				{
					m_Count = dynValue.Tuple.Length - 1 + m_Args.Count;
					m_LastIsTuple = true;
				}
				else if (dynValue.Type == DataType.Void)
				{
					m_Count = m_Args.Count - 1;
				}
				else
				{
					m_Count = m_Args.Count;
				}
			}
			else
			{
				m_Count = 0;
			}
			IsMethodCall = isMethodCall;
		}

		public DynValue RawGet(int index, bool translateVoids)
		{
			if (index >= m_Count)
			{
				return null;
			}
			DynValue dynValue = ((m_LastIsTuple && index >= m_Args.Count - 1) ? m_Args[m_Args.Count - 1].Tuple[index - (m_Args.Count - 1)] : m_Args[index]);
			if (dynValue.Type == DataType.Tuple)
			{
				dynValue = ((dynValue.Tuple.Length == 0) ? DynValue.Nil : dynValue.Tuple[0]);
			}
			if (translateVoids && dynValue.Type == DataType.Void)
			{
				dynValue = DynValue.Nil;
			}
			return dynValue;
		}

		public DynValue[] GetArray(int skip = 0)
		{
			if (skip >= m_Count)
			{
				return new DynValue[0];
			}
			DynValue[] array = new DynValue[m_Count - skip];
			for (int i = skip; i < m_Count; i++)
			{
				array[i - skip] = this[i];
			}
			return array;
		}

		public DynValue AsType(int argNum, string funcName, DataType type, bool allowNil = false)
		{
			return this[argNum].CheckType(funcName, type, argNum, allowNil ? (TypeValidationFlags.AllowNil | TypeValidationFlags.AutoConvert) : TypeValidationFlags.AutoConvert);
		}

		public T AsUserData<T>(int argNum, string funcName, bool allowNil = false)
		{
			return this[argNum].CheckUserDataType<T>(funcName, argNum, allowNil ? TypeValidationFlags.AllowNil : TypeValidationFlags.None);
		}

		public int AsInt(int argNum, string funcName)
		{
			return (int)AsType(argNum, funcName, DataType.Number).Number;
		}

		public long AsLong(int argNum, string funcName)
		{
			return (long)AsType(argNum, funcName, DataType.Number).Number;
		}

		public string AsStringUsingMeta(ScriptExecutionContext executionContext, int argNum, string funcName)
		{
			if (this[argNum].Type == DataType.Table && this[argNum].Table.MetaTable != null && this[argNum].Table.MetaTable.RawGet("__tostring") != null)
			{
				DynValue dynValue = executionContext.GetScript().Call(this[argNum].Table.MetaTable.RawGet("__tostring"), this[argNum]);
				if (dynValue.Type != DataType.String)
				{
					throw new ScriptRuntimeException("'tostring' must return a string to '{0}'", funcName);
				}
				return dynValue.ToPrintString();
			}
			return this[argNum].ToPrintString();
		}

		public CallbackArguments SkipMethodCall()
		{
			if (IsMethodCall)
			{
				return new CallbackArguments(new Slice<DynValue>(m_Args, 1, m_Args.Count - 1, reversed: false), isMethodCall: false);
			}
			return this;
		}
	}
	public class Closure : RefIdObject, IScriptPrivateResource
	{
		public enum UpvaluesType
		{
			None,
			Environment,
			Closure
		}

		private static ClosureContext emptyClosure = new ClosureContext();

		public int EntryPointByteCodeLocation { get; private set; }

		public Script OwnerScript { get; private set; }

		internal ClosureContext ClosureContext { get; private set; }

		internal Closure(Script script, int idx, SymbolRef[] symbols, IEnumerable<DynValue> resolvedLocals)
		{
			OwnerScript = script;
			EntryPointByteCodeLocation = idx;
			if (symbols.Length != 0)
			{
				ClosureContext = new ClosureContext(symbols, resolvedLocals);
			}
			else
			{
				ClosureContext = emptyClosure;
			}
		}

		public DynValue Call()
		{
			return OwnerScript.Call(this);
		}

		public DynValue Call(params object[] args)
		{
			return OwnerScript.Call(this, args);
		}

		public DynValue Call(params DynValue[] args)
		{
			return OwnerScript.Call(this, args);
		}

		public ScriptFunctionDelegate GetDelegate()
		{
			return (object[] args) => Call(args).ToObject();
		}

		public ScriptFunctionDelegate<T> GetDelegate<T>()
		{
			return (object[] args) => Call(args).ToObject<T>();
		}

		public int GetUpvaluesCount()
		{
			return ClosureContext.Count;
		}

		public string GetUpvalueName(int idx)
		{
			return ClosureContext.Symbols[idx];
		}

		public DynValue GetUpvalue(int idx)
		{
			return ClosureContext[idx];
		}

		public UpvaluesType GetUpvaluesType()
		{
			switch (GetUpvaluesCount())
			{
			case 0:
				return UpvaluesType.None;
			case 1:
				if (GetUpvalueName(0) == "_ENV")
				{
					return UpvaluesType.Environment;
				}
				break;
			}
			return UpvaluesType.Closure;
		}
	}
	public sealed class CallbackFunction : RefIdObject
	{
		private static InteropAccessMode m_DefaultAccessMode = InteropAccessMode.LazyOptimized;

		public string Name { get; private set; }

		public Func<ScriptExecutionContext, CallbackArguments, DynValue> ClrCallback { get; private set; }

		public static InteropAccessMode DefaultAccessMode
		{
			get
			{
				return m_DefaultAccessMode;
			}
			set
			{
				if (value == InteropAccessMode.Default || value == InteropAccessMode.HideMembers || value == InteropAccessMode.BackgroundOptimized)
				{
					throw new ArgumentException("DefaultAccessMode");
				}
				m_DefaultAccessMode = value;
			}
		}

		public object AdditionalData { get; set; }

		public CallbackFunction(Func<ScriptExecutionContext, CallbackArguments, DynValue> callBack, string name = null)
		{
			ClrCallback = callBack;
			Name = name;
		}

		public DynValue Invoke(ScriptExecutionContext executionContext, IList<DynValue> args, bool isMethodCall = false)
		{
			if (isMethodCall)
			{
				switch (executionContext.GetScript().Options.ColonOperatorClrCallbackBehaviour)
				{
				case ColonOperatorBehaviour.TreatAsColon:
					isMethodCall = false;
					break;
				case ColonOperatorBehaviour.TreatAsDotOnUserData:
					isMethodCall = args.Count > 0 && args[0].Type == DataType.UserData;
					break;
				}
			}
			return ClrCallback(executionContext, new CallbackArguments(args, isMethodCall));
		}

		public static CallbackFunction FromDelegate(Script script, Delegate del, InteropAccessMode accessMode = InteropAccessMode.Default)
		{
			if (accessMode == InteropAccessMode.Default)
			{
				accessMode = m_DefaultAccessMode;
			}
			return new MethodMemberDescriptor(del.Method, accessMode).GetCallbackFunction(script, del.Target);
		}

		public static CallbackFunction FromMethodInfo(Script script, MethodInfo mi, object obj = null, InteropAccessMode accessMode = InteropAccessMode.Default)
		{
			if (accessMode == InteropAccessMode.Default)
			{
				accessMode = m_DefaultAccessMode;
			}
			return new MethodMemberDescriptor(mi, accessMode).GetCallbackFunction(script, obj);
		}

		public static bool CheckCallbackSignature(MethodInfo mi, bool requirePublicVisibility)
		{
			ParameterInfo[] parameters = mi.GetParameters();
			if (parameters.Length == 2 && parameters[0].ParameterType == typeof(ScriptExecutionContext) && parameters[1].ParameterType == typeof(CallbackArguments) && mi.ReturnType == typeof(DynValue))
			{
				if (!requirePublicVisibility)
				{
					return mi.IsPublic;
				}
				return true;
			}
			return false;
		}
	}
	public sealed class DynValue
	{
		private static int s_RefIDCounter;

		private int m_RefID = ++s_RefIDCounter;

		private int m_HashCode = -1;

		private bool m_ReadOnly;

		private double m_Number;

		private object m_Object;

		private DataType m_Type;

		public int ReferenceID => m_RefID;

		public DataType Type => m_Type;

		public Closure Function => m_Object as Closure;

		public double Number => m_Number;

		public DynValue[] Tuple => m_Object as DynValue[];

		public Coroutine Coroutine => m_Object as Coroutine;

		public Table Table => m_Object as Table;

		public bool Boolean => Number != 0.0;

		public string String => m_Object as string;

		public CallbackFunction Callback => m_Object as CallbackFunction;

		public TailCallData TailCallData => m_Object as TailCallData;

		public YieldRequest YieldRequest => m_Object as YieldRequest;

		public UserData UserData => m_Object as UserData;

		public bool ReadOnly => m_ReadOnly;

		public static DynValue Void { get; private set; }

		public static DynValue Nil { get; private set; }

		public static DynValue True { get; private set; }

		public static DynValue False { get; private set; }

		public static DynValue NewNil()
		{
			return new DynValue();
		}

		public static DynValue NewBoolean(bool v)
		{
			return new DynValue
			{
				m_Number = (v ? 1 : 0),
				m_Type = DataType.Boolean
			};
		}

		public static DynValue NewNumber(double num)
		{
			return new DynValue
			{
				m_Number = num,
				m_Type = DataType.Number,
				m_HashCode = -1
			};
		}

		public static DynValue NewString(string str)
		{
			return new DynValue
			{
				m_Object = str,
				m_Type = DataType.String
			};
		}

		public static DynValue NewString(StringBuilder sb)
		{
			return new DynValue
			{
				m_Object = sb.ToString(),
				m_Type = DataType.String
			};
		}

		public static DynValue NewString(string format, params object[] args)
		{
			return new DynValue
			{
				m_Object = string.Format(format, args),
				m_Type = DataType.String
			};
		}

		public static DynValue NewCoroutine(Coroutine coroutine)
		{
			return new DynValue
			{
				m_Object = coroutine,
				m_Type = DataType.Thread
			};
		}

		public static DynValue NewClosure(Closure function)
		{
			return new DynValue
			{
				m_Object = function,
				m_Type = DataType.Function
			};
		}

		public static DynValue NewCallback(Func<ScriptExecutionContext, CallbackArguments, DynValue> callBack, string name = null)
		{
			return new DynValue
			{
				m_Object = new CallbackFunction(callBack, name),
				m_Type = DataType.ClrFunction
			};
		}

		public static DynValue NewCallback(CallbackFunction function)
		{
			return new DynValue
			{
				m_Object = function,
				m_Type = DataType.ClrFunction
			};
		}

		public static DynValue NewTable(Table table)
		{
			return new DynValue
			{
				m_Object = table,
				m_Type = DataType.Table
			};
		}

		public static DynValue NewPrimeTable()
		{
			return NewTable(new Table(null));
		}

		public static DynValue NewTable(Script script)
		{
			return NewTable(new Table(script));
		}

		public static DynValue NewTable(Script script, params DynValue[] arrayValues)
		{
			return NewTable(new Table(script, arrayValues));
		}

		public static DynValue NewTailCallReq(DynValue tailFn, params DynValue[] args)
		{
			return new DynValue
			{
				m_Object = new TailCallData
				{
					Args = args,
					Function = tailFn
				},
				m_Type = DataType.TailCallRequest
			};
		}

		public static DynValue NewTailCallReq(TailCallData tailCallData)
		{
			return new DynValue
			{
				m_Object = tailCallData,
				m_Type = DataType.TailCallRequest
			};
		}

		public static DynValue NewYieldReq(DynValue[] args)
		{
			return new DynValue
			{
				m_Object = new YieldRequest
				{
					ReturnValues = args
				},
				m_Type = DataType.YieldRequest
			};
		}

		internal static DynValue NewForcedYieldReq()
		{
			return new DynValue
			{
				m_Object = new YieldRequest
				{
					Forced = true
				},
				m_Type = DataType.YieldRequest
			};
		}

		public static DynValue NewTuple(params DynValue[] values)
		{
			if (values.Length == 0)
			{
				return NewNil();
			}
			if (values.Length == 1)
			{
				return values[0];
			}
			return new DynValue
			{
				m_Object = values,
				m_Type = DataType.Tuple
			};
		}

		public static DynValue NewTupleNested(params DynValue[] values)
		{
			if (!values.Any((DynValue v) => v.Type == DataType.Tuple))
			{
				return NewTuple(values);
			}
			if (values.Length == 1)
			{
				return values[0];
			}
			List<DynValue> list = new List<DynValue>();
			foreach (DynValue dynValue in values)
			{
				if (dynValue.Type == DataType.Tuple)
				{
					list.AddRange(dynValue.Tuple);
				}
				else
				{
					list.Add(dynValue);
				}
			}
			return new DynValue
			{
				m_Object = list.ToArray(),
				m_Type = DataType.Tuple
			};
		}

		public static DynValue NewUserData(UserData userData)
		{
			return new DynValue
			{
				m_Object = userData,
				m_Type = DataType.UserData
			};
		}

		public DynValue AsReadOnly()
		{
			if (ReadOnly)
			{
				return this;
			}
			return Clone(readOnly: true);
		}

		public DynValue Clone()
		{
			return Clone(ReadOnly);
		}

		public DynValue Clone(bool readOnly)
		{
			return new DynValue
			{
				m_Object = m_Object,
				m_Number = m_Number,
				m_HashCode = m_HashCode,
				m_Type = m_Type,
				m_ReadOnly = readOnly
			};
		}

		public DynValue CloneAsWritable()
		{
			return Clone(readOnly: false);
		}

		static DynValue()
		{
			Nil = new DynValue
			{
				m_Type = DataType.Nil
			}.AsReadOnly();
			Void = new DynValue
			{
				m_Type = DataType.Void
			}.AsReadOnly();
			True = NewBoolean(v: true).AsReadOnly();
			False = NewBoolean(v: false).AsReadOnly();
		}

		public string ToPrintString()
		{
			if (m_Object != null && m_Object is RefIdObject)
			{
				RefIdObject refIdObject = (RefIdObject)m_Object;
				string typeString = Type.ToLuaTypeString();
				if (m_Object is UserData)
				{
					UserData userData = (UserData)m_Object;
					string text = userData.Descriptor.AsString(userData.Object);
					if (text != null)
					{
						return text;
					}
				}
				return refIdObject.FormatTypeString(typeString);
			}
			return Type switch
			{
				DataType.String => String, 
				DataType.Tuple => string.Join("\t", Tuple.Select((DynValue t) => t.ToPrintString()).ToArray()), 
				DataType.TailCallRequest => "(TailCallRequest -- INTERNAL!)", 
				DataType.YieldRequest => "(YieldRequest -- INTERNAL!)", 
				_ => ToString(), 
			};
		}

		public string ToDebugPrintString()
		{
			if (m_Object != null && m_Object is RefIdObject)
			{
				RefIdObject refIdObject = (RefIdObject)m_Object;
				string typeString = Type.ToLuaTypeString();
				if (m_Object is UserData)
				{
					UserData userData = (UserData)m_Object;
					string text = userData.Descriptor.AsString(userData.Object);
					if (text != null)
					{
						return text;
					}
				}
				return refIdObject.FormatTypeString(typeString);
			}
			return Type switch
			{
				DataType.Tuple => string.Join("\t", Tuple.Select((DynValue t) => t.ToPrintString()).ToArray()), 
				DataType.TailCallRequest => "(TailCallRequest)", 
				DataType.YieldRequest => "(YieldRequest)", 
				_ => ToString(), 
			};
		}

		public override string ToString()
		{
			return Type switch
			{
				DataType.Void => "void", 
				DataType.Nil => "nil", 
				DataType.Boolean => Boolean.ToString().ToLower(), 
				DataType.Number => Number.ToString(CultureInfo.InvariantCulture), 
				DataType.String => "\"" + String + "\"", 
				DataType.Function => $"(Function {Function.EntryPointByteCodeLocation:X8})", 
				DataType.ClrFunction => string.Format("(Function CLR)", Function), 
				DataType.Table => "(Table)", 
				DataType.Tuple => string.Join(", ", Tuple.Select((DynValue t) => t.ToString()).ToArray()), 
				DataType.TailCallRequest => "Tail:(" + string.Join(", ", Tuple.Select((DynValue t) => t.ToString()).ToArray()) + ")", 
				DataType.UserData => "(UserData)", 
				DataType.Thread => $"(Coroutine {Coroutine.ReferenceID:X8})", 
				_ => "(???)", 
			};
		}

		public override int GetHashCode()
		{
			if (m_HashCode != -1)
			{
				return m_HashCode;
			}
			int num = (int)Type << 27;
			switch (Type)
			{
			case DataType.Nil:
			case DataType.Void:
				m_HashCode = 0;
				break;
			case DataType.Boolean:
				m_HashCode = (Boolean ? 1 : 2);
				break;
			case DataType.Number:
				m_HashCode = num ^ Number.GetHashCode();
				break;
			case DataType.String:
				m_HashCode = num ^ String.GetHashCode();
				break;
			case DataType.Function:
				m_HashCode = num ^ Function.GetHashCode();
				break;
			case DataType.ClrFunction:
				m_HashCode = num ^ Callback.GetHashCode();
				break;
			case DataType.Table:
				m_HashCode = num ^ Table.GetHashCode();
				break;
			case DataType.Tuple:
			case DataType.TailCallRequest:
				m_HashCode = num ^ Tuple.GetHashCode();
				break;
			default:
				m_HashCode = 999;
				break;
			}
			return m_HashCode;
		}

		public override bool Equals(object obj)
		{
			if (!(obj is DynValue dynValue))
			{
				return false;
			}
			if ((dynValue.Type == DataType.Nil && Type == DataType.Void) || (dynValue.Type == DataType.Void && Type == DataType.Nil))
			{
				return true;
			}
			if (dynValue.Type != Type)
			{
				return false;
			}
			switch (Type)
			{
			case DataType.Nil:
			case DataType.Void:
				return true;
			case DataType.Boolean:
				return Boolean == dynValue.Boolean;
			case DataType.Number:
				return Number == dynValue.Number;
			case DataType.String:
				return String == dynValue.String;
			case DataType.Function:
				return Function == dynValue.Function;
			case DataType.ClrFunction:
				return Callback == dynValue.Callback;
			case DataType.Table:
				return Table == dynValue.Table;
			case DataType.Tuple:
			case DataType.TailCallRequest:
				return Tuple == dynValue.Tuple;
			case DataType.Thread:
				return Coroutine == dynValue.Coroutine;
			case DataType.UserData:
			{
				UserData userData = UserData;
				UserData userData2 = dynValue.UserData;
				if (userData == null || userData2 == null)
				{
					return false;
				}
				if (userData.Descriptor != userData2.Descriptor)
				{
					return false;
				}
				if (userData.Object == null && userData2.Object == null)
				{
					return true;
				}
				if (userData.Object != null && userData2.Object != null)
				{
					return userData.Object.Equals(userData2.Object);
				}
				return false;
			}
			default:
				return this == dynValue;
			}
		}

		public string CastToString()
		{
			DynValue dynValue = ToScalar();
			if (dynValue.Type == DataType.Number)
			{
				return dynValue.Number.ToString();
			}
			if (dynValue.Type == DataType.String)
			{
				return dynValue.String;
			}
			return null;
		}

		public double? CastToNumber()
		{
			DynValue dynValue = ToScalar();
			if (dynValue.Type == DataType.Number)
			{
				return dynValue.Number;
			}
			if (dynValue.Type == DataType.String && double.TryParse(dynValue.String, NumberStyles.Any, CultureInfo.InvariantCulture, out var result))
			{
				return result;
			}
			return null;
		}

		public bool CastToBool()
		{
			DynValue dynValue = ToScalar();
			if (dynValue.Type == DataType.Boolean)
			{
				return dynValue.Boolean;
			}
			if (dynValue.Type != 0)
			{
				return dynValue.Type != DataType.Void;
			}
			return false;
		}

		public IScriptPrivateResource GetAsPrivateResource()
		{
			return m_Object as IScriptPrivateResource;
		}

		public DynValue ToScalar()
		{
			if (Type != DataType.Tuple)
			{
				return this;
			}
			if (Tuple.Length == 0)
			{
				return Void;
			}
			return Tuple[0].ToScalar();
		}

		public void Assign(DynValue value)
		{
			if (ReadOnly)
			{
				throw new ScriptRuntimeException("Assigning on r-value");
			}
			m_Number = value.m_Number;
			m_Object = value.m_Object;
			m_Type = value.Type;
			m_HashCode = -1;
		}

		public DynValue GetLength()
		{
			if (Type == DataType.Table)
			{
				return NewNumber(Table.Length);
			}
			if (Type == DataType.String)
			{
				return NewNumber(String.Length);
			}
			throw new ScriptRuntimeException("Can't get length of type {0}", Type);
		}

		public bool IsNil()
		{
			if (Type != 0)
			{
				return Type == DataType.Void;
			}
			return true;
		}

		public bool IsNotNil()
		{
			if (Type != 0)
			{
				return Type != DataType.Void;
			}
			return false;
		}

		public bool IsVoid()
		{
			return Type == DataType.Void;
		}

		public bool IsNotVoid()
		{
			return Type != DataType.Void;
		}

		public bool IsNilOrNan()
		{
			if (Type != 0 && Type != DataType.Void)
			{
				if (Type == DataType.Number)
				{
					return double.IsNaN(Number);
				}
				return false;
			}
			return true;
		}

		internal void AssignNumber(double num)
		{
			if (ReadOnly)
			{
				throw new InternalErrorException(null, "Writing on r-value");
			}
			if (Type != DataType.Number)
			{
				throw new InternalErrorException("Can't assign number to type {0}", Type);
			}
			m_Number = num;
		}

		public static DynValue FromObject(Script script, object obj)
		{
			return ClrToScriptConversions.ObjectToDynValue(script, obj);
		}

		public object ToObject()
		{
			return ScriptToClrConversions.DynValueToObject(this);
		}

		public object ToObject(Type desiredType)
		{
			return ScriptToClrConversions.DynValueToObjectOfType(this, desiredType, null, isOptional: false);
		}

		public T ToObject<T>()
		{
			return (T)ToObject(typeof(T));
		}

		public dynamic ToDynamic()
		{
			return ScriptToClrConversions.DynValueToObject(this);
		}

		public DynValue CheckType(string funcName, DataType desiredType, int argNum = -1, TypeValidationFlags flags = TypeValidationFlags.AutoConvert)
		{
			if (Type == desiredType)
			{
				return this;
			}
			bool flag = (flags & TypeValidationFlags.AllowNil) != 0;
			if (flag && IsNil())
			{
				return this;
			}
			if ((flags & TypeValidationFlags.AutoConvert) != 0)
			{
				switch (desiredType)
				{
				case DataType.Boolean:
					return NewBoolean(CastToBool());
				case DataType.Number:
				{
					double? num = CastToNumber();
					if (num.HasValue)
					{
						return NewNumber(num.Value);
					}
					break;
				}
				}
				if (desiredType == DataType.String)
				{
					string text = CastToString();
					if (text != null)
					{
						return NewString(text);
					}
				}
			}
			if (IsVoid())
			{
				throw ScriptRuntimeException.BadArgumentNoValue(argNum, funcName, desiredType);
			}
			throw ScriptRuntimeException.BadArgument(argNum, funcName, desiredType, Type, flag);
		}

		public T CheckUserDataType<T>(string funcName, int argNum = -1, TypeValidationFlags flags = TypeValidationFlags.AutoConvert)
		{
			DynValue dynValue = CheckType(funcName, DataType.UserData, argNum, flags);
			bool allowNil = (flags & TypeValidationFlags.AllowNil) != 0;
			if (dynValue.IsNil())
			{
				return default(T);
			}
			object @object = dynValue.UserData.Object;
			if (@object != null && @object is T)
			{
				return (T)@object;
			}
			throw ScriptRuntimeException.BadArgumentUserData(argNum, funcName, typeof(T), @object, allowNil);
		}
	}
	public struct TablePair
	{
		private static TablePair s_NilNode = new TablePair(DynValue.Nil, DynValue.Nil);

		private DynValue key;

		private DynValue value;

		public DynValue Key
		{
			get
			{
				return key;
			}
			private set
			{
				Key = key;
			}
		}

		public DynValue Value
		{
			get
			{
				return value;
			}
			set
			{
				if (key.IsNotNil())
				{
					Value = value;
				}
			}
		}

		public static TablePair Nil => s_NilNode;

		public TablePair(DynValue key, DynValue val)
		{
			this.key = key;
			value = val;
		}
	}
	public class ScriptExecutionContext : IScriptPrivateResource
	{
		private Processor m_Processor;

		private CallbackFunction m_Callback;

		public bool IsDynamicExecution { get; private set; }

		public SourceRef CallingLocation { get; private set; }

		public object AdditionalData
		{
			get
			{
				if (m_Callback == null)
				{
					return null;
				}
				return m_Callback.AdditionalData;
			}
			set
			{
				if (m_Callback == null)
				{
					throw new InvalidOperationException("Cannot set additional data on a context which has no callback");
				}
				m_Callback.AdditionalData = value;
			}
		}

		public Table CurrentGlobalEnv
		{
			get
			{
				DynValue dynValue = EvaluateSymbolByName("_ENV");
				if (dynValue == null || dynValue.Type != DataType.Table)
				{
					return null;
				}
				return dynValue.Table;
			}
		}

		public Script OwnerScript => GetScript();

		internal ScriptExecutionContext(Processor p, CallbackFunction callBackFunction, SourceRef sourceRef, bool isDynamic = false)
		{
			IsDynamicExecution = isDynamic;
			m_Processor = p;
			m_Callback = callBackFunction;
			CallingLocation = sourceRef;
		}

		public Table GetMetatable(DynValue value)
		{
			return m_Processor.GetMetatable(value);
		}

		public DynValue GetMetamethod(DynValue value, string metamethod)
		{
			return m_Processor.GetMetamethod(value, metamethod);
		}

		public DynValue GetMetamethodTailCall(DynValue value, string metamethod, params DynValue[] args)
		{
			DynValue metamethod2 = GetMetamethod(value, metamethod);
			if (metamethod2 == null)
			{
				return null;
			}
			return DynValue.NewTailCallReq(metamethod2, args);
		}

		public DynValue GetBinaryMetamethod(DynValue op1, DynValue op2, string eventName)
		{
			return m_Processor.GetBinaryMetamethod(op1, op2, eventName);
		}

		public Script GetScript()
		{
			return m_Processor.GetScript();
		}

		public Coroutine GetCallingCoroutine()
		{
			return m_Processor.AssociatedCoroutine;
		}

		public DynValue EmulateClassicCall(CallbackArguments args, string functionName, Func<LuaState, int> callback)
		{
			LuaState luaState = new LuaState(this, args, functionName);
			int retvals = callback(luaState);
			return luaState.GetReturnValue(retvals);
		}

		public DynValue Call(DynValue func, params DynValue[] args)
		{
			if (func.Type == DataType.Function)
			{
				return GetScript().Call(func, args);
			}
			if (func.Type == DataType.ClrFunction)
			{
				DynValue dynValue;
				while (true)
				{
					dynValue = func.Callback.Invoke(this, args);
					if (dynValue.Type == DataType.YieldRequest)
					{
						throw ScriptRuntimeException.CannotYield();
					}
					if (dynValue.Type != DataType.TailCallRequest)
					{
						break;
					}
					TailCallData tailCallData = dynValue.TailCallData;
					if (tailCallData.Continuation != null || tailCallData.ErrorHandler != null)
					{
						throw new ScriptRuntimeException("the function passed cannot be called directly. wrap in a script function instead.");
					}
					args = tailCallData.Args;
					func = tailCallData.Function;
				}
				return dynValue;
			}
			int num = 10;
			while (num > 0)
			{
				DynValue metamethod = GetMetamethod(func, "__call");
				if (metamethod == null && metamethod.IsNil())
				{
					throw ScriptRuntimeException.AttemptToCallNonFunc(func.Type);
				}
				func = metamethod;
				if (func.Type == DataType.Function || func.Type == DataType.ClrFunction)
				{
					return Call(func, args);
				}
			}
			throw ScriptRuntimeException.LoopInCall();
		}

		public DynValue EvaluateSymbol(SymbolRef symref)
		{
			if (symref == null)
			{
				return DynValue.Nil;
			}
			return m_Processor.GetGenericSymbol(symref);
		}

		public DynValue EvaluateSymbolByName(string symbol)
		{
			return EvaluateSymbol(FindSymbolByName(symbol));
		}

		public SymbolRef FindSymbolByName(string symbol)
		{
			return m_Processor.FindSymbolByName(symbol);
		}

		public void PerformMessageDecorationBeforeUnwind(DynValue messageHandler, ScriptRuntimeException exception)
		{
			if (messageHandler != null)
			{
				exception.DecoratedMessage = m_Processor.PerformMessageDecorationBeforeUnwind(messageHandler, exception.Message, CallingLocation);
			}
			else
			{
				exception.DecoratedMessage = exception.Message;
			}
		}
	}
	public enum CoroutineState
	{
		Main,
		NotStarted,
		Suspended,
		ForceSuspended,
		Running,
		Dead
	}
	public static class LinqHelpers
	{
		public static IEnumerable<T> Convert<T>(this IEnumerable<DynValue> enumerable, DataType type)
		{
			return from v in enumerable
				where v.Type == type
				select v.ToObject<T>();
		}

		public static IEnumerable<DynValue> OfDataType(this IEnumerable<DynValue> enumerable, DataType type)
		{
			return enumerable.Where((DynValue v) => v.Type == type);
		}

		public static IEnumerable<object> AsObjects(this IEnumerable<DynValue> enumerable)
		{
			return enumerable.Select((DynValue v) => v.ToObject());
		}

		public static IEnumerable<T> AsObjects<T>(this IEnumerable<DynValue> enumerable)
		{
			return enumerable.Select((DynValue v) => v.ToObject<T>());
		}
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, Inherited = false, AllowMultiple = false)]
	public sealed class MoonSharpUserDataAttribute : Attribute
	{
		public InteropAccessMode AccessMode { get; set; }

		public MoonSharpUserDataAttribute()
		{
			AccessMode = InteropAccessMode.Default;
		}
	}
	internal class AutoDescribingUserDataDescriptor : IUserDataDescriptor
	{
		private string m_FriendlyName;

		private Type m_Type;

		public string Name => m_FriendlyName;

		public Type Type => m_Type;

		public AutoDescribingUserDataDescriptor(Type type, string friendlyName)
		{
			m_FriendlyName = friendlyName;
			m_Type = type;
		}

		public DynValue Index(Script script, object obj, DynValue index, bool isDirectIndexing)
		{
			if (obj is IUserDataType userDataType)
			{
				return userDataType.Index(script, index, isDirectIndexing);
			}
			return null;
		}

		public bool SetIndex(Script script, object obj, DynValue index, DynValue value, bool isDirectIndexing)
		{
			if (obj is IUserDataType userDataType)
			{
				return userDataType.SetIndex(script, index, value, isDirectIndexing);
			}
			return false;
		}

		public string AsString(object obj)
		{
			return obj?.ToString();
		}

		public DynValue MetaIndex(Script script, object obj, string metaname)
		{
			if (obj is IUserDataType userDataType)
			{
				return userDataType.MetaIndex(script, metaname);
			}
			return null;
		}

		public bool IsTypeCompatible(Type type, object obj)
		{
			return Framework.Do.IsInstanceOfType(type, obj);
		}
	}
	public enum InteropAccessMode
	{
		Reflection,
		LazyOptimized,
		Preoptimized,
		BackgroundOptimized,
		Hardwired,
		HideMembers,
		NoReflectionAllowed,
		Default
	}
	public enum SymbolRefType
	{
		Local,
		Upvalue,
		Global,
		DefaultEnv
	}
	public class SymbolRef
	{
		private static SymbolRef s_DefaultEnv = new SymbolRef
		{
			i_Type = SymbolRefType.DefaultEnv
		};

		internal SymbolRefType i_Type;

		internal SymbolRef i_Env;

		internal int i_Index;

		internal string i_Name;

		public SymbolRefType Type => i_Type;

		public int Index => i_Index;

		public string Name => i_Name;

		public SymbolRef Environment => i_Env;

		public static SymbolRef DefaultEnv => s_DefaultEnv;

		public static SymbolRef Global(string name, SymbolRef envSymbol)
		{
			return new SymbolRef
			{
				i_Index = -1,
				i_Type = SymbolRefType.Global,
				i_Env = envSymbol,
				i_Name = name
			};
		}

		internal static SymbolRef Local(string name, int index)
		{
			return new SymbolRef
			{
				i_Index = index,
				i_Type = SymbolRefType.Local,
				i_Name = name
			};
		}

		internal static SymbolRef Upvalue(string name, int index)
		{
			return new SymbolRef
			{
				i_Index = index,
				i_Type = SymbolRefType.Upvalue,
				i_Name = name
			};
		}

		public override string ToString()
		{
			if (i_Type == SymbolRefType.DefaultEnv)
			{
				return "(default _ENV)";
			}
			if (i_Type == SymbolRefType.Global)
			{
				return string.Format("{2} : {0} / {1}", i_Type, i_Env, i_Name);
			}
			return string.Format("{2} : {0}[{1}]", i_Type, i_Index, i_Name);
		}

		internal void WriteBinary(BinaryWriter bw)
		{
			bw.Write((byte)i_Type);
			bw.Write(i_Index);
			bw.Write(i_Name);
		}

		internal static SymbolRef ReadBinary(BinaryReader br)
		{
			return new SymbolRef
			{
				i_Type = (SymbolRefType)br.ReadByte(),
				i_Index = br.ReadInt32(),
				i_Name = br.ReadString()
			};
		}

		internal void WriteBinaryEnv(BinaryWriter bw, Dictionary<SymbolRef, int> symbolMap)
		{
			if (i_Env != null)
			{
				bw.Write(symbolMap[i_Env]);
			}
			else
			{
				bw.Write(-1);
			}
		}

		internal void ReadBinaryEnv(BinaryReader br, SymbolRef[] symbolRefs)
		{
			int num = br.ReadInt32();
			if (num >= 0)
			{
				i_Env = symbolRefs[num];
			}
		}
	}
	public enum DataType
	{
		Nil,
		Void,
		Boolean,
		Number,
		String,
		Function,
		Table,
		Tuple,
		UserData,
		Thread,
		ClrFunction,
		TailCallRequest,
		YieldRequest
	}
	public static class LuaTypeExtensions
	{
		internal const DataType MaxMetaTypes = DataType.Table;

		internal const DataType MaxConvertibleTypes = DataType.ClrFunction;

		public static bool CanHaveTypeMetatables(this DataType type)
		{
			return type < DataType.Table;
		}

		public static string ToErrorTypeString(this DataType type)
		{
			return type switch
			{
				DataType.Void => "no value", 
				DataType.Nil => "nil", 
				DataType.Boolean => "boolean", 
				DataType.Number => "number", 
				DataType.String => "string", 
				DataType.Function => "function", 
				DataType.ClrFunction => "function", 
				DataType.Table => "table", 
				DataType.UserData => "userdata", 
				DataType.Thread => "coroutine", 
				_ => $"internal<{type.ToLuaDebuggerString()}>", 
			};
		}

		public static string ToLuaDebuggerString(this DataType type)
		{
			return type.ToString().ToLowerInvariant();
		}

		public static string ToLuaTypeString(this DataType type)
		{
			switch (type)
			{
			case DataType.Nil:
			case DataType.Void:
				return "nil";
			case DataType.Boolean:
				return "boolean";
			case DataType.Number:
				return "number";
			case DataType.String:
				return "string";
			case DataType.Function:
				return "function";
			case DataType.ClrFunction:
				return "function";
			case DataType.Table:
				return "table";
			case DataType.UserData:
				return "userdata";
			case DataType.Thread:
				return "thread";
			default:
				throw new ScriptRuntimeException("Unexpected LuaType {0}", type);
			}
		}
	}
	public enum ColonOperatorBehaviour
	{
		TreatAsDot,
		TreatAsDotOnUserData,
		TreatAsColon
	}
	[AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = false)]
	public sealed class MoonSharpModuleConstantAttribute : Attribute
	{
		public string Name { get; set; }
	}
	internal static class NamespaceDoc
	{
	}
	public class Script : IScriptPrivateResource
	{
		public const string VERSION = "2.0.0.0";

		public const string LUA_VERSION = "5.2";

		private Processor m_MainProcessor;

		private ByteCode m_ByteCode;

		private List<SourceCode> m_Sources = new List<SourceCode>();

		private Table m_GlobalTable;

		private IDebugger m_Debugger;

		private Table[] m_TypeMetatables = new Table[6];

		public static ScriptOptions DefaultOptions { get; private set; }

		public ScriptOptions Options { get; private set; }

		public static ScriptGlobalOptions GlobalOptions { get; private set; }

		public PerformanceStatistics PerformanceStats { get; private set; }

		public Table Globals => m_GlobalTable;

		public bool DebuggerEnabled
		{
			get
			{
				return m_MainProcessor.DebuggerEnabled;
			}
			set
			{
				m_MainProcessor.DebuggerEnabled = value;
			}
		}

		public int SourceCodeCount => m_Sources.Count;

		public Table Registry { get; private set; }

		Script IScriptPrivateResource.OwnerScript => this;

		static Script()
		{
			GlobalOptions = new ScriptGlobalOptions();
			DefaultOptions = new ScriptOptions
			{
				DebugPrint = delegate(string s)
				{
					GlobalOptions.Platform.DefaultPrint(s);
				},
				DebugInput = (string s) => GlobalOptions.Platform.DefaultInput(s),
				CheckThreadAccess = true,
				ScriptLoader = PlatformAutoDetector.GetDefaultScriptLoader(),
				TailCallOptimizationThreshold = 65536
			};
		}

		public Script()
			: this(CoreModules.Preset_Default)
		{
		}

		public Script(CoreModules coreModules)
		{
			Options = new ScriptOptions(DefaultOptions);
			PerformanceStats = new PerformanceStatistics();
			Registry = new Table(this);
			m_ByteCode = new ByteCode(this);
			m_MainProcessor = new Processor(this, m_GlobalTable, m_ByteCode);
			m_GlobalTable = new Table(this).RegisterCoreModules(coreModules);
		}

		public DynValue LoadFunction(string code, Table globalTable = null, string funcFriendlyName = null)
		{
			this.CheckScriptOwnership(globalTable);
			SourceCode sourceCode = new SourceCode($"libfunc_{funcFriendlyName ?? m_Sources.Count.ToString()}", code, m_Sources.Count, this);
			m_Sources.Add(sourceCode);
			int address = Loader_Fast.LoadFunction(this, sourceCode, m_ByteCode, globalTable != null || m_GlobalTable != null);
			SignalSourceCodeChange(sourceCode);
			SignalByteCodeChange();
			return MakeClosure(address, globalTable ?? m_GlobalTable);
		}

		private void SignalByteCodeChange()
		{
			if (m_Debugger != null)
			{
				m_Debugger.SetByteCode(m_ByteCode.Code.Select((Instruction s) => s.ToString()).ToArray());
			}
		}

		private void SignalSourceCodeChange(SourceCode source)
		{
			if (m_Debugger != null)
			{
				m_Debugger.SetSourceCode(source);
			}
		}

		public DynValue LoadString(string code, Table globalTable = null, string codeFriendlyName = null)
		{
			this.CheckScriptOwnership(globalTable);
			if (code.StartsWith("MoonSharp_dump_b64::"))
			{
				code = code.Substring("MoonSharp_dump_b64::".Length);
				using MemoryStream stream = new MemoryStream(Convert.FromBase64String(code));
				return LoadStream(stream, globalTable, codeFriendlyName);
			}
			string text = string.Format("{0}", codeFriendlyName ?? ("chunk_" + m_Sources.Count));
			SourceCode sourceCode = new SourceCode(codeFriendlyName ?? text, code, m_Sources.Count, this);
			m_Sources.Add(sourceCode);
			int address = Loader_Fast.LoadChunk(this, sourceCode, m_ByteCode);
			SignalSourceCodeChange(sourceCode);
			SignalByteCodeChange();
			return MakeClosure(address, globalTable ?? m_GlobalTable);
		}

		public DynValue LoadStream(Stream stream, Table globalTable = null, string codeFriendlyName = null)
		{
			this.CheckScriptOwnership(globalTable);
			Stream stream2 = new UndisposableStream(stream);
			if (!Processor.IsDumpStream(stream2))
			{
				using (StreamReader streamReader = new StreamReader(stream2))
				{
					string code = streamReader.ReadToEnd();
					return LoadString(code, globalTable, codeFriendlyName);
				}
			}
			string text = string.Format("{0}", codeFriendlyName ?? ("dump_" + m_Sources.Count));
			SourceCode sourceCode = new SourceCode(codeFriendlyName ?? text, $"-- This script was decoded from a binary dump - dump_{m_Sources.Count}", m_Sources.Count, this);
			m_Sources.Add(sourceCode);
			bool hasUpvalues;
			int address = m_MainProcessor.Undump(stream2, m_Sources.Count - 1, globalTable ?? m_GlobalTable, out hasUpvalues);
			SignalSourceCodeChange(sourceCode);
			SignalByteCodeChange();
			if (hasUpvalues)
			{
				return MakeClosure(address, globalTable ?? m_GlobalTable);
			}
			return MakeClosure(address);
		}

		public void Dump(DynValue function, Stream stream)
		{
			this.CheckScriptOwnership(function);
			if (function.Type != DataType.Function)
			{
				throw new ArgumentException("function arg is not a function!");
			}
			if (!stream.CanWrite)
			{
				throw new ArgumentException("stream is readonly!");
			}
			Closure.UpvaluesType upvaluesType = function.Function.GetUpvaluesType();
			if (upvaluesType == Closure.UpvaluesType.Closure)
			{
				throw new ArgumentException("function arg has upvalues other than _ENV");
			}
			UndisposableStream stream2 = new UndisposableStream(stream);
			m_MainProcessor.Dump(stream2, function.Function.EntryPointByteCodeLocation, upvaluesType == Closure.UpvaluesType.Environment);
		}

		public DynValue LoadFile(string filename, Table globalContext = null, string friendlyFilename = null)
		{
			this.CheckScriptOwnership(globalContext);
			filename = Options.ScriptLoader.ResolveFileName(filename, globalContext ?? m_GlobalTable);
			object obj = Options.ScriptLoader.LoadFile(filename, globalContext ?? m_GlobalTable);
			if (obj is string)
			{
				return LoadString((string)obj, globalContext, friendlyFilename ?? filename);
			}
			if (obj is byte[])
			{
				using (MemoryStream stream = new MemoryStream((byte[])obj))
				{
					return LoadStream(stream, globalContext, friendlyFilename ?? filename);
				}
			}
			if (obj is Stream)
			{
				try
				{
					return LoadStream((Stream)obj, globalContext, friendlyFilename ?? filename);
				}
				finally
				{
					((Stream)obj).Dispose();
				}
			}
			if (obj == null)
			{
				throw new InvalidCastException("Unexpected null from IScriptLoader.LoadFile");
			}
			throw new InvalidCastException($"Unsupported return type from IScriptLoader.LoadFile : {obj.GetType()}");
		}

		public DynValue DoString(string code, Table globalContext = null, string codeFriendlyName = null)
		{
			DynValue function = LoadString(code, globalContext, codeFriendlyName);
			return Call(function);
		}

		public DynValue DoStream(Stream stream, Table globalContext = null, string codeFriendlyName = null)
		{
			DynValue function = LoadStream(stream, globalContext, codeFriendlyName);
			return Call(function);
		}

		public DynValue DoFile(string filename, Table globalContext = null, string codeFriendlyName = null)
		{
			DynValue function = LoadFile(filename, globalContext, codeFriendlyName);
			return Call(function);
		}

		public static DynValue RunFile(string filename)
		{
			return new Script().DoFile(filename);
		}

		public static DynValue RunString(string code)
		{
			return new Script().DoString(code);
		}

		private DynValue MakeClosure(int address, Table envTable = null)
		{
			this.CheckScriptOwnership(envTable);
			Closure function;
			if (envTable == null)
			{
				Instruction instruction = m_MainProcessor.FindMeta(ref address);
				function = ((instruction == null || instruction.NumVal2 != 0) ? new Closure(this, address, new SymbolRef[0], new DynValue[0]) : new Closure(this, address, new SymbolRef[1] { SymbolRef.Upvalue("_ENV", 0) }, new DynValue[1] { instruction.Value }));
			}
			else
			{
				SymbolRef[] symbols = new SymbolRef[1]
				{
					new SymbolRef
					{
						i_Env = null,
						i_Index = 0,
						i_Name = "_ENV",
						i_Type = SymbolRefType.DefaultEnv
					}
				};
				DynValue[] resolvedLocals = new DynValue[1] { DynValue.NewTable(envTable) };
				function = new Closure(this, address, symbols, resolvedLocals);
			}
			return DynValue.NewClosure(function);
		}

		public DynValue Call(DynValue function)
		{
			return Call(function, new DynValue[0]);
		}

		public DynValue Call(DynValue function, params DynValue[] args)
		{
			this.CheckScriptOwnership(function);
			this.CheckScriptOwnership(args);
			if (function.Type != DataType.Function && function.Type != DataType.ClrFunction)
			{
				DynValue metamethod = m_MainProcessor.GetMetamethod(function, "__call");
				if (metamethod == null)
				{
					throw new ArgumentException("function is not a function and has no __call metamethod.");
				}
				DynValue[] array = new DynValue[args.Length + 1];
				array[0] = function;
				for (int i = 0; i < args.Length; i++)
				{
					array[i + 1] = args[i];
				}
				function = metamethod;
				args = array;
			}
			else if (function.Type == DataType.ClrFunction)
			{
				return function.Callback.ClrCallback(CreateDynamicExecutionContext(function.Callback), new CallbackArguments(args, isMethodCall: false));
			}
			return m_MainProcessor.Call(function, args);
		}

		public DynValue Call(DynValue function, params object[] args)
		{
			DynValue[] array = new DynValue[args.Length];
			for (int i = 0; i < array.Length; i++)
			{
				array[i] = DynValue.FromObject(this, args[i]);
			}
			return Call(function, array);
		}

		public DynValue Call(object function)
		{
			return Call(DynValue.FromObject(this, function));
		}

		public DynValue Call(object function, params object[] args)
		{
			return Call(DynValue.FromObject(this, function), args);
		}

		public DynValue CreateCoroutine(DynValue function)
		{
			this.CheckScriptOwnership(function);
			if (function.Type == DataType.Function)
			{
				return m_MainProcessor.Coroutine_Create(function.Function);
			}
			if (function.Type == DataType.ClrFunction)
			{
				return DynValue.NewCoroutine(new Coroutine(function.Callback));
			}
			throw new ArgumentException("function is not of DataType.Function or DataType.ClrFunction");
		}

		public DynValue CreateCoroutine(object function)
		{
			return CreateCoroutine(DynValue.FromObject(this, function));
		}

		public void AttachDebugger(IDebugger debugger)
		{
			DebuggerEnabled = true;
			m_Debugger = debugger;
			m_MainProcessor.AttachDebugger(debugger);
			foreach (SourceCode source in m_Sources)
			{
				SignalSourceCodeChange(source);
			}
			SignalByteCodeChange();
		}

		public SourceCode GetSourceCode(int sourceCodeID)
		{
			return m_Sources[sourceCodeID];
		}

		public DynValue RequireModule(string modname, Table globalContext = null)
		{
			this.CheckScriptOwnership(globalContext);
			Table globalContext2 = globalContext ?? m_GlobalTable;
			string text = Options.ScriptLoader.ResolveModuleName(modname, globalContext2);
			if (text == null)
			{
				throw new ScriptRuntimeException("module '{0}' not found", modname);
			}
			return LoadFile(text, globalContext, text);
		}

		public Table GetTypeMetatable(DataType type)
		{
			if (type >= DataType.Nil && (int)type < m_TypeMetatables.Length)
			{
				return m_TypeMetatables[(int)type];
			}
			return null;
		}

		public void SetTypeMetatable(DataType type, Table metatable)
		{
			this.CheckScriptOwnership(metatable);
			int num = (int)type;
			if (num >= 0 && num < m_TypeMetatables.Length)
			{
				m_TypeMetatables[num] = metatable;
				return;
			}
			throw new ArgumentException("Specified type not supported : " + type);
		}

		public static void WarmUp()
		{
			new Script(CoreModules.Basic).LoadString("return 1;");
		}

		public DynamicExpression CreateDynamicExpression(string code)
		{
			DynamicExprExpression expr = Loader_Fast.LoadDynamicExpr(this, new SourceCode("__dynamic", code, -1, this));
			return new DynamicExpression(this, code, expr);
		}

		public DynamicExpression CreateConstantDynamicExpression(string code, DynValue constant)
		{
			this.CheckScriptOwnership(constant);
			return new DynamicExpression(this, code, constant);
		}

		internal ScriptExecutionContext CreateDynamicExecutionContext(CallbackFunction func = null)
		{
			return new ScriptExecutionContext(m_MainProcessor, func, null, isDynamic: true);
		}

		public static string GetBanner(string subproduct = null)
		{
			subproduct = ((subproduct != null) ? (subproduct + " ") : "");
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.AppendLine(string.Format("MoonSharp {0}{1} [{2}]", subproduct, "2.0.0.0", GlobalOptions.Platform.GetPlatformName()));
			stringBuilder.AppendLine("Copyright (C) 2014-2016 Marco Mastropaolo");
			stringBuilder.AppendLine("http://www.moonsharp.org");
			return stringBuilder.ToString();
		}
	}
	public class Table : RefIdObject, IScriptPrivateResource
	{
		private readonly LinkedList<TablePair> m_Values;

		private readonly LinkedListIndex<DynValue, TablePair> m_ValueMap;

		private readonly LinkedListIndex<string, TablePair> m_StringMap;

		private readonly LinkedListIndex<int, TablePair> m_ArrayMap;

		private readonly Script m_Owner;

		private int m_InitArray;

		private int m_CachedLength = -1;

		private bool m_ContainsNilEntries;

		private Table m_MetaTable;

		public Script OwnerScript => m_Owner;

		public object this[params object[] keys]
		{
			get
			{
				return Get(keys).ToObject();
			}
			set
			{
				Set(keys, DynValue.FromObject(OwnerScript, value));
			}
		}

		public object this[object key]
		{
			get
			{
				return Get(key).ToObject();
			}
			set
			{
				Set(key, DynValue.FromObject(OwnerScript, value));
			}
		}

		public int Length
		{
			get
			{
				if (m_CachedLength < 0)
				{
					m_CachedLength = 0;
					for (int i = 1; m_ArrayMap.ContainsKey(i) && !m_ArrayMap.Find(i).Value.Value.IsNil(); i++)
					{
						m_CachedLength = i;
					}
				}
				return m_CachedLength;
			}
		}

		public Table MetaTable
		{
			get
			{
				return m_MetaTable;
			}
			set
			{
				this.CheckScriptOwnership(m_MetaTable);
				m_MetaTable = value;
			}
		}

		public IEnumerable<TablePair> Pairs => m_Values.Select((TablePair n) => new TablePair(n.Key, n.Value));

		public IEnumerable<DynValue> Keys => m_Values.Select((TablePair n) => n.Key);

		public IEnumerable<DynValue> Values => m_Values.Select((TablePair n) => n.Value);

		public Table(Script owner)
		{
			m_Values = new LinkedList<TablePair>();
			m_StringMap = new LinkedListIndex<string, TablePair>(m_Values);
			m_ArrayMap = new LinkedListIndex<int, TablePair>(m_Values);
			m_ValueMap = new LinkedListIndex<DynValue, TablePair>(m_Values);
			m_Owner = owner;
		}

		public Table(Script owner, params DynValue[] arrayValues)
			: this(owner)
		{
			for (int i = 0; i < arrayValues.Length; i++)
			{
				Set(DynValue.NewNumber(i + 1), arrayValues[i]);
			}
		}

		public void Clear()
		{
			m_Values.Clear();
			m_StringMap.Clear();
			m_ArrayMap.Clear();
			m_ValueMap.Clear();
			m_CachedLength = -1;
		}

		private int GetIntegralKey(double d)
		{
			int num = (int)d;
			if (d >= 1.0 && d == (double)num)
			{
				return num;
			}
			return -1;
		}

		private Table ResolveMultipleKeys(object[] keys, out object key)
		{
			Table table = this;
			key = ((keys.Length != 0) ? keys[0] : null);
			for (int i = 1; i < keys.Length; i++)
			{
				DynValue obj = table.RawGet(key) ?? throw new ScriptRuntimeException("Key '{0}' did not point to anything");
				if (obj.Type != DataType.Table)
				{
					throw new ScriptRuntimeException("Key '{0}' did not point to a table");
				}
				table = obj.Table;
				key = keys[i];
			}
			return table;
		}

		public void Append(DynValue value)
		{
			this.CheckScriptOwnership(value);
			PerformTableSet(m_ArrayMap, Length + 1, DynValue.NewNumber(Length + 1), value, isNumber: true, Length + 1);
		}

		private void PerformTableSet<T>(LinkedListIndex<T, TablePair> listIndex, T key, DynValue keyDynValue, DynValue value, bool isNumber, int appendKey)
		{
			TablePair tablePair = listIndex.Set(key, new TablePair(keyDynValue, value));
			if (m_ContainsNilEntries && value.IsNotNil() && (tablePair.Value == null || tablePair.Value.IsNil()))
			{
				CollectDeadKeys();
			}
			else if (value.IsNil())
			{
				m_ContainsNilEntries = true;
				if (isNumber)
				{
					m_CachedLength = -1;
				}
			}
			else
			{
				if (!isNumber || (tablePair.Value != null && !tablePair.Value.IsNilOrNan()))
				{
					return;
				}
				if (appendKey >= 0)
				{
					LinkedListNode<TablePair> linkedListNode = m_ArrayMap.Find(appendKey + 1);
					if (linkedListNode == null || linkedListNode.Value.Value == null || linkedListNode.Value.Value.IsNil())
					{
						m_CachedLength++;
					}
					else
					{
						m_CachedLength = -1;
					}
				}
				else
				{
					m_CachedLength = -1;
				}
			}
		}

		public void Set(string key, DynValue value)
		{
			if (key == null)
			{
				throw ScriptRuntimeException.TableIndexIsNil();
			}
			this.CheckScriptOwnership(value);
			PerformTableSet(m_StringMap, key, DynValue.NewString(key), value, isNumber: false, -1);
		}

		public void Set(int key, DynValue value)
		{
			this.CheckScriptOwnership(value);
			PerformTableSet(m_ArrayMap, key, DynValue.NewNumber(key), value, isNumber: true, -1);
		}

		public void Set(DynValue key, DynValue value)
		{
			if (key.IsNilOrNan())
			{
				if (key.IsNil())
				{
					throw ScriptRuntimeException.TableIndexIsNil();
				}
				throw ScriptRuntimeException.TableIndexIsNaN();
			}
			if (key.Type == DataType.String)
			{
				Set(key.String, value);
				return;
			}
			if (key.Type == DataType.Number)
			{
				int integralKey = GetIntegralKey(key.Number);
				if (integralKey > 0)
				{
					Set(integralKey, value);
					return;
				}
			}
			this.CheckScriptOwnership(key);
			this.CheckScriptOwnership(value);
			PerformTableSet(m_ValueMap, key, key, value, isNumber: false, -1);
		}

		public void Set(object key, DynValue value)
		{
			if (key == null)
			{
				throw ScriptRuntimeException.TableIndexIsNil();
			}
			if (key is string)
			{
				Set((string)key, value);
			}
			else if (key is int)
			{
				Set((int)key, value);
			}
			else
			{
				Set(DynValue.FromObject(OwnerScript, key), value);
			}
		}

		public void Set(object[] keys, DynValue value)
		{
			if (keys == null || keys.Length == 0)
			{
				throw ScriptRuntimeException.TableIndexIsNil();
			}
			ResolveMultipleKeys(keys, out var key).Set(key, value);
		}

		public DynValue Get(string key)
		{
			return RawGet(key) ?? DynValue.Nil;
		}

		public DynValue Get(int key)
		{
			return RawGet(key) ?? DynValue.Nil;
		}

		public DynValue Get(DynValue key)
		{
			return RawGet(key) ?? DynValue.Nil;
		}

		public DynValue Get(object key)
		{
			return RawGet(key) ?? DynValue.Nil;
		}

		public DynValue Get(params object[] keys)
		{
			return RawGet(keys) ?? DynValue.Nil;
		}

		private static DynValue RawGetValue(LinkedListNode<TablePair> linkedListNode)
		{
			return linkedListNode?.Value.Value;
		}

		public DynValue RawGet(string key)
		{
			return RawGetValue(m_StringMap.Find(key));
		}

		public DynValue RawGet(int key)
		{
			return RawGetValue(m_ArrayMap.Find(key));
		}

		public DynValue RawGet(DynValue key)
		{
			if (key.Type == DataType.String)
			{
				return RawGet(key.String);
			}
			if (key.Type == DataType.Number)
			{
				int integralKey = GetIntegralKey(key.Number);
				if (integralKey > 0)
				{
					return RawGet(integralKey);
				}
			}
			return RawGetValue(m_ValueMap.Find(key));
		}

		public DynValue RawGet(object key)
		{
			if (key == null)
			{
				return null;
			}
			if (key is string)
			{
				return RawGet((string)key);
			}
			if (key is int)
			{
				return RawGet((int)key);
			}
			return RawGet(DynValue.FromObject(OwnerScript, key));
		}

		public DynValue RawGet(params object[] keys)
		{
			if (keys == null || keys.Length == 0)
			{
				return null;
			}
			object key;
			return ResolveMultipleKeys(keys, out key).RawGet(key);
		}

		private bool PerformTableRemove<T>(LinkedListIndex<T, TablePair> listIndex, T key, bool isNumber)
		{
			bool num = listIndex.Remove(key);
			if (num && isNumber)
			{
				m_CachedLength = -1;
			}
			return num;
		}

		public bool Remove(string key)
		{
			return PerformTableRemove(m_StringMap, key, isNumber: false);
		}

		public bool Remove(int key)
		{
			return PerformTableRemove(m_ArrayMap, key, isNumber: true);
		}

		public bool Remove(DynValue key)
		{
			if (key.Type == DataType.String)
			{
				return Remove(key.String);
			}
			if (key.Type == DataType.Number)
			{
				int integralKey = GetIntegralKey(key.Number);
				if (integralKey > 0)
				{
					return Remove(integralKey);
				}
			}
			return PerformTableRemove(m_ValueMap, key, isNumber: false);
		}

		public bool Remove(object key)
		{
			if (key is string)
			{
				return Remove((string)key);
			}
			if (key is int)
			{
				return Remove((int)key);
			}
			return Remove(DynValue.FromObject(OwnerScript, key));
		}

		public bool Remove(params object[] keys)
		{
			if (keys == null || keys.Length == 0)
			{
				return false;
			}
			object key;
			return ResolveMultipleKeys(keys, out key).Remove(key);
		}

		public void CollectDeadKeys()
		{
			for (LinkedListNode<TablePair> linkedListNode = m_Values.First; linkedListNode != null; linkedListNode = linkedListNode.Next)
			{
				if (linkedListNode.Value.Value.IsNil())
				{
					Remove(linkedListNode.Value.Key);
				}
			}
			m_ContainsNilEntries = false;
			m_CachedLength = -1;
		}

		public TablePair? NextKey(DynValue v)
		{
			if (v.IsNil())
			{
				LinkedListNode<TablePair> first = m_Values.First;
				if (first == null)
				{
					return TablePair.Nil;
				}
				if (first.Value.Value.IsNil())
				{
					return NextKey(first.Value.Key);
				}
				return first.Value;
			}
			if (v.Type == DataType.String)
			{
				return GetNextOf(m_StringMap.Find(v.String));
			}
			if (v.Type == DataType.Number)
			{
				int integralKey = GetIntegralKey(v.Number);
				if (integralKey > 0)
				{
					return GetNextOf(m_ArrayMap.Find(integralKey));
				}
			}
			return GetNextOf(m_ValueMap.Find(v));
		}

		private TablePair? GetNextOf(LinkedListNode<TablePair> linkedListNode)
		{
			do
			{
				if (linkedListNode == null)
				{
					return null;
				}
				if (linkedListNode.Next == null)
				{
					return TablePair.Nil;
				}
				linkedListNode = linkedListNode.Next;
			}
			while (linkedListNode.Value.Value.IsNil());
			return linkedListNode.Value;
		}

		internal void InitNextArrayKeys(DynValue val, bool lastpos)
		{
			if (val.Type == DataType.Tuple && lastpos)
			{
				DynValue[] tuple = val.Tuple;
				foreach (DynValue val2 in tuple)
				{
					InitNextArrayKeys(val2, lastpos: true);
				}
			}
			else
			{
				Set(++m_InitArray, val.ToScalar());
			}
		}
	}
	[Flags]
	public enum CoreModules
	{
		None = 0,
		Basic = 0x40,
		GlobalConsts = 1,
		TableIterators = 2,
		Metatables = 4,
		String = 8,
		LoadMethods = 0x10,
		Table = 0x20,
		ErrorHandling = 0x80,
		Math = 0x100,
		Coroutine = 0x200,
		Bit32 = 0x400,
		OS_Time = 0x800,
		OS_System = 0x1000,
		IO = 0x2000,
		Debug = 0x4000,
		Dynamic = 0x8000,
		Json = 0x10000,
		Preset_HardSandbox = 0x56B,
		Preset_SoftSandbox = 0x18FEF,
		Preset_Default = 0x1BFFF,
		Preset_Complete = 0x1FFFF
	}
	internal static class CoreModules_ExtensionMethods
	{
		public static bool Has(this CoreModules val, CoreModules flag)
		{
			return (val & flag) == flag;
		}
	}
	public static class ModuleRegister
	{
		public static Table RegisterCoreModules(this Table table, CoreModules modules)
		{
			modules = Script.GlobalOptions.Platform.FilterSupportedCoreModules(modules);
			if (modules.Has(CoreModules.GlobalConsts))
			{
				table.RegisterConstants();
			}
			if (modules.Has(CoreModules.TableIterators))
			{
				table.RegisterModuleType<TableIteratorsModule>();
			}
			if (modules.Has(CoreModules.Basic))
			{
				table.RegisterModuleType<BasicModule>();
			}
			if (modules.Has(CoreModules.Metatables))
			{
				table.RegisterModuleType<MetaTableModule>();
			}
			if (modules.Has(CoreModules.String))
			{
				table.RegisterModuleType<StringModule>();
			}
			if (modules.Has(CoreModules.LoadMethods))
			{
				table.RegisterModuleType<LoadModule>();
			}
			if (modules.Has(CoreModules.Table))
			{
				table.RegisterModuleType<TableModule>();
			}
			if (modules.Has(CoreModules.Table))
			{
				table.RegisterModuleType<TableModule_Globals>();
			}
			if (modules.Has(CoreModules.ErrorHandling))
			{
				table.RegisterModuleType<ErrorHandlingModule>();
			}
			if (modules.Has(CoreModules.Math))
			{
				table.RegisterModuleType<MathModule>();
			}
			if (modules.Has(CoreModules.Coroutine))
			{
				table.RegisterModuleType<CoroutineModule>();
			}
			if (modules.Has(CoreModules.Bit32))
			{
				table.RegisterModuleType<Bit32Module>();
			}
			if (modules.Has(CoreModules.Dynamic))
			{
				table.RegisterModuleType<DynamicModule>();
			}
			if (modules.Has(CoreModules.OS_System))
			{
				table.RegisterModuleType<OsSystemModule>();
			}
			if (modules.Has(CoreModules.OS_Time))
			{
				table.RegisterModuleType<OsTimeModule>();
			}
			if (modules.Has(CoreModules.IO))
			{
				table.RegisterModuleType<IoModule>();
			}
			if (modules.Has(CoreModules.Debug))
			{
				table.RegisterModuleType<DebugModule>();
			}
			if (modules.Has(CoreModules.Json))
			{
				table.RegisterModuleType<JsonModule>();
			}
			return table;
		}

		public static Table RegisterConstants(this Table table)
		{
			DynValue dynValue = DynValue.NewTable(table.OwnerScript);
			Table table2 = dynValue.Table;
			table.Set("_G", DynValue.NewTable(table));
			table.Set("_VERSION", DynValue.NewString(string.Format("MoonSharp {0}", "2.0.0.0")));
			table.Set("_MOONSHARP", dynValue);
			table2.Set("version", DynValue.NewString("2.0.0.0"));
			table2.Set("luacompat", DynValue.NewString("5.2"));
			table2.Set("platform", DynValue.NewString(Script.GlobalOptions.Platform.GetPlatformName()));
			table2.Set("is_aot", DynValue.NewBoolean(Script.GlobalOptions.Platform.IsRunningOnAOT()));
			table2.Set("is_unity", DynValue.NewBoolean(PlatformAutoDetector.IsRunningOnUnity));
			table2.Set("is_mono", DynValue.NewBoolean(PlatformAutoDetector.IsRunningOnMono));
			table2.Set("is_clr4", DynValue.NewBoolean(PlatformAutoDetector.IsRunningOnClr4));
			table2.Set("is_pcl", DynValue.NewBoolean(PlatformAutoDetector.IsPortableFramework));
			table2.Set("banner", DynValue.NewString(Script.GetBanner()));
			return table;
		}

		public static Table RegisterModuleType(this Table gtable, Type t)
		{
			Table table = CreateModuleNamespace(gtable, t);
			foreach (MethodInfo item in from __mi in Framework.Do.GetMethods(t)
				where __mi.IsStatic
				select __mi)
			{
				if (item.GetCustomAttributes(typeof(MoonSharpModuleMethodAttribute), inherit: false).ToArray().Length != 0)
				{
					MoonSharpModuleMethodAttribute moonSharpModuleMethodAttribute = (MoonSharpModuleMethodAttribute)item.GetCustomAttributes(typeof(MoonSharpModuleMethodAttribute), inherit: false).First();
					if (!CallbackFunction.CheckCallbackSignature(item, requirePublicVisibility: true))
					{
						throw new ArgumentException($"Method {item.Name} does not have the right signature.");
					}
					Func<ScriptExecutionContext, CallbackArguments, DynValue> callBack = (Func<ScriptExecutionContext, CallbackArguments, DynValue>)Delegate.CreateDelegate(typeof(Func<ScriptExecutionContext, CallbackArguments, DynValue>), item);
					string text = ((!string.IsNullOrEmpty(moonSharpModuleMethodAttribute.Name)) ? moonSharpModuleMethodAttribute.Name : item.Name);
					table.Set(text, DynValue.NewCallback(callBack, text));
				}
				else if (item.Name == "MoonSharpInit")
				{
					object[] parameters = new object[2] { gtable, table };
					item.Invoke(null, parameters);
				}
			}
			foreach (FieldInfo item2 in from _mi in Framework.Do.GetFields(t)
				where _mi.IsStatic && _mi.GetCustomAttributes(typeof(MoonSharpModuleMethodAttribute), inherit: false).ToArray().Length != 0
				select _mi)
			{
				MoonSharpModuleMethodAttribute moonSharpModuleMethodAttribute2 = (MoonSharpModuleMethodAttribute)item2.GetCustomAttributes(typeof(MoonSharpModuleMethodAttribute), inherit: false).First();
				string name = ((!string.IsNullOrEmpty(moonSharpModuleMethodAttribute2.Name)) ? moonSharpModuleMethodAttribute2.Name : item2.Name);
				RegisterScriptField(item2, null, table, t, name);
			}
			foreach (FieldInfo item3 in from _mi in Framework.Do.GetFields(t)
				where _mi.IsStatic && _mi.GetCustomAttributes(typeof(MoonSharpModuleConstantAttribute), inherit: false).ToArray().Length != 0
				select _mi)
			{
				MoonSharpModuleConstantAttribute moonSharpModuleConstantAttribute = (MoonSharpModuleConstantAttribute)item3.GetCustomAttributes(typeof(MoonSharpModuleConstantAttribute), inherit: false).First();
				string name2 = ((!string.IsNullOrEmpty(moonSharpModuleConstantAttribute.Name)) ? moonSharpModuleConstantAttribute.Name : item3.Name);
				RegisterScriptFieldAsConst(item3, null, table, t, name2);
			}
			return gtable;
		}

		private static void RegisterScriptFieldAsConst(FieldInfo fi, object o, Table table, Type t, string name)
		{
			if (fi.FieldType == typeof(string))
			{
				string str = fi.GetValue(o) as string;
				table.Set(name, DynValue.NewString(str));
				return;
			}
			if (fi.FieldType == typeof(double))
			{
				double num = (double)fi.GetValue(o);
				table.Set(name, DynValue.NewNumber(num));
				return;
			}
			throw new ArgumentException($"Field {name} does not have the right type - it must be string or double.");
		}

		private static void RegisterScriptField(FieldInfo fi, object o, Table table, Type t, string name)
		{
			if (fi.FieldType != typeof(string))
			{
				throw new ArgumentException($"Field {name} does not have the right type - it must be string.");
			}
			string code = fi.GetValue(o) as string;
			DynValue value = table.OwnerScript.LoadFunction(code, table, name);
			table.Set(name, value);
		}

		private static Table CreateModuleNamespace(Table gtable, Type t)
		{
			MoonSharpModuleAttribute moonSharpModuleAttribute = (MoonSharpModuleAttribute)Framework.Do.GetCustomAttributes(t, typeof(MoonSharpModuleAttribute), inherit: false).First();
			if (string.IsNullOrEmpty(moonSharpModuleAttribute.Namespace))
			{
				return gtable;
			}
			Table table = null;
			DynValue dynValue = gtable.Get(moonSharpModuleAttribute.Namespace);
			if (dynValue.Type == DataType.Table)
			{
				table = dynValue.Table;
			}
			else
			{
				table = new Table(gtable.OwnerScript);
				gtable.Set(moonSharpModuleAttribute.Namespace, DynValue.NewTable(table));
			}
			DynValue dynValue2 = gtable.RawGet("package");
			if (dynValue2 == null || dynValue2.Type != DataType.Table)
			{
				gtable.Set("package", dynValue2 = DynValue.NewTable(gtable.OwnerScript));
			}
			DynValue dynValue3 = dynValue2.Table.RawGet("loaded");
			if (dynValue3 == null || dynValue3.Type != DataType.Table)
			{
				dynValue2.Table.Set("loaded", dynValue3 = DynValue.NewTable(gtable.OwnerScript));
			}
			dynValue3.Table.Set(moonSharpModuleAttribute.Namespace, DynValue.NewTable(table));
			return table;
		}

		public static Table RegisterModuleType<T>(this Table table)
		{
			return table.RegisterModuleType(typeof(T));
		}
	}
	[AttributeUsage(AttributeTargets.Method | AttributeTargets.Field, Inherited = false, AllowMultiple = false)]
	public sealed class MoonSharpModuleMethodAttribute : Attribute
	{
		public string Name { get; set; }
	}
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	public sealed class MoonSharpModuleAttribute : Attribute
	{
		public string Namespace { get; set; }
	}
	public class ScriptGlobalOptions
	{
		public CustomConvertersCollection CustomConverters { get; set; }

		public IPlatformAccessor Platform { get; set; }

		public bool RethrowExceptionNested { get; set; }

		internal ScriptGlobalOptions()
		{
			Platform = PlatformAutoDetector.GetDefaultPlatform();
			CustomConverters = new CustomConvertersCollection();
		}
	}
	public class ScriptOptions
	{
		public IScriptLoader ScriptLoader { get; set; }

		public Action<string> DebugPrint { get; set; }

		public Func<string, string> DebugInput { get; set; }

		public bool Us