private ProtoCore.AST.AssociativeAST.VarDeclNode ParseArgumentDeclaration(string parameterName, Type parameterType) { ProtoCore.AST.AssociativeAST.VarDeclNode varDeclNode = new ProtoCore.AST.AssociativeAST.VarDeclNode(); varDeclNode.memregion = ProtoCore.DSASM.MemoryRegion.kMemStack; varDeclNode.access = ProtoCore.DSASM.AccessSpecifier.kPublic; ProtoCore.AST.AssociativeAST.IdentifierNode identifierNode = new ProtoCore.AST.AssociativeAST.IdentifierNode { Value = parameterName, Name = parameterName, datatype = new ProtoCore.Type() { Name = "var", IsIndexable = false, rank = 0, UID = (int)ProtoCore.PrimitiveType.kTypeVar } }; //Lets emit native DS type object ProtoCore.Type argtype = CLRModuleType.GetProtoCoreType(parameterType, Module); varDeclNode.NameNode = identifierNode; varDeclNode.ArgumentType = argtype; return(varDeclNode); }
public static ProtoCore.Type GetProtoCoreType(Type type, CLRDLLModule module) { ProtoCore.Type protoCoreType; if (mTypeMaps.TryGetValue(type, out protoCoreType)) { return(protoCoreType); } if (type == typeof(object) || !CLRObjectMarshler.IsMarshaledAsNativeType(type)) { if (type.IsEnum) { protoCoreType = CLRModuleType.GetInstance(type, module, string.Empty).ProtoCoreType; } else { protoCoreType = CLRModuleType.GetInstance(type, null, string.Empty).ProtoCoreType; } } else { protoCoreType = CLRObjectMarshler.GetProtoCoreType(type); } lock (mTypeMaps) { mTypeMaps[type] = protoCoreType; } return(protoCoreType); }
/// <summary> /// Gets CLRModuleType for given Type. If CLRModuleType instance for the /// given type is not found, it creates a new one. If CLRDLLModule is /// passed as null, it creates empty CLRModuleType. /// </summary> /// <param name="module">CLRDLLModule which imports this type</param> /// <param name="type">System.Type to be imported in DesignScript</param> /// <param name="alias">Alias name, if any. For now its not supported.</param> public static CLRModuleType GetInstance(Type type, CLRDLLModule module, string alias) { CLRModuleType mtype; if (!mTypes.TryGetValue(type, out mtype)) { lock (mTypes) { if (!mTypes.TryGetValue(type, out mtype)) { mtype = new CLRModuleType(type); //Now check that a type with same name is not imported. Type otherType; if (mTypeNames.TryGetValue(mtype.FullName, out otherType)) throw new InvalidOperationException(string.Format("Can't import {0}, {1} is already imported as {2}, namespace support needed.", type.FullName, type.Name, otherType.FullName)); mTypes.Add(type, mtype); mTypeNames.Add(mtype.FullName, type); } } } if (module != null && mtype.Module == null) { mtype.Module = module; if (type.IsEnum) mtype.ClassNode = mtype.ParseEnumType(type, alias); else mtype.ClassNode = mtype.ParseSystemType(type, alias); } return mtype; }
/// <summary> /// /// </summary> /// <param name="type"></param> /// <param name="protoCoreType"></param> private static void GetProtoCoreType(Type type, ref ProtoCore.Type protoCoreType) { FFIObjectMarshler marshaler; if (type.IsArray) { Type elemType = type.GetElementType(); GetProtoCoreType(elemType, ref protoCoreType); protoCoreType.rank += type.GetArrayRank(); //set the rank. protoCoreType.IsIndexable = true; } else if (type.IsInterface && (typeof(ICollection).IsAssignableFrom(type) || typeof(IEnumerable).IsAssignableFrom(type))) { protoCoreType.rank += 1; protoCoreType.IsIndexable = true; } else if (type.IsGenericType && (typeof(ICollection).IsAssignableFrom(type) || typeof(IEnumerable).IsAssignableFrom(type))) { Type[] args = type.GetGenericArguments(); int nArgs = args.Length; if (nArgs != 1) { protoCoreType.Name = GetTypeName(type); protoCoreType.UID = (int)ProtoCore.PrimitiveType.kTypePointer; return; } Type elemType = args[0]; //TODO: Ideally we shouldn't be calling this method on CLRModuleType, //but we want to import this elemType, hence we do this. protoCoreType = CLRModuleType.GetProtoCoreType(elemType, null); protoCoreType.rank += 1; protoCoreType.IsIndexable = true; } else if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable <>)) { protoCoreType = CLRModuleType.GetProtoCoreType(Nullable.GetUnderlyingType(type), null); } else if (type == typeof(object)) { protoCoreType = PrimitiveMarshler.CreateType(ProtoCore.PrimitiveType.kTypeVar); } else if (type == typeof(void)) { protoCoreType = PrimitiveMarshler.CreateType(ProtoCore.PrimitiveType.kTypeVoid); } else if (protoCoreType.UID == (int)ProtoCore.PrimitiveType.kTypePointer) { protoCoreType.Name = GetTypeName(type); } else if (mPrimitiveMarshalers.TryGetValue(type, out marshaler)) { protoCoreType = marshaler.GetMarshaledType(type); } else { protoCoreType.Name = GetTypeName(type); protoCoreType.UID = (int)ProtoCore.PrimitiveType.kTypePointer; } }
private ProtoCore.AST.AssociativeAST.AssociativeNode ParseMethod(MethodInfo method) { ProtoCore.Type retype = CLRModuleType.GetProtoCoreType(method.ReturnType, Module); bool propaccessor = isPropertyAccessor(method); bool isOperator = isOverloadedOperator(method); FFIMethodAttributes mattrs = new FFIMethodAttributes(method); if (method.IsStatic && method.DeclaringType == method.ReturnType && !propaccessor && !isOperator) { //case for named constructor. Must return a pointer type if (!Object.Equals(method.ReturnType, CLRType)) { throw new InvalidOperationException("Unexpected type for constructor {0D28FC00-F8F4-4049-AD1F-BBC34A68073F}"); } retype = ProtoCoreType; ConstructorDefinitionNode node = ParsedNamedConstructor(method, method.Name, retype); node.MethodAttributes = mattrs; return(node); } //Need to hide property accessor from design script users, prefix with % string prefix = (isOperator || propaccessor) ? "%" : ""; var func = new ProtoCore.AST.AssociativeAST.FunctionDefinitionNode(); if (isOperator) { func.Name = string.Format("{0}{1}", prefix, GetDSOperatorName(method.Name)); } else { func.Name = string.Format("{0}{1}", prefix, method.Name); } func.Pattern = null; func.Signature = ParseArgumentSignature(method); if ((retype.IsIndexable && mattrs.AllowRankReduction) || (typeof(object).Equals(method.ReturnType))) { retype.rank = Constants.kArbitraryRank; } func.ReturnType = retype; func.FunctionBody = null; func.access = ProtoCore.Compiler.AccessSpecifier.kPublic; func.IsDNI = false; func.IsExternLib = true; func.ExternLibName = Module.Name; func.IsStatic = method.IsStatic; func.MethodAttributes = mattrs; return(func); }
//this is incomplete todo: implement public override List <FFIFunctionPointer> GetFunctionPointers(string className, string name) { CLRModuleType type = null; if (mTypes.TryGetValue(className, out type)) { return(type.GetFunctionPointers(name)); } if (name == ProtoCore.DSDefinitions.Keyword.Dispose) { List <FFIFunctionPointer> pointers = new List <FFIFunctionPointer>(); pointers.Add(new DisposeFunctionPointer(this, CLRModuleType.DisposeMethod, CLRModuleType.GetProtoCoreType(CLRModuleType.DisposeMethod.ReturnType, this))); return(pointers); } throw new KeyNotFoundException(string.Format("Function definition for {0}.{1}, not found", className, name)); }
public FFIMethodAttributes(MethodInfo method) { if (method == null) { throw new ArgumentException("method"); } FFIClassAttributes baseAttributes = null; Type type = method.DeclaringType; if (!CLRModuleType.TryGetTypeAttributes(type, out baseAttributes)) { baseAttributes = new FFIClassAttributes(type); CLRModuleType.SetTypeAttributes(type, baseAttributes); } if (null != baseAttributes) { HiddenInLibrary = baseAttributes.HiddenInLibrary; } attributes = method.GetCustomAttributes(false).Cast <Attribute>().ToArray(); foreach (var attr in attributes) { if (attr is AllowRankReductionAttribute) { AllowRankReduction = true; } else if (attr is RuntimeRequirementAttribute) { RequireTracing = (attr as RuntimeRequirementAttribute).RequireTracing; } else if (attr is MultiReturnAttribute) { var multiReturnAttr = (attr as MultiReturnAttribute); returnKeys = multiReturnAttr.ReturnKeys.ToList(); } else if (attr is IsVisibleInDynamoLibraryAttribute) { var visibleInLibraryAttr = attr as IsVisibleInDynamoLibraryAttribute; HiddenInLibrary = (visibleInLibraryAttr.Visible == false); } } }
private ProtoCore.AST.AssociativeAST.VarDeclNode ParseArgumentDeclaration(string parameterName, Type parameterType) { ProtoCore.AST.AssociativeAST.VarDeclNode varDeclNode = new ProtoCore.AST.AssociativeAST.VarDeclNode(); varDeclNode.memregion = ProtoCore.DSASM.MemoryRegion.kMemStack; varDeclNode.access = ProtoCore.Compiler.AccessSpecifier.kPublic; ProtoCore.AST.AssociativeAST.IdentifierNode identifierNode = new ProtoCore.AST.AssociativeAST.IdentifierNode { Value = parameterName, Name = parameterName, datatype = ProtoCore.TypeSystem.BuildPrimitiveTypeObject(ProtoCore.PrimitiveType.kTypeVar, 0) }; //Lets emit native DS type object ProtoCore.Type argtype = CLRModuleType.GetProtoCoreType(parameterType, Module); varDeclNode.NameNode = identifierNode; varDeclNode.ArgumentType = argtype; return(varDeclNode); }
private ProtoCore.AST.AssociativeAST.VarDeclNode ParseFieldDeclaration(FieldInfo f) { if (null == f || !IsBrowsable(f)) { return(null); } ProtoCore.AST.AssociativeAST.VarDeclNode varDeclNode = ParseArgumentDeclaration(f.Name, f.FieldType); //TODO: temporary limitation, can't have variable name matching with class name. if (null != CLRModuleType.GetImportedType(f.Name)) { return(null); } if (null != varDeclNode) { varDeclNode.IsStatic = f.IsStatic; } return(varDeclNode); }
private ProtoCore.AST.AssociativeAST.FunctionDefinitionNode ParseFieldAccessor(FieldInfo f) { if (null == f || !IsBrowsable(f)) { return(null); } ProtoCore.AST.AssociativeAST.FunctionDefinitionNode func = new ProtoCore.AST.AssociativeAST.FunctionDefinitionNode(); func.Name = string.Format("%get_{0}", f.Name); func.Pattern = null; func.Singnature = new ProtoCore.AST.AssociativeAST.ArgumentSignatureNode(); func.ReturnType = CLRModuleType.GetProtoCoreType(f.FieldType, Module); func.FunctionBody = null; func.access = ProtoCore.DSASM.AccessSpecifier.kPublic; func.IsDNI = false; func.IsExternLib = true; func.ExternLibName = Module.Name; func.IsStatic = f.IsStatic; return(func); }
/// <summary> /// Gets CLRModuleType for given Type. If CLRModuleType instance for the /// given type is not found, it creates a new one. If CLRDLLModule is /// passed as null, it creates empty CLRModuleType. /// </summary> /// <param name="module">CLRDLLModule which imports this type</param> /// <param name="type">System.Type to be imported in DesignScript</param> /// <param name="alias">Alias name, if any. For now its not supported.</param> public static CLRModuleType GetInstance(Type type, CLRDLLModule module, string alias) { CLRModuleType mtype; if (!mTypes.TryGetValue(type, out mtype)) { lock (mTypes) { if (!mTypes.TryGetValue(type, out mtype)) { mtype = new CLRModuleType(type); //Now check that a type with same name is not imported. Type otherType; if (mTypeNames.TryGetValue(mtype.ClassName, out otherType)) { throw new InvalidOperationException(string.Format("Can't import {0}, {1} is already imported as {2}, namespace support needed.", type.FullName, type.Name, otherType.FullName)); } mTypes.Add(type, mtype); mTypeNames.Add(mtype.ClassName, type); } } } if (module != null && mtype.Module == null) { mtype.Module = module; if (type.IsEnum) { mtype.ClassNode = mtype.ParseEnumType(type, alias); } else { mtype.ClassNode = mtype.ParseSystemType(type, alias); } } return(mtype); }
private ProtoCore.AST.AssociativeAST.AssociativeNode ParseMethod(MethodInfo method) { ProtoCore.Type retype = CLRModuleType.GetProtoCoreType(method.ReturnType, Module); bool propaccessor = isPropertyAccessor(method); if (method.IsStatic && method.DeclaringType == method.ReturnType && !propaccessor) { //case for named constructor. Must return a pointer type if (!Object.Equals(method.ReturnType, CLRType)) { throw new InvalidOperationException("Unexpected type for constructor {0D28FC00-F8F4-4049-AD1F-BBC34A68073F}"); } retype = ProtoCoreType; return(ParsedNamedConstructor(method, method.Name, retype)); } //Need to hide property accessor from design script users, prefix with % string prefix = propaccessor ? "%" : ""; ProtoCore.AST.AssociativeAST.FunctionDefinitionNode func = new ProtoCore.AST.AssociativeAST.FunctionDefinitionNode(); func.Name = string.Format("{0}{1}", prefix, method.Name); func.Pattern = null; func.Singnature = ParseArgumentSignature(method); if (retype.IsIndexable && AllowsRankReduction(method)) { retype.rank = -1; } func.ReturnType = retype; func.FunctionBody = null; func.access = ProtoCore.DSASM.AccessSpecifier.kPublic; func.IsDNI = false; func.IsExternLib = true; func.ExternLibName = Module.Name; func.IsStatic = method.IsStatic; return(func); }
private ProtoCore.Type[] GetArgumentTypes(FFIMemberInfo member) { return(member.GetParameters().Select( pi => CLRModuleType.GetProtoCoreType(pi.ParameterType, Module) ).ToArray()); }
private ClassDeclNode ParseSystemType(Type type, string alias) { Validity.Assert(!SupressesImport(type), "Supressed type is being imported!!"); string classname = alias; if (classname == null | classname == string.Empty) { classname = CLRObjectMarshler.GetTypeName(type); } ProtoCore.AST.AssociativeAST.ClassDeclNode classnode = CreateEmptyClassNode(classname); classnode.ExternLibName = Module.Name; classnode.className = classname; classnode.Name = type.Name; Type baseType = GetBaseType(type); if (baseType != null && !CLRObjectMarshler.IsMarshaledAsNativeType(baseType)) { string baseTypeName = CLRObjectMarshler.GetTypeName(baseType); classnode.superClass = new List <string>(); classnode.superClass.Add(baseTypeName); //Make sure that base class is imported properly. CLRModuleType.GetInstance(baseType, Module, string.Empty); } // There is no static class in runtime. static class is simply // marked as sealed and abstract. bool isStaticClass = type.IsSealed && type.IsAbstract; if (!isStaticClass) { // If all methods are static, it doesn't make sense to expose // constructor. ConstructorInfo[] ctors = type.GetConstructors(); foreach (var c in ctors) { if (c.IsPublic && !c.IsGenericMethod && !SupressesImport(c)) { ConstructorDefinitionNode node = ParseConstructor(c, type); classnode.funclist.Add(node); List <ProtoCore.Type> argTypes = GetArgumentTypes(node); RegisterFunctionPointer(node.Name, c, argTypes, node.ReturnType); } } } BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.Static; bool isDerivedClass = (classnode.superClass != null) && classnode.superClass.Count > 0; if (isDerivedClass) //has base class { flags |= BindingFlags.DeclaredOnly; //for derived class, parse only class declared methods. } bool isDisposable = typeof(IDisposable).IsAssignableFrom(type); MethodInfo[] methods = type.GetMethods(flags); bool hasDisposeMethod = false; foreach (var m in methods) { if (SupressesImport(m)) { continue; } if (isStaticClass && m.GetBaseDefinition().DeclaringType == baseType && baseType == typeof(object)) { continue; } //Don't include overriden methods or generic methods if (m.IsPublic && !m.IsGenericMethod && m == m.GetBaseDefinition()) { AssociativeNode node = ParseAndRegisterFunctionPointer(isDisposable, ref hasDisposeMethod, m); classnode.funclist.Add(node); } else if (!hasDisposeMethod && isDisposable && baseType == typeof(Object) && isDisposeMethod(m)) { AssociativeNode node = ParseAndRegisterFunctionPointer(isDisposable, ref hasDisposeMethod, m); classnode.funclist.Add(node); } } if (!hasDisposeMethod && !isDisposable) { AssociativeNode node = ParseAndRegisterFunctionPointer(true, ref hasDisposeMethod, mDisposeMethod); classnode.funclist.Add(node); } FieldInfo[] fields = type.GetFields(); foreach (var f in fields) { if (SupressesImport(f)) { continue; } //Supress if defined in super-type if (isDerivedClass) { FieldInfo[] supertypeFields = baseType.GetFields(); if (supertypeFields.Any(superF => superF.Name == f.Name)) { continue; } } VarDeclNode variable = ParseFieldDeclaration(f); if (null == variable) { continue; } classnode.varlist.Add(variable); FunctionDefinitionNode func = ParseFieldAccessor(f); if (null != func) { RegisterFunctionPointer(func.Name, f, null, func.ReturnType); } } PropertyInfo[] properties = type.GetProperties(flags); foreach (var p in properties) { AssociativeNode node = ParseProperty(p); if (null != node) { classnode.varlist.Add(node); } } FFIClassAttributes cattrs = new FFIClassAttributes(type); classnode.ClassAttributes = cattrs; SetTypeAttributes(type, cattrs); return(classnode); }
private static bool isEmpty(CLRModuleType type) { return null == type.Module; }
private ProtoCore.Type[] GetArgumentTypes() { return(ReflectionInfo.GetParameters().Select( pi => CLRModuleType.GetProtoCoreType(pi.Info.ParameterType, Module)).ToArray()); }
public override CodeBlockNode ImportCodeBlock(string typeName, string alias, CodeBlockNode refNode) { Type[] types = GetTypes(typeName); Type exttype = typeof(IExtensionApplication); #if PARALLEL System.Threading.Tasks.Parallel.ForEach(types, type => { //For now there is no support for generic type. if (!type.IsGenericType && type.IsPublic && !exttype.IsAssignableFrom(type) && CLRModuleType.IsBrowsable(type)) { CLRModuleType importedType = CLRModuleType.GetInstance(type, this, alias); } }); #else foreach (var type in types) { //For now there is no support for generic type. if (!type.IsGenericType && type.IsPublic && !exttype.IsAssignableFrom(type) && CLRModuleType.IsBrowsable(type)) { CLRModuleType importedType = CLRModuleType.GetInstance(type, this, alias); Type[] nestedTypes = type.GetNestedTypes(); if (null != nestedTypes && nestedTypes.Length > 0) { foreach (var item in nestedTypes) { importedType = CLRModuleType.GetInstance(item, this, string.Empty); } } } } #endif CodeBlockNode node = new CodeBlockNode(); //Get all the types available on this module. //TODO: need to optimize for performance. List <CLRModuleType> moduleTypes = CLRModuleType.GetTypes((CLRModuleType mtype) => { return(mtype.Module == this); }); foreach (var item in moduleTypes) { node.Body.Add(item.ClassNode); mTypes[item.ClassName] = item; //update Type dictionary. } //Also add all the available empty class nodes. List <CLRModuleType> emptyTypes = CLRModuleType.GetEmptyTypes(); foreach (var item in emptyTypes) { item.EnsureDisposeMethod(this); node.Body.Add(item.ClassNode); } string ffidump = Environment.GetEnvironmentVariable("FFIDUMP"); if (string.Compare(ffidump, "1") == 0) { System.Text.StringBuilder sb = new System.Text.StringBuilder(); foreach (var item in node.Body) { sb.Append(item.ToString()); sb.AppendLine(); } using (System.IO.FileStream fs = new System.IO.FileStream(string.Format("{0}.ds", this.Name), System.IO.FileMode.Create)) { byte[] bytes = System.Text.Encoding.ASCII.GetBytes(sb.ToString()); fs.Write(bytes, 0, bytes.Length); } } return(node); }
private ClassDeclNode ParseSystemType(Type type, string alias) { Validity.Assert(IsBrowsable(type), "Non browsable type is being imported!!"); string classname = alias; if (classname == null | classname == string.Empty) { classname = CLRObjectMarshler.GetTypeName(type); } ProtoCore.AST.AssociativeAST.ClassDeclNode classnode = CreateEmptyClassNode(classname); classnode.ExternLibName = Module.Name; classnode.className = classname; classnode.Name = type.Name; Type baseType = GetBaseType(type); if (baseType != null && !CLRObjectMarshler.IsMarshaledAsNativeType(baseType)) { string baseTypeName = CLRObjectMarshler.GetTypeName(baseType); classnode.superClass = new List <string>(); classnode.superClass.Add(baseTypeName); //Make sure that base class is imported properly. CLRModuleType.GetInstance(baseType, Module, string.Empty); } ConstructorInfo[] ctors = type.GetConstructors(); foreach (var c in ctors) { if (c.IsPublic && !c.IsGenericMethod && IsBrowsable(c)) { ConstructorDefinitionNode node = ParseConstructor(c, type); classnode.funclist.Add(node); RegisterFunctionPointer(node.Name, c, node.ReturnType); } } BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.Static; bool isDerivedClass = classnode.superClass != null; if (isDerivedClass) //has base class { flags |= BindingFlags.DeclaredOnly; //for derived class, parse only class declared methods. } bool isDisposable = typeof(IDisposable).IsAssignableFrom(type); MethodInfo[] methods = type.GetMethods(flags); bool hasDisposeMethod = false; foreach (var m in methods) { if (!IsBrowsable(m)) { continue; } //Don't include overriden methods or generic methods if (m.IsPublic && !m.IsGenericMethod && (m == m.GetBaseDefinition() || (m.GetBaseDefinition().DeclaringType == baseType && baseType == typeof(Object)))) { AssociativeNode node = ParseAndRegisterFunctionPointer(isDisposable, ref hasDisposeMethod, m); classnode.funclist.Add(node); } else if (!hasDisposeMethod && isDisposable && baseType == typeof(Object) && isDisposeMethod(m)) { AssociativeNode node = ParseAndRegisterFunctionPointer(isDisposable, ref hasDisposeMethod, m); classnode.funclist.Add(node); } } if (!hasDisposeMethod && !isDisposable) { AssociativeNode node = ParseAndRegisterFunctionPointer(true, ref hasDisposeMethod, mDisposeMethod); classnode.funclist.Add(node); } FieldInfo[] fields = type.GetFields(); foreach (var f in fields) { if (!IsBrowsable(f)) { continue; } VarDeclNode variable = ParseFieldDeclaration(f); if (null == variable) { continue; } classnode.varlist.Add(variable); FunctionDefinitionNode func = ParseFieldAccessor(f); if (null != func) { RegisterFunctionPointer(func.Name, f, func.ReturnType); } } PropertyInfo[] properties = type.GetProperties(flags); foreach (var p in properties) { AssociativeNode node = ParseProperty(p); if (null != node) { classnode.varlist.Add(node); } } return(classnode); }
private static bool isEmpty(CLRModuleType type) { return(null == type.Module); }