示例#1
0
        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);
        }
示例#2
0
        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);
        }
示例#3
0
        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());
            }
        }