public override void Exit(MethodDeclaration node) { int numReturnStatements = _returnTypes.Count; if (node.Symbol.Type == VoidType.GetInstance()) { // Void methods cannot have return statements // (because Mini-Java does not allow empty return statements). if (numReturnStatements > 0) { ReportError( ErrorTypes.TypeError, String.Format("Cannot return a value from a method whose result type is {0}.", node.Symbol.Type.Name), node); _returnTypes.Clear(); } } else if (numReturnStatements == 0 || !AllBranchesReturnAValue(node)) { ReportError( ErrorTypes.TypeError, String.Format("Missing return statement in method {0}.", node.Symbol.Name), node); } // Return types can be checked even if some branches were missing // a return statement. CheckReturnTypes(node, node.Symbol); }
public static MethodDeclaration CreateMainMethodDeclaration(List<IStatement> methodBody, int row, int col) { var method = new MethodDeclaration(MiniJavaInfo.MainMethodIdent, MiniJavaInfo.VoidType, false, new List<VariableDeclaration>(), methodBody, row, col, true); method.IsEntryPoint = true; return method; }
public override void Visit(MethodDeclaration node) { if (_pass == 0) { CheckStatements(node.MethodBody); } else if (_pass == 1) { _currentLocalIdx = 0; } }
public static ClassDeclaration CreateMainClassDeclaration(string name, MethodDeclaration mainMethod, int row, int col) { if (!mainMethod.IsEntryPoint) { throw new ArgumentException("Illegal main method declaration, the program has no entry point."); } var mainClass = new ClassDeclaration(name, null, new List<Declaration> { mainMethod }, row, col); mainClass.IsMainClass = true; return mainClass; }
private static MethodAttributes GetMethodAttributes(MethodDeclaration node) { MethodAttributes attrs = MethodAttributes.Public; // all methods are public if (node.IsStatic) { attrs |= MethodAttributes.Static; } else { attrs |= MethodAttributes.Virtual; } return attrs; }
private bool OverloadsSuperClassMethod(MethodDeclaration method, MethodDeclaration superClassMethod) { if (method.Formals.Count != superClassMethod.Formals.Count) { return true; } bool formalsEqual = true; for (int i = 0; i < method.Formals.Count && formalsEqual; i++) { var methodFormal = method.Formals[i].Type; var superFormal = superClassMethod.Formals[i].Type; // The method's formal parameter cannot be a subtype of the // superclass method's formal parameter type: // http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.4.2 // (This would be overloading.) if (methodFormal != ErrorType.GetInstance() && superFormal != ErrorType.GetInstance()) { formalsEqual = methodFormal.Equals(superFormal); } } return !formalsEqual; }
private Type[] GetParameterTypes(MethodDeclaration node) { if (node.Formals.Count == 0) return Type.EmptyTypes; Type[] types = new Type[node.Formals.Count]; for (int i = 0; i < node.Formals.Count; i++) { VariableDeclaration decl = node.Formals[i]; types[i] = _parent.BuildType(decl.TypeName, decl.IsArray); } return types; }
public override void Visit(MethodDeclaration node) { // Check that the method does not overload a method in a superclass. // Only overriding is allowed. var classSymbol = node.DeclaringType; var superClassMethod = classSymbol.SuperClass == null ? null : classSymbol.SuperClass.Scope.ResolveMethod(node.Name); if (superClassMethod != null) { CheckForOverloading(node, classSymbol, superClassMethod); } }
// Detects possible duplicate declaration of a method identifier. // A dummy scope is made to stand in for the method scope. public override void Visit(MethodDeclaration node) { Debug.Assert(CurrentScope is IMethodScope); node.Type = CheckDeclaredType(node); var methodScope = (IMethodScope) CurrentScope; // Note: the symbol is stored on the node even if the attempt // to define it fails. This feature can be used in the type // checking phase to e.g. check return types for even methods // that could not be defined due to a name clash. node.Symbol = new MethodSymbol(node.Name, node.Type, methodScope, node.IsStatic); IScope scope = node.Symbol.Scope; if (!methodScope.Define(node.Symbol)) { ReportSymbolDefinitionError(node); scope = new ErrorScope(CurrentScope); // Make an error scope to stand in for the method scope for purposes of recovery. } // (Both are IVariableScopes.) node.Symbol.Declaration = node; node.Scope = scope; EnterScope(scope); }
public override void Exit(MethodDeclaration node) { ExitScope(); }
private bool AllBranchesReturnAValue(MethodDeclaration node) { return BlockAlwaysReturnsAValue(node.MethodBody); }
private void ValidateCallParameterTypes(MethodInvocation node, MethodDeclaration methodDecl) { var callParamTypes = node.CallParameters.Select<IExpression, IType>((expr) => expr.Type).ToList(); for (int i = 0; i < methodDecl.Formals.Count; i++) { var callParamType = callParamTypes[i]; var formalParamType = methodDecl.Formals[i].Type; if (!callParamType.IsAssignableTo(formalParamType)) { var msg = String.Format( "Wrong type of argument to method {0}. Expected {1} but found {2}.", node.MethodName, formalParamType.Name, callParamType.Name); ReportError(ErrorTypes.TypeError, msg, node); } } }
public override void Visit(MethodDeclaration node) { MethodBuilder methodBuilder = _currentType.DefineMethod(node.Name, GetMethodAttributes(node)); if (node.IsEntryPoint) { _parent._asmBuilder.SetEntryPoint(methodBuilder, PEFileKinds.ConsoleApplication); } methodBuilder.SetReturnType(GetReturnType(node)); methodBuilder.SetParameters(GetParameterTypes(node)); var sym = node.Scope.ResolveMethod(node.Name); _parent._methods[sym] = methodBuilder; _currentMethod = methodBuilder; }
private void CheckReturnTypes(MethodDeclaration node, MethodSymbol method) { while (_returnTypes.Count > 0) { var returnType = _returnTypes.Pop(); if (!returnType.IsAssignableTo(method.Type)) { // The type of object returned by the return statement // must match the method's declared return type. ReportError(ErrorTypes.TypeError, String.Format("Cannot convert expression of type {0} to {1}.", returnType.Name, method.Type.Name), node); } } }
private void CheckForOverloading(MethodDeclaration node, TypeSymbol classSymbol, MethodSymbol superClassMethod) { var superClassMethodDeclaration = (MethodDeclaration)superClassMethod.Declaration; if (OverloadsSuperClassMethod(node, superClassMethodDeclaration)) { var msg = String.Format("Method {0} in class {1} overloads a method in class {2}. Overloading is not allowed.", node.Name, classSymbol.Name, classSymbol.SuperClass.Name); ReportError(ErrorTypes.InvalidOverride, msg, node); } // Subclass methods CANNOT have covariant return types with respect to overridden // superclass methods, though this is allowed in Java. This is because the .NET runtime // does not natively support them. (Reference link can be found in tests and docs.) if (node.Type != superClassMethodDeclaration.Type) { var msg = String.Format( "Method {0} in class {1} has a different return type from overridden method in class {2}.", node.Name, classSymbol.Name, classSymbol.SuperClass.Name); ReportError(ErrorTypes.InvalidOverride, msg, node); } }
public override void Exit(MethodDeclaration node) { _currentMethod = null; }
private Type GetReturnType(MethodDeclaration node) { return _parent.BuildType(node.TypeName, node.IsArray); }