1
1
#![ feature( try_trait) ]
2
- use std:: { collections:: HashMap , option:: NoneError } ;
3
- use Command :: * ;
2
+ use std:: collections:: HashMap ;
4
3
use Operator :: * ;
5
4
6
5
pub type Value = i32 ;
@@ -16,7 +15,7 @@ enum Operator {
16
15
17
16
#[ derive( Debug ) ]
18
17
enum Command {
19
- Dropp , // collides with Rust keyword
18
+ Drop , // collides with Rust keyword
20
19
Dup ,
21
20
Swap ,
22
21
Over ,
@@ -31,12 +30,6 @@ pub enum Error {
31
30
InvalidWord ,
32
31
}
33
32
34
- impl From < NoneError > for Error {
35
- fn from ( _error : NoneError ) -> Error {
36
- Error :: StackUnderflow
37
- }
38
- }
39
-
40
33
#[ derive( Default , Debug ) ]
41
34
pub struct Forth {
42
35
text : String ,
@@ -53,12 +46,13 @@ impl Forth {
53
46
}
54
47
55
48
fn filter_words ( & mut self ) {
56
- self . text = self . text . chars ( ) . fold ( String :: new ( ) , |acc, chr| {
49
+ self . text = self . text . chars ( ) . fold ( String :: new ( ) , |mut acc, chr| {
57
50
if chr. is_whitespace ( ) || chr. is_control ( ) {
58
- acc + & ' ' . to_string ( )
51
+ acc. push ( ' ' ) ;
59
52
} else {
60
- acc + & chr . to_string ( )
53
+ acc. push ( chr )
61
54
}
55
+ acc
62
56
} )
63
57
}
64
58
@@ -69,7 +63,7 @@ impl Forth {
69
63
self . eval_digits ( ) ;
70
64
self . eval_operators ( ) ?;
71
65
self . eval_word_declarations ( ) ?;
72
- self . eval_word ( ) ? ;
66
+ self . eval_word ( ) ;
73
67
self . eval_commands ( ) ?;
74
68
}
75
69
Ok ( ( ) )
@@ -83,8 +77,8 @@ impl Forth {
83
77
84
78
fn eval_operators ( & mut self ) -> ForthResult {
85
79
while let Some ( operator) = self . parse_operator ( ) {
86
- let value2 = self . stack . pop ( ) ?;
87
- let value1 = self . stack . pop ( ) ?;
80
+ let value2 = self . pop_stack ( ) ?;
81
+ let value1 = self . pop_stack ( ) ?;
88
82
match operator {
89
83
Plus => self . stack . push ( value1 + value2) ,
90
84
Minus => self . stack . push ( value1 - value2) ,
@@ -101,43 +95,42 @@ impl Forth {
101
95
}
102
96
103
97
fn eval_word_declarations ( & mut self ) -> ForthResult {
104
- while let Some ( Word ( ( key, value) ) ) = self . parse_word_delcaration ( ) ? {
98
+ while let Some ( Command :: Word ( ( key, value) ) ) = self . parse_word_declaration ( ) ? {
105
99
self . words . insert ( key, value) ;
106
100
}
107
101
Ok ( ( ) )
108
102
}
109
103
110
- fn eval_word ( & mut self ) -> ForthResult {
104
+ fn eval_word ( & mut self ) {
111
105
if let Some ( value) = self . parse_word ( ) {
112
106
self . text = value;
113
107
}
114
- Ok ( ( ) )
115
108
}
116
109
117
110
fn eval_commands ( & mut self ) -> ForthResult {
118
111
while let Some ( command) = self . parse_command ( ) ? {
119
112
match command {
120
- Swap => {
121
- let value2 = self . stack . pop ( ) ?;
122
- let value1 = self . stack . pop ( ) ?;
113
+ Command :: Swap => {
114
+ let value2 = self . pop_stack ( ) ?;
115
+ let value1 = self . pop_stack ( ) ?;
123
116
self . stack . push ( value2) ;
124
117
self . stack . push ( value1) ;
125
118
}
126
- Dropp => {
127
- self . stack . pop ( ) ?;
119
+ Command :: Drop => {
120
+ self . pop_stack ( ) ?;
128
121
}
129
- Dup => {
130
- let last = * ( self . stack . iter ( ) . last ( ) ?) ;
122
+ Command :: Dup => {
123
+ let last = * ( self . stack . iter ( ) . last ( ) . ok_or ( Error :: StackUnderflow ) ?) ;
131
124
self . stack . push ( last) ;
132
125
}
133
- Over => {
134
- let value2 = self . stack . pop ( ) ?;
135
- let value1 = self . stack . pop ( ) ?;
126
+ Command :: Over => {
127
+ let value2 = self . pop_stack ( ) ?;
128
+ let value1 = self . pop_stack ( ) ?;
136
129
self . stack . push ( value1) ;
137
130
self . stack . push ( value2) ;
138
131
self . stack . push ( value1) ;
139
132
}
140
- Word ( ( key, value) ) => {
133
+ Command :: Word ( ( key, value) ) => {
141
134
self . words . insert ( key, value) ;
142
135
}
143
136
}
@@ -213,26 +206,26 @@ impl Forth {
213
206
match head. as_str ( ) {
214
207
"drop" => {
215
208
self . text = tail;
216
- Ok ( Some ( Dropp ) )
209
+ Ok ( Some ( Command :: Drop ) )
217
210
}
218
211
"dup" => {
219
212
self . text = tail;
220
- Ok ( Some ( Dup ) )
213
+ Ok ( Some ( Command :: Dup ) )
221
214
}
222
215
"swap" => {
223
216
self . text = tail;
224
- Ok ( Some ( Swap ) )
217
+ Ok ( Some ( Command :: Swap ) )
225
218
}
226
219
"over" => {
227
220
self . text = tail;
228
- Ok ( Some ( Over ) )
221
+ Ok ( Some ( Command :: Over ) )
229
222
}
230
223
digits if digits. parse :: < u32 > ( ) . is_ok ( ) => Ok ( None ) ,
231
224
_ => Err ( Error :: UnknownWord ) ,
232
225
}
233
226
}
234
227
235
- fn parse_word_delcaration ( & mut self ) -> Result < Option < Command > , Error > {
228
+ fn parse_word_declaration ( & mut self ) -> Result < Option < Command > , Error > {
236
229
let input = self . text . clone ( ) ;
237
230
if !input. starts_with ( ':' ) {
238
231
return Ok ( None ) ;
@@ -266,7 +259,7 @@ impl Forth {
266
259
. collect ( ) ;
267
260
self . text = rest. trim_left ( ) . to_string ( ) ;
268
261
269
- Ok ( Some ( Word ( ( key. to_lowercase ( ) , value) ) ) )
262
+ Ok ( Some ( Command :: Word ( ( key. to_lowercase ( ) , value) ) ) )
270
263
}
271
264
272
265
fn parse_word ( & self ) -> Option < String > {
@@ -284,4 +277,8 @@ impl Forth {
284
277
. get ( & head. to_lowercase ( ) )
285
278
. and_then ( |value| Some ( value. to_string ( ) + tail) )
286
279
}
280
+
281
+ fn pop_stack ( & mut self ) -> Result < i32 , Error > {
282
+ self . stack . pop ( ) . ok_or ( Error :: StackUnderflow )
283
+ }
287
284
}
0 commit comments