Skip to content

Commit

Permalink
Merge pull request #30 from skx/29-catch-overflow
Browse files Browse the repository at this point in the history
29 catch overflow
  • Loading branch information
skx committed Jul 9, 2019
2 parents d8b52e2 + 1894b13 commit 82cd69f
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 11 deletions.
29 changes: 21 additions & 8 deletions compiler/compiler.go
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ func (c *Compiler) tokenize() error {
len := len(c.tokens)
end := c.tokens[len-1]
if end.Type == token.NUMBER {
return fmt.Errorf("rogram ends with a number, which is invalid")
return fmt.Errorf("program ends with a number, which is invalid")
}
}

Expand Down Expand Up @@ -315,22 +315,24 @@ func (c *Compiler) output() string {
#
# depth: used to keep track of stack-depth.
#
# fmt: Used to output the result of the calculation, and div_zero for
# the obvious error-case.
# fmt: Used to output the result of the calculation, later strings are for
# various error-reports.
#
.data
a: .double 0.0
b: .double 0.0
depth: .double 0.0
int: .double 0.0
fmt: .asciz "Result %g\n"
div_zero: .asciz "Attempted division by zero. Aborting\n"
overflow: .asciz "Overflow - value out of range. Aborting\n"
stack_err: .asciz "Insufficient entries on the stack. Aborting\n"
stack_full: .asciz "Too many entries remaining on the stack. Aborting\n"
`

//
// Add on the constants
// Output each of our discovered constants.
//
for v := range c.constants {
header += fmt.Sprintf("%s: .double %s\n",
Expand All @@ -342,15 +344,18 @@ func (c *Compiler) output() string {
# Main is our entry-point.
#
# We'll save rbp before we begin
#
main:
push rbp
# Our stack is initially empty (of numbers), so ensure that [depth]
# is set to zero.
#
# Every time we push a value upon the stack we'll increase this value
# and before we pop arguments from the stack we'll check there are
# sufficient values stored. This will prevent segfaults when user
# programs are broken.
#
mov qword ptr [depth], 0
`
Expand All @@ -376,9 +381,6 @@ main:
case instructions.Abs:
body += c.genAbs()

case instructions.Factorial:
body += c.genFactorial(i)

case instructions.Cos:
body += c.genCos()

Expand All @@ -388,6 +390,9 @@ main:
case instructions.Dup:
body += c.genDup()

case instructions.Factorial:
body += c.genFactorial(i)

case instructions.Minus:
body += c.genMinus()

Expand Down Expand Up @@ -446,6 +451,13 @@ division_by_zero:
lea rdi,div_zero
jmp print_msg_and_exit
#
# This is hit when a register is too small to hold a value.
#
register_overflow:
lea rdi,overflow
jmp print_msg_and_exit
#
# This point is hit when the program is due to terminate, but the
Expand All @@ -467,7 +479,8 @@ stack_error:
#
# Print a message and terminate.
#
# NOTE: We call 'exit' here to allow stdout to be flushed.
# NOTE: We call 'exit' here to allow stdout to be flushed, and also to ensure
# we don't need to balance our stack.
#
print_msg_and_exit:
xor rax,rax
Expand Down
17 changes: 14 additions & 3 deletions compiler/generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ func (c *Compiler) escapeConstant(input string) string {
// run an ABS-operation, and store the result back on the stack.
func (c *Compiler) genAbs() string {
return `
# [Abs]
# [ABS]
# ensure there are at least one argument on the stack
mov rax, qword ptr [depth]
cmp rax, 1
Expand Down Expand Up @@ -136,7 +136,7 @@ func (c *Compiler) genDup() string {
// run a factorial-operation, and store the result back on the stack.
func (c *Compiler) genFactorial(i int) string {
text := `
# [Factorial]
# [FACTORIAL]
# ensure there are at least one argument on the stack
mov rax, qword ptr [depth]
cmp rax, 1
Expand Down Expand Up @@ -164,6 +164,10 @@ func (c *Compiler) genFactorial(i int) string {
again_#ID:
# rax = rax * rcx
imul rax, rcx
# value too big?
jo register_overflow
dec rcx
jnz again_#ID
Expand Down Expand Up @@ -379,6 +383,10 @@ none_one_#ID:
again_#ID:
# rax = rax * rcx (which is the original value we started with)
imul rax,rcx
# value too big?
jo register_overflow
dec rbx
jnz again_#ID
Expand Down Expand Up @@ -426,7 +434,7 @@ func (c *Compiler) genPush(value string) string {
// run a sin-operation, and store the result back on the stack.
func (c *Compiler) genSin() string {
return `
# [Sin]
# [SIN]
# ensure there are at least one argument on the stack
mov rax, qword ptr [depth]
cmp rax, 1
Expand All @@ -453,17 +461,20 @@ func (c *Compiler) genSin() string {
// push them back, in the other order.
func (c *Compiler) genSwap() string {
return `
# [SWAP]
pop rax
pop rbx
push rax
push rbx
# stack size didn't change; popped two, pushed two.
`
}

// genTan generates assembly code to pop a value from the stack,
// run a tan-operation, and store the result back on the stack.
func (c *Compiler) genTan() string {
return `
# [TAN]
# pop one value
pop rax
mov qword ptr [a], rax
Expand Down
2 changes: 2 additions & 0 deletions test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ test_compile '2 7 ^' 128
test_compile '2 8 ^' 256
test_compile '2 16 ^' 65536
test_compile '2 30 ^' 1.07374e+09
test_compile '2 300 ^' 'Overflow - value out of range. Aborting' 'full'

# factorials
test_compile '-3 !' 0
Expand All @@ -124,6 +125,7 @@ test_compile '4 !' 24
test_compile '5 !' 120
test_compile '6 !' 720
test_compile '5 5 + !' 3.6288e+06 # 3628800
test_compile '3 300 !' 'Overflow - value out of range. Aborting' 'full'

# division
test_compile '3 2 /' 1.5
Expand Down

0 comments on commit 82cd69f

Please sign in to comment.