public override void CheckSemantics(Scope scope, Report report) { id.CheckSemantics(scope, report); Scope forScope = scope.AddChild(ScopeType.For); from.CheckSemantics(scope, report); to.CheckSemantics(scope, report); if (id.returnType.isError || from.returnType.isError || to.returnType.isError) { returnType = scope.FindType("error"); return; } if (!from.returnType.isInt || !to.returnType.isInt) { report.Add(Line, CharPositionInLine, "For expressions must be integer"); returnType = scope.FindType("error"); return; } iterVar = forScope.AddVariable(id.name, scope.FindType("int")); iterVar.readOnly = true; block.CheckSemantics(forScope, report); if (block.returnType.isError) { returnType = scope.FindType("error"); return; } returnType = scope.FindType("void"); }
public override void CheckSemantics(Scope scope, Report report) { Scope letScope = scope.AddChild(ScopeType.Let); if (declarations == null) { returnType = scope.FindType("error"); return; } declarations.CheckSemantics(letScope, report); if (declarations.returnType.isError) { returnType = scope.FindType("error"); return; } block.CheckSemantics(letScope, report); if (block.returnType.isError) { returnType = scope.FindType("error"); return; } foreach (var item in block.exprs) { if (item.returnType.isUserDefine && letScope.FindType(item.returnType.name) == null) { report.Add(Line, CharPositionInLine, "Cant return an expression that doesn't exists in the context"); returnType = scope.FindType("error"); return; } } //El tipo de retorno va a ser el de la secuencia de expresiones, o sea el tipo de la ultima expresion, o si no hay expresiones, void returnType = block.returnType; if (block.existsBreak)//Si existe un break tiene mas importancia el tipo de la ultima expresion que el void que pone el break { returnType = block.possibleReturn; } //El tipo de retorno de su bloque debe existir en este scope var info = scope.FindType(block.returnType.name); if (info == null) { report.Add(block.Line, block.CharPositionInLine, string.Format("Cant return type {0}, because doesn't exists", block.returnType.name)); returnType = scope.FindType("error"); return; } }
public override void CheckSemantics(Scope scope, Report report) { Create(); foreach (var func in functions) {//agregar las funciones primero porque en el cuerpo se pueden usar funciones que esten declaradas debajo func.funcScope = scope.AddChild(ScopeType.Function); List <string> names = new List <string>(); func.paramList.Create(); foreach (var param in func.paramList.parameters) { if (names.Contains(param.id.name)) { report.Add(Line, CharPositionInLine, string.Format("Two parameters of function {0} cant have the name {1}", func.id.name, param.id.name)); returnType = scope.FindType("error"); return; } names.Add(param.id.name); func.funcScope.AddVariable(param.id.name, param.GetTypeInfo(func.funcScope)); } #region id check //esto no lo puedo hacer en el nodo de la funcion porque necesito agregar la funcion en el scope del let func.id.CheckSemantics(scope, report); if (func.id.returnType.isError || scope.ShortFindFunction(func.id.name) != null || scope.ShortFindVariable(func.id.name) != null) {//si entra aqui es que el id esta mal, o ya existe una variable y una funcion con el mismo id report.Add(Line, CharPositionInLine, string.Format("Can't create function {0}", func.id.name)); returnType = scope.FindType("error"); } #endregion scope.AddFunction(func.id.name, func); func.PutReturnType(func.funcScope); func.UpdateTypes(func.funcScope); } foreach (var func in functions) { //No puedo chequear la funcion al principio porque no estarian agregadas las variables, ni los tipos de los parametros func.CheckSemantics(func.funcScope, report); if (func.returnType != null && func.returnType.isError) { returnType = scope.FindType("error"); return; } } }
//public Symbol Lookup(string name) => current.Lookup(name); public void NewScope(string name) => current.AddChild(current = new Scope(name, current));