Source code: matrix.pal

From PROSE Programming Language - Wiki
Jump to: navigation, search
%
% Simple test of matrix arrays, where tabular data on standard input is
% reversed, then compared, with only identical cells remaining in output
%
._init
func/def	[main], &[.main]
func/def	[getmtx], &[.func_getmtx], [psMatrix]
func/def	[reverse], &[.func_reverse], [psMatrix], [psMatrixRef], [px],
							 [psInteger], [rows],
							 [psInteger], [cols]
func/def	[mask], &[.func_mask], NULL, [psMatrixRef], [px1],
					     [psMatrixRef], [px2]
func/def	[display], &[.func_display], NULL, [psMatrixRef], [px],
						   [psInteger], [rows],
						   [psInteger], [cols]
local/rtn

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

.main
%
% Read stdin into matrix array via getmtx() function
%
func/call	P0, [getmtx]

%
% Store the array as a local variable by creating an empty array
% and then replacing by the array returned by getmtx()
%
mtx/local	P1, [psByte], [mtx]
attr/mod	P1, [psMatrix], P0

%
% Record size of matrix array in two separate local variables
%
mtx/size	@[P10, P11], P1
var/local	P2, [psInteger], [rows], P10
var/local	P3, [psInteger], [cols], P11

%
% Copy rows and cols as XVALUEs ready for call to reverse()
%
attr/xcopy	P4, P2, [psInteger]
attr/xcopy	P5, P3, [psInteger]

%
% Create a reversed version of the array
%
func/bcall	P6, [reverse], P1, P4, P5

%
% Store the array as a local variable by creating an empty array
% and then replacing by the array returned by reverse()
%
mtx/local	P7, [psByte], [mtx2]
attr/mod	P7, [psMatrix], P6

%
% Walk through the first array, comparing with the second,
% and removing cells that do not match
%
func/bcall	NULL, [mask], P1, P7

%
% Copy rows and cols as XVALUEs ready for call to display()
%
attr/xcopy	P4, P2, [psInteger]
attr/xcopy	P5, P3, [psInteger]

%
% Display the contents of the array via the display() function
%
func/call	NULL, [display], P1, P4, P5
func/rtn

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

.func_getmtx
%
% Copy standard input to string
%
reg/load	P10, ![.prose.sys.io]
attr/load	P11, [psStreamIn]
attr/def	P2, [psInteger], #0

.stdin_loop
attr/copy	P1, P10, P11
reg/jmpeq	&[.stdin_eof], P1, NULL

%
% Strip newline character
%
reg/jmpneq	&[.P2], P2, #0
reg/xscan	P2, P1, [\n]

.P2
%
% Force all lines to have the same number of rows as the first
%
reg/save	P1, (P2)

reg/copy	P0, P0, P1
reg/clr		P1
local/jmp	&[.stdin_loop]

.stdin_eof
%
% Calculate array dimensions
%	P2  - already has correct number of columns
%	P3 - to contain number of rows
%
reg/xload	P3, (P0)
opx/div		P3, P3, P2

%
% Convert string to byte array, copy to XVALUE and return
%
mtx/local	P0, [psByte], [mtx], @[P3, P2], P0
attr/xcopy	P0, P0, [psMatrix]
func/rtn	P0

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

.func_reverse
%
% Read args
%
var/addr	P0, [px], P1, [rows], P2, [cols]

%
% Read array as byte string
%
attr/copy	P3, P0, [psMatrixRef]
obj/addr	PUSH, P3
reg/clr		P3
attr/copy	P3, PULL, [psMatrix]

%
% Reverse the byte string 4 bytes at a time
%
reg/xload	P4, (P3)
reg/copy	P5, []
reg/save	P5, (P4)

.reverse_loop
reg/cmp		P4, #4
reg/jmpeq	&[.reverse_end], SCMP, #2

opx/sub		P4, P4, #4
reg/load	P6, (P3, A)
op/swap		P6, P6, #0x4321
reg/save	P5, (P6, P4)
opa/add		#4
local/jmp	&[.reverse_loop]

.reverse_end
%
% Store last 1, 2 or 3 bytes
%
reg/jmpeq	&[.reverse_rtn], P4, #0
reg/load	P6, (P3, A)
op/swap		P6, P6, #0x4321
op/mask		A, P4
opa/not
reg/load	P7, (P5, #0)
opa/and		P7
op/sub		P8, #4, P4
op/mult		P8, P8, #8
op/shl		P6, P6, P8
opa/or		P6
reg/save	P5, (A, #0)

.reverse_rtn
%
% Convert string to byte array, copy to XVALUE and return
%
attr/index	P1, P1, [psInteger]
attr/index	P2, P2, [psInteger]
mtx/local	P5, [psByte], [mtxrev], @[P1, P2], P5
attr/xcopy	P5, P5, [psMatrix]
reg/clr		P3
func/rtn	P5

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

.func_mask
%
% Read args
%
var/addr	P0, [px1], P1, [px2]
attr/load	P2, [psMatrixVal]

%
% We'll loop through the array until we get an OutOfBounds error
%
error/jmp	&[.mask_end], ![.prose.error.sys.OutOfBounds]

%
% Loop through arrays px1 and px2 comparing cells
%
.mask_loop
attr/cmp	P0, P2, P1, P2
reg/jmpeq	&[.mask_next], SCMP, #1

%
% Cells don't match, replace cell in px1 with '.'
%
attr/mod	P0, P2, [.]

.mask_next
%
% Continue until OutOfBounds
%
op/incr		P0, P1
local/jmp	&[.mask_loop]

.mask_end
error/clr
func/rtn

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

.func_display
%
% Read args
%
var/addr	P0, [px], P1, [rows], P2, [cols]

%
% Set-up local reference variables
%
reg/load	P10, ![.prose.sys.io]
attr/load	P11, [psStreamOut], P12, [psMatrixVal], P13, [psInteger]

%
% Set-up local counter variables
%
var/local	P3, P13, [R], #0
var/local	P4, P13, [C], #0

%
% Scan array cell-by-cell
%
.tab_loop
attr/direct	P10, P11, P0, P12

%
% Increment column number
%
op/incr		P4
obj/cmp		P4, P2, P13
reg/jmpneq	&[.tab_next], SCMP, #2

%
% Advance matrix pointer
%
op/incr		P0
local/jmp	&[.tab_loop]

.tab_next
attr/mod	P10, P11, [\n]

%
% Increment row number
%
op/incr		P3
obj/cmp		P3, P1, P13
reg/jmpneq	&[.tab_end], SCMP, #2

%
% Reset column number
%
attr/mod	P4, P13, #0

%
% Advance matrix pointer
%
op/incr		P0
local/jmp	&[.tab_loop]

.tab_end
func/rtn