예제 #1
0
        internal static Prototype TranslatePrototype(ScriptProcessor processor, Type t)
        {
            var name = t.Name;
            var customNameAttribute = t.GetCustomAttribute <ScriptPrototypeAttribute>();

            if (!string.IsNullOrWhiteSpace(customNameAttribute?.VariableName))
            {
                name = customNameAttribute.VariableName;
            }

            var prototype = new Prototype(name);

            object typeInstance = null;

            if (!t.IsAbstract)
            {
                typeInstance = Activator.CreateInstance(t);
            }

            var fields = t
                         .GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static)
                         .Where(f => f.GetCustomAttribute <CompilerGeneratedAttribute>() == null)
                         .ToArray();

            foreach (var field in fields)
            {
                var attributes = field.GetCustomAttributes(false);

                foreach (var attr in attributes)
                {
                    if (attr.GetType() == typeof(ScriptVariableAttribute))
                    {
                        var memberAttr = (ScriptMemberAttribute)attr;
                        var identifier = field.Name;
                        if (!string.IsNullOrEmpty(memberAttr.VariableName))
                        {
                            identifier = memberAttr.VariableName;
                        }

                        var fieldContent = field.GetValue(typeInstance);

                        if (fieldContent == null)
                        {
                            prototype.AddMember(processor, new PrototypeMember(identifier, processor.Undefined, field.IsStatic, field.IsInitOnly, false, false));
                        }
                        else
                        {
                            prototype.AddMember(processor, new PrototypeMember(identifier, Translate(processor, fieldContent), field.IsStatic, field.IsInitOnly, false, false));
                        }
                    }
                    else if (attr.GetType() == typeof(ScriptFunctionAttribute))
                    {
                        var memberAttr = (ScriptFunctionAttribute)attr;
                        var identifier = field.Name;
                        if (!string.IsNullOrEmpty(memberAttr.VariableName))
                        {
                            identifier = memberAttr.VariableName;
                        }

                        var fieldContent = field.GetValue(typeInstance);

                        if (fieldContent == null)
                        {
                            if (memberAttr.FunctionType != ScriptFunctionType.Standard)
                            {
                                throw new InvalidOperationException("A member function marked with Indexer Set, Indexer Get or Constructor has to be defined.");
                            }

                            prototype.AddMember(processor, new PrototypeMember(identifier, processor.Undefined, field.IsStatic, field.IsInitOnly, false, false));
                        }
                        else
                        {
                            switch (memberAttr.FunctionType)
                            {
                            case ScriptFunctionType.Standard:
                                prototype.AddMember(processor, new PrototypeMember(identifier, new SFunction(processor, fieldContent.ToString()), field.IsStatic, field.IsInitOnly, false, false));
                                break;

                            case ScriptFunctionType.IndexerGet:
                                prototype.IndexerGetFunction = new SFunction(processor, fieldContent.ToString());
                                break;

                            case ScriptFunctionType.IndexerSet:
                                prototype.IndexerSetFunction = new SFunction(processor, fieldContent.ToString());
                                break;

                            case ScriptFunctionType.Constructor:
                                prototype.Constructor = new PrototypeMember(Prototype.CLASS_METHOD_CTOR, new SFunction(processor, fieldContent.ToString()), false, true, false, false);
                                break;
                            }
                        }
                    }
                }
            }

            var methods = t
                          .GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static)
                          .Where(f => f.GetCustomAttribute <CompilerGeneratedAttribute>() == null)
                          .ToArray();

            foreach (var method in methods)
            {
                var attr = method.GetCustomAttribute <ScriptFunctionAttribute>(false);
                if (attr != null)
                {
                    var identifier = method.Name;
                    if (!string.IsNullOrEmpty(attr.VariableName))
                    {
                        identifier = attr.VariableName;
                    }

                    if (attr.FunctionType == ScriptFunctionType.Getter)
                    {
                        identifier = SProtoObject.PROPERTY_GET_PREFIX + identifier;
                    }
                    if (attr.FunctionType == ScriptFunctionType.Setter)
                    {
                        identifier = SProtoObject.PROPERTY_SET_PREFIX + identifier;
                    }

                    Delegate methodDelegate = null;

                    if (method.GetParameters().Length == 3)
                    {
                        // two parameter means the method is a DotNetBuiltInMethod.
                        methodDelegate = (DotNetBuiltInMethod)Delegate.CreateDelegate(typeof(DotNetBuiltInMethod), method);
                    }
                    else if (method.GetParameters().Length == 4)
                    {
                        // four parameters means that the method is a valid BuiltInMethod.
                        methodDelegate = (BuiltInMethod)Delegate.CreateDelegate(typeof(BuiltInMethod), method);
                    }

                    switch (attr.FunctionType)
                    {
                    case ScriptFunctionType.Standard:
                    case ScriptFunctionType.Getter:
                    case ScriptFunctionType.Setter:
                        prototype.AddMember(processor, new PrototypeMember(identifier, new SFunction(methodDelegate), attr.IsStatic, true, false, false));
                        break;

                    case ScriptFunctionType.IndexerGet:
                        prototype.IndexerGetFunction = new SFunction(methodDelegate);
                        break;

                    case ScriptFunctionType.IndexerSet:
                        prototype.IndexerSetFunction = new SFunction(methodDelegate);
                        break;

                    case ScriptFunctionType.Constructor:
                        prototype.Constructor = new PrototypeMember(Prototype.CLASS_METHOD_CTOR, new SFunction(methodDelegate), false, true, false, false);
                        break;
                    }
                }
            }

            prototype.MappedType = t;

            return(prototype);
        }
