Esempio n. 1
0
        public SkryptProperty ExecuteAccess(SkryptObject Object, Node node, ScopeContext scopeContext)
        {
            if (node.SubNodes.Count == 0)
            {
                return(GetProperty(Object, node.Body));
            }

            SkryptProperty Property = GetProperty(Object, node.SubNodes[0].Body);

            if (node.SubNodes[1].Body == "access")
            {
                return(ExecuteAccess(Property.Value, node.SubNodes[1], scopeContext));
            }
            else
            {
                return(Property);
            }
        }
Esempio n. 2
0
        public static SkryptObject MakeObjectFromClass(Type Class)
        {
            SkryptObject Object = new SkryptObject();

            var Methods = Class.GetMethods().Where((m) => {
                if (m.ReturnType != typeof(SkryptObject))
                {
                    return(false);
                }

                if (m.GetParameters().Count() != 1)
                {
                    return(false);
                }

                if (m.GetParameters()[0].ParameterType != typeof(SkryptObject[]))
                {
                    return(false);
                }

                return(m.IsPublic);
            });

            foreach (MethodInfo M in Methods)
            {
                SharpMethod Method = new SharpMethod();
                Method.method = (SkryptDelegate)Delegate.CreateDelegate(typeof(SkryptDelegate), M);

                Method.Name = M.Name;

                SkryptProperty property = new SkryptProperty {
                    Name          = M.Name,
                    Value         = Method,
                    Accessibility = Access.Public
                };

                Object.Properties.Add(property);
            }

            var Fields = Class.GetFields().Where((f) => {
                if (!f.FieldType.IsSubclassOf(typeof(SkryptObject)))
                {
                    return(false);
                }

                return(f.IsPublic);
            });

            foreach (FieldInfo F in Fields)
            {
                SkryptProperty property = new SkryptProperty {
                    Name          = F.Name,
                    Value         = (SkryptObject)F.GetValue(null),
                    Accessibility = Access.Public
                };

                Object.Properties.Add(property);
            }

            var Classes = Class.GetNestedTypes();

            foreach (TypeInfo C in Classes)
            {
                SkryptObject v;

                v = MakeObjectFromClass(C);

                SkryptProperty property = new SkryptProperty {
                    Name          = C.Name,
                    Value         = v,
                    Accessibility = Access.Public
                };

                Object.Properties.Add(property);
            }

            return(Object);
        }
