internal void ResolveVariableOrigins(ParserContext parser) { VariableScope varScope = VariableScope.NewEmptyScope(this.CompilationScope.IsStaticallyTyped); this.ArgLocalIds = new VariableId[this.ArgNames.Length]; for (int i = 0; i < this.ArgNames.Length; ++i) { this.ArgLocalIds[i] = varScope.RegisterVariable(this.ArgTypes[i], this.ArgNames[i].Value); } foreach (Expression arg in this.BaseArgs) { arg.ResolveVariableOrigins(parser, varScope, VariableIdAllocPhase.ALLOC); } foreach (Executable ex in this.Code) { ex.ResolveVariableOrigins(parser, varScope, VariableIdAllocPhase.REGISTER_AND_ALLOC); } Lambda.DoVarScopeIdAllocationForLambdaContainer(parser, varScope, this); varScope.FinalizeScopeIds(); this.LocalScopeSize = varScope.Size; }
internal void ResolveVariableOrigins(ParserContext parser) { if (this.DefaultValue != null) { VariableScope varScope = VariableScope.NewEmptyScope(this.CompilationScope.IsStaticallyTyped); this.DefaultValue.ResolveVariableOrigins(parser, varScope, VariableIdAllocPhase.REGISTER_AND_ALLOC); if (varScope.Size > 0) { // Although if you manage to trigger this, I'd love to know how. throw new ParserException(this, "Cannot declare a variable this way."); } Lambda.DoVarScopeIdAllocationForLambdaContainer(parser, varScope, this); } }
public static TopLevelEntity[] Resolve(ParserContext parser, ICollection <CompilationScope> compilationScopesRaw) { List <TopLevelEntity> originalCode = new List <TopLevelEntity>(); Dictionary <string, CompilationScope> compilationScopeLookup = new Dictionary <string, CompilationScope>(); foreach (CompilationScope scope in compilationScopesRaw.OrderBy(scope => scope.ScopeKey)) { originalCode.AddRange(scope.GetTopLevelEntities()); compilationScopeLookup[scope.Metadata.ID] = scope; } TopLevelEntity[] code = originalCode.ToArray(); parser.VerifyNoBadImports(); ExternalAssemblyMetadata[] assembliesInDependencyOrder = AssemblyDependencyUtil.GetAssemblyResolutionOrder(parser.ScopeManager.ImportedAssemblyScopes.Select(scope => scope.Metadata)); List <CompilationScope> compilationScopes = new List <CompilationScope>( assembliesInDependencyOrder.Select(asm => compilationScopeLookup[asm.ID])); compilationScopes.Add(parser.RootScope); // Resolve raw names into the actual things they refer to based on namespaces and imports. foreach (CompilationScope scope in compilationScopes) { EntityNameResolver.Resolve(parser, scope); } LocalScopeVariableIdAllocator.Run(parser, code.Where(tle => !(tle is ConstDefinition || tle is EnumDefinition))); foreach (CompilationScope scope in compilationScopes) { TopLevelEntity[] topLevelEntities = scope.GetTopLevelEntities(); ConstDefinition[] consts = topLevelEntities.OfType <ConstDefinition>().ToArray(); EnumDefinition[] enums = topLevelEntities.OfType <EnumDefinition>().ToArray(); ClassDefinition[] classes = topLevelEntities.OfType <ClassDefinition>().ToArray(); FunctionDefinition[] functions = topLevelEntities.OfType <FunctionDefinition>().ToArray(); // Constants are provided in dependency order. Type resolution running in this order // will not encounter anything unknown. Const dependency loops are found by .SortConstants() // Note that this sorting is for the purposes of type resolution. All enums are automatically // known to be integers, so there's possibly still some dependency loops there, which are // caught during the consolidation in the Resolve() phase. TopLevelEntity[] topLevelEntitiesWithoutConstants = new TopLevelEntity[0] .Concat(enums) .Concat(functions) .Concat(classes) .ToArray(); // The type of the overall constant is dependent on the expression's type when there are // no type declarations (i.e. Crayon). Because signature types need to be resolved before // the expression itself, these are sorted in dependency order. Enum values, even though // a const expression can depend on them, are always an integer, so they don't need to be // type-resolved at this time. ConstDefinition[] dependencySortedConstants = new ConstantDependencySorter(consts).SortConstants(); foreach (ConstDefinition cnst in dependencySortedConstants) { TypeResolver typeResolver = new TypeResolver(parser.TypeContext, cnst); // This shouldn't pick anything up, but it'll fire any errors when undeclared variable-like expressions are used. cnst.Expression.ResolveVariableOrigins(parser, VariableScope.NewEmptyScope(false), VariableIdAllocPhase.REGISTER_AND_ALLOC); cnst.ResolveTypes(parser, typeResolver); cnst.ValidateConstTypeSignature(); } foreach (TopLevelEntity tle in topLevelEntitiesWithoutConstants) { TypeResolver typeResolver = new TypeResolver(parser.TypeContext, tle); tle.ResolveSignatureTypes(parser, typeResolver); } foreach (TopLevelEntity tle in topLevelEntitiesWithoutConstants.Where(t => !(t is EnumDefinition))) { tle.EnsureModifierAndTypeSignatureConsistency(parser.TypeContext); } foreach (TopLevelEntity tle in topLevelEntitiesWithoutConstants) { TypeResolver typeResolver = new TypeResolver(parser.TypeContext, tle); tle.ResolveTypes(parser, typeResolver); } } SpecialFunctionFinder.Run(parser); List <TopLevelEntity> newCode = new List <TopLevelEntity>(); foreach (CompilationScope scope in compilationScopes) { TopLevelEntity[] everything = scope.GetTopLevelEntities(); TopLevelEntity[] constsAndEnums = new TopLevelEntity[0] .Concat(everything.OfType <ConstDefinition>()) .Concat(everything.OfType <EnumDefinition>()) .ToArray(); TopLevelEntity[] codeContainers = new TopLevelEntity[0] .Concat(everything.OfType <FunctionDefinition>()) .Concat(everything.OfType <ClassDefinition>()) .ToArray(); foreach (TopLevelEntity tle in everything.Concat(codeContainers)) { tle.Resolve(parser); } newCode.AddRange(DependencyBasedClassSorter.Run(codeContainers)); } code = newCode.ToArray(); parser.InlinableLibraryFunctions = InlineableLibraryFunctionFinder.Find(code); return(code); }