/// <summary> /// 复制当前函数实例 /// </summary> /// <param name="pureFork">是否不要复制符号表</param> /// <returns>新的符号实例</returns> public SceneFunction Fork(bool pureFork) { SceneFunction nsf = new SceneFunction(this.Callname, this.ParentSceneName, this.Sa); nsf.Param = this.Param; if (!pureFork) { foreach (var svar in this.Symbols) { nsf.Symbols.Add(svar.Key, svar.Value); } } return nsf; }
/// <summary> /// 函数调用 /// </summary> /// <param name="function">函数模板实例</param> /// <param name="args">参数列表</param> public void CallFunction(SceneFunction function, List<object> args) { // 为模板创建一个分支实例 var callForker = function.Fork(true); this.CallStack.Submit(callForker, args); // 处理参数传递 var funcSymbols = callForker.Symbols; for (int i = 0; i < args.Count; i++) { funcSymbols[callForker.Param[i].Substring(1)] = args[i]; } }
/// <summary> /// 将动作序列绑定到一个新的场景函数 /// </summary> /// <param name="funcSa">动作序列</param> /// <param name="sceneName">场景名称</param> /// <returns>场景函数</returns> private SceneFunction ParseSaToSF(SceneAction funcSa, string sceneName) { // 获得函数签名 string signature = funcSa.argsDict["sign"]; string[] signItem = signature.Split(new char[] { '(', ')' }, StringSplitOptions.RemoveEmptyEntries); List<string> funcParas = new List<string>(); // 如果没有参数就跳过参数遍历 if (signItem.Length > 1) { string[] varItem = signItem[1].Split(new char[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries); foreach (string ivar in varItem) { funcParas.Add(ivar); } } SceneFunction nsf = new SceneFunction(signItem[0].Trim(), sceneName, funcSa); nsf.Param = funcParas; return nsf; }
/// <summary> /// 向栈机提交一个函数调用 /// </summary> /// <param name="sf">被调用函数的SceneFuction实例</param> /// <param name="args">实参数列表</param> /// <param name="offset">PC偏移量</param> public void Submit(SceneFunction sf, List<object> args, int offset = 0) { // 处理形参顺序 string argc = String.Empty; foreach (var arg in sf.Param) { argc += "," + arg; } if (argc.Length > 0) { argc = argc.Substring(1); } StackMachineFrame smf = new StackMachineFrame() { State = StackMachineState.FunctionCalling, ScriptName = sf.Callname, PC = offset, IP = sf.Sa, BindingFunction = sf, Argv = args, BindingFunctionName = String.Format("{0}?{1}", sf.GlobalName, this.coreStack.Count.ToString()), BindingSceneName = sf.ParentSceneName, Delay = TimeSpan.FromMilliseconds(0), Tag = argc }; this.coreStack.Push(smf); this.EBP = this.coreStack.Peek(); }