示例#1
0
        private ElfClass LoadClass(ClassDef classDef)
        {
            // so far we assume a single global namespace for class names
            var rtimpl = VM.Classes.SingleOrDefault(c => c.Name == classDef.Rtimpl);
            if (rtimpl == null)
            {
                var exception = new ErroneousScriptLoaderException(Script, classDef, ElfExceptionType.ClassRtimplNotFound);
                exception.ToString();
                throw exception;
            }

            var @class = new ElfClass(classDef, classDef.Name, rtimpl);

            var funcs = new Dictionary<String, NativeMethod>();
            foreach (var funcDef in classDef.Funcs)
            {
                var func = LoadNativeFunc(@class, funcDef);
                if (funcs.ContainsKey(func.Name))
                {
                    throw new ErroneousScriptLoaderException(Script, funcDef, ElfExceptionType.DuplicateFuncLoaded);
                }
                else
                {
                    funcs.Add(func.Name, func);
                }
            }

            @class.Methods.AddRange(funcs.Values.Cast<ElfMethod>());
            return @class;
        }
示例#2
0
 protected ElfMethod(AstNode elfNode, ElfClass declaringType, string name, String[] args, bool varargs) 
     : base(elfNode)
 {
     DeclaringType = declaringType;
     Name = name;
     Args = args;
     IsVarargs = varargs;
 }
        public static ElfMethod Resolve(VirtualMachine vm, String name, ElfClass thisClass, params ElfClass[] argClasses)
        {
            var firstArgClass = argClasses.Length == 0 ? new ElfClass(null, "aux", typeof(object)) : argClasses[0];

            Func<ElfMethod, int> isStaticOrCtor = m =>
            {
                if (!(m is ClrMethod)) return 0;
                if (m.DeclaringType != null && m.DeclaringType.Ctors.Contains((ClrMethod)m)) return 1;
                if (((ClrMethod)m).Rtimpl.IsStatic) return 1;
                return 0;
            };

            Func<ElfMethod, bool> argcOk = m =>
            {
                var sigArgs = m.DeclaringType == thisClass ? argClasses.Length : argClasses.Length + isStaticOrCtor(m) - 1;
                return m.IsVarargs ? m.Argc <= sigArgs : m.Argc == sigArgs;
            };

            var methodsOfThis = thisClass.Methods.Where(m => m.Name == name && argcOk(m)).ToArray();
            var ctorsOfName = vm.Classes.Where(c => c.Name == name).Select(c => c.Ctors.Where(m => argcOk(m))).Flatten().ToArray();
            var methodsOfFirstArg = firstArgClass.Methods.Where(m => m.Name == name && argcOk(m)).ToArray();
            var helperMethods = vm.HelperMethods.Where(m => m.Name == name && argcOk(m)).ToArray();

            if (methodsOfThis.Length != 0)
            {
                return methodsOfThis.Single();
            }
            else if (ctorsOfName.Length != 0)
            {
                return ctorsOfName.Single();
            }
            else if (methodsOfFirstArg.Length != 0)
            {
                return methodsOfFirstArg.Single();
            }
            else if (helperMethods.Length != 0)
            {
                return helperMethods.Single();
            }
            else
            {
                return null;
            }
        }
示例#4
0
文件: ElfClass.cs 项目: xeno-by/elf4b
 public ElfClass(AstNode elfNode, String name, ElfClass rtimpl)
     : this(elfNode, name, rtimpl.ClrType)
 {
     Rtimpl = rtimpl;
 }
 public ElfScriptDefinedClassInstance(ElfClass elfClass, Object clrInstance)
 {
     _type = elfClass;
     ClrObject = clrInstance;
 }
