-
Notifications
You must be signed in to change notification settings - Fork 1
/
runtime-errors.js
131 lines (113 loc) · 3.09 KB
/
runtime-errors.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
require( './polyfills' )
const checks = {
OUTBOX: {
checks: [ 'accumulator' ]
},
COPYFROM: {
checks: [ 'memory' ]
},
COPYTO: {
checks: [ 'accumulator' ]
},
ADD: {
checks: [ 'accumulator', 'memory' ]
},
SUB: {
checks: [ 'accumulator', 'memory' ]
},
BUMPUP: {
name: 'BUMP+',
checks: [ 'memory' ]
},
BUMPDN: {
name: 'BUMP-',
checks: [ 'memory' ]
},
JUMPZ: {
name: 'JUMP IF ZERO',
checks: [ 'accumulator' ]
},
JUMPN: {
name: 'JUMP IF NEGATIVE',
checks: [ 'accumulator' ]
}
}
const EmptyHandsError = instrName => {
return {
name: 'Empty Hands',
message: `Empty value! You can't ${ instrName } with empty hands!`
}
}
const EmptyTileError = instrName => {
return {
name: 'Empty Tile',
message: `Empty value! You can't ${ instrName } with an empty tile on the floor! Try writing something to that tile first.`
}
}
const BadTileAddressError = address => {
return {
name: 'Bad Tile Address',
message: `Bad tile address! Tile with address ${ address } does not exist! Where do you think you're going?`
}
}
const InstrNotAllowedError = instrName => {
return {
name: 'Instruction Not Allowed',
message: `Instruction not allowed! You can't use ${ instrName } on this level!`
}
}
const DereferencingNotAllowedError = () => {
return {
name: 'Dereferencing Not Allowed',
message: `Dereferencing not allowed! You can't dereference on this level!`
}
}
const TooManyStepsError = maxSteps => {
return {
name: 'Too Many Steps',
message: `Too many steps! The maximum steps allowed is ${ maxSteps }!`
}
}
const ProgramTooLongError = maxSize => {
return {
name: 'Program Too Long',
message: `Program too long! The maximum program length is ${ maxSize }!`
}
}
const OverflowError = ( minValue, maxValue ) => {
return {
name: 'Overflow!',
message: `Overflow! Each data unit is restricted to values between ${ minValue } and ${ maxValue }. That should be enough for anybody.`
}
}
module.exports = ( instr, arg, state ) => {
if( state.accumulator < state.minValue || state.accumulator > state.maxValue )
throw OverflowError( state.minValue, state.maxValue )
if( state.size > state.maxSize )
throw ProgramTooLongError( state.maxSize )
if( !state.commands.includes( instr ) )
throw InstrNotAllowedError( instr )
if( state.dereferenced && !state.dereferencing )
throw DereferencingNotAllowedError()
if( state.steps > state.maxSteps )
throw TooManyStepsError( state.maxSteps )
const errorChecks = {
accumulator: name => {
if( state.accumulator === null )
throw EmptyHandsError( name )
},
memory: ( name, address ) => {
if( address >= state.memorySize )
throw BadTileAddressError( address )
if( state.memory[ address ] === undefined || state.memory[ address ] === null )
throw EmptyTileError( name )
}
}
if( instr in checks ){
const check = checks[ instr ]
const name = check.name || instr
check.checks.forEach( key =>
errorChecks[ key ]( name, arg )
)
}
}