📄 objexpast.cs
字号:
// If we changed nodes, then resolve the new one.
// If we didn't change, then don't resolve again (else we have stack-overflow)
if (e != this)
Exp.ResolveExpAsRight(ref e, s);
e.SetLocation(this.Location);
return e;
}
// An ObjExp is just a temporary node. But that's the best a Context-Free parse can
// do. So now that we're building a symbol table, we can do a Context-Sensitive resolution
// and figure out what type of node this really is.
public Exp GetResolvedNode(ISemanticResolver s)
{
string stText = this.m_strId.Text;
// Left must already be resolved, then we resolve right in the context of left
Debug.Assert(m_left != null);
Exp eResolved = null;
// @todo, what if left is a NullExp?
if (m_left is NamespaceExp)
{
// We're either a nested namespace or a class
NamespaceEntry n = (m_left as NamespaceExp).Symbol;
SymEntry sym = n.ChildScope.LookupSymbol(stText);
if (sym is NamespaceEntry)
{
eResolved = new NamespaceExp(sym as NamespaceEntry);
}
else if (sym is TypeEntry)
{
eResolved = new TypeExp(sym as TypeEntry);
} else {
//ThrowError_UndefinedSymbolInNamespace(s, n, m_strId);
ThrowError(SymbolError.UndefinedSymbolInNamespace(n, m_strId));
}
}
// Check for statics
else if (m_left is TypeExp)
{
TypeEntry t = ((TypeExp) m_left).Symbol;
t.EnsureResolved(s);
SymEntry sym = t.MemberScope.LookupSymbol(stText);
if (sym is FieldExpEntry)
{
Debug.Assert(((FieldExpEntry) sym).IsStatic);
eResolved = new FieldExp(sym as FieldExpEntry, null); // static
}
else if (sym is PropertyExpEntry)
{
eResolved = new PropertyExp(sym as PropertyExpEntry, null);
}
else if (sym is EventExpEntry)
{
eResolved = new EventExp(sym as EventExpEntry, null);
}
// Allow nested types
else if (sym is TypeEntry)
{
eResolved = new TypeExp(sym as TypeEntry);
}
else
{
// Must be a method. The node transform occurs higher up though.
Debug.Assert((sym = t.LookupMethodHeader(stText)) != null);
eResolved = this;
}
if (eResolved == null) {
//ThrowError_UndefinedSymbolInType(s, t, m_strId);
ThrowError(SymbolError.UndefinedSymbolInType(t, m_strId));
}
}
// m_left is a variable, and we're doing an instance member dereference
else {
TypeEntry t = null;
t = s.ResolveCLRTypeToBlueType(this.m_left.CLRType);
t.EnsureResolved(s);
Scope scope = t.MemberScope;
// @todo - broken for an interface. IA : IB, scope for IA doesn't link to IB.
SymEntry sym = scope.LookupSymbol(stText);
if (sym is FieldExpEntry)
{
eResolved = new FieldExp(sym as FieldExpEntry, this.m_left);
}
else if (sym is PropertyExpEntry)
{
eResolved = new PropertyExp(sym as PropertyExpEntry, this.m_left);
}
else if (sym is EventExpEntry)
{
eResolved = new EventExp(sym as EventExpEntry, this.m_left);
}
else
{
// Must be a method. The node transform occurs higher up though.
sym = t.LookupMethodHeader(stText);
if (sym != null)
eResolved = this;
}
if (eResolved == null)
{
ThrowError(SymbolError.UndefinedSymbolInType(t, m_strId));
}
}
Debug.Assert(eResolved != null);
return eResolved;
}
#endregion
#region Checks
public override void DebugCheck(ISemanticResolver s)
{
Debug.Assert(false, "Temporary node still in Final pass");
}
public override void Dump(XmlWriter o)
{
}
public override void ToSource(System.CodeDom.Compiler.IndentedTextWriter sb)
{
this.m_left.ToSource(sb);
sb.Write(".'{0}'", this.Id.Text);
}
#endregion
}
//-----------------------------------------------------------------------------
//Method Call exp
//MethodCall-> LValue '.' id '(' paramlist ')'
//MethodCall-> id '(' paramlist ')' // no LValue, implied 'this'
//-----------------------------------------------------------------------------
public class MethodCallExp : StatementExp
{
#region Construction
public MethodCallExp(
Exp e, // may be null,
Identifier id,
ArgExp [] arParams
)
{
// m_objExp may be null _until_ we resolve this. And then it's either
// going to the implied 'this' ptr, a global func or a static func.
m_objExp = e;
m_idName = id;
m_arParams = (arParams == null) ? new ArgExp[0] : arParams;
// @todo - set in parser
m_filerange = id.Location;
}
// Use this when we already have a static method to call
// and we already have the symbols
public MethodCallExp(
Exp eInstance, // null if static
MethodExpEntry symMethod,
ArgExp [] arParams,
ISemanticResolver s
)
{
this.m_idName = new Identifier(symMethod.Name);
m_arParams = arParams;
m_symbol = symMethod;
// Spoof Left
if (eInstance == null)
{
//m_objExp = new SimpleObjExp(symMethod.SymbolClass.Name);
m_objExp = new TypeExp(symMethod.SymbolClass);
}
else
m_objExp = eInstance;
Exp.ResolveExpAsRight(ref m_objExp, s);
// Resolve args, just in case
foreach(ArgExp eArg in arParams)
{
Exp e = eArg;
Exp.ResolveExpAsRight(ref e, s);
Debug.Assert(e == eArg);
}
//ResolveAsExpEntry(m_symbol, s);
CalcCLRType(s);
}
#endregion
#region Checks
//-----------------------------------------------------------------------------
// Debugging check
//-----------------------------------------------------------------------------
public override void DebugCheck(ISemanticResolver s)
{
Debug.Assert(Symbol != null);
Debug.Assert(m_symbol.RetType.CLRType == base.CalcCLRType(s));
Debug.Assert(m_symbol.m_strName == this.m_idName.Text);
Debug.Assert(m_symbol.Info != null);
//Debug.Assert(m_mode == ObjExp.Mode.cExpEntry);
m_objExp.DebugCheck(s);
foreach(ArgExp e in ParamExps)
{
e.DebugCheck(s);
}
}
public override void ToSource(System.CodeDom.Compiler.IndentedTextWriter sb)
{
#if true
if (this.m_objExp == null)
sb.Write(this.Symbol.SymbolClass.FullName);
else
m_objExp.ToSource(sb);
sb.Write('.');
sb.Write(this.Symbol.Name);
#endif
sb.Write('(');
bool fFirst = true;
foreach(ArgExp a in m_arParams)
{
if (!fFirst)
sb.Write(',');
a.ToSource(sb);
fFirst = false;
}
sb.Write(')');
}
// Dump as XML
public override void Dump(XmlWriter o)
{
o.WriteStartElement("MethodCallExp");
o.WriteAttributeString("name", m_idName.Text);
if (m_symbol != null)
o.WriteAttributeString("symbol", m_symbol.ToString());
if (m_objExp != null)
m_objExp.Dump(o);
o.WriteStartElement("parameters");
foreach(ArgExp e in m_arParams)
{
e.Dump(o);
}
o.WriteEndElement();
o.WriteEndElement();
}
#endregion Checks
#region Properties & Data
Exp m_objExp;
public Exp LeftObjExp
{
get { return m_objExp; }
}
ArgExp [] m_arParams;
//readonly string m_strName;
readonly Identifier m_idName;
public MethodExpEntry m_symbol;
public ArgExp [] ParamExps
{
get { return m_arParams; }
}
public MethodExpEntry Symbol
{
get { return m_symbol; }
}
//bool m_fIsVarArg;
/*
public bool IsVarArg
{
get { return m_fIsVarArg; }
}*/
// Should codegen make this a static call or an instance call?
public bool IsStaticCall
{
get { return m_symbol.IsStatic; }
}
bool m_fIsNotPolymorphic;
public bool IsNotPolymorphic
{
get { return m_fIsNotPolymorphic; }
}
#endregion
#region Resolution
// The type of a method expression is its return type.
protected override Type CalcCLRTypeHelper(ISemanticResolver s)
{
return this.Symbol.CLRType;
}
// Semantic resolution
protected override Exp ResolveExpAsRight(ISemanticResolver s)
{
// Only resolve once.
if (m_symbol != null)
return this;
// First, resolve our parameters (because of overloading)
// We need to know the URT types for our parameters
// in order to resolve between overloaded operators
Type [] alParamTypes = new Type[m_arParams.Length];
for(int i = 0; i < m_arParams.Length; i++)
{
Exp e = m_arParams[i];
ResolveExpAsRight(ref e, s);
Debug.Assert(e == m_arParams[i]);
Type tParam = e.CLRType;
//if ((tParam !=null) && tParam.IsByRef)
// tParam = tParam.GetElementType();
alParamTypes[i] = tParam;
//Debug.Assert(alParamTypes[i] != null);
}
TypeEntry tCur = s.GetCurrentClass();
TypeEntry tLeft = null; // Type to lookup in
// Is this a 'base' access?
// Convert to the real type and set a non-virtual flag
if (m_objExp is SimpleObjExp)
{
SimpleObjExp e = m_objExp as SimpleObjExp;
if (e.Name.Text == "base")
{
// Set the scope that we lookup in.
tLeft = tCur.Super;
// Still need to resolve the expression.
m_objExp = new SimpleObjExp("this");
m_fIsNotPolymorphic = true;
}
}
#if true
// See if we have a delegate here
Exp eDelegate = null;
if (m_objExp == null)
{
Exp e = new SimpleObjExp(m_idName);
Exp.ResolveExpAsRight(ref e, s);
if (!(e is SimpleObjExp))
eDelegate = e;
} else {
// If it's an interface, then we know we can't have a delegate field on it,
// so short-circuit now.
Exp.ResolveExpAsRight(ref m_objExp, s);
if (!m_objExp.CLRType.IsInterface)
{
Exp e = new DotObjExp(m_objExp, m_idName);
Exp.ResolveExpAsRight(ref e, s);
if (!(e is DotObjExp))
eDelegate = e;
}
}
if (eDelegate != null)
{
if (!DelegateDecl.IsDelegate(eDelegate.CLRType))
{
//Debug.Assert(false, "@todo - " + m_strName + " is not a delegate or function"); // @todo - legit
// Just fall through for now, method resolution will decide if this is a valid function
} else
{
Exp e = new MethodCallExp(
eDelegate,
new Identifier("Invoke"),
this.m_arParams
);
Exp.ResolveExpAsRight(ref e, s);
return e;
}
}
#endif
// No delegate, carry on with a normal function call
// If there's no objexp, then the function is a method
// of the current class.
// make it either a 'this' or a static call
if (m_objExp == null)
{
// Lookup
bool fIsVarArgDummy;
MethodExpEntry sym = tCur.LookupMethod(s, m_idName, alParamTypes, out fIsVarArgDummy);
if (sym.IsStatic)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -