XXIIVV

Uxntal State

The ability to treat instructions as data makes programs that write programs possible. Self-modifying code(SMC) is generally considered harmful, and is therefore not permitted in most modern computer architectures today.

Action at a distance is an anti-pattern in computer science in which behavior in one part of a program modifies operations in another part of the program. This anti-pattern should be avoided whenever possible, but if wielded carefully SMC can become a practical ally when writing Uxntal.

Caching

In most cases, SMC is used to cache data that would otherwise be difficult or slow to retrieve, like when writing a responsive application that would make frequent requests to a device.

In the following example, we are comparing the state of the mouse device between vector events, we could store the previous state in a zero-page variable, but keeping the value locally allows to reserve a byte from within the context where it is needed, and is faster by being inlined.

@on-mouse ( -> )

	[ LIT &last $1 ] .Mouse/state DEI 
		DUP ,&last STR
		EORk ?&changed 
	POP2

BRK

Callbacks

To chain operations across vectors, one might try passing the next operation pointer on the stack, but since we cannot be certain which vector will happen next, we can't expect a specific stack state between events. A safer way is to write the next operation directly in memory where it will be needed, ideally preserving the label scope.

@set-animation ( callback* -- )

	,&callback STR2
	;&run .Screen/vector DEO2

JMP2r

&run ( -> )

	[ LIT &time f0 ] 
		INCk ,&time STR
		#00 EQU ?&done
	try-redraw

BRK

&done ( -> )

	[ LIT2 &callback $2 ] JSR2

BRK

Depth Punching

Routines should try and avoid accessing stack values that are further than 2 or 3 shorts deep on either stacks, but sometimes it cannot be helped. In the following example, we want to run a function over each value of a 2d array. Instead of juggling the stacks on each iteration to bring out the function pointer, it is often more efficient to write the function pointer across the nested loop.

@each-pixel ( fn* -- )

	,&fn STR2
	#1000
	&h
		STHk
		#2000
		&x
			DUP STHkr [ LIT2 &fn $2 ] JSR2
			INC GTHk ?&x
		POP2
		POPr
		INC GTHk ?&h
	POP2

JMP2r

incoming uxntal memory uxntal devices