-
Notifications
You must be signed in to change notification settings - Fork 48
/
enum_adr.rs
143 lines (124 loc) · 4.63 KB
/
enum_adr.rs
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
132
133
134
135
136
137
138
139
140
141
142
143
use crate::test_utils::tests::codegen;
/// # Architecture Design Record: Enums
/// An Enum (or Enumeration) is a special datatype in ST. An Enum datatype represents a numeric datatype (default is i32)
/// with a list of well defined values with dedicated names (e.g. `@red`, `@yellow`, `@green`).
///
/// e.g.
/// ```st
/// TYPE MyEnum: (element1, element2, element3);
/// END_TYPE
/// ```
#[test]
fn enums_generate_a_global_constants_for_each_element() {
let src = r#"
TYPE Color : (red, yellow, green);
END_TYPE;
VAR_GLOBAL
myColor : Color;
END_VAR"#;
insta::assert_snapshot!(codegen(src), @r###"
; ModuleID = 'main'
source_filename = "main"
@myColor = global i32 0
@red = unnamed_addr constant i32 0
@yellow = unnamed_addr constant i32 1
@green = unnamed_addr constant i32 2
"###);
}
/// The values of the enum constants are stored as (enum-local) unique numeric values. The values and their
/// datatype (see declaration of `State : BYTE`) can be defined by the user via an initialization statement,
/// or automatically assigned by the compiler.
/// `i32` is the default datatype for enums if no other type is specified (e.g. `Color`).
/// Values that are assigned by the compiler get unique ascending values.
#[test]
fn enums_constants_are_automatically_numbered_or_user_defined() {
let src = r#"
TYPE Color : (red := 1, yellow := 2, green := 4, blue := 8);
END_TYPE;
TYPE State : BYTE (open := 1, closed := 4, idle, running);
END_TYPE;
VAR_GLOBAL
myColor : Color;
myState : State;
END_VAR"#;
insta::assert_snapshot!(codegen(src), @r###"
; ModuleID = 'main'
source_filename = "main"
@myColor = global i32 0
@myState = global i8 0
@red = unnamed_addr constant i32 1
@yellow = unnamed_addr constant i32 2
@green = unnamed_addr constant i32 4
@blue = unnamed_addr constant i32 8
@open = unnamed_addr constant i8 1
@closed = unnamed_addr constant i8 4
@idle = unnamed_addr constant i8 5
@running = unnamed_addr constant i8 6
"###);
}
/// Enum types can be declared as dedicated DataTypes (see above) or direclty as part of a
/// variable declaration. Note that declaring the same enum twice will result in two distinct
/// enum-datatypes (and separate constant-variables - e.g. `@red` and `@red.1`).
#[test]
fn inline_declaration_of_enum_types() {
let src = r#"
VAR_GLOBAL
frontColor : (red, green, yellow);
backColor : (red, green, yellow);
END_VAR"#;
insta::assert_snapshot!(codegen(src), @r###"
; ModuleID = 'main'
source_filename = "main"
@frontColor = global i32 0
@backColor = global i32 0
@red = unnamed_addr constant i32 0
@green = unnamed_addr constant i32 1
@yellow = unnamed_addr constant i32 2
@red.1 = unnamed_addr constant i32 0
@green.2 = unnamed_addr constant i32 1
@yellow.3 = unnamed_addr constant i32 2
"###);
}
/// Enum elements can accessed like global variables. If there are mulitple candidates, one can
/// pick a specific element by qualifying it with the enum's name (note that this is not possible for inline
/// enums).
/// In this example the enum-element `open` is defined in the type `ProcessState` as well as in `Door`. We can now
/// select a specific element by qualifying it via `ProcessState#closed` or `Door#closed` to access the generated global
/// variables `@closed` or `@closed.2`.
#[test]
fn using_enums() {
let src = r#"
TYPE ProcessState : (open := 1, closed := 4, idle, running);
END_TYPE;
TYPE Door : (open := 8, closed := 16);
END_TYPE;
PROGRAM prg
VAR x, y, z : DINT; END_VAR
x := idle;
y := ProcessState#closed;
z := Door#closed;
END_PROGRAM
"#;
insta::assert_snapshot!(codegen(src), @r###"
; ModuleID = 'main'
source_filename = "main"
%prg = type { i32, i32, i32 }
@prg_instance = global %prg zeroinitializer
@open = unnamed_addr constant i32 1
@closed = unnamed_addr constant i32 4
@idle = unnamed_addr constant i32 5
@running = unnamed_addr constant i32 6
@open.1 = unnamed_addr constant i32 8
@closed.2 = unnamed_addr constant i32 16
define void @prg(%prg* %0) {
entry:
%x = getelementptr inbounds %prg, %prg* %0, i32 0, i32 0
%y = getelementptr inbounds %prg, %prg* %0, i32 0, i32 1
%z = getelementptr inbounds %prg, %prg* %0, i32 0, i32 2
store i32 5, i32* %x, align 4
store i32 4, i32* %y, align 4
store i32 16, i32* %z, align 4
ret void
}
"###);
}