Source code: students.pal
From PROSE Programming Language - Wiki
%
% Simple test of data entry via stdin which creates a hierarchy using
% classroom subjects and student names
%
._init
func/def [main], &[.main]
func/def [getsubjects], &[.func_subjects]
func/def [getstudents], &[.func_students]
func/def [getgrades], &[.func_grades]
func/def [display], &[.func_display]
%
% Create top-level containers for the data
%
reg/load PCTX, ![.prose]
obj/def P0
class/add P0, [psContainer]
obj/clone P1, P0, P2, P0
obj/commit [school], P0
reg/load P0, ![school]
obj/commit P0, [subjects], P1
obj/commit P0, [students], P2
local/rtn
.main
func/call NULL, [getsubjects]
func/call NULL, [getstudents]
func/call NULL, [display]
func/rtn
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
.func_subjects
%
% Preparation
%
reg/load PCTX, ![.prose.school.subjects], P9, ![.prose.sys.io]
attr/load P10, [psStreamIn], P11, [psStreamOut], P13, [description]
class/load P12, [psContainer]
%
% Obtain number of subjects from user
%
reg/load P0, [# of subjects \[1-10\]? ], P1, #1, P2, #10
local/jsr &[.getnumber]
reg/load A, #1, P1, P0
op/incr P1
.sbloop
%
% Get each subject name
%
reg/copy P0, [Name of subject #], A, [? ]
attr/mod P9, P11, P0
attr/copy P0, P9, P10
%
% Get rid of newline character at end of input
%
local/jsr &[.stripnl]
%
% Make sure there are no dots in the name (keep copy of original)
%
reg/copy P3, P0
local/jsr &[.stripdots]
%
% Create a container for this subject
%
obj/def P7
class/add P7, P12
attr/add P7, P13, P3
obj/commit P0, P7
reg/clr P0
op/incr
reg/jmpneq &[.sbloop], A, P1
%
% Set flag for getgrades() function to indicate that we are obtaining
% grades for the classroom subjects
%
attr/add ![.prose.school], [description], [0]
func/call NULL, [getgrades]
func/rtn
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
.func_students
%
% Preparation
%
reg/load PCTX, ![.prose.school.students], P9, ![.prose.sys.io]
attr/load P10, [psStreamIn], P11, [psStreamOut], P13, [description]
class/load P12, [psContainer]
%
% Obtain number of students
%
reg/load P0, [# of students \[1-20\]? ], P1, #1, P2, #20
local/jsr &[.getnumber]
reg/load A, #1, P1, P0
op/incr P1
.stloop
%
% Get each student name
%
reg/copy P0, [Name of student #], A, [? ]
attr/mod P9, P11, P0
attr/copy P0, P9, P10
%
% Get rid of newline character at end of input
%
local/jsr &[.stripnl]
%
% Make sure there are no dots in the name (keep copy of original)
%
reg/copy P3, P0
local/jsr &[.stripdots]
%
% Create a container for this student
%
obj/def P7
class/add P7, P12
attr/add P7, P13, P3
obj/commit P0, P7
reg/clr P0
op/incr
reg/jmpneq &[.stloop], A, P1
%
% Set flag for getgrades() function to indicate that we are obtaining
% grades for the classroom subjects
%
attr/mod ![.prose.school], [description], [1]
func/call NULL, [getgrades]
func/rtn
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
.func_grades
%
% Preparation
%
reg/load PCTX, ![.prose.school], P9, ![.prose.sys.io]
attr/load P10, [psStreamIn], P11, [psStreamOut], P12, [description]
%
% Read flag to determine which branch we're grading
%
attr/test PCTX, [description], [0]
reg/jmpeq &[.grade1], SCMP, #1
%
% We're processing the students
%
reg/load PCTX, ![students]
reg/load P8, [Student: ]
local/jmp &[.grade2]
%
% We're processing the subjects
%
.grade1
reg/load PCTX, ![subjects]
reg/load P8, [Subject: ]
.grade2
%
% Iterate each node on the branch
%
reg/load P0, (PCTX)
attr/mod P9, P11, [\n]
.gdloop
reg/load P1, (P0)
reg/jmpeq &[.gdexit], P1, NULL
attr/copy P2, P1, P12
reg/copy P2, P8, P2, [\n]
attr/mod P9, P11, P2
%
% Obtain a grade for this subject or student
%
stack/push P0, P1
reg/load P1, #1, P2, #4, P0,
[Grade 1) Beginner, 2) Intermediate, 3) Advanced, 4) Postgrad \[1-4\]? ]
local/jsr &[.getnumber]
%
% Force .gdset label to be given an index number now
%
noop &[.gdset]
%
% Jump to correct code section based upon selection
%
reg/index A, &[.gdjmp1]
op/decr P0
opa/add P0
stack/pull P1, P0
reg/load P2, (#0, A)
local/jmp P2
.gdjmp1
stack/push [Beginner]
local/jmp &[.gdset]
.gdjmp2
stack/push [Intermediate]
local/jmp &[.gdset]
.gdjmp3
stack/push [Advanced]
local/jmp &[.gdset]
.gdjmp4
stack/push [Postgrad]
.gdset
%
% Add an additional description attribute
%
reg/copy P2, [Grade: ], PULL
attr/mvadd P1, P12, P2
local/jmp &[.gdloop]
.gdexit
func/rtn
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
.func_display
%
% Preparation
%
reg/load PCTX, ![.prose.school], P9, ![.prose.sys.io]
attr/load P11, [psStreamOut], P12, [description]
%
% Process each subject, and then list the students at the same grade
%
attr/mod P9, P11, [------------------------------------------------------------------------------\n]
reg/load P0, (![subjects])
.dloop
reg/load P1, (P0)
reg/jmpeq &[.dexit], P1, NULL
%
% Read both values from description (one is display name, one is the grade)
%
local/jsr &[.getdesc]
reg/copy P3, [Subject: ], P3, [\n]
attr/mod P9, P11, P3
reg/copy P5, P4, [\n]
attr/mod P9, P11, P5
%
% Display all students at this grade
%
reg/load P6, (![students])
reg/load A, #0
reg/move P8, P4
.dloop2
reg/load P1, (P6)
reg/jmpeq &[.dcont], P1, NULL
%
% Read both values from description (one is display name, one is the grade)
%
local/jsr &[.getdesc]
reg/jmpneq &[.dnext], P4, P8
%
% Display list of students on one line (comma-separated)
%
reg/jmpneq &[.dcomma], A, #0
reg/copy P3, [Students: ], P3
local/jmp &[.dstu]
.dcomma
reg/copy P3, [, ], P3
.dstu
attr/mod P9, P11, P3
op/incr
.dnext
reg/clr P3, P4
local/jmp &[.dloop2]
.dcont
reg/clr P3, P4, P6, P8
attr/mod P9, P11, [\n\n]
local/jmp &[.dloop]
.dexit
func/rtn
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
.stripdots
%
% Remove dots from text in P0
%
stack/push A, P1, P2, P3, P4
%
% Read length of text string and process 4 bytes at a time
%
reg/xload P1, (P0)
reg/load A, #0
.strip_loop
reg/load P2, (P0, A)
op/and P3, P2, #0xff000000
reg/jmpneq &[.strip2], P3, #0x2e000000
op/and P2, P2, #0x00ffffff
op/or P2, P2, #0x5f000000
reg/load P4, #1
.strip2
op/and P3, P2, #0x00ff0000
reg/jmpneq &[.strip3], P3, #0x002e0000
op/and P2, P2, #0xff00ffff
op/or P2, P2, #0x005f0000
reg/load P4, #1
.strip3
op/and P3, P2, #0x0000ff00
reg/jmpneq &[.strip4], P3, #0x00002e00
op/and P2, P2, #0xffff00ff
op/or P2, P2, #0x00005f00
reg/load P4, #1
.strip4
op/and P3, P2, #0x000000ff
reg/jmpneq &[.strip5], P3, #0x0000002e
op/and P2, P2, #0xffffff00
op/or P2, P2, #0x0000005f
reg/load P4, #1
.strip5
reg/jmpneq &[.strip_next], P4, #1
%
% Save new 4-byte sequence back over original text (replacing . for _)
%
reg/save P0, (P2, A)
.strip_next
opa/add #4
reg/cmp P1, A
reg/jmpeq &[.strip_loop], SCMP, #2
stack/pull P4, P3, P2, P1, A
local/rtn
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
.stripnl
%
% Remove newline from end of text in P0
%
stack/push A, P1, P2
reg/xload P1, (P0)
op/decr P1
reg/load P2, (P0, P1)
reg/jmpneq &[.stripnl2], P2, #0x0a000000
reg/save P0, (P1)
.stripnl2
stack/pull P2, P1, A
local/rtn
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
.getnumber
%
% Get number from user (prompt in P0, base P1, top P2)
% Result is returned in P0
%
reg/load PUSH, P3, P3, P0
.gnget
attr/mod P9, P11, P3
attr/copy P0, P9, P10
reg/conv P0, P0
reg/cmp P0, P1
reg/jmpeq &[.gnget], SCMP, #2
reg/cmp P0, P2
reg/jmpeq &[.gnget], SCMP, #4
attr/mod P9, P11, [\n]
stack/pull P3
local/rtn
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
.getdesc
%
% Read both values from description (one is display name, one is the grade)
% Will return display name in P3 and grade in P4
%
attr/copy P2, (P1, P12)
attr/copy P3, (P2)
attr/copy P4, (P2)
reg/clr P2
reg/xscan P2, P3, [Grade: ]
reg/jmpneq &[.gdret], P2, #0
%
% Swap P3 and P4
%
reg/move P5, P3, P3, P4, P4, P5
.gdret
local/rtn