/// <summary> /// Ejecuta las instrucciones de un bucle foreach /// </summary> private void Execute(InstructionForEach instruction) { Variable variable = ExpressionComputer.Search(instruction.IndexVariable, out string error); if (!string.IsNullOrEmpty(error)) { Compiler.LocalErrors.Add(instruction.Token, error); } else { VariablesCollection variables = ExpressionComputer.Search(instruction.ListVariable, out error).Members; if (!string.IsNullOrEmpty(error)) { Compiler.LocalErrors.Add(instruction.Token, error); } else { // Ordena las variables por su índice variables.SortByIndex(); // Recorre las variables ejecutando el código (en realidad puede que no fuera necesario comprobar el número de iteraciones porque // la colección de variables no se va a modificar por mucho que lo intente el código Nhaml) for (int index = 0; index < variables.Count && index < Compiler.MaximumRepetitionsLoop; index++) { // Asigna el contenido a la variable variable.Value = variables[index].Value; // Ejecuta las instrucciones Execute(instruction.Instructions); } } } }
/// <summary> /// Ejecuta una instrucción while /// </summary> private void Execute(InstructionWhile instruction) { bool end = false; int loopIndex = 0; // Ejecuta las instrucciones en un bucle do { ValueBase result = ExpressionComputer.Evaluate(instruction.ConditionRPN); if (result.HasError) { Compiler.LocalErrors.Add(instruction.Token, result.Error); end = true; } else if (!(result is ValueBool)) { Compiler.LocalErrors.Add(instruction.Token, "El resultado de calcular la expresión no es un valor lógico"); end = true; } else if (!(result as ValueBool).Value) { end = true; } else { Execute(instruction.Instructions); } }while (!end && ++loopIndex < Compiler.MaximumRepetitionsLoop); }
/// <summary> /// Obtiene una variable /// </summary> private ValueBase GetVariable(InstructionVariableIdentifier instruction) { Variable variable = ExpressionComputer.Search(instruction.Variable, out string error); if (!string.IsNullOrWhiteSpace(error)) { Compiler.LocalErrors.Add(instruction.Token, error); return(ValueBase.GetError($"## Error al obtener la variable: {error} ##")); } else if (variable == null) // ... nunca se debería dar { Compiler.LocalErrors.Add(instruction.Token, $"No se encuentra el valor de la variable {instruction.Variable.Name}"); return(ValueBase.GetError($"## No se encuentra la variable: {instruction.Variable.Name} ##")); } else { return(variable.Value); } }
/// <summary> /// Ejecuta una instrucción if /// </summary> private void Execute(InstructionIf instruction) { ValueBase result = ExpressionComputer.Evaluate(instruction.ConditionRPN); if (result.HasError) { Compiler.LocalErrors.Add(instruction.Token, result.Error); } else if (!(result is ValueBool)) { Compiler.LocalErrors.Add(instruction.Token, "El resultado de calcular la expresión no es un valor lógico"); } else if ((result as ValueBool).Value) { Execute(instruction.Instructions); } else { Execute(instruction.InstructionsElse); } }
/// <summary> /// Ejecuta una instrucción de asignación /// </summary> private void Execute(InstructionLet instruction) { Variable variable = ExpressionComputer.Search(instruction.Variable, out string error); if (!string.IsNullOrWhiteSpace(error)) { Compiler.LocalErrors.Add(instruction.Token, error); } else { ValueBase value = ExpressionComputer.Evaluate(instruction.ExpressionsRPN); if (value.HasError) { Compiler.LocalErrors.Add(instruction.Token, value.Error); } else { variable.Value = value; } } }
/// <summary> /// Obtiene los atributos de una instrucción /// </summary> private string GetAttributes(InstructionNhaml instruction) { string attributes = ""; // Añade los parámetros foreach (Parameter parameter in instruction.Attributes) { ValueBase result = ExpressionComputer.Evaluate(parameter.VariableRPN); // Añade el nombre attributes += $" {parameter.Name}="; // Añade el valor if (result.HasError) { Compiler.LocalErrors.Add(instruction.Token, result.Error); } else { attributes += $"\"{result.Content}\""; } } // Devuelve los atributos return(attributes); }
/// <summary> /// Ejecuta una instrucción for /// </summary> private void Execute(InstructionFor instruction) { Variable variableIndex = ExpressionComputer.Search(instruction.IndexVariable, out string error); if (!error.IsEmpty()) { Compiler.LocalErrors.Add(instruction.Token, $"Error al obtener la variable índice: {error}"); } else { ValueBase valueStart = ExpressionComputer.Evaluate(instruction.StartValueRPN); if (valueStart.HasError) { Compiler.LocalErrors.Add(instruction.Token, $"Error al obtener el valor de inicio del bucle for {valueStart.Error}"); } else if (!(valueStart is ValueNumeric)) { Compiler.LocalErrors.Add(instruction.Token, "El valor de inicio del bucle for no es un valor numérico"); } else { ValueBase valueEnd = ExpressionComputer.Evaluate(instruction.EndValueRPN); if (valueEnd.HasError) { Compiler.LocalErrors.Add(instruction.Token, $"Error al obtener el valor de fin del bucle for {valueEnd.Error}"); } else if (!(valueEnd is ValueNumeric)) { Compiler.LocalErrors.Add(instruction.Token, "El valor de fin del bucle for no es un valor numérico"); } else { ValueBase valueStep; // Obtiene el valor del paso if (instruction.StepValueRPN == null || instruction.StepValueRPN.Count == 0) { valueStep = ValueBase.GetInstance("1"); } else { valueStep = ExpressionComputer.Evaluate(instruction.StepValueRPN); } // Comprueba los errores antes de entrar en el bucle if (valueStep.HasError) { Compiler.LocalErrors.Add(instruction.Token, $"Error al obtener el valor de paso del bucle for {valueEnd.Error}"); } else if (!(valueEnd is ValueNumeric)) { Compiler.LocalErrors.Add(instruction.Token, "El valor de paso del bucle for no es un valor numérico"); } else { int indexLoop = 0; int start = (int)(valueStart as ValueNumeric).Value; int end = (int)(valueEnd as ValueNumeric).Value; int intStep = (int)(valueStep as ValueNumeric).Value; int index = start; // Cambia el valor de la variable de índice variableIndex.Value = ValueBase.GetInstance(index.ToString()); // Ejecuta las instrucciones del bucle while (index <= end && indexLoop < Compiler.MaximumRepetitionsLoop) { // Ejecuta las instrucciones del bucle Execute(instruction.Instructions); // Incrementa la variable índice y cambia el valor de la variable index += intStep; variableIndex.Value = ValueBase.GetInstance(index.ToString()); // Incrementa el número de iteraciones indexLoop++; } // Comprueba el número de iteraciones if (indexLoop >= Compiler.MaximumRepetitionsLoop) { Compiler.LocalErrors.Add(instruction.Token, "Se ha sobrepasado el número máximo de iteraciones del bucle for"); } } } } } }