/// <summary> /// Creates a new container, consuming the provided builder. /// </summary> /// <param name="builder"></param> public Container(ContainerBuilder builder) { ContainerScope = new Scoped(this); Registrations = builder.Registrations; Settings = builder.Settings; DependencyGraph = new ResolverPipeline(builder.Registrations, ContainerScope, Settings, null); }
internal override Expression ResolveEntityNames(ParserContext parser) { if (this.Name == "$var") { return(new CompileTimeDictionary(this.FirstToken, "var", this.Owner)); } if (this.Name == "$$$") { throw new ParserException(this, "Core function invocations cannot stand alone and must be immediately invoked."); } NamespaceReferenceTemplate nrt = this.Owner.FileScope.FileScopeEntityLookup.DoNamespaceLookup(this.Name, this.TopLevelEntity); if (nrt != null) { return(new NamespaceReference(this.FirstToken, this.Owner, nrt)); } TopLevelEntity exec = this.Owner.FileScope.FileScopeEntityLookup.DoEntityLookup(this.Name, this.Owner); if (exec != null) { if (!(this.Owner is ICodeContainer && ((ICodeContainer)this.Owner).ArgumentNameLookup.Contains(this.Name))) { return(ResolverPipeline.ConvertStaticReferenceToExpression(exec, this.FirstToken, this.Owner)); } } return(this); }
/// <summary> /// Creates a new child container using the provided builder. /// </summary> /// <param name="parentContainer"></param> /// <param name="builder"></param> private Container(Container parentContainer, ContainerBuilder builder) { Settings = parentContainer.Settings; _parentContainer = parentContainer; ContainerScope = new Scoped(this); Registrations = builder.Registrations; DependencyGraph = new ResolverPipeline(builder.Registrations, ContainerScope, Settings, parentContainer.DependencyGraph); }
/// <summary> /// Creates a new container using the provided builder. /// </summary> /// <param name="builder"></param> /// <param name="options"></param> public Container(Action <ContainerBuilder>?builder = null, SingularitySettings?options = null) { var context = new ContainerBuilder(this); builder?.Invoke(context); _options = options ?? SingularitySettings.Default; _containerScope = new Scoped(this); Registrations = context.Registrations; _dependencyGraph = new ResolverPipeline(context.Registrations, _containerScope, _options, null); }
private Container(Container parentContainer, Action <ContainerBuilder>?builder) { var context = new ContainerBuilder(this); builder?.Invoke(context); _parentContainer = parentContainer; _options = parentContainer._options; _containerScope = new Scoped(this); Registrations = context.Registrations; _dependencyGraph = new ResolverPipeline(context.Registrations, _containerScope, _options, parentContainer._dependencyGraph); }
public TopLevelConstruct[] ParseAllTheThings() { Dictionary <string, string> files = this.GetCodeFiles(); // When a syntax error is encountered, add it to this list (RELEASE builds only). // Only allow one syntax error per file. Libraries are considered stable and will // only report the first error in the event that an error occurs (since they get // parsed along with the file that imports it and so it's considered an error from // the importing file). List <ParserException> parseErrors = new List <ParserException>(); // Only iterate through actual user files. Library imports will be inserted into the code when encountered // the first time for each library. foreach (string fileName in files.Keys) { string code = files[fileName]; #if DEBUG this.ParseInterpretedCode(fileName, code); #else try { this.ParseInterpretedCode(fileName, code); } catch (ParserException pe) { parseErrors.Add(pe); } #endif } if (parseErrors.Count > 0) { throw new MultiParserException(parseErrors); } return(ResolverPipeline.Resolve(this, this.compilationScopes.Values)); }
internal override Expression ResolveEntityNames( ParserContext parser) { FunctionDefinition funcDef; // used in multiple places. FieldDefinition fieldDec; this.Root = this.Root.ResolveEntityNames(parser); Expression root = this.Root; string field = this.FieldToken.Value; if (root is NamespaceReference) { // already a fully qualified namespace, therefore imports don't matter. string fullyQualifiedName = ((NamespaceReference)root).Template.Name + "." + field; TopLevelEntity entity = this.Owner.FileScope.FileScopeEntityLookup.DoEntityLookup(fullyQualifiedName, parser.CurrentCodeContainer); if (entity != null) { return(ResolverPipeline.ConvertStaticReferenceToExpression(entity, this.FirstToken, this.Owner)); } NamespaceReferenceTemplate nrt = this.Owner.FileScope.FileScopeEntityLookup.DoNamespaceLookup(fullyQualifiedName, parser.CurrentCodeContainer); if (nrt != null) { return(new NamespaceReference(this.FirstToken, this.Owner, nrt)); } throw new ParserException(this, "Could not find class or function by the name of: '" + fullyQualifiedName + "'"); } if (root is ClassReference) { ClassDefinition cd = ((ClassReference)root).ClassDefinition; funcDef = cd.GetMethod(field, false); if (funcDef != null) { if (!funcDef.Modifiers.HasStatic) { string className = cd.NameToken.Value; string functionName = funcDef.NameToken.Value; throw new ParserException(this.DotToken, "'" + className + "." + functionName + "' is not a static method, but it is being used as though it is static."); } Node.EnsureAccessIsAllowed(this.FieldToken, this.Owner, funcDef); return(new FunctionReference(this.FirstToken, funcDef, this.Owner)); } fieldDec = cd.GetField(field, false); if (fieldDec != null) { if (!fieldDec.Modifiers.HasStatic) { throw new ParserException(this.DotToken, "Cannot make a static reference to a non-static field."); } Node.EnsureAccessIsAllowed(this.FieldToken, this.Owner, fieldDec); return(new FieldReference(this.FirstToken, fieldDec, this.Owner)); } // TODO: typeof(class name) is less error prone with localization conflicts. // However there's a Core.typeOf() method that sort of conflicts. // TODO: if this notation is kept, then this needs to be split into two class keywords // since they do different things. if (field == parser.Keywords.CLASS) { return(new ClassReferenceLiteral(this.FirstToken, cd, this.Owner)); } // TODO: nested classes, enums, constants // TODO: show spelling suggestions. throw new ParserException(this.FieldToken, "No static fields or methods named '" + field + "' on the class " + cd.NameToken.Value + "."); } if (root is BaseKeyword) { ClassDefinition thisClass = null; if (this.Owner != null) { if (this.Owner is FunctionDefinition) { thisClass = this.Owner.Owner as ClassDefinition; } else { thisClass = this.Owner as ClassDefinition; } } if (thisClass == null) { throw new ParserException(root, "'base' keyword can only be used inside classes."); } ClassDefinition cd = thisClass.BaseClass; if (cd == null) { throw new ParserException(root, "'base' keyword can only be used inside classes that extend from another class."); } FunctionDefinition fd = cd.GetMethod(field, true); if (fd == null) { throw new ParserException(this.DotToken, "Cannot find a method by that name in the base class chain."); } if (fd.Modifiers.HasStatic) { throw new ParserException(this.DotToken, "Cannot reference static methods using 'base' keyword."); } Node.EnsureAccessIsAllowed(this.DotToken, this.Owner, fd); return(new BaseMethodReference(this.FirstToken, this.DotToken, this.FieldToken, this.Owner)); } if (root is ThisKeyword) { ClassDefinition cd = null; TopLevelEntity owner = this.TopLevelEntity; if (owner is FunctionDefinition) { FunctionDefinition functionOwner = (FunctionDefinition)owner; if (functionOwner.Modifiers.HasStatic) { throw new ParserException(this.Root, "'this' keyword cannot be used in static methods."); } if (!(functionOwner.Owner is ClassDefinition)) { throw new ParserException(this.Root, "'this' keyword cannot be used in a function that isn't in a class."); } cd = (ClassDefinition)owner.Owner; } else if (owner is FieldDefinition) { if (((FieldDefinition)owner).Modifiers.HasStatic) { throw new ParserException(this.Root, "'this' keyword cannot be used in static fields."); } cd = (ClassDefinition)owner.Owner; } else if (owner is ConstructorDefinition) { if (((ConstructorDefinition)owner).Modifiers.HasStatic) { throw new ParserException(this.Root, "'this', keyword cannot be used in static constructors."); } cd = (ClassDefinition)owner.Owner; } else { throw new ParserException(this.Root, "'this' keyword must be used inside a class."); } funcDef = cd.GetMethod(field, true); if (funcDef != null) { if (funcDef.Modifiers.HasStatic) { throw new ParserException(this.DotToken, "This method is static and must be referenced by the class name, not 'this'."); } Node.EnsureAccessIsAllowed(this.DotToken, this.Owner, funcDef); return(new FunctionReference(this.FirstToken, funcDef, this.Owner)); } FieldDefinition fieldDef = cd.GetField(field, true); if (fieldDef != null) { if (fieldDef.Modifiers.HasStatic) { throw new ParserException(this.DotToken, "This field is static and must be referenced by the class name, not 'this'."); } Node.EnsureAccessIsAllowed(this.DotToken, this.Owner, fieldDef); return(new FieldReference(this.FirstToken, fieldDef, this.Owner)); } // TODO: show suggestions in the error message for anything close to what was typed. throw new ParserException(this.FieldToken, "The class '" + cd.NameToken.Value + "' does not have a field named '" + field + "'."); } if (this.Root is EnumReference) { EnumDefinition enumDef = ((EnumReference)this.Root).EnumDefinition; if (field == parser.Keywords.FIELD_ENUM_LENGTH) { return(new IntegerConstant(this.FirstToken, enumDef.Items.Length, this.Owner)); } if (field == parser.Keywords.FIELD_ENUM_MAX) { return(new SpecialEntity.EnumMaxFunction(this.FirstToken, enumDef, this.Owner)); } if (field == parser.Keywords.FIELD_ENUM_VALUES) { return(new SpecialEntity.EnumValuesFunction(this.FirstToken, enumDef, this.Owner)); } return(new EnumFieldReference(this.FirstToken, enumDef, this.FieldToken, this.Owner)); } // This is done here in the resolver instead of the parser because some unallowed // field names (such as .class) are valid. if (field == parser.Keywords.CLASS) { if (this.Root is Variable) { throw new ParserException(this.Root, "'" + ((Variable)this.Root).Name + "' is not a class."); } throw new ParserException(this.DotToken, ".class can only be applied to class names."); } parser.VerifyIdentifier(this.FieldToken); return(this); }
internal override Expression ResolveNames( ParserContext parser) { FunctionDefinition funcDef; // used in multiple places. FieldDeclaration fieldDec; this.Root = this.Root.ResolveNames(parser); Expression root = this.Root; string field = this.StepToken.Value; if (root is NamespaceReference) { // already a fully qualified namespace, therefore imports don't matter. string fullyQualifiedName = ((NamespaceReference)root).Template.Name + "." + field; TopLevelConstruct entity = this.Owner.FileScope.FileScopeEntityLookup.DoEntityLookup(fullyQualifiedName, parser.CurrentCodeContainer); if (entity != null) { return(ResolverPipeline.ConvertStaticReferenceToExpression(entity, this.FirstToken, this.Owner)); } NamespaceReferenceTemplate nrt = this.Owner.FileScope.FileScopeEntityLookup.DoNamespaceLookup(fullyQualifiedName, parser.CurrentCodeContainer); if (nrt != null) { return(new NamespaceReference(this.FirstToken, this.Owner, nrt)); } throw new ParserException(this.FirstToken, "Could not find class or function by the name of: '" + fullyQualifiedName + "'"); } if (root is ClassReference) { ClassDefinition cd = ((ClassReference)root).ClassDefinition; funcDef = cd.GetMethod(field, false); if (funcDef != null) { if (!funcDef.IsStaticMethod) { string className = cd.NameToken.Value; string functionName = funcDef.NameToken.Value; throw new ParserException(this.DotToken, "'" + className + "." + functionName + "' is not a static method, but it is being used as though it is static."); } return(new FunctionReference(this.FirstToken, funcDef, this.Owner)); } fieldDec = cd.GetField(field, false); if (fieldDec != null) { if (!fieldDec.IsStaticField) { throw new ParserException(this.DotToken, "Cannot make a static reference to a non-static field."); } return(new FieldReference(this.FirstToken, fieldDec, this.Owner)); } if (field == "class") { return(new ClassReferenceLiteral(this.FirstToken, cd, this.Owner)); } // TODO: nested classes, enums, constants // TODO: show spelling suggestions. throw new ParserException(this.StepToken, "No static fields or methods named '" + field + "' on the class " + cd.NameToken.Value + "."); } if (root is BaseKeyword) { ClassDefinition thisClass = null; if (this.Owner != null) { if (this.Owner is FunctionDefinition) { thisClass = this.Owner.Owner as ClassDefinition; } else { thisClass = this.Owner as ClassDefinition; } } if (thisClass == null) { throw new ParserException(root.FirstToken, "'base' keyword can only be used inside classes."); } ClassDefinition cd = thisClass.BaseClass; if (cd == null) { throw new ParserException(root.FirstToken, "'base' keyword can only be used inside classes that extend from another class."); } FunctionDefinition fd = cd.GetMethod(field, true); if (fd == null) { throw new ParserException(this.DotToken, "Cannot find a method by that name in the base class chain."); } if (fd.IsStaticMethod) { throw new ParserException(this.DotToken, "Cannot reference static methods using 'base' keyword."); } return(new BaseMethodReference(this.FirstToken, this.DotToken, this.StepToken, this.Owner)); } if (root is ThisKeyword) { ClassDefinition cd = null; if (this.Owner != null) { if (this.Owner is FunctionDefinition) { funcDef = this.Owner as FunctionDefinition; if (funcDef.IsStaticMethod) { throw new ParserException(this.Root.FirstToken, "'this' keyword cannot be used in static methods."); } cd = funcDef.Owner as ClassDefinition; if (cd == null) { throw new ParserException(this.Root.FirstToken, "'this' keyword must be used inside a class."); } } else if (this.Owner is ClassDefinition) { cd = (ClassDefinition)this.Owner; } } if (cd == null) { throw new ParserException(this.Root.FirstToken, "'this' keyword is not allowed here."); } funcDef = cd.GetMethod(field, true); if (funcDef != null) { if (funcDef.IsStaticMethod) { throw new ParserException(this.DotToken, "This method is static and must be referenced by the class name, not 'this'."); } return(new FunctionReference(this.FirstToken, funcDef, this.Owner)); } FieldDeclaration fieldDef = cd.GetField(field, true); if (fieldDef != null) { if (fieldDef.IsStaticField) { throw new ParserException(this.DotToken, "This field is static and must be referenced by the class name, not 'this'."); } return(new FieldReference(this.FirstToken, fieldDef, this.Owner)); } // TODO: show suggestions in the error message for anything close to what was typed. throw new ParserException(this.StepToken, "The class '" + cd.NameToken.Value + "' does not have a field named '" + field + "'."); } // This is done here in the resolver instead of the parser because some unallowed // field names (such as .class) are valid. if (this.StepToken.Value == parser.Keywords.CLASS) { if (this.Root is Variable) { throw new ParserException(this.Root.FirstToken, "'" + ((Variable)this.Root).Name + "' is not a class."); } throw new ParserException(this.DotToken, ".class can only be applied to class names."); } parser.VerifyIdentifier(this.StepToken); return(this); }