예제 #2
0
        /// <summary>
        /// Parses an anonymous object.
        /// </summary>
        internal static SProtoObject Parse(ScriptProcessor processor, string source)
        {
            var prototype = new Prototype(LITERAL_OBJECT);

            source = source.Trim();

            // Format: { member1 : content1, member2 : content2 }

            // Remove "{" and "}":
            source = source.Remove(source.Length - 1, 1).Remove(0, 1).Trim();

            if (source.Length == 0)
            {
                return(prototype.CreateInstance(processor, null, false));
            }

            var     index      = 0;
            var     identifier = "";
            var     content    = "";
            SObject contentObj = null;

            while (index < source.Length)
            {
                var nextSeperatorIndex = source.IndexOf(",", index);
                if (nextSeperatorIndex == -1)
                {
                    nextSeperatorIndex = source.Length;
                }
                else
                {
                    //Let's find the correct ",":

                    nextSeperatorIndex = index;

                    var depth = 0;
                    StringEscapeHelper escaper = new LeftToRightStringEscapeHelper(source, nextSeperatorIndex, true);
                    var foundSeperator         = false;

                    while (!foundSeperator && nextSeperatorIndex < source.Length)
                    {
                        var t = source[nextSeperatorIndex];

                        escaper.CheckStartAt(nextSeperatorIndex);

                        if (!escaper.IsString)
                        {
                            if (t == '{' || t == '[' || t == '(')
                            {
                                depth++;
                            }
                            else if (t == '}' || t == ']' || t == ')')
                            {
                                depth--;
                            }
                            else if (t == ',' && depth == 0)
                            {
                                foundSeperator = true;
                                nextSeperatorIndex--; // it adds one to the index at the end of the while loop, but we need the index where we stopped searching, so we subtract 1 here to accommodate for that.
                            }
                        }

                        nextSeperatorIndex++;
                    }
                }

                var member = source.Substring(index, nextSeperatorIndex - index);

                if (member.Contains(":"))
                {
                    identifier = member.Remove(member.IndexOf(":")).Trim();
                    content    = member.Remove(0, member.IndexOf(":") + 1);

                    contentObj = processor.ExecuteStatement(new ScriptStatement(content));
                }
                else
                {
                    identifier = member.Trim();
                    contentObj = processor.Undefined;
                }

                if (!ScriptProcessor.IsValidIdentifier(identifier))
                {
                    processor.ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_MISSING_VAR_NAME);
                }

                prototype.AddMember(processor, new PrototypeMember(identifier, contentObj));

                index = nextSeperatorIndex + 1;
            }

            return(prototype.CreateInstance(processor, null, false));
        }