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 (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 ElicitAction(d dynamics.Dwimmer, context *term.SettingT, setting *term.Setting) dynamics.Transition { for { Q := FallThrough.T(represent.Setting(setting)) result := dynamics.SubRun(d, Q, context) switch result.Head() { case TakeTransition: transition, err := represent.ToTransition(d, result.Values()[0]) if err == nil { return transition } case core.OK: default: result, err := d.Answer(TransitionGiven.T(result, Q)) if err == nil { transition, err := represent.ToTransition(d, result) if err == nil { return transition } } } } }
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") }