Esempio n. 3
0
        public SkryptObject ExecuteExpression(Node node, ScopeContext scopeContext)
        {
            Operator op = Operator.AllOperators.Find(o => o.OperationName == node.Body || o.Operation == node.Body);

            if (op != null)
            {
                if (op.OperationName == "return")
                {
                    if (!scopeContext.subContext.InMethod)
                    {
                        engine.throwError("Can't use return operator outside method!", node.SubNodes[0].Token);
                    }

                    SkryptObject result = null;

                    if (node.SubNodes.Count == 1)
                    {
                        result = ExecuteExpression(node.SubNodes[0], scopeContext);
                    }
                    else
                    {
                        result = new Library.Native.System.Void();
                    }

                    scopeContext.subContext.ReturnObject = result;
                    return(result);
                }

                if (op.OperationName == "access")
                {
                    SkryptObject Target = ExecuteExpression(node.SubNodes[1], scopeContext);
                    SkryptObject Result = ExecuteAccess(Target, node.SubNodes[0], scopeContext).Value;
                    return(Result);
                }

                if (op.OperationName == "assign")
                {
                    SkryptObject result = ExecuteExpression(node.SubNodes[1], scopeContext);

                    if (node.SubNodes[0].SubNodes.Count == 0 && node.SubNodes[0].TokenType == "Identifier")
                    {
                        Variable Variable = getVariable(node.SubNodes[0].Body, scopeContext);

                        if (Variable != null)
                        {
                            Variable.Value = result;
                        }
                        else
                        {
                            scopeContext.Variables[node.SubNodes[0].Body] = new Variable {
                                Name  = node.SubNodes[0].Body,
                                Value = result,
                                Scope = scopeContext
                            };
                        }
                    }
                    else if (node.SubNodes[0].Body == "access")
                    {
                        SkryptObject   Target       = ExecuteExpression(node.SubNodes[0].SubNodes[1], scopeContext);
                        SkryptProperty AccessResult = ExecuteAccess(Target, node.SubNodes[0].SubNodes[0], scopeContext);

                        AccessResult.Value = result;
                    }
                    else if (node.SubNodes[0].Body == "Index")
                    {
                        ExecuteIndexSet(result, node.SubNodes[0], scopeContext);
                    }
                    else
                    {
                        engine.throwError("Left hand side needs to be a variable or property!", node.SubNodes[0].Token);
                    }

                    return(result);
                }

                if (op.Members == 2)
                {
                    SkryptObject LeftResult  = ExecuteExpression(node.SubNodes[0], scopeContext);
                    SkryptObject RightResult = ExecuteExpression(node.SubNodes[1], scopeContext);

                    dynamic Left  = Convert.ChangeType(LeftResult, LeftResult.GetType());
                    dynamic Right = Convert.ChangeType(RightResult, RightResult.GetType());

                    Operation OpLeft  = Left.GetOperation(op.OperationName, LeftResult.GetType(), RightResult.GetType(), Left.Operations);
                    Operation OpRight = Right.GetOperation(op.OperationName, LeftResult.GetType(), RightResult.GetType(), Right.Operations);

                    OperationDelegate Operation = null;

                    if (OpLeft != null)
                    {
                        Operation = OpLeft.operation;
                    }
                    else if (OpRight != null)
                    {
                        Operation = OpRight.operation;
                    }
                    else
                    {
                        engine.throwError("No such operation as " + Left.Name + " " + op.Operation + " " + Right.Name, node.SubNodes[0].Token);
                    }

                    return(Operation(new SkryptObject[] { LeftResult, RightResult }));
                }
                else if (op.Members == 1)
                {
                    SkryptObject LeftResult = ExecuteExpression(node.SubNodes[0], scopeContext);

                    dynamic Left = Convert.ChangeType(LeftResult, LeftResult.GetType());

                    Operation OpLeft = Left.GetOperation(op.OperationName, LeftResult.GetType(), null, Left.Operations);

                    OperationDelegate Operation = null;

                    if (OpLeft != null)
                    {
                        Operation = OpLeft.operation;
                    }
                    else
                    {
                        engine.throwError("No such operation as " + Left.Name + " " + op.Operation, node.SubNodes[0].Token);
                    }

                    return(Operation(new SkryptObject[] { LeftResult }));
                }
            }
            else if (node.TokenType == "ArrayLiteral")
            {
                Library.Native.System.Array array = new Library.Native.System.Array();

                for (int i = 0; i < node.SubNodes.Count; i++)
                {
                    Node subNode = node.SubNodes[i];

                    SkryptObject Result = ExecuteExpression(subNode, scopeContext);

                    if (Result.Name == "void")
                    {
                        engine.throwError("Can't add void to array!", node.SubNodes[0].Token);
                    }

                    array.value["" + i] = Result;
                }

                return(array);
            }
            else if (node.SubNodes.Count == 0)
            {
                switch (node.TokenType)
                {
                case "NumericLiteral":
                    return(new Library.Native.System.Numeric(Double.Parse(node.Body)));

                case "StringLiteral":
                    return(new Library.Native.System.String(node.Body));

                case "BooleanLiteral":
                    return(new Library.Native.System.Boolean(node.Body == "true" ? true : false));

                case "NullLiteral":
                    return(new Library.Native.System.Null());
                }
            }
            else if (node.TokenType == "FunctionLiteral")
            {
                UserMethod result = new UserMethod();
                result.Name      = "method";
                result.Signature = node.Body;
                result.BlockNode = node.SubNodes[0];
                result.CallName  = node.Body.Split('_')[0];

                foreach (Node snode in node.SubNodes[1].SubNodes)
                {
                    result.Parameters.Add(snode.Body);
                }

                return(result);
            }

            if (node.TokenType == "Identifier")
            {
                if (engine.Constants.ContainsKey(node.Body))
                {
                    return(engine.Constants[node.Body]);
                }

                Variable foundVariable = getVariable(node.Body, scopeContext);

                if (foundVariable != null)
                {
                    return(foundVariable.Value);
                }
                else
                {
                    engine.throwError("Variable '" + node.Body + "' does not exist in the current context!", node.Token);
                }
            }

            if (node.TokenType == "Index")
            {
                return(ExecuteIndex(node, scopeContext));
            }

            if (node.TokenType == "Call")
            {
                List <SkryptObject> Arguments     = new List <SkryptObject>();
                ScopeContext        methodContext = new ScopeContext {
                    ParentScope = scopeContext
                };

                foreach (Node subNode in node.SubNodes[1].SubNodes)
                {
                    SkryptObject Result = ExecuteExpression(subNode, scopeContext);

                    if (Result.Name == "void")
                    {
                        engine.throwError("Can't pass void into arguments!", node.SubNodes[0].Token);
                    }

                    Arguments.Add(Result);
                }

                SkryptObject Method = ExecuteExpression(node.SubNodes[0].SubNodes[0], scopeContext);

                if (Method.GetType() != typeof(SharpMethod))
                {
                    var Find = Method.Properties.Find((x) => x.Name == "Constructor");

                    if (Find != null)
                    {
                        Method = Find.Value;
                    }
                }

                if (Method.GetType() == typeof(UserMethod))
                {
                    UserMethod method = (UserMethod)Method;

                    for (int i = 0; i < method.Parameters.Count; i++)
                    {
                        string       parName = method.Parameters[i];
                        SkryptObject input;

                        if (i < Arguments.Count)
                        {
                            input = Arguments[i];
                        }
                        else
                        {
                            input = new Library.Native.System.Null();
                        }

                        methodContext.Variables[parName] = new Variable {
                            Name  = parName,
                            Value = input,
                            Scope = methodContext
                        };
                    }

                    SkryptObject MethodResult = method.Execute(engine, Arguments.ToArray(), methodContext);

                    return(MethodResult);
                }
                else if (Method.GetType() == typeof(SharpMethod))
                {
                    SkryptObject MethodResult = ((SharpMethod)Method).Execute(engine, Arguments.ToArray(), methodContext);

                    return(MethodResult);
                }
                else
                {
                    engine.throwError("Cannot call value, as it is not a function!", node.SubNodes[0].SubNodes[0].Token);
                }
            }

            return(null);
        }
