# Lesson IX
A stroke begins by knowing where it will appear.
## Try
```prolog
?- empty_env(E),
infer(E, [push(quote([dup, mul])), call], Effect).
Effect = effect([int|S], [int|S]).
?- empty_env(E),
run(E, [push(int(4)), push(quote([dup, mul])), call], [], Stack).
Stack = [int(16)].
```
## Learn
We made the environment an explicit argument everywhere a program can run, infer, or validate a literal. The old arities are changed because an implicit empty context would not scale to user definitions or environment-backed declarations.
> [!info]- Change
> ```diff
> - run([], Stack, Stack).
> - run([Word|Words], Stack0, Stack) :-
> - apply(Word, Stack0, Stack1),
> - run(Words, Stack1, Stack).
> -
> - apply(Word, Stack0, Stack) :-
> - word(Word, InPattern -- OutPattern, Goal),
> - bind(InPattern, Stack0),
> - call(Goal),
> - build(OutPattern, Stack).
> - apply(push(Value), Stack, [Value|Stack]) :-
> - lit(Value, _Type).
> - apply(call, [quote(Words)|Stack0], Stack) :-
> - run(Words, Stack0, Stack).
> -
> - infer([], effect(Stack, Stack)).
> - infer([Word|Words], effect(Stack0, Stack)) :-
> - infer1(Word, Stack0, Stack1),
> - infer(Words, effect(Stack1, Stack)).
> -
> - infer1(push(Value), Stack, [Type|Stack]) :-
> - !,
> - lit(Value, Type).
> - infer1(call, [quote(Effect)|Stack0], Stack) :-
> - !,
> - copy_term(Effect, effect(Stack0, Stack)).
> - infer1(Word, Stack0, Stack) :-
> - word(Word, InPattern -- OutPattern, _Goal),
> - types(InPattern, Stack0),
> - types(OutPattern, Stack).
> -
> - types([Item|Items], [Type|Types]) :-
> - typed(Item, _Payload, Type),
> - !,
> - types(Items, Types).
> -
> - typed(Item, Payload, Type) :-
> - nonvar(Item),
> - Item = (Payload::Type).
> -
> - bind([Item|Patterns], [Value|Values]) :-
> - typed(Item, Payload, Type),
> - !,
> - unpack(Type, Value, Payload),
> - bind(Patterns, Values).
> -
> - build([Item|Patterns], [Value|Values]) :-
> - typed(Item, Payload, Type),
> - !,
> - pack(Type, Payload, Value),
> - build(Patterns, Values).
> -
> - lit(int(Int), int) :-
> - integer(Int).
> - lit(quote(Words), quote(effect(In, Out))) :-
> - infer(Words, effect(In, Out)).
> ```
Runtime sequencing is ordinary stack threading over a word list.
```prolog
run(_, [], Stack, Stack).
run(Env, [Word|Words], Stack0, Stack) :-
apply(Env, Word, Stack0, Stack1),
run(Env, Words, Stack1, Stack).
```
Fixed words project through primitive rows. `push/1` validates a literal and puts it on the runtime stack unchanged.
```prolog
apply(_Env, Word, Stack0, Stack) :-
word(Word, InPattern -- OutPattern, Goal),
bind(InPattern, Stack0),
call(Goal),
build(OutPattern, Stack).
apply(Env, push(Value), Stack, [Value|Stack]) :-
lit(Env, Value, _Type).
apply(Env, call, [quote(Words)|Stack0], Stack) :-
run(Env, Words, Stack0, Stack).
```
Static sequencing publishes an input stack and an output stack. Public inference now returns an `effect/2` term. That term can appear by itself or inside the type of a quotation.
```prolog
infer(_, [], effect(Stack, Stack)).
infer(Env, [Word|Words], effect(Stack0, Stack)) :-
infer1(Env, Word, Stack0, Stack1),
infer(Env, Words, effect(Stack1, Stack)).
```
`push/1` contributes the literal's type to the static stack.
```prolog
infer1(Env, push(Value), Stack, [Type|Stack]) :-
!,
lit(Env, Value, Type).
infer1(_Env, call, [quote(Effect)|Stack0], Stack) :-
!,
copy_term(Effect, effect(Stack0, Stack)).
infer1(_Env, Word, Stack0, Stack) :-
word(Word, InPattern -- OutPattern, _Goal),
types(InPattern, Stack0),
types(OutPattern, Stack).
```
`lit/3` is the only way a literal enters runtime or inference.
```prolog
types([_Payload::Type|Items], [Type|Types]) :-
!,
types(Items, Types).
bind([Payload::Type|Patterns], [Value|Values]) :-
!,
unpack(Type, Value, Payload),
bind(Patterns, Values).
build([Payload::Type|Patterns], [Value|Values]) :-
!,
pack(Type, Payload, Value),
build(Patterns, Values).
```
A quotation is valid when its body has a static stack effect.
```prolog
lit(_Env, int(Int), int) :-
integer(Int).
lit(Env, quote(Words), quote(effect(In, Out))) :-
infer(Env, Words, effect(In, Out)).
```
Declare an empty context.
```prolog
empty_env(env([])).
```
[[08_lesson|Prev]] | [[10_lesson|Next]]