示例#6
0
        public void Load()
        {
            try
            {
                var classes = new Dictionary<String, ElfClass>();
                foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()
                    .Where(asm => asm.IsDefined(typeof(ElfDiscoverableAttribute), false)))
                {
                    // n0te. this is useful for debugging so I didn't remove it
//                    var aname = String.Format("{0} at {1}", assembly.FullName, assembly.Location);
//                    Trace.WriteLine("======= asm: " + aname + "=======");
//                    var oldKeys = classes.Keys.ToArray();

                    foreach (var type in assembly.GetTypes())
                    {
                        if (type.IsRtimpl())
                        {
                            if (type.IsOpenGeneric())
                            {
                                throw new UnexpectedLoaderException(String.Format(
                                    "Fatal error loading RTIMPL type '{0}'. Reason: type is an open generic.", type));
                            }

                            // so far we assume a single global namespace for class names
                            var @class = new ElfClass(null, type.RtimplOf(), type);

                            // todo. before release we can add russian-names-only regex validator here
                            if (@class.Name.IsNullOrEmpty())
                            {
                                throw new UnexpectedLoaderException(String.Format(
                                    "Fatal error loading RTIMPL type '{0}'. Reason: Elf class name is null or empty.", type));
                            }

                            if (classes.ContainsKey(@class.Name))
                            {
                                throw new UnexpectedLoaderException(String.Format(
                                    "Fatal error loading RTIMPL type '{0}'. Reason: duplicate Elf class name.", @class.Name));
                            }
                            else
                            {
                                classes.Add(@class.Name, @class);
                            }

                            foreach (var ctor in type.GetConstructors(
                                BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
                                .Where(ctor1 => ctor1.IsRtimpl()))
                            {
                                @class.Ctors.Add(new ClrMethod(null, @class, @class.Name, ctor));
                            }

                            foreach (var method in type.GetMethods(
                                BindingFlags.Instance | BindingFlags.Static | BindingFlags.FlattenHierarchy |
                                BindingFlags.Public | BindingFlags.NonPublic)
                                .Where(method1 => method1.IsRtimpl()))
                            {
                                @class.Methods.Add(new ClrMethod(null, @class, method.RtimplOf(), method));
                            }

                            VM.Classes.Add(@class);
                        }

                        if (type.IsElfSerializable())
                        {
                            var serializableAs = type.ElfSerializableAs();
                            if (serializableAs.IsNullOrEmpty())
                            {
                                throw new UnexpectedLoaderException(String.Format(
                                    "Fatal error registering type '{0}' as serializable. Reason: Type token is null or empty.", type));
                            }

                            if (!type.GetInterfaces().Any(iface => iface == typeof(IElfObject)))
                            {
                                throw new UnexpectedLoaderException(String.Format(
                                    "Fatal error registering type '{0}' as serializable. Reason: Type doesn't implement the IElfObject interface.", type));
                            }

                            var deserializer = type.ElfDeserializer();
                            if (deserializer == null)
                            {
                                throw new UnexpectedLoaderException(String.Format(
                                    "Fatal error registering type '{0}' as serializable. Reason: Type doesn't expose a static Parse method, neither it is convertible from string.", type));
                            }

                            VM.Deserializers.Add(serializableAs, deserializer);
                        }

                        if (type.IsRthelper())
                        {
                            foreach (var ctor in type.GetConstructors(
                                BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
                                .Where(ctor1 => ctor1.IsRtimpl()))
                            {
                                throw new UnexpectedLoaderException(String.Format(
                                    "Fatal error registering type '{0}' as RTHELPER. Reason: Rthelpers cannot define RTIMPL constructors.", type));
                            }

                            foreach (var ctor in type.GetMethods(
                                BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
                                .Where(ctor1 => ctor1.IsRtimpl()))
                            {
                                throw new UnexpectedLoaderException(String.Format(
                                    "Fatal error registering type '{0}' as RTHELPER. Reason: Rthelpers cannot define RTIMPL instance methods.", type));
                            }

                            foreach (var method in type.GetMethods(
                                BindingFlags.Static | BindingFlags.FlattenHierarchy | BindingFlags.Public | BindingFlags.NonPublic)
                                .Where(method1 => method1.IsRtimpl()))
                            {
                                VM.HelperMethods.Add(new ClrMethod(method.RtimplOf(), method));
                            }
                        }
                    }

                    // n0te. this is useful for debugging so I didn't remove it
//                    classes.Keys.Except(oldKeys).ForEach(cls => Trace.WriteLine(cls + " " + classes[cls]));
                }
            }
            catch (Exception e)
            {
                if (e is UnexpectedLoaderException) throw;
                throw new UnexpectedLoaderException(e);
            }
        }
示例#7
0
 public NativeMethod(AstNode elfNode, ElfClass declaringType)
     : base(elfNode, declaringType, ((FuncDef)elfNode).Name, ((FuncDef)elfNode).Args.ToArray(), false) 
 {
     FuncDef = (FuncDef)elfNode;
 }
示例#8
0
 private NativeMethod LoadNativeFunc(ElfClass @class, FuncDef funcDef)
 {
     var native = new NativeMethod(funcDef, @class);
     native.Body = VM.Compiler.Compile(native.FuncDef);
     return native;
 }
示例#9
0
 public ClrMethod(AstNode elfNode, ElfClass declaringType, string name, MethodBase rtimpl)
     : base(elfNode, declaringType, name, rtimpl.GetParameters().Select(pi => pi.Name).ToArray(), rtimpl.IsVarargs()) 
 {
     Rtimpl = rtimpl;
 }