Esempio n. 4
0
        public static SkryptObject MakeObjectFromClass(Type type, SkryptEngine engine, SkryptObject parent = null)
        {
            var Object = new SkryptObject {
                Name = type.Name
            };

            if (parent != null)
            {
                Object.Name = parent.Name + "." + Object.Name;
            }

            SkryptObject Instance = (SkryptObject)Activator.CreateInstance(type);

            Instance.Name = type.Name;

            var methods = type.GetMethods().Where(m => {
                if (m.ReturnType != typeof(SkryptObject))
                {
                    return(false);
                }

                if (m.GetParameters().Count() != 3)
                {
                    return(false);
                }

                if (m.GetParameters()[0].ParameterType != typeof(SkryptEngine))
                {
                    return(false);
                }

                if (m.GetParameters()[1].ParameterType != typeof(SkryptObject))
                {
                    return(false);
                }

                if (m.GetParameters()[2].ParameterType != typeof(SkryptObject[]))
                {
                    return(false);
                }

                return(true);
            });

            foreach (var m in methods)
            {
                SkryptDelegate del;
                var            parameters = new List <string>();

                if (m.IsStatic)
                {
                    del = (SkryptDelegate)Delegate.CreateDelegate(typeof(SkryptDelegate), m);
                }
                else
                {
                    del = (SkryptDelegate)Delegate.CreateDelegate(typeof(SkryptDelegate), Instance, m);
                }

                var method = new SharpMethod(del)
                {
                    Name       = m.Name,
                    Parameters = parameters
                };

                var property = new SkryptProperty {
                    Name  = m.Name,
                    Value = method
                };

                if (Attribute.GetCustomAttribute(m, typeof(ConstantAttribute)) != null)
                {
                    property.Modifiers = property.Modifiers | Parsing.Modifier.Const;
                }

                if (m.IsPublic)
                {
                    property.Modifiers = property.Modifiers | Parsing.Modifier.Public;
                }
                else
                {
                    property.Modifiers = property.Modifiers | Parsing.Modifier.Private;
                }

                if (property.IsGetter)
                {
                    property.Name = property.Name.TrimStart('_');
                }

                if (!m.IsStatic)
                {
                    Instance.Properties.Add(property);
                }
                else
                {
                    Object.Properties.Add(property);
                }
            }

            var fields = type.GetFields().Where(f => typeof(SkryptObject).IsAssignableFrom(f.FieldType));

            foreach (var f in fields)
            {
                var property = new SkryptProperty {
                    Name  = f.Name,
                    Value = (SkryptObject)f.GetValue(Instance)
                };

                if (Attribute.GetCustomAttribute(f, typeof(ConstantAttribute)) != null)
                {
                    property.Modifiers = property.Modifiers | Parsing.Modifier.Const;
                }

                if (f.IsPublic)
                {
                    property.Modifiers = property.Modifiers | Parsing.Modifier.Public;
                }
                else
                {
                    property.Modifiers = property.Modifiers | Parsing.Modifier.Private;
                }

                if (!f.IsStatic)
                {
                    Instance?.Properties.Add(property);
                }
                else
                {
                    Object.Properties.Add(property);
                }
            }

            var properties = type.GetProperties().Where(p => typeof(SkryptObject).IsAssignableFrom(p.PropertyType));

            foreach (var p in properties)
            {
                var getter = p.GetGetMethod();

                if (!getter.IsPublic)
                {
                    continue;
                }

                DynamicMethod dm   = new DynamicMethod("GetValue", typeof(SkryptObject), new Type[] { typeof(SkryptObject), typeof(SkryptObject[]) }, typeof(SkryptObject), false);
                ILGenerator   lgen = dm.GetILGenerator();

                lgen.Emit(OpCodes.Ldarg_0);
                lgen.Emit(OpCodes.Call, getter);

                if (getter.ReturnType.GetTypeInfo().IsValueType)
                {
                    lgen.Emit(OpCodes.Box, getter.ReturnType);
                }

                lgen.Emit(OpCodes.Ret);

                var del = dm.CreateDelegate(typeof(SkryptGetDelegate)) as SkryptGetDelegate;

                var method = new GetMethod {
                    Method = del,
                    Name   = p.Name
                };

                var property = new SkryptProperty {
                    Name     = p.Name,
                    Value    = method,
                    IsGetter = true
                };

                if (Attribute.GetCustomAttribute(p, typeof(ConstantAttribute)) != null)
                {
                    property.Modifiers = property.Modifiers | Parsing.Modifier.Const;
                }

                if (getter.IsPublic)
                {
                    property.Modifiers = property.Modifiers | Parsing.Modifier.Public;
                }
                else
                {
                    property.Modifiers = property.Modifiers | Parsing.Modifier.Private;
                }

                Instance?.Properties.Add(property);

                var setter = p.GetSetMethod(false);

                if (setter == null)
                {
                    continue;
                }

                if (!setter.IsPublic)
                {
                    continue;
                }

                dm   = new DynamicMethod("SetValue", typeof(void), new Type[] { typeof(SkryptObject), typeof(SkryptObject) }, typeof(SkryptObject), true);
                lgen = dm.GetILGenerator();

                lgen.Emit(OpCodes.Ldarg_0);
                lgen.Emit(OpCodes.Ldarg_1);

                Type parameterType = setter.GetParameters()[0].ParameterType;

                if (parameterType.GetTypeInfo().IsValueType)
                {
                    lgen.Emit(OpCodes.Unbox_Any, setter.ReturnType);
                }

                lgen.Emit(OpCodes.Call, setter);
                lgen.Emit(OpCodes.Ret);

                var setdel = dm.CreateDelegate(typeof(SkryptSetDelegate)) as SkryptSetDelegate;

                var setMethod = new SetMethod {
                    Method = setdel,
                    Name   = p.Name
                };

                property = new SkryptProperty {
                    Name     = p.Name,
                    Value    = setMethod,
                    IsSetter = true
                };

                if (Attribute.GetCustomAttribute(p, typeof(ConstantAttribute)) != null)
                {
                    property.Modifiers = property.Modifiers | Parsing.Modifier.Const;
                }

                if (setter.IsPublic)
                {
                    property.Modifiers = property.Modifiers | Parsing.Modifier.Public;
                }
                else
                {
                    property.Modifiers = property.Modifiers | Parsing.Modifier.Private;
                }

                Instance?.Properties.Add(property);
            }

            var classes = type.GetNestedTypes();

            foreach (var c in classes)
            {
                SkryptObject v;

                v = MakeObjectFromClass(c, engine, Object);

                var property = new SkryptProperty {
                    Name  = c.Name,
                    Value = v,
                };

                if (Attribute.GetCustomAttribute(c, typeof(ConstantAttribute)) != null)
                {
                    property.Modifiers = property.Modifiers | Parsing.Modifier.Const;
                }

                if (c.IsPublic)
                {
                    property.Modifiers = property.Modifiers | Parsing.Modifier.Private;
                }
                else
                {
                    property.Modifiers = property.Modifiers | Parsing.Modifier.Public;
                }

                if (Attribute.GetCustomAttribute(c, typeof(StaticAttribute)) == null)
                {
                    Instance?.Properties.Add(property);
                }
                else
                {
                    Object.Properties.Add(property);
                }
            }

            var className = type.ToString();

            Instance.Properties.Add(new SkryptProperty {
                Name      = "TypeName",
                Value     = new Native.System.String(className),
                Modifiers = Parsing.Modifier.Const
            });

            Instance.Properties.Add(new SkryptProperty {
                Name      = "Type",
                Value     = Object,
                Modifiers = Parsing.Modifier.Const
            });

            Object.Properties.Add(new SkryptProperty {
                Name      = "TypeName",
                Value     = new Native.System.String(className),
                Modifiers = Parsing.Modifier.Const | Parsing.Modifier.Instance
            });

            engine.GlobalScope.AddType(className, Instance);

            return(Object);
        }
