/// <summary> /// Detects if the FLInterpreter has reached the end of the current function /// </summary> private void DetectEnd() { if (currentIndex == data.ParsedSource.Count || data.ParsedSource[currentIndex].InstructionType == FLInstructionType.FunctionHeader) { if (jumpStack.Count == 0) { Logger.Log(DebugChannel.Log | DebugChannel.OpenFL, Verbosity.Level8, "Reached End of Code"); Terminated = true; } else { FLInterpreterState lastState = jumpStack.Pop(); Logger.Log(DebugChannel.Log | DebugChannel.OpenFL, Verbosity.Level8, "Returning to location: " + data.Source[lastState.Line]); currentIndex = lastState.Line; if (lastState.ArgumentStack.Count != 0 && lastState.ArgumentStack.Peek() == null) { leaveStack = true; lastState.ArgumentStack.Pop(); lastState.ArgumentStack.Push(currentBuffer); } currentArgStack = lastState.ArgumentStack; currentBuffer = lastState.ActiveBuffer; currentWord = lastState.ArgumentStack.Count; } } }
/// <summary> /// Resets the FLInterpreter to work with a new script /// </summary> /// <param name="file">The file containing the source</param> /// <param name="input">The input buffer</param> /// <param name="width">Width of the input buffer</param> /// <param name="height">Height of the input buffer</param> /// <param name="depth">Depth of the input buffer</param> /// <param name="channelCount">The Channel Count</param> /// <param name="kernelDb">The Kernel DB that will be used</param> /// <param name="ignoreDebug">a flag to ignore the brk statement</param> public void Reset(string file, MemoryBuffer input, int width, int height, int depth, int channelCount, KernelDatabase kernelDb, bool ignoreDebug) { //Clear old stuff ReleaseResources(); //Setting variables currentBuffer = new CLBufferInfo(input, false); currentBuffer.SetKey(INPUT_BUFFER_NAME); this.ignoreDebug = ignoreDebug; this.width = width; this.height = height; this.depth = depth; this.channelCount = channelCount; this.kernelDb = kernelDb; activeChannels = new byte[this.channelCount]; currentArgStack = new Stack <object>(); for (int i = 0; i < this.channelCount; i++) { activeChannels[i] = 1; } activeChannelBuffer = CLAPI.CreateBuffer(instance, activeChannels, MemoryFlag.ReadOnly | MemoryFlag.CopyHostPointer); //Parsing File currentBuffer.SetKey(INPUT_BUFFER_NAME); data = LoadScriptData(instance, file, currentBuffer, width, height, depth, channelCount, kernelDb, flFunctions); Reset(); }
private FLScriptData LoadScriptData(CLAPI instance, string file, CLBufferInfo inBuffer, int width, int height, int depth, int channelCount, KernelDatabase db, Dictionary <string, FLInterpreterFunctionInfo> funcs) { Logger.Log(DebugChannel.Log | DebugChannel.OpenFL, Verbosity.Level6, "Loading Script Data for File: " + file); FLScriptData ret = new FLScriptData(LoadSource(file, channelCount)); ret.Defines.Add(INPUT_BUFFER_NAME, inBuffer); Logger.Log(DebugChannel.Log | DebugChannel.OpenFL, Verbosity.Level5, "Parsing Texture Defines for File: " + file); ParseDefines(instance, DEFINE_KEY, DefineTexture, ret.Source, ret.Defines, width, height, depth, channelCount, db); Logger.Log(DebugChannel.Log | DebugChannel.OpenFL, Verbosity.Level5, "Parsing Script Defines for File: " + file); ParseDefines(instance, SCRIPT_DEFINE_KEY, DefineScript, ret.Source, ret.Defines, width, height, depth, channelCount, db); Logger.Log(DebugChannel.Log | DebugChannel.OpenFL, Verbosity.Level5, "Parsing JumpLocations for File: " + file); ret.JumpLocations = ParseJumpLocations(ret.Source); Logger.Log(DebugChannel.Log | DebugChannel.OpenFL, Verbosity.Level5, "Parsing Instruction Data for File: " + file); foreach (string line in ret.Source) { Logger.Log(DebugChannel.Log | DebugChannel.OpenFL, Verbosity.Level3, "Parsing Instruction Data for Line: " + line); FLInstructionData data = GetInstructionData(line, ret.Defines, ret.JumpLocations, funcs, db); Logger.Log(DebugChannel.Log | DebugChannel.OpenFL, Verbosity.Level3, "Parsed Instruction Data: " + Enum.GetName(typeof(FLInstructionType), data.InstructionType)); ret.ParsedSource.Add(data); } return(ret); }
/// <summary> /// Jumps the interpreter to the specified index /// </summary> /// <param name="index">the index of the line to jump to</param> /// <param name="leaveBuffer">a flag to optionally keep the current buffer</param> private void JumpTo(int index, bool leaveBuffer = false) { Logger.Log(DebugChannel.Log | DebugChannel.OpenFL, Verbosity.Level6, "Jumping To Function: " + data.Source[index]); jumpStack.Push(new FLInterpreterState(currentIndex, currentBuffer, currentArgStack)); stepResult.HasJumped = true; int size = (int)currentBuffer.Buffer.Size; if (!leaveBuffer) { currentBuffer = new CLBufferInfo( CLAPI.CreateEmpty <byte>(instance, size, MemoryFlag.ReadWrite | MemoryFlag.CopyHostPointer), true); currentBuffer.SetKey("Internal_JumpBuffer_Stack_Index" + (jumpStack.Count - 1)); } currentIndex = index + 1; //+1 because the index is the function header currentWord = 0; }
/// <summary> /// Creates an interpreter state /// </summary> /// <param name="line">The line where the interpreter is</param> /// <param name="activeBuffer">The active buffer</param> /// <param name="argumentStack">The unfinished argument stack</param> internal FLInterpreterState(int line, CLBufferInfo activeBuffer, Stack <object> argumentStack) { Line = line; ActiveBuffer = activeBuffer; ArgumentStack = argumentStack; }
/// <summary> /// Define handler that loads defined scripts /// </summary> /// <param name="instance">CLAPI Instance of the Current Thread</param> /// <param name="arg">Args from the FL Script</param> /// <param name="defines">Defines</param> /// <param name="width">width of the input buffer</param> /// <param name="height">height of the input buffer</param> /// <param name="depth">depth of the input buffer</param> /// <param name="channelCount">channel count of the input buffer</param> /// <param name="kernelDb">the kernel database to use</param> private void DefineScript(CLAPI instance, string[] arg, Dictionary <string, CLBufferInfo> defines, int width, int height, int depth, int channelCount, KernelDatabase kernelDb) { if (arg.Length < 2) { throw new FLInvalidFunctionUseException(SCRIPT_DEFINE_KEY, "Invalid Define statement"); } string varname = arg[0].Trim(); if (defines.ContainsKey(varname)) { Logger.Log(DebugChannel.Error, Verbosity.Level1, "Overwriting " + varname, DebugChannel.Warning | DebugChannel.OpenFL, 10); defines.Remove(varname); } string[] args = arg[1].Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); string filename = args[0].Trim(); int inputBufferSize = width * height * depth * channelCount; if (IsSurroundedBy(filename, FILEPATH_INDICATOR)) { Logger.Log(DebugChannel.Error, Verbosity.Level1, "Loading SubScript...", DebugChannel.Log | DebugChannel.OpenFL, 10); MemoryBuffer buf = CLAPI.CreateEmpty <byte>(instance, inputBufferSize, MemoryFlag.ReadWrite); string fn = filename.Replace(FILEPATH_INDICATOR, ""); if (CLAPI.FileExists(fn)) { FLInterpreter flInterpreter = new FLInterpreter(instance, fn, buf, width, height, depth, channelCount, kernelDb, true); do { flInterpreter.Step(); } while (!flInterpreter.Terminated); CLBufferInfo info = flInterpreter.GetActiveBufferInternal(); info.SetKey(varname); defines.Add(varname, info); flInterpreter.ReleaseResources(); } else { throw new FLInvalidFunctionUseException(SCRIPT_DEFINE_KEY, "Not a valid filepath as argument.", new InvalidFilePathException(fn)); } } else { throw new FLInvalidFunctionUseException(SCRIPT_DEFINE_KEY, "Not a valid filepath as argument."); } }
/// <summary> /// Define handler that loads defined Textures /// </summary> /// <param name="instance">CLAPI Instance of the Current Thread</param> /// <param name="arg">Args from the FL Script</param> /// <param name="defines">Defines</param> /// <param name="width">width of the input buffer</param> /// <param name="height">height of the input buffer</param> /// <param name="depth">depth of the input buffer</param> /// <param name="channelCount">channel count of the input buffer</param> /// <param name="kernelDb">the kernel database to use</param> private void DefineTexture(CLAPI instance, string[] arg, Dictionary <string, CLBufferInfo> defines, int width, int height, int depth, int channelCount, KernelDatabase kernelDb) { if (arg.Length < 2) { throw new FLInvalidFunctionUseException(SCRIPT_DEFINE_KEY, "Invalid Define statement"); } string varname = arg[0].Trim(); if (defines.ContainsKey(varname)) { Logger.Log(DebugChannel.Error, Verbosity.Level1, "Overwriting " + varname, DebugChannel.Warning | DebugChannel.OpenFL, 10); defines.Remove(varname); } MemoryFlag flags = MemoryFlag.ReadWrite; string[] flagTest = varname.Split(' '); if (flagTest.Length > 1) { varname = flagTest[1]; if (flagTest[0] == "r") { flags = MemoryFlag.ReadOnly; } else if (flagTest[0] == "w") { flags = MemoryFlag.WriteOnly; } } string[] args = arg[1].Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); string filename = args[0].Trim(); byte[] activeChannels = new byte[channelCount]; for (int i = 0; i < activeChannels.Length; i++) { activeChannels[i] = 1; } int inputBufferSize = width * height * depth * channelCount; if (IsSurroundedBy(filename, FILEPATH_INDICATOR)) { string fn = filename.Replace(FILEPATH_INDICATOR, ""); if (File.Exists(fn)) { Bitmap bmp = new Bitmap((Bitmap)System.Drawing.Image.FromFile(fn), width, height); CLBufferInfo info = new CLBufferInfo(CLAPI.CreateFromImage(instance, bmp, MemoryFlag.CopyHostPointer | flags), true); info.SetKey(varname); defines.Add(varname, info); } else { throw new FLInvalidFunctionUseException(DEFINE_KEY, "Invalid Filepath", new InvalidFilePathException(fn)); } } else if (filename == "rnd") { MemoryBuffer buf = CLAPI.CreateEmpty <byte>(instance, inputBufferSize, flags | MemoryFlag.CopyHostPointer); CLAPI.WriteRandom(instance, buf, Randombytesource, activeChannels, false); CLBufferInfo info = new CLBufferInfo(buf, true); info.SetKey(varname); defines.Add(varname, info); } else if (filename == "urnd") { MemoryBuffer buf = CLAPI.CreateEmpty <byte>(instance, inputBufferSize, flags | MemoryFlag.CopyHostPointer); CLAPI.WriteRandom(instance, buf, Randombytesource, activeChannels, true); CLBufferInfo info = new CLBufferInfo(buf, true); info.SetKey(varname); defines.Add(varname, info); } else if (filename == "empty") { CLBufferInfo info = new CLBufferInfo(CLAPI.CreateEmpty <byte>(instance, inputBufferSize, flags), true); info.SetKey(varname); defines.Add(varname, info); } else if (filename == "wfc" || filename == "wfcf") { bool force = filename == "wfcf"; if (args.Length < 10) { throw new FLInvalidFunctionUseException("wfc", "Invalid WFC Define statement"); } else if (!int.TryParse(args[2], out int n)) { throw new FLInvalidFunctionUseException("wfc", "Invalid WFC Define statement"); } else if (!int.TryParse(args[3], out int widh)) { throw new FLInvalidFunctionUseException("wfc", "Invalid WFC Define statement"); } else if (!int.TryParse(args[4], out int heigt)) { throw new FLInvalidFunctionUseException("wfc", "Invalid WFC Define statement"); } else if (!bool.TryParse(args[5], out bool periodicInput)) { throw new FLInvalidFunctionUseException("wfc", "Invalid WFC Define statement"); } else if (!bool.TryParse(args[6], out bool periodicOutput)) { throw new FLInvalidFunctionUseException("wfc", "Invalid WFC Define statement"); } else if (!int.TryParse(args[7], out int symmetry)) { throw new FLInvalidFunctionUseException("wfc", "Invalid WFC Define statement"); } else if (!int.TryParse(args[8], out int ground)) { throw new FLInvalidFunctionUseException("wfc", "Invalid WFC Define statement"); } else if (!int.TryParse(args[9], out int limit)) { throw new FLInvalidFunctionUseException("wfc", "Invalid WFC Define statement"); } else { string fn = args[1].Trim().Replace(FILEPATH_INDICATOR, ""); if (CLAPI.FileExists(fn)) { Bitmap bmp; WFCOverlayMode wfc = new WFCOverlayMode(fn, n, widh, heigt, periodicInput, periodicOutput, symmetry, ground); if (force) { do { wfc.Run(limit); bmp = new Bitmap(wfc.Graphics(), new Size(width, height)); //Apply scaling } while (!wfc.Success); } else { wfc.Run(limit); bmp = new Bitmap(wfc.Graphics(), new Size(width, height)); //Apply scaling } CLBufferInfo info = new CLBufferInfo(CLAPI.CreateFromImage(instance, bmp, MemoryFlag.CopyHostPointer | flags), true); info.SetKey(varname); defines.Add(varname, info); } else { throw new FLInvalidFunctionUseException("wfc", "Invalid WFC Image statement", new InvalidFilePathException(fn)); } } } else { StringBuilder s = new StringBuilder(); foreach (string s1 in args) { s.Append(s1 + " "); } throw new FLInvalidFunctionUseException(DEFINE_KEY, "Define statement wrong: " + s); } }