📄 objexpast.cs
字号:
// Now we're back to normal...
// Figure out what constructor we're calling
if (m_tType.BlueType.IsStruct && (alParamTypes.Length == 0))
{
// Structs have no default constructor
} else {
// Else resolve the ctor
bool fIsVarArg;
m_symCtor = m_tType.BlueType.LookupMethod(
s,
new Identifier(m_tType.BlueType.Name, this.Location),
alParamTypes,
out fIsVarArg);
}
//(m_tType.TypeRec, s);
CalcCLRType(s);
return this;
}
protected override Type CalcCLRTypeHelper(ISemanticResolver s)
{
return m_tType.BlueType.CLRType;
}
#endregion
}
//-----------------------------------------------------------------------------
// New array
// Expression List - specifies size of array, eval at runtime
// Initilizer List - specifies intializer list
//-----------------------------------------------------------------------------
public class NewArrayObjExp : Exp
{
// Implicit size from init list
public NewArrayObjExp(
ArrayTypeSig tArrayType, // includes rank specifiers
ArrayInitializer aInit // mandatory
)
{
Debug.Assert(tArrayType != null);
Debug.Assert(aInit != null);
m_tFullType = tArrayType;
this.m_arExpList = null;
this.m_ArrayInit = aInit;
// @todo - this is wrong
m_filerange = tArrayType.Location;
}
public NewArrayObjExp(
ArrayTypeSig tArrayType, // full array type (includes rank)
Exp [] arExpSize, // rank to allocate, eval at runtime
ArrayInitializer aInit // optional initilizer list
)
{
Debug.Assert(tArrayType != null);
Debug.Assert(arExpSize != null);
m_tFullType = tArrayType;
this.m_arExpList = arExpSize;
this.m_ArrayInit = aInit;
// @todo - this is wrong
m_filerange = tArrayType.Location;
}
#region Checks
//-----------------------------------------------------------------------------
// Debugging check
//-----------------------------------------------------------------------------
public override void DebugCheck(ISemanticResolver s)
{
Debug.Assert(this.CLRType.IsArray);
//Debug.Assert(TypeRec.AsArrayType.ElemType == ElemType.TypeRec);
if (HasInitializerList) {
ArrayInit.DebugCheck(s);
}
if (DimensionExpList != null)
{
foreach(Exp e in DimensionExpList)
{
e.DebugCheck(s);
}
}
}
// Dump as XML
public override void Dump(XmlWriter o)
{
o.WriteStartElement("NewArrayObjExp");
o.WriteAttributeString("elementtype", ElemType.ToString());
if (HasInitializerList)
{
ArrayInit.Dump(o);
}
o.WriteEndElement();
}
public override void ToSource(System.CodeDom.Compiler.IndentedTextWriter sb)
{
sb.Write("new {0}[{1}]", this.ElemType.ToString(), this.DimensionExpList.Length);
}
#endregion
#region Properties & Data
// The array type that this expression will evaluate to
protected ArrayTypeSig m_tFullType;
// The type of object that we're allocating
public TypeEntry ElemType
{
get { return m_tFullType.ElemType; }
}
// Array Initializer
ArrayInitializer m_ArrayInit;
public ArrayInitializer ArrayInit
{
get { return m_ArrayInit; }
}
/*
// A block statement that has the code needed to
// initialize the array for the Initializer list
BlockStatement m_stmtInit;
public BlockStatement InitStmt
{
get { return m_stmtInit; }
}
*/
// Return true if we have an init list, else false
public bool HasInitializerList
{
get { return m_ArrayInit != null; }
}
// Expression list for the size to allocate
protected Exp[] m_arExpList;
public Exp[] DimensionExpList
{
get { return m_arExpList; }
}
ArrayTypeEntry m_symbol;
public ArrayTypeEntry ArraySymbol
{
get { return m_symbol; }
}
#endregion
// Do codegen
public override void GenerateAsRight(CodeGen.EmitCodeGen gen)
{
gen.Generate(this);
}
#region Resolution
// Resolve
protected override Exp ResolveExpAsRight(ISemanticResolver s)
{
if (m_symbol != null)
return this;
// Resolve the type we're allocating
m_tFullType.ResolveType(s);
Debug.Assert(this.ElemType != null);
// Resolve the initializer list
if (HasInitializerList)
{
// If we specified a length, it'd better match the intializer list length.
if (DimensionExpList != null)
{
Debug.Assert(this.DimensionExpList.Length == 1, "@todo -multidimensional arrays");
Exp e = DimensionExpList[0];
// e must be a compile time constant who's value matches the ArrayInit length
IntExp eInt = e as IntExp;
if (eInt == null)
ThrowError(SymbolError.MustBeCompileTimeConstant(e));
if (eInt.Value != m_ArrayInit.Length)
ThrowError(SymbolError.NewArrayBoundsMismatch(this));
}
m_ArrayInit.Resolve(s, this.ElemType);
// The ability to not specifiy a dimension list is just syntactic sugar.
// So if we still don't have it, we'd better fill it in based of the array-init list.
if (DimensionExpList == null)
{
m_arExpList = new Exp[] { new IntExp(m_ArrayInit.Length, this.Location) };
}
}
Debug.Assert(DimensionExpList != null);
for(int i = 0; i < this.m_arExpList.Length; i++)
{
ResolveExpAsRight(ref m_arExpList[i], s);
}
m_symbol = new ArrayTypeEntry(m_tFullType, s);
CalcCLRType(s);
// Transform an initializer list into an CompoundExpression:
// new T[] { e0, e1, ... en}
// <DeclareTemp(x), x = new T[], x[0]=e0, ... x[n]=en, x>
if (HasInitializerList)
{
DeclareLocalStmtExp declare_x = new DeclareLocalStmtExp(this.ArraySymbol);
LocalExp x = declare_x.GetLocal();
StatementExp [] list = new StatementExp[m_ArrayInit.Length + 2];
list[0] = declare_x;
list[1] = new AssignStmtExp(x, this);
for(int i = 0; i < m_ArrayInit.Length; i++)
list[i + 2] = new AssignStmtExp(
new ArrayAccessExp(
x,
new IntExp(i, null)
),
m_ArrayInit.GetExpAt(i)
);
// Strip the ArrayInitializer off this node.
m_ArrayInit = null;
StatementExp c = new CompoundStmtExp(list, x);
StatementExp.ResolveExpAsRight(ref c, s);
return c;
} // end has Initializer
return this;
}
protected override Type CalcCLRTypeHelper(ISemanticResolver s)
{
return m_symbol.CLRType;
}
#endregion
}
#endregion // New
//-----------------------------------------------------------------------------
// Array access
// May be an actual array access, or an indexer overload
// If this is an indexer, we expect to be transformed into methodcalls
// before we get to codegen
//-----------------------------------------------------------------------------
public class ArrayAccessExp : Exp
{
public ArrayAccessExp(
Exp expLeft,
Exp expIndex
)
{
Debug.Assert(expLeft != null);
Debug.Assert(expIndex != null);
m_oeLeft = expLeft;
m_expIndex = expIndex;
// @todo- this is wrong
m_filerange = m_oeLeft.Location;
}
#region Checks
//-----------------------------------------------------------------------------
// Debugging check
//-----------------------------------------------------------------------------
public override void DebugCheck(ISemanticResolver s)
{
m_oeLeft.DebugCheck(s);
m_expIndex.DebugCheck(s);
}
// Dump as XML
public override void Dump(XmlWriter o)
{
o.WriteStartElement("ArrayAccessExp");
m_oeLeft.Dump(o);
m_expIndex.Dump(o);
o.WriteEndElement();
}
#endregion
#region Properties & Data
// Array object on the left side to be dereferenced
protected Exp m_oeLeft;
public Exp Left
{
get { return m_oeLeft; }
}
// Expression to evaluate to integer index
protected Exp m_expIndex;
public Exp ExpIndex
{
get { return m_expIndex; }
}
// Is this ArrayAccess actually an indexer?
bool m_fIsIndexer;
public bool IsIndexer
{
get {return m_fIsIndexer; }
}
// Get the element type as a CLR type
// If we're an indexer, this will be the return type on the property
public System.Type CLRElemType
{
get {
// ...
// ...
// There is a bug in .NET where references are not properly stripped, so
// we have to be a little more round-about here.
System.Type tLeft = Left.CLRType;
string stLeft = tLeft.ToString();
System.Type tNoRef;
if (tLeft.IsByRef)
tNoRef = tLeft.GetElementType();
else
tNoRef = tLeft;
string stNoRef = tNoRef.ToString();
Debug.Assert(!tNoRef.IsByRef);
Debug.Assert(tNoRef.IsArray);
System.Type tElem = tNoRef.GetElementType();
string stElem = tElem.ToString();
Debug.Assert(!tElem.IsByRef); // Can't be a ref, could still be an array.
return tElem;
}
}
#endregion
#region Generate
// Do codegen
public override void GenerateAsRight(CodeGen.EmitCodeGen gen)
{
Debug.Assert(!IsIndexer, "Don't codegen Indexers as Array Access");
gen.Generate(this);
}
public override void GenerateAsLeftPre(CodeGen.EmitCodeGen gen)
{
Debug.Assert(!IsIndexer, "Don't codegen Indexers as Array Access");
gen.GenerateAsLeftPre(this);
}
public override void GenerateAsLeftPost(CodeGen.EmitCodeGen gen)
{
Debug.Assert(!IsIndexer, "Don't codegen Indexers as Array Access");
gen.GenerateAsLeftPost(this);
}
public override void GenerateAddrOf(CodeGen.EmitCodeGen gen)
{
Debug.Assert(!IsIndexer, "Don't codegen Indexers as Array Access");
gen.GenerateAddrOf(this);
}
#endregion
#region Resolve
protected override Exp ResolveExpAsLeft(ISemanticResolver s)
{
return ResolveInternal(s, true);
}
// Resolve
protected override Exp ResolveExpAsRight(ISemanticResolver s)
{
return ResolveInternal(s, false);
}
// Internal helper. Since the left & right cases are close enough
// we want to merge them into a function.
private Exp ResolveInternal(ISemanticResolver s, bool fIsLeft)
{
ResolveExpAsRight(ref m_oeLeft, s);
ResolveExpAsRight(ref m_expIndex, s);
// @todo - check that m_expIndex is an integer
// Check for indexers:
// If the Left is not an array, then we must be an indexer.
// Strip references, So T[]& --> T[]
System.Type t = m_oeLeft.CLRType;
if (t.IsByRef)
t = t.GetElementType();
if (!t.IsArray)
{
m_fIsIndexer = true;
// If we're the leftside, we have a problem. We don't know the exp on the RS,
// so we don't have a full signature, so we don't know what we're supposed to
// change too. So just leave it that we're an indexer and let our parent
// in the AST resolve us.
// But this also means that we don't have a good thing to set our CLR type too.
// So we just don't call CalcCLRType(). That's ok since our parent will drop
// this node immediately anyways.
if (fIsLeft)
{
return this;
}
// Rightside: get_Item(idx);
System.Type [] alParams = new Type [] {
this.ExpIndex.CLRType
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -