package p4spectec
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>
P4-SpecTec: A mechanization toolchain for the P4 Programming Language
Install
dune-project
Dependency
Authors
Maintainers
Sources
v0.1.2.tar.gz
md5=1a3bc0a385fe1ecf403c019f49aa6de6
sha512=5d20b5821f33e2a3a5419b208606f27c01511994c2b3b1e1cdf4c077056dfd0aa81682af0720e1060ee2bfb0341918fcc4c53159820205a2bc32b725e5c1a714
doc/src/interp_pl/ctx.ml.html
Source file ctx.ml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381open Domain.Lib open Lang open Pl module Typdef = Runtime.Type.Typdef open Runtime.Dynamic_Pl open Envs open Interp_common.Error open Interp_common.Backtrace open Util.Source (* Error *) let error_undef (at : region) (kind : string) (id : string) = error at (Format.asprintf "%s `%s` is undefined" kind id) let back_undef (at : region) (kind : string) (id : string) = back_err at (Format.asprintf "%s `%s` is undefined" kind id) let error_dup (at : region) (kind : string) (id : string) = error at (Format.asprintf "%s `%s` was already defined" kind id) let back_dup (at : region) (kind : string) (id : string) = back_err at (Format.asprintf "%s `%s` was already defined" kind id) module Make () = struct (* Cursor *) type cursor = Global | Local (* Mode *) let is_det : bool ref = ref false (* Context *) (* Global layer *) type global = { (* Map from syntax ids to type definitions *) tdtbl : TDTbl.t; (* Map from relation ids to relations *) rtbl : RTbl.t; (* Map from function ids to functions *) ftbl : FTbl.t; } (* Local layer *) type local = | Empty | Rel of { (* Relation name *) rid : RId.t; (* Input values *) values_input : value list; (* Map from variables to values *) venv : VEnv.t; } | Func of { (* Function name *) fid : FId.t; (* Input values *) values_input : value list; (* Map from syntax ids to type definitions *) tdenv : TDEnv.t; (* Map from function ids to functions *) fenv : FEnv.t; (* Map from variables to values *) venv : VEnv.t; } type t = { global : global; local : local } (* Global constructor *) let global : global = let tdtbl = TDTbl.create ~size:500 in let rtbl = RTbl.create ~size:500 in let ftbl = FTbl.create ~size:500 in { tdtbl; rtbl; ftbl } (* Adders for globals *) let add_typdef_global (tid : TId.t) (td : Typdef.t) : unit = if TDTbl.find_opt tid global.tdtbl |> Option.is_some then error_dup tid.at "type" tid.it; TDTbl.add tid td global.tdtbl let add_rel_global (rid : RId.t) (rel : Rel.t) : unit = if RTbl.find_opt rid global.rtbl |> Option.is_some then error_dup rid.at "relation" rid.it; RTbl.add rid rel global.rtbl let add_func_global (fid : FId.t) (func : Func.t) : unit = if FTbl.find_opt fid global.ftbl |> Option.is_some then error_dup fid.at "function" fid.it; FTbl.add fid func global.ftbl (* Global initializer *) let load_def (def : def) : unit = match def.node.it with | ExternTypD id -> let td = Typdef.Extern in add_typdef_global id td | TypD (id, tparams, deftyp) -> let td = Typdef.Defined (tparams, deftyp) in add_typdef_global id td | VarD _ -> () | ExternRelD (id, rel_signature, _) -> let rel = Rel.Extern rel_signature in add_rel_global id rel | RelD (id, rel_signature, exps_match, block, elseblock_opt) -> let rel = Rel.Defined (rel_signature, exps_match, block, elseblock_opt) in add_rel_global id rel | ExternDecD (id, tparams, params, typ) -> let func = Func.Extern (tparams, params, typ) in add_func_global id func | BuiltinDecD (id, tparams, params, typ) -> let func = Func.Builtin (tparams, params, typ) in add_func_global id func | TableDecD (id, params, typ, tablerows) -> let func = Func.Table (params, typ, tablerows) in add_func_global id func | FuncDecD (id, tparams, params, typ, block, elseblock_opt) -> let func = Func.Defined (tparams, params, typ, block, elseblock_opt) in add_func_global id func let init ~(det : bool) (spec : spec) : unit = is_det := det; List.iter load_def spec (* Constructor *) let empty () : t = { global; local = Empty } (* Finders *) (* Finders for input values *) let find_values_input_opt (ctx : t) : Value.t list option = match ctx.local with | Empty -> None | Rel { values_input; _ } -> Some values_input | Func { values_input; _ } -> Some values_input let find_values_input (ctx : t) : Value.t list = match find_values_input_opt ctx with | Some values_input -> values_input | None -> back_err no_region "cannot find input values in empty local context" (* Finders for values *) let find_value_opt (ctx : t) (var : Var.t) : Value.t option = match ctx.local with | Empty -> None | Rel { venv; _ } -> VEnv.find_opt var venv | Func { venv; _ } -> VEnv.find_opt var venv let find_value (ctx : t) (var : Var.t) : Value.t = match find_value_opt ctx var with | Some value -> value | None -> let id, _ = var in back_undef id.at "value" (Var.to_string var) let bound_value (ctx : t) (var : Var.t) : bool = find_value_opt ctx var |> Option.is_some (* Finders for type definitions *) let find_typdef_opt (ctx : t) (tid : TId.t) : Typdef.t option = let tdenv = match ctx.local with | Empty | Rel _ -> TDEnv.empty | Func { tdenv; _ } -> tdenv in match TDEnv.find_opt tid tdenv with | Some td -> Some td | None -> TDTbl.find_opt tid ctx.global.tdtbl let find_typdef (ctx : t) (tid : TId.t) : Typdef.t = match find_typdef_opt ctx tid with | Some td -> td | None -> back_undef tid.at "type" tid.it let find_defined_typdef (ctx : t) (tid : TId.t) : tparam list * deftyp = match find_typdef ctx tid with | Param | Extern | Defining _ -> back_undef tid.at "defined type" tid.it | Defined (tparams, deftyp) -> (tparams, deftyp) let bound_typdef (ctx : t) (tid : TId.t) : bool = find_typdef_opt ctx tid |> Option.is_some (* Finders for rules *) let find_rel_opt (ctx : t) (rid : RId.t) : Rel.t option = RTbl.find_opt rid ctx.global.rtbl let find_rel (ctx : t) (rid : RId.t) : Rel.t = match find_rel_opt ctx rid with | Some rel -> rel | None -> back_undef rid.at "relation" rid.it let find_rel_signature_opt (ctx : t) (rid : RId.t) : (nottyp * Hints.Input.t) option = find_rel_opt ctx rid |> Option.map Rel.get_signature let find_rel_signature (ctx : t) (rid : RId.t) : nottyp * Hints.Input.t = match find_rel_signature_opt ctx rid with | Some (nottyp, inputs) -> (nottyp, inputs) | None -> back_undef rid.at "relation" rid.it let bound_rel (ctx : t) (rid : RId.t) : bool = find_rel_opt ctx rid |> Option.is_some (* Finders for definitions *) let find_func_opt (ctx : t) (fid : FId.t) : (cursor * Func.t) option = let fenv = match ctx.local with | Empty | Rel _ -> FEnv.empty | Func { fenv; _ } -> fenv in match FEnv.find_opt fid fenv with | Some func -> Some (Local, func) | None -> FTbl.find_opt fid ctx.global.ftbl |> Option.map (fun func -> (Global, func)) let find_func (ctx : t) (fid : FId.t) : cursor * Func.t = match find_func_opt ctx fid with | Some (cursor, func) -> (cursor, func) | None -> back_undef fid.at "function" fid.it let find_func_signature_opt (ctx : t) (fid : FId.t) : (tparam list * typ list * typ) option = find_func_opt ctx fid |> Option.map (fun (_, func) -> Func.get_signature func) let find_func_signature (ctx : t) (fid : FId.t) : tparam list * typ list * typ = match find_func_signature_opt ctx fid with | Some (tparams, typs, typ) -> (tparams, typs, typ) | None -> back_undef fid.at "function" fid.it let bound_func (ctx : t) (fid : FId.t) : bool = find_func_opt ctx fid |> Option.is_some (* Adders *) (* Adders for values *) let add_value (ctx : t) (var : Var.t) (value : Value.t) : t = match ctx.local with | Empty -> let id, _ = var in back_err id.at "cannot add value to empty local context" | Rel { rid; values_input; venv } -> let venv = VEnv.add var value venv in { ctx with local = Rel { rid; values_input; venv } } | Func { fid; values_input; tdenv; fenv; venv } -> let venv = VEnv.add var value venv in { ctx with local = Func { fid; values_input; tdenv; fenv; venv } } (* Adders for type definitions *) let add_typdef (ctx : t) (tid : TId.t) (td : Typdef.t) : t = if bound_typdef ctx tid then back_dup tid.at "type" tid.it; match ctx.local with | Empty -> back_err tid.at "cannot add type to empty local context" | Rel _ -> back_err tid.at "cannot add type to rule context" | Func { fid; values_input; tdenv; fenv; venv } -> let tdenv = TDEnv.add tid td tdenv in { ctx with local = Func { fid; values_input; tdenv; fenv; venv } } (* Adders for functions *) let add_func (ctx : t) (fid : FId.t) (func : Func.t) : t = if bound_func ctx fid then back_dup fid.at "function" fid.it; match ctx.local with | Empty -> back_err fid.at "cannot add function to empty local context" | Rel _ -> back_err fid.at "cannot add function to relation context" | Func { fid = fid_local; values_input; tdenv; fenv; venv } -> let fenv = FEnv.add fid func fenv in { ctx with local = Func { fid = fid_local; values_input; tdenv; fenv; venv }; } (* Constructors *) (* Constructing a local context *) let localize (ctx : t) : t = { ctx with local = Empty } let localize_rule (ctx : t) (rid : RId.t) (values_input : value list) : t = let local = Rel { rid; values_input; venv = VEnv.empty } in { ctx with local } let localize_func (ctx : t) (fid : FId.t) (values_input : value list) (tdenv : TDEnv.t) : t = let local = Func { fid; values_input; tdenv; fenv = FEnv.empty; venv = VEnv.empty } in { ctx with local } let localize_clear (ctx : t) : t = match ctx.local with | Empty -> back_err no_region "cannot clear empty local context" | Rel { rid; values_input; _ } -> { ctx with local = Rel { rid; values_input; venv = VEnv.empty } } | Func { fid; values_input; tdenv; fenv; _ } -> { ctx with local = Func { fid; values_input; tdenv; fenv; venv = VEnv.empty }; } (* Constructing sub-contexts *) (* Transpose a matrix of values, as a list of value batches that are to be each fed into an iterated expression *) let transpose (value_matrix : value list list) : value list list = match value_matrix with | [] -> [] | row_h :: _ -> let width = List.length row_h in let cols = Array.make width [] in List.iter (fun row -> check_back_err (List.length row = width) no_region "cannot transpose a matrix of value batches"; List.iteri (fun j v -> cols.(j) <- v :: cols.(j)) row) (List.rev value_matrix); Array.to_list cols let sub_opt (ctx : t) (vars : var list) : t option = (* First collect the values that are to be iterated over *) let values = List.map (fun (id, _typ, iters) -> find_value ctx (id, iters @ [ Il.Opt ]) |> Value.Get.opt) vars in (* Iteration is valid when all variables agree on their optionality *) if List.for_all Option.is_some values then let values = List.map Option.get values in let ctx_sub = List.fold_left2 (fun ctx_sub (id, _typ, iters) value -> add_value ctx_sub (id, iters) value) ctx vars values in Some ctx_sub else if List.for_all Option.is_none values then None else back_err no_region "mismatch in optionality of iterated variables" let sub_list (ctx : t) (vars : var list) : t list = (* First break the values that are to be iterated over, into a batch of values *) let values_batch = List.map (fun (id, _typ, iters) -> find_value ctx (id, iters @ [ Il.List ]) |> Value.Get.list) vars |> transpose in (* For each batch of values, create a sub-context *) List.map (fun value_batch -> List.fold_left2 (fun ctx_sub (id, _typ, iters) value -> add_value ctx_sub (id, iters) value) ctx vars value_batch) values_batch end
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>