@@ -729,9 +729,9 @@ let private createChoiceChild (r:Asn1AcnAst.AstRoot) (lm:LanguageMacros) (m:Asn
729729let private createReferenceType ( r : Asn1AcnAst.AstRoot ) ( deps : Asn1AcnAst.AcnInsertedFieldDependencies ) ( lm : LanguageMacros ) ( m : Asn1AcnAst.Asn1Module ) ( pi : Asn1Fold.ParentInfo < ParentInfoData > option ) ( t : Asn1AcnAst.Asn1Type ) ( o : Asn1AcnAst.ReferenceType ) ( newResolvedType : Asn1Type , us : State ) =
730730 let newPrms , us0 = t.acnParameters |> foldMap( fun ns p -> mapAcnParameter r deps lm m t p ns) us
731731 let defOrRef = lm.lg.definitionOrRef o.definitionOrRef
732- let equalFunction = DAstEqual.createReferenceTypeEqualFunction r lm t o defOrRef newResolvedType
733- let initFunction = DAstInitialize.createReferenceType r lm t o defOrRef newResolvedType
734- let isValidFunction , s1 = DastValidate2.createReferenceTypeFunction r lm t o defOrRef newResolvedType us
732+ let equalFunction , s00 = DAstEqual.createReferenceTypeEqualFunction r lm t o defOrRef newResolvedType us
733+ let initFunction , s0 = DAstInitialize.createReferenceType r lm t o defOrRef newResolvedType s00
734+ let isValidFunction , s1 = DastValidate2.createReferenceTypeFunction r lm t o defOrRef newResolvedType s0
735735 let uperEncFunction , s2 = DAstUPer.createReferenceFunction r lm Codec.Encode t o defOrRef isValidFunction newResolvedType s1
736736 let uperDecFunction , s3 = DAstUPer.createReferenceFunction r lm Codec.Decode t o defOrRef isValidFunction newResolvedType s2
737737 let acnEncFunction , s4 = DAstACN.createReferenceFunction r deps lm Codec.Encode t o defOrRef isValidFunction newResolvedType s3
@@ -782,6 +782,7 @@ let private createType (r:Asn1AcnAst.AstRoot) pi (t:Asn1AcnAst.Asn1Type) ((newKi
782782 inheritInfo = t.inheritInfo
783783 typeAssignmentInfo = t.typeAssignmentInfo
784784 unitsOfMeasure = t.unitsOfMeasure
785+ referencedBy = t.referencedBy
785786 //newTypeDefName = DAstTypeDefinition2.getTypedefName r pi t
786787 }
787788 match us.newTypesMap.ContainsKey t.id with
@@ -1000,41 +1001,203 @@ let private mapFile (r:Asn1AcnAst.AstRoot) (newTasMap : Map<TypeAssignmentInfo,
10001001let private reMapFile ( r : Asn1AcnAst.AstRoot ) ( icdStgFileName : string ) ( files0 : Asn1File list ) ( deps : Asn1AcnAst.AcnInsertedFieldDependencies ) ( lm : LanguageMacros ) ( f : Asn1File ) ( us : State ) =
10011002 let newModules , ns = f.Modules |> foldMap ( fun cs m -> reMapModule r icdStgFileName files0 deps lm m cs) us
10021003 { f with Modules = newModules}, ns
1003- (*
1004- //the following functions determines which functions are used by PDU types.
1005- //Only those functions are generated in the generated code.
1006- let determinGeneratedFunctions (r:Asn1AcnAst.AstRoot) (files: Asn1File list) (us:State) =
1007- let getFunctionCalls (tasId:ReferenceToType)=
1004+
1005+ let detectPDUs2 ( r : Asn1AcnAst.AstRoot ) =
1006+ let callesMap =
1007+ r.allDependencies |>
1008+ List.groupBy( fun ( a , _ ) -> a) |> //group by caller
1009+ List.map( fun ( a , b ) -> a, b |> List.map snd |> List.distinct) |> //remove duplicates
1010+ Map.ofList
1011+
1012+ let callesSet =
1013+ r.allDependencies |>
1014+ List.map( fun ( caller , callee ) -> callee) |>
1015+ Set.ofList
1016+
1017+ let rec getCallesCount ( tsInfo : TypeAssignmentInfo ) =
1018+ match callesMap.TryFind tsInfo with
1019+ | None -> 0
1020+ | Some l ->
1021+ let l1 = l.Length
1022+ let l2 = l |> List.map getCallesCount |> List.sum
1023+ l1 + l2
1024+
1025+ //PDUS are the types that are not called by any other types
1026+ let pdus =
1027+ seq {
1028+ for f in r.Files do
1029+ for m in f.Modules do
1030+ for tas in m.TypeAssignments do
1031+ let tsInfo = { TypeAssignmentInfo.modName = m.Name.Value; tasName = tas.Name.Value}
1032+ if not ( callesSet.Contains tsInfo) then
1033+ yield ( tsInfo, getCallesCount tsInfo)
1034+ } |> Seq.toList
1035+
1036+ let pudsSorted = pdus |> List.sortByDescending( fun ( tas , callesCnt ) -> callesCnt)
1037+ let maxToPrint = min 100 ( pudsSorted.Length)
1038+ printfn " PDUs detected: %d . Printing the first %d " pudsSorted.Length maxToPrint
1039+ for ( tas, callesCnt) in pudsSorted |> List.take maxToPrint do
1040+ printfn " %s .%s references %d types" tas.modName tas.tasName callesCnt
1041+
1042+ let detectPDUs ( r : Asn1AcnAst.AstRoot ) ( us : State ) =
1043+ let functionTypes = Set.ofList [ AcnEncDecFunctionType]
1044+ let functionCalls = us.functionCalls |> Map.filter( fun z _ -> z.funcType = AcnEncDecFunctionType)
1045+ printfn " Detecting PDUs. Function calls: %d " functionCalls.Count
1046+
1047+ //print all calls
1048+ printfn " == Calls detected =="
1049+ functionCalls |> Seq.iter( fun fc ->
1050+ let calleesStr = sprintf " %s .%s " fc.Key.typeId.modName fc.Key.typeId.tasName
1051+ let callees = fc.Value |> List.map( fun c -> c.typeId) |> List.distinct |> List.map( fun z -> sprintf " %s .%s " z.modName z.tasName) |> Seq.StrJoin " , "
1052+ printfn " %s calls %s " calleesStr callees)
1053+ printfn " == End of calls =="
1054+
1055+ let memo = System.Collections.Generic.Dictionary< Caller, Set< Caller> >()
1056+ let rec getCallees2 bIsTass ( c : Caller ) =
1057+ let getCallees2_aux ( c : Caller ) =
1058+ if memo.ContainsKey( c) then
1059+ memo.[ c]
1060+ else
1061+ let result =
1062+ match functionCalls.ContainsKey( c) with
1063+ | false ->
1064+ match bIsTass with
1065+ | true -> Set.empty
1066+ | false -> Set.singleton c
1067+ | true ->
1068+ let callees = functionCalls.[ c]
1069+ let ret2 =
1070+ callees
1071+ |> List.map ( fun callee -> getCallees2 false { Caller.typeId = callee.typeId; funcType = callee.funcType})
1072+ |> List.fold Set.union Set.empty
1073+ match bIsTass with
1074+ | true -> ret2
1075+ | false -> Set.add c ret2
1076+ memo.[ c] <- result
1077+ result
1078+ getCallees2_ aux c
1079+
1080+ let callesList =
10081081 seq {
1009- for c in us.functionCalls do
1010- if c.Key.typeId.AsString.StartsWith (tasId.AsString) then
1011- yield (c.Key, c.Value)
1082+ for f in r.Files do
1083+ for m in f.Modules do
1084+ for tas in m.TypeAssignments do
1085+ for fncType in functionTypes do
1086+ //let msg = sprintf "Processing %s.%s. " m.Name.Value tas.Name.Value
1087+ //printf "%s" msg
1088+ let tsInfo = { TypeAssignmentInfo.modName = m.Name.Value; tasName = tas.Name.Value}
1089+ let caller = { Caller.typeId = tsInfo; funcType = fncType}
1090+ //let calles = getCallees true caller |> List.map(fun c -> c.typeId) |> List.distinct
1091+ if tas.Name.Value = " Observable-Event" then
1092+ printfn " debug"
1093+ let calles = getCallees2 true caller |> Set.map( fun c -> c.typeId)
1094+ //printfn "Calles detected: %d" calles.Length
1095+ yield calles
10121096 } |> Seq.toList
1097+ printfn " Calles detected: %d " callesList.Length
1098+ //let callesMap = callesList |> List.collect id |> List.distinct |> Set.ofList
1099+ let callesMap = callesList |> List.fold ( fun acc x -> Set.union acc x) Set.empty
10131100
1014- let allTasses =
1101+ //PDUS are the types that are not called by any other types
1102+ let pdus =
10151103 seq {
1016- for f in files do
1104+ for f in r.Files do
10171105 for m in f.Modules do
10181106 for tas in m.TypeAssignments do
1019- match tas.Type.isValidFunction with
1020- | None -> ()
1021- | Some isValidFunction ->
1022- match isValidFunction.funcName with
1023- | None -> ()
1024- | Some fncName ->
1025- let fncCalls = getFunctionCalls tas.Type.id
1026- yield {modName = m.Name.Value; tasName = tas.Name.Value; validationFunName = fncName; validationDependencies = fncCalls}
1027-
1028- } |> List.ofSeq
1029- let ret =
1030- match r.args.icdPdus with
1031- | None -> allTasses |> List.map(fun tas -> tas.modName, tas.tasName)
1032- | Some pdus ->
1033- let pduTas = pdus |> List.choose (fun pdu -> allTasses |> List.tryFind(fun tas -> tas.tasName = pdu))
1034- 0
1035- 0
1036-
1037- *)
1107+ let tsInfo = { TypeAssignmentInfo.modName = m.Name.Value; tasName = tas.Name.Value}
1108+ if not ( callesMap.Contains tsInfo) then
1109+ //printfn "PDU detected: %s.%s" m.Name.Value tas.Name.Value
1110+ let caller = { Caller.typeId = tsInfo; funcType = AcnEncDecFunctionType}
1111+ //let calles = getCallees true caller |> List.map(fun c -> c.typeId) |> List.distinct
1112+ let calles = getCallees2 true caller |> Set.map( fun c -> c.typeId)
1113+ yield ( tsInfo, calles)
1114+ } |> Seq.toList
1115+
1116+ let pudsSorted = pdus |> List.sortByDescending( fun ( tas , calles ) -> calles.Count)
1117+ let maxToPrint = min 100 ( pudsSorted.Length)
1118+ printfn " PDUs detected: %d . Printing the first %d " pudsSorted.Length maxToPrint
1119+ for ( tas, calles) in pudsSorted |> List.take maxToPrint do
1120+ printfn " %s .%s references %d types" tas.modName tas.tasName calles.Count
1121+
1122+ let calculateFunctionToBeGenerated ( r : Asn1AcnAst.AstRoot ) ( us : State ) =
1123+ let functionCalls = us.functionCalls
1124+ let requiresUPER = r.args.encodings |> Seq.exists ( (=) Asn1Encoding.UPER)
1125+ let requiresAcn = r.args.encodings |> Seq.exists ( (=) Asn1Encoding.ACN)
1126+
1127+ let functionTypes =
1128+ seq {
1129+ yield InitFunctionType;
1130+ yield IsValidFunctionType;
1131+ if r.args.GenerateEqualFunctions then yield EqualFunctionType;
1132+ if requiresUPER then yield UperEncDecFunctionType;
1133+ if requiresAcn then yield AcnEncDecFunctionType;
1134+ } |> Seq.toList
1135+
1136+ (*
1137+ let rec getCallees (c: Caller)=
1138+ seq {
1139+ yield c
1140+ match functionCalls.ContainsKey c with
1141+ | false -> ()
1142+ | true ->
1143+ let callees = functionCalls[c]
1144+ for callee in callees do
1145+ yield! getCallees {Caller.typeId = callee.typeId; funcType = callee.funcType}
1146+ } |> Seq.toList
1147+ *)
1148+ let memo2 = System.Collections.Generic.Dictionary< Caller, Set< Caller> >()
1149+ let rec getCallees ( c : Caller )=
1150+ if memo2.Count% 50 = 0 then printfn " Processing %d " memo2.Count
1151+ match memo2.ContainsKey( c) with
1152+ | true -> memo2.[ c]
1153+ | false ->
1154+ let getCallees_aux ( c : Caller ) =
1155+ let result =
1156+ match functionCalls.ContainsKey c with
1157+ | false -> Set.singleton c
1158+ | true ->
1159+ let callees = functionCalls[ c]
1160+ let ret2 =
1161+ callees
1162+ |> List.map ( fun callee -> getCallees { Caller.typeId = callee.typeId; funcType = callee.funcType})
1163+ |> List.fold Set.union Set.empty
1164+ Set.add c ret2
1165+ memo2.[ c] <- result
1166+ result
1167+ getCallees_ aux c
1168+
1169+ let ret =
1170+ seq {
1171+ for f in r.Files do
1172+ for m in f.Modules do
1173+ let tasToGenerate , bFindCalles =
1174+ match r.args.icdPdus with
1175+ | None -> m.TypeAssignments, false
1176+ | Some pdus -> pdus |> List.choose ( fun pdu -> m.TypeAssignments |> List.tryFind( fun tas -> tas.Name.Value = pdu)), true
1177+ for tas in tasToGenerate do
1178+ for fncType in functionTypes do
1179+ let tsInfo = { TypeAssignmentInfo.modName = m.Name.Value; tasName = tas.Name.Value}
1180+ let caller = { Caller.typeId = tsInfo; funcType = fncType}
1181+ match bFindCalles with
1182+ | true -> yield ! getCallees caller
1183+ | false -> yield caller
1184+ } |> Set.ofSeq
1185+ printfn " Function calls detected: %d " ret.Count
1186+ match r.args.icdPdus with
1187+ | None -> ()
1188+ | Some _ ->
1189+ //let's print in the console the functions that will not be generated
1190+ let s = ret
1191+ for f in r.Files do
1192+ for m in f.Modules do
1193+ for tas in m.TypeAssignments do
1194+ for fncType in functionTypes do
1195+ let tsInfo = { TypeAssignmentInfo.modName = m.Name.Value; tasName = tas.Name.Value}
1196+ let caller = { Caller.typeId = tsInfo; funcType = fncType}
1197+ if not ( s.Contains caller) then
1198+ printfn " Function %A will not be generated for %s .%s " fncType tsInfo.modName tsInfo.tasName
1199+
1200+ ret
10381201
10391202let DoWork ( r : Asn1AcnAst.AstRoot ) ( icdStgFileName : string ) ( deps : Asn1AcnAst.AcnInsertedFieldDependencies ) ( lang : CommonTypes.ProgrammingLanguage ) ( lm : LanguageMacros ) ( encodings : CommonTypes.Asn1Encoding list ) : AstRoot =
10401203 let l = lang
@@ -1063,6 +1226,8 @@ let DoWork (r:Asn1AcnAst.AstRoot) (icdStgFileName:string) (deps:Asn1AcnAst.AcnIn
10631226 let files0 , ns = TL " mapFile" ( fun () -> r.Files |> foldMap ( fun cs f -> mapFile r newTasMap icdStgFileName deps lm f cs) ns0)
10641227 let files , ns = TL " reMapFile" ( fun () -> files0 |> foldMap ( fun cs f -> reMapFile r icdStgFileName files0 deps lm f cs) ns)
10651228 let icdTases = ns.icdHashes
1229+ if r.args.detectPdus then
1230+ detectPDUs2 r //this function will print the PDUs detected
10661231 {
10671232 AstRoot.Files = files
10681233 acnConstants = r.acnConstants
@@ -1072,4 +1237,5 @@ let DoWork (r:Asn1AcnAst.AstRoot) (icdStgFileName:string) (deps:Asn1AcnAst.AcnIn
10721237 acnParseResults = r.acnParseResults
10731238 deps = deps
10741239 icdHashes = ns.icdHashes
1240+ callersSet = calculateFunctionToBeGenerated r ns
10751241 }
0 commit comments