diff --git a/base/builtin/bigint.c b/base/builtin/bigint.c index 6ea8251ab..0e190ce2a 100644 --- a/base/builtin/bigint.c +++ b/base/builtin/bigint.c @@ -648,14 +648,6 @@ bool B_OrdD_bigintD___ge__ (B_OrdD_bigint wit, B_bigint a, B_bigint b) { // B_HashableD_bigint /////////////////////////////////////////////////////////////////////////////////////////////////////// -bool B_HashableD_bigintD___eq__(B_HashableD_bigint wit, B_bigint a, B_bigint b) { - return zz_equal(&a->val,&b->val); -} - -bool B_HashableD_bigintD___ne__(B_HashableD_bigint wit, B_bigint a, B_bigint b) { - return !zz_equal(&a->val,&b->val); -} - B_NoneType B_HashableD_bigintD_hash(B_HashableD_bigint wit, B_bigint a, B_hasher h) { long sz = a->val.size; unsigned long data; diff --git a/base/builtin/complex.c b/base/builtin/complex.c index 777ef51c3..3224ae209 100644 --- a/base/builtin/complex.c +++ b/base/builtin/complex.c @@ -142,14 +142,6 @@ bool B_EqD_complexD___ne__ (B_EqD_complex wit, B_complex a, B_complex b) { // B_HashableD_complex //////////////////////////////////////////////////////////////////////////////////////// -bool B_HashableD_complexD___eq__(B_HashableD_complex wit, B_complex a, B_complex b) { - return creal(a->val) == creal(b->val) && cimag(a->val) == cimag(b->val); -} - -bool B_HashableD_complexD___ne__(B_HashableD_complex wit, B_complex a, B_complex b) { - return !B_HashableD_complexD___eq__(wit,a,b); -} - B_NoneType B_HashableD_complexD_hash(B_HashableD_complex wit, B_complex a, B_hasher h) { zig_hash_wyhash_update(h->_hasher, to$bytesD_len((char *)&(a->val), 16)); return B_None; diff --git a/base/builtin/float.c b/base/builtin/float.c index 637a989ba..a514814c2 100644 --- a/base/builtin/float.c +++ b/base/builtin/float.c @@ -221,14 +221,6 @@ bool B_OrdD_floatD___ge__ (B_OrdD_float wit, B_float a, B_float b) { // B_HashableD_float /////////////////////////////////////////////////////////////////////////////////////////////////////// -bool B_HashableD_floatD___eq__(B_HashableD_float wit, B_float a, B_float b) { - return a->val == b->val; -} - -bool B_HashableD_floatD___ne__(B_HashableD_float wit, B_float a, B_float b) { - return a->val != b->val; -} - B_NoneType B_HashableD_floatD_hash(B_HashableD_float wit, B_float a, B_hasher h) { zig_hash_wyhash_update(h->_hasher, to$bytesD_len((char *)&a, 8)); return B_None; diff --git a/base/builtin/i16.c b/base/builtin/i16.c index a1cb37985..934f9c655 100644 --- a/base/builtin/i16.c +++ b/base/builtin/i16.c @@ -266,14 +266,6 @@ bool B_OrdD_i16D___ge__ (B_OrdD_i16 wit, B_i16 a, B_i16 b) { // B_HashableD_i16 /////////////////////////////////////////////////////////////////////////////////////////////////////// -bool B_HashableD_i16D___eq__(B_HashableD_i16 wit, B_i16 a, B_i16 b) { - return a->val == b->val; -} - -bool B_HashableD_i16D___ne__(B_HashableD_i16 wit, B_i16 a, B_i16 b) { - return a->val != b->val; -} - B_NoneType B_HashableD_i16D_hash(B_HashableD_i16 wit, B_i16 a, B_hasher h) { zig_hash_wyhash_update(h->_hasher, to$bytesD_len((char *)&(a), 4)); return B_None; diff --git a/base/builtin/i32.c b/base/builtin/i32.c index 5ca4bab0c..c0a15cd47 100644 --- a/base/builtin/i32.c +++ b/base/builtin/i32.c @@ -266,14 +266,6 @@ bool B_OrdD_i32D___ge__ (B_OrdD_i32 wit, B_i32 a, B_i32 b) { // B_HashableD_i32 /////////////////////////////////////////////////////////////////////////////////////////////////////// -bool B_HashableD_i32D___eq__(B_HashableD_i32 wit, B_i32 a, B_i32 b) { - return a->val == b->val; -} - -bool B_HashableD_i32D___ne__(B_HashableD_i32 wit, B_i32 a, B_i32 b) { - return a->val != b->val; -} - B_NoneType B_HashableD_i32D_hash(B_HashableD_i32 wit, B_i32 a, B_hasher h) { zig_hash_wyhash_update(h->_hasher, to$bytesD_len((char *)&(a), 4)); return B_None; diff --git a/base/builtin/i8.c b/base/builtin/i8.c index 51a92474f..9791137b5 100644 --- a/base/builtin/i8.c +++ b/base/builtin/i8.c @@ -266,14 +266,6 @@ bool B_OrdD_i8D___ge__ (B_OrdD_i8 wit, B_i8 a, B_i8 b) { // B_HashableD_i8 /////////////////////////////////////////////////////////////////////////////////////////////////////// -bool B_HashableD_i8D___eq__(B_HashableD_i8 wit, B_i8 a, B_i8 b) { - return a->val == b->val; -} - -bool B_HashableD_i8D___ne__(B_HashableD_i8 wit, B_i8 a, B_i8 b) { - return a->val != b->val; -} - B_NoneType B_HashableD_i8D_hash(B_HashableD_i8 wit, B_i8 a, B_hasher h) { zig_hash_wyhash_update(h->_hasher, to$bytesD_len((char *)&(a), 4)); return B_None; diff --git a/base/builtin/int.c b/base/builtin/int.c index 84aaa1942..84783f0d4 100644 --- a/base/builtin/int.c +++ b/base/builtin/int.c @@ -269,14 +269,6 @@ bool B_OrdD_intD___ge__ (B_OrdD_int wit, B_int a, B_int b) { // B_HashableD_int /////////////////////////////////////////////////////////////////////////////////////////////////////// -bool B_HashableD_intD___eq__(B_HashableD_int wit, B_int a, B_int b) { - return a->val == b->val; -} - -bool B_HashableD_intD___ne__(B_HashableD_int wit, B_int a, B_int b) { - return a->val != b->val; -} - B_NoneType B_HashableD_intD_hash(B_HashableD_int wit, B_int a, B_hasher h) { zig_hash_wyhash_update(h->_hasher,to$bytesD_len((char *)&(a->val),8)); return B_None; diff --git a/base/builtin/str.c b/base/builtin/str.c index 10c2064c6..317aa03c1 100644 --- a/base/builtin/str.c +++ b/base/builtin/str.c @@ -1599,14 +1599,6 @@ bool B_OrdD_strD___ge__ (B_OrdD_str wit, B_str a, B_str b) { // B_Hashable /////////////////////////////////////////////////////////////////////////////////// -bool B_HashableD_strD___eq__ (B_HashableD_str wit, B_str a, B_str b) { - return strcmp((char *)a->str,(char *)b->str) == 0; -} - -bool B_HashableD_strD___ne__ (B_HashableD_str wit, B_str a, B_str b) { - return strcmp((char *)a->str,(char *)b->str) != 0; -} - B_NoneType B_HashableD_strD_hash(B_HashableD_str wit, B_str a, B_hasher h) { zig_hash_wyhash_update(h->_hasher,to$bytes((char *)a->str)); return B_None; @@ -2668,18 +2660,6 @@ struct B_IteratorD_bytearrayG_class B_IteratorD_bytearrayG_methods = { B_IteratorD_bytearrayD_next }; -B_Iterator B_ContainerD_bytearrayD___iter__ (B_ContainerD_bytearray wit, B_bytearray str) { - return (B_Iterator)$NEW(B_IteratorD_bytearray,str); -} - -B_bytearray B_ContainerD_bytearrayD___fromiter__ (B_ContainerD_bytearray wit, B_Iterable wit2, $WORD iter) { - return B_bytearrayD_join(toB_bytearray(""),wit2,iter); -} - -int64_t B_ContainerD_bytearrayD___len__ (B_ContainerD_bytearray wit, B_bytearray str) { - return (int64_t)str->nbytes; -} - bool B_ContainerD_bytearrayD___contains__(B_ContainerD_bytearray wit, B_bytearray self, B_int n) { bool res = false; for (int i=0; i < self->nbytes; i++) { @@ -2761,7 +2741,7 @@ B_NoneType B_SequenceD_bytearrayD_reverse(B_SequenceD_bytearray wit, B_bytearray B_Iterator B_SequenceD_bytearrayD___reversed__(B_SequenceD_bytearray wit, B_bytearray self) { B_bytearray copy = B_bytearrayD_copy(self); B_SequenceD_bytearrayD_reverse(wit,copy); - return B_ContainerD_bytearrayD___iter__ (NULL, copy); + return (B_Iterator)$NEW(B_IteratorD_bytearray,copy); } B_bytearray B_SequenceD_bytearrayD___getslice__ (B_SequenceD_bytearray wit, B_bytearray self, B_slice slc) { @@ -3901,19 +3881,6 @@ B_bytes B_TimesD_bytesD___mul__ (B_TimesD_bytes wit, B_bytes a, B_int n) { // Hashable -bool B_HashableD_bytesD___eq__ (B_HashableD_bytes wit, B_bytes a, B_bytes b) { - if (a->nbytes != b->nbytes) - return false; - for (int i=0; i < a->nbytes; i++) - if (a->str[i] != b->str[i]) - return false; - return true; -} - -bool B_HashableD_bytesD___ne__ (B_HashableD_bytes wit, B_bytes a, B_bytes b) { - return !B_HashableD_bytesD___eq__(wit,a,b); -} - B_NoneType B_HashableD_bytesD_hash(B_HashableD_bytes wit, B_bytes a, B_hasher h) { zig_hash_wyhash_update(h->_hasher, a); return B_None; diff --git a/base/builtin/u1.c b/base/builtin/u1.c index a874c3217..28d4f46d6 100644 --- a/base/builtin/u1.c +++ b/base/builtin/u1.c @@ -270,14 +270,6 @@ bool B_OrdD_u1D___ge__ (B_OrdD_u1 wit, B_u1 a, B_u1 b) { // B_HashableD_u1 /////////////////////////////////////////////////////////////////////////////////////////////////////// -bool B_HashableD_u1D___eq__(B_HashableD_u1 wit, B_u1 a, B_u1 b) { - return a->val == b->val; -} - -bool B_HashableD_u1D___ne__(B_HashableD_u1 wit, B_u1 a, B_u1 b) { - return a->val != b->val; -} - B_NoneType B_HashableD_u1D_hash(B_HashableD_u1 wit, B_u1 a, B_hasher h) { zig_hash_wyhash_update(h->_hasher,to$bytesD_len((char *)&(a->val),8)); return B_None; diff --git a/base/builtin/u16.c b/base/builtin/u16.c index 4480245f7..a1711a33a 100644 --- a/base/builtin/u16.c +++ b/base/builtin/u16.c @@ -259,14 +259,6 @@ bool B_OrdD_u16D___ge__ (B_OrdD_u16 wit, B_u16 a, B_u16 b) { // B_HashableD_u16 /////////////////////////////////////////////////////////////////////////////////////////////////////// -bool B_HashableD_u16D___eq__(B_HashableD_u16 wit, B_u16 a, B_u16 b) { - return a->val == b->val; -} - -bool B_HashableD_u16D___ne__(B_HashableD_u16 wit, B_u16 a, B_u16 b) { - return a->val != b->val; -} - B_NoneType B_HashableD_u16D_hash(B_HashableD_u16 wit, B_u16 a, B_hasher h) { zig_hash_wyhash_update(h->_hasher,to$bytesD_len((char *)&(a->val),8)); return B_None; diff --git a/base/builtin/u32.c b/base/builtin/u32.c index b531b74ae..151c35e5d 100644 --- a/base/builtin/u32.c +++ b/base/builtin/u32.c @@ -259,14 +259,6 @@ bool B_OrdD_u32D___ge__ (B_OrdD_u32 wit, B_u32 a, B_u32 b) { // B_HashableD_u32 /////////////////////////////////////////////////////////////////////////////////////////////////////// -bool B_HashableD_u32D___eq__(B_HashableD_u32 wit, B_u32 a, B_u32 b) { - return a->val == b->val; -} - -bool B_HashableD_u32D___ne__(B_HashableD_u32 wit, B_u32 a, B_u32 b) { - return a->val != b->val; -} - B_NoneType B_HashableD_u32D_hash(B_HashableD_u32 wit, B_u32 a, B_hasher h) { zig_hash_wyhash_update(h->_hasher,to$bytesD_len((char *)&(a->val),8)); return B_None; diff --git a/base/builtin/u64.c b/base/builtin/u64.c index a220a2b54..08badc876 100644 --- a/base/builtin/u64.c +++ b/base/builtin/u64.c @@ -259,14 +259,6 @@ bool B_OrdD_u64D___ge__ (B_OrdD_u64 wit, B_u64 a, B_u64 b) { // B_HashableD_u64 /////////////////////////////////////////////////////////////////////////////////////////////////////// -bool B_HashableD_u64D___eq__(B_HashableD_u64 wit, B_u64 a, B_u64 b) { - return a->val == b->val; -} - -bool B_HashableD_u64D___ne__(B_HashableD_u64 wit, B_u64 a, B_u64 b) { - return a->val != b->val; -} - B_NoneType B_HashableD_u64D_hash(B_HashableD_u64 wit, B_u64 a, B_hasher h) { zig_hash_wyhash_update(h->_hasher,to$bytesD_len((char *)&(a->val),8)); return B_None; diff --git a/base/builtin/u8.c b/base/builtin/u8.c index 5372bcf76..5385e3529 100644 --- a/base/builtin/u8.c +++ b/base/builtin/u8.c @@ -259,14 +259,6 @@ bool B_OrdD_u8D___ge__ (B_OrdD_u8 wit, B_u8 a, B_u8 b) { // B_HashableD_u8 /////////////////////////////////////////////////////////////////////////////////////////////////////// -bool B_HashableD_u8D___eq__(B_HashableD_u8 wit, B_u8 a, B_u8 b) { - return a->val == b->val; -} - -bool B_HashableD_u8D___ne__(B_HashableD_u8 wit, B_u8 a, B_u8 b) { - return a->val != b->val; -} - B_NoneType B_HashableD_u8D_hash(B_HashableD_u8 wit, B_u8 a, B_hasher h) { zig_hash_wyhash_update(h->_hasher,to$bytesD_len((char *)&(a->val),8)); return B_None; diff --git a/base/src/__builtin__.ext.c b/base/src/__builtin__.ext.c index 636c4139b..05c4c17ad 100644 --- a/base/src/__builtin__.ext.c +++ b/base/src/__builtin__.ext.c @@ -1,23 +1,6 @@ #include "rts/rts.c" void B___ext_init__() { - /* - B_HashableD_bigintG_methods.__eq__ = (B_bool (*)(B_HashableD_bigint, B_bigint, B_bigint))B_OrdD_bigintD___eq__; - B_HashableD_intG_methods.__eq__ = (B_bool (*)(B_HashableD_int, B_int, B_int))B_OrdD_intD___eq__; - B_HashableD_i32G_methods.__eq__ = (B_bool (*)(B_HashableD_i32, B_i32, B_i32))B_OrdD_i32D___eq__; - B_HashableD_i16G_methods.__eq__ = (B_bool (*)(B_HashableD_i16, B_i16, B_i16))B_OrdD_i16D___eq__; - B_HashableD_u64G_methods.__eq__ = (B_bool (*)(B_HashableD_u64, B_u64, B_u64))B_OrdD_u64D___eq__; - B_HashableD_u32G_methods.__eq__ = (B_bool (*)(B_HashableD_u32, B_u32, B_u32))B_OrdD_u32D___eq__; - B_HashableD_u16G_methods.__eq__ = (B_bool (*)(B_HashableD_u16, B_u16, B_u16))B_OrdD_u16D___eq__; - B_HashableD_floatG_methods.__eq__ = (B_bool (*)(B_HashableD_float, B_float, B_float))B_OrdD_floatD___eq__; - B_HashableD_strG_methods.__eq__ = (B_bool (*)(B_HashableD_str, B_str, B_str))B_OrdD_strD___eq__; - B_HashableD_bytesG_methods.__eq__ = (B_bool (*)(B_HashableD_bytes, B_bytes, B_bytes))B_OrdD_bytesD___eq__; - B_HashableD_complexG_methods.__eq__ = (B_bool (*)(B_HashableD_complex, B_complex, B_complex))B_HashableD_complexD___eq__; - - B_ContainerD_listG_methods.__len__ = (int64_t (*)(B_ContainerD_list, B_list))B_CollectionD_SequenceD_listD___len__; - B_ContainerD_listG_methods.__fromiter__ = (B_list (*)(B_ContainerD_list, B_Iterable, $WORD))B_CollectionD_SequenceD_listD___fromiter__; - B_ContainerD_listG_methods.__iter__ = (B_Iterator (*)(B_ContainerD_list, B_list))B_CollectionD_SequenceD_listD___iter__; - */ } B_str B_BaseExceptionD__name (B_BaseException self) { diff --git a/compiler/lib/src/Acton/CodeGen.hs b/compiler/lib/src/Acton/CodeGen.hs index 1546be8d2..58a27be6b 100644 --- a/compiler/lib/src/Acton/CodeGen.hs +++ b/compiler/lib/src/Acton/CodeGen.hs @@ -17,7 +17,6 @@ module Acton.CodeGen where import qualified Data.Set import qualified Data.HashSet as HashSet import qualified Data.List -import qualified Data.Map.Strict as Map import qualified Acton.Env import Utils import Pretty @@ -532,10 +531,8 @@ declDecl env (Def dloc n q p KwdNIL (Just t) b d fx ddoc) declDecl env (Class _ n q as b ddoc) | cDefinedClass = vcat [ declDecl env1 d{ dname = methodname n (dname d) } | Decl _ ds <- b', d@Def{} <- ds ] $+$ - forwardDecls env1 n q $+$ text "struct" <+> classname env n <+> methodtable env n <> semi | otherwise = vcat [ declDecl env1 d{ dname = methodname n (dname d) } | Decl _ ds <- b', d@Def{} <- ds ] $+$ - forwardDecls env1 n q $+$ declSerialize env1 n c props sup_c $+$ declDeserialize env1 n c props sup_c $+$ declCleanup env1 n sup_c $+$ @@ -675,14 +672,12 @@ initGlobalDoc env s = genStmt1 env s $+$ initClassBase env c q as hasCDef = methodtable env c <> dot <> gen env gcinfoKW <+> equals <+> doubleQuotes (genTopName env c) <> semi $+$ methodtable env c <> dot <> gen env superclassKW <+> equals <+> super <> semi $+$ - vcat [ inherit c' n | (c',n) <- inheritedAttrs env (NoQ c) ] $+$ - vcat [ forward n | ForwardSlot n _ _ _ _ <- forwardSlots env c q ] + vcat [ inherit c' n | (c',n) <- inheritedAttrs env (NoQ c) ] where tc = TC (NoQ c) [ tVar v | QBind v _ <- q ] super = if null as then text "NULL" else parens (gen env qnSuperClass) <> text "&" <> methodtable' env (tcname $ head as) inherit c' n | hasCDef = methodtable env c <> dot <> gen env n <+> equals <+> genTopName env (methodname c n) <> semi | otherwise = methodtable env c <> dot <> gen env n <+> equals <+> inheritedCast n <> methodtable' env c' <> dot <> gen env n <> semi - forward n = methodtable env c <> dot <> gen env n <+> equals <+> methodCast env c q n <> genTopName env (forwardName c n) <> semi inheritedCast n = case lookup n (fullAttrEnv env tc) of Just (NVar t) -> parens (gen env (vsubst [(tvSelf,tCon tc)] t)) _ -> methodCast env c q n @@ -716,201 +711,6 @@ methodCast env c q n = case lookup n (fullAttrEnv env tc) of where tc = TC (NoQ c) (map tVar $ qbound q) rt = B.rtypeOf env tc n --- Protocol witness classes can inherit abstract slots through more than one --- protocol path. If the target witness does not implement such a slot itself --- and normal inheritance did not fill it, generate a small forwarding wrapper --- that calls the same slot on a concrete provider witness. The wrapper keeps --- the target table ABI while avoiding unsafe casts of the target witness to the --- provider witness type. -data ForwardSlot = ForwardSlot Name Type TCon Doc Type - -forwardName c n = Derived c (Derived (name "$forward") n) - -forwardDecls env c q = vcat [ forwardDecl env c q f | f <- forwardSlots env c q ] - -forwardDecl env c q (ForwardSlot n targetSlot providerTc providerExpr providerSlot) - = text "static" <+> forwardResult env targetSlot <+> genTopName env (forwardName c n) <> parens (repPar env paramNames (posrow targetSlot)) <+> char '{' $+$ - nest 4 (gen env (tCon providerTc) <+> gen env providerV <+> equals <+> providerValue <> semi $+$ - text "return" <+> providerCall <> semi) $+$ - char '}' - where paramNames = take (arity $ posrow targetSlot) forwardParamNames - providerArgs = hsep $ punctuate comma $ map (gen env) (drop 1 paramNames) - providerValue = parens (gen env (tCon providerTc)) <> parens providerExpr - providerCall = parens (parens (funsig2 env Nothing providerSlot) <> gen env providerV <> text "->" <> gen env classKW <> text "->" <> gen env n) <> - parens (gen env providerV <> comma' providerArgs) - --- Missing slots are only forwarded for generated witness classes, and only --- when the provider slot has the same ABI after removing the witness argument. -forwardSlots env c q - | not $ forwardClass c = [] - | otherwise = [ ForwardSlot n targetSlot providerTc providerExpr providerSlot - | (n, i) <- fullAttrEnv env tc, - forwardTarget i, - forwardableSlot n, - n `notElem` inherited, - n `notElem` direct, - Just targetSlot <- [slotType env tc n], - Just (providerTc, providerExpr, providerSlot) <- [forwardProvider env providers tc n targetSlot] ] - where tc = TC (NoQ c) (map tVar $ qbound q) - inherited = [ n | (_, n) <- inheritedAttrs env (NoQ c) ] - direct = directNoDecMethods env (NoQ c) - providers = providerObjects env - -slotType env tc n = case lookup n (fullAttrEnv env tc) of - Just (NDef _ Static _) -> Just rt - Just (NSig _ Static _) -> Just rt - Just (NDef _ NoDec _) -> Just $ vsubst [(tvSelf, tCon tc)] $ addSelf rt (Just NoDec) - Just (NSig _ NoDec _) -> Just $ vsubst [(tvSelf, tCon tc)] $ addSelf rt (Just NoDec) - _ -> Nothing - where rt = B.rtypeOf env tc n - --- Pick the first concrete witness that already provides the requested slot for --- the same protocol/type owner. This still permits a sibling witness such as --- Ord[str] to fill an Eq[str] slot in Hashable[str], but excludes unrelated --- classes that only happen to have the same method name and ABI. -forwardProvider env providers targetTc n targetSlot - = first [ (providerTc, providerExpr, providerSlot) - | ownerTc <- slotOwners env targetTc n, - (providerTc, providerExpr) <- providers, - providerTc /= targetTc, - providerCoversOwner env providerTc ownerTc, - concreteProvider env providerTc n, - Just providerSlot <- [slotType env providerTc n], - compatibleSlots targetSlot providerSlot ] - -slotOwners env targetTc n = [ ownerTc - | (_, ownerTc) <- tail (findAncestry env targetTc), - ownsSlotDirectly env ownerTc n ] - -ownsSlotDirectly env tc n = case findAttrInfoIn n te of - Just NDef{} -> True - Just NSig{} -> True - Just NVar{} -> True - Just NSVar{} -> True - _ -> False - where (_, te) = findCon env tc - -providerCoversOwner env providerTc ownerTc - = any ((== ownerTc) . snd) (findAncestry env providerTc) - -providerObjects env = concat [ providerRoot qn q | (qn, q) <- allClasses env, nullConArgs env qn ] - where providerRoot qn q = walk [] rootExpr rootTc - where rootTc = TC qn (map tVar $ qbound q) - rootExpr = rootWitnessExpr env qn - walk seen expr tc - | tcname tc `elem` seen = [] - | otherwise = (tc, expr) : concat [ walk (tcname tc : seen) (expr <> text "->" <> gen env w) tc' - | (w, tc') <- witnessFields env tc ] - --- Not to intrude in Types.hs, we accept that we do not have the complete list of witnesses in Env --- For completing method tables, we start with all classes in the program but filter to only consider ancestor witness classes. -allClasses env = active ++ closed ++ mods - where active = [ (NoQ n, q) | (n, NClass q _ _ _) <- activeNames env ] - closed = [ (NoQ n, q) | (n, NClass q _ _ _) <- closedNames env ] - -- modulePublicTEnv resolves through each module's lookup function, so - -- entries rewritten by earlier passes are seen in converted form. - mods = [ (GName m n, q) | (m, mi) <- Map.toList (modules env), - (n, NClass q _ _ _) <- modulePublicTEnv mi ] - -nullConArgs env qn = case findQName qn env of - NClass _ _ te _ -> case lookup initKW te of - Just (NDef sc _ _) -> initArity sc == 0 - Just (NSig sc _ _) -> initArity sc == 0 - _ -> False - _ -> False - where initArity (TSchema _ _ (TFun _ _ r _ _)) = arity r - initArity _ = 1 - -rootWitnessExpr env (NoQ n) - | inBuiltin env = staticwitness env (gname env n) - | otherwise = newcon env n <> parens empty -rootWitnessExpr env qn@(GName m n) - | m == mBuiltin = staticwitness env qn - | otherwise = newcon' env qn <> parens empty -rootWitnessExpr env qn = newcon' env qn <> parens empty - -witnessFields env tc = [ (n, tc') | (n, i) <- fullAttrEnv env tc, - isWitness n, - TCon _ fieldTc <- [fieldType i], - tc' <- witnessTargets env tc fieldTc ] - where fieldType (NDef sc Property _) = sctype sc - fieldType (NSig sc Property _) = sctype sc - fieldType (NVar t) = t - fieldType (NSVar t) = t - fieldType _ = tWild - --- Witness fields are often typed as an abstract protocol witness. Prefer the --- concrete generated witness named by convention when it exists, but keep the --- declared field type as a fallback. -witnessTargets env ownerTc fieldTc = case concreteWitnessTarget env ownerTc fieldTc of - Just tc -> [tc, fieldTc] - Nothing -> [fieldTc] - -concreteWitnessTarget env ownerTc fieldTc - = case classQBinds env qn of - Just q -> Just $ TC qn (take (length $ qbound q) (tcargs ownerTc ++ tcargs fieldTc)) - Nothing -> Nothing - where qn = derivedWitnessQName (tcname ownerTc) (tcname fieldTc) - -derivedWitnessQName (NoQ owner) field - = NoQ (Derived (noq field) owner) -derivedWitnessQName (GName m owner) field - = GName m (Derived (noq field) owner) -derivedWitnessQName (QName m owner) field - = GName m (Derived (noq field) owner) - -classQBinds env (NoQ n) = case lookupName n env of - Just (NClass q _ _ _) -> Just q - _ -> Nothing -classQBinds env (GName m n) = case lookupModuleInfo m env >>= \mi -> moduleLookupName mi n of - Just (NClass q _ _ _) -> Just q - _ -> Nothing -classQBinds env (QName m n) = classQBinds env (GName m n) - -concreteProvider env tc n = case lookup n (fullAttrEnv env tc) of - Just (NDef _ _ _) -> True - Just (NVar _) -> True - Just (NSVar _) -> True - _ -> False - -compatibleSlots (TFun _ fx1 p1 k1 t1) (TFun _ fx2 p2 k2 t2) - = fx1 == fx2 && k1 == k2 && t1 == t2 && dropFirstRow p1 == dropFirstRow p2 -compatibleSlots _ _ = False - -dropFirstRow (TRow _ _ _ _ r) = r -dropFirstRow r = r - -forwardResult env (TFun _ fx _ _ t) = repType env (exposeMsg fx t) -forwardResult _ _ = empty - -repPar env (n : ns) (TRow _ _ _ t r@TRow{}) - = repType env t <+> gen env n <> comma <+> repPar env ns r -repPar env (n : _) (TRow _ _ _ t TNil{}) - = repType env t <+> gen env n -repPar env (n : _) (TRow _ _ _ t TVar{}) - = repType env t <+> gen env n -repPar _ _ TNil{} = empty -repPar _ _ _ = empty - -forwardTarget (NDef _ NoDec _) = True -forwardTarget (NSig _ NoDec _) = True -forwardTarget _ = False - -forwardableSlot n = n `notElem` ([initKW, serializeKW, deserializeKW] ++ valueKWs) - -forwardClass Derived{} = True -forwardClass _ = False - -directNoDecMethods env qn = case findQName qn env of - NClass _ _ te _ -> [ n | (n, NDef _ NoDec _) <- te ] - _ -> [] - -forwardParamNames = [ name ("fw_" ++ show i) | i <- [(0 :: Int)..] ] -providerV = name "fw_provider" -first (x:_) = Just x -first [] = Nothing - - initFlag = name "done$" methodname c n = Derived c n @@ -1501,21 +1301,6 @@ containsGeneratedMethodCallComp env (CompIf _ e c) containsGeneratedMethodCallComp _ NoComp = False -genDirectMethodCall env targetTc n rt (PosArg w p) - = callee <> parens (witness <> comma' (genCallPosArgs env r p)) - where TFun _ _ r _ _ = rt - slot = staticWitnessSlotType env targetTc n rt - witness = staticWitnessObject env targetTc w - callee = case staticWitnessMethodImpl env [] targetTc n of - Just implTc -> staticWitnessDirectCallee env slot implTc n - Nothing -> staticWitnessTableCallee env slot witness n -genDirectMethodCall _ _ n _ p = error ("Internal error: direct witness call for " ++ show n ++ " has arguments " ++ show p) - -staticWitnessObject env tc e = case staticWitnessName e of - (Just obj, path) -> parens (gen env (tCon tc)) <> foldl field (staticwitness env (unalias env obj)) path - _ -> error ("Internal error: direct witness call with non-static witness " ++ show e) - where field d n = d <> text "->" <> gen env n - genGeneratedMethodCall env n ts (PosArg w p) | Just (tc, _) <- generatedMethodClass env n ts = gen env (generatedMethodQName n) <> parens (witness <> comma' (gen env p)) @@ -1528,47 +1313,6 @@ staticWitnessValue env e = case staticWitnessName e of _ -> gen env e where field d n = d <> text "->" <> gen env n --- Direct witness calls name the target table slot. Defaults may be supplied --- by an ancestor protocol class, so the concrete implementation is resolved --- here and cast back to the target slot ABI. -staticWitnessSlotType env tc n rt - | Just slot <- slotType env tc n = slot - | otherwise = addWitness rt - where addWitness (TFun l fx r k t)= TFun l fx (posRow (tCon tc) r) k t - addWitness t = t - -staticWitnessDirectCallee env slot implTc n - = parens (parens (funsig2 env Nothing slot) <> staticWitnessMethodName env implTc n) - -staticWitnessTableCallee env slot witness n - = parens (parens (funsig2 env Nothing slot) <> parens witness <> text "->" <> gen env classKW <> text "->" <> gen env n) - -staticWitnessMethodName env (TC (GName m c) _) n - = gen env (GName m (methodname c n)) -staticWitnessMethodName env (TC (QName m c) _) n - = gen env (GName m (methodname c n)) -staticWitnessMethodName env (TC (NoQ c) _) n - = genTopName env (methodname c n) - -staticWitnessMethodImpl env seen tc n - | tcname tc `elem` seen = Nothing - | directMethodImpl env (tcname tc) n - = Just tc - | otherwise = do provider <- first [ provider | (provider, n') <- inheritedAttrs env (tcname tc), n' == n ] - staticWitnessMethodImpl env (tcname tc : seen) (schematicClass env provider) n - -directMethodImpl env qn n = case findQName qn env of - NClass _ _ te _ -> direct te - NProto _ _ te _ -> direct te - _ -> False - where direct te = case findAttrInfoIn n te of - Just NDef{} -> True - _ -> False - -schematicClass env qn = case classQBinds env qn of - Just q -> TC qn (map tVar $ qbound q) - Nothing -> TC qn [] - -- Compute the C-facing callable type used for argument rendering. Public -- polymorphic callables are matched against a wildcard instantiation so -- polymorphic positions keep their boxed ABI; internal/generated functions and diff --git a/compiler/lib/src/Acton/Env.hs b/compiler/lib/src/Acton/Env.hs index b60d82877..0842e7448 100644 --- a/compiler/lib/src/Acton/Env.hs +++ b/compiler/lib/src/Acton/Env.hs @@ -848,7 +848,7 @@ fullAttrEnv = attributes f where f wp i n = Just (n,i) parentTEnv :: EnvF x -> [WTCon] -> TEnv -parentTEnv env us = [ (n,i) | (_,c) <- us, let (_,te) = findCon env c, (n,i) <- reverse te ] -- in override order +parentTEnv env us = [ (n,i) | (_,c) <- reverse us, let (_,te) = findCon env c, (n,i) <- te ] -- in program order findAttr :: EnvF x -> TCon -> Name -> Maybe (Expr->Expr, TSchema, Maybe Deco) findAttr env tc n = go (findAncestry env tc) diff --git a/compiler/lib/src/Acton/TypeEnv.hs b/compiler/lib/src/Acton/TypeEnv.hs index 92786c789..2c9cde51b 100644 --- a/compiler/lib/src/Acton/TypeEnv.hs +++ b/compiler/lib/src/Acton/TypeEnv.hs @@ -312,7 +312,8 @@ tydefineVars q env = modX env1 (\x -> foldl' addvarinfo x tvs) tydefineInst :: TCon -> [WTCon] -> Name -> Env -> Env tydefineInst c ps w env = modX env (\x -> foldl' addActiveWit x wits) - where wits = [ WInst [] (tCon c) p (NoQ w) ws | (ws,p) <- ps ] + where wits = [ wit | wit <- wits0, not (hasVisibleWit env wit) ] + wits0 = [ WInst [] (tCon c) p (NoQ w) ws | (ws,p) <- ps ] addActiveWit :: TypeX -> Witness -> TypeX addActiveWit x wit diff --git a/compiler/lib/src/Acton/Types.hs b/compiler/lib/src/Acton/Types.hs index a5e469946..300f97f91 100644 --- a/compiler/lib/src/Acton/Types.hs +++ b/compiler/lib/src/Acton/Types.hs @@ -23,7 +23,7 @@ import Control.Monad import Control.Monad.Except (runExceptT) import Control.Monad.State.Strict (runState) import Data.Maybe (isJust) -import Data.List (nub, intersect, sort) +import Data.List (nub, nubBy, intersect, sort) import Pretty import qualified Control.Exception import Debug.Trace @@ -1047,13 +1047,13 @@ instance InfEnv Decl where popFX when (not $ null cs) $ err (loc n) "Deprecated class syntax" checkClassAttributesInitialized n l env as' b - (nterms,asigs,_) <- checkAttributes [] te' te + (nterms,asigs,_,_) <- checkAttributes [] te' te let (te2,b2) = if notImplBody b then let te1 = unSig asigs in (te++te1, addImpl te1 b1) else if null asigs && initKW `notElem` dom te then relayInit te b1 else (te,b1) return ([], [(n, NClass q as' (te0++te2) ddoc)], Class l n q us (props te0 ++ b2) ddoc) _ -> illegalRedef n - where env1 = define (exclude (toSigs te') [initKW]) $ reserve (assigned b0) $ tydefineVars (stripQual q') $ setInClass env + where env1 = define (toSigs te' `exclude` [initKW]) $ reserve (assigned b0) $ tydefineVars (stripQual q') $ setInClass env (as,ps) = mro2 env us as' = if null as && not (inBuiltin env && n == nValue) then leftpath [cValue] else as te' = parentTEnv env as' @@ -1078,7 +1078,7 @@ instance InfEnv Decl where userMethods = [ dname d | Decl _ ds <- b, d@Def{} <- ds ] getAttrDef = sDef getAttrKW (pospar [(selfKW,tSelf),(nameKW,tStr)]) (tOpt tValue) [sReturn eNone] fxPure relayInit te b = --trace ("####### Creating relayInit for class " ++ prstr n) $ - case lookup initKW te' of + case lookup initKW (reverse te') of Just ni@(NDef sc _ _) -> ((initKW,ni):te, sDecl [Def NoLoc initKW [] pp kp Nothing body NoDec fx Nothing]:b) where t = addSelf (sctype sc) (Just NoDec) @@ -1095,7 +1095,7 @@ instance InfEnv Decl where (cs,te,b') <- infEnv env1 b popFX when (not $ null cs) $ err (loc n) "Deprecated protocol syntax" - (nterms,_,sigs) <- checkAttributes [] te' te + (nterms,_,_,sigs) <- checkAttributes [] te' te let noself = [ n | (n, NSig sc Static _) <- te, tvSelf `notElem` vfree sc ] when (notImplBody b) $ err0 (notImpls b) "A protocol body cannot be NotImplemented" when (not $ null nterms) $ err2 (dom nterms) "Method/attribute lacks signature:" @@ -1124,22 +1124,32 @@ instance InfEnv Decl where (cs,te,b1) <- infEnv env1 b popFX when (not $ null cs) $ err (loc n) "Deprecated extension syntax" - (nterms,asigs,sigs) <- checkAttributes final te' te + (nterms,asigs,fsigs,sigs) <- checkAttributes (dom finals) te' te when (not $ null nterms) $ err2 (dom nterms) "Method/attribute not in listed protocols:" when (not $ null sigs) $ err2 sigs "Extension with new methods/attributes not supported" when (not (null asigs || notImplBody b)) $ err3 l (dom asigs) "Protocol method/attribute lacks implementation:" let te1 = unSig $ selfSubst n q asigs - te2 = te ++ te1 - b2 = addImpl te1 b1 + fwds = selfSubst n q $ nubBy (\a b -> fst a == fst b) $ reverse fsigs + te2 = te ++ te1 ++ unSig fwds + b2 = addImpl te1 b1 ++ map fwdDef fwds return ([], [(extensionName us c, NExt q c ps te2 [] ddoc)], Extension l q c us b2 ddoc) where TC n ts = c env1 = define (toSigs te') $ reserve (assigned b) $ tydefineVars (stripQual q') $ setInClass env witsearch = findWitness env (tCon c) u u = head us ps = selfSubst n q $ mro1 env us -- TODO: check that ps doesn't contradict any previous extension mro for c - final = concat [ conAttrs env (tcname p) | (_,p) <- tail ps, hasWitness env (tCon c) p ] + finals = [ (a, p) | (_,p) <- tail ps, hasWitness env (tCon c) p, a <- conAttrs env (tcname p) ] te' = parentTEnv env ps q' = selfQuant n q + -- A final slot is already implemented by an earlier witness for its protocol. + -- It becomes a method that calls the slot through that protocol, which the type + -- checker resolves to the covering witness like any other call. + fwdDef (a, NSig sc dec _) = sDecl [Def NoLoc a (scbind sc) pp kp (Just $ restype t) [sReturn call] dec (effect t) Nothing] + where t = addSelf (sctype sc) (Just dec) + pp = pPar pNames $ posrow t + kp = kPar attrKW $ kwdrow t + Just owner = lookup a finals + call = Call NoLoc (eDot (eQVar $ tcname owner) a) (pArg pp) (kArg kp) -------------------------------------------------------------------------------------------------------------------------- @@ -1147,13 +1157,18 @@ checkAttributes final te' te | not $ null dupsigs = err2 dupsigs "Duplicate signatures for" | not $ null props = err2 props "Property attributes cannot have class-level definitions:" | not $ null nodef = err2 nodef "Methods finalized in a previous extension cannot be overridden:" - | otherwise = return (nterms, abssigs, dom sigs) + | not $ null clashes = err2 clashes "Conflicting inherited signatures for" + | otherwise = return (nterms, abssigs, finalsigs, dom sigs) where (sigs,terms) = sigTerms te (sigs',terms') = sigTerms te' (allsigs,allterms) = (sigs ++ sigs', terms ++ terms') dupsigs = duplicates (dom sigs) - nterms = exclude terms (dom allsigs) - abssigs = allsigs `exclude` (dom allterms ++ final) + nterms = terms `exclude` dom allsigs + misssigs = allsigs `exclude` dom allterms + abssigs = misssigs `exclude` final + finalsigs = misssigs `restrict` final + clashes = nub [ n | (n, NSig sc dec _) <- sigs', n /= initKW, (n', NSig sc' dec' _) <- sigs', + n == n', sctype sc' /= sctype sc || dec' /= dec ] props = dom terms `intersect` dom (propSigs allsigs) nodef = dom terms `intersect` final @@ -1822,7 +1837,7 @@ instance Check Decl where checkEnv' env (Extension l q c us b ddoc) | isActor env n = notYet (loc n) "Extension of an actor" | isProto env n = notYet (loc n) "Extension of a protocol" - | otherwise = do --traceM ("## checkEnv extension " ++ prstr n ++ "(" ++ prstrs us ++ ")") + | otherwise = do --traceM ("## checkEnv extension " ++ prstr n' ++ "(" ++ prstrs us ++ ")") pushFX fxPure tNone wellformed env1 q (csu,wmap) <- wellformedProtos env1 us diff --git a/compiler/lib/test/3-types/witness_forward.input b/compiler/lib/test/3-types/witness_forward.input new file mode 100644 index 000000000..65c7650a6 --- /dev/null +++ b/compiler/lib/test/3-types/witness_forward.input @@ -0,0 +1,25 @@ +# recursive group: +protocol PA: + @static + same : (Self, Self) -> __builtin__.bool + total : () -> __builtin__.int +protocol PB (PA): + beta : () -> __builtin__.int +protocol PC (PA): + gamma : () -> __builtin__.int +class Thing (__builtin__.object): + n : __builtin__.int + T_13w def __init__ (self : T_5w, n : __builtin__.int) -> T_9w: + self.n = n +extension Thing (PB): + @static + T_17w def same (a : Thing, b : Thing) -> __builtin__.bool: + return a.n == b.n + T_29w def total (self : T_21w) -> T_25w: + return self.n + T_41w def beta (self : T_33w) -> T_37w: + return 1 +extension Thing (PC): + T_53w def gamma (self : T_45w) -> T_49w: + return 2 +# (recursive group) \ No newline at end of file diff --git a/compiler/lib/test/3-types/witness_forward.output b/compiler/lib/test/3-types/witness_forward.output new file mode 100644 index 000000000..cb77a9f70 --- /dev/null +++ b/compiler/lib/test/3-types/witness_forward.output @@ -0,0 +1,45 @@ +# recursive group: +class PA[G_self] (__builtin__.value): + pure def __init__ (W_self : Self) -> None: + same : (G_self, G_self) -> __builtin__.bool + total : (G_self) -> __builtin__.int +class PB[G_self] (PA[G_self], __builtin__.value): + pure def __init__ (W_self : Self) -> None: + PA.__init__@[G_self](W_self) + beta : (G_self) -> __builtin__.int +class PC[G_self] (PA[G_self], __builtin__.value): + pure def __init__ (W_self : Self) -> None: + PA.__init__@[G_self](W_self) + gamma : (G_self) -> __builtin__.int +class Thing (__builtin__.object, __builtin__.value): + pure def __get_attr__ (self : Self, name : __builtin__.str) -> ?__builtin__.value: + return None + pure def G_init (self : Self) -> None: + pass + @property + n : __builtin__.int + pure def __init__ (self : Self, n : __builtin__.int) -> None: + self.n = n +class PBD_Thing (PB[Thing], PA[Thing], __builtin__.value): + W_PA_26: __builtin__.Number[__builtin__.int] = __builtin__.IntegralD_int() + pure def __init__ (W_self : Self) -> None: + PB.__init__@[Thing](W_self) + pure def same (W_self : Self, a : Thing, b : Thing) -> __builtin__.bool: + W_PA_15: __builtin__.Eq[__builtin__.int] = __builtin__.OrdD_int() + return W_PA_15.__eq__(a.n, b.n) + pure def total (W_self : Self, self : Thing) -> __builtin__.int: + return self.n + pure def beta (W_self : Self, self : Thing) -> __builtin__.int: + return W_PA_26.__fromatom__(1) +class PCD_Thing (PC[Thing], PA[Thing], __builtin__.value): + W_PA_34: PA[Thing] = PBD_Thing() + W_PA_30: __builtin__.Number[__builtin__.int] = __builtin__.IntegralD_int() + pure def __init__ (W_self : Self) -> None: + PC.__init__@[Thing](W_self) + pure def gamma (W_self : Self, self : Thing) -> __builtin__.int: + return W_PA_30.__fromatom__(2) + pure def total (W_self : Self, G_1p : Thing) -> __builtin__.int: + return W_PA_34.total(G_1p) + pure def same (W_self : Self, G_1p : Thing, G_2p : Thing) -> __builtin__.bool: + return W_PA_34.same(G_1p, G_2p) +# (recursive group) \ No newline at end of file diff --git a/compiler/lib/test/9-codegen/witness_forward.c b/compiler/lib/test/9-codegen/witness_forward.c new file mode 100644 index 000000000..76c9b3cbe --- /dev/null +++ b/compiler/lib/test/9-codegen/witness_forward.c @@ -0,0 +1,262 @@ +/* Acton impl hash: test-hash */ +#include "rts/common.h" +#include "out/types/witness_forward.h" +B_NoneType witness_forwardQ_PAD___init__ (witness_forwardQ_PA W_self) { + return B_None; +} +void witness_forwardQ_PAD___serialize__ (witness_forwardQ_PA self, $Serial$state state) { +} +witness_forwardQ_PA witness_forwardQ_PAD___deserialize__ (witness_forwardQ_PA self, $Serial$state state) { + $WORD $tmp; + if (!self) { + if (!state) { + self = acton_malloc(sizeof(struct witness_forwardQ_PA)); + self->$class = &witness_forwardQ_PAG_methods; + return self; + } + self = $DNEW(witness_forwardQ_PA, state); + } + return self; +} +struct witness_forwardQ_PAG_class witness_forwardQ_PAG_methods; +B_NoneType witness_forwardQ_PBD___init__ (witness_forwardQ_PB W_self) { + ((B_NoneType (*) (witness_forwardQ_PA))witness_forwardQ_PAG_methods.__init__)(((witness_forwardQ_PA)W_self)); + return B_None; +} +void witness_forwardQ_PBD___serialize__ (witness_forwardQ_PB self, $Serial$state state) { +} +witness_forwardQ_PB witness_forwardQ_PBD___deserialize__ (witness_forwardQ_PB self, $Serial$state state) { + $WORD $tmp; + if (!self) { + if (!state) { + self = acton_malloc(sizeof(struct witness_forwardQ_PB)); + self->$class = &witness_forwardQ_PBG_methods; + return self; + } + self = $DNEW(witness_forwardQ_PB, state); + } + return self; +} +struct witness_forwardQ_PBG_class witness_forwardQ_PBG_methods; +B_NoneType witness_forwardQ_PCD___init__ (witness_forwardQ_PC W_self) { + ((B_NoneType (*) (witness_forwardQ_PA))witness_forwardQ_PAG_methods.__init__)(((witness_forwardQ_PA)W_self)); + return B_None; +} +void witness_forwardQ_PCD___serialize__ (witness_forwardQ_PC self, $Serial$state state) { +} +witness_forwardQ_PC witness_forwardQ_PCD___deserialize__ (witness_forwardQ_PC self, $Serial$state state) { + $WORD $tmp; + if (!self) { + if (!state) { + self = acton_malloc(sizeof(struct witness_forwardQ_PC)); + self->$class = &witness_forwardQ_PCG_methods; + return self; + } + self = $DNEW(witness_forwardQ_PC, state); + } + return self; +} +struct witness_forwardQ_PCG_class witness_forwardQ_PCG_methods; +B_value witness_forwardQ_ThingD___get_attr__ (witness_forwardQ_Thing self, B_str name) { + if (B_OrdD_strD___eq__(B_OrdD_strG_witness, name, to$str("n"))) { + return (B_value)toB_int(self->n); + } + return B_None; +} +B_NoneType witness_forwardQ_ThingG_init (witness_forwardQ_Thing self) { + return B_None; +} +#line 19 "test/src/witness_forward.act" +B_NoneType witness_forwardQ_ThingD___init__ (witness_forwardQ_Thing self, int64_t n) { + #line 20 "test/src/witness_forward.act" + ((witness_forwardQ_Thing)(self))->n = n; + return B_None; +} +void witness_forwardQ_ThingD___serialize__ (witness_forwardQ_Thing self, $Serial$state state) { + $val_serialize(I64_ID, &self->n, state); +} +witness_forwardQ_Thing witness_forwardQ_ThingD___deserialize__ (witness_forwardQ_Thing self, $Serial$state state) { + $WORD $tmp; + if (!self) { + if (!state) { + self = acton_malloc(sizeof(struct witness_forwardQ_Thing)); + self->$class = &witness_forwardQ_ThingG_methods; + return self; + } + self = $DNEW(witness_forwardQ_Thing, state); + } + $tmp = $val_deserialize(state); + memcpy(&self->n, &$tmp, sizeof(self->n)); + return self; +} +witness_forwardQ_Thing witness_forwardQ_ThingG_new(int64_t G_1) { + witness_forwardQ_Thing $tmp = acton_malloc(sizeof(struct witness_forwardQ_Thing)); + $tmp->$class = &witness_forwardQ_ThingG_methods; + witness_forwardQ_ThingG_methods.G_init($tmp); + witness_forwardQ_ThingG_methods.__init__($tmp, G_1); + return $tmp; +} +struct witness_forwardQ_ThingG_class witness_forwardQ_ThingG_methods; +B_NoneType witness_forwardQ_PBD_ThingD___init__ (witness_forwardQ_PBD_Thing W_self) { + ((B_NoneType (*) (witness_forwardQ_PB))witness_forwardQ_PBG_methods.__init__)(((witness_forwardQ_PB)W_self)); + return B_None; +} +#line 23 "test/src/witness_forward.act" +bool witness_forwardQ_PBD_ThingD_same (witness_forwardQ_PBD_Thing W_self, witness_forwardQ_Thing a, witness_forwardQ_Thing b) { + bool N_tmp = (((int64_t)((witness_forwardQ_Thing)(a))->n) == ((int64_t)((witness_forwardQ_Thing)(b))->n)); + #line 25 "test/src/witness_forward.act" + return N_tmp; +} +#line 26 "test/src/witness_forward.act" +int64_t witness_forwardQ_PBD_ThingD_total (witness_forwardQ_PBD_Thing W_self, witness_forwardQ_Thing self) { + #line 27 "test/src/witness_forward.act" + return ((int64_t)((witness_forwardQ_Thing)(self))->n); +} +#line 28 "test/src/witness_forward.act" +int64_t witness_forwardQ_PBD_ThingD_beta (witness_forwardQ_PBD_Thing W_self, witness_forwardQ_Thing self) { + int64_t N_1tmp = 1LL; + #line 29 "test/src/witness_forward.act" + return N_1tmp; +} +void witness_forwardQ_PBD_ThingD___serialize__ (witness_forwardQ_PBD_Thing self, $Serial$state state) { +} +witness_forwardQ_PBD_Thing witness_forwardQ_PBD_ThingD___deserialize__ (witness_forwardQ_PBD_Thing self, $Serial$state state) { + $WORD $tmp; + if (!self) { + if (!state) { + self = acton_malloc(sizeof(struct witness_forwardQ_PBD_Thing)); + self->$class = &witness_forwardQ_PBD_ThingG_methods; + return self; + } + self = $DNEW(witness_forwardQ_PBD_Thing, state); + } + return self; +} +witness_forwardQ_PBD_Thing witness_forwardQ_PBD_ThingG_new() { + witness_forwardQ_PBD_Thing $tmp = acton_malloc(sizeof(struct witness_forwardQ_PBD_Thing)); + $tmp->$class = &witness_forwardQ_PBD_ThingG_methods; + witness_forwardQ_PBD_ThingG_methods.__init__($tmp); + return $tmp; +} +struct witness_forwardQ_PBD_ThingG_class witness_forwardQ_PBD_ThingG_methods; +B_NoneType witness_forwardQ_PCD_ThingD___init__ (witness_forwardQ_PCD_Thing W_self) { + ((witness_forwardQ_PCD_Thing)(W_self))->W_PA_34 = ((witness_forwardQ_PA)witness_forwardQ_PBD_ThingG_new()); + ((B_NoneType (*) (witness_forwardQ_PC))witness_forwardQ_PCG_methods.__init__)(((witness_forwardQ_PC)W_self)); + return B_None; +} +#line 32 "test/src/witness_forward.act" +int64_t witness_forwardQ_PCD_ThingD_gamma (witness_forwardQ_PCD_Thing W_self, witness_forwardQ_Thing self) { + int64_t N_2tmp = 2LL; + #line 33 "test/src/witness_forward.act" + return N_2tmp; +} +int64_t witness_forwardQ_PCD_ThingD_total (witness_forwardQ_PCD_Thing W_self, witness_forwardQ_Thing G_1p) { + int64_t N_3tmp = ((int64_t (*) ($WORD, witness_forwardQ_Thing))((witness_forwardQ_PA)(((witness_forwardQ_PCD_Thing)(W_self))->W_PA_34))->$class->total)(((witness_forwardQ_PCD_Thing)(W_self))->W_PA_34, G_1p); + return N_3tmp; +} +bool witness_forwardQ_PCD_ThingD_same (witness_forwardQ_PCD_Thing W_self, witness_forwardQ_Thing G_1p, witness_forwardQ_Thing G_2p) { + bool N_4tmp = ((bool (*) ($WORD, witness_forwardQ_Thing, witness_forwardQ_Thing))((witness_forwardQ_PA)(((witness_forwardQ_PCD_Thing)(W_self))->W_PA_34))->$class->same)(((witness_forwardQ_PCD_Thing)(W_self))->W_PA_34, G_1p, G_2p); + return N_4tmp; +} +void witness_forwardQ_PCD_ThingD___serialize__ (witness_forwardQ_PCD_Thing self, $Serial$state state) { + $step_serialize(self->W_PA_34, state); +} +witness_forwardQ_PCD_Thing witness_forwardQ_PCD_ThingD___deserialize__ (witness_forwardQ_PCD_Thing self, $Serial$state state) { + $WORD $tmp; + if (!self) { + if (!state) { + self = acton_malloc(sizeof(struct witness_forwardQ_PCD_Thing)); + self->$class = &witness_forwardQ_PCD_ThingG_methods; + return self; + } + self = $DNEW(witness_forwardQ_PCD_Thing, state); + } + self->W_PA_34 = $step_deserialize(state); + return self; +} +witness_forwardQ_PCD_Thing witness_forwardQ_PCD_ThingG_new() { + witness_forwardQ_PCD_Thing $tmp = acton_malloc(sizeof(struct witness_forwardQ_PCD_Thing)); + $tmp->$class = &witness_forwardQ_PCD_ThingG_methods; + witness_forwardQ_PCD_ThingG_methods.__init__($tmp); + return $tmp; +} +struct witness_forwardQ_PCD_ThingG_class witness_forwardQ_PCD_ThingG_methods; +int witness_forwardQ_done$ = 0; +void witness_forwardQ___init__ () { + if (witness_forwardQ_done$) return; + witness_forwardQ_done$ = 1; + { + witness_forwardQ_PAG_methods.$GCINFO = "witness_forwardQ_PA"; + witness_forwardQ_PAG_methods.$superclass = ($SuperG_class)&B_valueG_methods; + witness_forwardQ_PAG_methods.__bool__ = (bool (*) (witness_forwardQ_PA))B_valueG_methods.__bool__; + witness_forwardQ_PAG_methods.__str__ = (B_str (*) (witness_forwardQ_PA))B_valueG_methods.__str__; + witness_forwardQ_PAG_methods.__repr__ = (B_str (*) (witness_forwardQ_PA))B_valueG_methods.__repr__; + witness_forwardQ_PAG_methods.__init__ = (B_NoneType (*) (witness_forwardQ_PA))witness_forwardQ_PAD___init__; + witness_forwardQ_PAG_methods.__serialize__ = witness_forwardQ_PAD___serialize__; + witness_forwardQ_PAG_methods.__deserialize__ = witness_forwardQ_PAD___deserialize__; + $register(&witness_forwardQ_PAG_methods); + } + { + witness_forwardQ_PBG_methods.$GCINFO = "witness_forwardQ_PB"; + witness_forwardQ_PBG_methods.$superclass = ($SuperG_class)&witness_forwardQ_PAG_methods; + witness_forwardQ_PBG_methods.__bool__ = (bool (*) (witness_forwardQ_PB))B_valueG_methods.__bool__; + witness_forwardQ_PBG_methods.__str__ = (B_str (*) (witness_forwardQ_PB))B_valueG_methods.__str__; + witness_forwardQ_PBG_methods.__repr__ = (B_str (*) (witness_forwardQ_PB))B_valueG_methods.__repr__; + witness_forwardQ_PBG_methods.__init__ = (B_NoneType (*) (witness_forwardQ_PB))witness_forwardQ_PBD___init__; + witness_forwardQ_PBG_methods.__serialize__ = witness_forwardQ_PBD___serialize__; + witness_forwardQ_PBG_methods.__deserialize__ = witness_forwardQ_PBD___deserialize__; + $register(&witness_forwardQ_PBG_methods); + } + { + witness_forwardQ_PCG_methods.$GCINFO = "witness_forwardQ_PC"; + witness_forwardQ_PCG_methods.$superclass = ($SuperG_class)&witness_forwardQ_PAG_methods; + witness_forwardQ_PCG_methods.__bool__ = (bool (*) (witness_forwardQ_PC))B_valueG_methods.__bool__; + witness_forwardQ_PCG_methods.__str__ = (B_str (*) (witness_forwardQ_PC))B_valueG_methods.__str__; + witness_forwardQ_PCG_methods.__repr__ = (B_str (*) (witness_forwardQ_PC))B_valueG_methods.__repr__; + witness_forwardQ_PCG_methods.__init__ = (B_NoneType (*) (witness_forwardQ_PC))witness_forwardQ_PCD___init__; + witness_forwardQ_PCG_methods.__serialize__ = witness_forwardQ_PCD___serialize__; + witness_forwardQ_PCG_methods.__deserialize__ = witness_forwardQ_PCD___deserialize__; + $register(&witness_forwardQ_PCG_methods); + } + { + witness_forwardQ_ThingG_methods.$GCINFO = "witness_forwardQ_Thing"; + witness_forwardQ_ThingG_methods.$superclass = ($SuperG_class)&B_objectG_methods; + witness_forwardQ_ThingG_methods.__bool__ = (bool (*) (witness_forwardQ_Thing))B_valueG_methods.__bool__; + witness_forwardQ_ThingG_methods.__str__ = (B_str (*) (witness_forwardQ_Thing))B_valueG_methods.__str__; + witness_forwardQ_ThingG_methods.__repr__ = (B_str (*) (witness_forwardQ_Thing))B_valueG_methods.__repr__; + witness_forwardQ_ThingG_methods.__get_attr__ = (B_value (*) (witness_forwardQ_Thing, B_str))witness_forwardQ_ThingD___get_attr__; + witness_forwardQ_ThingG_methods.G_init = (B_NoneType (*) (witness_forwardQ_Thing))witness_forwardQ_ThingG_init; + witness_forwardQ_ThingG_methods.__init__ = (B_NoneType (*) (witness_forwardQ_Thing, int64_t))witness_forwardQ_ThingD___init__; + witness_forwardQ_ThingG_methods.__serialize__ = witness_forwardQ_ThingD___serialize__; + witness_forwardQ_ThingG_methods.__deserialize__ = witness_forwardQ_ThingD___deserialize__; + $register(&witness_forwardQ_ThingG_methods); + } + { + witness_forwardQ_PBD_ThingG_methods.$GCINFO = "witness_forwardQ_PBD_Thing"; + witness_forwardQ_PBD_ThingG_methods.$superclass = ($SuperG_class)&witness_forwardQ_PBG_methods; + witness_forwardQ_PBD_ThingG_methods.__bool__ = (bool (*) (witness_forwardQ_PBD_Thing))B_valueG_methods.__bool__; + witness_forwardQ_PBD_ThingG_methods.__str__ = (B_str (*) (witness_forwardQ_PBD_Thing))B_valueG_methods.__str__; + witness_forwardQ_PBD_ThingG_methods.__repr__ = (B_str (*) (witness_forwardQ_PBD_Thing))B_valueG_methods.__repr__; + witness_forwardQ_PBD_ThingG_methods.__init__ = (B_NoneType (*) (witness_forwardQ_PBD_Thing))witness_forwardQ_PBD_ThingD___init__; + witness_forwardQ_PBD_ThingG_methods.same = (bool (*) (witness_forwardQ_PBD_Thing, witness_forwardQ_Thing, witness_forwardQ_Thing))witness_forwardQ_PBD_ThingD_same; + witness_forwardQ_PBD_ThingG_methods.total = (int64_t (*) (witness_forwardQ_PBD_Thing, witness_forwardQ_Thing))witness_forwardQ_PBD_ThingD_total; + witness_forwardQ_PBD_ThingG_methods.beta = (int64_t (*) (witness_forwardQ_PBD_Thing, witness_forwardQ_Thing))witness_forwardQ_PBD_ThingD_beta; + witness_forwardQ_PBD_ThingG_methods.__serialize__ = witness_forwardQ_PBD_ThingD___serialize__; + witness_forwardQ_PBD_ThingG_methods.__deserialize__ = witness_forwardQ_PBD_ThingD___deserialize__; + $register(&witness_forwardQ_PBD_ThingG_methods); + } + { + witness_forwardQ_PCD_ThingG_methods.$GCINFO = "witness_forwardQ_PCD_Thing"; + witness_forwardQ_PCD_ThingG_methods.$superclass = ($SuperG_class)&witness_forwardQ_PCG_methods; + witness_forwardQ_PCD_ThingG_methods.__bool__ = (bool (*) (witness_forwardQ_PCD_Thing))B_valueG_methods.__bool__; + witness_forwardQ_PCD_ThingG_methods.__str__ = (B_str (*) (witness_forwardQ_PCD_Thing))B_valueG_methods.__str__; + witness_forwardQ_PCD_ThingG_methods.__repr__ = (B_str (*) (witness_forwardQ_PCD_Thing))B_valueG_methods.__repr__; + witness_forwardQ_PCD_ThingG_methods.__init__ = (B_NoneType (*) (witness_forwardQ_PCD_Thing))witness_forwardQ_PCD_ThingD___init__; + witness_forwardQ_PCD_ThingG_methods.gamma = (int64_t (*) (witness_forwardQ_PCD_Thing, witness_forwardQ_Thing))witness_forwardQ_PCD_ThingD_gamma; + witness_forwardQ_PCD_ThingG_methods.total = (int64_t (*) (witness_forwardQ_PCD_Thing, witness_forwardQ_Thing))witness_forwardQ_PCD_ThingD_total; + witness_forwardQ_PCD_ThingG_methods.same = (bool (*) (witness_forwardQ_PCD_Thing, witness_forwardQ_Thing, witness_forwardQ_Thing))witness_forwardQ_PCD_ThingD_same; + witness_forwardQ_PCD_ThingG_methods.__serialize__ = witness_forwardQ_PCD_ThingD___serialize__; + witness_forwardQ_PCD_ThingG_methods.__deserialize__ = witness_forwardQ_PCD_ThingD___deserialize__; + $register(&witness_forwardQ_PCD_ThingG_methods); + } +} \ No newline at end of file diff --git a/compiler/lib/test/9-codegen/witness_forward.h b/compiler/lib/test/9-codegen/witness_forward.h new file mode 100644 index 000000000..b44a95501 --- /dev/null +++ b/compiler/lib/test/9-codegen/witness_forward.h @@ -0,0 +1,142 @@ +/* Acton impl hash: test-hash */ +#pragma once +#include "builtin/builtin.h" +#include "rts/rts.h" +struct witness_forwardQ_PA; +struct witness_forwardQ_PB; +struct witness_forwardQ_PC; +struct witness_forwardQ_Thing; +struct witness_forwardQ_PBD_Thing; +struct witness_forwardQ_PCD_Thing; +typedef struct witness_forwardQ_PA *witness_forwardQ_PA; +typedef struct witness_forwardQ_PB *witness_forwardQ_PB; +typedef struct witness_forwardQ_PC *witness_forwardQ_PC; +typedef struct witness_forwardQ_Thing *witness_forwardQ_Thing; +typedef struct witness_forwardQ_PBD_Thing *witness_forwardQ_PBD_Thing; +typedef struct witness_forwardQ_PCD_Thing *witness_forwardQ_PCD_Thing; +struct witness_forwardQ_PAG_class { + char *$GCINFO; + int $class_id; + $SuperG_class $superclass; + B_NoneType (*__init__) (witness_forwardQ_PA); + void (*__serialize__) (witness_forwardQ_PA, $Serial$state); + witness_forwardQ_PA (*__deserialize__) (witness_forwardQ_PA, $Serial$state); + bool (*__bool__) (witness_forwardQ_PA); + B_str (*__str__) (witness_forwardQ_PA); + B_str (*__repr__) (witness_forwardQ_PA); + bool (*same) (witness_forwardQ_PA, $WORD, $WORD); + int64_t (*total) (witness_forwardQ_PA, $WORD); +}; +struct witness_forwardQ_PA { + struct witness_forwardQ_PAG_class *$class; +}; +struct witness_forwardQ_PBG_class { + char *$GCINFO; + int $class_id; + $SuperG_class $superclass; + B_NoneType (*__init__) (witness_forwardQ_PB); + void (*__serialize__) (witness_forwardQ_PB, $Serial$state); + witness_forwardQ_PB (*__deserialize__) (witness_forwardQ_PB, $Serial$state); + bool (*__bool__) (witness_forwardQ_PB); + B_str (*__str__) (witness_forwardQ_PB); + B_str (*__repr__) (witness_forwardQ_PB); + bool (*same) (witness_forwardQ_PB, $WORD, $WORD); + int64_t (*total) (witness_forwardQ_PB, $WORD); + int64_t (*beta) (witness_forwardQ_PB, $WORD); +}; +struct witness_forwardQ_PB { + struct witness_forwardQ_PBG_class *$class; +}; +struct witness_forwardQ_PCG_class { + char *$GCINFO; + int $class_id; + $SuperG_class $superclass; + B_NoneType (*__init__) (witness_forwardQ_PC); + void (*__serialize__) (witness_forwardQ_PC, $Serial$state); + witness_forwardQ_PC (*__deserialize__) (witness_forwardQ_PC, $Serial$state); + bool (*__bool__) (witness_forwardQ_PC); + B_str (*__str__) (witness_forwardQ_PC); + B_str (*__repr__) (witness_forwardQ_PC); + bool (*same) (witness_forwardQ_PC, $WORD, $WORD); + int64_t (*total) (witness_forwardQ_PC, $WORD); + int64_t (*gamma) (witness_forwardQ_PC, $WORD); +}; +struct witness_forwardQ_PC { + struct witness_forwardQ_PCG_class *$class; +}; +struct witness_forwardQ_ThingG_class { + char *$GCINFO; + int $class_id; + $SuperG_class $superclass; + B_NoneType (*__init__) (witness_forwardQ_Thing, int64_t); + void (*__serialize__) (witness_forwardQ_Thing, $Serial$state); + witness_forwardQ_Thing (*__deserialize__) (witness_forwardQ_Thing, $Serial$state); + bool (*__bool__) (witness_forwardQ_Thing); + B_str (*__str__) (witness_forwardQ_Thing); + B_str (*__repr__) (witness_forwardQ_Thing); + B_value (*__get_attr__) (witness_forwardQ_Thing, B_str); + B_NoneType (*G_init) (witness_forwardQ_Thing); +}; +struct witness_forwardQ_Thing { + struct witness_forwardQ_ThingG_class *$class; + int64_t n; +}; +struct witness_forwardQ_PBD_ThingG_class { + char *$GCINFO; + int $class_id; + $SuperG_class $superclass; + B_NoneType (*__init__) (witness_forwardQ_PBD_Thing); + void (*__serialize__) (witness_forwardQ_PBD_Thing, $Serial$state); + witness_forwardQ_PBD_Thing (*__deserialize__) (witness_forwardQ_PBD_Thing, $Serial$state); + bool (*__bool__) (witness_forwardQ_PBD_Thing); + B_str (*__str__) (witness_forwardQ_PBD_Thing); + B_str (*__repr__) (witness_forwardQ_PBD_Thing); + bool (*same) (witness_forwardQ_PBD_Thing, witness_forwardQ_Thing, witness_forwardQ_Thing); + int64_t (*total) (witness_forwardQ_PBD_Thing, witness_forwardQ_Thing); + int64_t (*beta) (witness_forwardQ_PBD_Thing, witness_forwardQ_Thing); +}; +struct witness_forwardQ_PBD_Thing { + struct witness_forwardQ_PBD_ThingG_class *$class; +}; +struct witness_forwardQ_PCD_ThingG_class { + char *$GCINFO; + int $class_id; + $SuperG_class $superclass; + B_NoneType (*__init__) (witness_forwardQ_PCD_Thing); + void (*__serialize__) (witness_forwardQ_PCD_Thing, $Serial$state); + witness_forwardQ_PCD_Thing (*__deserialize__) (witness_forwardQ_PCD_Thing, $Serial$state); + bool (*__bool__) (witness_forwardQ_PCD_Thing); + B_str (*__str__) (witness_forwardQ_PCD_Thing); + B_str (*__repr__) (witness_forwardQ_PCD_Thing); + bool (*same) (witness_forwardQ_PCD_Thing, witness_forwardQ_Thing, witness_forwardQ_Thing); + int64_t (*total) (witness_forwardQ_PCD_Thing, witness_forwardQ_Thing); + int64_t (*gamma) (witness_forwardQ_PCD_Thing, witness_forwardQ_Thing); +}; +struct witness_forwardQ_PCD_Thing { + struct witness_forwardQ_PCD_ThingG_class *$class; + witness_forwardQ_PA W_PA_34; +}; +extern struct witness_forwardQ_PAG_class witness_forwardQ_PAG_methods; +B_NoneType witness_forwardQ_PAD___init__(witness_forwardQ_PA W_self); +extern struct witness_forwardQ_PBG_class witness_forwardQ_PBG_methods; +B_NoneType witness_forwardQ_PBD___init__(witness_forwardQ_PB W_self); +extern struct witness_forwardQ_PCG_class witness_forwardQ_PCG_methods; +B_NoneType witness_forwardQ_PCD___init__(witness_forwardQ_PC W_self); +extern struct witness_forwardQ_ThingG_class witness_forwardQ_ThingG_methods; +witness_forwardQ_Thing witness_forwardQ_ThingG_new(int64_t); +B_value witness_forwardQ_ThingD___get_attr__(witness_forwardQ_Thing self, B_str name); +B_NoneType witness_forwardQ_ThingG_init(witness_forwardQ_Thing self); +B_NoneType witness_forwardQ_ThingD___init__(witness_forwardQ_Thing self, int64_t n); +extern struct witness_forwardQ_PBD_ThingG_class witness_forwardQ_PBD_ThingG_methods; +witness_forwardQ_PBD_Thing witness_forwardQ_PBD_ThingG_new(); +B_NoneType witness_forwardQ_PBD_ThingD___init__(witness_forwardQ_PBD_Thing W_self); +bool witness_forwardQ_PBD_ThingD_same(witness_forwardQ_PBD_Thing W_self, witness_forwardQ_Thing a, witness_forwardQ_Thing b); +int64_t witness_forwardQ_PBD_ThingD_total(witness_forwardQ_PBD_Thing W_self, witness_forwardQ_Thing self); +int64_t witness_forwardQ_PBD_ThingD_beta(witness_forwardQ_PBD_Thing W_self, witness_forwardQ_Thing self); +extern struct witness_forwardQ_PCD_ThingG_class witness_forwardQ_PCD_ThingG_methods; +witness_forwardQ_PCD_Thing witness_forwardQ_PCD_ThingG_new(); +B_NoneType witness_forwardQ_PCD_ThingD___init__(witness_forwardQ_PCD_Thing W_self); +int64_t witness_forwardQ_PCD_ThingD_gamma(witness_forwardQ_PCD_Thing W_self, witness_forwardQ_Thing self); +int64_t witness_forwardQ_PCD_ThingD_total(witness_forwardQ_PCD_Thing W_self, witness_forwardQ_Thing G_1p); +bool witness_forwardQ_PCD_ThingD_same(witness_forwardQ_PCD_Thing W_self, witness_forwardQ_Thing G_1p, witness_forwardQ_Thing G_2p); +void witness_forwardQ___init__ (); \ No newline at end of file diff --git a/compiler/lib/test/9-codegen/witness_forward.input b/compiler/lib/test/9-codegen/witness_forward.input new file mode 100644 index 000000000..caed9e7e9 --- /dev/null +++ b/compiler/lib/test/9-codegen/witness_forward.input @@ -0,0 +1,56 @@ +# recursive group: +class PA[G_self] (__builtin__.value): + pure def __init__ (W_self : PA[G_self]) -> None: + return None + same : (G_self, G_self) -> __builtin__.bool + total : (G_self) -> __builtin__.int +class PB[G_self] (PA[G_self], __builtin__.value): + pure def __init__ (W_self : PB[G_self]) -> None: + PA.__init__@[G_self](W_self) + return None + beta : (G_self) -> __builtin__.int +class PC[G_self] (PA[G_self], __builtin__.value): + pure def __init__ (W_self : PC[G_self]) -> None: + PA.__init__@[G_self](W_self) + return None + gamma : (G_self) -> __builtin__.int +class Thing (__builtin__.object, __builtin__.value): + pure def __get_attr__ (self : Thing, name : __builtin__.str) -> ?__builtin__.value: + return None + pure def G_init (self : Thing) -> None: + pass + return None + @property + n : __builtin__.int + pure def __init__ (self : Thing, n : UNBOXED __builtin__.int) -> None: + self.n = (UNBOX __builtin__.int n) + return None +class PBD_Thing (PB[Thing], PA[Thing], __builtin__.value): + pure def __init__ (W_self : PBD_Thing) -> None: + PB.__init__@[Thing](W_self) + return None + pure def same (W_self : PBD_Thing, a : Thing, b : Thing) -> UNBOXED __builtin__.bool: + N_tmp: UNBOXED __builtin__.bool = (a.n == b.n) + return (UNBOX __builtin__.bool N_tmp) + pure def total (W_self : PBD_Thing, self : Thing) -> UNBOXED __builtin__.int: + return self.n + pure def beta (W_self : PBD_Thing, self : Thing) -> UNBOXED __builtin__.int: + N_1tmp: UNBOXED __builtin__.int = (UNBOX __builtin__.int 1) + return (UNBOX __builtin__.int N_1tmp) +class PCD_Thing (PC[Thing], PA[Thing], __builtin__.value): + @property + W_PA_34 : PA[Thing] + pure def __init__ (W_self : PCD_Thing) -> None: + W_self.W_PA_34 = PBD_Thing() + PC.__init__@[Thing](W_self) + return None + pure def gamma (W_self : PCD_Thing, self : Thing) -> UNBOXED __builtin__.int: + N_2tmp: UNBOXED __builtin__.int = (UNBOX __builtin__.int 2) + return (UNBOX __builtin__.int N_2tmp) + pure def total (W_self : PCD_Thing, G_1p : Thing) -> UNBOXED __builtin__.int: + N_3tmp: UNBOXED __builtin__.int = W_self.W_PA_34.total(G_1p) + return (UNBOX __builtin__.int N_3tmp) + pure def same (W_self : PCD_Thing, G_1p : Thing, G_2p : Thing) -> UNBOXED __builtin__.bool: + N_4tmp: UNBOXED __builtin__.bool = W_self.W_PA_34.same(G_1p, G_2p) + return (UNBOX __builtin__.bool N_4tmp) +# (recursive group) \ No newline at end of file diff --git a/compiler/lib/test/ActonSpec.hs b/compiler/lib/test/ActonSpec.hs index dbe786bec..531df4a09 100644 --- a/compiler/lib/test/ActonSpec.hs +++ b/compiler/lib/test/ActonSpec.hs @@ -1851,6 +1851,7 @@ main = do describe "Pass 3: Types" $ do testTypes env0 ["deact"] testTypes env0 ["test_discovery"] + testTypes env0 ["witness_forward"] testAttributesInitialization env0 @@ -2107,6 +2108,7 @@ main = do testCodeGen env0 ["lines"] testCodeGen env0 ["chunking"] testCodeGen env0 ["boxparam"] + testCodeGen env0 ["witness_forward"] -- A local that is live across a for-loop must be emitted as `volatile` so it -- survives the loop's StopIteration setjmp/longjmp under optimization. testCodeGenContains env0 "forloop_volatile" ["volatile B_str marker", "if ($PUSH())"] diff --git a/compiler/lib/test/src/witness_forward.act b/compiler/lib/test/src/witness_forward.act new file mode 100644 index 000000000..8ce8c608c --- /dev/null +++ b/compiler/lib/test/src/witness_forward.act @@ -0,0 +1,33 @@ +# Extensions leaving inherited protocol slots to another witness: the +# converted witness classes must contain ordinary forwarding methods (see +# Converter.fwdImpl). PC$Thing gets forwarding defs for PA's static 'same' +# and instance 'total', routed to the earlier PB extension's witness. + +protocol PA: + @staticmethod + same : (Self,Self) -> bool + total : () -> int + +protocol PB (PA): + beta : () -> int + +protocol PC (PA): + gamma : () -> int + +class Thing(object): + n: int + def __init__(self, n: int): + self.n = n + +extension Thing (PB): + @staticmethod + def same(a: Thing, b: Thing) -> bool: + return a.n == b.n + def total(self): + return self.n + def beta(self): + return 1 + +extension Thing (PC): + def gamma(self): + return 2 diff --git a/test/core_lang_auto/conflicting_signatures__bf.act b/test/core_lang_auto/conflicting_signatures__bf.act new file mode 100644 index 000000000..1cc2c9373 --- /dev/null +++ b/test/core_lang_auto/conflicting_signatures__bf.act @@ -0,0 +1,10 @@ +# A slot inherited through two parents with incompatible signatures is rejected. + +protocol Alpha: + f : (int) -> int + +protocol Beta: + f : (str) -> str + +protocol AlphaBeta (Alpha, Beta): + pass diff --git a/test/core_lang_auto/mro_inconsistent_instances__bf.act b/test/core_lang_auto/mro_inconsistent_instances__bf.act new file mode 100644 index 000000000..7470b34e2 --- /dev/null +++ b/test/core_lang_auto/mro_inconsistent_instances__bf.act @@ -0,0 +1,13 @@ +# A common ancestor inherited via differently instantiated paths is rejected. + +protocol Zero[T]: + f : (T) -> T + +protocol Alpha (Zero[int]): + pass + +protocol Beta (Zero[str]): + pass + +protocol AlphaBeta (Alpha, Beta): + pass diff --git a/test/core_lang_auto/mro_inconsistent_resolution__bf.act b/test/core_lang_auto/mro_inconsistent_resolution__bf.act new file mode 100644 index 000000000..6d4c21c47 --- /dev/null +++ b/test/core_lang_auto/mro_inconsistent_resolution__bf.act @@ -0,0 +1,10 @@ +# A contradictory ancestry order is rejected. + +protocol Alpha: + f : (int) -> int + +protocol Beta (Alpha): + pass + +protocol AlphaBeta (Alpha, Beta): + pass diff --git a/test/core_lang_auto/witness_forward_cyclic.act b/test/core_lang_auto/witness_forward_cyclic.act new file mode 100644 index 000000000..316a127d6 --- /dev/null +++ b/test/core_lang_auto/witness_forward_cyclic.act @@ -0,0 +1,43 @@ +# Forwarding into a cyclic witness path: the Eq witnesses for Node and Edge +# construct each other (a WitKnots cycle, broken with optional parameters), +# and Hashable[Node] forwards __eq__ into that cyclic Eq witness. + +class Node(object): + v: int + r: ?Edge + def __init__(self, v: int, r: ?Edge): + self.v = v + self.r = r + +class Edge(object): + w: int + l: ?Node + def __init__(self, w: int, l: ?Node): + self.w = w + self.l = l + +extension Node (Eq): + def __eq__(a: Node, b: Node) -> bool: + return a.v == b.v and a.r == b.r + +extension Edge (Eq): + def __eq__(a: Edge, b: Edge) -> bool: + return a.w == b.w and a.l == b.l + +extension Node (Hashable): + def hash(self, h): + self.v.hash(h) + +actor main(env): + a = Node(1, Edge(2, None)) + b = Node(1, Edge(2, None)) + c = Node(1, Edge(3, None)) + if a != b or a == c: + print("FAIL: cyclic Eq witnesses") + await async env.exit(1) + d: dict[Node, str] = {} + d[a] = "hit" + if b not in d or c in d: + print("FAIL: dict through __eq__ forwarded into a cyclic witness") + await async env.exit(1) + await async env.exit(0) diff --git a/test/core_lang_auto/witness_forward_diamond.act b/test/core_lang_auto/witness_forward_diamond.act new file mode 100644 index 000000000..08717130c --- /dev/null +++ b/test/core_lang_auto/witness_forward_diamond.act @@ -0,0 +1,35 @@ +# A slot inherited through two parents with agreeing signatures must produce +# exactly one forwarding method per generated witness class (main and +# sibling), routed to the extension that implements it. + +protocol Alpha: + f : (int) -> int + +protocol Beta: + f : (int) -> int + +protocol AlphaBeta (Alpha, Beta): + pass + +class Thing(object): + def __init__(self): + pass + +extension Thing (Alpha): + def f(self, x: int) -> int: + return x + +extension Thing (AlphaBeta): + pass + +def via_beta[T(Beta)](x: T, k: int) -> int: + return Beta.f(x, k) + +actor main(env): + if AlphaBeta.f(Thing(), 1) != 1: + print("FAIL: forwarded diamond slot in the main witness class") + await async env.exit(1) + if via_beta(Thing(), 5) != 5: + print("FAIL: forwarded diamond slot in the sibling witness class") + await async env.exit(1) + await async env.exit(0) diff --git a/test/core_lang_auto/witness_forward_diamond_clash__bf.act b/test/core_lang_auto/witness_forward_diamond_clash__bf.act new file mode 100644 index 000000000..33388fcc5 --- /dev/null +++ b/test/core_lang_auto/witness_forward_diamond_clash__bf.act @@ -0,0 +1,26 @@ +# A slot inherited through two parents with incompatible signatures is +# rejected by ordinary type checking; witness forwarding must not paper over +# the clash. + +protocol Alpha: + f : (int) -> int + +protocol Beta: + f : (str) -> str + +protocol AlphaBeta (Alpha, Beta): + pass + +class Thing(object): + def __init__(self): + pass + +extension Thing (Alpha): + def f(self, x: int) -> int: + return x + +extension Thing (AlphaBeta): + pass + +actor main(env): + await async env.exit(0) diff --git a/test/core_lang_auto/witness_forward_generic.act b/test/core_lang_auto/witness_forward_generic.act new file mode 100644 index 000000000..4172a7e01 --- /dev/null +++ b/test/core_lang_auto/witness_forward_generic.act @@ -0,0 +1,36 @@ +# Forwarding between generic extensions: Hashable[Box[A]] forwards __eq__ to +# Ord[Box[A]]. Generic slots pass boxed arguments, and the witness class must +# come out complete enough to instantiate for dict keys. + +class Box[X](object): + item: X + def __init__(self, item: X): + self.item = item + +extension Box[A(Ord)] (Ord): + def __eq__(a: Box[A], b: Box[A]) -> bool: + return a.item == b.item + def __lt__(a: Box[A], b: Box[A]) -> bool: + return a.item < b.item + +extension Box[A(Ord,Hashable)] (Hashable): + def hash(self, h): + self.item.hash(h) + +actor main(env): + d: dict[Box[int], str] = {} + d[Box(1)] = "one" + d[Box(2)] = "two" + if d[Box(1)] != "one" or Box(2) not in d or Box(3) in d: + print("FAIL: dict through forwarded generic __eq__") + await async env.exit(1) + l = sorted([Box(3), Box(1), Box(2)]) + if l[0].item != 1 or l[1].item != 2 or l[2].item != 3: + print("FAIL: sorted through generic Ord witness") + await async env.exit(1) + s: dict[Box[str], int] = {} + s[Box("a")] = 1 + if Box("a") not in s: + print("FAIL: str instantiation of forwarded generic __eq__") + await async env.exit(1) + await async env.exit(0) diff --git a/test/core_lang_auto/witness_forward_nested.act b/test/core_lang_auto/witness_forward_nested.act new file mode 100644 index 000000000..80a690d76 --- /dev/null +++ b/test/core_lang_auto/witness_forward_nested.act @@ -0,0 +1,55 @@ +# Forwarding through a nested witness path: Coll is a second (sibling) base of +# Seq2, so the provider for Cont's inherited Coll slots is the sibling witness +# reached through Seq2$Vec's witness field. Covers an instance slot (total), +# an inherited instance slot (Src.total via Coll) and a static slot with Self +# in result position (make), both statically and through a generic witness +# parameter. + +protocol Src: + total : () -> int + +protocol Coll (Src): + @staticmethod + make : (int) -> Self + +protocol Extra: + tag : () -> int + +protocol Seq2 (Extra, Coll): + step : () -> int + +protocol Cont (Coll): + has : (int) -> bool + +class Vec(object): + n: int + def __init__(self, n: int): + self.n = n + +extension Vec (Seq2): + def tag(self): + return 7 + def step(self): + return 1 + def total(self): + return self.n + @staticmethod + def make(k: int) -> Vec: + return Vec(k) + +extension Vec (Cont): + def has(self, i: int) -> bool: + return i < self.n + +def use_cont[T(Cont)](x: T) -> int: + y: T = Cont.make(x.total() + 1) + return y.total() + +actor main(env): + if use_cont(Vec(5)) != 6: + print("FAIL: forwarded slots through generic Cont witness") + await async env.exit(1) + if Cont.make(3).total() != 3: + print("FAIL: forwarded static make at concrete type") + await async env.exit(1) + await async env.exit(0) diff --git a/test/core_lang_auto/witness_forward_order.act b/test/core_lang_auto/witness_forward_order.act new file mode 100644 index 000000000..11fd1b894 --- /dev/null +++ b/test/core_lang_auto/witness_forward_order.act @@ -0,0 +1,39 @@ +# Extension order decides the provider: here Hashable comes first and defines +# __eq__ directly (deliberately as parity equality), so the later Ord extension +# gets a forwarding __eq__ that must route to Hashable's direct implementation. +# Direct implementations take precedence; forwarding only fills missing slots. + +class Par(object): + x: int + def __init__(self, x: int): + self.x = x + +extension Par (Hashable): + def __eq__(a: Par, b: Par) -> bool: + return a.x % 2 == b.x % 2 + def hash(self, h): + (self.x % 2).hash(h) + +extension Par (Ord): + def __lt__(a: Par, b: Par) -> bool: + return a.x < b.x + +actor main(env): + # The canonical Eq witness is Hashable's direct (parity) implementation. + if not (Par(2) == Par(4)) or Par(2) == Par(3): + print("FAIL: language-level == must use the direct implementation") + await async env.exit(1) + # Ord's inherited __le__ default calls __lt__ and the forwarded __eq__: + # 3 < 1 is False, but 3 == 1 holds under parity equality. + if not (Par(3) <= Par(1)): + print("FAIL: __le__ default through Ord's forwarded __eq__") + await async env.exit(1) + if not (Par(1) < Par(2)) or Par(2) < Par(1): + print("FAIL: __lt__ through Ord witness") + await async env.exit(1) + d: dict[Par, str] = {} + d[Par(2)] = "even" + if Par(4) not in d or Par(5) in d: + print("FAIL: dict through direct parity __eq__") + await async env.exit(1) + await async env.exit(0) diff --git a/test/core_lang_auto/witness_forward_sibling.act b/test/core_lang_auto/witness_forward_sibling.act new file mode 100644 index 000000000..418c3808b --- /dev/null +++ b/test/core_lang_auto/witness_forward_sibling.act @@ -0,0 +1,40 @@ +# A witness class with an inherited protocol slot implemented by a sibling +# witness gets an ordinary forwarding method: Hashable[Pt] lacks __eq__, which +# is provided by the earlier Ord[Pt] extension. The dict/set runtime calls +# __eq__ through the Hashable witness, so lookups with equal but distinct +# key objects exercise the forwarded slot. + +class Pt(object): + x: int + def __init__(self, x: int): + self.x = x + +extension Pt (Ord): + def __eq__(a: Pt, b: Pt) -> bool: + return a.x == b.x + def __lt__(a: Pt, b: Pt) -> bool: + return a.x < b.x + +extension Pt (Hashable): + def hash(self, h): + self.x.hash(h) + +actor main(env): + d: dict[Pt, str] = {} + d[Pt(1)] = "one" + d[Pt(2)] = "two" + if d[Pt(1)] != "one": + print("FAIL: dict lookup through forwarded __eq__") + await async env.exit(1) + if Pt(2) not in d or Pt(3) in d: + print("FAIL: dict membership through forwarded __eq__") + await async env.exit(1) + s = {Pt(4), Pt(4), Pt(5)} + if len(s) != 2: + print("FAIL: set dedup through forwarded __eq__") + await async env.exit(1) + # Protocol default methods are inherited, not forwarded. + if Pt(1) != Pt(1) or not (Pt(1) <= Pt(1)): + print("FAIL: inherited default methods") + await async env.exit(1) + await async env.exit(0) diff --git a/test/regression_auto/witness_forward_import/Build.act b/test/regression_auto/witness_forward_import/Build.act new file mode 100644 index 000000000..3481b82a3 --- /dev/null +++ b/test/regression_auto/witness_forward_import/Build.act @@ -0,0 +1,2 @@ +name = "witness_forward_import" +fingerprint = 0x969df9b892763322 diff --git a/test/regression_auto/witness_forward_import/src/hashpt.act b/test/regression_auto/witness_forward_import/src/hashpt.act new file mode 100644 index 000000000..6fe6b6cec --- /dev/null +++ b/test/regression_auto/witness_forward_import/src/hashpt.act @@ -0,0 +1,13 @@ +# The extending module: Hashable[Pt] leaves __eq__ to the imported Ord +# witness. Since Eq was finalized elsewhere, this extension registers no +# Eq witness of its own; uses here and in importing modules resolve to +# points' canonical one. + +import points + +extension points.Pt (Hashable): + def hash(self, h): + self.x.hash(h) + +def same_here(a: points.Pt, b: points.Pt) -> bool: + return a == b diff --git a/test/regression_auto/witness_forward_import/src/points.act b/test/regression_auto/witness_forward_import/src/points.act new file mode 100644 index 000000000..a536abce5 --- /dev/null +++ b/test/regression_auto/witness_forward_import/src/points.act @@ -0,0 +1,13 @@ +# The provider module: defines the class and its Ord extension. An importing +# module's Hashable extension must forward __eq__ to this witness. + +class Pt(object): + x: int + def __init__(self, x: int): + self.x = x + +extension Pt (Ord): + def __eq__(a: Pt, b: Pt) -> bool: + return a.x == b.x + def __lt__(a: Pt, b: Pt) -> bool: + return a.x < b.x diff --git a/test/regression_auto/witness_forward_import/src/witness_forward_import.act b/test/regression_auto/witness_forward_import/src/witness_forward_import.act new file mode 100644 index 000000000..9f7a9718e --- /dev/null +++ b/test/regression_auto/witness_forward_import/src/witness_forward_import.act @@ -0,0 +1,27 @@ +# A third module importing both the provider (points: class + Ord) and the +# extender (hashpt: Hashable, with __eq__ finalized by points). Eq[Pt] must +# resolve to points' canonical witness here even though hashpt's extension +# also covers Eq through its ancestry. + +import points +import hashpt + +actor main(env): + a = points.Pt(1) + b = points.Pt(1) + if not (a == b) or a == points.Pt(2): + print("FAIL: == through the imported Ord witness") + await async env.exit(1) + if not hashpt.same_here(a, b): + print("FAIL: == inside the extending module") + await async env.exit(1) + d: dict[points.Pt, str] = {} + d[a] = "one" + if b not in d or points.Pt(7) in d: + print("FAIL: dict through __eq__ forwarded to the imported witness") + await async env.exit(1) + l = sorted([points.Pt(3), points.Pt(1), points.Pt(2)]) + if l[0].x != 1 or l[1].x != 2 or l[2].x != 3: + print("FAIL: sorted through the imported Ord witness") + await async env.exit(1) + await async env.exit(0)