diff --git a/cozy/codegen/cxx.py b/cozy/codegen/cxx.py index d9decf5e..275dcf58 100644 --- a/cozy/codegen/cxx.py +++ b/cozy/codegen/cxx.py @@ -274,6 +274,14 @@ def construct_concrete(self, t : Type, e : Exp, out : Exp): return SEscape("{indent}{lhs} = {rhs};\n", ["lhs", "rhs"], [out, e]) elif is_scalar(t): return SEscape("{indent}{lhs} = {rhs};\n", ["lhs", "rhs"], [out, e]) + elif isinstance(t, TTuple): + x = self.fv(t, "x") + indices = range(len(t.ts)) + return SSeq( + SEscape("{indent}{rv} = {rhs};\n", ["rv", "rhs"], [x, e]), + SEscape("{indent}{lhs} = {rv};\n", ["lhs", "rv"], + [out, ETuple([ETupleGet(x, i).with_type(t.ts[i]) for i in indices]).with_type(t)]), + ) else: h = extension_handler(type(t)) if h is not None: diff --git a/cozy/synthesis/core.py b/cozy/synthesis/core.py index 6e60fde6..6b4c68bf 100644 --- a/cozy/synthesis/core.py +++ b/cozy/synthesis/core.py @@ -603,7 +603,7 @@ def possibly_useful_nonrecursive(solver, e : Exp, context : Context, pool = RUNT if not allow_int_arithmetic_state.value and not at_runtime and isinstance(e, EBinOp) and e.type == INT: return No("integer arithmetic in state position") if is_collection(e.type) and not is_scalar(e.type.elem_type): - return No("collection of nonscalar") + return No("collection of nonscalar: e {}\n elem_type: {}\n".format(e, e.type.elem_type)) if isinstance(e.type, TMap) and not is_scalar(e.type.k): return No("bad key type {}".format(pprint(e.type.k))) if isinstance(e.type, TMap) and isinstance(e.type.v, TMap): diff --git a/examples/nonscalar-tuple.ds b/examples/nonscalar-tuple.ds new file mode 100644 index 00000000..1a111b60 --- /dev/null +++ b/examples/nonscalar-tuple.ds @@ -0,0 +1,12 @@ +Example: + type Member = { + id : Int, + name: String + } + handletype Clz = { + id : Int, + members : Bag + } + state classes : Bag + query selectClzMembers() + [ (c, [ m.id | m <- c.val.members, m.id > 10 ]) | c <- classes ]