public Word Visit(Block block) { PushScope(); Word result; foreach (var stmt in block.StmtList) { result = stmt.Accept(this); if (IsJumper(result)) { var jumper = (Jumper)result; if (jumper.WasPopped())//Chapuz Alto para que no haga pop until mas de una vez cuando hay bloques adentro de bloques { return(jumper); } if (ControlStack.PopUntil(jumper)) { return(jumper); } else { ErrorFactory.NotValidJumper(stmt, jumper); } } } PopScope(); return(null); }
public Word Visit(SwitchNode switchNode) { ControlStack.Push(ControlType.Switch);//Push into control stack var result = switchNode.Flag.Accept(this); if (IsError(result)) { ControlStack.Pop(); return(result); } PyObj pyObjFlag; if (IsMemoryBlock(result))//comentar ese if else si se hace la desereferencia en atomic expr. { pyObjFlag = ((MemoryBlock)result).Value; } else { pyObjFlag = (PyObj)result; } //pyObj = (PyObj)result;//Descomentar esta linea si se hace la desereferencia en atomic expr. var switchElements = new AstNode[switchNode.SwitchElements.Count]; switchNode.SwitchElements.CopyTo(switchElements); //Caso que dio true a pyObjFlag cuando se comparar con == int? trueCaseIndex = null; int? defaultIndex = null; SwitchLabel switchLabel; PyObj pyObjCase; MyBoolean caseEvaluationResult; for (int i = 0; i < switchElements.Length; i++) { //Quitar comentario si se desea que no puedan venir declaraciones dentro del if //if (switchElements[i].GetNodeType() == NodeType.Declaration) //{ // ControlStack.Pop(); // return ErrorFactory.DeclarationInSwitch(switchElements[i]); //} if (switchElements[i].GetNodeType() != NodeType.SwitchLabel) { continue; } result = switchElements[i].Accept(this); if (IsError(result)) { ControlStack.Pop(); return(result); } switchLabel = (SwitchLabel)result; if (switchLabel.GetLabelType() == LabelType.Default) { if (defaultIndex != null) { ControlStack.Pop(); return(ErrorFactory.MultipleDefaultInSwitch(switchElements[i])); } else { defaultIndex = i; } } else { pyObjCase = switchLabel.Value; result = pyObjFlag.BinaryOperation(BinaryOperator.PyEquals, pyObjCase); if (IsError(result)) { ControlStack.Pop(); return(ErrorFactory.Create(switchElements[i], (MyError)result)); } if (((PyObj)result).GetMyType() != TypeConstants.BOOLEAN) { ControlStack.Pop(); return(ErrorFactory.NotValidOperationInSwitch(switchElements[i])); } caseEvaluationResult = (MyBoolean)result; if (caseEvaluationResult.Bool) { if (trueCaseIndex != null) { ControlStack.Pop(); return(ErrorFactory.MultipleTrueCasesInSwitch(switchElements[i])); } else { trueCaseIndex = i; } } } } int startIndex = switchElements.Length; if (trueCaseIndex != null) { startIndex = (int)trueCaseIndex; } else if (defaultIndex != null) { startIndex = (int)defaultIndex; } for (int i = startIndex; i < switchElements.Length; i++) { if (switchElements[i].GetNodeType() == NodeType.SwitchLabel) { continue; } result = switchElements[i].Accept(this); if (IsJumper(result)) { var jumper = (Jumper)result; if (jumper.CanJump(ControlType.Switch)) { if (!jumper.WasPopped())//Chapuz alto en el caso que retorne un jumper que no este metido dentro de ningun scope { ControlStack.Pop(); } return(null); } if (jumper.WasPopped())//Chapuz Alto para que no haga pop until mas de una vez cuando hay bloques adentro de bloques { return(jumper); } if (ControlStack.PopUntil(jumper)) { return(jumper); } else { ErrorFactory.NotValidJumper(switchElements[i], jumper); } } } return(null); }
public Word InvokeProcedure(ProcedureSegment procedureSegment) { var name = procedureSegment.Id; name = name.ToLowerInvariant(); var arguments = procedureSegment.Arguments; var argumentCount = arguments.Count; Procedure procedure; Procedures.TryGetValue(Procedure.EmptySignature(name, argumentCount), out procedure); if (procedure == null) { return(new MyError("No existe una funcion con el nombre: " + name + " y numero de parametros: " + argumentCount + " en las definiciones globales")); } //scope antes de llamar a la funcion var previousScope = CurrentScope; //Pasamos al scope global para llamar a la funcion CurrentScope = GlobalScope; ControlType controlType; if (procedure.GetDefinitionType() == DefinitionType.Function) { controlType = ControlType.Function; } else if (procedure.GetDefinitionType() == DefinitionType.Method) { controlType = ControlType.Method; } else { throw new Exception("definicion no valida. tiene que ser funciton o method"); } ControlStack.Push(controlType); //hacemos las declaraciones del metodo en un nuevo scope PushScope(); Word result; for (int i = 0; i < argumentCount; i++) { result = CurrentScope.Add(procedure.ParamNames[i], arguments[i]); if (IsError(result)) { ControlStack.Pop(); CurrentScope = previousScope; return(result); } } //Los stmt del metodo: foreach (var stmt in procedure.Stmts) { result = stmt.Accept(this); if (IsJumper(result)) { var jumper = (Jumper)result; if (!jumper.WasPopped() && !ControlStack.PopUntil(jumper)) { ErrorFactory.NotValidJumper(stmt, jumper); continue; } CurrentScope = previousScope; return(((Return)jumper).Obj); } } //Si termina de visitar los stmt, no entro jumper y es una funcion retorna MyNull y reporta un error ControlStack.Pop(); CurrentScope = previousScope; if (controlType == ControlType.Method) { return(null); } else { ErrorFactory.NoValueReturnedInFunction(procedure.Stmts.Last()); return(MyNull.GetInstance()); } }