/// <summary> /// Ensures that the parameters for an API method fulfill the type contract. It also converts all script objects to .Net objects. /// </summary> protected static bool EnsureTypeContract(SObject[] parameters, Type[] typeContract, out object[] netObjects) { if (parameters.Length >= typeContract.Length) { netObjects = new object[parameters.Length]; var i = 0; while (i < parameters.Length) { netObjects[i] = ScriptOutAdapter.Translate(parameters[i]); if (i < typeContract.Length && typeContract[i] != netObjects[i].GetType()) return false; i++; } return true; } else { netObjects = null; return false; } }
internal static string AddOperator(ScriptProcessor processor, SObject left, SObject right) { if (left is SString || right is SString) { string strLeft, strRight; if (left is SString) strLeft = ((SString)left).Value; else strLeft = left.ToString(processor).Value; if (right is SString) strRight = ((SString)right).Value; else strRight = right.ToString(processor).Value; return "\"" + strLeft + strRight + "\""; } else { var numbers = GetNumericOperatorParameters(processor, left, right); return SNumber.ConvertToScriptString(numbers.Item1 + numbers.Item2); } }
public static SObject getEntity(ScriptProcessor processor, SObject[] parameters) { object[] netObjects; if (EnsureTypeContract(parameters, new[] { typeof(string) }, out netObjects)) { var entity = new EntityWrapper {id = (string)netObjects[0]}; return ScriptInAdapter.Translate(processor, entity); } return ScriptInAdapter.GetUndefined(processor); }
/// <summary> /// Translates an <see cref="SObject"/> to a dynamic type. /// </summary> public static object Translate(SObject obj) { // todo: C# 7: put a swtich statement type match instead of aweful if case blocks. if (obj is SBool) { return ((SBool)obj).Value; } else if (obj is SString) { return ((SString)obj).Value; } else if (obj is SNumber) { return TranslateNumber((SNumber)obj); } else if (obj is SArray) { return TranslateArray((SArray)obj); } else if (obj is SNull) { return null; } else if (obj is SUndefined) { return obj; } else if (obj is SFunction) { return TranslateFunction((SFunction)obj); } else if (obj is SError) { return TranslateError((SError)obj); } else if (obj is SUndefined) { return NetUndefined.Instance; } else if ((obj as SProtoObject)?.Prototype?.MappedType != null) { return Translate((SProtoObject)obj, ((SProtoObject)obj).Prototype.MappedType); } else if (obj is SProtoObject) { return TranslateDynamic((SProtoObject)obj); } else { return obj.ToScriptSource(); } }
internal override void SetMember(ScriptProcessor processor, SObject accessor, bool isIndexer, SObject value) { if (processor.Context.HasCallback(CallbackType.SetMember)) { var callback = (DSetMember)processor.Context.GetCallback(CallbackType.SetMember); var task = Task.Factory.StartNew(() => callback(processor, ModuleName, accessor, isIndexer, value)); task.Wait(); } else { processor.ErrorHandler.ThrowError(ErrorType.APIError, ErrorHandler.MESSAGE_API_NOT_SUPPORTED); } }
public static SObject Eval(ScriptProcessor processor, SObject instance, SObject This, SObject[] parameters) { if (parameters.Length == 0) return processor.Undefined; string code; if (parameters[0] is SString) code = ((SString)parameters[0]).Value; else code = parameters[0].ToString(processor).Value; var evalProcessor = new ScriptProcessor(processor.Context); return evalProcessor.Run(code); }
public static SObject ToComplex(ScriptProcessor processor, SObject instance, SObject This, SObject[] parameters) { if (parameters.Length == 0) return processor.Undefined; if (parameters[0] is SString) return processor.Context.CreateInstance("String", new SObject[] { parameters[0] }); else if (parameters[0] is SNumber) return processor.Context.CreateInstance("Number", new SObject[] { parameters[0] }); else if (parameters[0] is SBool) return processor.Context.CreateInstance("Boolean", new SObject[] { parameters[0] }); else return parameters[0]; // returns the input object, if no conversion was conducted. }
public static SObject load(ScriptProcessor processor, SObject[] parameters) { object[] netObjects; if (EnsureTypeContract(parameters, new[] { typeof(string), typeof(Vector3Wrapper) }, out netObjects)) { var screen = (OverworldScreen)GameProvider.GameInstance.GetService<ScreenManager>().CurrentScreen; var position = netObjects[1] as Vector3Wrapper; if (position != null) screen.ActiveWorld.LoadMap(netObjects[0] as string, position.X, position.Y, position.Z); } return ScriptInAdapter.GetUndefined(processor); }
public static SObject NameOf(ScriptProcessor processor, SObject instance, SObject This, SObject[] parameters) { if (parameters.Length == 0) return processor.Undefined; if (parameters[0] is SProtoObject) { var protoObj = (SProtoObject)parameters[0]; return processor.CreateString(protoObj.IsProtoInstance ? protoObj.Prototype.Name : protoObj.TypeOf()); } else { return processor.CreateString(parameters[0].TypeOf()); } }
private static Tuple<double, double> GetNumericOperatorParameters(ScriptProcessor processor, SObject left, SObject right) { double numLeft, numRight; if (left is SNumber) numLeft = ((SNumber)left).Value; else numLeft = left.ToNumber(processor).Value; if (right is SNumber) numRight = ((SNumber)right).Value; else numRight = right.ToNumber(processor).Value; return new Tuple<double, double>(numLeft, numRight); }
private static SObject ExecuteMethod(ScriptProcessor processor, string className, string methodName, SObject[] parameters) { if (_apiClasses.ContainsKey(className)) { var method = _apiClasses[className].FirstOrDefault(m => m.Name == methodName); if (method != null) { var result = method.Invoke(null, new object[] { processor, parameters }); return (SObject)result; } } // fallback, in case no class/method was found: return ScriptInAdapter.GetUndefined(processor); }
private static Tuple<bool, bool> GetBooleanicOperatorParameters(ScriptProcessor processor, SObject left, SObject right) { bool boolLeft, boolRight; if (left is SBool) boolLeft = ((SBool)left).Value; else boolLeft = left.ToBool(processor).Value; if (right is SBool) boolRight = ((SBool)right).Value; else boolRight = right.ToBool(processor).Value; return new Tuple<bool, bool>(boolLeft, boolRight); }
internal override SObject ExecuteMethod(ScriptProcessor processor, string methodName, SObject caller, SObject This, SObject[] parameters) { if (processor.Context.HasCallback(CallbackType.ExecuteMethod)) { var callback = (DExecuteMethod)processor.Context.GetCallback(CallbackType.ExecuteMethod); var task = Task<SObject>.Factory.StartNew(() => callback(processor, ModuleName, methodName, parameters)); task.Wait(); return task.Result; } else { processor.ErrorHandler.ThrowError(ErrorType.APIError, ErrorHandler.MESSAGE_API_NOT_SUPPORTED); return processor.Undefined; } }
internal override SObject GetMember(ScriptProcessor processor, SObject accessor, bool isIndexer) { if (processor.Context.HasCallback(CallbackType.GetMember)) { var callback = (DGetMember)processor.Context.GetCallback(CallbackType.GetMember); var task = Task<SObject>.Factory.StartNew(() => callback(processor, ModuleName, accessor, isIndexer)); task.Wait(); return task.Result; } else { processor.ErrorHandler.ThrowError(ErrorType.APIError, ErrorHandler.MESSAGE_API_NOT_SUPPORTED); return processor.Undefined; } }
internal override SObject GetMember(ScriptProcessor processor, SObject accessor, bool isIndexer) { if (isIndexer && accessor.TypeOf() == LITERAL_TYPE_NUMBER) { if (Prototype.GetIndexerGetFunction() != IndexerGetFunction) IndexerGetFunction = Prototype.GetIndexerGetFunction(); if (IndexerGetFunction != null) { return IndexerGetFunction.Call(processor, this, this, new SObject[] { accessor }); } else { return processor.Undefined; } } string memberName; if (accessor is SString) memberName = ((SString)accessor).Value; else memberName = accessor.ToString(processor).Value; if (Members.ContainsKey(PROPERTY_GET_PREFIX + memberName)) // getter property { return ((SFunction)Members[PROPERTY_GET_PREFIX + memberName].Data).Call(processor, this, this, new SObject[] { }); } else if (Members.ContainsKey(memberName)) { return Members[memberName]; } else if (Prototype != null && Prototype.HasMember(processor, memberName)) { return Prototype.GetMember(processor, accessor, isIndexer); } else if (SuperClass != null) { return SuperClass.GetMember(processor, accessor, isIndexer); } return processor.Undefined; }
public static SObject show(ScriptProcessor processor, SObject[] parameters) { object[] netObjects; if (EnsureTypeContract(parameters, new[] { typeof(string) }, out netObjects)) { var text = (string)netObjects[0]; var screen = (OverworldScreen)GameProvider.GameInstance.GetService<ScreenManager>().CurrentScreen; var uiElement = new MessageOverworldUIElement(text); screen.AddUiElement(uiElement); uiElement.IsActive = true; BlockThreadUntilCondition(() => !uiElement.IsActive); screen.RemoveUiElement(uiElement); } return ScriptInAdapter.GetUndefined(processor); }
public static bool Ensure(SObject[] parameters, Type[] typeContract) { if (parameters.Length >= typeContract.Length) { var i = 0; while (i < parameters.Length) { if (i < typeContract.Length && typeContract[i] != SObject.Unbox(parameters[i]).GetType()) return false; i++; } return true; } else { return false; } }
internal override SObject ExecuteMethod(ScriptProcessor processor, string methodName, SObject caller, SObject This, SObject[] parameters) { return(Call(processor, caller, This, parameters)); }
public static SObject TypeOf(ScriptProcessor processor, SObject instance, SObject This, SObject[] parameters) => parameters.Length == 0 ? processor.Undefined : processor.CreateString(parameters[0].TypeOf());
public static SObject SizeOf(ScriptProcessor processor, SObject instance, SObject This, SObject[] parameters) => parameters.Length == 0 ? processor.Undefined : processor.CreateNumber(parameters[0].SizeOf());
public static SObject DoSync(ScriptProcessor processor, SObject instance, SObject This, SObject[] parameters) { string[] tasks = processor.Context.Parent.AsyncTasks.ToArray(); if (parameters.Length >= 1) { var param = SObject.Unbox(parameters[0]); if (param is SString) tasks = new[] { (param as SString).Value }; else if (param is SArray) { tasks = (param as SArray).ArrayMembers.Select(m => m.ToString(processor).Value).ToArray(); } } Console.WriteLine($"Sync tasks: ({string.Join(",", tasks)})"); SpinWait.SpinUntil(() => tasks.All(t => !processor.Context.Parent.AsyncTasks.Contains(t))); return processor.Undefined; }
public static SObject IsFinite(ScriptProcessor processor, SObject instance, SObject This, SObject[] parameters) { if (parameters.Length == 0) return processor.Undefined; double dbl; if (parameters[0] is SNumber) dbl = ((SNumber)parameters[0]).Value; else dbl = parameters[0].ToNumber(processor).Value; return processor.CreateBool(!(double.IsNaN(dbl) || double.IsInfinity(dbl))); }
/// <summary> /// Adds a variable to the context. /// </summary> internal void AddVariable(string identifier, SObject data) { AddVariable(new SVariable(identifier, data)); }
public static SObject ToPrimitive(ScriptProcessor processor, SObject instance, SObject This, SObject[] parameters) { if (parameters.Length == 0) return processor.Undefined; if (parameters[0] is SString) return processor.CreateString(((SString)parameters[0]).Value); else if (parameters[0] is SNumber) return processor.CreateNumber(((SNumber)parameters[0]).Value); else if (parameters[0] is SBool) return processor.CreateBool(((SBool)parameters[0]).Value); else return parameters[0]; // returns the input object, if no conversion was conducted. }
/// <summary> /// Throws an error with the given error object. /// </summary> public SObject ThrowError(SObject errorObject) { ErrorObject = errorObject; throw new ScriptException(ErrorObject); }
internal void Clean() { _errorObject = null; }
/// <summary> /// Creates an instance of the given prototype. /// </summary> internal SObject CreateInstance(Prototype prototype, SObject[] parameters) { if (!prototype.IsAbstract) return prototype.CreateInstance(_processor, parameters, true); else return _processor.ErrorHandler.ThrowError(ErrorType.TypeError, ErrorHandler.MESSAGE_TYPE_ABSTRACT_NO_INSTANCE); }
private SObject InvokeMethod(SObject owner, string methodName) { var exp = methodName; var index = exp.Length - 1; var argumentStartIndex = -1; var This = owner; if (exp.EndsWith("()")) { argumentStartIndex = exp.Length - 2; index = argumentStartIndex - 1; } else { var depth = 0; var foundArguments = false; StringEscapeHelper escaper = new RightToLeftStringEscapeHelper(exp, index); while (index > 0 && !foundArguments) { var t = exp[index]; escaper.CheckStartAt(index); if (!escaper.IsString) { if (t == ')' || t == '}' || t == ']') { depth++; } else if (t == '(' || t == '{' || t == '[') { depth--; } if (depth == 0) { if (index > 0) { foundArguments = true; argumentStartIndex = index; } } } index--; } } methodName = exp.Remove(argumentStartIndex); var argumentCode = exp.Remove(0, argumentStartIndex + 1); argumentCode = argumentCode.Remove(argumentCode.Length - 1, 1).Trim(); var parameters = ParseParameters(argumentCode); if (methodName == CALL_LITERAL && owner is SFunction) { This = Context.This; } // If it has an indexer, parse it again: if (index > 0 && exp[index] == ']') { var member = InvokeMemberOrMethod(owner, methodName); if ((member as SVariable)?.Data is SFunction) { return owner.ExecuteMethod(this, ((SVariable)member).Identifier, owner, This, parameters); } else { return ErrorHandler.ThrowError(ErrorType.TypeError, ErrorHandler.MESSAGE_TYPE_NOT_A_FUNCTION, methodName); } } else { return owner.ExecuteMethod(this, methodName, owner, This, parameters); } }
/// <summary> /// Adds a variable to the context and sets the readonly property. /// </summary> internal void AddVariable(string identifier, SObject data, bool isReadOnly) { AddVariable(new SVariable(identifier, data, isReadOnly)); }
/// <summary> /// Creates an instance with the given prototype name. /// </summary> internal SObject CreateInstance(string prototypeName, SObject[] parameters) { return CreateInstance(GetPrototype(prototypeName), parameters); }
internal SArray CreateArray(SObject[] elements) { // the array prototype constructor needs the first element // in the params list to be the desired length of the array: var destElements = new SObject[elements.Length + 1]; Array.Copy(elements, 0, destElements, 1, elements.Length); destElements[0] = CreateNumber(elements.Length); return Context.CreateInstance("Array", destElements) as SArray; }