/// <summary> /// Tries to get the <see cref="L20nCore.Objects.Entity"/> instance based on the stored reference (name) /// and will return the evaluation result of the looked up object if possible. /// Returns <c>null</c> in case the object could not be found or the evaluation /// of the looked up object returned <c>null</c> itself. /// </summary> public override L20nObject Eval(LocaleContext ctx, params L20nObject[] argv) { var entity = GetEntity(ctx); if (entity == null) { Logger.Warning("AttributeExpression: couldn't find the entity"); return entity; } var identifier = GetIdentifier(ctx); if (identifier == null) { Logger.Warning("AttributeExpression: couldn't evaluate identifier"); return identifier; } var attribute = entity.GetAttribute(ctx, identifier); if (attribute == null) { Logger.WarningFormat("AttributeExpression: couldn't find an atttribute with key {0}", identifier.Value); return attribute; } // mixed expressions are valid too if (m_PropertyExpression != null) { return m_PropertyExpression.Eval(ctx, attribute); } return attribute.Eval(ctx); }
/// <summary> /// Returns the value that matches the hash key given as the first given parameter. /// </summary> public override L20nObject Eval(LocaleContext ctx, params L20nObject[] argv) { if (m_Items.Count == 0 || argv.Length < 1) { return null; } var first = argv [0].Eval(ctx); Identifier id = first as Identifier; if (id == null) { var str = first as StringOutput; if (str == null) { Logger.Warning("Attributes: first variadic argument couldn't be evaluated as an <Identifier>"); return id; } id = new Identifier(str.Value); } L20nObject obj; if (!m_Items.TryGetValue(id.Value, out obj)) { Logger.WarningFormat("{0} is not a valid <identifier>", id.Value); return null; } return obj; }
/// <summary> /// Evaluates the macro expression body, using the stack-pushed variables, /// defined by the <see cref="L20nCore.Objects.CallExpression"/> calling this macro. /// Returns <c>null</c> in case something went wrong. /// </summary> public override L20nObject Eval(LocaleContext ctx, params L20nObject[] argv) { if (m_Parameters.Length != argv.Length) { Logger.WarningFormat( "<macro> expects {0} parameters, received {1}", m_Parameters.Length, argv.Length); return null; } // Push variables on 'stack', parameters with previously used names will be shadowed. for (int i = 0; i < m_Parameters.Length; ++i) { ctx.PushVariable(m_Parameters [i], argv [i].Eval(ctx)); } // evaluate the actual macro expression var output = m_Expression.Eval(ctx); // Remove them from the 'stack' for (int i = 0; i < m_Parameters.Length; ++i) { ctx.DropVariable(m_Parameters [i]); } return output; }
/// <summary> /// Returns the evaluation of one of the two wrapped up expressions. /// Returns <c>null</c> in case something went wrong. /// </summary> public override L20nObject Eval(LocaleContext ctx, params L20nObject[] argv) { var condition = m_Condition.Eval(ctx) as BooleanValue; if (condition == null) return condition; return condition.Value ? m_IfTrue.Eval(ctx) : m_IfFalse.Eval(ctx); }
public override L20nObject Eval(LocaleContext ctx, params L20nObject[] argv) { var global = ctx.GetGlobal(m_Identifier); if (global == null) { return global; } return global.Eval(ctx, argv); }
/// <summary> /// Evaluates to the result of this binary expression in case both /// wrapped objects can be evaluated to <see cref="L20nCore.Objects.Literal"/> values. /// Returns <c>null</c> in case something went wrong. /// </summary> public override L20nObject Eval(LocaleContext ctx, params L20nObject[] argv) { var first = m_First.Eval(ctx) as Literal; var second = m_Second.Eval(ctx) as Literal; if (first != null && second != null) return Operation(first.Value, second.Value); return null; }
/// <summary> /// Tries to get the external variable based on the stored reference /// and will return the evaluation result of the looked up object if possible. /// Returns <c>null</c> in case the variable could not be found or the evaluation /// of the looked up variable returned <c>null</c>. /// </summary> public override L20nObject Eval(LocaleContext ctx, params L20nObject[] argv) { var variable = ctx.GetVariable(m_Identifier); if (variable == null) { return variable; } return variable.Eval(ctx, argv); }
/// <summary> /// Tries to get the <see cref="L20nCore.Objects.Entity"/> instance based on the stored reference (name) /// and will return the evaluation result of the looked up object if possible. /// Returns <c>null</c> in case the object could not be found or the evaluation /// of the looked up object returned <c>null</c> itself. /// </summary> public override L20nObject Eval(LocaleContext ctx, params L20nObject[] argv) { var entity = ctx.GetEntity(m_Identifier); if (entity == null) { return entity; } return entity.Eval(ctx, argv); }
/// <summary> /// Looks up the Macro in the current or default <see cref="L20nCore.Internal.LocaleContext"/> /// and returns the evaluation of the macro evaluation passing in the values as parameters, /// so that they can be bound to the macro parameters during the actual evaluation. /// Returns <c>null</c> in case the macro couldn't be found, or in case the Macro Evaluation /// itself returned <c>null</c>. /// </summary> public override L20nObject Eval(LocaleContext ctx, params L20nObject[] argv) { var macro = ctx.GetMacro(m_Identifier); if (macro == null) { Logger.WarningFormat("couldn't find macro with name {0}", m_Identifier); return macro; } return macro.Eval(ctx, m_Variables); }
/// <summary> /// Evaluates the given value, with optionally an index given as a first argument, /// in case the value is a <see cref="L20nCore.Objects.HashValue"/>. /// If the index of this attribute is set, and no arguments are given, it will be used as the argument. /// Otherwise we'll simply evaluate the value with the given arguments, which can be none. /// </summary> public override L20nObject Eval(LocaleContext ctx, params L20nObject[] argv) { // if index is given and no extern parameters have been given, // we'll evaluate the index and will use that to evaluate the final output value. // this also assumes that in case the index is given, // that the value is a HashValue rather than a StringValue, // which is something the parser of this type enforces anyhow. if (m_Index != null && argv.Length == 0) { var index = m_Index.Eval(ctx); if (index == null) { Logger.Warning("<KeyValuePair>: index couldn't be evaluated"); return index; } // could be one simple identifier, in which case we can evaluate // the HashValue of this instance given the identifier as a parameter var identifier = index as Identifier; if (identifier != null) { var result = m_Value.Eval(ctx, identifier); if (result == null) { Logger.Warning("<KeyValuePair>: <Identifier>-index got evaluated to null"); return null; } return result.Eval(ctx); } // otherwise it should be a PropertyExpression, // in which case we evaluate that expression given this instance as the first parameter. var property = index as PropertyExpression; if (property != null) { var result = property.Eval(ctx, this); if (result == null) { Logger.Warning("<Entity>: <PropertyExpression>-index got evaluated to null"); return null; } return result.Eval(ctx); } Logger.Warning("couldn't evaluate <KeyValuePair> as index was expexted to be a <property_expression>"); return null; } // in all other cases we simply evaluate the wrapped value, // passing on the given external parameters (e.g. an index) return m_Value.Eval(ctx, argv); }
/// <summary> /// Initializes a new instance of the <see cref="L20nCore.Internal.LocaleContext"/> class. /// </summary> public LocaleContext( Utils.DictionaryRef<string, L20nObject> globals, Dictionary<string, Macro> macros, Dictionary<string, Entity> entities, LocaleContext parent) { m_Globals = globals; m_Macros = new Dictionary<string, Macro>(macros); m_Entities = new Dictionary<string, Entity>(entities); m_Variables = new ShadowStack<L20nObject>(); m_Parent = parent; }
/// <summary> /// Returns a literal value, that consists of an integer value that's the result of /// this unary operation applied on the evaluation of the wrapped L20nObject. /// <c>null</c> gets returned in case something went wrong. /// </summary> public override L20nObject Eval(LocaleContext ctx, params L20nObject[] argv) { var literal = m_Expression.Eval(ctx) as Literal; if (literal == null) { Logger.Warning("couldn't operate on non-valid literal evaluation"); return literal; } m_Output.Value = Operation(literal.Value); return m_Output; }
/// <summary> /// Evaluates to a negated <see cref="L20nCore.Objects.BooleanValue"/> result, /// in case the wrapped <see cref="L20nCore.Objects.L20nObject"/> can be evaluated to /// a <see cref="L20nCore.Objects.BooleanValue"/> itself. /// Returns <c>null</c> otherwise. /// </summary> public override L20nObject Eval(LocaleContext ctx, params L20nObject[] argv) { var expression = m_Expression.Eval(ctx) as BooleanValue; if (expression == null) { Logger.Warning("negation of non-valid boolean evaluation isn't allowed"); return expression; } m_Output.Value = !expression.Value; return m_Output; }
/// <summary> /// Returns the value that matches the hash key given as the first given parameter. /// In case a default value is specified, and no hash key is given or the given hash key /// matches no key registered in the hash table, that value will be returned instead. /// In all other cases, including when something went wrong, <c>null</c> will be returned. /// </summary> public override L20nObject Eval(LocaleContext ctx, params L20nObject[] argv) { if (m_Items.Count == 0) { return null; } if (argv.Length != 1) { if (m_Default == null) { Logger.Warning( "no <identifier> was given and <hash_value> has no default specified"); return null; } return m_Items [m_Default].Eval(ctx); } var first = argv [0].Eval(ctx); Identifier id = first as Identifier; if (id == null) { var str = first as StringOutput; if (str == null) { Logger.Warning("HashValue: first variadic argument couldn't be evaluated as an <Identifier>"); return id; } id = new Identifier(str.Value); } L20nObject obj; if (!m_Items.TryGetValue(id.Value, out obj)) { if (m_Default == null) { Logger.WarningFormat( "{0} is not a valid <identifier>, " + "and this <hash_value> has no default specified", id.Value); return null; } obj = m_Items [m_Default]; } return obj; }
/// <summary> /// Evaluate all the expressions contained in this <see cref="L20nCore.Objects.StringValue"/> /// and use the results of these evaluations as the variables used in the evaluation /// of the format string to compute the final result value as a <see cref="L20nCore.Objects.StringOutput"/>. /// </summary> public override L20nObject Eval(LocaleContext ctx, params L20nObject[] argv) { // Evaluate each expression and store them in the cached list for (int i = 0; i < m_EvaluatedExpressions.Length; ++i) { var e = m_Expressions [i].Eval(ctx); // if one cannot evaluate, we can't know the real final result // and thus we return early if (e == null) { return null; } // Identifiers get evaluated until we get a non-reference value Identifier id; Entity entity; while ((id = e as Identifier) != null) { entity = ctx.GetEntity(id.Value); if (entity != null) e = entity.Eval(ctx); } var primitive = e as Primitive; // in the end we expect to be left with a primitive value, // if not there is something wrong in the global evaluation logic. if (primitive == null) { Logger.WarningFormat("<StringValue>: couldn't evaluate expression #{0}", i); return null; } // we expect a primitive value so that we can turn it into a string var stringOutput = primitive.ToString(ctx); if (stringOutput == null) { Logger.WarningFormat("<StringValue>: couldn't evaluate expression #{0} to <StringOutput>", i); return null; } m_EvaluatedExpressions [i] = stringOutput; } // we update the cached StringOutput value and return it as // the result of this evaluation. m_Output.Value = FormatString(m_Value, m_EvaluatedExpressions); return m_Output; }
/// <summary> /// A helper function to retrieve the identifier, /// which can either be an identifier already or a string value, /// which has to be transformed to an identifier at runtime. /// </summary> private Identifier GetIdentifier(LocaleContext ctx) { var obj = m_Identifier.Eval(ctx); // check if it's a string value var stringOutput = obj as StringOutput; if (stringOutput != null) { return new Identifier(stringOutput.Value); } // otherwise simply return the object `as` an `Identifier` return obj as Identifier; }
/// <summary> /// Evaluates <c>this</c> instance to an Identifier or PropertyExpression. /// Returns <c>null</c> in case something went wrong. /// </summary> public override L20nObject Eval(LocaleContext ctx, params L20nObject[] argv) { // Evaluates each stored index and expects them to be Identifiers // (or strings that can be converted to Identifiers) for (int i = 0; i < m_EvaluatedIndeces.Length; ++i) { var index = m_Indeces [i].Eval(ctx); var identifier = index as Identifier; if (identifier == null) { var output = index as StringOutput; if (output != null) identifier = new Identifier(output.Value); } // if it's not an identifier, we simply return null, // as something went wrong. if (identifier != null) { m_EvaluatedIndeces [i] = identifier; } else { if (index == null) { Internal.Logger.WarningFormat( "index #{0} got evaluated to null, stopping the evaluation of this Index", i); } else { Internal.Logger.WarningFormat( "index #{0} got evaluated to {1}, while expecting {2}," + "stopping the evaluation of this Index", i, index.GetType(), typeof(Identifier)); } return null; } } // we either have a simple Identifier, or we need to generate // a property expressions based on the given Indeces. if (m_EvaluatedIndeces.Length == 1) return m_EvaluatedIndeces [0]; return new PropertyExpression(m_EvaluatedIndeces); }
// this method should never be called as it is... a dummy object public override L20nObject Eval(LocaleContext ctx, params L20nObject[] argv) { throw new NotImplementedException(); }
/// <summary> /// Will return <c>null</c> in case this is a root entity and this instance is private, /// or in case something else went wrong. /// Otherwise it will evaluate the value, optionally using the first given <c>argv</c> parameter, /// which will always result in a <see cref="L20nCore.Objects.StringOutput"/> value in case of success. /// </summary> public override L20nObject Eval(LocaleContext ctx, params L20nObject[] argv) { // if the first given parameter is of L20n type dummy, we'll check if we're not private. // if not we can continue and will simply re-call this method with the // dummy object removed from the given parameters. if (argv.Length != 0 && (argv [0] as Dummy) != null) { if (m_IsPrivate) { Logger.Warning("entity is marked as private and cannot be accessed from C#"); return null; } if (argv.Length > 1) { var arguments = new L20nObject[argv.Length - 1]; for (int i = 0; i < arguments.Length; ++i) arguments [i] = argv [i + 1]; return this.Eval(ctx, arguments); } else { return this.Eval(ctx); } } // if index is given and no extern parameters have been given, // we'll evaluate the index and will use that to evaluate the final output value. // this also assumes that in case the index is given, // that the value is a HashValue rather than a StringValue, // which is something the parser of this type enforces anyhow. if (m_Index != null && argv.Length == 0) { var index = m_Index.Eval(ctx); if (index == null) { Logger.Warning("Entity: index couldn't be evaluated"); return index; } // could be one simple identifier, in which case we can evaluate // the HashValue of this instance given the identifier as a parameter var identifier = index as Identifier; if (identifier != null) { var result = m_Value.Eval(ctx, identifier); if (result == null) { Logger.Warning("<Entity>: <Identifier>-index got evaluated to null"); return null; } return result.Eval(ctx); } // otherwise it should be a PropertyExpression, // in which case we evaluate that expression given this instance as the first parameter. var property = index as PropertyExpression; if (property != null) { var result = property.Eval(ctx, this); if (result == null) { Logger.Warning("<Entity>: <PropertyExpression>-index got evaluated to null"); return null; } return result.Eval(ctx); } Logger.Warning("couldn't evaluate entity as index was expexted to be a <property_expression>"); return null; } // in all other cases we simply evaluate the wrapped value, // passing on the given external parameters (e.g. an index) return m_Value.Eval(ctx, argv); }
/// <summary> /// Returns simply this instance, and no actual evaluation takes place. /// </summary> public override L20nObject Eval(LocaleContext ctx, params L20nObject[] argv) { return this; }
/// <summary> /// Evaluates (this.Eval) this <see cref="L20nCore.Objects.StringValue"/> and returns /// the string value of the computed StringOutput output. /// Returns <c>null</c> in case the call to <c>this.Eval</c> resulted in <c>null</c> as well. /// </summary> public override string ToString(LocaleContext ctx, params L20nObject[] argv) { var str = Eval(ctx) as StringOutput; return str != null ? str.Value : null; }
/// <summary> /// Create an instance of <see cref="L20nCore.Internal.LocaleContext"/> /// using the added objects and imported localization files. /// </summary> public LocaleContext Build(Dictionary<string, L20nObject> globals, LocaleContext parent) { var globalsRef = new Utils.DictionaryRef<string, L20nObject>(globals); return new LocaleContext(globalsRef, m_Macros, m_Entities, parent); }
public L20nObject GetAttribute(LocaleContext ctx, Identifier identifier) { return m_Attributes.Eval(ctx, identifier); }
/// <summary> /// Returns the string value that makes up this /// <see cref="L20nCore.Objects.StringOutput"/> object. /// </summary> public override string ToString(LocaleContext ctx, params L20nObject[] argv) { return m_Value; }
/// <summary> /// Returns a BooleanValue with the result of this expression evaluation, /// using the evaluated results of the 2 wrapped L20nObjects. /// Returns <c>null</c> in case something went wrong. /// </summary> public override L20nObject Eval(LocaleContext ctx, params L20nObject[] argv) { return Operation(ctx); }
// This operation will be overriden by the actual expression classes // This way we can allow the expressions to evaluate the wrapped objects // in a lazy manner, rather than evaluating them prematurely. protected abstract L20nObject Operation(LocaleContext ctx);
/// <summary> /// The <c>Eval</c> methods returns the result of the object and its content /// with optional access to the current <see cref="L20nCore.Internal.LocaleContext"/> /// and optional parameters given by the callee (the object owner, in most cases another L20nObject type). /// </summary> public abstract L20nObject Eval(LocaleContext ctx, params L20nObject[] argv);
/// <summary> /// Evaluates to a BooleanValue containing the result of the /// And Expression applied on the 2 wrapped <see cref="L20nCore.Objects.L20nObject"/> values. /// Returns <c>null</c> in case something went wrong. /// </summary> protected override L20nObject Operation(LocaleContext ctx) { var first = m_First.Eval(ctx) as BooleanValue; if (first == null || !first.Value) return first; return m_Second.Eval(ctx) as BooleanValue; }
/// <summary> /// A help function to get the entity based on the first variable. /// The given identifier is either an Identifier, Variable or Global, /// which will define the action to be taken in order to get and return the Root Entity. /// </summary> private Entity GetEntity(LocaleContext ctx) { // is it an identifier? var identifier = m_Root as Identifier; if (identifier != null) return ctx.GetEntity(identifier.Value); // is it a string? var str = m_Root.Eval(ctx) as StringOutput; if (str != null) return ctx.GetEntity(str.Value); // is it a variable? var variable = m_Root as Variable; if (variable != null) return ctx.GetVariable(variable.Identifier) as Entity; // is it a global? var global = m_Root as Global; if (global != null) return ctx.GetGlobal(global.Identifier) as Entity; return null; }
/// <summary> /// Evaluates this instance and returns the resulting primitive to a string value if possible. /// Returns <c>null</c> in case something went wrong during evaluation or if the evaluation result is /// not a <see cref="L20nCore.Objects.Primitive"/> value type. /// </summary> public override string ToString(LocaleContext ctx, params L20nObject[] argv) { var primitive = Eval(ctx, argv) as Primitive; if (primitive != null) return primitive.ToString(ctx); return null; }