#region Copyright // -------------------------------------------------------------------------------------------------------------------- // // Copyright (C) 2015 Ian Horswill // // Permission is hereby granted, free of charge, to any person obtaining a copy of // this software and associated documentation files (the "Software"), to deal in the // Software without restriction, including without limitation the rights to use, copy, // modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, // and to permit persons to whom the Software is furnished to do so, subject to the // following conditions: // // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // // -------------------------------------------------------------------------------------------------------------------- #endregion using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; namespace Prolog { /// /// A Lisp Symbol /// [Documentation("The class of LISP symbols.")] public sealed class Symbol : Term { #region Fields and Properties /// /// The printed representation of the symbol /// [SuppressMessage("Microsoft.Design", "CA1051:DoNotDeclareVisibleInstanceFields")] [Documentation("Printed representation of the symbol.")] public readonly string Name; /// /// The keyword name without the trailing colon. /// [Documentation("The keyword name without the trailing colon.")] public string KeywordName { get { return Name.TrimEnd(':'); } } /// /// True if this is a keyword symbol. Keywords are self-evaluating. /// [Documentation("True if this is a keyword symbol, i.e. ends with a colon. Keywords are self-evaluating.")] public bool IsKeyword { get { return Name.EndsWith(":"); } } /// /// True if this is a pattern variable. /// [Documentation("True if this is a pattern variable, either in traditional lisp format (starts with a '?') or Prolog format (starts with a captial letter or '_').")] public bool IsPatternVariable { get { return Name.StartsWith("?") || Name[0] == '_' || char.IsUpper(Name[0]); } } #endregion #region Printing /// /// Prints the name of the symbol. /// public override string ToString() { return Name; } #endregion #region Interning and symbol table static readonly Dictionary SymbolTable = new Dictionary(); /// /// Returns the symbol with the specified name. /// Creates a new symbol if necessary, but always returns the same object /// when called with the same string. /// [Documentation("Returns the unique symbol iwth the specified name.")] public static Symbol Intern(string name) { Symbol s; SymbolTable.TryGetValue(name, out s); if (s != null) return s; // Constructor adds to symbol table automatically return new Symbol(name); } /// /// True if the string names a symbol in the symbol table. Does not intern a new symbol. /// /// Name of the symbol to search for /// True if there is a symbol by that name. public static bool IsInterned(string name) { return SymbolTable.ContainsKey(name); } #endregion #region Constructor - private - Symbol(string name) { //Prolog allows null atoms, alas. //System.Diagnostics.Debug.Assert(!string.IsNullOrEmpty(name)); Name = name; SymbolTable[name] = this; } #endregion #region Unification internal override IEnumerable UnifyWithTerm(Term value) { return value.UnifyWithAtomicConstant(this); } internal override bool UnifyWithTerm(Term value, PrologContext context) { return value.UnifyWithAtomicConstant(this, context); } #endregion #region Symbol constants /// /// The symbol 'quote /// [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")] public static readonly Symbol Quote = Intern("quote"); /// /// The symbol 'quasiquote /// [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")] [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Quasiquote")] public static readonly Symbol Quasiquote = Intern("quasiquote"); /// /// The symbol 'unquote /// [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")] public static readonly Symbol Unquote = Intern("unquote"); /// /// The symbol 'unquote-splicing /// [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")] public static readonly Symbol UnquoteSplicing = Intern("unquote-splicing"); /// /// The symbol 'lambda /// [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")] public static readonly Symbol Lambda = Intern("lambda"); /// /// The symbol 'member /// [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")] public static readonly Symbol Member = Intern("member"); /// /// The symbol 'macroexpand /// [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")] [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Macroexpand")] public static readonly Symbol Macroexpand = Intern("macroexpand"); /// /// The symbol 'else /// [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")] public static readonly Symbol Else = Intern("else"); /// /// The symbol 'if /// [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")] public static readonly Symbol If = Intern("if"); /// /// The symbol 'begin /// [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")] public static readonly Symbol Begin = Intern("begin"); /// /// The symbol 'set! /// [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")] public static readonly Symbol SetBang = Intern("set!"); /// /// The symbol 'define /// [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")] public static readonly Symbol Define = Intern("define"); /// /// The symbol 'let /// [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")] public static readonly Symbol Let = Intern("let"); /// /// The symbol 'new /// [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")] public static readonly Symbol New = Intern("new"); /// /// The symbol 'not /// [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")] public static readonly Symbol Not = Intern("not"); /// /// The symbol 'list /// [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")] public static readonly Symbol List = Intern("list"); /// /// The symbol 'append /// [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")] public static readonly Symbol Append = Intern("append"); /// /// The symbol 'this /// [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")] public static readonly Symbol This = Intern("this"); /// /// The symbol 'stack /// [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")] public static readonly Symbol Stack = Intern("stack"); /// /// The symbol '... /// [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")] public static readonly Symbol Ellipsis = Intern("..."); /// /// The symbol 'Object /// [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")] public static readonly Symbol Object = Intern("Object"); /// /// The Prolog symbol ',' /// [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")] public static readonly Symbol Comma = Intern(","); /// /// The symbol '=' /// [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")] public static readonly Symbol EqualSign = Intern("="); /// /// The Prolog symbol '|' /// [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")] public static readonly Symbol VerticalBar = Intern("|"); /// /// The Prolog symbol ':-' /// [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")] public static readonly Symbol Implication = Intern(":-"); /// /// The Prolog symbol '.' /// [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")] public static readonly Symbol PrologListConstructor = Intern("cons"); /// /// The Prolog symbol '.' /// [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")] public static readonly Symbol Dot = Intern("."); /// /// The Prolog symbol '!' /// [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")] public static readonly Symbol Cut = Intern("!"); /// /// The Prolog symbol 'call' /// [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")] public static readonly Symbol Call = Intern("call"); /// /// The Prolog symbol 'fail' /// [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")] public static readonly Symbol Fail = Intern("fail"); /// /// The Prolog symbol 'true' /// [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")] public static readonly Symbol True = Intern("true"); /// /// The Prolog symbol '{}' /// [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")] public static readonly Symbol CurlyBrackets = Intern("{}"); /// /// The Prolog symbol '-->' /// [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")] public static readonly Symbol GrammarRule = Intern("-->"); /// /// The Prolog symbol '$' /// [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")] public static readonly Symbol DollarSign = Intern("$"); /// /// The Prolog symbol 'end_of_file' /// [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")] public static readonly Symbol EndOfFile = Intern("end_of_file"); /// /// The division symbol, '/' /// [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")] public static readonly Symbol Slash = Intern("/"); /// /// The grammar rule predicate indicator symbol, '//' /// [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")] public static readonly Symbol SlashSlash = Intern("//"); /// /// The symbol 'maplist' /// [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")] public static readonly Symbol MapList = Intern("maplist"); /// /// The Prolog symbol ';' /// [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")] public static readonly Symbol Semicolon = Intern(";"); /// /// The Prolog symbol '->' /// [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")] public static readonly Symbol IfThenArrow = Intern("->"); /// /// The Prolog symbol ':' /// [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")] public static readonly Symbol Colon = Intern(":"); /// /// The Prolog symbol 'global' /// [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")] public static readonly Symbol Global = Intern("global"); /// /// The Prolog symbol '-' /// public static readonly Symbol Minus = Intern("-"); /// /// The Prolog symbol '::' /// public static readonly Symbol ColonColon = Intern("::"); /// /// The Prolog symbol '::' /// public static readonly Symbol Text = Intern("text"); #endregion } }