public object Execute(FiMClass reportClass, bool global = false) { if (reportClass.GetVariable(this.Name) != null) { throw new FiMException("Variable " + this.Name + " already exists"); } KirinValue value = new KirinValue(this.RawValue, reportClass, this.ExpectedType); if (value.Value == null) { value.Value = FiMHelper.GetDefaultValue(this.ExpectedType); } else { if (value.Type != this.ExpectedType) { throw new FiMException("Expected " + this.ExpectedType.AsNamedString() + ", got " + value.Type.AsNamedString()); } } value.Constant = Constant; FiMVariable var = new FiMVariable(this.Name, value); reportClass.Variables.Push(var, global); return(null); }
public static bool IsValidPlace(string place, FiMClass reportClass, out object index) { if (IsValidNumberPlace(place, out var nIndex)) { index = nIndex; return(true); } if (reportClass.GetVariable(place) != null) { var variable = reportClass.GetVariable(place); if (!variable.Constant) { throw new FiMException("Cannot use a non-constant variable as a case"); } if (FiMHelper.IsTypeArray(variable.Type)) { throw new FiMException("Can only use non-array variables as a case"); } index = variable.Value; return(true); } index = null; return(false); }
public KirinValue(string raw, FiMClass reportClass, KirinVariableType forcedType) { this.Raw = raw; this.Class = reportClass; this.ForcedType = forcedType; this.Load(); }
public override object Execute(FiMClass reportClass, params object[] args) { int localVariables = 0; reportClass.Variables.PushFunctionStack(); if (this.Arguments?.Count() > 0) { for (int i = 0; i < this.Arguments.Count(); i++) { if (reportClass.Variables.Has(this.Arguments[i].Name)) { throw new FiMException("Variable name " + this.Arguments[i].Name + " already exists"); } if (i < args.Length) { if (FiMHelper.AsVariableType(args[i]) != this.Arguments[i].Type) { throw new FiMException("Expected " + this.Arguments[i].Type.AsNamedString() + ", got " + FiMHelper.AsVariableType(args[i]).AsNamedString()); } reportClass.Variables.Push(new FiMVariable(this.Arguments[i].Name, new KirinValue(args[i]))); } else { reportClass.Variables.Push( new FiMVariable( this.Arguments[i].Name, new KirinValue(FiMHelper.GetDefaultValue(this.Arguments[i].Type)) ) ); } localVariables++; } } var result = Statement.Execute(reportClass); reportClass.Variables.PopFunctionStack(); if (result != null && this.Returns == null) { throw new FiMException("Non-value returning function returned value"); } if (result != null && this.Returns != null && this.Returns != KirinVariableType.UNKNOWN) { if (FiMHelper.AsVariableType(result) != this.Returns) { throw new FiMException("Expected " + ((KirinVariableType)this.Returns).AsNamedString() + ", got " + FiMHelper.AsVariableType(result).AsNamedString()); } return(result); } return(null); }
/// <summary> /// Evaluates raw FiM++ string into a value /// </summary> public static object Evaluate( FiMClass reportClass, string evaluatable, KirinVariableType?expectedType = null ) { return(Evaluate(reportClass, evaluatable, out _, expectedType)); }
public override object Execute(FiMClass reportClass, params object[] args) { object[] sanitizedArgs = null; if (this.Arguments?.Count > 0) { sanitizedArgs = new object[this.Arguments.Count]; for (int i = 0; i < this.Arguments.Count; i++) { if (i < args.Length) { if (this.Arguments[i] == KirinVariableType.EXPERIMENTAL_DYNAMIC_ARRAY) { if (!FiMHelper.IsTypeArray(args[i])) { throw new FiMException("Expected an array, got " + FiMHelper.AsVariableType(args[i]).AsNamedString()); } } else if (FiMHelper.AsVariableType(args[i]) != this.Arguments[i]) { throw new FiMException("Expected " + this.Arguments[i].AsNamedString() + ", got " + FiMHelper.AsVariableType(args[i]).AsNamedString()); } sanitizedArgs[i] = args[i]; } else { sanitizedArgs[i] = FiMHelper.GetDefaultValue(this.Arguments[i]); } } } object result; try { result = this.Function.DynamicInvoke(sanitizedArgs); } catch (Exception ex) { throw new Exception("An error has occured while running a custom method\n\n" + ex.ToString()); } if (result != null && this.Returns == null) { throw new FiMException("Non-value returning function returned value"); } if (result != null && this.Returns != null && this.Returns != KirinVariableType.UNKNOWN) { if (FiMHelper.AsVariableType(result) != this.Returns) { throw new FiMException("Expected " + ((KirinVariableType)this.Returns).AsNamedString() + ", got " + FiMHelper.AsVariableType(result).AsNamedString()); } return(result); } return(null); }
public KirinValue(string raw, FiMClass reportClass) { this.Raw = raw; this.Class = reportClass; if (raw != null) { this.Load(); } }
public virtual object Execute(FiMClass reportClass) { uint localVariables = 0; object result = null; foreach (var node in this.Body) { if (!node.GetType().IsSubclassOf(typeof(KirinExecutableNode))) { if (node.GetType().IsSubclassOf(typeof(KirinNode)) || node.GetType() == typeof(KirinNode)) { var no = (KirinNode)node; throw new FiMException($"Paragraph contains a non-KirinExecutable node at line ${FiMHelper.GetIndexPair(reportClass.Report.ReportString, node.Start).Line}"); } else { throw new FiMException($"Paragraph contains a non-KirinExecutable node ('{node.NodeType}')"); } } var n = (KirinExecutableNode)node; if (n.NodeType == "KirinVariableDeclaration") { localVariables++; } object r; #if HIDE_ERROR r = n.Execute(reportClass); #else try { r = n.Execute(reportClass); } catch (FiMException err) { throw new Exception(err.Message + " at line " + FiMHelper.GetIndexPair(reportClass.Report.ReportString, n.Start).Line); } #endif if (r != null) { reportClass.Variables.Pop(count: localVariables); return(r); } if (n.NodeType == "KirinReturn") { result = ((KirinValue)r).Value; break; } } reportClass.Variables.Pop(count: localVariables); return(result); }
public override object Execute(FiMClass reportClass) { #if DEBUG if (System.Diagnostics.Debugger.IsAttached) { System.Diagnostics.Debugger.Break(); } #endif return(null); }
public override object Execute(FiMClass reportClass) { if (reportClass.GetVariable(this.VariableName) != null) { throw new FiMException("Variable " + this.VariableName + " already exists"); } var varFrom = new KirinValue(this.RawFrom, reportClass); var varTo = new KirinValue(this.RawTo, reportClass); if (varFrom.Type != KirinVariableType.NUMBER || varTo.Type != KirinVariableType.NUMBER) { throw new FiMException("Expected type number on for-to loops"); } var valFrom = Convert.ToDouble(varFrom.Value); var valTo = Convert.ToDouble(varTo.Value); double interval; if (this.RawInterval != string.Empty) { var varInterval = new KirinValue(this.RawInterval, reportClass); if (varInterval.Type != KirinVariableType.NUMBER) { throw new FiMException("Expected tpye number of for-to interval"); } interval = Convert.ToDouble(varInterval.Value); } else { interval = valTo - valFrom > 0 ? 1.0d : -1.0d; } reportClass.Variables.Push(new FiMVariable(this.VariableName, valFrom)); while (interval > 0 ? valFrom <= valTo : valFrom >= valTo) { reportClass.Variables.Get(this.VariableName).Value = valFrom; var value = this.Statement.Execute(reportClass); if (value != null) { reportClass.Variables.Pop(false); return(value); } valFrom += interval; } reportClass.Variables.Pop(false); return(null); }
public override object Eval(FiMClass reportClass) { var lv = Left.Eval(reportClass); var rv = Right.Eval(reportClass); var lvt = FiMHelper.AsVariableType(lv); var rvt = FiMHelper.AsVariableType(rv); if (FiMHelper.IsTypeArray(lvt) || FiMHelper.IsTypeArray(rvt)) { throw new FiMException("Cannot execute conditional with an array"); } if (this.Condition == "==") { return(IsEqual(lv, rv)); } if (this.Condition == "!=") { return(!IsEqual(lv, rv)); } if (this.Condition == "&&") { return(Convert.ToBoolean(lv) && Convert.ToBoolean(rv)); } if (this.Condition == "||") { return(Convert.ToBoolean(lv) || Convert.ToBoolean(rv)); } if (lvt != KirinVariableType.NUMBER || rvt != KirinVariableType.NUMBER) { throw new FiMException("Expected number value in conditional"); } double lvd = Convert.ToDouble(lv); double rvd = Convert.ToDouble(rv); switch (this.Condition) { case ">=": return(lvd >= rvd); case "<=": return(lvd <= rvd); case ">": return(lvd > rvd); case "<": return(lvd < rvd); default: throw new FiMException("Invalid expression " + this.Condition); } }
public override object Execute(FiMClass reportClass) { var value = new KirinValue(this.RawParameters, reportClass); if (this.ExpectedType != KirinVariableType.UNKNOWN) { if (value.Type != this.ExpectedType) { throw new FiMException("Expected " + this.ExpectedType.AsNamedString() + ", got " + value.Type.AsNamedString()); } } return(value.Value); }
public override object Execute(FiMClass reportClass) { if (reportClass.Variables.Has(this.VariableName)) { throw new FiMException("Variable " + this.VariableName + " already exists"); } var varArray = new KirinValue(this.RawValue, reportClass); if (!FiMHelper.IsTypeArray(varArray.Type) && varArray.Type != KirinVariableType.STRING) { throw new FiMException("Expected type array on for-in loops"); } if (varArray.Type == KirinVariableType.STRING) { string str = Convert.ToString(varArray.Value); reportClass.Variables.Push(new FiMVariable(this.VariableName, str[0])); foreach (char c in str) { reportClass.Variables.Get(this.VariableName).Value = c; var value = this.Statement.Execute(reportClass); if (value != null) { reportClass.Variables.Pop(false); return(value); } } } else { var list = varArray.Value as System.Collections.IDictionary; var sortedKeys = list.Keys.Cast <int>().ToArray().OrderBy(k => k).ToArray(); reportClass.Variables.Push(new FiMVariable(this.VariableName, list[sortedKeys[0]])); foreach (int k in sortedKeys) { reportClass.Variables.Get(this.VariableName).Value = list[k]; var value = this.Statement.Execute(reportClass); if (value != null) { reportClass.Variables.Pop(false); return(value); } } } reportClass.Variables.Pop(false); return(null); }
public override object Execute(FiMClass reportClass) { var p = reportClass.GetParagraph(FunctionName); if (p == null) { throw new FiMException("Cannot find paragraph " + FunctionName); } var parameters = KirinFunctionCall.ParseCallArguments(this.RawParameters, reportClass); p.Execute(parameters.ToArray()); return(null); }
public override object Execute(FiMClass reportClass) { var lVariable = reportClass.GetVariable(this.LeftOp); if (lVariable == null) { throw new FiMException("Variable " + this.LeftOp + " does not exist"); } var kValue = new KirinValue(this.RightOp, reportClass); lVariable.Value = kValue.Value; return(null); }
/// <param name="content">Starting after <c>KirinFunctionCall.FunctionParam</c></param> public static List <KirinValue> ParseCallArguments(string content, FiMClass reportClass) { var a = new List <KirinValue>(); if (content != string.Empty) { foreach (string param in content.Split(new string[] { " and " }, StringSplitOptions.RemoveEmptyEntries)) { a.Add(new KirinValue(param, reportClass)); } } return(a); }
public override object Execute(FiMClass reportClass) { if (!this.Complete) { throw new FiMException("Executing an incomplete switch statement"); } var variable = reportClass.GetVariable(this.RawVariable); if (variable == null) { throw new FiMException("Varible " + this.RawVariable + " does not exist"); } if (FiMHelper.IsTypeArray(variable)) { throw new FiMException("Cannot use array on a switch"); } Dictionary <object, string> CasesLookup = new Dictionary <object, string>(); foreach (var key in Cases.Keys) { if (!KirinSwitchCase.IsValidPlace(key, reportClass, out object value)) { throw new FiMException("Invalid case " + key); } if (CasesLookup.Keys.Any(k => KirinValue.IsEqual(k, value))) { throw new FiMException("Duplicate case value " + key); } CasesLookup.Add(value, key); } KirinStatement s = DefaultCase; if (CasesLookup.Keys.Any(k => KirinValue.IsEqual(k, variable.Value))) { s = Cases[CasesLookup.First(l => KirinValue.IsEqual(l.Key, variable.Value)).Value]; } if (s != null) { return(s.Execute(reportClass)); } return(null); }
public override object Execute(FiMClass reportClass) { var result = (new KirinValue(RawParameters, reportClass)).Value; if (result == null) { return(null); } if (FiMHelper.IsTypeArray(result)) { throw new FiMException("Cannot print an array"); } reportClass.Report.Output(Convert.ToString(result) + (NewLine ? "\n" : "")); return(null); }
public override dynamic Eval(FiMClass reportClass) { switch (this.Expression) { case "+": return(Left.Eval(reportClass) + Right.Eval(reportClass)); case "-": return(Left.Eval(reportClass) - Right.Eval(reportClass)); case "*": return(Left.Eval(reportClass) * Right.Eval(reportClass)); case "/": return(Left.Eval(reportClass) / Right.Eval(reportClass)); case "%": return(Left.Eval(reportClass) % Right.Eval(reportClass)); default: throw new FiMException("Invalid expression " + this.Expression); } }
public override object Execute(FiMClass reportClass) { if (!this.Complete) { throw new FiMException("Executing an incomplete if statement"); } foreach (var cS in Conditions) { var conditional = new KirinConditional(cS.Condition); if (conditional.GetValue(reportClass) == false) { continue; } return(cS.Statement.Execute(reportClass)); } return(null); }
public override object Execute(FiMClass reportClass) { var variable = reportClass.GetVariable(this.RawVariable); if (variable == null) { throw new Exception("Variable " + this.RawVariable + " does not exist"); } if (FiMHelper.IsTypeArray(variable.Type)) { throw new Exception("Cannot input into an array"); } string prompt = ""; if (!string.IsNullOrWhiteSpace(this.PromptString)) { prompt = this.PromptString; } string input = reportClass.Report.Input(prompt, this.RawVariable); if (variable.Type == KirinVariableType.STRING) { input = $"\"{input}\""; } else if (variable.Type == KirinVariableType.CHAR) { input = $"'{input}'"; } if (!KirinLiteral.TryParse(input, out object value)) { throw new Exception("Invalid input " + input); } if (FiMHelper.AsVariableType(value) != variable.Type) { throw new Exception("Input type doesnt match variable type"); } variable.Value = value; return(null); }
public override object Execute(FiMClass reportClass) { if (this.Statement == null) { throw new FiMException("While loop has no statement"); } var conditional = new KirinConditional(Condition); while (conditional.GetValue(reportClass) == true) { var value = Statement.Execute(reportClass); if (value != null) { break; } } return(null); }
public override dynamic Eval(FiMClass reportClass) { var value = new KirinValue(this.RawValue, reportClass); if (value.Type == KirinVariableType.STRING) { return(Convert.ToString(value.Value)); } if (value.Type == KirinVariableType.CHAR) { return(Convert.ToString(value.Value)); } if (value.Type == KirinVariableType.NUMBER) { return(Convert.ToDouble(value.Value)); } throw new FiMException("Cannot do arithmetic on a non-number value"); }
/// <summary> /// Evaluates raw FiM++ string into a value /// </summary> public static object Evaluate( FiMClass reportClass, string evaluatable, out KirinVariableType returnedType, KirinVariableType?expectedType = null ) { returnedType = KirinVariableType.UNKNOWN; // Nothing if (evaluatable == "nothing" && expectedType != null) { returnedType = (KirinVariableType)expectedType; return(FiMHelper.GetDefaultValue(returnedType)); } // Calling an existing variable if (reportClass.GetVariable(evaluatable) != null) { var variable = reportClass.GetVariable(evaluatable); returnedType = variable.Type; return(variable.Value); } // Calling an existing method if (reportClass.GetParagraphLazy(evaluatable) != null) { KirinValue[] args = null; string pName = evaluatable; if (pName.Contains(KirinFunctionCall.FunctionParam)) { int pIndex = pName.IndexOf(KirinFunctionCall.FunctionParam); pName = pName.Substring(0, pIndex); args = KirinFunctionCall.ParseCallArguments( evaluatable.Substring(pName.Length + KirinFunctionCall.FunctionParam.Length), reportClass ).ToArray(); } var paragraph = reportClass.GetParagraph(pName); if (paragraph == null) { throw new FiMException("Paragraph " + pName + " not found"); } if (paragraph.ReturnType == KirinVariableType.UNKNOWN) { throw new FiMException("Paragraph returns nothing"); } returnedType = paragraph.ReturnType; return(paragraph.Execute(args)); } // Array if (expectedType != null && FiMHelper.IsTypeArray((KirinVariableType)expectedType)) { System.Collections.IDictionary dict = null; var args = KirinFunctionCall.ParseCallArguments(evaluatable, reportClass); if (!FiMHelper.IsTypeOfArray(args[0].Type, (KirinArrayType)expectedType)) { throw new FiMException("Invalid list value type"); } if (!args.All(a => a.Type == args[0].Type)) { throw new FiMException("Unidentical list value type"); } int i = 1; if (expectedType == KirinVariableType.STRING_ARRAY) { dict = new Dictionary <int, string>(); args.ForEach(kv => dict.Add(i++, Convert.ToString(kv.Value))); } else if (expectedType == KirinVariableType.NUMBER_ARRAY) { dict = new Dictionary <int, double>(); args.ForEach(kv => dict.Add(i++, Convert.ToDouble(kv.Value))); } else if (expectedType == KirinVariableType.BOOL_ARRAY) { dict = new Dictionary <int, bool>(); args.ForEach(kv => dict.Add(i++, Convert.ToBoolean(kv.Value))); } returnedType = (KirinVariableType)expectedType; return(dict); } // Array index if (FiMHelper.ArrayIndex.IsArrayIndex(evaluatable, reportClass)) { var match = FiMHelper.ArrayIndex.GetArrayIndex(evaluatable, reportClass); var varIndex = new KirinValue(match.RawIndex, reportClass); if (varIndex.Type != KirinVariableType.NUMBER) { throw new FiMException("Invalid index value"); } int index = Convert.ToInt32(varIndex.Value); string strVar = match.RawVariable; if (!reportClass.Variables.Has(strVar)) { throw new FiMException("Variable " + strVar + " does not exist"); } var variable = reportClass.Variables.Get(strVar); if (!FiMHelper.IsTypeArray(variable.Type) && variable.Type != KirinVariableType.STRING) { throw new FiMException("Cannot index a non-array variable"); } if (variable.Type == KirinVariableType.STRING) { returnedType = KirinVariableType.CHAR; return(Convert.ToString(variable.Value)[index - 1]); } var dict = variable.Value as System.Collections.IDictionary; if (variable.Type == KirinVariableType.STRING_ARRAY) { returnedType = KirinVariableType.STRING; return(Convert.ToString(dict[index])); } if (variable.Type == KirinVariableType.BOOL_ARRAY) { returnedType = KirinVariableType.BOOL; return(Convert.ToBoolean(dict[index])); } if (variable.Type == KirinVariableType.NUMBER_ARRAY) { returnedType = KirinVariableType.NUMBER; return(Convert.ToDouble(dict[index])); } } // Arithmetic if (KirinArithmetic.IsArithmetic(evaluatable, out var arithmeticResult)) { var arithmetic = new KirinArithmetic(arithmeticResult); var value = arithmetic.GetValue(reportClass); returnedType = FiMHelper.AsVariableType(value.GetType()); return(value); } // Conditional if (KirinConditional.IsConditional(evaluatable, out var conditionalResult)) { var conditional = new KirinConditional(conditionalResult); returnedType = KirinVariableType.BOOL; return(conditional.GetValue(reportClass)); } throw new FiMException("Cannot evaluate " + evaluatable); }
public virtual object Execute(FiMClass reportClass) => null;
public override object Eval(FiMClass reportClass) { var value = new KirinValue(this.RawValue, reportClass); return(value.Value); }
public virtual object Execute(FiMClass reportClass, params object[] args) { return(null); }
public override object Execute(FiMClass reportClass) { var variable = reportClass.GetVariable(this.LeftOp); if (variable == null) { throw new FiMException("Variable " + this.LeftOp + " does not exist"); } if (!FiMHelper.IsTypeArray(variable.Type) && variable.Type != KirinVariableType.STRING) { throw new FiMException("Variable " + this.LeftOp + " is not an array"); } var kIndex = new KirinValue(this.RawIndex, reportClass); if (kIndex.Type != KirinVariableType.NUMBER) { throw new FiMException("Invalid index " + kIndex.Value); } var iValue = Convert.ToInt32(kIndex.Value); var value = new KirinValue(this.RightOp, reportClass); if (variable.Type == KirinVariableType.STRING) { if (value.Type != KirinVariableType.CHAR) { throw new FiMException("Invalid array modify value"); } var sb = new StringBuilder(variable.Value as string); sb[iValue] = (char)variable.Value; variable.Value = sb.ToString(); } else { if (!FiMHelper.IsTypeOfArray(value.Type, (KirinArrayType)variable.Type)) { throw new FiMException("Invalid array modify value"); } dynamic dict; int index = Convert.ToInt32(kIndex.Value); if (variable.Type == KirinVariableType.STRING_ARRAY) { dict = variable.Value as Dictionary <int, string>; dict[index] = Convert.ToString(value.Value); } else if (variable.Type == KirinVariableType.NUMBER_ARRAY) { dict = variable.Value as Dictionary <int, double>; dict[index] = Convert.ToDouble(value.Value); } else if (variable.Type == KirinVariableType.BOOL_ARRAY) { dict = variable.Value as Dictionary <int, bool>; dict[index] = Convert.ToBoolean(value.Value); } } ; return(null); }
public override object Execute(FiMClass reportClass) { if (reportClass.GetVariable(this.RawVariable) != null) { var variable = reportClass.GetVariable(this.RawVariable); if (variable.Type != KirinVariableType.NUMBER) { if (this.Increment) { throw new FiMException("Cannot apply unary increment on a non-number variable"); } else { throw new FiMException("Cannot apply unary decrement on a non-number variable"); } } if (this.Increment) { variable.Value = Convert.ToDouble(variable.Value) + 1.0d; } else { variable.Value = Convert.ToDouble(variable.Value) - 1.0d; } } else if (FiMHelper.ArrayIndex.IsArrayIndex(this.RawVariable, reportClass)) { var match = FiMHelper.ArrayIndex.GetArrayIndex(this.RawVariable, reportClass); var variable = reportClass.GetVariable(match.RawVariable); if (variable.Type != KirinVariableType.NUMBER_ARRAY) { if (this.Increment) { throw new FiMException("Cannot apply unary increment on a non-number array"); } else { throw new FiMException("Cannot apply unary decrement on a non-number array"); } } var varIndex = new KirinValue(match.RawIndex, reportClass); if (varIndex.Type != KirinVariableType.NUMBER) { throw new FiMException("Invalid index value"); } int index = Convert.ToInt32(varIndex.Value); var dict = variable.Value as Dictionary <int, double>; if (!dict.ContainsKey(index)) { dict[index] = 0.0d; } if (this.Increment) { dict[index] += 1.0d; } else { dict[index] -= 1.0d; } } else { throw new FiMException("Variable " + this.RawVariable + " does not exist"); } return(null); }
public abstract object Eval(FiMClass reportClass);