public override void CheckSemantic(SymbolTable symbolTable, List <CompileError> errors)
        {
            SemanticInfo variableInfo;

            ///chequeamos que no haya una variable con el mismo nombre
            if (symbolTable.GetDefinedVariableShallow(CallableId, out variableInfo))
            {
                errors.Add(new CompileError
                {
                    Line         = GetChild(ChildCount - 2).Line,
                    Column       = GetChild(ChildCount - 2).CharPositionInLine,
                    ErrorMessage = string.Format("There is already a definition for '{0}' in current context", CallableId),
                    Kind         = ErrorKind.Semantic
                });

                ///el nodo evalúa de error
                NodeInfo = SemanticInfo.SemanticError;
            }

            ///creamos el scope de la función o procedimiento
            symbolTable.InitNewScope();

            SemanticInfo param;

            ///agregamos los parámetros de la función o procedimiento al scope
            for (int i = 0; i < Parameters.Count; i++)
            {
                param = new SemanticInfo
                {
                    Name         = Parameters[i].Key,
                    ElementKind  = SymbolKind.Variable,
                    BuiltInType  = parametersType[i].BuiltInType,
                    Type         = parametersType[i],
                    ElementsType = parametersType[i].ElementsType,
                    Fields       = parametersType[i].Fields
                };

                symbolTable.InsertSymbol(param);
            }

            ///check semantics al CallableBody
            CallableBody.CheckSemantic(symbolTable, errors);

            ///destruimos el scope de la función o procedimiento
            symbolTable.CloseCurrentScope();
        }
        public override void GenerateCode(ILCodeGenerator cg)
        {
            if (FirstPass)
            {
                if (this is FunctionDeclarationNode)
                {
                    ILElementInfo returnILElementInfo = cg.ILContextTable.GetDefinedType((this as FunctionDeclarationNode).ReturnType);
                    returnILType = returnILElementInfo.ILType;

                    if (Object.Equals(returnILType, null))
                    {
                        returnILType = (this as FunctionDeclarationNode).functionParche.ILType;
                    }
                }

                for (int i = 0; i < ILTypes.Count; i++)
                {
                    if (Object.Equals(ILTypes[i], null))
                    {
                        ILTypes[i] = parametersType[i].Type.ILType;
                    }
                }

                ///creamos un método estático en la clase Program
                string        callableName = string.Format("{0}{1}", CallableId, cg.ILContextTable.ContextNumber);
                MethodBuilder callable     = cg.Program.DefineMethod(callableName, MethodAttributes.Private | MethodAttributes.Static, returnILType, ILTypes.ToArray());

                ///lo insertamos el la tabla de contextos
                cg.ILContextTable.InsertILElement(CallableId, new ILElementInfo {
                    MethodBuilder = callable, ElementKind = SymbolKind.Function
                });

                ///ya no va a ser la 1era pasada
                FirstPass = false;
            }
            else
            {
                ILElementInfo callable = cg.ILContextTable.GetDefinedVarOrFunction(CallableId);

                MethodBuilder callableBuilder = callable.MethodBuilder;

                ILGenerator tmpIL = cg.ILGenerator;
                cg.ILGenerator = callableBuilder.GetILGenerator();

                ///creamos un nuevo contexto
                cg.ILContextTable.InitNewContext();

                List <LocalBuilder> localSaving = new List <LocalBuilder>();

                ///creamos los parámetros y variables en la clase Program
                for (int i = 0; i < Parameters.Count; i++)
                {
                    ParameterBuilder pb = callableBuilder.DefineParameter(i + 1, ParameterAttributes.None, Parameters[i].Key);

                    string       parameterName = string.Format("{0}{1}", Parameters[i].Key, cg.ILContextTable.ContextNumber);
                    FieldBuilder fb            = cg.Program.DefineField(parameterName, ILTypes[i], FieldAttributes.Public | FieldAttributes.Static);
                    cg.ILContextTable.InsertILElement(Parameters[i].Key, new ILElementInfo {
                        FieldBuilder = fb, ElementKind = SymbolKind.Variable
                    });
                }

                //salvamos los valores de las variables de la clase
                for (int i = 0; i < Parameters.Count; i++)
                {
                    localSaving.Add(cg.ILGenerator.DeclareLocal(ILTypes[i]));
                    callable = cg.ILContextTable.GetDefinedVarOrFunction(Parameters[i].Key);
                    cg.ILGenerator.Emit(OpCodes.Ldsfld, callable.FieldBuilder);
                    cg.ILGenerator.Emit(OpCodes.Stloc, localSaving[i]);
                }

                ///cargando los argumentos
                for (int i = 0; i < Parameters.Count; i++)
                {
                    callable = cg.ILContextTable.GetDefinedVarOrFunction(Parameters[i].Key);
                    cg.ILGenerator.Emit(OpCodes.Ldarg, i);
                    cg.ILGenerator.Emit(OpCodes.Stsfld, callable.FieldBuilder);
                }

                ///gen code al body de la función o procedimiento
                CallableBody.GenerateCode(cg);

                bool         isFunction  = this is FunctionDeclarationNode;
                LocalBuilder returnValue = null;

                ///en caso de ser función
                if (isFunction)
                {
                    returnValue = cg.ILGenerator.DeclareLocal(returnILType);
                    cg.ILGenerator.Emit(OpCodes.Stloc, returnValue);
                }

                ///restauramos los valores de las variables de la clase
                for (int i = 0; i < Parameters.Count; i++)
                {
                    callable = cg.ILContextTable.GetDefinedVarOrFunction(Parameters[i].Key);
                    cg.ILGenerator.Emit(OpCodes.Ldloc, localSaving[i]);
                    cg.ILGenerator.Emit(OpCodes.Stsfld, callable.FieldBuilder);
                }
                List <KeyValuePair <LocalBuilder, FieldBuilder> > localvars = CallableBody.GetLocalVariableDeclarations();
                foreach (var item in localvars)
                {
                    cg.ILGenerator.Emit(OpCodes.Ldloc, item.Key);
                    cg.ILGenerator.Emit(OpCodes.Stsfld, item.Value);
                }


                ///destruimos el contexto de la función o procedimiento
                cg.ILContextTable.CloseCurrentContext();

                ///si es función ponemos en el tope de la pila el valor de retorno
                if (isFunction)
                {
                    cg.ILGenerator.Emit(OpCodes.Ldloc, returnValue);
                }

                ///emitimos el return de la función
                cg.ILGenerator.Emit(OpCodes.Ret);

                ///restauramos el ILGenerator del cg
                cg.ILGenerator = tmpIL;
            }
        }