public static Session Load (FileSystemDatabase fsd, int key) { var toLoad = fsd.Read (key); if (toLoad == null) { return null; } var result = new Session (); result.Id = key; if (toLoad.ContainsKey (ShovelVmStateName)) { result.ShovelVmState = toLoad [ShovelVmStateName]; } if (toLoad.ContainsKey (ShovelVmBytecodeName)) { result.ShovelVmBytecode = toLoad [ShovelVmBytecodeName]; } if (toLoad.ContainsKey (ShovelVmSourcesName)) { result.ShovelVmSources = Encoding.UTF8.GetString (toLoad [ShovelVmSourcesName]); } if (toLoad.ContainsKey (PageContentName)) { result.PageContent.Append (Encoding.UTF8.GetString (toLoad [PageContentName])); } if (toLoad.ContainsKey (ReadStateName)) { result.ReadState = (ReadStates)BitConverter.ToInt32 (toLoad [ReadStateName], 0); } return result; }
static Session FreshSession(FileSystemDatabase fsd, Shovel.Instruction[] bytecode, string program) { var session = new Session (); session.Id = fsd.GetFreshId (); session.ShovelVmSources = program; session.ShovelVmBytecode = Shovel.Api.SerializeBytecode (bytecode); return session; }
static IEnumerable<Shovel.Callable> Udps(Session session, string userInput) { var rng = new Random (); Action<Shovel.VmApi, Shovel.Value[], Shovel.UdpResult> print = (api, args, result) => { if (args.Length > 0 && args [0].Kind == Shovel.Value.Kinds.String) { session.PageContent.Append ("<span>"); session.PageContent.Append (HttpUtility.HtmlEncode (args [0].StringValue)); session.PageContent.Append ("</span>"); } else { session.PageContent.Append ("PRINT call failed!"); } }; Action<Shovel.VmApi, Shovel.Value[], Shovel.UdpResult> printLn = (api, args, result) => { if (args.Length > 0 && args [0].Kind == Shovel.Value.Kinds.String) { session.PageContent.Append ("<span>"); session.PageContent.Append (HttpUtility.HtmlEncode (args [0].StringValue)); session.PageContent.Append ("</span><br/>"); } else { session.PageContent.Append ("PRINT call failed!"); } }; Action<Shovel.VmApi, Shovel.Value[], Shovel.UdpResult> readLine = (api, args, result) => { if (session.ReadState == Session.ReadStates.None) { result.After = Shovel.UdpResult.AfterCall.NapAndRetryOnWakeUp; session.ReadState = Session.ReadStates.ReadLine; } else if (session.ReadState == Session.ReadStates.ReadLine) { result.Result = Shovel.Value.Make (userInput); session.ReadState = Session.ReadStates.None; session.PageContent.Append (HttpUtility.HtmlEncode (userInput)); session.PageContent.Append ("<br/>"); } else { throw new InvalidOperationException (); } }; Action<Shovel.VmApi, Shovel.Value[], Shovel.UdpResult> readInt = (api, args, result) => { if (session.ReadState == Session.ReadStates.None) { result.After = Shovel.UdpResult.AfterCall.NapAndRetryOnWakeUp; session.ReadState = Session.ReadStates.ReadInteger; } else if (session.ReadState == Session.ReadStates.ReadInteger) { int dummy; if (!int.TryParse (userInput, out dummy)) { dummy = 0; } result.Result = Shovel.Value.MakeInt (dummy); session.ReadState = Session.ReadStates.None; session.PageContent.Append (HttpUtility.HtmlEncode (userInput)); session.PageContent.Append ("<br/>"); } else { throw new InvalidOperationException (); } }; Action<Shovel.VmApi, Shovel.Value[], Shovel.UdpResult> readChar = (api, args, result) => { if (session.ReadState == Session.ReadStates.None) { result.After = Shovel.UdpResult.AfterCall.NapAndRetryOnWakeUp; session.ReadState = Session.ReadStates.ReadChar; } else if (session.ReadState == Session.ReadStates.ReadChar) { var line = userInput; if (line.Length > 0) { result.Result = Shovel.Value.Make (line.Substring (0, 1)); } else { result.Result = Shovel.Value.Make (""); } session.ReadState = Session.ReadStates.None; session.PageContent.Append (HttpUtility.HtmlEncode (userInput)); session.PageContent.Append ("<br/>"); } else { throw new InvalidOperationException (); } }; Action<Shovel.VmApi, Shovel.Value[], Shovel.UdpResult> random = (api, args, result) => { result.Result = Shovel.Value.MakeFloat (rng.NextDouble ()); }; return new Shovel.Callable[] { Shovel.Callable.MakeUdp ("print", print, 1), Shovel.Callable.MakeUdp ("printLn", printLn, 1), Shovel.Callable.MakeUdp ("readLine", readLine, 0), Shovel.Callable.MakeUdp ("readInt", readInt, 0), Shovel.Callable.MakeUdp ("readChar", readChar, 0), Shovel.Callable.MakeUdp ("random", random, 0), }; }
static void ServeSession(HttpListenerContext ctx, FileSystemDatabase fsd, Session session, string userInput) { var vm = Shovel.Api.RunVm ( Shovel.Api.DeserializeBytecode (session.ShovelVmBytecode), ProgramSources (session.ShovelVmSources), Udps (session, userInput), session.ShovelVmState, totalTicksQuota: null, ticksUntilNextNapQuota: null, usedCellsQuota: null); if (Shovel.Api.VmProgrammingError (vm) != null) { ServeError (ctx, session, Shovel.Api.VmProgrammingError (vm).Message); } else if (Shovel.Api.VmUserDefinedPrimitiveError (vm) != null) { ServeError (ctx, session, Shovel.Api.VmUserDefinedPrimitiveError (vm).Message); } else if (Shovel.Api.VmExecutionComplete (vm)) { using (var sw = new StreamWriter(ctx.Response.OutputStream)) { sw.Write ("<!DOCTYPE html>\n"); sw.Write (session.PageContent.ToString ()); sw.Write ("<p>Program execution completed.</p>"); sw.Write ("<a href='/' id='restart-link'>Enter another program.</p>"); sw.Write ("<script>\n"); sw.Write ("document.getElementById('restart-link').focus()\n"); sw.Write ("</script>\n"); } } else { session.ShovelVmState = Shovel.Api.SerializeVmState (vm); session.Id = fsd.GetFreshId (); session.Save (fsd); using (var sw = new StreamWriter(ctx.Response.OutputStream)) { sw.Write ("<!DOCTYPE html>\n"); sw.Write (session.PageContent.ToString ()); sw.Write ("<form action='/' method='get'>"); sw.Write ("<input type='text' name='input' id='shovel-input'/>"); sw.Write ("<input type='submit' value='Submit'/>"); sw.Write (String.Format ( "<input type='hidden' name='sessionid' value='{0}' id='shovel-input'/>", session.Id) ); sw.Write ("</form>"); sw.Write ("<script>\n"); sw.Write ("document.getElementById('shovel-input').focus()\n"); sw.Write ("</script>\n"); } } ctx.Response.OutputStream.Close (); }
static void ServeError(HttpListenerContext ctx, Session session, string error) { using (var sw = new StreamWriter(ctx.Response.OutputStream)) { sw.Write ("<!DOCTYPE html>\n"); sw.Write (session.PageContent.ToString ()); sw.Write ("<p>Program execution failed.</p>"); sw.Write ("<pre>"); sw.Write (HttpUtility.HtmlEncode (error)); sw.Write ("</pre>"); sw.Write ("<a href='/' id='restart-link'>Enter another program.</p>"); sw.Write ("<script>\n"); sw.Write ("document.getElementById('restart-link').focus()\n"); sw.Write ("</script>\n"); } }