public override bool OnExportCode(ActionBranch previousAction, ActionBranch nextAction, ILimnorCodeCompiler compiler, CodeMemberMethod method, CodeStatementCollection statements) { if (IsCompiled) { return(false); } //preventing of compiling it twice IsCompiled = true; bool isGotoPoint = this.IsGotoPoint; ActionBranch nt = nextAction; if (_jumpToId != 0) { //next action is the one it jumps to nt = _jumpToActionBranch; } MethodSegment ms0 = null; CodeStatementCollection sts = statements; if (isGotoPoint) { //two or more branches in the same thread linked to this branch //since goto-label must be in the method scope, not sub-scope, this branch code must be //in the method scope ms0 = CompilerUtil.GetGotoBranch(method, Method, this.FirstActionId); if (ms0 == null) { sts = new CodeStatementCollection(); ms0 = new MethodSegment(sts); CompilerUtil.AddGotoBranch(method, Method, this.FirstActionId, ms0, this.GroupBranchId); } else { throw new DesignerException("Action list as goto branch {0} compiled twice", this.FirstActionId); } //use goto statement to jump to this branch is the responsibility of the branches jumping to it. } if (this.IsWaitingPoint) { sts.Add(new CodeExpressionStatement( new CodeMethodInvokeExpression( new CodeTypeReferenceExpression(typeof(WaitHandle)), "WaitAll", new CodeVariableReferenceExpression(XmlSerialization.FormatString("wh_{0}_{1}", IdToKey(this.StartingBranchId), this.BranchKey))))); } bool b0 = base.OnExportCode(previousAction, nt, compiler, method, sts); if (ms0 != null) { ms0.Completed = b0; } if (b0) { return(true); } else { //not all sub-branches of this branch completed. //check jumping if (_jumpToId != 0) { bool bRet = false; //same thread: use goto or fall through; otherwise use waiting point if (_jumpToActionBranch.StartingBranchId == this.StartingBranchId) { //a goto branch, use goto if (_jumpToActionBranch.IsGotoPoint) { sts.Add(new CodeGotoStatement(ActionBranch.IdToLabel(_jumpToId))); bRet = true; } if (!_jumpToActionBranch.IsCompiled) { bool b = _jumpToActionBranch.ExportCode(this, null, compiler, method, sts); if (!_jumpToActionBranch.IsGotoPoint) { bRet = b; } } } return(bRet); } else { //not completed return(false); } } }
/// <summary> /// /// </summary> /// <param name="previousAction"></param> /// <param name="nextAction"></param> /// <param name="compiler"></param> /// <param name="method"></param> /// <param name="statements"></param> /// <returns></returns> public override bool OnExportCode(ActionBranch previousAction, ActionBranch nextAction, ILimnorCodeCompiler compiler, CodeMemberMethod method, CodeStatementCollection statements) { if (IsCompiled) { return(false); } //preventing of compiling it twice IsCompiled = true; if (_ifActions != null && _elseActions != null && _ifActions.BranchId == _elseActions.BranchId) { throw new DesignerException("'Cast as' action [{0}, {1}] goes to the same action", this.BranchId, this.Name); } bool isGotoPoint = this.IsGotoPoint; MethodSegment ms0 = null; CodeStatementCollection sts = statements; if (isGotoPoint) { //two or more branches in the same thread linked to this branch //since goto-label must be in the method scope, not sub-scope, this branch code must be //in the method scope ms0 = CompilerUtil.GetGotoBranch(method, Method, this.FirstActionId); if (ms0 == null) { sts = new CodeStatementCollection(); ms0 = new MethodSegment(sts); CompilerUtil.AddGotoBranch(method, Method, this.FirstActionId, ms0, this.GroupBranchId); } else { throw new DesignerException("Action list as goto branch {0} compiled twice", this.FirstActionId); } //use goto statement to jump to this branch is the responsibility of the branches jumping to it. } if (this.IsWaitingPoint) { sts.Add(new CodeExpressionStatement( new CodeMethodInvokeExpression( new CodeTypeReferenceExpression(typeof(WaitHandle)), "WaitAll", new CodeVariableReferenceExpression(XmlSerialization.FormatString("wh_{0}_{1}", IdToKey(this.StartingBranchId), this.BranchKey))))); } try { CodeExpression c; if (_source == null || _target == null) { c = new CodePrimitiveExpression(false); } else { StringBuilder sb = new StringBuilder(); sb.Append(_source.CodeName); sb.Append(" as "); sb.Append(_target.BaseClassType.FullName); CodeAssignStatement cas = new CodeAssignStatement(); cas.Left = new CodeVariableReferenceExpression(_target.CodeName); cas.Right = new CodeSnippetExpression(sb.ToString()); sts.Add(cas); CodeBinaryOperatorExpression cb = new CodeBinaryOperatorExpression(); cb.Left = new CodeVariableReferenceExpression(_target.CodeName); cb.Operator = CodeBinaryOperatorType.IdentityInequality; cb.Right = new CodePrimitiveExpression(null); c = cb; } bool b1 = false; bool b2 = false; CodeConditionStatement ccs = new CodeConditionStatement(); ccs.Condition = c; if (_ifActions != null) { if (_ifActions.IsGotoPoint) { CodeGotoStatement gotoCode = new CodeGotoStatement(ActionBranch.IdToLabel(_ifActions.FirstActionId)); ccs.TrueStatements.Add(gotoCode); if (!_ifActions.IsCompiled) { _ifActions.ExportCode(null, null, compiler, method, null); } b1 = true; } else { b1 = _ifActions.ExportCode(previousAction, null, compiler, method, ccs.TrueStatements); } } if (_elseActions != null) { if (_elseActions.IsGotoPoint) { CodeGotoStatement gotoCode = new CodeGotoStatement(ActionBranch.IdToLabel(_elseActions.FirstActionId)); ccs.FalseStatements.Add(gotoCode); if (!_elseActions.IsCompiled) { _elseActions.ExportCode(null, null, compiler, method, null); } b2 = true; } else { b2 = _elseActions.ExportCode(previousAction, null, compiler, method, ccs.FalseStatements); } } sts.Add(ccs); if (b1 && b2) { if (ms0 != null) { ms0.Completed = true; } return(true); } } catch (Exception err) { throw new DesignerException(err, "Error compiling Condition action {0}. See inner exception for details", TraceInfo); } return(false); }