Ejemplo n.º 1
0
 public override void VisitInvoke(ASTInvoke n)
 {
     if (SystemMethodManager.IsSystemMethod(n.Method))
     {
         n.Actuals.Visit(this);
         SystemMethod method = SystemMethodManager.Lookup(n.Method);
         method.Emit(_gen);
         //store the return type so we can invoke methods and stuff on it.
         _lastWalkedType = _typeManager.LookupCilType(method.FuncInfo.ReturnType);
     }
     else
     {
         //push who
         n.Object.Visit(this);
         Type who = _lastWalkedType;
         //push actuals
         n.Actuals.Visit(this);
         //find the method to execute on the given class
         MethodBuilderInfo info = _typeManager.GetMethodBuilderInfo(who.Name, n.Method);
         _gen.Emit(OpCodes.Callvirt, info.Builder);
         //store the return type of the method
         _lastWalkedType = info.Builder.ReturnType;
     }
 }
Ejemplo n.º 2
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++;
            }
        }
Ejemplo n.º 3
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));
            }
        }
Ejemplo n.º 4
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++;
            }
        }
Ejemplo n.º 5
0
 /// <summary>
 /// Returns whether or not the invoked method "counts" as a return statement.
 /// This is equivalent to C# where if a method that has a return value throws an exception, its decided
 /// to return control properly.
 /// </summary>
 /// <param name="n"></param>
 /// <returns></returns>
 private bool IsExitMethod(ASTInvoke n)
 {
     return(_systemMethods.Any(m => m.Name == n.Method && m.IsExitStatement));
 }