/Microsoft.Scripting/Actions/CallSignature.cs
C# | 333 lines | 240 code | 58 blank | 35 comment | 77 complexity | 65287e634ed938897676b69ee0c60395 MD5 | raw file
- /* ****************************************************************************
- *
- * Copyright (c) Microsoft Corporation.
- *
- * This source code is subject to terms and conditions of the Microsoft Public License. A
- * copy of the license can be found in the License.html file at the root of this distribution. If
- * you cannot locate the Microsoft Public License, please send an email to
- * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
- * by the terms of the Microsoft Public License.
- *
- * You must not remove this notice, or any other, from this software.
- *
- *
- * ***************************************************************************/
-
- #if CODEPLEX_40
- using System;
- #else
- using System; using Microsoft;
- #endif
- using System.Collections.Generic;
- using System.Diagnostics;
- #if CODEPLEX_40
- using System.Linq.Expressions;
- #else
- using Microsoft.Linq.Expressions;
- #endif
- using Microsoft.Scripting.Utils;
- using System.Text;
- using Microsoft.Contracts;
- using Microsoft.Scripting.Generation;
- using AstUtils = Microsoft.Scripting.Ast.Utils;
-
- namespace Microsoft.Scripting.Actions {
- /// <summary>
- /// Richly represents the signature of a callsite.
- /// </summary>
- public struct CallSignature : IEquatable<CallSignature> {
- // TODO: invariant _infos != null ==> _argumentCount == _infos.Length
-
- /// <summary>
- /// Array of additional meta information about the arguments, such as named arguments.
- /// Null for a simple signature that's just an expression list. eg: foo(a*b,c,d)
- /// </summary>
- private readonly Argument[] _infos;
-
- /// <summary>
- /// Number of arguments in the signature.
- /// </summary>
- private readonly int _argumentCount;
-
- /// <summary>
- /// All arguments are unnamed and matched by position.
- /// </summary>
- public bool IsSimple {
- get { return _infos == null; }
- }
-
- public int ArgumentCount {
- get {
- Debug.Assert(_infos == null || _infos.Length == _argumentCount);
- return _argumentCount;
- }
- }
-
- #region Construction
-
- public CallSignature(CallSignature signature) {
- _infos = signature.GetArgumentInfos();
- _argumentCount = signature._argumentCount;
- }
-
- public CallSignature(int argumentCount) {
- ContractUtils.Requires(argumentCount >= 0, "argumentCount");
- _argumentCount = argumentCount;
- _infos = null;
- }
-
- public CallSignature(params Argument[] infos) {
- bool simple = true;
-
- if (infos != null) {
- _argumentCount = infos.Length;
- for (int i = 0; i < infos.Length; i++) {
- if (infos[i].Kind != ArgumentType.Simple) {
- simple = false;
- break;
- }
- }
- } else {
- _argumentCount = 0;
- }
-
- _infos = (!simple) ? infos : null;
- }
-
- public CallSignature(params ArgumentType[] kinds) {
- bool simple = true;
-
- if (kinds != null) {
- _argumentCount = kinds.Length;
- for (int i = 0; i < kinds.Length; i++) {
- if (kinds[i] != ArgumentType.Simple) {
- simple = false;
- break;
- }
- }
- } else {
- _argumentCount = 0;
- }
-
- if (!simple) {
- _infos = new Argument[kinds.Length];
- for (int i = 0; i < kinds.Length; i++) {
- _infos[i] = new Argument(kinds[i]);
- }
- } else {
- _infos = null;
- }
- }
-
- #endregion
-
- #region IEquatable<CallSignature> Members
-
- [StateIndependent]
- public bool Equals(CallSignature other) {
- if (_infos == null) {
- return other._infos == null && other._argumentCount == _argumentCount;
- } else if (other._infos == null) {
- return false;
- }
-
- if (_infos.Length != other._infos.Length) return false;
-
- for (int i = 0; i < _infos.Length; i++) {
- if (!_infos[i].Equals(other._infos[i])) return false;
- }
-
- return true;
- }
-
- #endregion
-
- #region Overrides
-
- public override bool Equals(object obj) {
- return obj is CallSignature && Equals((CallSignature)obj);
- }
-
- public static bool operator ==(CallSignature left, CallSignature right) {
- return left.Equals(right);
- }
-
- public static bool operator !=(CallSignature left, CallSignature right) {
- return !left.Equals(right);
- }
-
- public override string ToString() {
- if (_infos == null) {
- return "Simple";
- }
-
- StringBuilder sb = new StringBuilder("(");
- for (int i = 0; i < _infos.Length; i++) {
- if (i > 0) {
- sb.Append(", ");
- }
- sb.Append(_infos[i].ToString());
- }
- sb.Append(")");
- return sb.ToString();
- }
-
- public override int GetHashCode() {
- int h = 6551;
- if (_infos != null) {
- foreach (Argument info in _infos) {
- h ^= (h << 5) ^ info.GetHashCode();
- }
- }
- return h;
- }
-
- #endregion
-
- #region Helpers
-
- public Argument[] GetArgumentInfos() {
- return (_infos != null) ? ArrayUtils.Copy(_infos) : CompilerHelpers.MakeRepeatedArray(Argument.Simple, _argumentCount);
- }
-
- public CallSignature InsertArgument(Argument info) {
- return InsertArgumentAt(0, info);
- }
-
- public CallSignature InsertArgumentAt(int index, Argument info) {
- if (this.IsSimple) {
- if (info.IsSimple) {
- return new CallSignature(_argumentCount + 1);
- }
-
- return new CallSignature(ArrayUtils.InsertAt(GetArgumentInfos(), index, info));
- }
-
- return new CallSignature(ArrayUtils.InsertAt(_infos, index, info));
- }
-
- public CallSignature RemoveFirstArgument() {
- return RemoveArgumentAt(0);
- }
-
- public CallSignature RemoveArgumentAt(int index) {
- if (_argumentCount == 0) {
- throw new InvalidOperationException();
- }
-
- if (IsSimple) {
- return new CallSignature(_argumentCount - 1);
- }
-
- return new CallSignature(ArrayUtils.RemoveAt(_infos, index));
- }
-
- public int IndexOf(ArgumentType kind) {
- if (_infos == null) {
- return (kind == ArgumentType.Simple && _argumentCount > 0) ? 0 : -1;
- }
-
- for (int i = 0; i < _infos.Length; i++) {
- if (_infos[i].Kind == kind) {
- return i;
- }
- }
- return -1;
- }
-
- public bool HasDictionaryArgument() {
- return IndexOf(ArgumentType.Dictionary) > -1;
- }
-
- public bool HasInstanceArgument() {
- return IndexOf(ArgumentType.Instance) > -1;
- }
-
- public bool HasListArgument() {
- return IndexOf(ArgumentType.List) > -1;
- }
-
- internal bool HasNamedArgument() {
- return IndexOf(ArgumentType.Named) > -1;
- }
-
- /// <summary>
- /// True if the OldCallAction includes an ArgumentInfo of ArgumentKind.Dictionary or ArgumentKind.Named.
- /// </summary>
- public bool HasKeywordArgument() {
- if (_infos != null) {
- foreach (Argument info in _infos) {
- if (info.Kind == ArgumentType.Dictionary || info.Kind == ArgumentType.Named) {
- return true;
- }
- }
- }
- return false;
- }
-
- public ArgumentType GetArgumentKind(int index) {
- // TODO: Contract.Requires(index >= 0 && index < _argumentCount, "index");
- return _infos != null ? _infos[index].Kind : ArgumentType.Simple;
- }
-
- public string GetArgumentName(int index) {
- ContractUtils.Requires(index >= 0 && index < _argumentCount);
- return _infos != null ? _infos[index].Name : null;
- }
-
- /// <summary>
- /// Gets the number of positional arguments the user provided at the call site.
- /// </summary>
- [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")]
- public int GetProvidedPositionalArgumentCount() {
- int result = _argumentCount;
-
- if (_infos != null) {
- for (int i = 0; i < _infos.Length; i++) {
- ArgumentType kind = _infos[i].Kind;
-
- if (kind == ArgumentType.Dictionary || kind == ArgumentType.List || kind == ArgumentType.Named) {
- result--;
- }
- }
- }
-
- return result;
- }
-
- public string[] GetArgumentNames() {
- if (_infos == null) {
- return ArrayUtils.EmptyStrings;
- }
-
- List<string> result = new List<string>();
- foreach (Argument info in _infos) {
- if (info.Name != null) {
- result.Add(info.Name);
- }
- }
-
- return result.ToArray();
- }
-
- public Expression CreateExpression() {
- if (_infos == null) {
- return Expression.New(
- typeof(CallSignature).GetConstructor(new Type[] { typeof(int) }),
- AstUtils.Constant(ArgumentCount)
- );
- } else {
- Expression[] args = new Expression[_infos.Length];
- for (int i = 0; i < args.Length; i++) {
- args[i] = _infos[i].CreateExpression();
- }
- return Expression.New(
- typeof(CallSignature).GetConstructor(new Type[] { typeof(Argument[]) }),
- Expression.NewArrayInit(typeof(Argument), args)
- );
- }
- }
-
- #endregion
- }
- }