📄 expast.cs
字号:
#endregion
#region Checks
public override void DebugCheck(ISemanticResolver s)
{
}
// Dump as XML
public override void Dump(XmlWriter o)
{
o.WriteStartElement("DeclareLocalStmtExp");
o.WriteEndElement();
}
public override void ToSource(System.CodeDom.Compiler.IndentedTextWriter sb)
{
sb.Write("<TempLocal>{0}", this.m_exp.Symbol.Name);
}
#endregion
#region Resolution
// There's nothing to resolve here. No real action happens until
// codegen...
protected override Exp ResolveExpAsRight(ISemanticResolver s)
{
return this;
}
static int m_count = 0;
#endregion
#region Generate
// We should only do this as a Statement (since it produces side-effects)
public override void GenerateAsStatement(CodeGen.EmitCodeGen gen)
{
gen.GenerateAsStatement(this);
}
#endregion
}
//-----------------------------------------------------------------------------
// Compound expressions
// useful in code transformations.
// Has a list of statement expressions that get generated. And then generates
// the last expression and uses that value.
//-----------------------------------------------------------------------------
public class CompoundStmtExp : StatementExp
{
// <e0, e1, e2 .... en>
// e_0 .. e_n-1 are StatementExp, that generate as Statements (to produce side effects)
// e_n is a normal expression, generated as an expression, to produce a value
public CompoundStmtExp(
StatementExp [] eList,
Exp eLast
)
{
Debug.Assert(eList != null);
Debug.Assert(eLast != null);
m_eList = eList;
m_eLast = eLast;
}
#region Properties & Data
StatementExp [] m_eList;
Exp m_eLast;
#endregion
#region Resolution
protected override Exp ResolveExpAsRight(ISemanticResolver s)
{
for(int i = 0; i < m_eList.Length; i++)
StatementExp.ResolveExpAsRight(ref m_eList[i], s);
Exp.ResolveExpAsRight(ref m_eLast, s);
CalcCLRType(s);
return this;
}
// Type of an assignment is the type of the Right Side
protected override Type CalcCLRTypeHelper(ISemanticResolver s)
{
return m_eLast.CLRType;
}
#endregion
#region Checks
public override void DebugCheck(ISemanticResolver s)
{
foreach(Exp e in m_eList)
e.DebugCheck(s);
m_eLast.DebugCheck(s);
}
// Dump as XML
public override void Dump(XmlWriter o)
{
o.WriteStartElement("CompoundStmtExp");
o.WriteStartElement("Statements");
foreach(Exp e in m_eList)
e.Dump(o);
o.WriteEndElement();
m_eLast.Dump(o);
o.WriteEndElement();
}
public override void ToSource(System.CodeDom.Compiler.IndentedTextWriter sb)
{
sb.Write('[');
foreach(StatementExp e in m_eList)
{
e.ToSource(sb);
sb.Write(',');
}
m_eLast.ToSource(sb);
sb.Write(']');
}
#endregion
#region CodeGen
// For all CodeGen variations on a CompoundStatement, we want to
// first generate the StmtExp list to get the sideffects, and
// then fall through to the last expression and use that
// as the real CodeGen target.
// Code generation as an expression
public override void GenerateAsRight(CodeGen.EmitCodeGen gen)
{
// Generate the StmtExp to get their sideffects
foreach(StatementExp e in m_eList)
e.GenerateAsStatement(gen);
m_eLast.GenerateAsRight(gen);
}
// We can only generate as a Statement if the last thing is also
// a StatementeExp
public override void GenerateAsStatement(CodeGen.EmitCodeGen gen)
{
// Generate the StmtExp to get their sideffects
foreach(StatementExp e in m_eList)
e.GenerateAsStatement(gen);
Debug.Assert(m_eLast is StatementExp);
StatementExp se = (StatementExp) m_eLast;
se.GenerateAsStatement(gen);
}
// Generate the address
public override void GenerateAddrOf(CodeGen.EmitCodeGen gen)
{
// Still generate all the StmtExp normally because we
// need their side-effects
foreach(StatementExp e in m_eList)
e.GenerateAsStatement(gen);
// Use the address of the last expression.
m_eLast.GenerateAddrOf(gen);
}
#endregion
}
#endif
#if false
//-----------------------------------------------------------------------------
// OpEqual exoressions: +=, *=, /=, -=, %=
//-----------------------------------------------------------------------------
public class OpEqualStmtExp : StatementExp
{
#region Construction
public OpEqualStmtExp(Exp expLeft, Exp expRight, BinaryExp.BinaryOp op)
{
Debug.Assert(false, "OpEqualStmtExp is obsolete"); //
m_op = op;
m_eLeft = expLeft;
m_expRight = expRight;
}
#endregion
#region Checks
public override void DebugCheck(ISemanticResolver s)
{
Debug.Assert(Left != null);
Debug.Assert(Right != null);
Left.DebugCheck(s);
Right.DebugCheck(s);
}
// Dump as XML
public override void Dump(XmlWriter o)
{
o.WriteStartElement("OpEqualStmtExp");
Left.Dump(o);
Right.Dump(o);
o.WriteEndElement();
}
#endregion
#region Properties & Data
BinaryExp.BinaryOp m_op;
public BinaryExp.BinaryOp Op
{
get { return m_op; }
}
protected Exp m_eLeft;
public Exp Left
{
get { return m_eLeft; }
}
protected Exp m_expRight;
public Exp Right
{
get { return m_expRight; }
}
#endregion
#region Resolution
// Semantic resolution
// "a X= b" is semantically equivalent to "a = a X b"
protected override Exp ResolveExpAsRight(ISemanticResolver s)
{
// Note that the left side ("a") of "a X= b" is both a
// Left & Right side value
ResolveExpAsLeft(ref this.m_eLeft, s);
ResolveExpAsRight(ref this.m_expRight, s);
CalcCLRType(s);
// Ensure type match
s.EnsureAssignable(m_expRight, Left.CLRType);
return this;
}
// Type of an assignment is the type of the Right Side
protected override Type CalcCLRTypeHelper(ISemanticResolver s)
{
return Left.CLRType;
}
#endregion
// Code generation as an expression
public override void GenerateAsRight(CodeGen.EmitCodeGen gen)
{
gen.Generate(this);
}
public override void GenerateAsStatement(CodeGen.EmitCodeGen gen)
{
gen.GenerateAsStatement(this);
}
}
#endif
//-----------------------------------------------------------------------------
// Assignment statement
//-----------------------------------------------------------------------------
public class AssignStmtExp : StatementExp
{
#region Construction
public AssignStmtExp(Exp expLeft, Exp expRight)
{
Debug.Assert(expLeft != null);
Debug.Assert(expRight != null);
m_oeLeft = expLeft;
m_expRight = expRight;
//m_filerange = FileRange.Merge(expLeft.Location, expRight.Location);
}
#endregion
#region Checks
//-----------------------------------------------------------------------------
// Debugging check
//-----------------------------------------------------------------------------
public override void DebugCheck(ISemanticResolver s)
{
Debug.Assert(m_oeLeft != null);
Debug.Assert(m_expRight != null);
m_oeLeft.DebugCheck(s);
m_expRight.DebugCheck(s);
}
// Dump as XML
public override void Dump(XmlWriter o)
{
o.WriteStartElement("AssignStmtExp");
m_oeLeft.Dump(o);
m_expRight.Dump(o);
o.WriteEndElement();
}
public override void ToSource(System.CodeDom.Compiler.IndentedTextWriter sb)
{
m_oeLeft.ToSource(sb);
sb.Write("=");
m_expRight.ToSource(sb);
}
#endregion
#region Resolution
// Semantic resolution.
// This is where we check for Set-Property transformations (where an
// assignment gets changed into a methodcall)
protected override Exp ResolveExpAsRight(ISemanticResolver s)
{
// Resolve the leftside of the operator
Exp.ResolveExpAsLeft(ref m_oeLeft, s);
// Event transform actually occurs in the assignment node.
// A.e = A.e + d --> A.add_e(d)
// We have to do this before we resolve the RHS of the operator (Since we
// can't resolve events as a RHS).
if (m_oeLeft is EventExp)
{
EventExp nodeEvent = (EventExp)m_oeLeft;
EventExpEntry e = nodeEvent.Symbol;
// Here we just do some asserts.
BinaryExp b = this.m_expRight as BinaryExp;
Debug.Assert(b != null, "bad formed event +=,-=");
// By now, we know we have something of the form A = B + C
// Make sure that A=B. Since we resolved A as left, must resolve B as left too.
Exp eTempLeft = b.Left;
Exp.ResolveExpAsLeft(ref eTempLeft, s);
Debug.Assert(eTempLeft is EventExp);
Debug.Assert(Object.ReferenceEquals(((EventExp) eTempLeft).Symbol, e)); // symbols should be exact references
// Resolve C (the delegate that we're adding to the event)
Exp eTempRight = b.Right;
Exp.ResolveExpAsRight(ref eTempRight, s);
Debug.Assert(AST.DelegateDecl.IsDelegate(eTempRight.CLRType), "Event only ops w/ delegates"); // @todo -legit/
Debug.Assert(b.Op == BinaryExp.BinaryOp.cAdd || b.Op == BinaryExp.BinaryOp.cSub);
MethodExpEntry m2 = (b.Op == BinaryExp.BinaryOp.cAdd) ? e.AddMethod : e.RemoveMethod;
Exp e2 = new MethodCallExp(
nodeEvent.InstanceExp,
m2,
new ArgExp[] {
new ArgExp(EArgFlow.cIn, eTempRight)
},
s
);
Exp.ResolveExpAsRight(ref e2, s);
return e2;
}
Exp.ResolveExpAsRight(ref m_expRight, s);
// Check for calling add_, remove on events
// a.E += X
// a.E = a.E + X (parser transforms)
// if E is a delegate, and RHS is structured like E + X
// then transform to a.add_E(X) or a.remove_E(x)
// @todo - use the EventInfo to get exact add / remove functions
if (DelegateDecl.IsDelegate(m_oeLeft.CLRType))
{
// Events can only exist on a class
AST.FieldExp f = m_oeLeft as FieldExp;
if (f == null)
goto NotAnEvent;
Exp eInstance = f.InstanceExp; // ok if static
BinaryExp rhs = m_expRight as BinaryExp;
if (rhs == null)
goto NotAnEvent;
// Check if RHS is a.E + X
if ((rhs.Left != m_oeLeft) || (rhs.Right.CLRType != rhs.Left.CLRType))
goto NotAnEvent;
string stEventName = f.Symbol.Name;
string stOpName;
if (rhs.Op == BinaryExp.BinaryOp.cAdd)
stOpName = "add_" + stEventName;
else if (rhs.Op == BinaryExp.BinaryOp.cSub)
stOpName = "remove_" + stEventName;
else
goto NotAnEvent;
// a.add_E(X);
Exp e = new MethodCallExp(
eInstance,
new Identifier(stOpName),
new ArgExp[] {
new ArgExp(EArgFlow.cIn, rhs.Right)
}
);
Exp.ResolveExpAsRight(ref e, s);
e.SetLocation(this.Location);
return e;
NotAnEvent:
;
}
// Check for set-indexer
if (m_oeLeft is ArrayAccessExp)
{
ArrayAccessExp a = m_oeLeft as ArrayAccessExp;
if (a.IsIndexer)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -