private static SObject TranslateExpandoObject(ScriptProcessor processor, ExpandoObject objIn) { var obj = new SProtoObject(); foreach (var member in objIn) { obj.AddMember(member.Key, Translate(processor, member.Value)); } return(obj); }
/// <summary> /// Creates an instance derived from this prototype. /// </summary> internal SProtoObject CreateInstance(ScriptProcessor processor, SObject[] parameters, bool executeCtor) { SProtoObject obj = CreateBaseObject(); obj.IsProtoInstance = true; obj.AddMember(MEMBER_NAME_PROTOTYPE, this); if (typeof(ObjectPrototype) != GetType()) { // If no extends class is explicitly specified, "Object" is assumed. if (Extends == null) { Extends = processor.Context.GetPrototype("Object"); } var superInstance = Extends.CreateInstance(processor, null, true); obj.AddMember(MEMBER_NAME_SUPER, superInstance); } foreach (var member in GetInstanceMembers()) { obj.AddMember(member.Identifier, member.Data); } var indexerGetFunction = GetIndexerGetFunction(); if (indexerGetFunction != null) { obj.IndexerGetFunction = indexerGetFunction; } var indexerSetFunction = GetIndexerSetFunction(); if (indexerSetFunction != null) { obj.IndexerSetFunction = indexerSetFunction; } if (executeCtor) { Constructor?.ToFunction().Call(processor, obj, obj, parameters); } // Lock all readonly members after the constructor call, so they can be set in the constructor: foreach (PrototypeMember member in GetReadOnlyInstanceMembers()) { obj.Members[member.Identifier].IsReadOnly = true; } return(obj); }
private static double GetNumberMember(SProtoObject obj, string member) { var memberObj = SObject.Unbox(obj.Members[member]); if (memberObj is SNumber) { return(((SNumber)memberObj).Value); } else { return(-1); } }
private static string GetStringMember(SProtoObject obj, string member) { var memberObj = SObject.Unbox(obj.Members[member]); if (memberObj is SString) { return(((SString)memberObj).Value); } else { return(""); } }
/// <summary> /// Translates an <see cref="SObject"/> to a specific type. /// </summary> public static object Translate(SProtoObject obj, Type t) { var instance = Activator.CreateInstance(t); var fields = t .GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance) .Where(f => f.GetCustomAttribute <CompilerGeneratedAttribute>() == null) .ToArray(); foreach (var field in fields) { var varAttr = field.GetCustomAttribute <ScriptVariableAttribute>(false); if (varAttr != null) { var identifier = field.Name; if (!string.IsNullOrEmpty(varAttr.VariableName)) { identifier = varAttr.VariableName; } var setValue = SObject.Unbox(obj.Members[identifier]); try { field.SetValue(instance, Translate(setValue)); } catch (Exception) { // This is most likely a type binding issue: Set null if the types don't fit! field.SetValue(instance, null); } } else { var refAttr = field.GetCustomAttribute <ReferenceAttribute>(false); if (refAttr != null) { var identifier = field.Name; if (!string.IsNullOrEmpty(refAttr.VariableName)) { identifier = refAttr.VariableName; } field.SetValue(instance, obj.ReferenceContainer[identifier]); } } } return(instance); }
private static object TranslateDynamic(SProtoObject obj) { var returnObj = new ExpandoObject() as IDictionary <string, object>; foreach (var item in obj.Members) { var memberName = item.Key; // Do not translate back the prototype and super instances: if (memberName != SProtoObject.MemberNamePrototype && memberName != SProtoObject.MemberNameSuper) { var memberContent = SObject.Unbox(item.Value); returnObj.Add(memberName, Translate(memberContent)); } } return(returnObj); }
/// <summary> /// Converts a string expression into a script object. /// </summary> private SObject ToScriptObject(string exp) { exp = exp.Trim(); // This means it's either an indexer or an array if (exp.EndsWith("]")) { if (!(exp.StartsWith("[") && !exp.Remove(0, 1).Contains("["))) // When there's no "[" besides the start, and it starts with [, then it is an array. Otherwise, do real check. { // It is possible that we are having a simple array declaration here. // We check that by looking if we can find a "[" before the expression ends: var depth = 0; var index = exp.Length - 2; var indexerStartIndex = 0; var foundIndexer = false; StringEscapeHelper escaper = new RightToLeftStringEscapeHelper(exp, index); while (index > 0 && !foundIndexer) { var t = exp[index]; escaper.CheckStartAt(index); if (!escaper.IsString) { if (t == ')' || t == '}' || t == ']') { depth++; } else if (t == '(' || t == '{') { depth--; } else if (t == '[') { if (depth == 0) { if (index > 0) { indexerStartIndex = index; foundIndexer = true; } } else { depth--; } } } index--; } if (foundIndexer) { var indexerCode = exp.Substring(indexerStartIndex + 1, exp.Length - indexerStartIndex - 2); var identifier = exp.Remove(indexerStartIndex); var statementResult = ExecuteStatement(new ScriptStatement(indexerCode)); return(ToScriptObject(identifier).GetMember(this, statementResult, true)); } } } // Normal object return procedure: // Negative number: var isNegative = false; if (exp.StartsWith("-")) { exp = exp.Remove(0, 1); isNegative = true; } double dblResult; SObject returnObject; if (exp == SObject.LITERAL_NULL) { returnObject = Null; } else if (exp == SObject.LITERAL_UNDEFINED) { returnObject = Undefined; } else if (exp == SObject.LITERAL_BOOL_FALSE) { returnObject = CreateBool(false); } else if (exp == SObject.LITERAL_BOOL_TRUE) { returnObject = CreateBool(true); } else if (exp == SObject.LITERAL_NAN) { returnObject = CreateNumber(double.NaN); } else if (exp == SObject.LITERAL_THIS) { returnObject = Context.This; } else if (SNumber.TryParse(exp, out dblResult)) { returnObject = CreateNumber(dblResult); } else if (exp.StartsWith("\"") && exp.EndsWith("\"") || exp.StartsWith("\'") && exp.EndsWith("\'")) { returnObject = CreateString(exp.Remove(exp.Length - 1, 1).Remove(0, 1), true, false); } else if (exp.StartsWith("$\"") && exp.EndsWith("\"") || exp.StartsWith("$\'") && exp.EndsWith("\'")) { returnObject = CreateString(exp.Remove(exp.Length - 1, 1).Remove(0, 2), true, true); } else if (exp.StartsWith("@\"") && exp.EndsWith("\"") || exp.StartsWith("@\'") && exp.EndsWith("\'")) { returnObject = CreateString(exp.Remove(exp.Length - 1, 1).Remove(0, 2), false, false); } else if (exp.StartsWith("{") && exp.EndsWith("}")) { returnObject = SProtoObject.Parse(this, exp); } else if (exp.StartsWith("[") && exp.EndsWith("]")) { returnObject = SArray.Parse(this, exp); } else if (exp.StartsWith("function") && Regex.IsMatch(exp, REGEX_FUNCTION)) { returnObject = new SFunction(this, exp); } else if (Context.IsAPIUsing(exp)) { returnObject = Context.GetAPIUsing(exp); } else if (Context.IsVariable(exp)) { returnObject = Context.GetVariable(exp); } else if (Context.This.HasMember(this, exp)) { returnObject = Context.This.GetMember(this, CreateString(exp), false); } else if (Context.IsPrototype(exp)) { returnObject = Context.GetPrototype(exp); } else if (exp.StartsWith("new ")) { returnObject = Context.CreateInstance(exp); } else if (exp.StartsWith(ObjectBuffer.OBJ_PREFIX)) { var strId = exp.Remove(0, ObjectBuffer.OBJ_PREFIX.Length); var id = 0; if (int.TryParse(strId, out id) && ObjectBuffer.HasObject(id)) { returnObject = (SObject)ObjectBuffer.GetObject(id); } else { returnObject = ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_INVALID_TOKEN, exp); } } else { returnObject = ErrorHandler.ThrowError(ErrorType.ReferenceError, ErrorHandler.MESSAGE_REFERENCE_NOT_DEFINED, exp); } if (isNegative) { returnObject = ObjectOperators.NegateNumber(this, returnObject); } return(returnObject); }
private static double GetNumberMember(SProtoObject obj, string member) { var memberNumber = SObject.Unbox(obj.Members[member]) as SNumber; return(memberNumber?.Value ?? -1); }
private static string GetStringMember(SProtoObject obj, string member) { var memberString = SObject.Unbox(obj.Members[member]) as SString; return(memberString != null ? memberString.Value : ""); }