//
//
//
//
// $Revision$
//
using System;
using System.Collections.Generic;
using System.Drawing;
using ICSharpCode.NRefactory.Parser;
using ICSharpCode.NRefactory.Parser.AST;
using Boo.Lang.Compiler;
using B = Boo.Lang.Compiler.Ast;
namespace NRefactoryToBooConverter
{
public partial class ConvertVisitor : IAstVisitor
{
string fileName;
CompilerErrorCollection errors;
CompilerWarningCollection warnings;
StringComparer nameComparer;
ConverterSettings settings;
B.Module module;
public ConvertVisitor(ConverterSettings settings)
{
this.settings = settings;
this.fileName = settings.FileName;
this.errors = settings.Errors;
this.warnings = settings.Warnings;
this.nameComparer = settings.NameComparer;
}
int generatedNameNumber;
string GenerateName()
{
return settings.NameGenerationPrefix + (++generatedNameNumber).ToString(System.Globalization.NumberFormatInfo.InvariantInfo);
}
B.LexicalInfo lastLexicalInfo;
B.LexicalInfo GetLexicalInfo(INode node)
{
if (node == null)
return new B.LexicalInfo(fileName);
Location point = node.StartLocation;
if (!point.IsEmpty) {
lastLexicalInfo = new B.LexicalInfo(fileName, point.Y, point.X);
}
if (lastLexicalInfo == null) {
lastLexicalInfo = new B.LexicalInfo(fileName);
}
return lastLexicalInfo;
}
void AddError(B.LexicalInfo lex, string errorMessage)
{
errors.Add(new CompilerError(lex, errorMessage));
}
void AddError(INode node, string errorMessage)
{
AddError(GetLexicalInfo(node), errorMessage);
}
void AddWarning(B.LexicalInfo lex, string warningMessage)
{
warnings.Add(new CompilerWarning(lex, warningMessage));
}
void AddWarning(INode node, string warningMessage)
{
AddWarning(GetLexicalInfo(node), warningMessage);
}
B.SourceLocation GetEndLocation(INode node)
{
return GetLocation(node.EndLocation);
}
B.SourceLocation GetLocation(Location point)
{
return new B.SourceLocation(point.Y, point.X);
}
B.TypeMemberModifiers ConvertModifier(AttributedNode node, B.TypeMemberModifiers defaultVisibility)
{
Modifier m = node.Modifier;
B.TypeMemberModifiers r = B.TypeMemberModifiers.None;
if ((m & Modifier.Private) != 0)
r |= B.TypeMemberModifiers.Private;
if ((m & Modifier.Internal) != 0)
r |= B.TypeMemberModifiers.Internal;
if ((m & Modifier.Public) != 0)
r |= B.TypeMemberModifiers.Public;
if ((m & Modifier.Protected) != 0)
r |= B.TypeMemberModifiers.Protected;
if (r == B.TypeMemberModifiers.None)
r = defaultVisibility;
if ((m & Modifier.Abstract) != 0)
r |= B.TypeMemberModifiers.Abstract;
if ((m & Modifier.Virtual) != 0)
r |= B.TypeMemberModifiers.Virtual;
if ((m & Modifier.Sealed) != 0)
r |= B.TypeMemberModifiers.Final;
if ((m & Modifier.Static) != 0) {
r |= B.TypeMemberModifiers.Static;
} else if (currentType != null && currentType.IsStatic) {
if (!(node is TypeDeclaration))
r |= B.TypeMemberModifiers.Static;
}
if ((m & Modifier.Override) != 0)
r |= B.TypeMemberModifiers.Override;
if ((m & Modifier.ReadOnly) != 0 && !(node is PropertyDeclaration)) {
r |= B.TypeMemberModifiers.Final;
}
if ((m & Modifier.Const) != 0) {
r |= B.TypeMemberModifiers.Final | B.TypeMemberModifiers.Static;
}
if ((m & Modifier.New) != 0) {
AddError(node, "shadowing is not supported");
}
if ((m & Modifier.Partial) != 0) {
r |= B.TypeMemberModifiers.Partial;
}
if ((m & Modifier.Extern) != 0) {
// not necessary in Boo
}
if ((m & Modifier.Volatile) != 0) {
AddError(node, "Volatile modifier is not supported");
}
if ((m & Modifier.Unsafe) != 0) {
AddError(node, "Unsafe modifier is not supported");
}
if ((m & Modifier.Overloads) != 0) {
// not necessary in Boo
}
if ((m & Modifier.WithEvents) != 0) {
// not necessary in Boo
}
if ((m & Modifier.Default) != 0) {
ParametrizedNode parametrizedNode = node as ParametrizedNode;
string name = null;
if (parametrizedNode != null) {
name = parametrizedNode.Name;
} else {
AddError(node, "Default modifier is not supported on this member.");
}
if (name != null && currentType != null) {
currentType.Attributes.Add(MakeAttribute("System.Reflection.DefaultMember", new B.StringLiteralExpression(name)));
}
}
return r;
}
B.Attribute MakeAttribute(string name, params B.Expression[] arguments)
{
B.Attribute a = new B.Attribute(lastLexicalInfo, name);
foreach (B.Expression arg in arguments) {
a.Arguments.Add(arg);
}
return a;
}
void ConvertTypeReferences(List input, B.TypeReferenceCollection output)
{
foreach (TypeReference t in input) {
B.TypeReference r = ConvertTypeReference(t);
if (r != null) {
output.Add(r);
}
}
}
Dictionary intrinsicTypeDictionary;
class BooTypeSystemServices : Boo.Lang.Compiler.TypeSystem.TypeSystemServices
{
public System.Collections.Hashtable Primitives {
get {
return _primitives;
}
}
}
string GetIntrinsicTypeName(string typeName)
{
if (settings.SimplifyTypeNames) {
if (intrinsicTypeDictionary == null) {
intrinsicTypeDictionary = new Dictionary();
foreach (System.Collections.DictionaryEntry entry in new BooTypeSystemServices().Primitives) {
string fullName = ((Boo.Lang.Compiler.TypeSystem.IEntity)entry.Value).FullName;
string primitiveName = (string)entry.Key;
intrinsicTypeDictionary[fullName] = primitiveName;
}
intrinsicTypeDictionary["System.Object"] = "object"; // and not 'duck'
}
string result;
if (intrinsicTypeDictionary.TryGetValue(typeName, out result))
return result;
}
return typeName;
}
B.TypeReference ConvertTypeReference(TypeReference t)
{
if (t == null || t.IsNull)
return null;
B.TypeReference r;
if (t.GenericTypes.Count > 0) {
r = new B.GenericTypeReference(GetLexicalInfo(t), GetIntrinsicTypeName(t.SystemType));
foreach (TypeReference ta in t.GenericTypes) {
((B.GenericTypeReference)r).GenericArguments.Add(ConvertTypeReference(ta));
}
} else {
r = new B.SimpleTypeReference(GetLexicalInfo(t), GetIntrinsicTypeName(t.SystemType));
}
if (t.IsArrayType) {
for (int i = t.RankSpecifier.Length - 1; i >= 0; --i) {
r = new B.ArrayTypeReference(GetLexicalInfo(t), r, new B.IntegerLiteralExpression(t.RankSpecifier[i] + 1));
}
}
if (t.PointerNestingLevel != 0) {
AddError(t, "Pointers are not supported by boo.");
}
return r;
}
B.TypeReference ConvertTypeReference(B.Expression expr)
{
B.TypeofExpression te = expr as B.TypeofExpression;
if (te != null)
return te.Type;
if (expr is B.ReferenceExpression) {
return new B.SimpleTypeReference(expr.ToCodeString());
}
AddError(expr.LexicalInfo, "Expected type, but found expression.");
return null;
}
public object Visit(TypeReference typeReference, object data)
{
return ConvertTypeReference(typeReference);
}
public object Visit(InnerClassTypeReference typeReference, object data)
{
return ConvertTypeReference(typeReference);
}
}
}