/// <summary> /// Process <paramref name="qname"/>. Ensure <paramref name="qname"/> will be fully qualified. /// Outputs <paramref name="fallbackQName"/> which should be used if <paramref name="qname"/> does not refer to any existing entity. /// </summary> /// <param name="qname"></param> /// <param name="fallbackQName"></param> /// <remarks>Used for handling global function call and global constant use. /// In PHP entity in current namespace is tried first, then it falls back to global namespace.</remarks> private void TranslateFallbackQualifiedName(ref QualifiedName qname, out QualifiedName?fallbackQName) { qname = TranslateNamespace(qname); if (!qname.IsFullyQualifiedName && qname.IsSimpleName && !IsInGlobalNamespace && !sourceUnit.HasImportedNamespaces && !reservedTypeNames.Contains(qname.Name.Value)) { // "\foo" fallbackQName = new QualifiedName(qname.Name) { IsFullyQualifiedName = true }; // "namespace\foo" qname = new QualifiedName(qname.Name, currentNamespace.QualifiedName.Namespaces) { IsFullyQualifiedName = true }; } else { fallbackQName = null; qname.IsFullyQualifiedName = true; // just ensure } }
/// <summary> /// Initializes new instance of <see cref="NamingContext"/> /// </summary> public NamingContext(QualifiedName?currentNamespace, Dictionary <string, QualifiedName> aliases) { Debug.Assert(!currentNamespace.HasValue || string.IsNullOrEmpty(currentNamespace.Value.Name.Value)); this.CurrentNamespace = currentNamespace; _aliases = aliases; }
public virtual LangElement Namespace(Span span, QualifiedName?name, Span nameSpan, NamingContext context) { NamespaceDecl space = new NamespaceDecl(span, name.HasValue ? new QualifiedNameRef(nameSpan, name.Value) : QualifiedNameRef.Invalid, true); space.Naming = context; return(space); }
/// <summary> /// Called only by Analyzer. O this instance analyze method will not be called. /// </summary> internal GlobalConstUse(Position position, QualifiedName name, AccessType access) : base(position) { this.access = access; this.name = name; this.fallbackName = null; }
public DirectFcnCall(Position position, QualifiedName qualifiedName, QualifiedName? fallbackQualifiedName, Position qualifiedNamePosition, List<ActualParam>/*!*/ parameters, List<TypeRef>/*!*/ genericParams) : base(position, qualifiedNamePosition, parameters, genericParams) { this.qualifiedName = qualifiedName; this.fallbackQualifiedName = fallbackQualifiedName; }
public DirectFcnCall(Text.Span span, QualifiedName qualifiedName, QualifiedName?fallbackQualifiedName, Text.Span qualifiedNameSpan, IList <ActualParam> parameters, IList <TypeRef> genericParams) : base(span, qualifiedNameSpan, parameters, genericParams) { this.qualifiedName = qualifiedName; this.fallbackQualifiedName = fallbackQualifiedName; }
public DirectFcnCall(Text.Span span, QualifiedName qualifiedName, QualifiedName? fallbackQualifiedName, Text.Span qualifiedNameSpan, List<ActualParam>/*!*/ parameters, List<TypeRef>/*!*/ genericParams) : base(span, qualifiedNameSpan, parameters, genericParams) { this.qualifiedName = qualifiedName; this.fallbackQualifiedName = fallbackQualifiedName; }
/// <summary> /// Creates a node representing an eval-like construct (eval, assert, deferred type). /// </summary> /// <param name="position">Position.</param> /// <param name="code">Source code.</param> /// <param name="currentNamespace">Current namespace to be passed into the transient compilation unit.</param> /// <param name="aliases">Aliases to be passed into the transient compilation unit.</param> /// <remarks> /// Creates a node which actually doesn't exist in the source code but represents a piece of code /// which compilation has been deferred to the run-time. It is used for example when /// a class is declared to be child of a unknown class or interface. /// </remarks> public EvalEx(Position position, string code, QualifiedName?currentNamespace, Dictionary <string, QualifiedName> aliases) : base(position) { this.kind = EvalKinds.SyntheticEval; this.code = new StringLiteral(position, code); this.currentNamespace = currentNamespace; this.aliases = aliases; }
public virtual LangElement Namespace(Span span, QualifiedName?name, Span nameSpan, LangElement block, NamingContext context) { Debug.Assert(block != null); NamespaceDecl space = new NamespaceDecl(span, name.HasValue ? new QualifiedNameRef(nameSpan, name.Value) : QualifiedNameRef.Invalid, false); space.Naming = context; space.Body = (BlockStmt)block; return(space); }
public QualifiedName Prepend(QualifiedName?qualifiedName) { if (qualifiedName is null) { return(this); } return(qualifiedName.Append(this)); }
public void WriteQualifiedName(string?fieldName, QualifiedName?value) { if (value == null) { this.WriteUInt16(null, 0); this.WriteString(null, null); return; } this.WriteUInt16(null, value.NamespaceIndex); this.WriteString(null, value.Name); }
public SourceSymbolContext( IMethod?scope, IAssembly assembly, ImmutableArray <QualifiedName> imports, QualifiedName?nameSpace, Func <ImmutableArray <ITypeParameter> > currentLevelTypeParameters) { Scope = scope; Assembly = assembly; Imports = imports.IsDefault ? throw Release.Fail("imports cannot be default") : imports; NameSpace = nameSpace; CurrentLevelTypeParameters = currentLevelTypeParameters; }
public Variant(QualifiedName?value) { if (value is null) { this.Value = null; this.Type = VariantType.Null; this.ArrayDimensions = null; return; } this.Value = value; this.Type = VariantType.QualifiedName; this.ArrayDimensions = null; }
/// <summary> /// Merges current namespace with the name. /// Returns a qualified name based only on the suffix, if the namespace is <c>null</c>. /// </summary> /// <param name="currentNamespace">Current namespace name, can be <c>null</c>.</param> /// <param name="suffix">Rest of the name, after current namespace.</param> /// <returns>Complete qualified name</returns> QualifiedName MergeWithCurrentNamespace(QualifiedName? currentNamespace, IList<string> suffix) { if (!currentNamespace.HasValue) return new QualifiedName((List<string>)suffix, true, true); QualifiedName currentNS = currentNamespace.Value; Name[] namespaces = new Name[currentNS.Namespaces.Length + suffix.Count - 1]; currentNS.Namespaces.CopyTo(namespaces, 0); for (int i = currentNS.Namespaces.Length; i < namespaces.Length; i++) { namespaces[i] = new Name(suffix[i - currentNS.Namespaces.Length]); // loop otimization } return new QualifiedName(new Name(suffix.Last()), namespaces, true); }
public QualifiedName Append(QualifiedName?qualifiedName) { if (qualifiedName is null) { return(this); } var name = qualifiedName.Name; if (qualifiedName.Parent is null) { return(new QualifiedName(name, this)); } return(new QualifiedName(name, Append(qualifiedName.Parent))); }
public NamingContext(string currentNamespace, int aliases) { // current namespace: if (string.IsNullOrEmpty(currentNamespace)) { this.CurrentNamespace = null; } else { Debug.Assert(currentNamespace.IndexOf(QualifiedName.Separator) != 0); // not starting with separator this.CurrentNamespace = new QualifiedName(currentNamespace.Split(QualifiedName.Separator), false, true); } // aliases (just initialize dictionary, items added later): this.Aliases = (aliases > 0) ? new Dictionary <string, QualifiedName>(aliases) : null; }
public bool Equals(QualifiedName?other) { if (other is null) { return(false); } if (!Name.Equals(other.Name, StringComparison.Ordinal)) { return(false); } if (Parent is null) { return(other.Parent is null); } return(Parent.Equals(other.Parent)); }
//#region Aliases and Imported Namespaces //public bool AddTypeAlias(QualifiedName typeName, Name alias) //{ // if (typeAliases == null) // typeAliases = new Dictionary<Name, QualifiedName>(); // else if (typeAliases.ContainsKey(alias)) // return false; // typeAliases.Add(alias, typeName); // return true; //} //public bool AddFunctionAlias(QualifiedName functionName, Name alias) //{ // if (functionAliases == null) // functionAliases = new Dictionary<Name, QualifiedName>(); // else if (functionAliases.ContainsKey(alias)) // return false; // functionAliases.Add(alias, functionName); // return true; //} //public bool AddConstantAlias(QualifiedName constantName, Name alias) //{ // if (constantAliases == null) // constantAliases = new Dictionary<Name, QualifiedName>(); // else if (constantAliases.ContainsKey(alias)) // return false; // constantAliases.Add(alias, constantName); // return true; //} //public void AddImportedNamespace(QualifiedName namespaceName) //{ // if (importedNamespaces == null) // importedNamespaces = new List<QualifiedName>(); // importedNamespaces.Add(namespaceName); //} /// <summary> /// Used to merge namespaces included by the caller of 'eval' function. /// </summary> /// <param name="namingContext">Naming context of the caller</param> public void AddImportedNamespaces(NamingContext namingContext) { if (namingContext == null) { return; } this.currentNamespace = namingContext.CurrentNamespace; if (namingContext.Aliases != null) { foreach (var alias in namingContext.Aliases) { this.Aliases.Add(alias.Key, alias.Value); } } //foreach (string s in namingContext.Prefixes) //{ // string nsn = s.EndsWith(QualifiedName.Separator.ToString()) ? s.Substring(0, s.Length - QualifiedName.Separator.ToString().Length) : s; // AddImportedNamespace(new QualifiedName(nsn, false)); //} }
/// <summary> /// Emit instantiation and initialization of NamingContext. Leaves reference to new NamingContext on the top of evaluation stack. /// </summary> /// <param name="il"></param> /// <param name="currentNamespace">Namespace to be passed as current namespace to the new instance of <see cref="NamingContext"/>.</param> /// <param name="aliases">Aliases to be passed to the new instance of <see cref="NamingContext"/>.</param> public static void EmitNewNamingContext(Emit.ILEmitter /*!*/ il, QualifiedName?currentNamespace, Dictionary <string, QualifiedName> aliases) { if (!NeedsNamingContext(currentNamespace, aliases)) { il.Emit(OpCodes.Ldnull); return; } // // new NamingContext( currentNamespace.NamespacePhpName, aliases.Count ) if (currentNamespace.HasValue && currentNamespace.Value.Namespaces.Length > 0) { il.Emit(OpCodes.Ldstr, currentNamespace.Value.NamespacePhpName); } else { il.Emit(OpCodes.Ldnull); } il.LdcI4((aliases != null) ? aliases.Count : 0); il.Emit(OpCodes.Newobj, Constructors.NamingContext); // tmp.AddAlias( aliases[i].Key, aliases[i].Value.NamespacePhpName if (aliases != null) { foreach (var alias in aliases) { il.Emit(OpCodes.Dup); // the NamingContext instance il.Emit(OpCodes.Ldstr, alias.Key); // alias il.Emit(OpCodes.Ldstr, alias.Value.ToString()); // qualifiedName il.Emit(OpCodes.Call, Methods.NamingContext.AddAlias); // AddAlias( <alias>, <qualifiedName> ) } } }
public GlobalConstUse(Text.Span span, QualifiedName name, QualifiedName?fallbackName) : base(span) { this.name = name; this.fallbackName = fallbackName; }
/// <summary> /// Builds <see cref="QualifiedName"/> with first element aliased if posible. /// </summary> /// <param name="qname">Qualified name to translate.</param> /// <param name="kind">Type of the translated alias.</param> /// <param name="aliases">Enumeration of aliases.</param> /// <param name="currentNamespace">Current namespace to be prepended if no alias is found.</param> /// <param name="translated">Qualified name that has been tralated according to given naming context.</param> /// <returns>Indication if the name has been translated or not.</returns> public static bool TryTranslateAlias(QualifiedName qname, AliasKind kind, Dictionary <Alias, QualifiedName> aliases, QualifiedName?currentNamespace, out QualifiedName translated) { if (!qname.IsFullyQualifiedName) { // get first part of the qualified name: string first = qname.IsSimpleName ? qname.Name.Value : qname.Namespaces[0].Value; // return the alias if found: QualifiedName alias; if (aliases != null && aliases.TryGetValue(new Alias(first, kind), out alias)) { if (qname.IsSimpleName) { translated = alias; translated.IsFullyQualifiedName = true; } else { // [ alias.namespaces, alias.name, qname.namespaces+1 ] Name[] names = new Name[qname.namespaces.Length + alias.namespaces.Length]; for (int i = 0; i < alias.namespaces.Length; ++i) { names[i] = alias.namespaces[i]; } names[alias.namespaces.Length] = alias.name; for (int j = 1; j < qname.namespaces.Length; ++j) { names[alias.namespaces.Length + j] = qname.namespaces[j]; } translated = new QualifiedName(qname.name, names) { IsFullyQualifiedName = true }; } return(true); } else { if (currentNamespace.HasValue) { Debug.Assert(string.IsNullOrEmpty(currentNamespace.Value.Name.Value)); translated = new QualifiedName(qname, currentNamespace.Value) { IsFullyQualifiedName = true }; return(true); } else { translated = new QualifiedName(qname.Name, qname.Namespaces) { IsFullyQualifiedName = true }; return(false); } } } translated = qname; return(false); }
/// <summary> /// Translates <see cref="QualifiedName"/> according to given naming. /// </summary> public static QualifiedName TranslateAlias(QualifiedName qname, AliasKind kind, Dictionary <Alias, QualifiedName> aliases, QualifiedName?currentNamespace) { QualifiedName translated; TryTranslateAlias(qname, kind, aliases, currentNamespace, out translated); return(translated); }
public TranslatedQualifiedName(QualifiedName name, Span nameSpan, QualifiedName originalName, QualifiedName?nameFallback) { _name = new QualifiedNameRef(nameSpan, name); _originalName = originalName; _fallbackName = nameFallback; }
/// <summary> /// Initializes new instance of <see cref="NamingContext"/> /// </summary> public NamingContext(QualifiedName?currentNamespace) { Debug.Assert(!currentNamespace.HasValue || string.IsNullOrEmpty(currentNamespace.Value.Name.Value), "Valid namespace QualifiedName has no base name."); this.CurrentNamespace = currentNamespace; }
public QualifiedName(string name, QualifiedName?parent = null) { Name = name; Parent = parent; }
internal void EnterNamespace(NamespaceDecl ns) { Debug.Assert(!currentNamespace.HasValue, "Namespace nesting not supported"); currentNamespace = ns.QualifiedName; }
public DConstant ResolveConstantName(QualifiedName qualifiedName, Scope currentScope, out QualifiedName?alias, ErrorSink errors, Position position, bool mustResolve) { return((DConstant)ResolveName(qualifiedName, DeclarationKind.Constant, currentScope, out alias, errors, position, mustResolve)); }
public override LangElement Namespace(Span span, QualifiedName?name, Span nameSpan, LangElement block, NamingContext context) => CountLE(base.Namespace(span, name, nameSpan, block, context));
/// <summary> /// Creates a node representing an eval-like construct (eval, assert, deferred type). /// </summary> /// <param name="position">Position.</param> /// <param name="code">Source code.</param> /// <param name="currentNamespace">Current namespace to be passed into the transient compilation unit.</param> /// <param name="aliases">Aliases to be passed into the transient compilation unit.</param> /// <remarks> /// Creates a node which actually doesn't exist in the source code but represents a piece of code /// which compilation has been deferred to the run-time. It is used for example when /// a class is declared to be child of a unknown class or interface. /// </remarks> public EvalEx(Position position, string code, QualifiedName? currentNamespace, Dictionary<string,QualifiedName> aliases) : base(position) { this.kind = EvalKinds.SyntheticEval; this.code = new StringLiteral(position, code); this.currentNamespace = currentNamespace; this.aliases = aliases; }
public BoundGlobalFunctionCall(QualifiedName name, QualifiedName?nameOpt, ImmutableArray <BoundArgument> arguments) : base(arguments) { _name = new BoundRoutineName(name); _nameOpt = nameOpt; }
public GlobalConstUse(Position position, QualifiedName name, QualifiedName? fallbackName) : base(position) { this.name = name; this.fallbackName = fallbackName; }
public GlobalConstUse(Text.Span span, QualifiedName name, QualifiedName? fallbackName) : base(span) { this.name = name; this.fallbackName = fallbackName; }
//#endregion #region Name Resolving /// <summary> /// Resolves a function or type name using aliases and imported namespaces of the source unit. /// </summary> /// <param name="qualifiedName">Function qualified name to resolve. Doesn't resolve special names ("self", "parent").</param> /// <param name="kind">Declaration kind.</param> /// <param name="currentScope">Current scope.</param> /// <param name="alias"> /// <B>null</B>, if the function name is resolved immediately. /// Otherwise, if the <paramref name="qualifiedName"/> is simple and an alias exists, contains its qualified target. /// </param> /// <param name="errors">Error sink or <B>null</B> if errors shouldn't be reported.</param> /// <param name="position">Position where to report an error.</param> /// <param name="mustResolve">Whether name must be resolved if possible.</param> /// <returns> /// Resolved member, the unknown member, or <B>null</B> if error reporting is disabled (errors == null). /// </returns> /// <remarks> /// If the name is simple, is not resolved and has an alias then the run-time resolve should be run on the alias. /// If the name is simple, is not resolved and hasn't an alias, the run-time resolve should be run on the name /// within the naming context of the source unit (i.e. imported namespaces should be considered). /// If the name is fully qualified and is not resolved then then the run-time resolve should be run on the name itself. /// </remarks> private DMember ResolveName(QualifiedName qualifiedName, DeclarationKind kind, Scope currentScope, out QualifiedName?alias, ErrorSink errors, Position position, bool mustResolve) { string full_name = null; DMember result; alias = null; // try exact match: result = ResolveExactName(qualifiedName, ref full_name, kind, currentScope, mustResolve); if (result != null) { return(result); } /* // aliases are resolved in parse-time * // try explicit aliases: * if (qualifiedName.IsSimpleName) * { * QualifiedName alias_qualified_name; * * Dictionary<Name, QualifiedName> aliases = null; * switch (kind) * { * case DeclarationKind.Type: aliases = typeAliases; break; * case DeclarationKind.Function: aliases = functionAliases; break; * case DeclarationKind.Constant: aliases = constantAliases; break; * } * * // try alias: * if (aliases != null && aliases.TryGetValue(qualifiedName.Name, out alias_qualified_name)) * { * // alias exists // * * full_name = null; * result = ResolveExactName(alias_qualified_name, ref full_name, kind, currentScope, mustResolve); * if (result != null) * return result; * * alias = alias_qualified_name; * * switch (kind) * { * case DeclarationKind.Type: result = new UnknownType(full_name); break; * case DeclarationKind.Function: result = new UnknownFunction(full_name); break; * case DeclarationKind.Constant: result = new UnknownGlobalConstant(full_name); break; * } * * return result; * } * } */ // try imported namespaces: if (!qualifiedName.IsFullyQualifiedName && HasImportedNamespaces) { result = null; foreach (QualifiedName imported_ns in importedNamespaces) { QualifiedName combined_qualified_name = new QualifiedName(qualifiedName, imported_ns); full_name = null; DMember candidate = ResolveExactName(combined_qualified_name, ref full_name, kind, currentScope, mustResolve); if (candidate != null) { if (result != null) { if (errors != null) { ErrorInfo error; switch (kind) { case DeclarationKind.Type: error = Errors.AmbiguousTypeMatch; break; case DeclarationKind.Function: error = Errors.AmbiguousFunctionMatch; break; case DeclarationKind.Constant: error = Errors.AmbiguousConstantMatch; break; default: throw null; } errors.Add(error, this, position, result.FullName, candidate.FullName, qualifiedName.Name); } } else { result = candidate; } } } if (result != null) { return(result); } } // unknown qualified name: if (errors != null) { switch (kind) { case DeclarationKind.Type: result = new UnknownType(qualifiedName.ToString()); break; case DeclarationKind.Function: result = new UnknownFunction(qualifiedName.ToString()); break; case DeclarationKind.Constant: result = new UnknownGlobalConstant(qualifiedName.ToString()); break; } return(result); } return(null); }
internal void LeaveNamespace() { currentNamespace = null; }
/// <summary> /// Determine if <see cref="NamingContext "/> is needed for the current namespace and aliases. /// </summary> /// <param name="currentNamespace"></param> /// <param name="aliases"></param> /// <returns>True if current namespace is not global namespace or there are some aliases.</returns> public static bool NeedsNamingContext(QualifiedName?currentNamespace, Dictionary <string, QualifiedName> aliases) { return ((currentNamespace.HasValue && currentNamespace.Value.Namespaces.Length > 0) || (aliases != null && aliases.Count > 0)); }
public DType ResolveTypeName(QualifiedName qualifiedName, Scope currentScope, out QualifiedName?alias, ErrorSink errors, Position position, bool mustResolve) { return((DType)ResolveName(qualifiedName, DeclarationKind.Type, currentScope, out alias, errors, position, mustResolve)); }
//internal static QualifiedName Parse(string/*!*/ buffer, int startIndex, int length, bool hasBaseName) //{ // Debug.Assert(buffer != null && startIndex >= 0 && startIndex <= buffer.Length - length); // QualifiedName result = new QualifiedName(); // // handle fully qualified namespace name: // if (length > 0 && buffer[startIndex] == Separator) // { // result.isFullyQualifiedName = true; // startIndex++; // length--; // } // // names separated by Separator: // int slash_count = 0; // for (int i = startIndex; i < startIndex + length; i++) // if (buffer[i] == Separator) slash_count++; // int separator_count = slash_count;// / Separator.ToString().Length; // //Debug.Assert(slash_count % Separator.Length == 0); // if (separator_count == 0) // { // Name entire_name = new Name(buffer.Substring(startIndex, length)); // if (hasBaseName) // { // result.namespaces = Name.EmptyNames; // result.name = entire_name; // } // else // { // result.namespaces = new Name[] { entire_name }; // result.name = Name.EmptyBaseName; // } // } // else // { // result.namespaces = new Name[separator_count + (hasBaseName ? 0 : 1)]; // int current_name = startIndex; // int next_separator = startIndex; // int i = 0; // do // { // while (buffer[next_separator] != Separator) // next_separator++; // result.namespaces[i++] = new Name(buffer.Substring(current_name, next_separator - current_name)); // next_separator += Separator.ToString().Length; // current_name = next_separator; // } // while (i < separator_count); // Name base_name = new Name(buffer.Substring(current_name, length - current_name)); // if (hasBaseName) // { // result.name = base_name; // } // else // { // result.namespaces[separator_count] = base_name; // result.name = Name.EmptyBaseName; // } // } // return result; //} /// <summary> /// Builds <see cref="QualifiedName"/> with first element aliased if posible. /// </summary> /// <param name="qname"></param> /// <param name="aliases"></param> /// <param name="currentNamespace">Current namespace to be prepended if no alias if found.</param> /// <returns></returns> internal static QualifiedName TranslateAlias(QualifiedName qname, Dictionary <string, QualifiedName> /*!*/ aliases, QualifiedName?currentNamespace) { if (qname.IsFullyQualifiedName) { return(qname); } // get first part of the qualified name: string first = qname.IsSimpleName ? qname.Name.Value : qname.Namespaces[0].Value; // return the alias if found: QualifiedName alias; if (aliases.TryGetValue(first, out alias)) { if (qname.IsSimpleName) { return(alias); } // [ alias.namespaces, alias.name, qname.namespaces+1 ] Name[] names = new Name[qname.namespaces.Length + alias.namespaces.Length]; for (int i = 0; i < alias.namespaces.Length; ++i) { names[i] = alias.namespaces[i]; } names[alias.namespaces.Length] = alias.name; for (int j = 1; j < qname.namespaces.Length; ++j) { names[alias.namespaces.Length + j] = qname.namespaces[j]; } return(new QualifiedName(qname.name, names) { IsFullyQualifiedName = true }); } else { if (currentNamespace.HasValue) { Debug.Assert(string.IsNullOrEmpty(currentNamespace.Value.Name.Value)); return(new QualifiedName(qname, currentNamespace.Value)); } else { return(qname); } } }
/// <summary> /// Used to merge namespaces included by the caller of 'eval' function. /// </summary> /// <param name="namingContext">Naming context of the caller</param> public void AddImportedNamespaces(NamingContext namingContext) { if (namingContext == null) return; this.currentNamespace = namingContext.CurrentNamespace; if (namingContext.Aliases != null) foreach (var alias in namingContext.Aliases) this.Aliases.Add(alias.Key, alias.Value); }