Example #1
0
        internal override Executable ResolveEntityNames(ParserContext parser)
        {
            this.BatchExecutableEntityNameResolver(parser, this.TryBlock);

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

            ClassDefinition simpleException = this.FileScope.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 = this.FileScope.DoClassLookup(this.Owner, token, typeName, true);
                    if (resolvedType == null)
                    {
                        throw new ParserException(token, "Could not resolve class name for catch.");
                    }
                    if (!resolvedType.ExtendsFrom(simpleException))
                    {
                        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.BatchExecutableEntityNameResolver(parser, cb.Code);
            }

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

            return(this);
        }