Wednesday, May 11, 2016

Vim Regex C# to F#

This is really trying my patience. Converting a C# class to F# using regex. Not the cleanest or sanest approach, but really with the patterns in the code I'm targeting it shouldn't be a very big deal
I welcome any and all input or suggestions besides do it with a real code parser/generator (I've done lots of work in this area and realize the benefits, but I'm working on something that isn't as robust but gets the job done)

vim :set magic? returns:magic
I started out with the following code


namespace PracticeManagement.Foundation.DataModels
{
    public class BillingStageDataAccess
    {
        public static IEnumerable<BillingStageDataModel> LoadRejectedGrid(string payerId, Connector cn)
        {
            return Pm.Dal.BillingStages.loadRejectedGrid(payerId, SessionVariables.Instance.CurrentFacility.FacilityID, cn)
                .Select(r => new BillingStageDataModel(r));
        }

        public static IEnumerable<BillingStageDataModel> LoadPendingGrid(string payerId, Connector cn)
        {
            return Pm.Dal.BillingStages.loadPendingGrid(payerId, SessionVariables.Instance.CurrentFacility.FacilityID, cn)
                .Select(r=> new BillingStageDataModel(r));
        }

        public static IEnumerable<BillingStageDataModel> LoadReviewGrid(string payerId, Connector cn)
        {
            return Pm.Dal.BillingStages.loadReviewGrid(payerId, SessionVariables.Instance.CurrentFacility.FacilityID, cn)
                .Select(r => new BillingStageDataModel(r));
        }

        public static IEnumerable<BillingStageDataModel> LoadPatientBilling(bool? includeThirdParty, Connector cn)
        {
            return Pm.Dal.BillingStages.loadPatientBilling(SessionVariables.Instance.CurrentFacility.FacilityID, includeThirdParty, cn).Select(bsm => new BillingStageDataModel(new Pm.Schema.BillingStageRecord(bsm.Age.ToString(), 0m, 0m, bsm.DOS ?? DateTime.Now, null, 0, bsm.FirstStatement ?? DateTime.Now, bsm.NofStatements ?? 0, bsm.PatientName, bsm.ThirdPartyPayerId ?? 0, null, null, bsm.Appointmentid ?? 0, null, null)) { PrimaryGuarantorType= bsm.AppointmentPrimaryGuarantorType });
        }

        public static IEnumerable<BillingStageDataModel> LoadCompleted(Connector cn)
        {
            return Pm.Dal.BillingStages.loadCompleted(SessionVariables.Instance.CurrentFacility.FacilityID, cn).Select(bsm => new BillingStageDataModel(new Pm.Schema.BillingStageRecord(null,bsm.ClaimAmount ?? 0, 0, bsm.DOS ?? DateTime.Now, bsm.Claimdate ?? DateTime.Now, bsm.Daysfilled ?? 0, null, 0,bsm.PatientName, 0, bsm.Claimstatus, null, bsm.Appointmentid ?? 0,null,null)));
        }

        public static IEnumerable<BillingStageDataModel> LoadPrepGrid(int facilityId, Connector cn)
        {
            return Pm.Dal.BillingStages.loadPrepClaimGrid(facilityId, cn).Select(r => new BillingStageDataModel(r));
        }
    }
}

Stage 1

  1. use dd to delete the namespace and class lines
  2. add module name =
  3. highlight that block pasted into an F# file.
  4. then apply the regex to remove lines that only open or close blocks :'<,'>s:^\s*[{}]\s*$:
regex irritation
  • * doesn't need an escape but in other places + does
  • that leaves a bunch of empty lines unfortunately

Stage 2

  1. re-highlight with gv
  2. then eliminate the public static T with :'<,'>s:public static [\w<>]\+:let
regex irritation
  • + needed to be escaped!

Stage 3

  1. re-highlight with gv
  2. fix indention with << followed by . as needed
  3. re-highlight with gv
  4. eliminate returns with :'<,'>s/return /
  5. re-highlight with gv
  6. add = on the end of the let lines with :'<,'>s:let .*:\0 =
  7. re-highlight with gv
  8. Fix casing to my preference for module methods (camel-case) with :'<,'>s:let \(\u\w\+\):let \l\1 or closer to regular regex :'<,'>s:let \([A-Z]\w\+\):let \l\1
regex inconsistencies and irritations
  • had to escape ( and ) for capturing groups
  • had to escape + (:'<,'>s:let \(\u\w+\):let \l\1 did not work)
  • didn't have to escape any of the following .*

Stage 4 (work in progress)

fix up the method declarations a little more
  1. re-highlight with gv
  2. regex: :'<,'>s/\(let \w\+\)(\?\(\w\+\)\(?\)\? \(\w\+\)[,)]/\1(\3\4:\2)/ 
    • switch the order of type and name
    • move ? (Nullable to the front for replacement with the word `Nullable` in F#)
    • add : of the first argument on method declaration lines with
which leaves me with the following to convert so far
module BillingStages =

    let loadRejectedGrid(payerId:string) Connector cn) =

        Pm.Dal.BillingStages.loadRejectedGrid(payerId, SessionVariables.Instance.CurrentFacility.FacilityID, cn)
            .Select(r => new BillingStageDataModel(r));


    let loadPendingGrid(payerId:string) Connector cn) =

        Pm.Dal.BillingStages.loadPendingGrid(payerId, SessionVariables.Instance.CurrentFacility.FacilityID, cn)
            .Select(r=> new BillingStageDataModel(r));


    let loadReviewGrid(payerId:string) Connector cn) =

        Pm.Dal.BillingStages.loadReviewGrid(payerId, SessionVariables.Instance.CurrentFacility.FacilityID, cn)
            .Select(r => new BillingStageDataModel(r));


    let loadPatientBilling(?includeThirdParty:bool) Connector cn) =

        Pm.Dal.BillingStages.loadPatientBilling(SessionVariables.Instance.CurrentFacility.FacilityID, includeThirdParty, cn).Select(bsm => new BillingStageDataModel(new Pm.Schema.BillingStageRecord(bsm.Age.ToString(), 0m, 0m, bsm.DOS ?? DateTime.Now, null, 0, bsm.FirstStatement ?? DateTime.Now, bsm.NofStatements ?? 0, bsm.PatientName, bsm.ThirdPartyPayerId ?? 0, null, null, bsm.Appointmentid ?? 0, null, null)) { PrimaryGuarantorType= bsm.AppointmentPrimaryGuarantorType });


    let loadCompleted(cn:Connector) =

        Pm.Dal.BillingStages.loadCompleted(SessionVariables.Instance.CurrentFacility.FacilityID, cn).Select(bsm => new BillingStageDataModel(new Pm.Schema.BillingStageRecord(null,bsm.ClaimAmount ?? 0, 0, bsm.DOS ?? DateTime.Now, bsm.Claimdate ?? DateTime.Now, bsm.Daysfilled ?? 0, null, 0,bsm.PatientName, 0, bsm.Claimstatus, null, bsm.Appointmentid ?? 0,null,null)));


    let loadPrepGrid(facilityId:int) Connector cn) =

        Pm.Dal.BillingStages.loadPrepClaimGrid(facilityId, cn).Select(r => new BillingStageDataModel(r));