Hi!

I must start with to say, thank you for a quick reply when I previously 
E-Mailed you, JB Evains!

To make it easier, i will paste some of the mail I sent JB Evains earlier.

----

I'm trying to create an application to translate Bethesda's Skyrim Papyrus 
script into CLR and back. Enabling people to write all scripts using C# or 
any other .NET language; build it using visual studio and then 
automatically converts the CIL from the built .dll into Papyrus Assembly 
code. So far this works for very simple .NET applications. It even builds 
the output Papyrus Assembly into a compiled script that works in Skyrim.

Now for my main issue. I'm also trying to do it the other way around. And 
that is to read a Papyrus Assembly Code and generate a .NET library so that 
the users can reference to any existing scripts from C#.

I'm able to generate a .dll after reading a Papyrus Assembly file but 
having issues wheb it comes to the  TypeReference object. Since Papyrus is 
a Object Oriented Script Language it contains stuff as extending a script 
from another (BaseTypes) using other scripts as variables, parameters and 
ReturnTypes for methods.

But the issue is that when I'm trying to add a basetype to a defined 
TypeDefinition using a TypeReference, or when trying to add a TypeReference 
to a parameter or as a ReturnType of a method, i'm able to write the binary 
but when i try to reference to the written binary from a new .NET project, 
all the objects gives out weird information in the intellisense of visual 
studio.

Looks like:
PapyrusDotNet.Core.Actor+ PapyrusDotNet.Core.ObjectReference/Form

And doesnt show any information about the parameters or the method name.

What would be the best way to define your own TypeReference when you are 
trying to Reference to a Type that you have created inside the same Module. 
Basically, best way to get a TypeReference from a TypeDefinition?


Now, for some code, this is how i create my TypeDefinitions (Remember, the 
original scripts are referencing to eachother but at the same time i'm only 
adding them one after another, which I know that right now gave me a small 
headache as it may happen that one of the scripts parsed/ and added as a 
TypeDefinition to my output .dll are referencing to other objects that not 
yet have been added. I tried solving this by going through all those 
references after all objects have been added and updating any references 
that did not work during the parsing)

public static TypeDefinition TypeDefinitionFromPapyrus(PapyrusAsmObject 
input)
{
var newType = new TypeDefinition("PapyrusDotNet.Core", input.Name, 
TypeAttributes.Class);
newType.IsPublic = true;

if (!string.IsNullOrEmpty(input.ExtendsName))
{
newType.BaseType = new TypeReference("PapyrusDotNet.Core", 
input.ExtendsName, MainModule, MainModule);
newType.DeclaringType = MainModule.Types.FirstOrDefault(t => t.FullName == 
newType.BaseType.FullName);
newType.Scope = MainModule;
}

foreach (var prop in input.PropertyTable)
{
var typeRef = GetTypeReference(null, prop.Type);
var pro = new PropertyDefinition(prop.Name, PropertyAttributes.HasDefault, 
typeRef);
newType.Properties.Add(pro);
}

AddEmptyConstructor(newType);

foreach (var state in input.States)
{
TypeReference typeRef = GetTypeReference(newType);
// var typeRef = MainModule.TypeSystem.Void;

var function = new MethodDefinition(state.Name, MethodAttributes.Public, 
typeRef);
function.IsStatic = state.IsStatic;


foreach (var par in state.Params)
{
TypeReference typeRefp = GetTypeReference(null, par.Type);
// var typeRefp = MainModule.TypeSystem.Object;

var nPar = new ParameterDefinition(par.Name, ParameterAttributes.None, 
typeRefp);
function.Parameters.Add(nPar);
}
bool skipAdd = false;
foreach (var m in newType.Methods)
{
if (m.Name == function.Name)
{
if (m.Parameters.Count == function.Parameters.Count)
{
skipAdd = true;
for (int pi = 0; pi < m.Parameters.Count; pi++)
{
if (m.Parameters[pi].ParameterType.FullName != 
function.Parameters[pi].ParameterType.FullName) skipAdd = false;
}
break;
}
}
}
if (!skipAdd)
newType.Methods.Add(function);
}
return newType;
}

