ordinary_app_access.bend

bendvy-ecs-core@0.1.0.0 · 104 lines · 0 definitions

1import Base
2import bendvy-ecs-core@0.1.0.0/world.bend as W
3import bendvy-ecs-core@0.1.0.0/ordinary_schema.bend as Schema
4import bendvy-ecs-core@0.1.0.0/ordinary_app_schema.bend as SchemaApp
5import bendvy-ecs-core@0.1.0.0/ordinary_app_registration_fields.bend as Records
6import bendvy-ecs-core@0.1.0.0/ordinary_query_declaration.bend as Query
7import bendvy-ecs-core@0.1.0.0/ordinary_app_composer.bend as App
8import bendvy-ecs-core@0.1.0.0/ordinary_app_recipe.bend as Tree
9import bendvy-ecs-core@0.1.0.0/ordinary_app_observation_data.bend as DTO
10import bendvy-ecs-core@0.1.0.0/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))