I think a number of the issues described above were due to my choice to use PASM, while Parrot apparently intends for most users to use (and of course by "use" I mean have their compilers output) PIR (Parrot Intermediate Representation) code which is then converted to PASM. And because this is the intent, good PASM documentation was harder to find than PIR. Luckily, there was a list of opcodes, and a whopping 4 examples that came with Parrot, so those two things combined are what I used to get through most of this.
The last issue was stuff with the input file having Windows newlines while I only tested on Unix newlines to begin with. But oh well, that was fixed relatively easily.
My use of PASM has inspired me to look into soon using a similar language...Java ByteCode (and, if it is sufficiently different, PIR).
Anyway, even if it runs on a VM, it is still basically an assembly language, so my solution below runs very quickly: about 25ms on my machine.
.loadlib 'io_ops'
#ASCII values of important letters
.macro_const M 77
.macro_const D 68
.macro_const C 67
.macro_const L 76
.macro_const X 88
.macro_const V 86
.macro_const I 73
#Impromptu convention:
#arguments passed in I/S 1, returned in I/S 0
.pcc_sub :main main:
#'The Stack'
new P10,'ResizableIntegerArray'
getstdin P0
set I9, 0
MAINLOOP:
readline S1, P0
unless S1, FINAL
#get length of string
length I8, S1
#subtract 2 from length because windows newline
sub I8, I8, 2
inc I8
#cutoff one char of newline, as methods expect
#UNIX newlines
substr S1, S1, 0, I8
dec I8
#Now that that is done...
local_branch P10, GET_STRING_VALUE
local_branch P10, GET_CHAR_COUNT
sub I0, I8, I0
add I9, I9, I0
branch MAINLOOP
FINAL:
say I9
end
#Basically a switch statement
#input: I0
#output: I0
GET_CHAR_VALUE:
eq I0, .M, M
eq I0, .D, D
eq I0, .C, C
eq I0, .L, L
eq I0, .X, X
eq I0, .V, V
I:
set I0, 1
local_return P10
V:
set I0, 5
local_return P10
X:
set I0, 10
local_return P10
L:
set I0, 50
local_return P10
C:
set I0, 100
local_return P10
D:
set I0, 500
local_return P10
M:
set I0, 1000
local_return P10
#compute integer corresponding to Roman Numeral
#input: S1
#output: I0
#used: I2, I3, I4, I5, S2
GET_STRING_VALUE:
length I2, S1
dec I2
set I3, 0
set I4, 0
set I5, 0
LOOP:
ge I3, I2, ENDLOOP
substr S2, S1, I3, 1
ord I0, S2
local_branch P10, GET_CHAR_VALUE
set I4, I0
inc I3
substr S2, S1, I3, 1
ord I0, S2
local_branch P10, GET_CHAR_VALUE
lt I4, I0, _SUB
add I5, I5, I4
branch LOOP
_SUB:
sub I5, I5, I4
branch LOOP
ENDLOOP:
set I0, I5
local_return P10
#This could be written much more nicely
#If I could figure out how to do arrays
#input: I0
#used: I1, I6, I7
GET_CHAR_COUNT:
#Move input into I1
#And compute number of M's
set I1, I0
div I6, I1, 1000
mul I0, I6, 1000
sub I1, I1, I0
set I7, I6
#CM
div I6, I1, 900
mul I0, I6, 900
sub I1, I1, I0
mul I6, I6, 2
add I7, I7, I6
#D
div I6, I1, 500
mul I0, I6, 500
sub I1, I1, I0
add I7, I7, I6
#CD
div I6, I1, 400
mul I0, I6, 400
sub I1, I1, I0
mul I6, I6, 2
add I7, I7, I6
#C
div I6, I1, 100
mul I0, I6, 100
sub I1, I1, I0
add I7, I7, I6
#XC
div I6, I1, 90
mul I0, I6, 90
sub I1, I1, I0
mul I6, I6, 2
add I7, I7, I6
#L
div I6, I1, 50
mul I0, I6, 50
sub I1, I1, I0
add I7, I7, I6
#XL
div I6, I1, 40
mul I0, I6, 40
sub I1, I1, I0
mul I6, I6, 2
add I7, I7, I6
#X
div I6, I1, 10
mul I0, I6, 10
sub I1, I1, I0
add I7, I7, I6
#IX
div I6, I1, 9
mul I0, I6, 9
sub I1, I1, I0
mul I6, I6, 2
add I7, I7, I6
#V
div I6, I1, 5
mul I0, I6, 5
sub I1, I1, I0
add I7, I7, I6
#IV
div I6, I1, 4
mul I0, I6, 4
sub I1, I1, I0
mul I6, I6, 2
add I7, I7, I6
#I
add I0, I7, I1
local_return P10
No comments:
Post a Comment