Source code: matrix.pal
From PROSE Programming Language - Wiki
% % 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