/// <summary> /// For now, this will only allow Classes to have fields and methods. /// So primitives like int, real, bool won't have any. /// </summary> /// <param name="n"></param> public override void VisitDerefField(ASTDereferenceField n) { //we're processing something of the form: lvalue.identifier //Make sure the lvalue is a type and the identifier exists CFlatType lhs = CheckSubTree(n.Object); if (lhs.IsClass) { TypeClass lvalue = (TypeClass)lhs; var descriptor = (ClassDescriptor)_scopeMgr.Find(lvalue.ClassName, p => p is ClassDescriptor); //check if a field exists. MemberDescriptor memberDesc = _scopeMgr.Find(n.Field, d => d is MemberDescriptor, descriptor.Scope) as MemberDescriptor; if (memberDesc != null && descriptor.Fields.Contains(memberDesc)) { if (memberDesc.Modifiers.Contains(PRIVATE_MODIFIER, StringComparer.InvariantCultureIgnoreCase)) { if (!_scopeMgr.HasSymbolShallow(n.Field)) { ReportError(n.Location, "Cannot reference the private member '{0}' on class '{1}' from class '{2}'", memberDesc.Name, memberDesc.ContainingClass.Name, _currentClass.ClassName); } } if (memberDesc != null) { //hooray, code is valid n.Descriptor = memberDesc; n.CFlatType = memberDesc.Type; _lastSeenType = memberDesc.Type; } else { ReportError(n.Location, "'{0}' is not a field for type '{1}'", n.Field, TypeToFriendlyName(lvalue)); } } else { ReportError(n.Location, "Field '{0}' does not exist for type '{1}'", n.Field, TypeToFriendlyName(lvalue)); } } else { ReportError(n.Location, "Type '{0}' does not support fields.", TypeToFriendlyName(lhs)); } }
public override void VisitDerefField(ASTDereferenceField n) { //visit the identifier n.Object.Visit(this); TypeBuilderInfo info = _typeManager.GetBuilderInfo(_lastWalkedType.Name); FieldBuilder field = info.FieldMap[n.Field]; //store the type that we're dereferencing _lastWalkedType = field.FieldType; //see what we need to do after visiting the identifier if (!n.IsLeftHandSide) { _gen.Emit(OpCodes.Ldfld, field); } else { _assignmentCallback = gen => gen.Emit(OpCodes.Stfld, field); //set what needs to happen at the end of the assignment } }