Esempio n. 5
0
        /// <summary>
        ///     Executes a class definition node.
        /// </summary>
        public SkryptObject ExecuteClassDeclaration(ClassNode node, ScopeContext scopeContext)
        {
            string ClassName   = node.Name;
            var    ParentClass = scopeContext.ParentClass;

            if (ParentClass != null)
            {
                ClassName = ParentClass.Name + "." + ClassName;
            }

            // The static object.
            SkryptObject Object = new SkryptObject {
                Name = ClassName,
            };

            // The object base that gets instantiated.
            SkryptType TypeObject = new SkryptType {
                Name = ClassName,
            };

            scopeContext.AddType(ClassName, TypeObject);

            // Give objects a value displaying their type.
            Object.Properties.Add(new SkryptProperty {
                Name      = "TypeName",
                Value     = new Library.Native.System.String(ClassName),
                Modifiers = Parsing.Modifier.Const
            });

            TypeObject.Properties.Add(new SkryptProperty {
                Name      = "TypeName",
                Value     = new Library.Native.System.String(ClassName),
                Modifiers = Parsing.Modifier.Const
            });

            // Give instance object a value pointing to its base type.
            TypeObject.Properties.Add(new SkryptProperty {
                Name      = "Type",
                Value     = Object,
                Modifiers = Parsing.Modifier.Const
            });

            // Execute class body.
            var scope = ExecuteBlock(node.BodyNode, scopeContext, ScopeProperties.InClassDeclaration);

            // Add variables with modifiers to instance and base objects.
            foreach (var v in scope.Variables)
            {
                if (v.Value.Modifiers != Modifier.None)
                {
                    var property = new SkryptProperty {
                        Name      = v.Key,
                        Value     = v.Value.Value,
                        Modifiers = v.Value.Modifiers
                    };

                    if ((v.Value.Modifiers & Modifier.Instance) == 0)
                    {
                        var find = TypeObject.Properties.Find(x => x.Name == v.Key);

                        if (find != null)
                        {
                            find = property;
                        }
                        else
                        {
                            Object.Properties.Add(property);
                        }
                    }
                    else
                    {
                        var find = TypeObject.Properties.Find(x => x.Name == v.Key);

                        if (find != null)
                        {
                            find = property;
                        }
                        else
                        {
                            TypeObject.Properties.Add(property);
                        }
                    }
                }
            }

            // Add variables from inherited classes to objects.
            foreach (var inheritNode in node.InheritNode.Nodes)
            {
                var value = ExecuteExpression(inheritNode, scopeContext);

                var BaseType = GetType(((Library.Native.System.String)value.GetProperty("TypeName")).Value, scopeContext);
                var instance = (SkryptType)Activator.CreateInstance(BaseType.GetType());
                instance.ScopeContext = _engine.CurrentScope;
                instance.Engine       = _engine;
                instance.GetPropertiesFrom(BaseType);

                if (value.GetType() != typeof(SkryptObject) || BaseType.GetType() != typeof(SkryptType))
                {
                    _engine.ThrowError("Can only inherit from Skrypt-based objects");
                }

                foreach (var p in value.Properties)
                {
                    var find = Object.Properties.Find(x => {
                        if (x.IsGetter != p.IsGetter)
                        {
                            return(false);
                        }
                        if (x.IsSetter != p.IsSetter)
                        {
                            return(false);
                        }
                        if (x.Name != p.Name)
                        {
                            return(false);
                        }

                        return(true);
                    });

                    if (find == null)
                    {
                        Object.Properties.Add(new SkryptProperty {
                            Name      = p.Name,
                            Value     = p.Value,
                            Modifiers = p.Modifiers,
                            IsGetter  = p.IsGetter,
                            IsSetter  = p.IsSetter
                        });
                    }
                }

                foreach (var p in instance.Properties)
                {
                    var find = TypeObject.Properties.Find(x => {
                        if (x.IsGetter != p.IsGetter)
                        {
                            return(false);
                        }
                        if (x.IsSetter != p.IsSetter)
                        {
                            return(false);
                        }
                        if (x.Name != p.Name)
                        {
                            return(false);
                        }

                        return(true);
                    });

                    if (find == null)
                    {
                        TypeObject.Properties.Add(new SkryptProperty {
                            Name      = p.Name,
                            Value     = p.Value,
                            Modifiers = p.Modifiers,
                            IsGetter  = p.IsGetter,
                            IsSetter  = p.IsSetter
                        });
                    }
                }
            }

            foreach (var p in Object.Properties)
            {
                SetFunctionOwner(p.Value, Object);
            }

            Object.Name = node.Name;

            return(Object);
        }