private bool CheckFunctionParams(FunctionDeclarationAST fDecl) { int posParam = 0; //get from the scope the function signature. if (_scope.HasFunction(fDecl.FunctionId) == ScopeLocation.NotDeclared) { _errorListener.Add(AnalysisError.FunctionNotDeclared(fDecl)); return(false); } var funInfo = _scope.GetFunction(fDecl.FunctionId); foreach (var parameter in funInfo.ParameterList) { //existen dos parametros con el mismo nombre. if (_scope.HasVar(parameter.Key) == ScopeLocation.DeclaredLocal) { _errorListener.Add(AnalysisError.FunctionParameterAlreadyExists(fDecl, parameter.Key)); fDecl.ReturnType = TigerType.GetType <ErrorType>(); return(false); } //existe una variable con el mismo nombre que este parametro en un ambito mas externo if (_scope.HasVar(parameter.Key) != ScopeLocation.NotDeclared) { _errorListener.Add(AnalysisError.VariableHidesAnotherOne(fDecl)); } //se anade este valor al scope de la funcion var parameterTypeId = fDecl.ParameterList.First(x => x.Key == parameter.Key).Value; _scope.AddVarParameter(parameter.Key, parameterTypeId, posParam, fDecl.FunctionId); posParam++; } return(true); }
/// <summary> /// This method verifies that the function signature is correct. That is that the return type and parameter types are already /// defined. It also verifies that the function does not exist in the scope. /// </summary> /// <param name="fDecl"></param> /// <returns></returns> private bool CheckFunctionSignature(FunctionDeclarationAST fDecl) { TigerType ret = null; if (!string.IsNullOrEmpty(fDecl.ReturnTypeId)) { //si se especifica retorno pero este no es un tipo ya definido ERROR //esto lo garantiza haber organizado las declaraciones if (_scope.HasType(fDecl.ReturnTypeId, out ret) == ScopeLocation.NotDeclared) { _errorListener.Add(AnalysisError.TypeIsNotDefined(fDecl, fDecl.ReturnTypeId)); fDecl.ReturnType = TigerType.GetType <ErrorType>(); return(false); } if (!ret.IsLegalType) { //TODO: Hasta que punto interesa lanzar este error?? _errorListener.Add(new AnalysisError( string.Format(AnalysisError.LoadMessage("InavalidRet"), fDecl.ReturnTypeId), fDecl.Line, fDecl.Columns)); fDecl.ReturnType = TigerType.GetType <ErrorType>(); return(false); } } //ver que la funcion no este previamente declarada if (_scope.HasFunction(fDecl.FunctionId) == ScopeLocation.NotDeclared) { var paramsInfo = new List <KeyValuePair <string, TigerType> >(); foreach (var nameType in fDecl.ParameterList) { TigerType t; //verificar si existe el tipo del parametro. if (_scope.HasType(nameType.Value, out t) == ScopeLocation.NotDeclared) { _errorListener.Add(new AnalysisError( $"Type {nameType.Value} in parameter {fDecl.FunctionId} is not defined", fDecl.Line, fDecl.Columns)); fDecl.ReturnType = TigerType.GetType <ErrorType>(); return(false); } paramsInfo.Add(new KeyValuePair <string, TigerType>(nameType.Key, t)); } var funInfo = new FunctionInfo(paramsInfo, ret ?? TigerType.GetType <NoType>()) { FunctionName = fDecl.FunctionId, FunctionParent = _scope.CurrentFunction }; //se anade en el padre para q este disponible en el scope donde se declara _scope.AddFunction(fDecl.FunctionId, funInfo); return(true); } //ya habia una funcion con ese nombre _errorListener.Add(new AnalysisError(string.Format(AnalysisError.LoadMessage("FuncDecl"), fDecl.FunctionId), fDecl.Line, fDecl.Columns)); return(false); }
public override bool VisitFunctionDeclaration(FunctionDeclarationAST functionDeclaration) { //chequear la semantica del cuerpo de la funcion, la signatura ya fue chequeada en el let correspondiente //here we create a new scope for this function and its parameters PushScope(new Scope(_scope)); //verificar que todos los tipos de los parametros existan y si ya existe el nombre de los parametros //en el scope if (!CheckFunctionParams(functionDeclaration)) { PopScope(); return(false); } functionDeclaration.CurrentScope = _scope; TigerType retType = functionDeclaration.ReturnTypeId != null? functionDeclaration.CurrentScope.GetType(functionDeclaration.ReturnTypeId) : TigerType.GetType <NoType>(); //poner esta funcion como la funcion actual de scope donde se encuentra. FunctionInfo temp = _scope.CurrentFunction; _scope.CurrentFunction = _scope.GetFunction(functionDeclaration.FunctionId); functionDeclaration.ExprInstructions.Accept(this); _scope.CurrentFunction = temp; if (!functionDeclaration.ExprInstructions.AlwaysReturn && retType != TigerType.GetType <NoType>()) { _errorListener.Add(new AnalysisError(string.Format(AnalysisError.LoadMessage("FuncDeclRet"), functionDeclaration.FunctionId), functionDeclaration.Line, functionDeclaration.Columns)); } else if (string.IsNullOrEmpty(functionDeclaration.ReturnTypeId) || functionDeclaration.ExprInstructions.ReturnType.CanConvertTo( _scope.GetType(functionDeclaration.ReturnTypeId))) { PopScope(); return(true); } else { _errorListener.Add( new AnalysisError( string.Format(AnalysisError.LoadMessage("Match"), functionDeclaration.ReturnTypeId, functionDeclaration.ExprInstructions.ReturnType), functionDeclaration.Line, functionDeclaration.Columns)); } functionDeclaration.ReturnType = TigerType.GetType <ErrorType>(); PopScope(); return(false); }
public override bool VisitFunctionDeclaration(FunctionDeclarationAST functionDeclaration) { var other = _other as FunctionDeclarationAST; if (other == null) { return(false); } return(IsEqualNodes(other.FormalParameterList, functionDeclaration.FormalParameterList) && other.FunctionId == functionDeclaration.FunctionId && other.ReturnTypeId == functionDeclaration.ReturnTypeId && IsEqualNodes(other.ExprInstructions, functionDeclaration.ExprInstructions)); }
public override Unit VisitFunctionDeclaration(FunctionDeclarationAST functionDeclaration) { var funDeclGeneratorHelper = new FunctionDeclarationILGeneratorHelper(functionDeclaration); //-----> bool pushOnStack = code.PushOnStack; bool isFunction = !string.IsNullOrEmpty(functionDeclaration.ReturnTypeId); //ver si tengo que generar una clase que contenga toda la informacion para mis hijas MethodBuilder mBuilder; //construir la funcion en il con su clase wrapper a las funciones que ella usa mBuilder = funDeclGeneratorHelper.GenerateInstanceMethodWithClassWrapper(code); //--> MethodBuilder temp = code.Method; code.Method = mBuilder; //--------> FunctionInfo temp1 = functionDeclaration.CurrentScope.CurrentFunction; functionDeclaration.CurrentScope.CurrentFunction = functionDeclaration.CurrentScope.GetFunction(functionDeclaration.FunctionId); code.PushOnStack = isFunction; functionDeclaration.ExprInstructions.Accept(this); mBuilder.GetILGenerator().Emit(OpCodes.Ret); //<-------- functionDeclaration.CurrentScope.CurrentFunction = temp1; //<-- code.Method = temp; //<---- code.PushOnStack = pushOnStack; //crear el tipo que acabo de crear como nested string currentWrapper = string.Format("Tg_{0}", funDeclGeneratorHelper.FunctionCodeName()); var wrapper = (TypeBuilder)code.DefinedType[currentWrapper]; wrapper.CreateType(); return(Unit.Create()); }
public FunctionDeclarationILGeneratorHelper(FunctionDeclarationAST functionDeclaration) { _functionDecl = functionDeclaration; }
public abstract T VisitFunctionDeclaration(FunctionDeclarationAST functionDeclaration);
public static AnalysisError FunctionParameterAlreadyExists(FunctionDeclarationAST fDecl, string parameter) { return(new AnalysisError( string.Format(LoadMessage("FuncDeclParams"), parameter, fDecl.FunctionId), fDecl.Line, fDecl.Columns)); }
public static AnalysisError FunctionNotDeclared(FunctionDeclarationAST fDecl) { return(new AnalysisError( $"It is expected that the function {fDecl.FunctionId} is at scope at this point", fDecl.Line, fDecl.Columns)); }