Source code: students.pal

From PROSE Programming Language - Wiki
Jump to: navigation, search
%
% 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