public static void AddEmptyConstructor(TypeDefinition type)
{
var methodAttributes = MethodAttributes.Public | MethodAttributes.HideBySig 
| MethodAttributes.SpecialName | MethodAttributes.RTSpecialName;
var method = new MethodDefinition(".ctor", methodAttributes, 
MainModule.TypeSystem.Void);
/*method.Body.Instructions.Add(Instruction.Create(OpCodes.Ldarg_0));
method.Body.Instructions.Add(Instruction.Create(OpCodes.Call, 
baseEmptyConstructor));
*/
method.Body.Instructions.Add(Instruction.Create(OpCodes.Ret));
type.Methods.Add(method);
}

private static TypeReference GetTypeReference(TypeDefinition newType, 
string fallback = null)
{
var typeName = "";
if (!string.IsNullOrEmpty(fallback))
typeName = fallback;
else
typeName = newType.FullName;

var ns = GetTypeNamespace(typeName);
var tn = GetTypeName(typeName);

if (ns == "System")
{
switch (tn.ToLower())
{
case "none":
case "void":
return MainModule.TypeSystem.Void;
case "int":
return MainModule.TypeSystem.Int32;
case "string":
return MainModule.TypeSystem.String;
case "float":
return MainModule.TypeSystem.Double;
case "bool":
case "boolean":
return MainModule.TypeSystem.Boolean;
default:
return MainModule.TypeSystem.Object;
}
}
var typeRef = new TypeReference(ns, tn, MainModule, MainModule);
typeRef.DeclaringType = MainModule.Types.FirstOrDefault(t => t.FullName == 
typeName);
typeRef.Scope = MainModule;
return typeRef;
}



private static string GetTypeName(string p)
{
if (p.Contains('.')) p = p.Split('.').LastOrDefault();
var pl = p.ToLower();

if (pl == "boolean") 
return "bool";
if (pl == "none") 
return "void";
 if (pl == "float" || pl == "int" || pl == "bool" || pl == "string") return 
pl;

return p;
}

private static string GetTypeNamespace(string p)
{
if (p.Contains('.')) p = p.Split('.').LastOrDefault();
var pl = p.ToLower();
/* have not added all possible types yet though.. might be a better way of 
doing it. */
if (pl == "string" || pl == "int" || pl == "boolean" || pl == "bool" || pl 
== "none"
   || pl == "void" || pl == "float" || pl == "short" || pl == "char" || pl 
== "double"
   || pl == "int32" || pl == "integer32" || pl == "long" || pl == "uint")
{
return "System";
}
return "PapyrusDotNet.Core";
}



I'm sorry for the lack of comments in my code...
But as I said before, i'm able to build a .dll containing the classes that 
I was looking for, except... When I'm opening up the .dll file in, lets say 
.NET Reflector 


The classes looks like following:

namespace PapyrusDotNet.Core
{
    using System;

    public class Action : Form
    {
        public Form.Action.Form/Action GetState();
        public Form.Action.Form/Action GotoState(string newState);
    }
}

Clicking on 'Form.Action.Form/Action' would give me an error as 
'PapyrusDotNet.Core.Form+Action+Form/Action' is not loaded or may be hidden 
due to your visbility settings.

And when referencing to this dll in visual studio, lets say I have a method 
called: 

public ObjectReference OnSell(Actor actor)

but in Intellisense i get something as following for it:

(PapyrusDotNet.Core.actor 
akSeller):PapyrusDotNet.Core.Form+PapyrusDotNet.Core.ObjectReference+PapyrusDotNet.Core.Form/ObjectReference

When i'm expecting to see:

(Actor akSeller):ObjectReference



Once again, I have to apologize for this long post! I hope it made any 
sense to you guys, in general what i'm trying to do is to create an 
assembly using mono.cecil, within this assembly i define new Types and 
those types may be extending some of eachother, so one type that ive 
recently added to the assembly might be extending another/new type that is 
being added later in the process. These types are in turn used as 
parameters, method returnTypes and variables.

Best Regards,
Karl Johansson

-- 
-- 
--
mono-cecil
--- 
You received this message because you are subscribed to the Google Groups 
"mono-cecil" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to