Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
a9b22a0
sketch of code gen
crusso Jan 19, 2026
923b144
curried versions, so viewer is just a function, defaulting to var.view()
crusso Jan 20, 2026
3775ce6
add infer_viwer
crusso Jan 21, 2026
c5614cb
working version (WIP)
crusso Jan 21, 2026
7ac4715
disable debug spew
crusso Jan 21, 2026
b115c08
reject inappropriate viewer
crusso Jan 21, 2026
279f251
reuse variable name for query name (cannot clash), support variables …
crusso Jan 21, 2026
e14746e
disable authentication for demo
crusso Jan 21, 2026
5e93c55
fix moc.js
crusso Jan 21, 2026
a64fe8a
Merge remote-tracking branch 'origin/master' into claudio/data-view
crusso Feb 2, 2026
67a7aec
merge with master
crusso Feb 2, 2026
79df36b
removve old test
crusso Feb 2, 2026
55a2bbd
mv test; add test output
crusso Feb 2, 2026
95ee335
don't drop actor type fields in desugaring
crusso Feb 2, 2026
59c3dca
disable core dependent test for CI
crusso Feb 2, 2026
f25f216
fix one
crusso Feb 2, 2026
5aec9ce
Merge remote-tracking branch 'origin/master' into claudio/data-view
crusso Feb 3, 2026
75710b6
enable core test
crusso Feb 3, 2026
a92dfee
fixes
crusso Feb 3, 2026
a2ec417
experiment: data viewer (alternative approach) (#5820)
crusso Feb 9, 2026
a841281
only reveal view methods in .did file; not custom sections. Then fron…
crusso Feb 12, 2026
e9181c2
Merge branch 'master' into claudio/data-view
crusso Feb 12, 2026
b4e2b51
better error on access control failure
crusso Feb 18, 2026
27b70fd
add isAdmin(caller) access control checks when available
crusso Feb 18, 2026
d3a90ef
Merge branch 'claudio/data-view' of github.com:dfinity/motoko into cl…
crusso Feb 18, 2026
85b16bc
prefix stable var queries with __; fix resolution of isAdmin; mark is…
crusso Feb 19, 2026
bc7ce79
use no to prefix queries (avoiding any clash and enabling easy disc…
crusso Feb 20, 2026
89d3a97
use . not __ to prefix queries (avoiding any clash and enabling easy …
crusso Feb 20, 2026
0a7643e
Merge branch 'claudio/data-view' of github.com:dfinity/motoko into cl…
crusso Feb 20, 2026
f791e07
revert to __ (. was a bad idea)
crusso Feb 20, 2026
6922bcf
update test output
crusso Feb 23, 2026
b5bfb07
add compiler flag --generate-view-queries (disabled by default)
crusso Feb 23, 2026
696638d
fix bug in flag logic; refactor for clarity
crusso Feb 23, 2026
8e9538c
Merge branch 'master' into claudio/data-view
crusso Mar 4, 2026
b06f119
missing test file
crusso Mar 4, 2026
e1498a8
missing output
crusso Mar 4, 2026
4ebc2a6
don't consider identifiers in generated queries used
crusso Mar 4, 2026
df47d39
update test output
crusso Mar 4, 2026
d567944
Apply suggestion from @crusso
crusso Mar 4, 2026
87a61d3
test file
crusso Mar 4, 2026
c9cdfe0
test option isAdmin functionality
crusso Mar 4, 2026
2a556d0
add more realistic sample
crusso Mar 4, 2026
1403e6e
typos
crusso Mar 4, 2026
9804aac
fix and test viewer arity bug
crusso Mar 4, 2026
89e1e6a
missing commits
crusso Mar 9, 2026
7a09f9f
Merge branch 'master' into claudio/data-view
crusso Mar 10, 2026
a20aa81
refactors infer_viewer by extracting some common bits (#5905)
christoph-dfinity Mar 12, 2026
73853e1
Merge branch 'master' into claudio/data-view
crusso Mar 16, 2026
0a4f983
undo dodgy refactoring that relies on eval order to infer typ
crusso Mar 16, 2026
ac76d28
first go at to_stable approximation
crusso Mar 16, 2026
ea8dc11
tweak: remove isAdmin functionality (#5912)
crusso Mar 16, 2026
9e4a823
Merge branch 'claudio/data-view' into claudio/data-view-approximate-s…
crusso Mar 16, 2026
fac3196
first stab (WIP)
crusso Mar 16, 2026
a5cd6a6
refactor and use CastPrim not let
crusso Mar 16, 2026
76b7b4c
adjust test
crusso Mar 16, 2026
a487893
fix broken casting in desugar.ml
crusso Mar 16, 2026
e93417d
test and fix set_king bug with recursive types
crusso Mar 16, 2026
ba4d77e
Merge branch 'master' into claudio/data-view
crusso Mar 26, 2026
908c3d3
add example of nested stable type, approximated
crusso Apr 7, 2026
c1e726b
remove unused viewer bindings
crusso Apr 7, 2026
f36837d
consider identifiers in successfully generated queries _used_
crusso Apr 7, 2026
7657c27
remove commented debug code
crusso Apr 7, 2026
3d4bf0f
merge with master
crusso Apr 7, 2026
678e537
merge with parent
crusso Apr 7, 2026
55e6ebc
Merge branch 'master' into claudio/data-view-approximate-shared
crusso Apr 9, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/mo_frontend/typing.ml
Original file line number Diff line number Diff line change
Expand Up @@ -4196,9 +4196,9 @@ and infer_viewer env scope mut id viewer =
then () (* avoid any clash with local or reserved `__motokoXXX` members by omitting viewer *)
else
let viewer_field args ret =
(* approximate non-shared returns to Any, if necessary *)
(* approximate any stable to shared returns, if necessary *)
let shared_ret =
List.map (fun ty -> if T.shared ty then ty else T.Any) ret in
List.map (fun ty -> if T.shared ty then ty else T.shared_of_stable ty) ret in
T.{ lab; typ = Func (Shared Query, Promises, [scope_bind], args, shared_ret); src = empty_src } in
let infer_dot_view =
Diag.with_message_store (recover_opt (fun msgs ->
Expand All @@ -4214,7 +4214,7 @@ and infer_viewer env scope mut id viewer =
let viewer_typ = infer_exp env exp in
match T.normalize viewer_typ with
| T.Func(T.Local, T.Returns, [], ts1, ts2)
when List.for_all T.shared ts1 && List.for_all T.shared ts2 ->
when List.for_all T.shared ts1 && List.for_all T.stable ts2 ->
{ viewer_body = DotViewV exp;
viewer_field = viewer_field ts1 ts2 }
| _ ->
Expand Down
52 changes: 52 additions & 0 deletions src/mo_types/type.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1016,6 +1016,58 @@ let is_local_async_func typ =
let shared t = serializable false t
let stable t = serializable true t

let shared_of_stable t =
assert (stable t);
let seen = ref ConEnv.empty in
let rec go t =
begin
match t with
| Var _ | Pre -> t
| Prim Error -> assert false
| Prim Region -> Any
| Any | Non | Prim _ -> t
| Async _ -> assert false
| Weak t -> Any
| Mut t -> Any
| Con (c, ts) ->
(match ConEnv.find_opt c !seen with
| Some c' -> Con (c', List.map go ts)
| None ->
match Cons.kind c with
| Abs _ -> Any
| Def(tbs, u) ->
(* copy constructor with approximated body *)
(* just weaken bounds to Any *)
let tbs' = List.map (fun tb -> {tb with bound = Any}) tbs in
let c' = Cons.fresh (Cons.name c) (Abs(tbs', Pre)) in
seen := ConEnv.add c c' !seen;
let u' = go u in
set_kind c' (Def(tbs', u'));
Con (c', List.map go ts))
| Array (Mut t) -> Any
| Array t -> Array (go t)
| Opt t -> Opt (go t)
| Tup ts -> Tup (List.map go ts)
| Obj (s, fs, ts) ->
(match s with
| Actor -> t
| Module | Mixin ->
assert false (* TODO(1452) make modules sharable *)
| Object | Memory ->
Obj(s,
(* drop mutable fields, approx others *)
List.filter_map (fun f ->
if is_mut f.typ then
None else
Some { f with typ = go f.typ }) fs, ts))
| Variant fs -> Variant (List.map (fun f -> {f with typ = go f.typ}) fs)
| Func (s, c, tbs, ts1, ts2) ->
assert (is_shared_sort s);
t
| Named (n, t) -> Named (n, go t)
end
in go t

(* Forward declare
TODO: haul string_of_typ before the lub/glb business, if possible *)
let str = ref (fun _ -> failwith "")
Expand Down
2 changes: 2 additions & 0 deletions src/mo_types/type.mli
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,8 @@ val is_local_async_func : typ -> bool

val stable : typ -> bool

val shared_of_stable : typ -> typ

val inhabited : typ -> bool
val singleton : typ -> bool

Expand Down
30 changes: 23 additions & 7 deletions test/run-drun/data-view-nested.mo
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//MOC-FLAG --generate-view-queries --package core $MOTOKO_CORE
import Map "mo:core/Map";
import Set "mo:core/Set";
import Nat "mo:core/Nat";
import Text "mo:core/Text";
import Principal "mo:core/Principal";
import Debug "mo:core/Debug";
Expand All @@ -11,8 +12,20 @@ import Views "data-view-sample/views";
/*
produces .did

type Set = record {}; // approximated
service : {
__customers: () -> (reserved) query; // approximated
__customers: (ko: opt text, count: opt nat) ->
(vec
record {
text;
record {
city: text;
companyName: text;
contactName: text;
contactTitle: text;
countries: Set;
};
}) query;
go: () -> ();
}
*/
Expand Down Expand Up @@ -47,16 +60,19 @@ persistent actor Self {
customers.add("CHOPS", {companyName = "Chop-suey Chinese"; contactName = "Yang Wang"; contactTitle = "Owner"; city = "Bern"; countries = Set.singleton "Switzerland"});
customers.add("COMMI", {companyName = "Comercio Mineiro"; contactName = "Pedro Afonso"; contactTitle = "Sales Associate"; city = "Sao Paulo"; countries = Set.singleton "Brazil"});

func debugShow(_ : Any) { Debug.print("any") };

public func go() : async () {
let views = actor (debug_show (Principal.fromActor(Self))) :
actor {
__customers: query () ->
async Any
__customers: query (ko: ?Text, count: ?Nat) ->
async [(Text,
{ city: Text;
companyName: Text;
contactName: Text;
contactTitle: Text;
countries: {} })]
};

debugShow(await views.__customers());
Debug.print(debug_show (await views.__customers(null, null))); // show all customers from first key
Debug.print(debug_show (await views.__customers(?"BOTTM", ?4))); // show at most 4 customers from key ""
}

}
Expand Down
34 changes: 17 additions & 17 deletions test/run-drun/data-view.mo
Original file line number Diff line number Diff line change
Expand Up @@ -20,23 +20,22 @@ persistent actor Self {
*/

// here, [array_of_non_shared.view] produces a non-shared result type,
// approximated to Any entries
// approximated to shared {b:{#B}; c : Any} entries
let array_of_non_shared : [var { var a : {#A}; b : {#B}; c : [var {#C}]}] =
[ var {var a = #A; b = #B; c = [var #C]} ];

/* generates
public query func __array_of_non_shared() :
async Any // <- approximation
{
array_of_non_shared : Any;
public query func __array_of_non_shared(start:Nat, count: Nat) : async [
{b:{#B}; c : Any} // <- approximation
] {
array_of_non_shared.view()(start, count);
};
*/

// here, [non_shared_array.view] produces a non-shared (mutable) type,
// approximate to Any
// approximate to [Any]
let non_shared_array : [[var Nat]] = [];


// shared values we can just display, sans viewer
type Tree = { #leaf; #node : (Tree, Nat, Tree) };
var some_variant = #node (#leaf, 0, #leaf);
Expand Down Expand Up @@ -67,36 +66,37 @@ persistent actor Self {
/* generates nothing as would clash with reserved __motoko_ members" */



public func go() : async () {
let views = actor (debug_show (Prim.principalOfActor(Self))) :
actor {
/* generated .views */
__array : shared query (Nat, Nat) -> async [(Nat, Text)];
__array_of_non_shared : shared query () -> async Any; // approximation
__array_of_non_shared : shared query (Nat, Nat) -> async [
{b:{#B}; c : Any} ];
/* generated simple */
__some_variant: shared query () -> async Tree;
__some_record : shared query () -> async {a:Nat; b: Text; c : Bool};
/* user-defined */
__override : shared query () -> async Text;
/* unable to generate because of (potential) name clash, no viewer or non-shared type*/
__non_shared_array : shared query() -> async Any; // approximation
__some_mutable_record : shared query() -> async Any; // approximation
__non_shared_array : shared query() -> async [Any];
__some_mutable_record : shared query() -> async {b : Nat; c : Any}; // drop a, approximate type of c
__some_list : shared query () -> async List<Nat>;
__some_non_shared_list : shared query () -> async Any; // approximation
__some_non_shared_list : shared query () -> async List<{b:Text}>;
__motoko_xxx : shared query () -> async None;

};
func printAny(_ : Any) { Prim.debugPrint("any") };
Prim.debugPrint(debug_show (await views.__array(0,0)));
Prim.debugPrint(debug_show (await views.__some_variant()));
Prim.debugPrint(debug_show (await views.__some_record()));
Prim.debugPrint(debug_show (await views.__override())); // calls user-defined method
Prim.debugPrint(debug_show (await views.__some_list()));
// debug_show doesn't support Any values, so avoid those below
printAny(await views.__array_of_non_shared());
printAny(await views.__non_shared_array());
printAny(await views.__some_mutable_record());
printAny(await views.__some_non_shared_list());
Prim.debugPrint(debug_show (await views.__array_of_non_shared(0,0)).size());
Prim.debugPrint(debug_show (await views.__non_shared_array()).size());
Prim.debugPrint(debug_show (await views.__some_mutable_record()).b);
Prim.debugPrint(debug_show (await views.__some_list()));
Prim.debugPrint(debug_show (await views.__some_non_shared_list()));
try {
await views.__motoko_xxx(); //fails with method not available
assert false;
Expand Down
1 change: 1 addition & 0 deletions test/run-drun/ok/data-view-nested.tc.ok
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
moc: multiple execution modes specified
1 change: 1 addition & 0 deletions test/run-drun/ok/data-view-nested.tc.ret.ok
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Return code 1
8 changes: 4 additions & 4 deletions test/run-drun/ok/data-view.drun-run.ok
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ debug.print: []
debug.print: #node(#leaf, 0, #leaf)
debug.print: {a = 1; b = "hello"; c = true}
debug.print: "user defined __override"
debug.print: 0
debug.print: 0
debug.print: 0
debug.print: ?(1, ?(2, null))
debug.print: any
debug.print: any
debug.print: any
debug.print: any
debug.print: ?({b = "1"}, ?({b = "2"}, null))
debug.print: IC0536: Error from Canister rwlgt-iiaaa-aaaaa-aaaaa-cai: Canister has no update method '__motoko_xxx'..
Check that the method being called is exported by the target canister. See documentation: https://internetcomputer.org/docs/current/references/execution-errors#method-not-found
ingress Completed: Reply: 0x4449444c0000
6 changes: 3 additions & 3 deletions test/run-drun/ok/data-view.tc.ok
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
data-view.mo:42.7-42.19: warning [M0244], variable some_variant is never reassigned, consider using `let`
data-view.mo:63.7-63.15: warning [M0194], unused identifier: `override`
data-view.mo:41.7-41.19: warning [M0244], variable some_variant is never reassigned, consider using `let`
data-view.mo:62.7-62.15: warning [M0194], unused identifier: `override`
help: if this is intentional, prefix it with an underscore: `_override`
data-view.mo:66.7-66.17: warning [M0194], unused identifier: `motoko_xxx`
data-view.mo:65.7-65.17: warning [M0194], unused identifier: `motoko_xxx`
help: if this is intentional, prefix it with an underscore: `_motoko_xxx`
Loading