1
1
use std:: { collections:: HashMap , fmt} ;
2
2
3
- use super :: { Instruction , DEFAULT_CONSTANTS } ;
3
+ use super :: { Field , Instruction , Opcode , DEFAULT_CONSTANTS } ;
4
4
5
5
type Instructions = Vec < Instruction > ;
6
6
pub type LabelMap = HashMap < String , usize > ;
@@ -9,6 +9,7 @@ pub struct Program {
9
9
instructions : Instructions ,
10
10
resolved : Option < Instructions > ,
11
11
labels : LabelMap ,
12
+ origin : Option < Field > ,
12
13
}
13
14
14
15
impl PartialEq for Program {
@@ -36,6 +37,9 @@ impl fmt::Debug for Program {
36
37
37
38
impl fmt:: Display for Program {
38
39
fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
40
+ if let Some ( origin) = self . get_origin ( ) {
41
+ writeln ! ( f, "{:<6} {}" , Opcode :: Org , origin. value) ?;
42
+ }
39
43
write ! (
40
44
f,
41
45
"{}" ,
@@ -57,6 +61,7 @@ impl Program {
57
61
instructions : Instructions :: new ( ) ,
58
62
resolved : None ,
59
63
labels : DEFAULT_CONSTANTS . clone ( ) ,
64
+ origin : None ,
60
65
}
61
66
}
62
67
@@ -65,6 +70,7 @@ impl Program {
65
70
instructions : vec ! [ Default :: default ( ) ; size] ,
66
71
resolved : None ,
67
72
labels : DEFAULT_CONSTANTS . clone ( ) ,
73
+ origin : None ,
68
74
}
69
75
}
70
76
@@ -85,6 +91,16 @@ impl Program {
85
91
self . instructions [ index] = value;
86
92
}
87
93
94
+ pub fn set_origin ( & mut self , field : Field ) {
95
+ self . origin = Some ( field) ;
96
+ }
97
+
98
+ pub fn get_origin ( & self ) -> Option < Field > {
99
+ self . origin
100
+ . as_ref ( )
101
+ . and_then ( |field| field. resolve ( 0 , & self . labels ) . ok ( ) )
102
+ }
103
+
88
104
pub fn add_label ( & mut self , index : usize , label : String ) -> Result < ( ) , String > {
89
105
if index > self . instructions . len ( ) {
90
106
return Err ( format ! (
@@ -151,6 +167,34 @@ mod tests {
151
167
assert ! ( program. label_address( "never_mentioned" ) . is_none( ) ) ;
152
168
}
153
169
170
+ #[ test]
171
+ fn literal_origin ( ) {
172
+ let mut program = Program :: with_capacity ( 200 ) ;
173
+
174
+ program. set_origin ( Field :: direct ( 12 ) ) ;
175
+
176
+ assert_eq ! ( program. get_origin( ) . unwrap( ) , Field :: direct( 12 ) )
177
+ }
178
+
179
+ #[ test]
180
+ fn labeled_origin ( ) {
181
+ let mut program = Program :: with_capacity ( 200 ) ;
182
+
183
+ program
184
+ . add_label ( 123 , "baz" . into ( ) )
185
+ . expect ( "Should add baz" ) ;
186
+ program. add_label ( 0 , "foo" . into ( ) ) . expect ( "Should add foo" ) ;
187
+
188
+ program. set_origin ( Field :: direct_label ( "baz" ) ) ;
189
+ assert_eq ! ( program. get_origin( ) . unwrap( ) , Field :: direct( 123 ) ) ;
190
+
191
+ program. set_origin ( Field :: direct_label ( "foo" ) ) ;
192
+ assert_eq ! ( program. get_origin( ) . unwrap( ) , Field :: direct( 0 ) ) ;
193
+
194
+ program. set_origin ( Field :: direct_label ( "nonexistent" ) ) ;
195
+ assert ! ( program. get_origin( ) . is_none( ) ) ;
196
+ }
197
+
154
198
#[ test]
155
199
fn resolve_failure ( ) {
156
200
let mut program = Program :: with_capacity ( 10 ) ;
0 commit comments