Files
RustIJVM/files/advanced/SimpleCalc.jas

304 lines
3.5 KiB
Plaintext

//SimpleCalc.jas by Ronald Bethlehem
//Includes the recursive function for factorial and printing a number
//Utilises reverse polish notation
//Also tests the SWAP and IF_ICMPEQ operators
//Can read larger numbers, all undefined characters delimit
//Valid example:
//99 5 + 4 / 22 1*- ! ? 99 5+4/22v1*-!?. (prints 24\n24\n)
.constant
OBJREF 0xDEAD
ZERO 0x30
NINE 0x39
FACTORIAL 0x21
DUPLICATE 0x26
MULTIPLY 0x2A
PLUS 0x2B
MINUS 0x2D
DIVIDE 0x2F
PRINT 0x3F
END 0x2E
.end-constant
.main
.var
mode //0 for end, 1 for numberreading, 2 for other
tmp
.end-var
// Add some things to the stack
BIPUSH 0x0
BIPUSH 0x0
BIPUSH 0x0
BIPUSH 2
ISTORE mode
readchar:
ILOAD mode
IFEQ end
IN
//Is is a number?
DUP
LDC_W ZERO
ISUB
IFLT continue
DUP
LDC_W NINE
BIPUSH 1
IADD
ISUB
IFLT read_number
//Set mode to not number (aka delimited)
continue:
BIPUSH 2
ISTORE mode
//Check for operators
DUP
LDC_W END
IF_ICMPEQ read_end
DUP
LDC_W FACTORIAL
IF_ICMPEQ read_factorial
DUP
LDC_W DUPLICATE
IF_ICMPEQ read_duplicate
DUP
LDC_W MULTIPLY
IF_ICMPEQ read_multiply
DUP
LDC_W PLUS
IF_ICMPEQ read_plus
DUP
LDC_W MINUS
IF_ICMPEQ read_minus
DUP
LDC_W DIVIDE
IF_ICMPEQ read_divide
DUP
LDC_W PRINT
IF_ICMPEQ read_print
//Ignore character
POP
GOTO readchar
read_end:
POP
BIPUSH 0
ISTORE mode
GOTO readchar
read_factorial:
POP
ISTORE tmp
LDC_W OBJREF
SWAP
ILOAD tmp
INVOKEVIRTUAL factorial
GOTO readchar
read_duplicate:
POP
DUP
GOTO readchar
read_multiply:
POP
ISTORE tmp
LDC_W OBJREF
SWAP
ILOAD tmp
INVOKEVIRTUAL mul
GOTO readchar
read_plus:
POP
IADD
GOTO readchar
read_minus:
POP
ISUB
GOTO readchar
read_divide:
POP
ISTORE tmp
LDC_W OBJREF
SWAP
ILOAD tmp
INVOKEVIRTUAL divide
GOTO readchar
read_print:
POP
LDC_W OBJREF
SWAP
INVOKEVIRTUAL printNumber
POP
BIPUSH 0xA //newline
OUT
GOTO readchar
read_number:
LDC_W ZERO
ISUB
ILOAD mode
BIPUSH 1
IF_ICMPEQ read_number_continue
BIPUSH 1
ISTORE mode
GOTO readchar
read_number_continue:
SWAP
LDC_W OBJREF
SWAP
BIPUSH 10
INVOKEVIRTUAL mul
IADD
GOTO readchar
end:
HALT
.end-main
.method printNumber(a)
ILOAD a
BIPUSH 10
ISUB
IFLT small
recurse:
LDC_W OBJREF
LDC_W OBJREF
ILOAD a
BIPUSH 10
INVOKEVIRTUAL mod
LDC_W OBJREF
LDC_W OBJREF
ILOAD a
BIPUSH 10
INVOKEVIRTUAL divide
INVOKEVIRTUAL printNumber
POP
INVOKEVIRTUAL printNum
//POP
IRETURN
small:
LDC_W OBJREF
ILOAD a
INVOKEVIRTUAL printNum
//POP
IRETURN
.end-method
.method printNum(a)
ILOAD a
LDC_W ZERO
IADD
OUT
BIPUSH 0x0
IRETURN
.end-method
.method mul(a,b)
ILOAD b
ILOAD a
ISUB
IFLT noswap
ILOAD a
ILOAD b
SWAP
ISTORE b
ISTORE a
noswap:
BIPUSH 0
loop:
ILOAD b
IFEQ bzero
bpos:
ILOAD b
BIPUSH 1
ISUB
ISTORE b
add:
ILOAD a
IADD
GOTO loop
bzero:
IRETURN
.end-method
.method divide(a,b)
.var
count
.end-var
ILOAD b
IFEQ err
BIPUSH 0
ISTORE count
ILOAD a
loop:
ILOAD a
ILOAD b
ISUB
DUP
IFLT done
ISTORE a
inc:
ILOAD count
BIPUSH 1
IADD
ISTORE count
GOTO loop
done:
ILOAD count
IRETURN
err:
ERR
.end-method
.method mod(a,b)
LDC_W OBJREF
LDC_W OBJREF
ILOAD a
ILOAD b
INVOKEVIRTUAL divide
ILOAD b
INVOKEVIRTUAL mul
ILOAD a
SWAP // yeah I know, I could also have pushed a at the start, but its a test, who gives a carp about performance
ISUB
IRETURN
.end-method
.method factorial(i)
.var
tmp
.end-var
LDC_W OBJREF
ILOAD i
ILOAD i
BIPUSH 1
ISUB
ISTORE tmp
ILOAD tmp
IFEQ one
LDC_W OBJREF
ILOAD tmp
INVOKEVIRTUAL factorial
INVOKEVIRTUAL mul
one:
IRETURN
.end-method