public class Parameter {
[Flags]
public enum Modifier : byte {
- NONE = 0,
- REF = 1,
- OUT = 2,
- PARAMS = 4,
+ NONE = 0,
+ REF = 1,
+ OUT = 2,
+ PARAMS = 4,
+ // This is a flag which says that it's either REF or OUT.
+ ISBYREF = 8
}
- public readonly string TypeName;
- public readonly string Name;
+ public readonly Expression TypeName;
public readonly Modifier ModFlags;
public Attributes OptAttributes;
- public Type ParameterType;
+ public readonly string Name;
+ public Type parameter_type;
- public Parameter (string type, string name, Modifier mod, Attributes attrs)
+ public Parameter (Expression type, string name, Modifier mod, Attributes attrs)
{
Name = name;
ModFlags = mod;
OptAttributes = attrs;
}
- public bool Resolve (DeclSpace ds)
+ // <summary>
+ // Resolve is used in method definitions
+ // </summary>
+ public bool Resolve (DeclSpace ds, Location l)
{
- ParameterType = ds.LookupType (TypeName, false);
- return ParameterType != null;
+ parameter_type = ds.ResolveType (TypeName, false, l);
+
+ if (parameter_type == TypeManager.void_type){
+ Report.Error (1536, l, "`void' parameter is not permitted");
+ return false;
+ }
+
+ return parameter_type != null;
}
- public Type ExternalType ()
+ public Type ExternalType (DeclSpace ds, Location l)
{
- if ((ModFlags & (Parameter.Modifier.REF | Parameter.Modifier.OUT)) != 0){
- string n = ParameterType.FullName + "&";
- Type t;
-
- t = Type.GetType (n);
-
- //
- // It is a type defined by the source code we are compiling
- //
- if (t == null){
- ModuleBuilder mb = RootContext.ModuleBuilder;
-
- t = mb.GetType (n);
- }
+ if ((ModFlags & Parameter.Modifier.ISBYREF) != 0)
+ return TypeManager.GetReferenceType (parameter_type);
+
+ return parameter_type;
+ }
- return t;
+ public Type ParameterType {
+ get {
+ return parameter_type;
}
-
- return ParameterType;
}
public ParameterAttributes Attributes {
get {
- switch (ModFlags){
+ int flags = ((int) ModFlags) & ~((int) Parameter.Modifier.ISBYREF);
+ switch ((Modifier) flags) {
case Modifier.NONE:
return ParameterAttributes.None;
case Modifier.REF:
/// Returns the signature for this parameter evaluating it on the
/// @tc context
/// </summary>
- public string GetSignature (DeclSpace ds)
+ public string GetSignature (DeclSpace ds, Location loc)
{
- if (ParameterType == null){
- if (!Resolve (ds))
+ if (parameter_type == null){
+ if (!Resolve (ds, loc))
return null;
}
- return ExternalType ().FullName;
+ return ExternalType (ds, loc).FullName;
}
}
public readonly Parameter ArrayParameter;
string signature;
Type [] types;
+ Location loc;
static Parameters empty_parameters;
- public Parameters (Parameter [] fixed_parameters, Parameter array_parameter)
+ public Parameters (Parameter [] fixed_parameters, Parameter array_parameter, Location l)
{
FixedParameters = fixed_parameters;
ArrayParameter = array_parameter;
+ loc = l;
}
/// <summary>
/// This is used to reuse a set of empty parameters, because they
/// are common
/// </summary>
- public static Parameters GetEmptyReadOnlyParameters ()
- {
- if (empty_parameters == null)
- empty_parameters = new Parameters (null, null);
+ public static Parameters EmptyReadOnlyParameters {
+ get {
+ if (empty_parameters == null)
+ empty_parameters = new Parameters (null, null, Location.Null);
- return empty_parameters;
+ return empty_parameters;
+ }
}
public bool Empty {
}
}
- public void ComputeSignature (TypeContainer tc)
+ public void ComputeSignature (DeclSpace ds)
{
signature = "";
if (FixedParameters != null){
for (int i = 0; i < FixedParameters.Length; i++){
Parameter par = FixedParameters [i];
- signature += par.GetSignature (tc);
+ signature += par.GetSignature (ds, loc);
}
}
//
//
}
- public bool VerifyArgs (TypeContainer tc)
+ static void Error_DuplicateParameterName (string name)
+ {
+ Report.Error (
+ 100, "The parameter name `" + name + "' is a duplicate");
+ }
+
+ public bool VerifyArgs ()
{
int count;
int i, j;
return true;
count = FixedParameters.Length;
+ string array_par_name = ArrayParameter != null ? ArrayParameter.Name : null;
for (i = 0; i < count; i++){
+ string base_name = FixedParameters [i].Name;
+
for (j = i + 1; j < count; j++){
- if (FixedParameters [i].Name != FixedParameters [j].Name)
+ if (base_name != FixedParameters [j].Name)
continue;
- Report.Error (
- 100, "The parameter name `" + FixedParameters [i].Name +
- "' is a duplicate");
+ Error_DuplicateParameterName (base_name);
+ return false;
+ }
+
+ if (base_name == array_par_name){
+ Error_DuplicateParameterName (base_name);
return false;
}
}
/// Returns the signature of the Parameters evaluated in
/// the @tc environment
/// </summary>
- public string GetSignature (TypeContainer tc)
+ public string GetSignature (DeclSpace ds)
{
if (signature == null){
- VerifyArgs (tc);
- ComputeSignature (tc);
+ VerifyArgs ();
+ ComputeSignature (ds);
}
return signature;
public Parameter GetParameterByName (string name, out int idx)
{
idx = 0;
-
- if (FixedParameters == null)
- return null;
-
int i = 0;
- foreach (Parameter par in FixedParameters){
- if (par.Name == name){
- idx = i;
- return par;
+
+ if (FixedParameters != null){
+ foreach (Parameter par in FixedParameters){
+ if (par.Name == name){
+ idx = i;
+ return par;
+ }
+ i++;
}
- i++;
}
- if (ArrayParameter != null)
+ if (ArrayParameter != null){
if (name == ArrayParameter.Name){
idx = i;
return ArrayParameter;
}
+ }
return null;
}
- bool ComputeParameterTypes (TypeContainer tc)
+ bool ComputeParameterTypes (DeclSpace ds)
{
int extra = (ArrayParameter != null) ? 1 : 0;
int i = 0;
- int pc = FixedParameters.Length + extra;
-
+ int pc;
+
+ if (FixedParameters == null)
+ pc = extra;
+ else
+ pc = extra + FixedParameters.Length;
+
types = new Type [pc];
- if (!VerifyArgs (tc)){
+ if (!VerifyArgs ()){
FixedParameters = null;
return false;
}
+
+ bool failed = false;
+ if (FixedParameters != null){
+ foreach (Parameter p in FixedParameters){
+ Type t = null;
+
+ if (p.Resolve (ds, loc))
+ t = p.ExternalType (ds, loc);
+ else
+ failed = true;
+
+ types [i] = t;
+ i++;
+ }
+ }
+
+ if (extra > 0){
+ if (ArrayParameter.Resolve (ds, loc))
+ types [i] = ArrayParameter.ExternalType (ds, loc);
+ else
+ failed = true;
+ }
+
+ if (failed){
+ types = null;
+ return false;
+ }
+
+ return true;
+ }
+
+ //
+ // This variant is used by Delegates, because they need to
+ // resolve/define names, instead of the plain LookupType
+ //
+ public bool ComputeAndDefineParameterTypes (DeclSpace ds)
+ {
+ int extra = (ArrayParameter != null) ? 1 : 0;
+ int i = 0;
+ int pc;
+
+ if (FixedParameters == null)
+ pc = extra;
+ else
+ pc = extra + FixedParameters.Length;
- foreach (Parameter p in FixedParameters){
- Type t = null;
-
- if (p.Resolve (tc))
- t = p.ExternalType ();
-
- types [i] = t;
- i++;
+ types = new Type [pc];
+
+ if (!VerifyArgs ()){
+ FixedParameters = null;
+ return false;
}
+ bool ok_flag = true;
+
+ if (FixedParameters != null){
+ foreach (Parameter p in FixedParameters){
+ Type t = null;
+
+ if (p.Resolve (ds, loc))
+ t = p.ExternalType (ds, loc);
+ else
+ ok_flag = false;
+
+ types [i] = t;
+ i++;
+ }
+ }
+
if (extra > 0){
- if (ArrayParameter.Resolve (tc))
- types [i] = ArrayParameter.ExternalType ();
+ if (ArrayParameter.Resolve (ds, loc))
+ types [i] = ArrayParameter.ExternalType (ds, loc);
+ else
+ ok_flag = false;
}
- return true;
+ //
+ // invalidate the cached types
+ //
+ if (!ok_flag){
+ types = null;
+ }
+
+ return ok_flag;
}
/// <summary>
/// </summary>
static Type [] no_types = new Type [0];
- public Type [] GetParameterInfo (TypeContainer tc)
+ public Type [] GetParameterInfo (DeclSpace ds)
{
if (types != null)
return types;
- if (FixedParameters == null)
+ if (FixedParameters == null && ArrayParameter == null)
return no_types;
- if (ComputeParameterTypes (tc) == false)
+ if (ComputeParameterTypes (ds) == false){
+ types = null;
return null;
-
+ }
+
return types;
}
/// Note that the returned type will not contain any dereference in this
/// case (ie, you get "int" for a ref int instead of "int&"
/// </summary>
- public Type GetParameterInfo (TypeContainer tc, int idx, out bool is_out)
+ public Type GetParameterInfo (DeclSpace ds, int idx, out Parameter.Modifier mod)
{
- is_out = false;
+ mod = Parameter.Modifier.NONE;
- if (!VerifyArgs (tc)){
+ if (!VerifyArgs ()){
FixedParameters = null;
return null;
}
- if (FixedParameters == null)
+ if (FixedParameters == null && ArrayParameter == null)
return null;
if (types == null)
- if (ComputeParameterTypes (tc) == false){
- is_out = false;
+ if (ComputeParameterTypes (ds) == false)
return null;
- }
//
// If this is a request for the variable lenght arg.
//
- if (idx == FixedParameters.Length){
- is_out = false;
+ int array_idx = (FixedParameters != null ? FixedParameters.Length : 0);
+ if (idx == array_idx)
return types [idx];
- }
//
// Otherwise, it is a fixed parameter
//
Parameter p = FixedParameters [idx];
- is_out = ((p.ModFlags & (Parameter.Modifier.REF | Parameter.Modifier.OUT)) != 0);
+ mod = p.ModFlags;
+
+ if ((mod & (Parameter.Modifier.REF | Parameter.Modifier.OUT)) != 0)
+ mod |= Parameter.Modifier.ISBYREF;
return p.ParameterType;
}