CLanguage by praeclarum

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

.NET API 206,336 bytes

 MemberFromPointerExpression

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 MemberFromPointerExpression : Expression { public Expression Left { get; set; } public string MemberName { get; set; } public override bool CanEmitPointer => true; public MemberFromPointerExpression(Expression left, string memberName) { Left = left; MemberName = memberName; } public override CType GetEvaluatedCType(EmitContext ec) { CType evaluatedCType = Left.GetEvaluatedCType(ec); CPointerType cPointerType = evaluatedCType as CPointerType; if (cPointerType != null) { CStructType cStructType = cPointerType.InnerType 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; } } if (cPointerType != null) { ec.Report.Error(1061, "'{1}' not found in '{0}'", cPointerType, MemberName); return CBasicType.SignedInt; } ec.Report.Error(1061, "-> cannot be used with '{0}'", evaluatedCType); return CBasicType.SignedInt; } protected override void DoEmit(EmitContext ec) { CType evaluatedCType = Left.GetEvaluatedCType(ec); CPointerType cPointerType = evaluatedCType as CPointerType; if (cPointerType != null) { CStructType cStructType = cPointerType.InnerType 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 { CStructMethod cStructMethod = cStructMember as CStructMethod; if (cStructMethod != null && cStructMember.MemberType is CFunctionType) { ResolvedVariable resolvedVariable = ec.ResolveMethodFunction(cStructType, cStructMethod); if (resolvedVariable != null) { Left.Emit(ec); ec.Emit(OpCode.LoadConstant, Value.Pointer(resolvedVariable.Address)); } } else { Left.Emit(ec); ec.Emit(OpCode.LoadConstant, Value.Pointer(cStructType.GetFieldValueOffset(cStructMember, ec))); ec.Emit(OpCode.OffsetPointer); ec.Emit(OpCode.LoadPointer); } } return; } } throw new NotSupportedException("Cannot read '" + MemberName + "' on " + evaluatedCType?.GetType().Name); } protected override void DoEmitPointer(EmitContext ec) { CType evaluatedCType = Left.GetEvaluatedCType(ec); CPointerType cPointerType = evaluatedCType as CPointerType; if (cPointerType != null) { CStructType cStructType = cPointerType.InnerType 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.Emit(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}"; } } }