ordinary_app_access.bend
bendvy-ecs-core@0.1.0.1 · 104 lines · 0 definitions
1import Base
2import bendvy-ecs-core@0.1.0.1/world.bend as W
3import bendvy-ecs-core@0.1.0.1/ordinary_schema.bend as Schema
4import bendvy-ecs-core@0.1.0.1/ordinary_app_schema.bend as SchemaApp
5import bendvy-ecs-core@0.1.0.1/ordinary_app_registration_fields.bend as Records
6import bendvy-ecs-core@0.1.0.1/ordinary_query_declaration.bend as Query
7import bendvy-ecs-core@0.1.0.1/ordinary_app_composer.bend as App
8import bendvy-ecs-core@0.1.0.1/ordinary_app_recipe.bend as Tree
9import bendvy-ecs-core@0.1.0.1/ordinary_app_observation_data.bend as DTO
10import bendvy-ecs-core@0.1.0.1/ordinary_app_description.bend as Description
11
12type Category is Data:
13 Components{}
14 Resources{}
15 Events{}
16 Services{}
17type Role is Data:
18 Reader{}
19 Writer{}
20 Filter{}
21type Use is Data:
22 Use{namespace:U32,id:U32,name:String,mode:Query.Mode,role:Role}
23type Entry is Data:
24 Entry{category:Category,key:String,uses:List<&2,Use>}
25# Typed modes retain the exact operational declaration, including filter-only modes.
26def resource_fields(~S:Data,+mode:Query.Mode,access:List<&2,String>) -> List<&2,Query.Clause<S>>:
27 match access:
28 case []:[]
29 case name <> rest:Query.Clause{name,mode} <> resource_fields(~S,mode,rest)
30def clauses(~S:Data,kind:Records.RegistrationKind,access:List<&2,String>,retained:List<&2,Query.Clause<S>>) -> List<&2,Query.Clause<S>>:
31 match kind:
32 case Records.ComponentKind{}:retained
33 case Records.FieldKind{}:retained
34 case Records.ServiceKind{}:[]
35 case Records.EventKind{}:retained
36 case Records.MixedKind{uses}:Description.mixed_clauses(~S,uses)
37 case Records.ResourceKind{mode}:resource_fields(~S,mode,access)
38def role(mode:Query.Mode) -> Role:
39 match mode:
40 case Query.Write{}:Writer{}
41 case Query.With{}:Filter{}
42 case Query.Without{}:Filter{}
43 case Query.Read{}:Reader{}
44 case Query.Optional{}:Reader{}
45 case Query.Added{}:Reader{}
46 case Query.Changed{}:Reader{}
47def entries(~S:Data,+category:Category,+namespace:U32,+id:U32,+name:String,clauses:List<&2,Query.Clause<S>>) -> List<&2,Entry>:
48 match clauses:
49 case []:[]
50 case Query.Clause{key,+mode} <> rest:Entry{category,key,[Use{namespace,id,name,mode,role(mode)}]} <> entries(~S,category,namespace,id,name,rest)
51def mixed_category(category:Records.UseCategory) -> Category:
52 match category:
53 case Records.ComponentUse{}:Components{}
54 case Records.ResourceUse{}:Resources{}
55 case Records.EventUse{}:Events{}
56def mixed_entries(~S:Data,+namespace:U32,+id:U32,+name:String,uses:List<&2,Records.DeclaredUse>) -> List<&2,Entry>:
57 match uses:
58 case []:[]
59 case Records.DeclaredUse{category,_,key,+mode} <> rest:Entry{mixed_category(category),key,[Use{namespace,id,name,mode,role(mode)}]} <> mixed_entries(~S,namespace,id,name,rest)
60def kind_entries(~S:Data,+namespace:U32,+id:U32,+name:String,slot:String,access:List<&2,String>,retained:List<&2,Query.Clause<S>>,kind:Records.RegistrationKind) -> List<&2,Entry>:
61 match kind:
62 case Records.ComponentKind{}:entries(~S,Components{},namespace,id,name,retained)
63 case Records.FieldKind{}:entries(~S,Resources{},namespace,id,name,retained)
64 case Records.ServiceKind{}:[Entry{Services{},slot,[]}]
65 case Records.EventKind{}:entries(~S,Events{},namespace,id,name,retained)
66 case Records.ResourceKind{mode}:entries(~S,Resources{},namespace,id,name,resource_fields(~S,mode,access))
67 case Records.MixedKind{uses}:mixed_entries(~S,namespace,id,name,uses)
68def fields(~S:Data,records:List<&2,Records.Fields<S>>) -> List<&2,Entry>:
69 match records:
70 case []:[]
71 case Records.Fields{namespace,id,name,access,_,slot,retained,kind} <> rest:List.append(&2,Entry,kind_entries(~S,namespace,id,name,slot,access,retained,kind),fields(~S,rest))
72def same_category(left:Category,right:Category) -> Bool:
73 match left right:
74 case Components{} Components{}:True{}
75 case Resources{} Resources{}:True{}
76 case Events{} Events{}:True{}
77 case Services{} Services{}:True{}
78 case _ _:False{}
79def selected(found:Bool,category:Category,key:String,uses:List<&2,Use>,other:Category,otherKey:String,otherUses:List<&2,Use>,rest:List<&2,Entry>,tail:Unit -> List<&2,Entry>) -> List<&2,Entry>:
80 match found:
81 case True{}:Entry{other,otherKey,List.append(&2,Use,otherUses,uses)} <> rest
82 case False{}:Entry{other,otherKey,otherUses} <> tail(Unit{})
83def insert(+category:Category,+key:String,+uses:List<&2,Use>,entries:List<&2,Entry>) -> List<&2,Entry>:
84 match entries:
85 case []:[Entry{category,key,uses}]
86 case Entry{+other,+otherKey,+otherUses} <> +rest:selected(Bool.and(same_category(category,other),String.eq(key,otherKey)),category,key,uses,other,otherKey,otherUses,rest,_ => insert(category,key,uses,rest))
87def grouped(entries:List<&2,Entry>,index:List<&2,Entry>) -> List<&2,Entry>:
88 match entries:
89 case []:index
90 case Entry{category,key,uses} <> rest:grouped(rest,insert(category,key,uses,index))
91def folded(~S:Data,~World:Type,~Owners:Type,~Rows:Data,~observe:World -> World & DTO.Observation<Rows>,~fold:Owners -> Owners & List<&2,Records.Fields<S>>,world:World,recipe:Tree.Recipe<World,Rows,observe>,result:Owners & List<&2,Records.Fields<S>>) -> App.Registered<S,World,Owners,Rows,observe,fold> & Maybe<&2,List<&2,Entry>>:
92 match result:
93 case (owners,records):(App.Registered{world,owners,recipe,True{}},Some{grouped(fields(~S,records),[])})
94def index(~S:Data,~World:Type,~Owners:Type,~Rows:Data,~observe:World -> World & DTO.Observation<Rows>,~fold:Owners -> Owners & List<&2,Records.Fields<S>>,app:App.Registered<S,World,Owners,Rows,observe,fold>) -> App.Registered<S,World,Owners,Rows,observe,fold> & Maybe<&2,List<&2,Entry>>:
95 match app:
96 case App.Registered{world,owners,recipe,False{}}:(App.Registered{world,owners,recipe,False{}},None{})
97 case App.Registered{world,owners,recipe,True{}}:folded(~S,~World,~Owners,~Rows,~observe,~fold,world,recipe,fold(owners))
98
99def schema_returned(~S:Data,~C:Type,~R:Type,~E:Data,~Owners:Type,~Rows:Data,~observe:W.World<S,C,R,E> -> W.World<S,C,R,E> & DTO.Observation<Rows>,~fold:Owners -> Owners & List<&2,Records.Fields<S>>,schema:Schema.Schema<S,C,R>,result:App.Registered<S,W.World<S,C,R,E>,Owners,Rows,observe,fold> & Maybe<&2,List<&2,Entry>>) -> SchemaApp.Application<S,C,R,E,Owners,Rows,observe,fold> & Maybe<&2,List<&2,Entry>>:
100 match result:
101 case (app,view):(SchemaApp.Application{schema,app},view)
102def schema_index(~S:Data,~C:Type,~R:Type,~E:Data,~Owners:Type,~Rows:Data,~observe:W.World<S,C,R,E> -> W.World<S,C,R,E> & DTO.Observation<Rows>,~fold:Owners -> Owners & List<&2,Records.Fields<S>>,value:SchemaApp.Application<S,C,R,E,Owners,Rows,observe,fold>) -> SchemaApp.Application<S,C,R,E,Owners,Rows,observe,fold> & Maybe<&2,List<&2,Entry>>:
103 match value:
104 case SchemaApp.Application{schema,app}:schema_returned(~S,~C,~R,~E,~Owners,~Rows,~observe,~fold,schema,index(~S,~W.World<S,C,R,E>,~Owners,~Rows,~observe,~fold,app))