📄 objexpast.cs
字号:
m_objExp = new TypeExp(tCur);
} else {
m_objExp = new SimpleObjExp("this");
}
}
// Need to Lookup m_strName in m_objExp's scope (inherited scope)
Exp.ResolveExpAsRight(ref m_objExp, s);
// Get type of of left side object
// This call can either be a field on a variable
// or a static method on a class
bool fIsStaticMember = false;
// If we don't yet know what TypeEntry this methodcall is on, then figure
// it out based off the expression
if (tLeft == null)
{
if (m_objExp is TypeExp)
{
fIsStaticMember = true;
tLeft = ((TypeExp) m_objExp).Symbol;
} else {
fIsStaticMember = false;
tLeft = s.ResolveCLRTypeToBlueType(m_objExp.CLRType);
}
}
// Here's the big lookup. This will jump through all sorts of hoops to match
// parameters, search base classes, do implied conversions, varargs,
// deal with abstract, etc.
bool fIsVarArg;
m_symbol = tLeft.LookupMethod(s, m_idName, alParamTypes, out fIsVarArg);
Debug.Assert(m_symbol != null);
if (m_fIsNotPolymorphic)
{
// of the form 'base.X(....)'
if (m_symbol.IsStatic)
ThrowError(SymbolError.BaseAccessCantBeStatic(this.Location, m_symbol)); // @todo - PrintError?
} else {
// normal method call
/*
if (fIsStaticMember && !m_symbol.IsStatic)
ThrowError(SymbolError.ExpectInstanceMember(this.Location)); // @todo - PrintError?
else if (!fIsStaticMember && m_symbol.IsStatic)
ThrowError(SymbolError.ExpectStaticMember(this.Location)); // @todo - PrintError?
*/
Debug.Assert(fIsStaticMember == m_symbol.IsStatic, "@todo - user error. Mismatch between static & instance members on line.");
}
// If we have a vararg, then transform it
if (fIsVarArg)
{
// Create the array
int cDecl = m_symbol.ParamCount;
int cCall = this.ParamExps.Length;
ArrayTypeSig tSig = new ArrayTypeSig(m_symbol.ParamCLRType(cDecl - 1), s);
Node [] list = new Node[cCall - cDecl + 1];
for(int i = 0; i < list.Length; i++)
{
list[i] = this.ParamExps[i + cDecl - 1];
}
Exp eArray = new NewArrayObjExp(
tSig,
new ArrayInitializer(
list
)
);
Exp.ResolveExpAsRight(ref eArray, s);
// Change the parameters to use the array
ArgExp [] arParams = new ArgExp[cDecl];
for(int i = 0; i < cDecl - 1; i++)
arParams[i] = m_arParams[i];
arParams[cDecl - 1] = new ArgExp(EArgFlow.cIn, eArray);
m_arParams = arParams;
} // end vararg transformation
this.CalcCLRType(s);
return this;
}
#endregion
public override void GenerateAsRight(CodeGen.EmitCodeGen gen)
{
gen.Generate(this);
}
public override void GenerateAsStatement(CodeGen.EmitCodeGen gen)
{
// Default impl generates as a RHS exp and just pops the value off
gen.GenerateAsStatement(this);
}
}
#region Cast Expressions (TypeCasting & As operator)
//-----------------------------------------------------------------------------
// Type Cast any expression into a specific type
// TypeCast -> '(' Type ')' Exp
// AsExp -> Exp as Type
//-----------------------------------------------------------------------------
public class AsExp : BaseCastObjExp
{
public AsExp(
TypeSig tTargetType,
Exp expSource
)
: base(tTargetType, expSource)
{
}
public override void ToSource(System.CodeDom.Compiler.IndentedTextWriter sb)
{
sb.Write('(');
this.m_expSource.ToSource(sb);
sb.Write(" as {0}", this.m_tTargetType.ToString());
sb.Write(')');
}
// Resolve
// The 'as' operator can only be used on a Reference type (not a struct)
// So let the base class resolve, and then just add the error check here
protected override Exp ResolveExpAsRight(ISemanticResolver s)
{
Exp e = base.ResolveExpAsRight(s);
if (this.SourceExp.CLRType.IsValueType)
ThrowError(SymbolError.AsOpOnlyOnRefTypes(this.Location));
return e;
}
// Do codegen
public override void GenerateAsRight(CodeGen.EmitCodeGen gen)
{
gen.Generate(this);
}
}
public class CastObjExp : BaseCastObjExp
{
public CastObjExp(
TypeSig tTargetType,
Exp expSource
)
: base(tTargetType, expSource)
{
}
public override void ToSource(System.CodeDom.Compiler.IndentedTextWriter sb)
{
sb.Write("(({0}) ", m_tTargetType.ToString());
this.m_expSource.ToSource(sb);
sb.Write(')');
}
// Do codegen
public override void GenerateAsRight(CodeGen.EmitCodeGen gen)
{
gen.Generate(this);
}
}
// Base class for both TypeCasting & As operator
public abstract class BaseCastObjExp : Exp
{
public BaseCastObjExp(
TypeSig tTargetType,
Exp expSource
)
{
m_tTargetType = tTargetType;
m_expSource = expSource;
Debug.Assert(m_tTargetType != null);
Debug.Assert(m_expSource != null);
// @todo - have parser resolve this
//m_filerange = FileRange.Merge(expSource.Location, m_tTargetType.Location);
}
//-----------------------------------------------------------------------------
// Debugging check
//-----------------------------------------------------------------------------
public override void DebugCheck(ISemanticResolver s)
{
Debug.Assert(m_tTargetType != null);
m_tTargetType.DebugCheck(s);
Debug.Assert(m_expSource != null);
m_expSource.DebugCheck(s);
//Debug.Assert(m_tTargetType.TypeRec == base.TypeRec);
}
// Get the type that we want to cast too
protected TypeSig m_tTargetType;
public TypeSig TargetType
{
get { return m_tTargetType; }
}
// The source expression whos type will get converted
protected Exp m_expSource;
public Exp SourceExp
{
get { return m_expSource; }
}
// Dump as XML
public override void Dump(XmlWriter o)
{
o.WriteStartElement(this.GetType().ToString());
o.WriteAttributeString("targettype", TargetType.ToString());
m_expSource.Dump(o);
o.WriteEndElement();
}
// Resolve
protected override Exp ResolveExpAsRight(ISemanticResolver s)
{
ResolveExpAsRight(ref m_expSource, s);
m_tTargetType.ResolveType(s);
// Optimizing Check - if we're casting to the type of the source exp,
// then remove the cast. ex: '(T) t --> t'
if (m_tTargetType.CLRType == m_expSource.CLRType)
{
return m_expSource;
}
//ResolveAsExpEntry(m_tTargetType.TypeRec, s);
CalcCLRType(s);
return this;
}
protected override Type CalcCLRTypeHelper(ISemanticResolver s)
{
return m_tTargetType.BlueType.CLRType;
}
} // end cast expression
#endregion
#region New Expressions
//-----------------------------------------------------------------------------
// Allocate an object and invoke the proper constructor
// NewObjExp -> 'new' type '(' exp_list ')'
//-----------------------------------------------------------------------------
public class NewObjExp : Exp
{
public NewObjExp(
TypeSig tType,
Exp [] arParams
)
{
Debug.Assert(tType != null);
Debug.Assert(arParams != null);
m_tType = tType;
m_arParams = arParams;
// @todo- this is wrong
m_filerange = tType.Location;
}
#region Checks
//-----------------------------------------------------------------------------
// Debugging check
//-----------------------------------------------------------------------------
public override void DebugCheck(ISemanticResolver s)
{
/*
Debug.Assert(m_tType != null);
m_tType.DebugCheck(s);
Debug.Assert(m_tType.TypeRec == TypeRec);
Debug.Assert(m_arParams != null);
foreach(Exp e in m_arParams)
{
e.DebugCheck(s);
}
if (m_tType.TypeRec.IsStruct && (m_arParams.Length == 0))
{
// structs can't have a parameterless ctor
} else {
Debug.Assert(SymbolCtor != null);
Debug.Assert(SymbolCtor.IsCtor ||
(SymbolCtor.SymbolClass.IsStruct && (SymbolCtor.RetType.CLRType == typeof(void)))
);
Debug.Assert(!SymbolCtor.IsStatic); // new can't call a static ctor
// Name of ctor must match name of the type we're creating
Debug.Assert(SymbolCtor.Name == m_tType.TypeRec.Name);
}
*/
}
public override void ToSource(System.CodeDom.Compiler.IndentedTextWriter sb)
{
sb.Write("new {0}", this.ElemType.ToString());
}
// Dump as XML
public override void Dump(XmlWriter o)
{
o.WriteStartElement("NewObjExp");
o.WriteAttributeString("targettype", ElemType.ToString());
if (SymbolCtor != null)
o.WriteAttributeString("ctor", SymbolCtor.ToString());
o.WriteStartElement("parameters");
foreach(Exp e in Params)
{
e.Dump(o);
}
o.WriteEndElement();
o.WriteEndElement();
}
#endregion
#region Properties & Data
// The type of object that we're allocating
protected TypeSig m_tType;
public TypeSig ElemType
{
get { return m_tType; }
}
// The parameter list for the constructor call
protected Exp[] m_arParams;
public Exp[] Params
{
get { return m_arParams; }
}
// To make codegen's like easier, semantic checking
// figures out what constructor operator new should
// invoke
protected MethodExpEntry m_symCtor;
public MethodExpEntry SymbolCtor
{
get { return m_symCtor; }
}
#endregion
// Do codegen
public override void GenerateAsRight(CodeGen.EmitCodeGen gen)
{
gen.Generate(this);
}
#region Resolution
// Resolve
protected override Exp ResolveExpAsRight(ISemanticResolver s)
{
// Resolve the type we're allocating
m_tType.ResolveType(s);
// One major exception for creating a new delegate, of the form:
// new T(E.i)
//if (m_tType.CLRType.BaseType == typeof(System.MulticastDelegate))
if (DelegateDecl.IsDelegate(m_tType.CLRType))
{
//Debug.Assert(false, "@todo - Impl Delegates in New");
if (Params.Length != 1)
{
// When this is resolved, we actually have 2 params (not just one).
// Make sure we've already resolved this.
return this;
}
Exp.ResolveExpAsRight(ref m_arParams[0], s);
DotObjExp e = m_arParams[0] as DotObjExp;
Debug.Assert(e != null);
Exp expInstance = null;
TypeEntry tLeft = null;
if (e.LeftExp is TypeExp)
{
// Static
expInstance = new NullExp(Location);
tLeft = ((TypeExp) e.LeftExp).Symbol;
} else {
// Instance
expInstance = e.LeftExp;
tLeft = s.ResolveCLRTypeToBlueType(e.LeftExp.CLRType);
}
// Use the parameter list off the delegate type to discern for overloads.
System.Type [] alDelegateParams = DelegateDecl.GetParams(m_tType.BlueType);
// Lookup what function we're passing to the delegate.
bool fIsOut;
MethodExpEntry m = tLeft.LookupMethod(s, e.Id, alDelegateParams, out fIsOut);
Debug.Assert(!fIsOut, "@todo - can't have a delegate reference a vararg function");
// Change parameters
m_arParams = new Exp [] {
expInstance,
new MethodPtrExp(m)
};
}
// Resolve all parameters
System.Type [] alParamTypes = new Type[Params.Length];
for(int i = 0; i < this.m_arParams.Length; i++)
{
Exp.ResolveExpAsRight(ref m_arParams[i], s);
alParamTypes[i] = m_arParams[i].CLRType;
//Debug.Assert(alParamTypes[i] != null);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -