bool IsAgentsEyes(ObjSpec obj) { if (obj.referredToAs == "eyes" && obj.owner == Owner.You) { return(true); } return(false); }
private bool isObjAssignable(ObjSpec sObj, ObjSpec slotObj) { C.Nn(sObj, slotObj); foreach (var slotMember in slotObj.Env.Items) { var sMember = sObj.Env.GetFromThisEnvOnlyOrNull(slotMember.Key.Ident, null); if (sMember == null || !isAssignable(sMember.Value, slotMember.Value.Value)) { return(false); } } return(true); }
private void specStm(Stm e, Env <Spec> env) { C.Nn(e, env); switch (e) { case Declr d: if (d.Exp == null) { env.Declare(d, NotSetSpec.Instance); } else { env.Declare(d, specExp(d.Exp, env, AnySpec.Instance)); if (d.Exp is Ident fromIdent) { d.AssignedFrom.Add(fromIdent); } d.Ident.Spec = d.Exp.Spec; } break; case Assign a: switch (a.To) { case Ident ident: { var orig = env.Get(ident, true).Value; var slot3 = orig == NotSetSpec.Instance ? AnySpec.Instance : orig; var s = specExp(a.Exp, env, slot3); if (orig == NotSetSpec.Instance) { env.Set(ident, s); } if (a.Exp is Ident fromIdent) { a.AssignedFrom.Add(fromIdent); } break; } case MemberAccess ma: { var minObjEnv = env.Create(); var declr = new Let( new Ident(ma.Ident.Name, ma.Ident.TokenType) .CopyInfoFrom(ma.Ident, true), Void.Instance); minObjEnv.Declare(declr, AnySpec.Instance); var minObj = new ObjSpec(minObjEnv); var maExpS = specExp(ma.Exp, env, minObj); if (maExpS is ObjSpec objS) { var orig = objS.Env.Get(ma.Ident, true).Value; var slot3 = orig == NotSetSpec.Instance ? AnySpec.Instance : orig; var s = specExp(a.Exp, env, slot3); if (orig == AnySpec.Instance) { objS.Env.Set(ma.Ident, s); a.AssignedFrom.Add(ma.Ident); } } break; } default: throw new NotSupportedException(); } break; case Return r: var slot2 = returns.Peek(); var retS = specExp(r.Exp, env, slot2 == NotSetSpec.Instance ? AnySpec.Instance : slot2); returns.UpdateTop(retS); break; case Loop l: specSequence(l.Body, env); break; case Break _: break; case Continue _: break; case Toss ts: var _ = specExp(ts.Exception, env, AnySpec.Instance); // TODO requires exp to be of some type? break; case Attempt att: specSequence(att.Body, env); if (att.Grab != null) { var grabEnv = env.Create(); var exDeclr = new Let(new Ident("exception", TokenType.Ident)); grabEnv.Declare(exDeclr, AnySpec.Instance); specSequence(att.Grab, grabEnv); } if (att.AtLast != null) { specSequence(att.AtLast, env); } break; case Import imp: isImportContext = true; var objSpecWithNoMembers = new ObjSpec(env.Create()); var modImpEl = specExp(imp.QualifiedIdent, env, objSpecWithNoMembers); isImportContext = false; if (modImpEl is ObjSpec modImp) { env.AddImport(imp.QualifiedIdent, modImp.Env, (Declr)modImp.Parent); } break; case Sequence seq: specSequence(seq, env); break; default: throw new NotSupportedException(); } }
private Spec specExp2(Exp exp, Env <Spec> env, Spec slot) { C.Nn(exp, env, slot); C.ReturnsNn(); Spec ss; switch (exp) { case Ident i: if (isImportContext) { return(env.GetWithoutImports(i).Value); } else { var orig = env.Get(i).Value; if (orig == NotSetSpec.Instance || orig == AnySpec.Instance) { //prog.RemarkList.AttemptToReadUninitializedVariableWarn(i); setIdentAndAssignedFrom(env, i, slot); return(slot); } if (!isAssignable(orig, slot)) { prog.RemarkList.CannotConvertType(orig, slot, i); } return(orig); } case FnApply fna: { if (fna.Fn is Ident fnI && fnI.Name == "typeof") { if (!(fna.Arguments[0] is Spec)) { fna.Arguments = new FnArguments(new List <Exp> { specExp(fna.Arguments[0], env, AnySpec.Instance) }); } return(VoidSpec.Instance); } var orig = specExp(fna.Fn, env, AnySpec.Instance); if (orig is FnSpec fnS) { if (fnS.ParameterSpec.Count != fna.Arguments.Count) { throw prog.RemarkList.ParameterArgumentCountMismatch(fna, fnS.ParameterSpec.Count); } var argumentSpecs = new List <Spec>(); var ix = 0; foreach (var aa in fna.Arguments) { var pS = fnS.ParameterSpec[ix]; var aS = specExp(aa, env, pS); argumentSpecs.Add(isAssignable(aS, pS) ? aS : pS); ++ix; } if (fna.Arguments.Count != 0 && fnS.Fn?.SpecEnv != null) { var newFn = new Fn(fnS.Fn.Parameters, fnS.Fn.Sequence, fnS.Fn.SpecEnv).CopyInfoFrom(fnS.Fn); var newFnS = specFn(newFn, null, argumentSpecs); fnS = newFnS; } if (!isAssignable(fnS.ReturnSpec, slot)) { prog.RemarkList.CannotConvertType(fnS.ReturnSpec, slot, fna); } return(fnS.ReturnSpec); } var sigS = new List <Spec>(); foreach (var aa in fna.Arguments) { var aS = specExp(aa, env, AnySpec.Instance); sigS.Add(aS); } sigS.Add(slot == NotSetSpec.Instance ? AnySpec.Instance : slot); var newFnSpec = new FnSpec(sigS, null); if (fna.Fn is Ident fnI2) { env.Set(fnI2, newFnSpec); } return(slot); } case Fn f: return(specFn(f, env)); case When w: var _ = specExp(w.Test, env, BoolSpec.Instance); var thenS = specSequenceItem(w.Then, env, slot); if (w.Otherwise == null) { return(VoidSpec.Instance); } else { var otherwiseS = specSequenceItem(w.Otherwise, env, slot); if (!areSame(thenS, otherwiseS)) { prog.RemarkList.CannotConvertType(thenS, otherwiseS, w.Otherwise); } return(thenS); } case ArrConstructor ae: var s = new ArrSpec(commonType(ae.Arguments, env)); var notSetArgs = ae.Arguments.OfType <Ident>().ToList(); foreach (var a in notSetArgs) { var orig2 = env.Get(a).Value; if (isAssignable(s.ItemSpec, orig2)) { setIdentAndAssignedFrom(env, a, s.ItemSpec); } } return(s); case MemberAccess ma: ss = specExp(ma.Exp, env, NotSetSpec.Instance); var mai = ma.Ident; if (ss is NotSetSpec || ss is AnySpec) { var objSEnv = env.Create(); var objS = new ObjSpec(objSEnv) { FromUsage = true }; var declr = new Var(new Ident(mai.Name, mai.TokenType).CopyInfoFrom(mai, true)); objSEnv.Declare(declr, slot); var __ = specExp(mai, objSEnv, slot); ss = objS; if (ma.Exp is Ident i) { setIdentAndAssignedFrom(env, i, objS); } } var objS2 = ss as ObjSpec; if (objS2 == null) { throw prog.RemarkList.OnlyObjectsCanHaveMembers(ma, ss); } if (objS2.FromUsage) { var member = objS2.Env.GetFromThisEnvOnlyOrNull(mai, null); // also use type and var/let? if (member == null) { var declr = new Var(new Ident(mai.Name, mai.TokenType).CopyInfoFrom(mai, true)); objS2.Env.Declare(declr, slot); var __ = specExp(mai, objS2.Env, slot); } } var objSpec = (ObjSpec)ss; ss = objSpec.Env.GetFromThisEnvOnly(mai, null).Value; return(ss); case New n: var objEnv = env.Create(); foreach (var classItem in n.Body) { specStm(classItem, objEnv); } return(new ObjSpec(objEnv) { Parent = n.Parent }); case Text _: return(TextSpec.Instance); case Bool _: return(BoolSpec.Instance); case Builtin bu: return(bu.FixedSpec); case Char _: return(CharSpec.Instance); case Int _: return(IntSpec.Instance); case Void _: return(VoidSpec.Instance); default: throw new NotSupportedException(); } }
public static ActionSpec GrokAction(ParseState st, int verbIdx) { //UnityEngine.Debug.Log("GrokAction: " + st.ToString() + " with verb at " + verbIdx); var act = new ActionSpec(); string verb = st.words[verbIdx].ToLower(); switch (verb) { case "grab": case "pick_up": act.action = Action.PickUp; break; case "drop": case "set_down": case "put_down": act.action = Action.SetDown; break; case "say": act.action = Action.Say; break; case "put": case "set": case "place": act.action = Action.Put; break; case "close": act.action = Action.Close; break; case "open": act.action = Action.Open; break; case "raise": case "lift": act.action = Action.Raise; break; case "lower": act.action = Action.Lower; break; case "look": case "look_at": act.action = Action.Look; break; case "point": act.action = Action.Point; break; case "stop": act.action = Action.Stop; break; case "thank": case "thank_you": // whoops, this isn't an action, it's a phatic comment. return(null); case "stand_by": act.action = Action.StandBy; break; } // Check for specific action idioms. string verbTree = st.TreeForm(verbIdx); if (verbTree == "VB[is RB[enough]]" && verbIdx > 0 && st.words[verbIdx - 1] == "that") { // that's enough: idiom for "stop" act.action = Action.Stop; } var kids = st.ChildrenOf(verbIdx); if (kids != null) { foreach (int i in kids) { if (st.partOfSpeech[i] == PartOfSpeech.NN) { ObjSpec obj = GrokObject(st, i); act.directObject = obj; if (obj.referredToAs == "hand" && verb == "follow") { // "Follow my hand" idiom act.action = Action.Point; } } if (st.partOfSpeech[i] == PartOfSpeech.WRB) { // e.g.: [VB[point WRB[where]] VB[NN[I] point]] // For now, we'll assume any "where" clause boils down to: act.direction = new DirectionSpec(DirectionSpec.Direction.WhereUserPoints); } if (st.partOfSpeech[i] == PartOfSpeech.RB) { if (st.words[i] == "up" && verb == "pick") { act.action = Action.PickUp; } else if (st.words[i] == "down" && (verb == "put" || verb == "set" || verb == "place")) { act.action = Action.SetDown; } else if (st.words[i] == "here" || st.words[i] == "there" || st.words[i] == "over_here" || st.words[i] == "over_there") { act.location = new LocationSpec() { relation = LocationSpec.Relation.Indicated }; } } } } return(act); }
public static ObjSpec GrokObject(ParseState st, int root) { var obj = new ObjSpec(); obj.referredToAs = st.words[root].ToLower(); // ToDo: we could get better determination of singular/plural, // and get the lemma at the same time, from the SEMCOR corpus. // But for now we'll just hard-code a few. if (EqualsAny(obj.referredToAs, "i", "me", "you", "it", "they", "them")) { obj.specificity = Specificity.Named; } if (EqualsAny(obj.referredToAs, "block", "one", "cube", "thing", "i", "me", "it", "box", "book")) { obj.plurality = Plurality.Singular; } else if (EqualsAny(obj.referredToAs, "blocks", "ones", "cubes", "things", "boxes", "books")) { obj.plurality = Plurality.Plural; obj.referredToAs = obj.referredToAs.Substring(0, obj.referredToAs.Length - 1); } else if (EqualsAny(obj.referredToAs, "they", "them")) { obj.plurality = Plurality.Plural; } var kids = st.ChildrenOf(root); if (kids != null) { foreach (int i in kids) { string pos = st.partOfSpeech[i]; string word = st.words[i].ToLower(); if (pos == PartOfSpeech.DT) { if (EqualsAny(word, "the", "that", "this", "those")) { obj.specificity = Specificity.Specific; } else if (EqualsAny(word, "a", "some", "any")) { obj.specificity = Specificity.Nonspecific; } } else if (pos == PartOfSpeech.JJ) { switch (word) { case "big": case "large": obj.vagueSize = VagueSize.Large; break; case "medium": obj.vagueSize = VagueSize.Medium; break; case "small": case "little": obj.vagueSize = VagueSize.Small; break; case "left": obj.leftRight = LeftRightAxis.Left; break; case "right": obj.leftRight = LeftRightAxis.Right; break; case "your": obj.owner = Owner.You; break; case "my": obj.owner = Owner.Me; break; default: foreach (Color c in System.Enum.GetValues(typeof(Color))) { if (word == c.ToString().ToLower()) { obj.color = c; break; } } break; } } } } return(obj); }