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); } }
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); }
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); }
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); }
/// <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); }