Example #1
0
        public void CheckReadonlyNotPassedAsModifiable(MethodDescriptor methodDesc, ActualBuilder builder, ASTInvoke n)
        {
            //check for readonly params being passed as modifiable parameters.
            int index = 0;

            foreach (var actual in builder.Actuals)
            {
                if (actual.IsFromFormal && actual.IsFormalReadonly)
                {
                    if (String.IsNullOrEmpty(methodDesc.Formals[index].Modifier) ||
                        !methodDesc.Formals[index].Modifier.Equals(READONLY_MODIFIER, StringComparison.OrdinalIgnoreCase))
                    {
                        ReportError(n.Location, "Cannot pass readonly identifier '{0}' as a modifiable parameter to method '{1}'", actual.Name, methodDesc.Name);
                    }
                }
                index++;
            }
        }
Example #2
0
        public void CheckActualsHaveReadonly(MethodDescriptor desc, ActualBuilder builder, ASTInvoke n)
        {
            //check that for all readonly formals the actual is being passes with a readonly modifier
            int index = 0;

            foreach (var formal in desc.Formals)
            {
                if (!String.IsNullOrEmpty(formal.Modifier) &&
                    formal.Modifier.Equals(READONLY_MODIFIER, StringComparison.OrdinalIgnoreCase))
                {
                    if (string.IsNullOrEmpty(builder.Actuals[index].Modifier) ||
                        !builder.Actuals[index].Modifier.Equals(READONLY_MODIFIER, StringComparison.OrdinalIgnoreCase))
                    {
                        ReportError(n.Location, "Missing readonly declaration on method invocation - Parameter '{0}' on function '{1}' must be marked as readonly.", formal.Name, desc.Name);
                    }
                }
                index++;
            }
        }
Example #3
0
        public override void VisitInstantiateClass(ASTInstantiateClass n)
        {
            ClassDescriptor desc = _scopeMgr.GetType(n.ClassName) as ClassDescriptor;

            if (desc != null)
            {
                var cls  = (ClassDescriptor)_scopeMgr.Find(n.ClassName, p => p is ClassDescriptor);
                var func = cls.Methods.Where(prop => prop.Name.Equals(n.ClassName, StringComparison.OrdinalIgnoreCase)).SingleOrDefault().Type as TypeFunction;
                //Check if the class we're working with has a constructor of the same name
                if (func != null)
                {
                    CheckSubTree(n.Actuals);
                    //check the method signature of the constructor to make sure the correct arguments are passed in
                    ActualBuilder builder = new ActualBuilder();
                    n.Actuals.Visit(builder);

                    if (func.AcceptCall(builder.Actuals))
                    {
                        //hooray, the code is valid
                        MethodDescriptor ctorDescriptor = (MethodDescriptor)_scopeMgr.Find(n.ClassName, p => p is MethodDescriptor, func.Scope);
                        _lastSeenType     = desc.Type;
                        n.ClassDescriptor = desc;
                        n.Descriptor      = ctorDescriptor;
                    }
                    else
                    {
                        ReportError(n.Location, "Invalid parameters for constructor '{0}'", n.ClassName);
                    }
                }
                else
                {
                    ReportError(n.Location, "No constructor found for class '{0}'.", n.ClassName);
                }
            }
            else
            {
                ReportError(n.Location, "The name '{0}' is not a class.", n.ClassName);
            }
        }
Example #4
0
        /// <summary>
        /// VisitInvoke and VisitDereferenceField are very similiar, so this should probably be refactored out
        /// into a common method.
        /// </summary>
        /// <param name="n"></param>
        public override void VisitInvoke(ASTInvoke n)
        {
            //Make sure the lvalue is a type and the method name exists
            CFlatType lhs = CheckSubTree(n.Object);

            if (lhs.IsClass)
            {
                TypeClass lvalue     = (TypeClass)lhs;
                var       descriptor = (ClassDescriptor)_scopeMgr.Find(lvalue.ClassName, p => p is ClassDescriptor);
                //check if a method with the given name exists in the scope.
                //This needs to check not only the class's shallow scope, but all the parents as well.
                MethodDescriptor methodDesc = _scopeMgr.Find(n.Method, d => d is MethodDescriptor, descriptor.Scope) as MethodDescriptor;

                //if (methodDesc != null && (descriptor.Methods.Contains(methodDesc) || methodDesc.IsCFlatMethod))
                if (methodDesc != null)
                {
                    if (methodDesc.Modifiers.Contains(PRIVATE_MODIFIER, StringComparer.InvariantCultureIgnoreCase))
                    {
                        if (!_scopeMgr.HasSymbol(n.Method, _currentClass.Scope))
                        {
                            ReportError(n.Location, "Cannot access the private method {0} in class {1} from class {2}", methodDesc.Name, methodDesc.ContainingClass.Name, _currentClass.ClassName);
                        }
                    }

                    //check if the arguments match
                    TypeFunction method = (TypeFunction)methodDesc.Type;
                    //visit any actuals that need processing
                    CheckSubTree(n.Actuals);
                    //collect the actuals
                    var           curMethDesc = _scopeMgr.Find(_currentMethod.Name, d => d is MethodDescriptor) as MethodDescriptor;
                    ActualBuilder builder     = new ActualBuilder(curMethDesc);
                    n.Actuals.Visit(builder);

                    if (method.AcceptCall(builder.Actuals)) //if the types check
                    {
                        CheckActualsHaveReadonly(methodDesc, builder, n);

                        CheckReadonlyNotPassedAsModifiable(methodDesc, builder, n);

                        n.Descriptor = methodDesc;
                        n.CFlatType  = method.ReturnType;

                        _lastSeenType = method.ReturnType;

                        //check if we're processing an exit instruction, and if so, this counts as a return for the current block.
                        if (IsExitMethod(n))
                        {
                            _currentMethod.RegisterReturnStatement();
                        }
                    }
                    else
                    {
                        ReportError(n.Location, "Invalid parameters for method '{0}.{1}'", TypeToFriendlyName(lvalue), n.Method);
                    }
                }
                else
                {
                    ReportError(n.Location, "Method '{0}' does not exist for type '{1}'", n.Method, TypeToFriendlyName(lvalue));
                }
            }
            else
            {
                ReportError(n.Location, "Type '{0}' does not support methods.", TypeToFriendlyName(lhs));
            }
        }