CLanguage by praeclarum

<PackageReference Include="CLanguage" Version="0.19.67" />

.NET API 205,824 bytes

 MemberFromReferenceExpression

using CLanguage.Compiler; using CLanguage.Interpreter; using CLanguage.Types; using System; using System.Linq; using System.Runtime.CompilerServices; namespace CLanguage.Syntax { [System.Runtime.CompilerServices.NullableContext(1)] [System.Runtime.CompilerServices.Nullable(0)] public class MemberFromReferenceExpression : Expression { public Expression Left { get; set; } public string MemberName { get; set; } public override bool CanEmitPointer => true; public MemberFromReferenceExpression(Expression left, string memberName) { Left = left; MemberName = memberName; } public override CType GetEvaluatedCType(EmitContext ec) { CType evaluatedCType = Left.GetEvaluatedCType(ec); CStructType cStructType = evaluatedCType as CStructType; if (cStructType != null) { CStructMember cStructMember = cStructType.Members.FirstOrDefault((CStructMember x) => x.Name == MemberName); if (cStructMember == null) { ec.Report.Error(1061, "'{1}' not found in '{0}'", 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 = evaluatedCType as CStructType; if (cStructType == null) throw new NotSupportedException("Cannot read '" + MemberName + "' on " + evaluatedCType?.GetType().Name); CStructMember cStructMember = cStructType.Members.FirstOrDefault((CStructMember x) => x.Name == MemberName); if (cStructMember == null) ec.Report.Error(1061, "'{1}' not found in '{0}'", cStructType.Name, MemberName); else { CStructMethod cStructMethod = cStructMember as CStructMethod; if (cStructMethod != null && cStructMember.MemberType is CFunctionType) { ResolvedVariable resolvedVariable = ec.ResolveMethodFunction(cStructType, cStructMethod); if (resolvedVariable != null) { Left.EmitPointer(ec); ec.Emit(OpCode.LoadConstant, Value.Pointer(resolvedVariable.Address)); } } else { Left.EmitPointer(ec); ec.Emit(OpCode.LoadConstant, Value.Pointer(cStructType.GetFieldValueOffset(cStructMember, ec))); ec.Emit(OpCode.OffsetPointer); ec.Emit(OpCode.LoadPointer); } } } protected override void DoEmitPointer(EmitContext ec) { CType evaluatedCType = Left.GetEvaluatedCType(ec); CStructType cStructType = evaluatedCType as CStructType; if (cStructType != null) { CStructMember cStructMember = cStructType.Members.FirstOrDefault((CStructMember x) => x.Name == MemberName); if (cStructMember == null) ec.Report.Error(1061, "'{1}' not found in '{0}'", cStructType.Name, MemberName); else if (cStructMember is CStructMethod && cStructMember.MemberType is CFunctionType) { ec.Report.Error(1656, "Cannot assign to '{0}'", MemberName); } else { Left.EmitPointer(ec); ec.Emit(OpCode.LoadConstant, Value.Pointer(cStructType.GetFieldValueOffset(cStructMember, ec))); ec.Emit(OpCode.OffsetPointer); } return; } throw new NotSupportedException("Cannot write '" + MemberName + "' on " + evaluatedCType?.GetType().Name); } public override string ToString() { return $"{Left}""{MemberName}"; } } }