/// <summary> /// Loads the arguments supplied into the runtime. /// </summary> /// <param name="args">The metadata of the arguments.</param> /// <param name="argValues">The argument values as strings</param> public RunResult LoadArguments(List <ArgAttribute> args, List <string> argValues) { var errors = new List <ScriptError>(); var start = DateTime.Now; for (var ndx = 0; ndx < args.Count; ndx++) { var arg = args[ndx]; var argVal = argValues[ndx]; try { var langType = LangTypeHelper.ConvertToLangTypeFromLangTypeName(arg.Type); var langValueText = argVal; if (string.IsNullOrEmpty(argVal) && !arg.Required && arg.DefaultValue != null) { langValueText = Convert.ToString(arg.DefaultValue); } var langValue = LangTypeHelper.ConvertToLangValue(langType, langValueText); this.Context.Memory.SetValue(arg.Name, langValue, false); this.Context.Symbols.DefineVariable(arg.Name, langType); } catch (Exception) { var error = new ScriptError(); error.Message = "Unable to create variable : " + arg.Name + " with value : " + argVal; errors.Add(error); throw; } } var end = DateTime.Now; var result = new RunResult(start, end, errors.Count == 0, errors); return(result); }
/// <summary> /// Creates new instance of the type. /// </summary> /// <returns></returns> public override object DoEvaluate() { object[] constructorArgs = null; if (ParamListExpressions != null && ParamListExpressions.Count > 0) { ParamList = new List <object>(); ParamHelper.ResolveNonNamedParameters(ParamListExpressions, ParamList); constructorArgs = ParamList.ToArray(); } // CASE 1: Built in basic system types ( string, date, time, etc ) if (LTypesLookup.IsBasicTypeShortName(this.TypeName)) { // TODO: Move this check to Semacts later var langType = LTypesLookup.GetLType(this.TypeName); var methods = this.Ctx.Methods.Get(langType); var canCreate = methods.CanCreateFromArgs(constructorArgs); if (!canCreate) { throw BuildRunTimeException("Can not create " + this.TypeName + " from parameters"); } // Allow built in type methods to create it. var result = methods.CreateFromArgs(constructorArgs); return(result); } // CASE 2: Custom types e.g. custom classes. var hostLangArgs = LangTypeHelper.ConvertToArrayOfHostLangValues(constructorArgs); var instance = Ctx.Types.Create(this.TypeName, hostLangArgs); return(new LClass(instance)); }
/// <summary> /// Called by the framework after the parse method is called /// </summary> /// <param name="node">The node returned by this implementations Parse method</param> public void OnParseComplete(AstNode node) { var stmt = node as AssignExpr; if (stmt._declarations.IsNullOrEmpty()) { return; } foreach (var decl in stmt._declarations) { var exp = decl.Item1; if (exp is VariableExpr) { var varExp = exp as VariableExpr; var valExp = decl.Item2; var name = varExp.Name; bool registeredTypeVar = false; if (valExp is NewExpr) { var newExp = valExp as NewExpr; if (this.Ctx.Types.Contains(newExp.TypeName)) { var type = this.Ctx.Types.Get(newExp.TypeName); var ltype = LangTypeHelper.ConvertToLangTypeClass(type); this.Ctx.Symbols.DefineVariable(name, ltype); registeredTypeVar = true; } } if (!registeredTypeVar) { this.Ctx.Symbols.DefineVariable(name, LTypes.Object); } } } }
/// <summary> /// Creates new instance of the type. /// </summary> /// <returns></returns> public object VisitNew(NewExpr expr) { object[] constructorArgs = null; var paramListExprs = expr.ParamListExpressions; if (paramListExprs != null && paramListExprs.Count > 0) { expr.ParamList = new List <object>(); ParamHelper.ResolveNonNamedParameters(paramListExprs, expr.ParamList, this); constructorArgs = expr.ParamList.ToArray(); } // CASE 1: Built in basic system types ( string, date, time, etc ) if (LTypesLookup.IsBasicTypeShortName(expr.TypeName)) { // TODO: Move this check to Semacts later var langType = LTypesLookup.GetLType(expr.TypeName); var methods = this.Ctx.Methods.Get(langType); var canCreate = methods.CanCreateFromArgs(constructorArgs); if (!canCreate) { throw ExceptionHelper.BuildRunTimeException(expr, "Can not create " + expr.TypeName + " from parameters"); } // Allow built in type methods to create it. var result = methods.CreateFromArgs(constructorArgs); return(result); } // CASE 2: Custom types e.g. custom classes. var hostLangArgs = LangTypeHelper.ConvertToArrayOfHostLangValues(constructorArgs); var instance = this.Ctx.Types.Create(expr.TypeName, hostLangArgs); var obj = LangTypeHelper.ConvertToLangClass(instance); return(obj); }
/// <summary> /// Evaluates a math expression of 2 time spans. /// </summary> /// <param name="node">The AST node the evaluation is a part of.</param> /// <param name="lhs">The time on the left hand side</param> /// <param name="rhs">The time on the right hand side</param> /// <param name="op">The math operator.</param> /// <returns></returns> public static LBool CompareDays(AstNode node, LObject lhs, LObject rhs, Operator op) { var left = LangTypeHelper.ConverToLangDayOfWeekNumber(lhs); var right = LangTypeHelper.ConverToLangDayOfWeekNumber(rhs); var res = CompareNumbers(node, left, right, op); return(res); }
/// <summary> /// Execute /// </summary> public object VisitTryCatch(TryCatchExpr expr) { var tryScopePopped = false; var catchScopePopped = false; try { this.Ctx.Memory.Push(); LangHelper.Evaluate(expr.Statements, expr, this); this.Ctx.Memory.Pop(); tryScopePopped = true; } // Force the langlimit excpetion to propegate // do not allow to flow through to the catch all "Exception ex". catch (LangLimitException) { throw; } catch (LangFailException) { throw; } catch (Exception ex) { this.Ctx.Limits.CheckExceptions(expr); // Pop the try scope. if (!tryScopePopped) { this.Ctx.Memory.Pop(); } // Push the scope in the catch block this.Ctx.Memory.Push(); var lException = LangTypeHelper.ConvertToLangClass(LError.FromException(ex)); this.Ctx.Memory.SetValue(expr.ErrorName, lException); // Run statements in catch block. if (expr.Catch != null && expr.Catch.Statements.Count > 0) { LangHelper.Evaluate(expr.Catch.Statements, expr.Catch, this); } // Pop the catch scope. this.Ctx.Memory.Pop(); catchScopePopped = true; } finally { // Pop the catch scope in case there was an error. if (!catchScopePopped) { this.Ctx.Memory.Remove(expr.ErrorName); } } return(LObjects.Null); }
/// <summary> /// Call a fluent script function from c#. /// </summary> /// <param name="functionName">The name of the function to call</param> /// <param name="convertApplicableTypes">Whether or not to convert applicable c# types to fluentscript types, eg. ints and longs to double, List(object) to LArrayType and Dictionary(string, object) to LMapType</param> /// <param name="args"></param> public object Call(string functionName, bool convertApplicableTypes, params object[] args) { var argsList = args.ToList <object>(); if (convertApplicableTypes) { LangTypeHelper.ConvertToLangTypeValues(argsList); } var result = _context.Functions.CallByName(functionName, null, argsList, false); return(result); }
/// <summary> /// Evaluate value. /// </summary> /// <returns></returns> public override object DoEvaluate() { // 1. Null if (this.Value == LObjects.Null) { return(this.Value); } // 2. Actual value. var ltype = LangTypeHelper.ConvertToLangValue(this.Value); return(ltype); }
/// <summary> /// Adds new elements to the end of an array, and returns the new length /// </summary> /// <param name="target">The target list to apply this method on.</param> /// <param name="elements">The elements to add</param> /// <returns>The new length</returns> public int Push(LObject target, params object[] elements) { if (elements == null || elements.Length == 0) { return(0); } // Add var list = target.GetValue() as IList; foreach (object elem in elements) { var langType = LangTypeHelper.ConvertToLangValue(elem); list.Add(langType); } return(list.Count); }
/// <summary> /// Evaluate a constant. /// </summary> /// <param name="val"></param> /// <returns></returns> public object VisitConstant(ConstantExpr expr) { var val = expr.Value; // 1. Null if (val == LObjects.Null) { return(val); } if (val is LObject) { return(val); } // 2. Actual value. var ltype = LangTypeHelper.ConvertToLangValue(val); return(ltype); }
/// <summary> /// Creates functionmetadata object with the supplied inputs. /// </summary> /// <param name="memberType">What type of member e.g. property,function.</param> /// <param name="name">The name of the function</param> /// <param name="implementationMethod">The method that implements the funcion in this host language.</param> /// <param name="returnType">The return values type</param> /// <param name="description">Description of the function.</param> /// <returns></returns> private FunctionMetaData AddMethodInfo(MemberTypes memberType, string name, string implementationMethod, Type returnType, string description) { var funcdef = new FunctionMetaData(name, null); funcdef.Doc = new Docs.DocTags(); // Todo: funcdef.ReturnType = LangTypeHelper.ConvertToLangType(returnType); funcdef.Doc.Summary = description; var mappedMethod = new MappedMethod(); mappedMethod.DataTypeMethod = name; mappedMethod.HostLanguageMethod = implementationMethod; mappedMethod.FuncDef = funcdef; _methodMap[name] = mappedMethod; _allMembersMap[name] = memberType; return(funcdef); }
/// <summary> /// Adds new elements to the end of an array, and returns the new length /// </summary> /// <param name="target">The target list to apply this method on.</param> /// <param name="elements">The elements to add</param> /// <returns>The new length</returns> public int Push(LObject target, params object[] elements) { if (elements == null || elements.Length == 0) { return(0); } // Add var list = target.GetValue() as IList; if (list == null) { return(0); } foreach (object elem in elements) { if (list.GetType().IsGenericType) { var gt = list.GetType().GetGenericArguments()[0]; if (gt != null && gt.FullName.StartsWith("ComLib.Lang")) { var langVal = LangTypeHelper.ConvertToLangValue(elem); list.Add(langVal); } else { list.Add(elem); } } else { var langType = LangTypeHelper.ConvertToLangValue(elem); list.Add(langType); } } return(list.Count); }
/// <summary> /// Sorts expression /// </summary> /// <returns></returns> public override Expr Parse(object context) { var constExp = context as ConstantExpr; var ctx = _parser.Context; var t = _tokenIt.Advance(); var lobj = (LObject)constExp.Value; // Validate. if (lobj.Type != LTypes.Number) { throw _tokenIt.BuildSyntaxException("number required when using units : " + t.Token.Text, t); } var lval = ((LNumber)lobj).Value; var result = ctx.Units.ConvertToUnits(lval, t.Token.Text); var lclass = LangTypeHelper.ConvertToLangUnit(result); var finalExp = Exprs.Const(lclass, t); // Move past the plugin. _tokenIt.Advance(); return(finalExp); }
/// <summary> /// Evaluate the result of indexing an object e.g. users[0] or users["admins"] /// </summary> /// <param name="regmethods"></param> /// <param name="node"></param> /// <param name="target"></param> /// <param name="ndxObj"></param> /// <returns></returns> public static LObject AccessIndex(RegisteredMethods regmethods, AstNode node, LObject target, LObject ndxObj) { object result = LObjects.Null; // Case 1: Array access users[0]; if (target.Type == LTypes.Array || target.Type.TypeVal == LTypes.Table.TypeVal) { var ndx = ((LNumber)ndxObj).Value; var isArray = target.Type == LTypes.Array; var methods = isArray ? regmethods.Get(LTypes.Array) : regmethods.Get(LTypes.Table); // TODO: Make this generic. var length = Convert.ToInt32(methods.ExecuteMethod(target, "length", null)); if (ndx >= length) { throw ExceptionHelper.BuildRunTimeException(node, "Index out of bounds : '" + ndx + "'"); } result = methods.GetByNumericIndex(target, (int)ndx); } // Case 2: Map access. users["kishore"]; else if (target.Type == LTypes.Map) { var memberName = ((LString)ndxObj).Value; var methods = regmethods.Get(LTypes.Map); if (!methods.HasProperty(target, memberName)) { throw ExceptionHelper.BuildRunTimeException(node, "Property does not exist : '" + memberName + "'"); } result = methods.GetByStringMember(target, memberName); } // Conver to lang type. if (result != LObjects.Null && !(result is LObject)) { result = LangTypeHelper.ConvertToLangValue(result); } return((LObject)result); }
/// <summary> /// Called by the framework after the parse method is called /// </summary> /// <param name="node">The node returned by this implementations Parse method</param> public void OnParseAssignComplete(Expr expr) { var stmt = expr as AssignMultiExpr; if (stmt.Assignments == null || stmt.Assignments.Count == 0) { return; } foreach (var assignment in stmt.Assignments) { var exp = assignment.VarExp; if (exp.IsNodeType(NodeTypes.SysVariable)) { var varExp = exp as VariableExpr; var valExp = assignment.ValueExp; var name = varExp.Name; var registeredTypeVar = false; var ctx = this._parser.Context; if (valExp != null && valExp.IsNodeType(NodeTypes.SysNew)) { var newExp = valExp as NewExpr; if (ctx.Types.Contains(newExp.TypeName)) { var type = ctx.Types.Get(newExp.TypeName); var ltype = LangTypeHelper.ConvertToLangTypeClass(type); ctx.Symbols.DefineVariable(name, ltype); registeredTypeVar = true; } } if (!registeredTypeVar) { ctx.Symbols.DefineVariable(name, LTypes.Object); } } } }
/// <summary> /// Evaluates a math expression of 2 units. /// </summary> /// <param name="node">The AST node the evaluation is a part of.</param> /// <param name="left">The unit on the left</param> /// <param name="right">The unit on the right</param> /// <param name="op">The math operator</param> /// <param name="units"></param> /// <returns></returns> public static LObject CalcUnits(AstNode node, LUnit left, LUnit right, Operator op, Units units) { double baseUnitsValue = 0; if (op == Operator.Multiply) { baseUnitsValue = left.BaseValue * right.BaseValue; } else if (op == Operator.Divide) { baseUnitsValue = left.BaseValue / right.BaseValue; } else if (op == Operator.Add) { baseUnitsValue = left.BaseValue + right.BaseValue; } else if (op == Operator.Subtract) { baseUnitsValue = left.BaseValue - right.BaseValue; } else if (op == Operator.Modulus) { baseUnitsValue = left.BaseValue % right.BaseValue; } var relativeValue = units.ConvertToRelativeValue(baseUnitsValue, left.SubGroup, null); var result = new LUnit(relativeValue); result.BaseValue = baseUnitsValue; result.Group = left.Group; result.SubGroup = left.SubGroup; //result.Value = relativeValue; var lclass = LangTypeHelper.ConvertToLangUnit(result); return(lclass); }
/// <summary> /// Execute each expression. /// </summary> /// <returns></returns> public object VisitForEach(ForEachExpr expr) { expr.DoContinueRunning = true; expr.DoBreakLoop = false; expr.DoContinueLoop = false; // for(user in users) // Push scope for var name var source = expr.SourceExpr.Evaluate(this) as LObject; // Check : 1. null object? if (source == LObjects.Null) { return(LObjects.Null); } IEnumerator enumerator = null; if (source.Type == LTypes.Array) { enumerator = ((IList)source.GetValue()).GetEnumerator(); } else if (source.Type == LTypes.Map) { enumerator = ((IDictionary)source.GetValue()).GetEnumerator(); } else if (source.Type == LTypes.Table) { enumerator = ((IList)source.GetValue()).GetEnumerator(); } expr.DoContinueRunning = enumerator.MoveNext(); while (expr.DoContinueRunning) { // Set the next value of "x" in for(x in y). var current = enumerator.Current is LObject ? enumerator.Current : LangTypeHelper.ConvertToLangClass(enumerator.Current); this.Ctx.Memory.SetValue(expr.VarName, current); if (expr.Statements != null && expr.Statements.Count > 0) { foreach (var stmt in expr.Statements) { stmt.Evaluate(this); this.Ctx.Limits.CheckLoop(expr); // If Break statment executed. if (expr.DoBreakLoop) { expr.DoContinueRunning = false; break; } // Continue statement. else if (expr.DoContinueLoop) { break; } } } else { break; } // Break loop here. if (expr.DoContinueRunning == false) { break; } // Increment. expr.DoContinueRunning = enumerator.MoveNext(); } return(LObjects.Null); }