use of ast.Ast.MethodType in project L42 by ElvisResearchGroup.
the class AlternativeMethodTypes method _bestMatchMtype.
public static MethodType _bestMatchMtype(Program p, MethodType superMt, List<MethodType> mts) {
List<MethodType> res = new ArrayList<>();
for (MethodType mt : mts) {
if (TypeSystem._methMdfTSubtype(mt, superMt)) {
if (!res.stream().anyMatch(mti -> TypeSystem._methMdfTSubtype(mti, mt))) {
res = res.stream().filter(mti -> !TypeSystem._methMdfTSubtype(mt, mti)).collect(Collectors.toList());
//if there is no method that is even better, add
res.add(mt);
}
}
}
//assert res.size()==1: res.size(); sometime is false, for example capsule->capsule and mut->mut
if (res.isEmpty()) {
return null;
}
if (res.size() == 1) {
return res.get(0);
}
//for final limitations
List<MethodType> _res = res;
Optional<MethodType> res1 = res.stream().filter(mt1 -> _res.stream().allMatch(mt2 -> Functions.isSubtype(mt1.getReturnType().getMdf(), mt2.getReturnType().getMdf()))).findAny();
if (res1.isPresent()) {
return res1.get();
}
assert false : "";
return res.get(0);
}
use of ast.Ast.MethodType in project L42 by ElvisResearchGroup.
the class TsLibrary method coherentF.
static boolean coherentF(Program p, MethodWithType ck, MethodWithType mwt) {
MethodType mt = mwt.getMt();
Mdf m = mt.getMdf();
if (mwt.getMs().getUniqueNum() != ck.getMs().getUniqueNum()) {
return false;
}
// internally do noFwd
Type Ti = _extractTi(ck, mwt.getMs().getName());
if (Ti == null) {
return false;
}
//if(m==Mdf.Class){return false;}
if (m == Mdf.Readable || m == Mdf.Immutable) {
//getter
if (!mt.getTs().isEmpty()) {
return false;
}
Type Ti_ = TypeManipulation._toRead(Ti);
//p|-toRead(Ti)<=T
if (Ti_ == null) {
return false;
}
if (null != TypeSystem.subtype(p, Ti_, mt.getReturnType())) {
return false;
}
return true;
}
if (m != Mdf.Mutable) {
return false;
}
//exposer/setter
if (mt.getTs().isEmpty()) {
//exposer
Type Ti_ = TypeManipulation.capsuleToLent(Ti);
//p|-capsuleToLent(Ti)<=T
if (Ti_ == null) {
return false;
}
if (null != TypeSystem.subtype(p, Ti_, mt.getReturnType())) {
return false;
}
return true;
}
//setter refine? mut method Void m[n?](T that)
if (!mt.getReturnType().equals(Type.immVoid)) {
return false;
}
if (mt.getTs().size() != 1) {
return false;
}
if (!mwt.getMs().getNames().get(0).equals("that")) {
return false;
}
Type T = mt.getTs().get(0);
if (null != TypeSystem.subtype(p, Ti, T)) {
return false;
}
if (Ti.getMdf() == Mdf.Readable) {
Mdf mT = T.getMdf();
if (mT != Mdf.Capsule && mT != Mdf.Immutable) {
return false;
}
}
return true;
}
use of ast.Ast.MethodType in project L42 by ElvisResearchGroup.
the class TsLibrary method memberMethod.
default default TOutM memberMethod(TIn in, List<Type> supertypes, MethodWithType mwt) {
//(member method)
//Phase| p| Ps |-M ~> M'
// where
// M =refine? mdf method T m(T1 x1 .. Tn xn)exceptions Ps0 e?
// M'=refine? mdf method T m(T1 x1 .. Tn xn)exceptions Ps0 e?'
// G=this:mdf This0,x1:T1,..,xn:Tn
// if e?=e then
// Typed| p| G |- e ~> e?':_ <=fwd% T | empty;Ps1
// forall P1 in Ps1 exists P0 in Ps0 such that p|-P1<=P0
//else
// e?=e?'
MethodWithType mwt1;
if (!mwt.get_inner().isPresent()) {
mwt1 = mwt;
} else {
TIn newIn = in.freshGFromMt(mwt);
TOut out = type(newIn);
if (!out.isOk()) {
return out.toError();
}
for (Path P1 : out.toOk().exceptions) {
//exists P0 in Ps0 such that p|-P1<=P0
boolean ok = mwt.getMt().getExceptions().stream().anyMatch(P0 -> null == TypeSystem.subtype(newIn.p, P1, P0.getPath()));
if (!ok) {
return new TErr(newIn, "", P1.toImmNT(), ErrorKind.MethodLeaksExceptions);
}
}
if (!out.toOk().returns.isEmpty()) {
return new TErr(newIn, "", out.toOk().returns.get(0), ErrorKind.MethodLeaksReturns);
}
mwt1 = mwt.with_inner(Optional.of(out.toOk().annotated));
}
if (mwt.getMt().isRefine()) {
// /or method declares an exception (P) which is not a subtype of ancestor exceptions
for (Type t : supertypes) {
Path P = t.getPath();
ClassB cbP = in.p.extractClassB(P);
MethodWithType mwtP = (MethodWithType) cbP._getMember(mwt.getMs());
if (mwtP == null) {
continue;
}
MethodType M0 = From.from(mwtP.getMt(), P);
ErrorKind kind = TypeSystem.subtype(in.p, mwt.getMt().getReturnType(), M0.getReturnType());
if (kind != null) {
return new TErr(in, "", P.toImmNT(), ErrorKind.InvalidImplements);
}
{
int i = -1;
for (Type Ti : mwt.getMt().getTs()) {
i += 1;
Type T1i = M0.getTs().get(i);
if (!in.p.equiv(Ti, T1i)) {
return new TErr(in, "", P.toImmNT(), ErrorKind.InvalidImplements);
}
}
}
for (Type Pi : mwt.getMt().getExceptions()) {
//exists Pj in Ps' such that p |- Pi<=Pj
boolean ok = M0.getExceptions().stream().anyMatch(Pj -> null == TypeSystem.subtype(in.p, Pi.getPath(), Pj.getPath()));
if (!ok) {
return new TErr(in, "", P.toImmNT(), ErrorKind.InvalidImplements);
}
}
}
}
return new TOkM(mwt1);
}
use of ast.Ast.MethodType in project L42 by ElvisResearchGroup.
the class TsLibrary method coherentK.
//coherent(n?,p,T1 x1..Tn xn,
//refine? class method T m[n?] (T1' x1..Tn' xn) exception _)
//where
//p|- This0 <=T.P and p|-Ti'<=fwd Ti
//T.mdf!=class and if T.mdf in {imm,capsule}, mut notin (T1..Tn).mdfs
static boolean coherentK(Program p, MethodWithType ck) {
MethodType mt = ck.getMt();
if (mt.getMdf() != Mdf.Class) {
return false;
}
Type rt = mt.getReturnType();
if (null != TypeSystem.subtype(p, Path.outer(0), rt.getPath())) {
return false;
}
Mdf m = rt.getMdf();
if (m == Mdf.Class) {
return false;
}
boolean immOrC = (m == Mdf.Immutable || m == Mdf.Capsule);
boolean lentOrR = (m == Mdf.Lent || m == Mdf.Readable);
int allowedR = lentOrR ? 1 : 0;
for (Type ti : mt.getTs()) {
Mdf mi = ti.getMdf();
if (mi == Mdf.Lent) {
return false;
}
if (mi == Mdf.Readable) {
if (allowedR == 0) {
return false;
}
allowedR -= 1;
}
if (immOrC & (mi == Mdf.Mutable || mi == Mdf.MutableFwd)) {
return false;
}
}
return true;
}
use of ast.Ast.MethodType in project L42 by ElvisResearchGroup.
the class TsMCall method tsMCall.
default default TOut tsMCall(TIn in, MCall s) {
Type _rec = GuessTypeCore._of(in.p, in, s.getInner());
if (_rec == null) {
return new TErr(in, "", null, ErrorKind.SelectorNotFound);
}
Path rec = _rec.getPath();
if (rec.isPrimitive()) {
return new TErr(in, "MethodCall on primitive type", null, ErrorKind.SelectorNotFound);
}
MethodType mDec = AlternativeMethodTypes._mtDeclared(in.p, rec, s.getS());
if (mDec == null) {
return new TErr(in, "", null, ErrorKind.SelectorNotFound);
}
Type ret = mDec.getReturnType();
ErrorKind kind = TypeSystem.subtype(in.p, ret.getPath(), in.expected.getPath());
if (kind != null) {
return new TErr(in, "", ret, kind);
}
List<MethodType> mTypes = AlternativeMethodTypes.types(mDec);
MethodType mType = AlternativeMethodTypes._firstMatchReturn(in.p, in.expected, mTypes);
if (mType == null) {
return new TErr(in, "", ret, ErrorKind.NotSubtypeMdf);
}
//unachievable return type (T) for method (P.ms) [line numbers of expression and declaration]
//2 type all the parameters with mutOnlyToLent(Ts) //we may include mutOnlyToLent in the computation of the MTypes, instead of in the loop below
List<TOk> resp = new ArrayList<>();
List<Type> computed = new ArrayList<>();
List<ExpCore> annotated = new ArrayList<>();
ExpCore e0 = s.getInner();
Type t0 = new Type(mType.getMdf(), rec, Doc.empty());
TOut _res0 = type(in.withE(e0, TypeManipulation.mutOnlyToLent(t0)));
if (!_res0.isOk()) {
return improveReceiverError(in, t0, _res0.toError());
}
TOk res0 = _res0.toOk();
Mdf recMdf = _res0.toOk().computed.getMdf();
{
int i = -1;
for (ExpCore ei : s.getEs()) {
i += 1;
Type ti = mType.getTs().get(i);
TOut _resi = type(in.withE(ei, TypeManipulation.mutOnlyToLent(ti)));
if (!_resi.isOk()) {
return _resi.toError();
}
resp.add(_resi.toOk());
computed.add(_resi.toOk().computed);
annotated.add(_resi.toOk().annotated);
}
}
MethodType computedMt = new MethodType(false, recMdf, computed, in.expected, Collections.emptyList());
MethodType mTypeRev = AlternativeMethodTypes._bestMatchMtype(in.p, computedMt, mTypes);
if (mTypeRev != null) {
MCall resM = new MCall(res0.annotated, s.getS(), s.getDoc(), annotated, s.getP());
TOk res = new TOk(in, resM, mTypeRev.getReturnType());
// Trs[with r in resp (use[r.Tr])].collapse())
res = res.trUnion(res0);
for (TOk oki : resp) {
res = res.trUnion(oki);
}
return res;
}
//3 if there is no matching method, we may need to retype some mut
//in capsule caused by mvp:
//it is not over if there is a mathing method type with mutToCapsule(result param types)
//tsToCaps=Ts[with r in resp (use[mutToCapsule(r.T)])]
//mTypeMVP=_bestMatchMtype(tsToCaps,TSIn.T,mTypes)
List<Type> tsToCaps = new ArrayList<>();
for (TOk r : resp) {
Mdf m = r.computed.getMdf();
if (m == Mdf.MutableFwd || m == Mdf.MutablePFwd) {
return new TErr(in, "impossible to search for mvp since mdf " + m, mTypes.get(0).getReturnType(), ErrorKind.NotSubtypeClass);
}
Type nt = TypeManipulation.mutToCapsule(r.computed);
tsToCaps.add(nt);
}
computedMt = computedMt.withTs(tsToCaps).withMdf(TypeManipulation.mutToCapsule(computedMt.getMdf()));
MethodType mTypeMVP = AlternativeMethodTypes._bestMatchMtype(in.p, computedMt, mTypes);
if (mTypeMVP == null) {
return new TErr(in, "mvp candidate notfound", mTypes.get(0).getReturnType(), ErrorKind.NotSubtypeClass);
}
//To be happy, we can retype the obtained mut parameters into expected capsule
TOut _newRes0 = innerMVPRetype(res0, t0.withMdf(mTypeMVP.getMdf()));
if (!_newRes0.isOk()) {
return _newRes0;
}
TOk newRes0 = _newRes0.toOk();
List<TOk> newResp = new ArrayList<>();
{
int i = -1;
for (TOk ri : resp) {
i += 1;
Type ti = mTypeMVP.getTs().get(i);
TOut outi = innerMVPRetype(ri, ti);
if (!outi.isOk()) {
return outi.toError();
}
newResp.add(outi.toOk());
}
}
//return res=makeMCallOK(TSIn,respMVP,mTypeMVP)
MCall resM = new MCall(newRes0.annotated, s.getS(), s.getDoc(), Map.of(r -> r.annotated, newResp), s.getP());
TOk res = new TOk(in, resM, mTypeMVP.getReturnType());
// Trs[with r in resp (use[r.Tr])].collapse())
res = res.trUnion(newRes0);
for (TOk oki : newResp) {
res = res.trUnion(oki);
}
return res;
}
Aggregations