func (d *Dwimmer) Answer(q term.T, optionalSetting ...*term.SettingT) (term.T, term.T) { var s *term.SettingT if len(optionalSetting) == 1 { s = optionalSetting[0] } else { s = term.InitT() s.AppendTerm(BuiltinAnswerer.T(q)) } a := dynamics.SubRun(d, q, s) switch a.Head() { case core.Answer: return a.Values()[0], nil case core.Yes, core.No: return a, nil } follow := term.InitT() isAnswer := dynamics.SubRun(d, IsAnswer.T(a, q), s, follow) for { switch isAnswer.Head() { case core.Yes: result, err := d.Answer(WhatAnswer.T(a, q)) if err != nil { return nil, a } return result, nil case core.No: return nil, a } isAnswer = dynamics.SubRun(d, IsAnswerClarify.T(), s, follow) } }
func RunDefaultInitializers(d dynamics.Dwimmer) { s := term.InitT() s.AppendTerm(Initialization.T()) for _, t := range dynamics.DefaultInitializers { c := term.InitT() dynamics.SubRun(d, t, s, c) } }
func StartShell(d dynamics.Dwimmer, ts ...term.T) term.T { pushShell() defer popShell() for _, t := range ts { shellSetting.AppendTerm(t) } for { transition := ElicitAction(d, term.InitT(), shellSetting.Setting) result := transition.Step(d, shellSetting) if result != nil { return result } } }
func (d *Dwimmer) watchdog(setting *term.SettingT) { if rand.Int()%(watchFrequency<<(3*watcherDepth)) == 0 { watcherDepth++ defer func() { watcherDepth-- }() parent := setting.Copy().AppendAction(term.MetaC()) oldWatcher := d.lastWatcher newWatcher := term.InitT() var Q term.T if d.lastWatcher == nil { Q = IsAllWell.T(term.MakeChannel(parent)) } else { Q = IsAllWellPred.T(term.MakeChannel(parent), term.MakeChannel(oldWatcher)) } d.lastWatcher = newWatcher dynamics.SubRun(d, Q, parent, newWatcher) } }
func SubRun(d Dwimmer, Q term.T, parent *term.SettingT, optionalChild ...*term.SettingT) term.T { var child *term.SettingT if len(optionalChild) == 1 { child = optionalChild[0] } else { child = term.InitT() } child.AppendTerm(Parent(parent)) child.AppendTerm(Q) d.Push(Q) stackCheck() A := d.Run(child) parent.AppendTerm(OpenChannel.T(term.MakeChannel(child))) if A != nil { parent.AppendTerm(A) } d.Pop() return A }
func TestRepresentations(t *testing.T) { d := dwimmer.TestDwimmer() defer d.Close() template := term.Make("term with argument [] and second half here") template2, err := represent.ToTemplate(d, represent.Template(template)) if err != nil { t.Errorf("received error %v", err) } if template != template2 { t.Errorf("%v != %v", template, template2) } setting := term.Init().Append(template) setting2, err := represent.ToSetting(d, represent.Setting(setting)) if err != nil { t.Errorf("received error %v", err) } if term.IDSetting(setting) != term.IDSetting(setting2) { t.Errorf("%v != %v", setting, setting2) } actions := []term.ActionC{term.ReturnC(term.Cr(3)), term.ClarifyC(term.Cr(2), core.OK.C()), term.DeleteC(7)} for _, action := range actions { action2, err := represent.ToActionC(d, represent.ActionC(action)) if err != nil { t.Errorf("received error %v", err) } if term.IDActionC(action) != term.IDActionC(action2) { t.Errorf("%v != %v", action, action2) } } stub := term.Make("stub") tm := template.T(stub.T()) tm2, err := represent.ToT(d, represent.T(tm)) if err != nil { t.Errorf("received error %v", err) } if tm2.String() != tm.String() { t.Errorf("%v != %v", tm2, tm) } rep, err := d.Answer(represent.Explicit.T(represent.T(tm))) if err != nil { t.Errorf("failed to make representation explicit: %v", err) } tm3, err := represent.ToT(d, rep) if err != nil { t.Errorf("received error %v", err) } if tm3.String() != tm.String() { t.Errorf("%v != %v", tm3, tm) } settingT := term.InitT().AppendTerm(tm) settingT2, err := represent.ToSettingT(d, represent.SettingT(settingT)) if err != nil { t.Errorf("received error %v") } if settingT2.Setting.ID != settingT.Setting.ID { t.Errorf("%v != %v", settingT2, settingT) } n := -127 n2, err := represent.ToInt(d, represent.Int(n)) if err != nil { t.Errorf("received error %v", err) } if n != n2 { t.Errorf("%v != %v", n, n2) } s := "hello ₳" s2, err := represent.ToStr(d, represent.Str(s)) if err != nil { t.Errorf("received error %v", err) } if s != s2 { t.Errorf("%s != %s", s, s2) } }
func (d *Dwimmer) Do(a term.ActionT, s *term.SettingT) term.T { switch a.Act { case term.Return: return a.Args[0] case term.Ask: Q := a.Args[0] child := term.InitT() dynamics.SubRun(d, Q, s, child) return nil case term.View: value := a.Args[0] if value != nil { s.AppendTerm(value) } else { s.AppendTerm(Closed.T()) } return nil case term.Replace: //value := a.Args[0] //n := a.IntArgs[0] //s.Rollback(n).AppendTerm(value) return nil case term.Replay: n := a.IntArgs[0] s.Rollback(n) return nil case term.Clarify: Q := a.Args[1] //TODO handle null pointers much better... //(e.g. one part of an expression may refer to a deleted variable) if a.Args[0] == nil { s.AppendTerm(Closed.T()) return nil } var target *term.SettingT channel, err := represent.ToChannel(d, a.Args[0]) if err == nil { target = channel.(term.Channel).Instantiate() } else { var othererr term.T target, othererr = represent.ToSettingT(d, a.Args[0]) if othererr != nil { s.AppendTerm(NotAChannel.T(err)) return nil } } dynamics.SubRun(d, Q, s, target) return nil case term.Correct: n := a.IntArgs[0] old := s.Setting.Rollback(n) transition := ElicitAction(d, term.InitT(), old) d.Save(old, transition) s.AppendTerm(core.OK.T()) return nil case term.Delete: n := a.IntArgs[0] s.Args[n] = nil s.AppendTerm(core.OK.T()) return nil case term.Meta: s.AppendTerm(CurrentSetting.T(represent.SettingT(s))) return nil } panic("unknown kind of action") }
func (d *Dwimmer) Ask(Q term.T) (term.T, *term.SettingT) { setting := term.InitT().AppendTerm(Q) return d.Run(setting), setting }
package dwimmer import ( "github.com/paulfchristiano/dwimmer/dynamics" "github.com/paulfchristiano/dwimmer/term" ) var ( RunShell = term.Make("run a shell with prompt [], and reply with the user's return value") shellSetting = term.InitT().AppendTerm(term.Make("[Home]").T()) oldShells []*term.SettingT ) func startWithPrompt(d dynamics.Dwimmer, setting *term.SettingT, question term.T) term.T { return StartShell(d, dynamics.Parent(setting), question) } func pushShell() { oldShells = append(oldShells, shellSetting.Copy()) } func popShell() { shellSetting = oldShells[len(oldShells)-1] oldShells = oldShells[:len(oldShells)-1] } func Show(t term.T) { shellSetting.AppendTerm(t) } func StartShell(d dynamics.Dwimmer, ts ...term.T) term.T {