diff options
Diffstat (limited to 'starts')
-rw-r--r-- | starts/meaning-vm/level-2/habits.cpp | 140 | ||||
-rw-r--r-- | starts/meaning-vm/level2.cpp | 268 |
2 files changed, 367 insertions, 41 deletions
diff --git a/starts/meaning-vm/level-2/habits.cpp b/starts/meaning-vm/level-2/habits.cpp index 49a48a3..c58cc74 100644 --- a/starts/meaning-vm/level-2/habits.cpp +++ b/starts/meaning-vm/level-2/habits.cpp @@ -35,16 +35,49 @@ void poplinkentry(ref le) } } -ref maketranslationmap(ref m, ref k = nothing) +// translationmap seems like extra verbose thing +// might just link to step: +// needed-map +// needed-set +// made-map +ref settranslationmap(ref c, ref m, ref k = nothing) { - ref result = makeconcept(); - result.link( + c.link( //habit, translation-map, "translation", m ); - if (k != nothing) { result.link("known", k); } - return result; + if (k != nothing) { c.link("known", k); } + return c; } +// we would like to use condition kind of like +// condition.next-step[true] = +// but provide for lots of exploration options +// next-steps, on a condition, would be an accessor. relates to structures, and virtual methods. +// until we have one of those 3 things, i guess, +// we'd have to decide which underlying representation to work with. +// i guess it seems okay to use a simpler underlying representation. +// it means adding more data is a little weird, making for more verbose accessors later +// there's a compromise where a little generality is added at a lower level +// it is easier for ai to do verbosity than karl. it can automate it. +// just code an accessor for next-steps, I guess. +// what do we want this for? +// want code after condition in script +// to link to anything option +// is just hard to access anything option +// off-hand, karl doesn't know where it is. +// concern around what to do if anything option is specified in script +// throw error if also code after +// maybe it is more intuitive to continue on after the condition. +// this would make condition resolve to a step, kind of. +// after the condition block, you'd want all the condition steps +// to wire to the following step as their next one +// means rewriting next-step for every condition, i guess +// instantiating next step in advance +// makes returning instead of continuing irritating +// would need to either rewire or have a noop step +// so, to mke choice, just rewrite for every condition +// means accessing every condition. no need to rewrite whole structure, just look up how to access. faster than rewriting. +// make a function to wire to end void contextmapinto(ref c1, ref m, ref c2) { @@ -143,9 +176,9 @@ void _condition(ref ctx, ref cond, ref steps, ref state) next = steps[cond]; } - if (next != nothing) { + //if (next != nothing) { state.set("next-step", next); - } + //} } void createhabits() @@ -209,22 +242,27 @@ void createhabits() decls(make, unmake, know, concept, is, group, already, in, iter); ahabit(make-concept, (), { result = makeconcept(); }); - ahabit(make-copy, ((concept, c)), + ahabit(copy-to, ((source, s), (target, t)), { // copies data too - result = makeconcept(); - result.replace(c); + if (t.hasval() || t.p->links.size() != 0) { throw makeconcept().link(is, "concept-not-empty", concept, t); } + result = t; + t.replace(s); }); ahabit(copy-data-to, ((source, s), (target, t)), { + if (t.hasval()) { throw makeconcept().link(is, "concept-has-data", concept, t); } t.ptr()->data = s.ptr()->data; }); + // if last-context is weird give it a default of nothing ahabit(concept-unmake, ((last-context, c), (concept-name, n)), { ref r = c.get(n); c.unlink(n); conceptunmake(r); }); + // if a concept or link is set crucial deleting it will be denied. no way + // to remove crucial mark is provided. nothing is marked crucial yet. ahabit(concept-crucial, ((concept, c)), { result = c.crucial(); @@ -235,7 +273,7 @@ void createhabits() }); decls(habit, context); - ahabit(know-is, ((concept, c), (group, g)), + ahabit(set-is, ((concept, c), (group, g)), { if (c.linked(is, group)) { throw (make-concept)().link @@ -252,28 +290,25 @@ void createhabits() // a way to iterate or inspect the links of a concept decl(entry); - ahabit(make-first-link-entry, ((concept, c)), - { - // left over from when allocation was handled by separate function, which - // I'd like to return to - //if (le.hasval()) { throw makeconcept().link( - // is, "already-has-value", - // concept, le, - // context, ctx); } - ref le = makeconcept(); + ahabit(first-link-entry, ((target, le), (concept, c)), + { + if (le.hasval()) { throw makeconcept().link( + is, "already-has-value", + concept, le, + context, ctx); } + //ref le = makeconcept(); le.link(is, link-entry); le.val<links_it>(c.links().begin()); le.set(source, c); poplinkentry(le); result = le; }); - ahabit(make-last-link-entry, ((concept, c)), + ahabit(last-link-entry, ((target, le), (concept, c)), { - //if (le.hasval()) { throw makeconcept().link( - // is, "already-has-value", - // concept, le, - // context, ctx); } - ref le = makeconcept(); + if (le.hasval()) { throw makeconcept().link( + is, "already-has-value", + concept, le, + context, ctx); } le.link(is, link-entry); le.val<links_it>(--c.links().end()); le.set(source, c); @@ -296,6 +331,12 @@ void createhabits() { return lea.val<links_it>() == leb.val<links_it>(); }); + ahabit(link-entry-insert-before, ((link-entry, le), (target, t)), + { + // todo: make clean + auto & it = le.val<links_it>(); + le.get(source).ptr()->links.emplace_hint(it.underlying(), le.get(type), t); + }) ahabit(link-entry-unlink, ((link-entry, le)), { le.get(source).unlink(le.val<links_it>()++); @@ -477,9 +518,10 @@ void createhabits() }) */ decls(needed, made, known, information, translation); - ahabit(make-translation-map, ((translation-map, m), (known-map, k, nothing)), + ahabit(set-translation-map, ((target, c), (translation-map, m), (known-map, k, nothing)), { - result = maketranslationmap(m, k); + if (c.isa("translation-map") || c.linked("translation") || c.linked("known")) { throw makeconcept().link(is, "already-has-translation-map-data", concept, c, context, ctx); } + result = settranslationmap(c, m, k); }); ahabit(context-map-into, ((source-context, c1), (translation-map, m), (target-context, c2)), { @@ -501,11 +543,30 @@ void createhabits() result = outer; }); */ + /* + ahabit(link-next-step, ((step, s), (next-step, ns)), + { + if (ns != nothing) { + if (s.isa("context-step")) { + if (s.linked(next-step)) { throw makeconcept().link(is, "previous-step-already-has-next-step", step, s, context, ctx); } + } else if (s.isa("condition-step")) { + // think about more. + // implementing this here immediately means walking through every step of every branch of the condition. + // one approach would be to do this elsewhere. to label the steps when the condition is made, add them to a set, and wire them. + // let the caller do step wiring. + // seems fastest, haven't reviewed relevency fully. + } else { + throw makeconcept().link(is, "unexpected-previous-step-type", step, s, context, ctx); + } + } + }); + */ decls(step, previous); - ahabit(make-context-step, ((previous-step, ps), (known-information, literals), (needed-information-map, in), (made-information-map, out), (action, act)), + ahabit(set-context-step, ((target, t), (previous-step, ps, nothing), (known-information, literals), (needed-information-map, in), (made-information-map, out), (action, act)), { + if (t.linked(needed-map) || t.linked(made-map) || t.linked(action)) { throw makeconcept().link(is, "concept-links-collide", concept, t, context, ctx); } if (ps != nothing && ps.linked(next-step)) { throw makeconcept().link(is, "previous-step-already-has-next-step", previous-step, ps, context, ctx); } - result = intellect::level1::a("context-step"); + result = intellect::level1::a("context-step", t); result.link( //habit, context-action, needed-map, maketranslationmap(in, literals), @@ -515,10 +576,15 @@ void createhabits() }); decls(order, steps); - // make steps doesn't allow for name, and isn't used in level2.cpp <==== - ahabit(make-steps, ((existing-concept, nam, nothing), (information-order, io, nothing)), + ahabit(set-steps, ((target, t), (information-order, io, nothing)), { - result = (nam == nothing) ? makeconcept() : nam; + if (t.linked(information-needed) || t.linked(next-step)) { + throw makeconcept().link(is, "concept-links-collide", + concept, t, + context, ctx); + } + result = t; + a(steps, t); ref infn = intellect::level1::a(habit-information-needed); result.set(information-needed, infn); ref posinf = infn; @@ -547,17 +613,19 @@ void createhabits() }); decls(condition); // steps must be actual steps, not a list of steps - ahabit(make-condition-step, ((previous-step, ps), (condition, cond), (steps, s, nothing)), + ahabit(set-condition-step, ((target, t), (previous-step, ps, nothing), (condition, cond), (next-steps, s, nothing)), { + if (t.linked(needed-map) || t.linked(made-map) || t.linked(action)) { throw makeconcept().link(is, "concept-links-collide", concept, t, context, ctx); } if (ps != nothing && ps.linked(next-step)) { throw makeconcept().link(is, "previous-step-already-has-next-step", previous-step, ps, context, ctx); } if (s == nothing) { s = makeconcept(); } - result = intellect::level1::a("condition-step").link( + result = t; + intellect::level1::a("condition-step", t).link( needed-map, maketranslationmap(makeconcept().link(condition, cond), makeconcept().link(next-steps, s)), action, condition ); if (ps != nothing) { ps.set(next-step, result); } }); - ahabit(condition-action-add, ((condition-action, ca), (value, v), (step, s)), + ahabit(condition-step-add, ((condition-step, ca), (value, v), (step, s)), { ca.get(needed-map).get(known).get(next-steps).set(v, s); }); diff --git a/starts/meaning-vm/level2.cpp b/starts/meaning-vm/level2.cpp index 990ea45..ac4828e 100644 --- a/starts/meaning-vm/level2.cpp +++ b/starts/meaning-vm/level2.cpp @@ -151,6 +151,110 @@ ref makestep(ref last, ref action, std::initializer_list<char const *> resultand // like closest friend, want to be friends for real, and tell both of our real // stories. + + + + + + + + + + + + +using namespace std; +void parse(string script) +{ + stringstream ss(script); + ss >> cmd; + if (cmd == "when") { + ref args = makeconcept(); + string name; + ss >> name; + while (true) { + string arg; + ss >> arg; + if (arg == "[") { break; } + args.link("information-order", arg); + } + ref result = (set-steps)(name, args); + ref laststep = result; + map<string,ref> labels; + labels["return"] = nothing; + // when dump group [ + // = is-in-set in-set group + // ? is-in-set if true go return. + // period-at-end: goto. + // comma-or-colon-at-end: label + // output-name group + // output-name ":" // quotes mean always-global + // ] + // + // proposing expression-based now. + // haven't resolved inherited name-contexts with literal strings fully. + // working on conditions. + // propose if tracks last step + // when if ends, adds last step to condition's set of last steps + // then next step after condition can wire to all steps in the set. + // can use 1-element set for normal steps. + // change step-creation to not automatically wire. + // and reconsider condition-step to not use its next-step attribute. + // instead its conditions decide what the next step is. + // looks good for conditions. fix names and update whole thing. + while (true) { + string label, action, result; + ss >> action; + if (action == "]") { break; } + if (action[action.size()-1] == ':' || action[action.size()-1] == ',') { + label = action; + label.resize(label.size() - 1); + if (label == "return") { throw makeconcept.link(is, "return-label-used"); } + ss >> action; + } + if (action == "=" || action == "set") { ss >> result; ss >> action; } + if (action[action.size()-1] == '.') { + // is goto + action.resize(action.size() - 1); + if (!labels.count(action)) { + labels.emplace(action, makeconcept()); + } + labels[action].link("label", action); + if (laststep.linked("next-step")) { throw makeconcept().link(is, "jump-from-nowhere", "label", action); } + laststep.link("next-step", labels[action]); + continue; + } + ref nextstep = label.size() ? labels[label] : makeconcept(); + if (action == "if") { + ref cond; + ss >> cond; + ss >> action; + if (action[action.size()-1] != '-') { + throw makeconcept().link(is, "condition-is-not-label", "action", action); + } + action.resize(action.size()-1); + if (!labels.count(action)) { + labels.emplace(action, makeconcept()); + } + (condition-step-add)(laststep, cond, labels[action]); + } + if (action == "?" || action == "pick") { + string cond; + ss >> cond; + laststep = (set-condition-step)(nextstep, laststep, cond, makeconcept().link("anything", "nothing")); + // todo: make a noop for 'anything' and use it in following actions + // todo: handle if + } else { + // otherwise, action is an action, and we have to read the right number o args + // if last-step is condition, connect to 'anything' + // oooogh + } + } + } else { + throw ref("parse-error").link("script", script, "unexpected-word", cmd); + } +} + int main() { createhabits(); @@ -198,8 +302,10 @@ int main() }); // dump changes to expand from a different node + // propose we make script interpreter. much faster in longer term. + // I guess I'd better code dump as a behavior. - begin(dump, concept); + begin(dump, set); // change the verbose dump habit to use responsibility-of-interest. // hey ask the opencoggers if they have a syntax sugar library // they must if they built a whole robot // no reply on opencog chat. could check hansen robotics repo or ml. @@ -247,10 +353,162 @@ int main() end(dump); ref memoryfile("memory-000.txt"); - decl(memory-000.txt) - decls(responsiblefor, responsibility, of, interest); + decls(responsiblefor, responsibility, interest); link(responsibility-of-interest, responsiblefor, dump); - for (ref a = dump; a. + for (ref a = dump; a.linked("next-step"); a = a.get("next-step")) { + (responsibility-of-interest).link(responsiblefor, dump); + } + // structure of steps + // [action] [parameter->value ...] repeat + // [active memory too small to resolve concern around shape of literals in context] + // make value quoted, like it already is. + // [parameter->`value] + // + // steps written can just be + // action value value value + // + // a definition of a list of steps + // internal structure (ternary nodes) + // (name arg->arg1 arg->arg2 arg->arg3) + // ohhhhh hmm + // so, if it isn't simplified, there's room for adding more information to stuff. like, arg-must-be-animal + // probably wnt arg1 replaceable with [is->arg name->arg1] + // can make a norm for general expandable structures + // value-> + // will need strucure definitions to do it really usefully though + // is->arg + // arg-> + // we want to tag it with additional stuff, optionally + // written structure + // steps name arg1 arg2 arg3 arg4 + // { + // label: action arg1 arg2 arg3 + // action arg1 arg2 arg3 + // } + // + // hmm + // + // let's try to make it c code, how about? until we can summarize better? + // + // walk-to street + // + // this is faster to implement. doesn't matter how it looks. + // + // when walk-to destination [ + // START: intermediary = get-middle origin destination + // // each step could also be a condition that branches to other steps + // pick intermediary [ + // school [ START ] + // desk [ + // stand-up + // leave-room + // ] + // ] + // ] + // it might make sense to use yaml or something + // is easier. rmember to implement comments. maybe #[ name free-text ] , dunno + // what we want is links. [ name type target type target ] seems good. + // [ ] might open a context with local names, eventually + // + // when dump concept [ + // = found-in-set in-set concept + // ? found-in-set true return <-- return is label at end + // write-name concept + // write-name ':' + // write-endl + // put-in-set concept + // link-entry = make-first-link-entry concept + // while-1: + // has-target = linked link-entry 'target' // propose '' can force something to be global. is also for clarity. + // has-target if false break-1 + // write-name ' ' + // link-type = get link-entry 'type' + // write-name link-type + // // we could expand to write-name [ get link-entry 'type' ] + // // but just get it working for now + // write-name ': ' + // link-target = get link-entry 'target' + // write-name link-target + // write-endl + // next-link-entry link-entry + // while-1 + // break-1: + // concept-unmake context 'link-entry' + // link-entry = make-first-link-entry concept + // while-2: + // has-target = linked link-entry 'target' + // has-target if false break-2 + // link-target = get link-entry 'target' + // self link-target + // next-link-entry link-entry + // while-2 + // break-2: + // concept-unmake context 'link-entry' + // ] + // + // norm: next-step always, unless action is label. then next-step is label. + // unresolved concern: want to write habits to do parsing + // auxiliary files, can propose to rewrite main file? + // good enough for now. + // additional unresolved concern: want whole file parseable as a script + // okay the outer command is 'when dump concept [ ... ]' + // i guess that means we want [] to make a lot of symbols into 1 symbol. + // then when is a function that takes 3 symbols + // no, when was defined differently. + // instead we would do when dump [ concept ] [ ... ] + // because could be n args + // oh. that looks okay, though. + // how about file is made of commands that do parsing. + // 'when' then spawns a parser named 'when'. it can process stream however + // it desires. + // then deserializers, desummarizers need to parse streams + // want summarized data without streams, internally? + // ummm wouldn't worry about it + // propose file is made of lists of symbols, a little + // [ when dump concept [ ... ] ] [ etc ] + // [when dump concept [...]] [etc] + // generalization is valued ... + // i like the list approach. + // comments can be treated special + // nah comments can become [comment free-text] + // so we partly propose implementing lisp with brackets + // to speed typing , removes shift key + // functions get list of symbols passed, and string rep of all for comment preservation + // + // binary form likely resolves concern. + // proposal will be that habit can replace if it will always be able to + // reproduce. + // ] + // + // internal structure could be simple too. + // hmm want tags. okay, so arguments are objects? + // since things are ternary, we could use the link 'type' to store data + // oh huh + // so, 'first-step' is special, but everything else is an arg. + // no, this is what karl's 'is' is for. you make the type store extra data, but if it 'is' an arg, + // or 'is' something that is an arg, it counts as an arg. + // he wanted to implement a way to lookup types by eveyrthing something is, which is easy to do by + // adding an index of categories to level-0. + // or the system could do it later. + // + // so, if oyu want to rewrite steplists, maybe [arg->arg1 arg->arg2 arg->arg3 first->[action->action arg1->source arg2->source arg3->`source] + // propose using strings to indicate information, rather than node structure. + // this will make a contextual index of word meaning + // `source doesn't refer to a unique concept. it means you can only refer to things with names. + // everything has a name inside this kind of habit. + // i suppose ... + // + // how scripts look. instead of while/if, are doing 'condition' + // influences imply above block is preferred. was leaning towards c++ code as below, takes longer + // + // ref name(ref arg1, ref arg2, ref arg3) + // { + // while() {} + // if() {} + // } + // + // takes a lot more parsing work, but should be okay + // /* // for dump, we make a list of contextual actions ahabit(dump, ((concept, c)), @@ -277,7 +535,7 @@ int main() // for some reason it's only running the second loop // nothing is output on the first std::cerr << intellect::level1::dump(dump, makeconcept()) << std::endl; - dump(dump); + dump(responsibility-of-interest); } catch(intellect::level1::ref r) { std::cerr << intellect::level1::ref(r.ptr()).dump(makeconcept()) << std::endl; throw; |