/// <summary> /// Invokes our function by using the Variables we have passed in /// </summary> public override void PerformOperation() { base.PerformOperation(); // Maybe we can improve this - store the array rather than create it every time we invoke the function object[] parameters = new object[OrderedParameterList.Count]; ParameterInfo[] methodParameters = Method.GetParameters(); int index = 0; foreach (Variable var in OrderedParameterList) { object parameter = (var.Value as Reference).Value; if (parameter.GetType() != methodParameters[index].ParameterType) { parameter = CelesteBinder.Bind(parameter, methodParameters[index].ParameterType); } parameters[index] = parameter;//new CelesteObject(var.Value as Reference); index++; } object returnedArgument = Method.Invoke(null, parameters); if (Method.ReturnType.Name != "Void") { // If the method does not return void, push it onto the stack CelesteStack.Push(returnedArgument); } }
// Because our Compiler is static, we have no constructor. // Therefore, to use reflection to pick up the compilable objects we need to call this function whenever we try to compile a script. // Foreach empty dictionary above, we will loop through our Assembly and attempt to populate the dictionary with // the appropriate objects for it. This is done using Attributes and the class hierarchy public static void Init() { // We have already set everything up so just return if (InitComplete) { return; } Cel.LogOutputFilePath = Cel.ScriptDirectoryPath + "\\Log.txt"; foreach (Type type in Assembly.GetExecutingAssembly().GetTypes()) { if (type.IsSubclassOf(typeof(Value)) && type.GetCustomAttribute <CompilableValue>() != null) { MethodInfo isTypeMethod = type.GetMethod("Is" + type.Name); Debug.Assert(isTypeMethod != null); RegisteredValues.Add(isTypeMethod, type); } // Don't add abstract classes - we shouldn't be able to create those anyway! else if (type.IsSubclassOf(typeof(Operator)) && !type.IsAbstract) { MethodInfo isTypeMethod = type.GetMethod("Is" + type.Name); Debug.Assert(isTypeMethod != null, "Is" + type.Name + " static method not implemented"); RegisteredOperators.Add(isTypeMethod, type); } else if (type.IsSubclassOf(typeof(FlowControl)) && !type.IsAbstract) { MethodInfo isTypeMethod = type.GetMethod("Is" + type.Name); Debug.Assert(isTypeMethod != null); RegisteredFlowControls.Add(isTypeMethod, type); } else if (type.IsSubclassOf(typeof(Keyword))) { FieldInfo scriptTokenField = type.GetField("scriptToken", BindingFlags.Static | BindingFlags.NonPublic); Debug.Assert(scriptTokenField != null); // Need to make the script token public rather than internal... will this work? string scriptToken = (string)scriptTokenField.GetValue(type); Debug.Assert(!string.IsNullOrEmpty(scriptToken)); RegisteredKeywords.Add(scriptToken, type); } else if (type.GetCustomAttribute <HasScriptCommands>() != null) { foreach (MethodInfo method in type.GetMethods()) { // Create the Delegate object from the attribute information and store it as a LocalVariable // For now we will do this in the GlobalScope, but this will change // Then it will be picked up and run like any other function if (method.GetCustomAttribute <ScriptCommand>() != null) { ScriptCommand scriptCommandAttr = method.GetCustomAttribute <ScriptCommand>(); Debug.Assert(scriptCommandAttr != null); Delegate celDelegate = new Delegate(scriptCommandAttr.Token, method); CelesteStack.GlobalScope.AddLocalVariable(celDelegate); } } } } CelesteBinder.Init(); InitComplete = true; }