# Lesson X The name does not move the brush. It keeps the hand from wandering. ## Try ```prolog % ?- infer(kernel, [push(quote([dup, mul])), call], Effect). % Effect = effect([int|S], [int|S]). % ?- run(kernel, [push(int(4)), push(quote([dup, mul])), call], [], Stack). % Stack = [int(16)]. ``` ## Lesson ```prolog % Primitive rows are the single source for fixed words. They describe % stack shape and runtime computation for words whose meaning does not % depend on a literal argument. % The base environment is the atom `kernel`. % Primitive words are explicit environment-indexed clauses. The % environment argument is what makes the kernel a lookup context % instead of a generated list of rows. word(kernel, dup, [A|S] -- [A, A|S], true). word(kernel, drop, [_|S] -- S, true). word(kernel, swap, [A, B|S] -- [B, A|S], true). word(kernel, over, [A, B|S] -- [B, A, B|S], true). word(kernel, add, [A::int, B::int|S] -- [C::int|S], C is B + A). word(kernel, sub, [A::int, B::int|S] -- [C::int|S], C is B - A). word(kernel, mul, [A::int, B::int|S] -- [C::int|S], C is B * A). % Find searches the current context for a word clause, then copies the % stored row so variables in primitive effects stay fresh for each % use. find(Env0, Word, InOut, Goal) :- nonvar(Env0), word(Env0, Word, StoredInOut, StoredGoal), copy_term(word(Word, StoredInOut, StoredGoal), word(Word, InOut, Goal)). % Fixed words project through primitive rows. apply(Env, Word, Stack0, Stack) :- find(Env, Word, InPattern -- OutPattern, Goal), bind(InPattern, Stack0), call(Goal), build(OutPattern, Stack). infer1(Env, Word, Stack0, Stack) :- find(Env, Word, InPattern -- OutPattern, _Goal), types(InPattern, Stack0), types(OutPattern, Stack). ```