📄 convertvisitorstatements.cs
字号:
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
// <version>$Revision: 1014 $</version>
// </file>
using System;
using System.Collections;
using System.Collections.Generic;
using ICSharpCode.NRefactory.Parser;
using ICSharpCode.NRefactory.Parser.AST;
using Boo.Lang.Compiler;
using B = Boo.Lang.Compiler.Ast;
namespace NRefactoryToBooConverter
{
partial class ConvertVisitor
{
void ConvertStatements(IEnumerable statements, B.Block b)
{
foreach (Statement n in statements) {
AddToBlock(n, b);
}
}
Statement currentStatement;
object ConvertStatementInternal(Statement stmt)
{
Statement oldStatement = currentStatement;
currentStatement = stmt;
try {
return stmt.AcceptVisitor(this, null);
} finally {
currentStatement = oldStatement;
}
}
void AddToBlock(Statement n, B.Block b)
{
object result = ConvertStatementInternal(n);
if (result is ArrayList) {
foreach (B.Statement stmt in (ArrayList)result) {
b.Add(stmt);
}
} else {
B.Statement stmt = (B.Statement)result;
if (stmt != null) {
b.Add(stmt);
}
}
}
ArrayList ConvertStatements(IEnumerable statements)
{
ArrayList r = new ArrayList();
foreach (Statement n in statements) {
object result = ConvertStatementInternal(n);
if (result is ArrayList) {
r.AddRange((ArrayList)result);
} else if (result != null) {
r.Add(result);
}
}
return r;
}
B.Block ConvertBlock(Statement statement)
{
if (statement == null || statement.IsNull)
return null;
List<Statement> statements = new List<Statement>(1);
statements.Add(statement);
return ConvertBlock(statements);
}
B.Block ConvertBlock(BlockStatement block)
{
B.Block b = new B.Block(GetLexicalInfo(block));
b.EndSourceLocation = GetLocation(block.EndLocation);
ConvertStatements(block.Children, b);
return b;
}
B.Block ConvertBlock(List<Statement> statements)
{
if (statements.Count == 1) {
if (statements[0] is BlockStatement)
return ConvertBlock(statements[0] as BlockStatement);
}
B.Block b = new B.Block();
ConvertStatements(statements, b);
return b;
}
public object Visit(BlockStatement blockStatement, object data)
{
return ConvertBlock(blockStatement);
}
B.MacroStatement CreateMacro(INode node, string name, Statement embedded, params Expression[] arguments)
{
B.MacroStatement macro = new B.MacroStatement(GetLexicalInfo(node));
macro.Name = name;
ConvertExpressions(arguments, macro.Arguments);
if (embedded is BlockStatement) {
macro.Block = ConvertBlock((BlockStatement)embedded);
} else {
macro.Block = new B.Block();
macro.Block.Add((B.Statement)embedded.AcceptVisitor(this, null));
}
return macro;
}
public object Visit(FixedStatement fixedStatement, object data)
{
AddError(fixedStatement, "FixedStatement is not supported.");
return null;
}
public object Visit(UnsafeStatement unsafeStatement, object data)
{
AddError(unsafeStatement, "UnsafeStatement is not supported.");
return null;
}
public object Visit(CheckedStatement checkedStatement, object data)
{
return CreateMacro(checkedStatement, "checked", checkedStatement.Block);
}
public object Visit(UncheckedStatement uncheckedStatement, object data)
{
return CreateMacro(uncheckedStatement, "unchecked", uncheckedStatement.Block);
}
public object Visit(ExitStatement exitStatement, object data)
{
if (exitStatement.ExitType == ExitType.Function || exitStatement.ExitType == ExitType.Sub || exitStatement.ExitType == ExitType.Property) {
AddWarning(exitStatement, "ExitStatement is converted to 'return'");
return new B.ReturnStatement(GetLexicalInfo(exitStatement));
} else {
AddWarning(exitStatement, "ExitStatement is converted to 'break'");
return new B.BreakStatement(GetLexicalInfo(exitStatement));
}
}
/// <summary>
/// Make a loop:
/// $initializers
/// goto converterGeneratedName#
/// while true:
/// $iterators
/// :converterGeneratedName#
/// break $conditionType $condition
/// $body
/// </summary>
ArrayList MakeManualLoop(INode node, List<Statement> initializers, B.StatementModifierType conditionType, Expression condition, List<Statement> iterators, Statement body)
{
// we use this "while true" form because "continue" must not skip the iterator.
ArrayList list = ConvertStatements(initializers);
B.LabelStatement labelStatement = MakeLabel(GenerateName());
B.GotoStatement gotoStatement = new B.GotoStatement();
gotoStatement.Label = new B.ReferenceExpression(labelStatement.Name);
list.Add(gotoStatement);
B.WhileStatement w = new B.WhileStatement(GetLexicalInfo(node));
w.Condition = new B.BoolLiteralExpression(true);
list.Add(w);
w.Block = ConvertBlock(iterators);
B.BreakStatement breakStatement = new B.BreakStatement();
breakStatement.Modifier = new B.StatementModifier(conditionType, ConvertExpression(condition));
w.Block.Add(labelStatement);
w.Block.Add(breakStatement);
foreach (B.Statement st in ConvertBlock(body).Statements) {
w.Block.Add(st);
}
return list;
}
ArrayList MakeManualLoop(ForNextStatement forNextStatement)
{
Expression var = new IdentifierExpression(forNextStatement.VariableName);
List<Statement> initializers = new List<Statement>(1);
initializers.Add(new StatementExpression(new AssignmentExpression(var, AssignmentOperatorType.Assign, forNextStatement.Start)));
List<Statement> iterators = new List<Statement>(1);
Expression step = forNextStatement.Step;
if (step == null || step.IsNull)
step = new PrimitiveExpression(1, "1");
iterators.Add(new StatementExpression(new AssignmentExpression(var, AssignmentOperatorType.Add, step)));
PrimitiveExpression stepPE = step as PrimitiveExpression;
if (stepPE == null || !(stepPE.Value is int)) {
AddError(forNextStatement, "Step must be an integer literal");
return null;
}
BinaryOperatorType conditionOperator;
if ((int)stepPE.Value < 0) {
conditionOperator = BinaryOperatorType.GreaterThanOrEqual;// counting down
} else {
conditionOperator = BinaryOperatorType.LessThanOrEqual;// counting up
}
Expression condition = new BinaryOperatorExpression(var, conditionOperator, forNextStatement.End);
return MakeManualLoop(forNextStatement, initializers, B.StatementModifierType.Unless, condition, iterators, forNextStatement.EmbeddedStatement);
}
public object Visit(ForNextStatement forNextStatement, object data)
{
if (forNextStatement.TypeReference.IsNull)
return MakeManualLoop(forNextStatement);
B.ForStatement fs = new B.ForStatement(GetLexicalInfo(forNextStatement));
fs.Block = ConvertBlock(forNextStatement.EmbeddedStatement);
fs.Declarations.Add(new B.Declaration(forNextStatement.VariableName, null));
B.Expression start = ConvertExpression(forNextStatement.Start);
Expression end = forNextStatement.End;
if (forNextStatement.Step == null || forNextStatement.Step.IsNull) {
// range only goes to end - 1, so increment end
end = Expression.AddInteger(end, 1);
fs.Iterator = MakeMethodCall("range", start, ConvertExpression(end));
} else {
PrimitiveExpression stepPE = forNextStatement.Step as PrimitiveExpression;
if (stepPE == null || !(stepPE.Value is int)) {
AddError(forNextStatement, "Step must be an integer literal");
} else {
if ((int)stepPE.Value < 0)
end = Expression.AddInteger(end, -1);
else
end = Expression.AddInteger(end, 1);
}
fs.Iterator = MakeMethodCall("range", start, ConvertExpression(end), ConvertExpression(forNextStatement.Step));
}
return fs;
}
public object Visit(ForStatement forStatement, object data)
{
return MakeManualLoop(forStatement, forStatement.Initializers, B.StatementModifierType.Unless,
forStatement.Condition, forStatement.Iterator, forStatement.EmbeddedStatement);
}
public object Visit(DoLoopStatement doLoopStatement, object data)
{
bool frontCondition = doLoopStatement.ConditionPosition != ConditionPosition.End;
bool negateCondition = doLoopStatement.ConditionType == ConditionType.Until;
if (frontCondition && negateCondition) {
// VB: Do Unless * : ** : Loop
B.UnlessStatement u = new B.UnlessStatement(GetLexicalInfo(doLoopStatement));
u.Condition = ConvertExpression(doLoopStatement.Condition);
u.Block = ConvertBlock(doLoopStatement.EmbeddedStatement);
return u;
}
// While and Do loop
B.WhileStatement w = new B.WhileStatement(GetLexicalInfo(doLoopStatement));
if (frontCondition)
w.Condition = ConvertExpression(doLoopStatement.Condition);
else
w.Condition = new B.BoolLiteralExpression(true);
w.Block = ConvertBlock(doLoopStatement.EmbeddedStatement);
if (!frontCondition) {
B.BreakStatement breakStatement = new B.BreakStatement();
breakStatement.Modifier = new B.StatementModifier(negateCondition ? B.StatementModifierType.If : B.StatementModifierType.Unless,
ConvertExpression(doLoopStatement.Condition));
w.Block.Add(breakStatement);
}
return w;
}
public object Visit(ForeachStatement foreachStatement, object data)
{
B.ForStatement fs = new B.ForStatement(GetLexicalInfo(foreachStatement));
fs.EndSourceLocation = GetLocation(foreachStatement.EndLocation);
fs.Iterator = ConvertExpression(foreachStatement.Expression);
fs.Declarations.Add(new B.Declaration(foreachStatement.VariableName, ConvertTypeReference(foreachStatement.TypeReference)));
fs.Block = ConvertBlock(foreachStatement.EmbeddedStatement);
return fs;
}
public object Visit(AddHandlerStatement addHandlerStatement, object data)
{
B.Expression expr = new B.BinaryExpression(GetLexicalInfo(addHandlerStatement),
B.BinaryOperatorType.InPlaceAddition,
ConvertExpression(addHandlerStatement.EventExpression),
ConvertExpression(addHandlerStatement.HandlerExpression));
return new B.ExpressionStatement(expr);
}
public object Visit(RemoveHandlerStatement removeHandlerStatement, object data)
{
B.Expression expr = new B.BinaryExpression(GetLexicalInfo(removeHandlerStatement),
B.BinaryOperatorType.InPlaceSubtraction,
ConvertExpression(removeHandlerStatement.EventExpression),
ConvertExpression(removeHandlerStatement.HandlerExpression));
return new B.ExpressionStatement(expr);
}
public object Visit(RaiseEventStatement raiseEventStatement, object data)
{
B.MethodInvocationExpression mie = new B.MethodInvocationExpression(GetLexicalInfo(raiseEventStatement));
mie.Target = new B.ReferenceExpression(raiseEventStatement.EventName);
ConvertExpressions(raiseEventStatement.Arguments, mie.Arguments);
return new B.ExpressionStatement(mie);
}
public object Visit(EraseStatement eraseStatement, object data)
{
ArrayList statements = new ArrayList();
foreach (Expression expr in eraseStatement.Expressions) {
B.Expression e = ConvertExpression(expr);
e = new B.BinaryExpression(B.BinaryOperatorType.Assign, e, new B.NullLiteralExpression());
statements.Add(new B.ExpressionStatement(e));
}
return statements;
}
public object Visit(ReDimStatement reDimStatement, object data)
{
// Redim [Preserve] a(newBounds)
// without preserve:
// a = array(Type, newBounds)
// with preserve:
// ??1 = array(Type, newBounds)
// Array.Copy(a, ??1, System.Math.Min(a.Length, ??1.Length))
// a = ??1
if (reDimStatement.IsPreserve)
AddError(reDimStatement, "Redim Preserve is not supported.");
ArrayList list = new ArrayList();
foreach (InvocationExpression o in reDimStatement.ReDimClauses) {
if (o.TypeArguments != null && o.TypeArguments.Count > 0) {
AddError(o, "Type parameter are not allowed here.");
}
IdentifierExpression identifier = o.TargetObject as IdentifierExpression;
if (identifier == null) {
AddError(o, "Sorry, that expression is too complex to be resolved by the converter.");
} else {
// first we need to find out the array type
VariableResolver resolver = new VariableResolver(nameComparer);
TypeReference r = resolver.FindType(identifier.Identifier, reDimStatement);
if (r == null) {
AddError(o, "The name '" + identifier.Identifier + "' could not be resolved by the converter.");
} else if (!r.IsArrayType) {
AddError(o, identifier.Identifier + " is not an array.");
} else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -