public override bool VisitArrayAccess(ArrayAccessAST arrayAccess) { //esto es para quedarme con el scope actual arrayAccess.CurrentScope = _scope; arrayAccess.ReturnType = TigerType.GetType <ErrorType>(); //visit the expression represeting the array arrayAccess.Array.Accept(this); //verifico que la expresion 'array' sea de tipo ArrayType var arrayType = arrayAccess.Array.ReturnType as ArrayType; if (arrayType != null) { arrayAccess.Indexer.Accept(this); //verifico que la expresion que indexada sea del tipo IntType var intType = arrayAccess.Indexer.ReturnType as IntType; if (intType != null) { arrayAccess.ReturnType = arrayType.BaseType; return(arrayAccess.AlwaysReturn = true); } _errorListener.Add(new AnalysisError(AnalysisError.LoadMessage("ArrayIndex"), arrayAccess.Line, arrayAccess.Columns)); return(false); } _errorListener.Add(new AnalysisError(AnalysisError.LoadMessage("Index"), arrayAccess.Line, arrayAccess.Columns)); return(false); }
public override bool VisitArrayDeclaration(ArrayDeclarationAST arrayDeclaration) { arrayDeclaration.CurrentScope = _scope; //la clase base chequea q el id sea valido if (VisitTypeDeclaration(arrayDeclaration)) { TigerType tt; if (_scope.HasType(arrayDeclaration.BaseTypeID, out tt) != ScopeLocation.NotDeclared) { var at = new ArrayType(tt, arrayDeclaration.TypeId); _scope.AddType(arrayDeclaration.TypeId, at); return(true); } int savedErrorPos = _errorListener.Count; _scope.TypeAdded += (sender, args) => { if (args.TypeName == arrayDeclaration.BaseTypeID) { _scope.AddType(arrayDeclaration.TypeId, new ArrayType(args.NewType, arrayDeclaration.TypeId)); } }; _scope.FinalizeScope += (sender, args) => { if (sender.HasType(arrayDeclaration.BaseTypeID) == ScopeLocation.NotDeclared) { _errorListener.Insert(savedErrorPos, AnalysisError.TypeIsNotDefined(arrayDeclaration, arrayDeclaration.BaseTypeID)); arrayDeclaration.ReturnType = TigerType.GetType <ErrorType>(); } }; return(true); } return(false); }
public override void CheckSemantics(TigerScope scope, Report report) { ContainingScope = scope; //Check children Condition.CheckSemantics(scope, report); InstructionNode.CheckSemantics(scope, report); if (!Condition.IsOK || !InstructionNode.IsOK) { return; } IsOK = true; //Check children types if (!TigerType.AreCompatible(Condition.TigerType, TigerType.Int)) { report.AddError(SemanticErrors.InvalidConditionType(Condition, Condition.TigerType)); IsOK = false; } if (!TigerType.AreCompatible(InstructionNode.TigerType, TigerType.Void)) { report.AddError(SemanticErrors.InvalidWhileBodyType(InstructionNode)); IsOK = false; } }
/// <summary> /// Este metodo es usado para crear un tipo al cual se hace referencia y es posible que no haya sido previamente creado en el codigo IL /// </summary> /// <param name="typeDeclaration"></param> /// <param name="typeId"></param> /// <returns></returns> private Type CreateTypeNotFounded(TypeDeclarationAST typeDeclaration, string typeId) { TypeInfo type = typeDeclaration.CurrentScope.GetTypeInfo(typeId); if (code.DefinedType.ContainsKey(type.CodeName)) { return(code.DefinedType[type.CodeName]); } TigerType t = type.Type; if (t is ArrayType) { Type baseType = CreateTypeNotFounded(typeDeclaration, ((ArrayType)t).BaseType.TypeID); Type arrayType = baseType.MakeArrayType(); code.DefinedType.Add(type.CodeName, arrayType); return(arrayType); } if (t is RecordType) { Type temp = code.Module.DefineType(type.CodeName); code.DefinedType.Add(type.CodeName, temp); return(temp); } throw new NotImplementedException("Los restantes tipos no estan soportados en tiger"); }
public override void GenerateCode(ILGenerator generator) { var saveFields = ContainingScope.FieldsToFunctionDeclaration(FunctionInfo); foreach (var fieldBuilder in saveFields) { generator.Emit(OpCodes.Ldsfld, fieldBuilder); } foreach (var expressionNode in Arguments) { expressionNode.GenerateCode(generator); } var method = FunctionInfo.MethodBuilder; generator.Emit(OpCodes.Call, method); LocalBuilder methodResult = null; if (!TigerType.AreOfSameType(FunctionInfo.ReturnType, TigerType.Void)) { methodResult = generator.DeclareLocal(FunctionInfo.ReturnType.Type); generator.Emit(OpCodes.Stloc, methodResult); } foreach (var t in saveFields) { generator.Emit(OpCodes.Stsfld, t); } if (!TigerType.AreOfSameType(FunctionInfo.ReturnType, TigerType.Void)) { generator.Emit(OpCodes.Ldloc, methodResult); } }
public override void CheckSemantics(TigerScope scope, Report report) { ContainingScope = scope; //Check children LeftOperandNode.CheckSemantics(scope, report); RightOperandNode.CheckSemantics(scope, report); if (!LeftOperandNode.IsOK || !RightOperandNode.IsOK) { return; } //Check children types if (TigerType.AreCompatible(LeftOperandNode.TigerType, TigerType.Int) && TigerType.AreCompatible(RightOperandNode.TigerType, TigerType.Int)) { TigerType = TigerType.Int; } else if (!TigerType.AreCompatible(LeftOperandNode.TigerType, TigerType.Int)) { report.AddError(SemanticErrors.LogicalOperandInvalidType(LeftOperandNode, LeftOperandNode.TigerType)); } else { report.AddError(SemanticErrors.LogicalOperandInvalidType(RightOperandNode, RightOperandNode.TigerType)); } }
public override void CheckSemantics(TigerScope scope, Report report) { ContainingScope = scope; //Checking children Condition.CheckSemantics(scope, report); IfBlock.CheckSemantics(scope, report); ElseBlock.CheckSemantics(scope, report); if (!Condition.IsOK || !IfBlock.IsOK || !ElseBlock.IsOK) { return; } TigerType = IfBlock.TigerType; //Checking children types if (!TigerType.AreCompatible(Condition.TigerType, TigerType.Int)) { report.AddError(SemanticErrors.InvalidConditionType(Condition, Condition.TigerType)); } if (!TigerType.AreCompatible(IfBlock.TigerType, ElseBlock.TigerType)) { report.AddError(SemanticErrors.IncompatibleIfElseReturnType(ElseBlock, IfBlock.TigerType, ElseBlock.TigerType)); } }
public override bool VisitSequence(SequenceExpressionAST sequenceExpression) { //Se asume q no se retorna nada sequenceExpression.ReturnType = TigerType.GetType <NoType>(); foreach (var exp in sequenceExpression.ExpressionList) { if (!exp.Accept(this)) { //hubo error sequenceExpression.ReturnType = TigerType.GetType <ErrorType>(); } } ExpressionAst last = sequenceExpression.ExpressionList.LastOrDefault(); if (last != null) { //si existe una ultima expresion, esta define el retorno del let sequenceExpression.AlwaysReturn = last.AlwaysReturn; sequenceExpression.ReturnType = last.ReturnType; } //true si no hubo ningun error return(sequenceExpression.ReturnType != TigerType.GetType <ErrorType>()); }
public AssignExpressionAST(LHSExpressionAST leftExp, ExpressionAst rightExp, int line, int col) : base(line, col) { LeftExpression = leftExp; RightExpression = rightExp; ReturnType = TigerType.GetType <NoType>(); }
public void CheckBodySemantics(TigerScope scope, Report report) { //If CheckSemantics failed (FunctionInfo was not created) return if (!IsOK) { return; } IsOK = false; //Create function scope FunctionBodyNode.CheckSemantics(FunctionScope, report); if (!FunctionBodyNode.IsOK) { return; } IsOK = true; if (ReturnTypeNode != null && !ReturnTypeNode.TigerType.Assignable(FunctionBodyNode.TigerType)) { report.AddError(SemanticErrors.IncompatibleFunctionReturnTypeBody(FunctionBodyNode, ReturnTypeNode.TigerType, FunctionBodyNode.TigerType)); } else if (ReturnTypeNode == null && !TigerType.AreOfSameType(TigerType.Void, FunctionBodyNode.TigerType)) { report.AddError(SemanticErrors.IncompatibleFunctionReturnTypeBody(FunctionBodyNode, TigerType.Void, FunctionBodyNode.TigerType)); } }
public override void CheckSemantics(TigerScope scope, Report report) { ContainingScope = scope; //Check children IdNode.CheckSemantics(scope, report); ExpressionNode.CheckSemantics(scope, report); if (!IdNode.IsOK || !ExpressionNode.IsOK) { return; } //Check use of variable name if (!scope.VariableNameAvailable(IdNode.Name)) { report.AddError(SemanticErrors.VariableNameAlreadyInUse(IdNode, IdNode.Name)); return; } //Check children types if (TigerType.AreOfSameType(ExpressionNode.TigerType, TigerType.Nil) || TigerType.AreOfSameType(ExpressionNode.TigerType, TigerType.Void)) { report.AddError(SemanticErrors.InvalidImplicitVariableDeclaration(ExpressionNode, ExpressionNode.TigerType)); return; } //Add variable to scope VariableInfo = scope.DefineVariable(IdNode.Name, ExpressionNode.TigerType, scope); IsOK = true; }
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); }
public override void CheckSemantics(TigerScope scope, Report report) { ContainingScope = scope; //Check children Condition.CheckSemantics(scope, report); IfBlock.CheckSemantics(scope, report); if (!Condition.IsOK && !IfBlock.IsOK) { return; } TigerType = TigerType.Void; //Check condition type if (!TigerType.AreCompatible(TigerType.Int, Condition.TigerType)) { report.AddError(SemanticErrors.InvalidConditionType(Condition, Condition.TigerType)); TigerType = TigerType.Error; } if (!TigerType.AreCompatible(TigerType.Void, IfBlock.TigerType)) { report.AddError(SemanticErrors.InvalidIfBodyType(IfBlock)); TigerType = TigerType.Error; } }
public override bool VisitRecordDeclaration(RecordDeclarationAST recordDeclaration) { recordDeclaration.CurrentScope = _scope; //se asuma que no habra problemas recordDeclaration.ReturnType = TigerType.GetType <NoType>(); //la clase base verifica el ID del type if (VisitTypeDeclaration(recordDeclaration)) { var rt = new RecordType(recordDeclaration.TypeId); //se anade el record creado al scope para q puedan haber records recursivos en su def _scope.AddType(recordDeclaration.TypeId, rt); //se verifica cada una de las declaraciones de los campos del record int savedErrorPos = _errorListener.Count; foreach (var kvp in recordDeclaration.Fields) { if (!rt.Contains(kvp.Key)) { TigerType tt; if (_scope.HasType(kvp.Value, out tt) == ScopeLocation.NotDeclared) { KeyValuePair <string, string> savedKvp = kvp; _scope.TypeAdded += (sender, args) => { if (args.TypeName == savedKvp.Value) { rt.AddField(savedKvp.Key, args.NewType); } }; _scope.FinalizeScope += (sender, args) => { if (sender.HasType(savedKvp.Value) == ScopeLocation.NotDeclared) { _errorListener.Insert(savedErrorPos, new AnalysisError( string.Format( AnalysisError.LoadMessage("TypeUndecl"), savedKvp.Value), recordDeclaration.Line, recordDeclaration.Columns)); recordDeclaration.ReturnType = TigerType.GetType <ErrorType>(); } }; } else { rt.AddField(kvp.Key, tt); } } else { _errorListener.Add(new AnalysisError(string.Format(AnalysisError.LoadMessage("RecDecl"), kvp.Key, recordDeclaration.TypeId), recordDeclaration.Line, recordDeclaration.Columns)); } } //TODO aqui se ve el prob con los ret Types y los return true pq no se puede decir nada en este momento return(true); } return(false); }
/// <summary> /// disparador del evento que ocurre cuando se aƱade un tipo /// </summary> protected virtual void OnTypeAdded(string typeName, TigerType type) { if (TypeAdded != null) { var args = new TypeAddedEventArgs(typeName, type); TypeAdded(this, args); } }
/// <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 void InitScope(Scope scope) { //predifined types scope.AddType("int", TigerType.GetType <IntType>()); scope.AddType("string", TigerType.GetType <StringType>()); //We add ErrorType to scope, because when a variable is not defined //we say that it has ErrorType, so ErrorType must be in the //Scope. scope.AddType(TigerType.GetType <ErrorType>().TypeID, TigerType.GetType <StringType>()); }
public void AddType(string typeId, TigerType type) { var t = new TypeInfo { CodeName = string.Format("{0}_{1}", typeId, Utils.GetUID()), Type = type, TypeId = typeId }; types.Add(typeId, t); OnTypeAdded(typeId, type); }
private bool VisitTypeDeclaration(TypeDeclarationAST typeDeclaration) { if (_scope.HasType(typeDeclaration.TypeId, out _) != ScopeLocation.NotDeclared) { _errorListener.Add(new AnalysisError(string.Format(AnalysisError.LoadMessage("TypeDecl"), typeDeclaration.TypeId), typeDeclaration.Line, typeDeclaration.Columns)); typeDeclaration.ReturnType = TigerType.GetType <ErrorType>(); return(false); } typeDeclaration.ReturnType = TigerType.GetType <NoType>(); return(true); }
private FunctionDeclarationAST(string id, FormalParameterList parameterList, ExpressionAst exprInstructions) { FunctionId = id; FormalParameterList = parameterList; ParameterList = (parameterList ?? new FormalParameterList()) .Parameters .Select(x => new KeyValuePair <string, string>(x.Name, x.TypeIdentifier)).ToList(); ExprInstructions = exprInstructions; ReturnType = TigerType.GetType <NoType>(); }
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 static void AddCharFunctionToScope(Inizializator <ILCode> init) { FunctionInfo funInfo; funInfo = new FunctionInfo(new List <KeyValuePair <string, TigerType> >(), TigerType.GetType <StringType>()); funInfo.ParameterList.Add(GetKeyValue("i", TigerType.GetType <IntType>())); funInfo.FunctionName = "chr"; funInfo.IsPredifined = true; var chr = new FunctionPredifined <ILCode>(funInfo, CharFunction); init.AddPredifinedFunction(chr); }
public static void AddPrintIntFunctionToScope(Inizializator <ILCode> init) { FunctionInfo funInfo; funInfo = new FunctionInfo(new List <KeyValuePair <string, TigerType> >(), TigerType.GetType <NoType>()); funInfo.ParameterList.Add(new KeyValuePair <string, TigerType>("i", TigerType.GetType <IntType>())); funInfo.FunctionName = "printi"; funInfo.IsPredifined = true; var printi = new FunctionPredifined <ILCode>(funInfo, PrintIntFunction); init.AddPredifinedFunction(printi); }
public override bool VisitBreakStatement(BreakAST breakStm) { breakStm.CurrentScope = _scope; if (!_scope.IsInLoop) { _errorListener.Add(new AnalysisError(AnalysisError.LoadMessage("Break"), breakStm.Line, breakStm.Columns)); breakStm.ReturnType = TigerType.GetType <ErrorType>(); return(false); } breakStm.BreakeableLoop = _scope.ContainerLoop; breakStm.ReturnType = TigerType.GetType <NoType>(); return(true); }
/// <summary> /// /// </summary> /// <param name="leftType"></param> /// <param name="rightType"></param> /// <param name="op"></param> /// <param name="tt"></param> /// <returns></returns> bool CheckOperator(TigerType leftType, TigerType rightType, Operators op, out TigerType tt) { if (leftType.SupportsOperator(rightType, op)) { tt = leftType.GetOperationResult(rightType, op); return(true); } if (rightType.SupportsOperator(leftType, op)) { tt = rightType.GetOperationResult(leftType, op); return(true); } tt = null; return(false); }
public override bool VisitNegExpression(NegExpressionAST negExpression) { negExpression.CurrentScope = _scope; if (negExpression.Expression.Accept(this)) { if (negExpression.Expression.ReturnType == TigerType.GetType <IntType>()) { negExpression.ReturnType = TigerType.GetType <IntType>(); return(true); } _errorListener.Add(new AnalysisError(string.Format(AnalysisError.LoadMessage("NegExp"), negExpression.Expression.ReturnType), negExpression.Line, negExpression.Columns)); } negExpression.ReturnType = TigerType.GetType <ErrorType>(); return(false); }
public override void CheckSemantics(TigerScope scope, Report report) { ContainingScope = scope; //Check children InstructionNodes.ToList().ForEach(i => i.CheckSemantics(scope, report)); if (InstructionNodes.Any(e => !e.IsOK)) { return; } //If type is not void (no break found inside) assign last instruction type if (!TigerType.AreCompatible(TigerType, TigerType.Void)) { TigerType = InstructionNodes.Length == 0 ? TigerType.Void : InstructionNodes.Last().TigerType; } }
public ScopeLocation HasVar(string varId, out TigerType varType) { VarInfo var; vars.TryGetValue(varId, out var); varType = var == null ? null : var.TypeInfo.Type; if (varType != null) { return(ScopeLocation.DeclaredLocal); } return((Parent != null) ? (Parent.HasVar(varId, out varType) == ScopeLocation.NotDeclared ? ScopeLocation.NotDeclared : ScopeLocation.DeclaredInParent) : ScopeLocation.NotDeclared); }
public ScopeLocation HasType(string typeID, out TigerType type) { TypeInfo t; types.TryGetValue(typeID, out t); type = (t != null) ? t.Type : null; if (type != null) { return(ScopeLocation.DeclaredLocal); } return((Parent != null) ? (Parent.HasType(typeID, out type) == ScopeLocation.NotDeclared ? ScopeLocation.NotDeclared : ScopeLocation.DeclaredInParent) : ScopeLocation.NotDeclared); }
public void BasicArrayAccess() { var arrayDecl = ArrayDecl("intArray", "int"); var arrayInstDecl = VarDecl("a", ArrayInst("intArray", Num(1), Num(5))); var let = Let( Decls(arrayDecl, arrayInstDecl), Seq(ArrayAccess(Var("a"), Num(0))) ); var errorCollector = new PrinterErrorListener(); var staticChecker = new StaticChecker(errorCollector, InitialScope()); Assert.IsTrue(let.Accept(staticChecker)); Assert.IsTrue(errorCollector.Count == 0); Assert.IsTrue(let.ReturnType == TigerType.GetType <IntType>()); }