MemberFromReferenceExpression
using CLanguage.Interpreter;
using CLanguage.Types;
using System;
using System.Linq;
namespace CLanguage.Syntax
{
public class MemberFromReferenceExpression : Expression
{
public Expression Left { get; set; }
public string MemberName { get; set; }
public MemberFromReferenceExpression(Expression left, string memberName)
{
Left = left;
MemberName = memberName;
}
public override CType GetEvaluatedCType(EmitContext ec)
{
CType evaluatedCType = Left.GetEvaluatedCType(ec);
CStructType cStructType;
if ((cStructType = (evaluatedCType as CStructType)) != null) {
CStructMember cStructMember = cStructType.Members.FirstOrDefault((CStructMember x) => x.Name == MemberName);
if (cStructMember == null) {
ec.Report.Error(1061, "Struct '{0}' does not contain a defintion for '{1}'", cStructType.Name, MemberName);
return CBasicType.SignedInt;
}
return cStructMember.MemberType;
}
throw new NotImplementedException("Member type on " + evaluatedCType.GetType().Name);
}
protected override void DoEmit(EmitContext ec)
{
CType evaluatedCType = Left.GetEvaluatedCType(ec);
CStructType cStructType;
if ((cStructType = (evaluatedCType as CStructType)) == null)
throw new NotSupportedException("Member access on " + evaluatedCType.GetType().Name);
CStructMember cStructMember = cStructType.Members.FirstOrDefault((CStructMember x) => x.Name == MemberName);
if (cStructMember == null)
ec.Report.Error(1061, "Struct '{0}' does not contain a definition for '{1}'", cStructType.Name, MemberName);
else {
CStructMethod method;
if ((method = (cStructMember as CStructMethod)) == null || !(cStructMember.MemberType is CFunctionType))
throw new NotSupportedException("Member field access on struct " + cStructType.Name);
ResolvedVariable resolvedVariable = ec.ResolveMethodFunction(cStructType, method);
if (resolvedVariable != null) {
Left.EmitPointer(ec);
ec.Emit(OpCode.LoadConstant, Value.Pointer(resolvedVariable.Address));
}
}
}
public override string ToString()
{
return $"{Left}""{MemberName}";
}
}
}