//-----------------------------------------------------------------------------
//
// Copyright (C) Microsoft Corporation. All Rights Reserved.
//
//-----------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Cci;
using Microsoft.Cci.MetadataReader;
using Microsoft.Cci.MutableCodeModel;
using Microsoft.Cci.Contracts;
using Microsoft.Cci.ILToCodeModel;
using Bpl = Microsoft.Boogie;
using System.Diagnostics.Contracts;
using TranslationPlugins;
using BytecodeTranslator.Phone;
namespace BytecodeTranslator {
///
/// Responsible for traversing all metadata elements (i.e., everything exclusive
/// of method bodies).
///
public class MetadataTraverser : BaseMetadataTraverser {
readonly Sink sink;
public readonly TraverserFactory factory;
public readonly IDictionary PdbReaders;
public PdbReader/*?*/ PdbReader;
public MetadataTraverser(Sink sink, IDictionary pdbReaders)
: base() {
this.sink = sink;
this.factory = sink.Factory;
this.PdbReaders = pdbReaders;
}
#region Overrides
public override void Visit(IModule module) {
this.PdbReaders.TryGetValue(module, out this.PdbReader);
base.Visit(module);
}
public override void Visit(IAssembly assembly) {
this.PdbReaders.TryGetValue(assembly, out this.PdbReader);
this.sink.BeginAssembly(assembly);
try {
base.Visit(assembly);
} finally {
this.sink.EndAssembly(assembly);
}
}
///
/// Translate the type definition.
///
///
public override void Visit(ITypeDefinition typeDefinition) {
if (!this.sink.TranslateType(typeDefinition)) return;
var savedPrivateTypes = this.privateTypes;
this.privateTypes = new List();
trackPageNameVariableName(typeDefinition);
trackPhoneApplicationClassname(typeDefinition);
if (typeDefinition.IsClass) {
bool savedSawCctor = this.sawCctor;
this.sawCctor = false;
sink.FindOrCreateType(typeDefinition);
base.Visit(typeDefinition);
if (!this.sawCctor) {
CreateStaticConstructor(typeDefinition);
}
this.sawCctor = savedSawCctor;
} else if (typeDefinition.IsDelegate) {
sink.AddDelegateType(typeDefinition);
} else if (typeDefinition.IsInterface) {
sink.FindOrCreateType(typeDefinition);
base.Visit(typeDefinition);
} else if (typeDefinition.IsEnum) {
return; // enums just are translated as ints
} else if (typeDefinition.IsStruct) {
sink.FindOrCreateType(typeDefinition);
CreateDefaultStructConstructor(typeDefinition);
CreateStructCopyConstructor(typeDefinition);
base.Visit(typeDefinition);
} else {
Console.WriteLine("Unknown kind of type definition '{0}' was found",
TypeHelper.GetTypeName(typeDefinition));
throw new NotImplementedException(String.Format("Unknown kind of type definition '{0}'.", TypeHelper.GetTypeName(typeDefinition)));
}
this.Visit(typeDefinition.PrivateHelperMembers);
foreach (var t in this.privateTypes) {
this.Visit(t);
}
}
List privateTypes = new List();
private void trackPhoneApplicationClassname(ITypeDefinition typeDef) {
if (PhoneCodeHelper.instance().PhonePlugin != null && typeDef.isPhoneApplicationClass(sink.host)) {
INamespaceTypeDefinition namedTypeDef = typeDef as INamespaceTypeDefinition;
// string fullyQualifiedName = namedTypeDef.ContainingNamespace.Name.Value + "." + namedTypeDef.Name.Value;
string fullyQualifiedName = namedTypeDef.ToString();
PhoneCodeHelper.instance().setMainAppTypeReference(typeDef);
PhoneCodeHelper.instance().setMainAppTypeName(fullyQualifiedName);
}
}
private void trackPageNameVariableName(ITypeDefinition typeDef) {
if (PhoneCodeHelper.instance().PhonePlugin != null && typeDef.isPhoneApplicationPageClass(sink.host)) {
INamespaceTypeDefinition namedTypeDef = typeDef as INamespaceTypeDefinition;
string fullyQualifiedName = namedTypeDef.ToString();
string xamlForClass = PhoneCodeHelper.instance().getXAMLForPage(fullyQualifiedName);
if (xamlForClass != null) { // if not it is possibly an abstract page
string uriName = PhoneControlsPlugin.getURIBase(xamlForClass);
Bpl.Constant uriConstant = sink.FindOrCreateConstant(uriName);
PhoneCodeHelper.instance().setBoogieStringPageNameForPageClass(fullyQualifiedName, uriConstant.Name);
}
}
}
private void CreateDefaultStructConstructor(ITypeDefinition typeDefinition) {
Contract.Requires(typeDefinition.IsStruct);
var proc = this.sink.FindOrCreateProcedureForDefaultStructCtor(typeDefinition);
this.sink.BeginMethod(typeDefinition);
var stmtTranslator = this.factory.MakeStatementTraverser(this.sink, this.PdbReader, false);
var stmts = new List();
foreach (var f in typeDefinition.Fields) {
if (f.IsStatic) continue;
var s = new ExpressionStatement() {
Expression = new Assignment() {
Source = new DefaultValue() { DefaultValueType = f.Type, Type = f.Type, },
Target = new TargetExpression() {
Definition = f,
Instance = new ThisReference() { Type = typeDefinition, },
Type = f.Type,
},
Type = f.Type,
},
};
}
stmtTranslator.Visit(stmts);
var translatedStatements = stmtTranslator.StmtBuilder.Collect(Bpl.Token.NoToken);
var lit = Bpl.Expr.Literal(1);
lit.Type = Bpl.Type.Int;
var args = new List