Xanathar 10 سال پیش
والد
کامیت
ae4a7fb104

+ 1 - 1
src/MoonSharp.Interpreter/CoreLib/IO/FileUserData.cs

@@ -10,7 +10,7 @@ namespace MoonSharp.Interpreter.CoreLib.IO
 	{
 		public FileUserData(Script script, string filename, Encoding encoding, string mode)
 		{
-			Stream stream = Script.Platform.OpenFileForIO(script, filename, encoding, mode);
+			Stream stream = Script.Platform.IO_OpenFile(script, filename, encoding, mode);
 
 			StreamReader reader = (stream.CanRead) ? new StreamReader(stream, encoding) : null;
 			StreamWriter writer = (stream.CanWrite) ? new StreamWriter(stream, encoding) : null;

+ 3 - 8
src/MoonSharp.Interpreter/CoreLib/IoModule.cs

@@ -12,7 +12,6 @@ namespace MoonSharp.Interpreter.CoreLib
 	[MoonSharpModule(Namespace = "io")]
 	public class IoModule
 	{
-
 		public static void MoonSharpInit(Table globalTable, Table ioTable)
 		{
 			UserData.RegisterType<FileUserDataBase>(InteropAccessMode.Default, "file");
@@ -53,7 +52,7 @@ namespace MoonSharp.Interpreter.CoreLib
 		{
 			Table R = S.Registry;
 
-			optionsStream = optionsStream ?? Script.Platform.GetStandardStream(file);
+			optionsStream = optionsStream ?? Script.Platform.IO_GetStandardStream(file);
 
 			FileUserDataBase udb = null;
 
@@ -168,7 +167,7 @@ namespace MoonSharp.Interpreter.CoreLib
 			{
 				List<DynValue> readLines = new List<DynValue>();
 
-				using (var stream = Script.Platform.OpenFileForIO(executionContext.GetScript(), filename, null, "r"))
+				using (var stream = Script.Platform.IO_OpenFile(executionContext.GetScript(), filename, null, "r"))
 				{
 					using (var reader = new System.IO.StreamReader(stream))
 					{
@@ -288,11 +287,7 @@ namespace MoonSharp.Interpreter.CoreLib
 		[MoonSharpMethod]
 		public static DynValue tmpfile(ScriptExecutionContext executionContext, CallbackArguments args)
 		{
-#if PCL
-			string tmpfilename = "tmp" + Guid.NewGuid().ToString("N");
-#else
-			string tmpfilename = System.IO.Path.GetTempFileName();
-#endif
+			string tmpfilename = Script.Platform.IO_OS_GetTempFilename();
 			FileUserDataBase file = Open(executionContext, tmpfilename, GetUTF8Encoding(), "w");
 			return UserData.Create(file);
 		}

+ 8 - 13
src/MoonSharp.Interpreter/CoreLib/OsSystemModule.cs

@@ -11,7 +11,6 @@ namespace MoonSharp.Interpreter.CoreLib
 	[MoonSharpModule(Namespace = "os")]
 	public class OsSystemModule
 	{
-#if !PCL
 		[MoonSharpMethod]
 		public static DynValue execute(ScriptExecutionContext executionContext, CallbackArguments args)
 		{
@@ -25,15 +24,12 @@ namespace MoonSharp.Interpreter.CoreLib
 			{
 				try
 				{
-					ProcessStartInfo psi = new ProcessStartInfo("cmd.exe", string.Format("/C {0}", v.String));
-					psi.ErrorDialog = false;
+					int exitCode = Script.Platform.OS_Execute(v.String);
 
-					Process proc = Process.Start(psi);
-					proc.WaitForExit();
 					return DynValue.NewTuple(
 						DynValue.Nil,
 						DynValue.NewString("exit"),
-						DynValue.NewNumber(proc.ExitCode));
+						DynValue.NewNumber(exitCode));
 				}
 				catch (Exception)
 				{
@@ -52,7 +48,7 @@ namespace MoonSharp.Interpreter.CoreLib
 			if (v_exitCode.IsNotNil())
 				exitCode = (int)v_exitCode.Number;
 
-			Environment.Exit(exitCode);
+			Script.Platform.OS_ExitFast(exitCode);
 
 			throw new InvalidOperationException("Unreachable code.. reached.");
 		}
@@ -77,9 +73,9 @@ namespace MoonSharp.Interpreter.CoreLib
 
 			try
 			{
-				if (File.Exists(fileName))
+				if (Script.Platform.OS_FileExists(fileName))
 				{
-					File.Delete(fileName);
+					Script.Platform.OS_FileDelete(fileName);
 					return DynValue.True;
 				}
 				else
@@ -104,14 +100,14 @@ namespace MoonSharp.Interpreter.CoreLib
 
 			try
 			{
-				if (!File.Exists(fileNameOld))
+				if (!Script.Platform.OS_FileExists(fileNameOld))
 				{
 					return DynValue.NewTuple(DynValue.Nil,
 						DynValue.NewString("{0}: No such file or directory.", fileNameOld),
 						DynValue.NewNumber(-1));
 				}
 
-				File.Move(fileNameOld, fileNameNew);
+				Script.Platform.OS_FileMove(fileNameOld, fileNameNew);
 				return DynValue.True;
 			}
 			catch (Exception ex)
@@ -129,8 +125,7 @@ namespace MoonSharp.Interpreter.CoreLib
 		[MoonSharpMethod]
 		public static DynValue tmpname(ScriptExecutionContext executionContext, CallbackArguments args)
 		{
-			return DynValue.NewString(Path.GetTempFileName());
+			return DynValue.NewString(Script.Platform.IO_OS_GetTempFilename());
 		}
-#endif
 	}
 }

+ 2 - 1
src/MoonSharp.Interpreter/MoonSharp.Interpreter.net35-client.csproj

@@ -206,7 +206,8 @@
     <Compile Include="Platforms\IPlatformAccessor.cs" />
     <Compile Include="Platforms\PlatformAccessorBase.cs" />
     <Compile Include="Platforms\PlatformAutoSelector.cs" />
-    <Compile Include="Platforms\SandboxedPlatformAccessor.cs" />
+    <Compile Include="Platforms\LimitedPlatformAccessorBase.cs" />
+    <Compile Include="Platforms\PortableFrameworkAccessor.cs" />
     <Compile Include="Platforms\StandardFileType.cs" />
     <Compile Include="Platforms\StandardPlatformAccessor.cs" />
     <Compile Include="RuntimeAbstraction\PortableWrappers\Attributes.cs" />

+ 96 - 25
src/MoonSharp.Interpreter/Platforms/IPlatformAccessor.cs

@@ -6,29 +6,29 @@ using System.Text;
 
 namespace MoonSharp.Interpreter.Platforms
 {
+	/// <summary>
+	/// Interface to abstract all accesses made to the underlying platform (OS, framework) by the scripting engine.
+	/// Can be used both to support "non-standard" platforms (i.e. non-posix, non-windows) and/or to sandbox the behaviour
+	/// of the scripting engine.
+	/// </summary>
 	public interface IPlatformAccessor
 	{
-		/// <summary>
-		/// A function used to open files in the 'io' and 'os' modules. 
-		/// It should return a correctly initialized Stream for the given file and access
-		/// </summary>
-		/// <param name="filename">The filename.</param>
-		/// <param name="encoding">The encoding.</param>
-		/// <param name="mode">The mode (as per Lua usage - e.g. 'w+', 'rb', etc.).</param>
-		/// <returns></returns>
-		Stream OpenFileForIO(Script script, string filename, Encoding encoding, string mode);
-
 		/// <summary>
 		/// Opens a file for reading the script code.
+		/// It can return either a string, a byte[] or a Stream.
+		/// If a byte[] is returned, the content is assumed to be a serialized (dumped) bytecode. If it's a string, it's
+		/// assumed to be either a script or the output of a string.dump call. If a Stream, autodetection takes place.
 		/// </summary>
+		/// <param name="script">The script.</param>
 		/// <param name="file">The file.</param>
 		/// <param name="globalContext">The global context.</param>
-		/// <returns></returns>
-		object LoadFile(Script script, string file, Table globalContext);
+		/// <returns>A string, a byte[] or a Stream.</returns>
+		object OpenScriptFile(Script script, string file, Table globalContext);
 
 		/// <summary>
-		/// Resolves the name of the module.
+		/// Resolves the name of a module to a filename (which will later be passed to OpenScriptFile)
 		/// </summary>
+		/// <param name="script">The script.</param>
 		/// <param name="modname">The modname.</param>
 		/// <param name="globalContext">The global context.</param>
 		/// <returns></returns>
@@ -38,37 +38,108 @@ namespace MoonSharp.Interpreter.Platforms
 		/// Filters the CoreModules enumeration to exclude non-supported operations
 		/// </summary>
 		/// <param name="module">The requested modules.</param>
-		/// <returns>The requested modules, with unsupported modules filtered out.</returns>
+		/// <returns>
+		/// The requested modules, with unsupported modules filtered out.
+		/// </returns>
 		CoreModules FilterSupportedCoreModules(CoreModules module);
 
 		/// <summary>
-		/// Gets an environment variable.
+		/// Gets an environment variable. Must be implemented, but an implementation is allowed
+		/// to always return null if a more meaningful implementation cannot be achieved or is
+		/// not desired.
 		/// </summary>
 		/// <param name="envvarname">The envvarname.</param>
-		/// <returns>The environment variable value, or null if not found</returns>
+		/// <returns>
+		/// The environment variable value, or null if not found
+		/// </returns>
 		string GetEnvironmentVariable(string envvarname);
 
 		/// <summary>
-		/// Checks if a file exists
+		/// Determines whether the application is running in AOT (ahead-of-time) mode
 		/// </summary>
-		/// <param name="name">The file name.</param>
-		bool FileExists(string name);
+		bool IsRunningOnAOT();
 
 		/// <summary>
-		/// Determines whether the application is running in AOT (ahead-of-time) mode
+		/// Gets the name of the platform (used for debug purposes).
 		/// </summary>
-		bool IsRunningOnAOT();
+		/// <returns>The name of the platform (used for debug purposes)</returns>
+		string GetPlatformName();
 
+		/// <summary>
+		/// Default handler for 'print' calls. Can be customized in ScriptOptions
+		/// </summary>
+		/// <param name="content">The content.</param>
+		void DefaultPrint(string content);
 
-		string GetPlatformName();
+		/// <summary>
+		/// Default handler for interactive line input calls. Can be customized in ScriptOptions.
+		/// If a meaningful implementation cannot be provided, this method should return null.
+		/// </summary>
+		/// <returns></returns>
+		string DefaultInput();
 
-		Stream GetStandardStream(StandardFileType type);
+		/// <summary>
+		/// A function used to open files in the 'io' module. 
+		/// Can have an invalid implementation if 'io' module is filtered out.
+		/// It should return a correctly initialized Stream for the given file and access
+		/// </summary>
+		/// <param name="filename">The filename.</param>
+		/// <param name="encoding">The encoding.</param>
+		/// <param name="mode">The mode (as per Lua usage - e.g. 'w+', 'rb', etc.).</param>
+		/// <returns></returns>
+		Stream IO_OpenFile(Script script, string filename, Encoding encoding, string mode);
 
+		/// <summary>
+		/// Gets a standard stream (stdin, stdout, stderr).
+		/// </summary>
+		/// <param name="type">The type.</param>
+		/// <returns></returns>
+		Stream IO_GetStandardStream(StandardFileType type);
 
+		/// <summary>
+		/// Gets a temporary filename. Used in 'io' and 'os' modules.
+		/// Can have an invalid implementation if 'io' and 'os' modules are filtered out.
+		/// </summary>
+		/// <returns></returns>
+		string IO_OS_GetTempFilename();
 
-		void DefaultPrint(string content);
-		string DefaultInput();
+		/// <summary>
+		/// Exits the process, returning the specified exit code.
+		/// Can have an invalid implementation if the 'os' module is filtered out.
+		/// </summary>
+		/// <param name="exitCode">The exit code.</param>
+		void OS_ExitFast(int exitCode);
+
+		/// <summary>
+		/// Checks if a file exists. Used by the 'os' module.
+		/// Can have an invalid implementation if the 'os' module is filtered out.
+		/// </summary>
+		/// <param name="file">The file.</param>
+		/// <returns>True if the file exists, false otherwise.</returns>
+		bool OS_FileExists(string file);
+
+		/// <summary>
+		/// Deletes the specified file. Used by the 'os' module.
+		/// Can have an invalid implementation if the 'os' module is filtered out.
+		/// </summary>
+		/// <param name="file">The file.</param>
+		void OS_FileDelete(string file);
 
+		/// <summary>
+		/// Moves the specified file. Used by the 'os' module.
+		/// Can have an invalid implementation if the 'os' module is filtered out.
+		/// </summary>
+		/// <param name="src">The source.</param>
+		/// <param name="dst">The DST.</param>
+		void OS_FileMove(string src, string dst);
+
+		/// <summary>
+		/// Executes the specified command line, returning the child process exit code and blocking in the meantime.
+		/// Can have an invalid implementation if the 'os' module is filtered out.
+		/// </summary>
+		/// <param name="cmdline">The cmdline.</param>
+		/// <returns></returns>
+		int OS_Execute(string cmdline);
 
 	}
 }

+ 145 - 0
src/MoonSharp.Interpreter/Platforms/LimitedPlatformAccessorBase.cs

@@ -0,0 +1,145 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace MoonSharp.Interpreter.Platforms
+{
+	/// <summary>
+	/// A class implementing all the bits needed to have a minimal 
+	/// </summary>
+	public abstract class LimitedPlatformAccessorBase : PlatformAccessorBase
+	{
+		/// <summary>
+		/// Gets an environment variable. Must be implemented, but an implementation is allowed
+		/// to always return null if a more meaningful implementation cannot be achieved or is
+		/// not desired.
+		/// </summary>
+		/// <param name="envvarname">The envvarname.</param>
+		/// <returns>
+		/// The environment variable value, or null if not found
+		/// </returns>
+		public override string GetEnvironmentVariable(string envvarname)
+		{
+			return null;
+		}
+
+		/// <summary>
+		/// Filters the CoreModules enumeration to exclude non-supported operations
+		/// </summary>
+		/// <param name="module">The requested modules.</param>
+		/// <returns>
+		/// The requested modules, with unsupported modules filtered out.
+		/// </returns>
+		public override CoreModules FilterSupportedCoreModules(CoreModules module)
+		{
+			return module & (~(CoreModules.IO | CoreModules.OS_System));
+		}
+
+		/// <summary>
+		/// A function used to open files in the 'io' module. 
+		/// LimitedPlatformAccessorBase does NOT offer a meaningful implementation of this method and
+		/// thus does not support 'io' and 'os' modules.
+		/// </summary>
+		/// <param name="script"></param>
+		/// <param name="filename">The filename.</param>
+		/// <param name="encoding">The encoding.</param>
+		/// <param name="mode">The mode (as per Lua usage - e.g. 'w+', 'rb', etc.).</param>
+		/// <returns></returns>
+		/// <exception cref="System.NotImplementedException">The current platform accessor does not support 'io' and 'os' operations. Provide your own implementation of platform to work around this limitation, if needed.</exception>
+		public override System.IO.Stream IO_OpenFile(Script script, string filename, Encoding encoding, string mode)
+		{
+			throw new NotImplementedException("The current platform accessor does not support 'io' and 'os' operations. Provide your own implementation of platform to work around this limitation, if needed.");
+		}
+
+		/// <summary>
+		/// Gets a standard stream (stdin, stdout, stderr).
+		/// LimitedPlatformAccessorBase does NOT offer a meaningful implementation of this method and
+		/// thus does not support 'io' and 'os' modules.
+		/// </summary>
+		/// <param name="type">The type.</param>
+		/// <returns></returns>
+		/// <exception cref="System.NotImplementedException">The current platform accessor does not support 'io' and 'os' operations. Provide your own implementation of platform to work around this limitation, if needed.</exception>
+		public override System.IO.Stream IO_GetStandardStream(StandardFileType type)
+		{
+			throw new NotImplementedException("The current platform accessor does not support 'io' and 'os' operations. Provide your own implementation of platform to work around this limitation, if needed.");
+		}
+
+		/// <summary>
+		/// Gets a temporary filename. Used in 'io' and 'os' modules.
+		/// LimitedPlatformAccessorBase does NOT offer a meaningful implementation of this method and
+		/// thus does not support 'io' and 'os' modules.
+		/// </summary>
+		/// <returns></returns>
+		/// <exception cref="System.NotImplementedException">The current platform accessor does not support 'io' and 'os' operations. Provide your own implementation of platform to work around this limitation, if needed.</exception>
+		public override string IO_OS_GetTempFilename()
+		{
+			throw new NotImplementedException("The current platform accessor does not support 'io' and 'os' operations. Provide your own implementation of platform to work around this limitation, if needed.");
+		}
+
+		/// <summary>
+		/// Exits the process, returning the specified exit code.
+		/// LimitedPlatformAccessorBase does NOT offer a meaningful implementation of this method and
+		/// thus does not support 'io' and 'os' modules.
+		/// </summary>
+		/// <param name="exitCode">The exit code.</param>
+		/// <exception cref="System.NotImplementedException">The current platform accessor does not support 'io' and 'os' operations. Provide your own implementation of platform to work around this limitation, if needed.</exception>
+		public override void OS_ExitFast(int exitCode)
+		{
+			throw new NotImplementedException("The current platform accessor does not support 'io' and 'os' operations. Provide your own implementation of platform to work around this limitation, if needed.");
+		}
+
+		/// <summary>
+		/// Checks if a file exists. Used by the 'os' module.
+		/// LimitedPlatformAccessorBase does NOT offer a meaningful implementation of this method and
+		/// thus does not support 'io' and 'os' modules.
+		/// </summary>
+		/// <param name="file">The file.</param>
+		/// <returns>
+		/// True if the file exists, false otherwise.
+		/// </returns>
+		/// <exception cref="System.NotImplementedException">The current platform accessor does not support 'io' and 'os' operations. Provide your own implementation of platform to work around this limitation, if needed.</exception>
+		public override bool OS_FileExists(string file)
+		{
+			throw new NotImplementedException("The current platform accessor does not support 'io' and 'os' operations. Provide your own implementation of platform to work around this limitation, if needed.");
+		}
+
+		/// <summary>
+		/// Deletes the specified file. Used by the 'os' module.
+		/// LimitedPlatformAccessorBase does NOT offer a meaningful implementation of this method and
+		/// thus does not support 'io' and 'os' modules.
+		/// </summary>
+		/// <param name="file">The file.</param>
+		/// <exception cref="System.NotImplementedException">The current platform accessor does not support 'io' and 'os' operations. Provide your own implementation of platform to work around this limitation, if needed.</exception>
+		public override void OS_FileDelete(string file)
+		{
+			throw new NotImplementedException("The current platform accessor does not support 'io' and 'os' operations. Provide your own implementation of platform to work around this limitation, if needed.");
+		}
+
+		/// <summary>
+		/// Moves the specified file. Used by the 'os' module.
+		/// LimitedPlatformAccessorBase does NOT offer a meaningful implementation of this method and
+		/// thus does not support 'io' and 'os' modules.
+		/// </summary>
+		/// <param name="src">The source.</param>
+		/// <param name="dst">The DST.</param>
+		/// <exception cref="System.NotImplementedException">The current platform accessor does not support 'io' and 'os' operations. Provide your own implementation of platform to work around this limitation, if needed.</exception>
+		public override void OS_FileMove(string src, string dst)
+		{
+			throw new NotImplementedException("The current platform accessor does not support 'io' and 'os' operations. Provide your own implementation of platform to work around this limitation, if needed.");
+		}
+
+		/// <summary>
+		/// Executes the specified command line, returning the child process exit code and blocking in the meantime.
+		/// LimitedPlatformAccessorBase does NOT offer a meaningful implementation of this method and
+		/// thus does not support 'io' and 'os' modules.
+		/// </summary>
+		/// <param name="cmdline">The cmdline.</param>
+		/// <returns></returns>
+		/// <exception cref="System.NotImplementedException">The current platform accessor does not support 'io' and 'os' operations. Provide your own implementation of platform to work around this limitation, if needed.</exception>
+		public override int OS_Execute(string cmdline)
+		{
+			throw new NotImplementedException("The current platform accessor does not support 'io' and 'os' operations. Provide your own implementation of platform to work around this limitation, if needed.");
+		}
+	}
+}

+ 189 - 29
src/MoonSharp.Interpreter/Platforms/PlatformAccessorBase.cs

@@ -6,21 +6,20 @@ using System.Text;
 
 namespace MoonSharp.Interpreter.Platforms
 {
+	/// <summary>
+	/// An abstract class which offers basic services on top of IPlatformAccessor to provide easier implementation of platforms.
+	/// </summary>
 	public abstract class PlatformAccessorBase : IPlatformAccessor
 	{
-		private string[] m_EnvironmentPaths = null;
 		private bool? m_IsAOT = null;
 
-		public PlatformAccessorBase()
-		{ }
-
-		public PlatformAccessorBase(string[] modulePaths)
-		{
-			m_EnvironmentPaths = modulePaths;
-		}
-
-
 
+		/// <summary>
+		/// Resolves the name of a module on a set of paths.
+		/// </summary>
+		/// <param name="modname">The modname.</param>
+		/// <param name="paths">The paths.</param>
+		/// <returns></returns>
 		protected virtual string ResolveModuleName(string modname, string[] paths)
 		{
 			modname = modname.Replace('.', '/');
@@ -29,14 +28,24 @@ namespace MoonSharp.Interpreter.Platforms
 			{
 				string file = path.Replace("?", modname);
 
-				if (FileExists(file))
+				if (ScriptFileExists(file))
 					return file;
 			}
 
 			return null;
 		}
 
-		public string ResolveModuleName(Script script, string modname, Table globalContext)
+		/// <summary>
+		/// Resolves the name of a module to a filename (which will later be passed to OpenScriptFile).
+		/// The resolution happens first on paths included in the LUA_PATH global variable, and - 
+		/// if the variable does not exist - by consulting the
+		/// ScriptOptions.ModulesPaths array. Override to provide a different behaviour.
+		/// </summary>
+		/// <param name="script">The script.</param>
+		/// <param name="modname">The modname.</param>
+		/// <param name="globalContext">The global context.</param>
+		/// <returns></returns>
+		public virtual string ResolveModuleName(Script script, string modname, Table globalContext)
 		{
 			DynValue s = (globalContext ?? script.Globals).RawGet("LUA_PATH");
 
@@ -47,16 +56,10 @@ namespace MoonSharp.Interpreter.Platforms
 		}
 
 
-		public virtual CoreModules FilterSupportedCoreModules(CoreModules module)
-		{
-			return module;
-		}
-
-		public virtual string GetEnvironmentVariable(string envvarname)
-		{
-			return null;
-		}
-
+		/// <summary>
+		/// Determines whether the application is running in AOT (ahead-of-time) mode
+		/// </summary>
+		/// <returns></returns>
 		public virtual bool IsRunningOnAOT()
 		{
 			if (m_IsAOT.HasValue) 
@@ -78,21 +81,178 @@ namespace MoonSharp.Interpreter.Platforms
 		}
 
 
-		public abstract Stream OpenFileForIO(Script script, string filename, Encoding encoding, string mode);
-		public abstract bool FileExists(string name);
-		public abstract object LoadFile(Script script, string file, Table globalContext);
-		public abstract Stream GetStandardStream(StandardFileType type);
-		public abstract void DefaultPrint(string content);
-		public abstract string DefaultInput();
+		/// <summary>
+		/// Checks if a script file exists. 
+		/// </summary>
+		/// <param name="name">The script filename.</param>
+		/// <returns></returns>
+		public abstract bool ScriptFileExists(string name);
+
+		/// <summary>
+		/// Opens a file for reading the script code.
+		/// It can return either a string, a byte[] or a Stream.
+		/// If a byte[] is returned, the content is assumed to be a serialized (dumped) bytecode. If it's a string, it's
+		/// assumed to be either a script or the output of a string.dump call. If a Stream, autodetection takes place.
+		/// </summary>
+		/// <param name="script">The script.</param>
+		/// <param name="file">The file.</param>
+		/// <param name="globalContext">The global context.</param>
+		/// <returns>
+		/// A string, a byte[] or a Stream.
+		/// </returns>
+		public abstract object OpenScriptFile(Script script, string file, Table globalContext);
 
+		/// <summary>
+		/// Gets the platform name prefix
+		/// </summary>
+		/// <returns></returns>
+		public abstract string GetPlatformNamePrefix();
 
+		/// <summary>
+		/// Gets the name of the platform (used for debug purposes).
+		/// </summary>
+		/// <returns>
+		/// The name of the platform (used for debug purposes)
+		/// </returns>
 		public string GetPlatformName()
 		{
-			return "";
+			string suffix = null;
+
+			if (PlatformAutoSelector.IsRunningOnUnity)
+			{
+				if (PlatformAutoSelector.IsRunningOnMono)
+					suffix = "unity.mono";
+				else
+					suffix = "unity.webp";
+			}
+			else if (PlatformAutoSelector.IsRunningOnMono)
+				suffix = "mono";
+			else
+				suffix = "dotnet";
+
+			if (PlatformAutoSelector.IsPortableFramework)
+				suffix = suffix + ".portable";
+			
+			if (PlatformAutoSelector.IsRunningOnClr4)
+				suffix = suffix + ".clr4";
+			else
+				suffix = suffix + ".clr2";
+
+			if (IsRunningOnAOT())
+				suffix = suffix + ".aot";
+
+			return GetPlatformNamePrefix() + "." + suffix;
 		}
 
+		/// <summary>
+		/// Default handler for 'print' calls. Can be customized in ScriptOptions
+		/// </summary>
+		/// <param name="content">The content.</param>
+		public abstract void DefaultPrint(string content);
+
+		/// <summary>
+		/// Default handler for interactive line input calls. Can be customized in ScriptOptions.
+		/// If an inheriting class whants to give a meaningful implementation, this method MUST be overridden.
+		/// </summary>
+		/// <returns>null</returns>
+		public virtual string DefaultInput()
+		{
+			return null;
+		}
+
+		/// <summary>
+		/// A function used to open files in the 'io' module. 
+		/// Can have an invalid implementation if 'io' module is filtered out.
+		/// It should return a correctly initialized Stream for the given file and access
+		/// </summary>
+		/// <param name="script"></param>
+		/// <param name="filename">The filename.</param>
+		/// <param name="encoding">The encoding.</param>
+		/// <param name="mode">The mode (as per Lua usage - e.g. 'w+', 'rb', etc.).</param>
+		/// <returns></returns>
+		public abstract Stream IO_OpenFile(Script script, string filename, Encoding encoding, string mode);
+
+
+		/// <summary>
+		/// Gets a standard stream (stdin, stdout, stderr).
+		/// </summary>
+		/// <param name="type">The type.</param>
+		/// <returns></returns>
+		public abstract Stream IO_GetStandardStream(StandardFileType type);
+
+
+		/// <summary>
+		/// Gets a temporary filename. Used in 'io' and 'os' modules.
+		/// Can have an invalid implementation if 'io' and 'os' modules are filtered out.
+		/// </summary>
+		/// <returns></returns>
+		public abstract string IO_OS_GetTempFilename();
+
+
+		/// <summary>
+		/// Exits the process, returning the specified exit code.
+		/// Can have an invalid implementation if the 'os' module is filtered out.
+		/// </summary>
+		/// <param name="exitCode">The exit code.</param>
+		public abstract void OS_ExitFast(int exitCode);
+
+
+		/// <summary>
+		/// Checks if a file exists. Used by the 'os' module.
+		/// Can have an invalid implementation if the 'os' module is filtered out.
+		/// </summary>
+		/// <param name="file">The file.</param>
+		/// <returns>
+		/// True if the file exists, false otherwise.
+		/// </returns>
+		public abstract bool OS_FileExists(string file);
+
+
+		/// <summary>
+		/// Deletes the specified file. Used by the 'os' module.
+		/// Can have an invalid implementation if the 'os' module is filtered out.
+		/// </summary>
+		/// <param name="file">The file.</param>
+		public abstract void OS_FileDelete(string file);
+
+
+		/// <summary>
+		/// Moves the specified file. Used by the 'os' module.
+		/// Can have an invalid implementation if the 'os' module is filtered out.
+		/// </summary>
+		/// <param name="src">The source.</param>
+		/// <param name="dst">The DST.</param>
+		public abstract void OS_FileMove(string src, string dst);
+
+
+		/// <summary>
+		/// Executes the specified command line, returning the child process exit code and blocking in the meantime.
+		/// Can have an invalid implementation if the 'os' module is filtered out.
+		/// </summary>
+		/// <param name="cmdline">The cmdline.</param>
+		/// <returns></returns>
+		public abstract int OS_Execute(string cmdline);
+
 
+		/// <summary>
+		/// Filters the CoreModules enumeration to exclude non-supported operations
+		/// </summary>
+		/// <param name="module">The requested modules.</param>
+		/// <returns>
+		/// The requested modules, with unsupported modules filtered out.
+		/// </returns>
+		public abstract CoreModules FilterSupportedCoreModules(CoreModules module);
 
+		/// <summary>
+		/// Gets an environment variable. Must be implemented, but an implementation is allowed
+		/// to always return null if a more meaningful implementation cannot be achieved or is
+		/// not desired.
+		/// </summary>
+		/// <param name="envvarname">The envvarname.</param>
+		/// <returns>
+		/// The environment variable value, or null if not found
+		/// </returns>
+		public abstract string GetEnvironmentVariable(string envvarname);
 
 	}
 }

+ 24 - 1
src/MoonSharp.Interpreter/Platforms/PlatformAutoSelector.cs

@@ -7,9 +7,32 @@ namespace MoonSharp.Interpreter.Platforms
 {
 	internal static class PlatformAutoSelector
 	{
+		public static bool IsRunningOnMono { get; private set; }
+		public static bool IsRunningOnClr4 { get; private set; }
+		public static bool IsRunningOnUnity { get; private set; }
+		public static bool IsPortableFramework { get; private set; }
+
+
 		internal static IPlatformAccessor GetDefaultPlatform()
 		{
-			return null; // new StandardPlatformAccessor();
+#if PCL
+			IsPortableFramework = true;
+#else
+			IsRunningOnUnity = AppDomain.CurrentDomain
+				.GetAssemblies()
+				.SelectMany(a => a.GetTypes())
+				.Any(t => t.FullName.StartsWith("UnityEngine."));
+#endif
+
+			IsRunningOnMono = (Type.GetType("Mono.Runtime") != null);
+
+			IsRunningOnClr4 = (Type.GetType("System.Lazy`1") != null);
+
+#if PCL
+			return null;
+#else
+			return new StandardPlatformAccessor();
+#endif
 		}
 
 

+ 30 - 0
src/MoonSharp.Interpreter/Platforms/PortableFrameworkAccessor.cs

@@ -0,0 +1,30 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace MoonSharp.Interpreter.Platforms
+{
+	public class PortableFrameworkAccessor: LimitedPlatformAccessorBase
+	{
+		public override bool ScriptFileExists(string name)
+		{
+			return true;
+		}
+
+		public override object OpenScriptFile(Script script, string file, Table globalContext)
+		{
+			throw new NotImplementedException();
+		}
+
+		public override string GetPlatformNamePrefix()
+		{
+			return "pstd";
+		}
+
+		public override void DefaultPrint(string content)
+		{
+			System.Diagnostics.Debug.WriteLine(content);
+		}
+	}
+}

+ 0 - 34
src/MoonSharp.Interpreter/Platforms/SandboxedPlatformAccessor.cs

@@ -1,34 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-namespace MoonSharp.Interpreter.Platforms
-{
-	public abstract class SandboxedPlatformAccessor : PlatformAccessorBase
-	{
-		public SandboxedPlatformAccessor()
-			: base()
-		{ }
-
-		public SandboxedPlatformAccessor(params string[] modulePaths)
-			: base(modulePaths)
-		{ }
-
-
-		public override System.IO.Stream OpenFileForIO(Script script, string filename, Encoding encoding, string mode)
-		{
-			throw new InvalidOperationException("SandboxedPlatformAccessor does not support 'io' and 'os' operations. Provide your own implementation of platform to work around this limitation, if needed.");
-		}
-
-		public override string GetEnvironmentVariable(string envvarname)
-		{
-			throw new InvalidOperationException("SandboxedPlatformAccessor does not support 'io' and 'os' operations. Provide your own implementation of platform to work around this limitation, if needed.");
-		}
-
-		public override CoreModules FilterSupportedCoreModules(CoreModules module)
-		{
-			return module & (~(CoreModules.IO | CoreModules.OS_System));
-		}
-	}
-}

+ 154 - 16
src/MoonSharp.Interpreter/Platforms/StandardPlatformAccessor.cs

@@ -1,23 +1,23 @@
 #if !PCL
 using System;
 using System.Collections.Generic;
+using System.Diagnostics;
 using System.IO;
 using System.Linq;
 using System.Text;
 
 namespace MoonSharp.Interpreter.Platforms
 {
+	/// <summary>
+	/// Class providing the IPlatformAccessor interface for standard implementations.
+	/// </summary>
 	public class StandardPlatformAccessor : PlatformAccessorBase
 	{
-		public StandardPlatformAccessor()
-			: base()
-		{ }
-
-		public StandardPlatformAccessor(params string[] modulePaths)
-			: base(modulePaths)
-		{ }
-
-
+		/// <summary>
+		/// Converts a Lua string access mode to a FileAccess enum
+		/// </summary>
+		/// <param name="mode">The mode.</param>
+		/// <returns></returns>
 		public static FileAccess ParseFileAccess(string mode)
 		{
 			mode = mode.Replace("b", "");
@@ -34,6 +34,11 @@ namespace MoonSharp.Interpreter.Platforms
 				return FileAccess.ReadWrite;
 		}
 
+		/// <summary>
+		/// Converts a Lua string access mode to a ParseFileMode enum
+		/// </summary>
+		/// <param name="mode">The mode.</param>
+		/// <returns></returns>
 		public static FileMode ParseFileMode(string mode)
 		{
 			mode = mode.Replace("b", "");
@@ -51,29 +56,70 @@ namespace MoonSharp.Interpreter.Platforms
 		}
 
 
-		public override Stream OpenFileForIO(Script script, string filename, Encoding encoding, string mode)
+		/// <summary>
+		/// A function used to open files in the 'io' module. 
+		/// Can have an invalid implementation if 'io' module is filtered out.
+		/// It should return a correctly initialized Stream for the given file and access
+		/// </summary>
+		/// <param name="script"></param>
+		/// <param name="filename">The filename.</param>
+		/// <param name="encoding">The encoding.</param>
+		/// <param name="mode">The mode (as per Lua usage - e.g. 'w+', 'rb', etc.).</param>
+		/// <returns></returns>
+		public override Stream IO_OpenFile(Script script, string filename, Encoding encoding, string mode)
 		{
 			return new FileStream(filename, ParseFileMode(mode), ParseFileAccess(mode), FileShare.ReadWrite | FileShare.Delete);
 		}
 
+		/// <summary>
+		/// Gets an environment variable. Must be implemented, but an implementation is allowed
+		/// to always return null if a more meaningful implementation cannot be achieved or is
+		/// not desired.
+		/// </summary>
+		/// <param name="envvarname">The envvarname.</param>
+		/// <returns>
+		/// The environment variable value, or null if not found
+		/// </returns>
 		public override string GetEnvironmentVariable(string envvarname)
 		{
 			return Environment.GetEnvironmentVariable(envvarname);
 		}
 
-		public override bool FileExists(string name)
+		/// <summary>
+		/// Checks if a script file exists.
+		/// </summary>
+		/// <param name="name">The script filename.</param>
+		/// <returns></returns>
+		public override bool ScriptFileExists(string name)
 		{
 			return File.Exists(name);
 		}
 
-		public override object LoadFile(Script script, string file, Table globalContext)
+		/// <summary>
+		/// Opens a file for reading the script code.
+		/// It can return either a string, a byte[] or a Stream.
+		/// If a byte[] is returned, the content is assumed to be a serialized (dumped) bytecode. If it's a string, it's
+		/// assumed to be either a script or the output of a string.dump call. If a Stream, autodetection takes place.
+		/// </summary>
+		/// <param name="script">The script.</param>
+		/// <param name="file">The file.</param>
+		/// <param name="globalContext">The global context.</param>
+		/// <returns>
+		/// A string, a byte[] or a Stream.
+		/// </returns>
+		public override object OpenScriptFile(Script script, string file, Table globalContext)
 		{
 			return new FileStream(file, FileMode.Open, FileAccess.Read);
 		}
 
 
-
-		public override Stream GetStandardStream(StandardFileType type)
+		/// <summary>
+		/// Gets a standard stream (stdin, stdout, stderr).
+		/// </summary>
+		/// <param name="type">The type.</param>
+		/// <returns></returns>
+		/// <exception cref="System.ArgumentException">type</exception>
+		public override Stream IO_GetStandardStream(StandardFileType type)
 		{
 			switch (type)
 			{
@@ -88,14 +134,106 @@ namespace MoonSharp.Interpreter.Platforms
 			}
 		}
 
+		/// <summary>
+		/// Default handler for 'print' calls. Can be customized in ScriptOptions
+		/// </summary>
+		/// <param name="content">The content.</param>
 		public override void DefaultPrint(string content)
 		{
 			Console.WriteLine(content);
 		}
 
-		public override string DefaultInput()
+
+		/// <summary>
+		/// Gets a temporary filename. Used in 'io' and 'os' modules.
+		/// Can have an invalid implementation if 'io' and 'os' modules are filtered out.
+		/// </summary>
+		/// <returns></returns>
+		public override string IO_OS_GetTempFilename()
+		{
+			return Path.GetTempFileName();
+		}
+
+		/// <summary>
+		/// Exits the process, returning the specified exit code.
+		/// Can have an invalid implementation if the 'os' module is filtered out.
+		/// </summary>
+		/// <param name="exitCode">The exit code.</param>
+		public override void OS_ExitFast(int exitCode)
+		{
+			Environment.Exit(exitCode);
+		}
+
+		/// <summary>
+		/// Checks if a file exists. Used by the 'os' module.
+		/// Can have an invalid implementation if the 'os' module is filtered out.
+		/// </summary>
+		/// <param name="file">The file.</param>
+		/// <returns>
+		/// True if the file exists, false otherwise.
+		/// </returns>
+		public override bool OS_FileExists(string file)
+		{
+			return File.Exists(file);
+		}
+
+		/// <summary>
+		/// Deletes the specified file. Used by the 'os' module.
+		/// Can have an invalid implementation if the 'os' module is filtered out.
+		/// </summary>
+		/// <param name="file">The file.</param>
+		public override void OS_FileDelete(string file)
+		{
+			File.Delete(file);
+		}
+
+		/// <summary>
+		/// Moves the specified file. Used by the 'os' module.
+		/// Can have an invalid implementation if the 'os' module is filtered out.
+		/// </summary>
+		/// <param name="src">The source.</param>
+		/// <param name="dst">The DST.</param>
+		public override void OS_FileMove(string src, string dst)
+		{
+			File.Move(src, dst);
+		}
+
+		/// <summary>
+		/// Executes the specified command line, returning the child process exit code and blocking in the meantime.
+		/// Can have an invalid implementation if the 'os' module is filtered out.
+		/// </summary>
+		/// <param name="cmdline">The cmdline.</param>
+		/// <returns></returns>
+		public override int OS_Execute(string cmdline)
+		{
+			ProcessStartInfo psi = new ProcessStartInfo("cmd.exe", string.Format("/C {0}", cmdline));
+			psi.ErrorDialog = false;
+
+			Process proc = Process.Start(psi);
+			proc.WaitForExit();
+			return proc.ExitCode;
+		}
+
+		/// <summary>
+		/// Filters the CoreModules enumeration to exclude non-supported operations
+		/// </summary>
+		/// <param name="module">The requested modules.</param>
+		/// <returns>
+		/// The requested modules, with unsupported modules filtered out.
+		/// </returns>
+		public override CoreModules FilterSupportedCoreModules(CoreModules module)
+		{
+			return module;
+		}
+
+		/// <summary>
+		/// Gets the platform name prefix
+		/// </summary>
+		/// <returns></returns>
+		/// <exception cref="System.NotImplementedException"></exception>
+		public override string GetPlatformNamePrefix()
 		{
-			return Console.ReadLine();
+			return "std";
 		}
 	}
 }

+ 1 - 1
src/MoonSharp.Interpreter/Script.cs

@@ -280,7 +280,7 @@ namespace MoonSharp.Interpreter
 		/// </returns>
 		public DynValue LoadFile(string filename, Table globalContext = null, string friendlyFilename = null)
 		{
-			object code = Platform.LoadFile(this, filename, globalContext ?? m_GlobalTable);
+			object code = Platform.OpenScriptFile(this, filename, globalContext ?? m_GlobalTable);
 
 			if (code is string)
 			{

+ 2 - 2
src/MoonSharp.Interpreter/_Projects/MoonSharp.Interpreter.net40-client/MoonSharp.Interpreter.net40-client.csproj

@@ -396,8 +396,8 @@
     <Compile Include="..\..\Platforms\PlatformAutoSelector.cs">
       <Link>PlatformAutoSelector.cs</Link>
     </Compile>
-    <Compile Include="..\..\Platforms\SandboxedPlatformAccessor.cs">
-      <Link>SandboxedPlatformAccessor.cs</Link>
+    <Compile Include="..\..\Platforms\LimitedPlatformAccessorBase.cs">
+      <Link>LimitedPlatformAccessorBase.cs</Link>
     </Compile>
     <Compile Include="..\..\Platforms\StandardFileType.cs">
       <Link>StandardFileType.cs</Link>

+ 2 - 2
src/MoonSharp.Interpreter/_Projects/MoonSharp.Interpreter.portable40/MoonSharp.Interpreter.portable40.csproj

@@ -393,8 +393,8 @@
     <Compile Include="..\..\Platforms\PlatformAutoSelector.cs">
       <Link>PlatformAutoSelector.cs</Link>
     </Compile>
-    <Compile Include="..\..\Platforms\SandboxedPlatformAccessor.cs">
-      <Link>SandboxedPlatformAccessor.cs</Link>
+    <Compile Include="..\..\Platforms\LimitedPlatformAccessorBase.cs">
+      <Link>LimitedPlatformAccessorBase.cs</Link>
     </Compile>
     <Compile Include="..\..\Platforms\StandardFileType.cs">
       <Link>StandardFileType.cs</Link>

+ 1 - 0
src/moonsharp.sln

@@ -84,6 +84,7 @@ Global
 		{43D3AD52-FED5-4305-B0F4-6B991220CD0A}.Release|Any CPU.Build.0 = Release|Any CPU
 		{43D3AD52-FED5-4305-B0F4-6B991220CD0A}.Release|x86.ActiveCfg = Release|Any CPU
 		{88D2880C-A863-4B16-ABEF-F67BD1E98BD1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{88D2880C-A863-4B16-ABEF-F67BD1E98BD1}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{88D2880C-A863-4B16-ABEF-F67BD1E98BD1}.Debug|x86.ActiveCfg = Debug|Any CPU
 		{88D2880C-A863-4B16-ABEF-F67BD1E98BD1}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{88D2880C-A863-4B16-ABEF-F67BD1E98BD1}.Release|Any CPU.Build.0 = Release|Any CPU