Example #1
0
 public ClassReferenceLiteral(Token firstToken, ClassDefinition cd, Node owner)
     : base(firstToken, owner)
 {
     this.ClassDefinition = cd;
 }
Example #2
0
 public ClassReference(Token token, ClassDefinition clazz, TopLevelConstruct owner)
     : base(token, owner)
 {
     this.ClassDefinition = clazz;
 }
Example #3
0
        internal override Executable ResolveNames(ParserContext parser)
        {
            this.BatchExecutableNameResolver(parser, this.TryBlock);

            Common.TODO.GetCoreNameFromMetadataWithLocale();
            string coreExceptionName = "Core.Exception";

            ClassDefinition simpleException = Node.DoClassLookup(this.Owner, null, coreExceptionName);

            foreach (CatchBlock cb in this.CatchBlocks)
            {
                string[] types      = cb.Types;
                Token[]  typeTokens = cb.TypeTokens;
                int      typeCount  = types.Length;
                cb.TypeClasses = new ClassDefinition[typeCount];
                for (int i = 0; i < typeCount; ++i)
                {
                    string          typeName     = types[i] ?? coreExceptionName;
                    Token           token        = typeTokens[i] ?? cb.CatchToken;
                    ClassDefinition resolvedType = Node.DoClassLookup(this.Owner, token, typeName, true);
                    if (resolvedType == null)
                    {
                        throw new ParserException(token, "Could not resolve class name for catch.");
                    }
                    if (!resolvedType.ExtendsFrom(simpleException))
                    {
                        if (resolvedType.BaseClass == null && resolvedType.Library == null)
                        {
                            throw new ParserException(token, "This class does not extend from Core.Exception.");
                        }
                        else
                        {
                            throw new ParserException(token, "Only classes that extend from Core.Exception may be caught.");
                        }
                    }
                    cb.TypeClasses[i] = resolvedType;

                    // There's only one type, it doesn't resolve into a class, there's no variable, and there's no '.' in the type name.
                    if (resolvedType == null &&
                        typeCount == 1 &&
                        cb.ExceptionVariableToken == null &&
                        !typeName.Contains("."))
                    {
                        // ...that means this is not a type but is actually a variable.

                        // Change the type to "Core.Exception", move this token to a variable
                        types[0] = coreExceptionName;
                        cb.ExceptionVariableToken = token;
                        typeTokens[0]             = null;
                        --i; // and then try resolving again.
                    }
                }

                /*
                 *  TODO: throw an error or warning if an exception catch is followed by a more specific catch.
                 *  e.g.
                 *  try { ... }
                 *  catch (Exception) { ... }
                 *  catch (InvalidArgumentException) { ... }
                 */

                this.BatchExecutableNameResolver(parser, cb.Code);
            }

            if (this.FinallyBlock != null)
            {
                this.BatchExecutableNameResolver(parser, this.FinallyBlock);
            }

            return(this);
        }
Example #4
0
        private void EnsureModifiersAndTypeSignatureConsistencyForClassMethods()
        {
            ClassDefinition classDef     = (ClassDefinition)this.Owner;
            ClassDefinition baseClass    = classDef.BaseClass;
            bool            hasBaseClass = baseClass != null;

            if (hasBaseClass)
            {
                FieldDefinition hiddenField = baseClass.GetField(this.NameToken.Value, true);
                if (hiddenField != null)
                {
                    throw new ParserException(this, "This function definition hides a field from a parent class.");
                }
            }

            if (!hasBaseClass)
            {
                if (this.Modifiers.HasOverride)
                {
                    throw new ParserException(this, "Cannot mark a method as 'override' if it has no base class.");
                }
            }
            else
            {
                FunctionDefinition overriddenFunction = baseClass.GetMethod(this.NameToken.Value, true);
                if (overriddenFunction != null)
                {
                    if (!this.Modifiers.HasOverride)
                    {
                        if (this.CompilationScope.IsCrayon)
                        {
                            // TODO: just warn if not present
                        }
                        else
                        {
                            throw new ParserException(this, "This function hides another function from a parent class. If overriding is intentional, use the 'override' keyword.");
                        }
                    }

                    if (overriddenFunction.Modifiers.HasStatic)
                    {
                        throw new ParserException(this, "Cannot override a static method.");
                    }

                    if (overriddenFunction.Modifiers.AccessModifierType != this.Modifiers.AccessModifierType)
                    {
                        throw new ParserException(this, "This method defines a different access modifier than its overridden parent.");
                    }

                    if (overriddenFunction.Modifiers.AccessModifierType == AccessModifierType.PRIVATE)
                    {
                        throw new ParserException(this, "Cannot override a private method.");
                    }

                    if (overriddenFunction.Modifiers.HasInternal &&
                        overriddenFunction.CompilationScope != this.CompilationScope)
                    {
                        throw new ParserException(this, "Cannot override this method. It is marked as internal and is located in a different assembly.");
                    }

                    if (overriddenFunction.ResolvedReturnType != this.ResolvedReturnType)
                    {
                        if (overriddenFunction.ResolvedReturnType == ResolvedType.ANY &&
                            this.ResolvedReturnType == ResolvedType.OBJECT)
                        {
                            // This is fine.
                        }
                        else
                        {
                            throw new ParserException(this, "This function returns a different type than its overridden parent.");
                        }
                    }

                    if (overriddenFunction.ArgTypes.Length != this.ArgTypes.Length)
                    {
                        throw new ParserException(this, "This function has a different number of arguments than its overridden parent.");
                    }

                    if (overriddenFunction.MinArgCount != this.MinArgCount)
                    {
                        throw new ParserException(this, "This function has a different number of optional arguments than its overridden parent.");
                    }

                    // TODO: if you are overridding a function between a statically and dynamically typed languagte,
                    // the dynamic language should pick up the types from the statically typed language or the
                    // statically typed language should require "object" types in its signature for the other direction.
                    for (int i = 0; i < this.ArgTypes.Length; ++i)
                    {
                        ResolvedType expected = overriddenFunction.ResolvedArgTypes[i];
                        ResolvedType actual   = this.ResolvedArgTypes[i];
                        if (actual != expected &&
                            !(actual == ResolvedType.OBJECT && expected == ResolvedType.ANY))
                        {
                            throw new ParserException(this, "This function has arguments that are different types than its overridden parent.");
                        }
                    }
                }
                else
                {
                    if (this.Modifiers.HasOverride)
                    {
                        throw new ParserException(this, "This function is marked as 'override', but there is no method in a parent class with the same name.");
                    }
                }
            }
        }
Example #5
0
 internal override Expression ResolveNames(ParserContext parser)
 {
     this.BatchExpressionNameResolver(parser, this.Args);
     this.Class = Node.DoClassLookup(this.Owner, this.NameToken, this.Name);
     return(this);
 }