private void AddBlockMethod(ZMethod zMethod, Class methodClass, BasicBlock block, List<Scope> nonTrivialScopes)
{
Method blockMethod = (Method)Templates.GetTypeTemplateByName("BlockMethod").Members[0];
blockMethod.Name = new Identifier(block.Name);
methodClass.Members.Add(blockMethod);
blockMethod.DeclaringType = methodClass;
// Generate the appropriate closing statements for the block. Indicate if the
// block terminates an atomic region and establish the transfer of control to
// the next block(s) or out of the method.
if ((ZingCompilerOptions.IsPreemtive && !block.MiddleOfTransition && !block.IsReturn) || (block.Yields))
{
// p.MiddleOfTransition = false;
blockMethod.Body.Statements.Add(
new ExpressionStatement(
new AssignmentExpression(
new AssignmentStatement(
new QualifiedIdentifier(Identifier.For("p"), Identifier.For("MiddleOfTransition")),
new Literal(false, SystemTypes.Boolean)
)
)
)
);
}
// p.AtomicityLevel = this.SavedAtomicityLevel + X;
blockMethod.Body.Statements.Add(
new ExpressionStatement(
new AssignmentExpression(
new AssignmentStatement(
new QualifiedIdentifier(Identifier.For("p"), Identifier.For("AtomicityLevel")),
new BinaryExpression(
new QualifiedIdentifier(new This(), Identifier.For("SavedAtomicityLevel")),
new Literal(block.RelativeAtomicLevel, SystemTypes.Int32),
NodeType.Add
)
)
)
)
);
#if false
//
// The following code was added for summarization, but isn't quite right. It
// updates the nextBlock too early for some blocks. -- Tony
//
//
// when generating summaries of type MaxCall, we need to
// know the value of nextBlock before we invoke p.Call().
// the first of the two basic blocks of a Zing method call
// is guaranteed to fall through, so we only need to lift
// the assignment of nextBlock for fall-through blocks.
if (block.ConditionalTarget == null && block.UnconditionalTarget != null)
{
stmt = Templates.GetStatementTemplate("UnconditionalBlockTransfer");
Replacer.Replace(stmt, "_UnconditionalBlock",
new Identifier(block.UnconditionalTarget.Name));
blockMethod.Body.Statements.Add(stmt);
}
#endif
if (block.Attributes != null)
{
Duplicator duplicator = new Duplicator(null, null);
for (int i = 0, n = block.Attributes.Count; i < n; i++)
{
if (block.Attributes[i] == null)
continue;
AttributeNode dupAttr = duplicator.VisitAttributeNode(block.Attributes[i]);
Normalizer normalizer = new Normalizer(false);
ExpressionList attrParams = normalizer.VisitExpressionList(dupAttr.Expressions);
// application.Trace(_context, _contextAttr, new Z.Attributes._attrName(...) );
ExpressionStatement traceStmt = new ExpressionStatement(
new MethodCall(
new QualifiedIdentifier(Identifier.For("application"), Identifier.For("Trace")),
new ExpressionList(
SourceContextConstructor(dupAttr.SourceContext),
new Literal(null, SystemTypes.Object),
new Construct(
new MemberBinding(
null,
new TypeExpression(
new QualifiedIdentifier(
new QualifiedIdentifier(Identifier.For("Z"), Identifier.For("Attributes")),
dupAttr.Type.Name
)
)
),
attrParams
)
)
)
);
blockMethod.Body.Statements.Add(traceStmt);
}
}
if (block.Statement != null)
{
if (block.SkipNormalizer)
blockMethod.Body.Statements.Add(block.Statement);
else
{
// Do statement-level code-gen pass on the block's statement
Normalizer normalizer = new Normalizer(this, block.Attributes, block.SecondOfTwo);
blockMethod.Body.Statements.Add((Statement)normalizer.Visit(block.Statement));
}
}
if (block.ConditionalTarget != null && block.ConditionalExpression != null)
{
Block trueBlock, falseBlock;
// if (_conditionalExpression)
// nextBlock = Blocks._conditionalTarget;
// else
// nextBlock = Blocks._unconditionalTarget;
blockMethod.Body.Statements.Add(
new If(
block.ConditionalExpression,
trueBlock = new Block(new StatementList(
new ExpressionStatement(
new AssignmentExpression(
new AssignmentStatement(
Identifier.For("nextBlock"),
new QualifiedIdentifier(
Identifier.For("Blocks"),
Identifier.For(block.ConditionalTarget.Name)
)
)
)
)
)),
falseBlock = new Block(new StatementList(
new ExpressionStatement(
new AssignmentExpression(
new AssignmentStatement(
Identifier.For("nextBlock"),
new QualifiedIdentifier(
Identifier.For("Blocks"),
Identifier.For(block.UnconditionalTarget.Name)
)
)
)
)
))
)
);
AddScopeCleanupCalls(trueBlock.Statements, block, block.ConditionalTarget, nonTrivialScopes);
AddScopeCleanupCalls(falseBlock.Statements, block, block.UnconditionalTarget, nonTrivialScopes);
}
else if (block.UnconditionalTarget != null)
{
// nextBlock = Blocks.X;
blockMethod.Body.Statements.Add(
new ExpressionStatement(
new AssignmentExpression(
new AssignmentStatement(
Identifier.For("nextBlock"),
new QualifiedIdentifier(Identifier.For("Blocks"), Identifier.For(block.UnconditionalTarget.Name))
)
)
)
);
AddScopeCleanupCalls(blockMethod.Body.Statements, block, block.UnconditionalTarget, nonTrivialScopes);
}
else if (block.IsReturn)
{
Debug.Assert(block.UnconditionalTarget == null);
Statement returnCall = Templates.GetStatementTemplate("ReturnBlockTransfer");
SourceContext context;
Return ret = block.Statement as Return;
if (ret != null)
{
context = ret.SourceContext;
}
else
{
// If not a return stmt, the context is the closing brace of the method
context = zMethod.SourceContext;
context.StartPos = context.EndPos - 1;
}
Replacer.Replace(returnCall, "_context", SourceContextConstructor(context));
Replacer.Replace(returnCall, "_contextAttr", ContextAttributeConstructor(block.Attributes));
blockMethod.Body.Statements.Add(returnCall);
// StateImpl.IsReturn = true;
blockMethod.Body.Statements.Add(
new ExpressionStatement(
new AssignmentExpression(
new AssignmentStatement(
new QualifiedIdentifier(Identifier.For("StateImpl"), Identifier.For("IsReturn")),
new Literal(true, SystemTypes.Boolean)
)
)
)
);
}
}