1use core::str::FromStr;
2use std::fmt;
3use std::hash::{Hash, Hasher};
4use time::Duration;
5
6use crate::ast::*;
7use crate::core::{Id, SourceLoc};
8use crate::sfc::Network;
9
10pub enum TypeDefinitionKind {
11 Enumeration,
12 FunctionBlock,
13 Function,
14 Structure,
15}
16
17#[derive(Debug, PartialEq)]
19pub enum LibraryElement {
20 DataTypeDeclaration(Vec<EnumerationDeclaration>),
21 FunctionDeclaration(FunctionDeclaration),
22 FunctionBlockDeclaration(FunctionBlockDeclaration),
24 ProgramDeclaration(ProgramDeclaration),
25 ConfigurationDeclaration(ConfigurationDeclaration),
26}
27
28pub struct Integer {
33 value: String,
34}
35
36impl Integer {
37 pub fn try_from<T: FromStr>(&self) -> T {
38 let v: String = self.value.chars().filter(|c| c.is_digit(10)).collect();
39 match v.parse::<T>() {
40 Ok(v) => return v,
41 Err(_) => panic!("out of range"),
42 }
43 }
44
45 pub fn as_type<T: FromStr>(&self) -> T {
46 self.try_from::<T>()
47 }
48
49 pub fn num_chars(&self) -> u8 {
50 let value: String = self.value.chars().filter(|c| c.is_digit(10)).collect();
51 let value: u8 = 1;
53 value
54 }
55
56 pub fn from(a: &str) -> Integer {
57 Integer {
58 value: String::from(a),
59 }
60 }
61}
62
63pub struct SignedInteger {
64 value: Integer,
65 is_neg: bool,
66}
67
68impl SignedInteger {
69 pub fn as_type<T: FromStr>(&self) -> T {
70 let val = self.value.try_from::<T>();
71 val
76 }
77 pub fn from(a: &str) -> SignedInteger {
78 match a.chars().nth(0) {
79 Some('+') => {
80 return SignedInteger {
81 value: Integer::from(a.get(1..).unwrap()),
82 is_neg: false,
83 }
84 }
85 Some('-') => {
86 return SignedInteger {
87 value: Integer::from(a.get(1..).unwrap()),
88 is_neg: true,
89 }
90 }
91 _ => {
92 return SignedInteger {
93 value: Integer::from(a),
94 is_neg: false,
95 }
96 }
97 }
98 }
99}
100
101#[derive(Debug, PartialEq, Clone)]
102pub struct Float {
103 pub value: f64,
104 pub data_type: Option<Id>,
105}
106
107#[derive(Debug, PartialEq, Clone)]
111pub struct Declaration {
112 pub name: Id,
113 pub storage_class: StorageClass,
114 pub at: Option<At>,
115 pub initializer: Option<TypeInitializer>,
116}
117
118#[derive(Debug, PartialEq, Clone)]
119pub enum VariableType {
120 Var,
122 VarTemp,
125 Input,
127 Output,
131 InOut,
134 External,
137 Global,
140 Access,
142}
143
144#[derive(Debug, PartialEq, Clone)]
145pub struct VarInitDecl {
146 pub name: Id,
147 pub var_type: VariableType,
148 pub storage_class: StorageClass,
149 pub initializer: TypeInitializer,
150 pub position: SourceLoc,
152}
153
154impl VarInitDecl {
155 pub fn simple_input(name: &str, type_name: &str, loc: SourceLoc) -> VarInitDecl {
157 VarInitDecl::simple(name, type_name, VariableType::Input, loc)
158 }
159
160 pub fn simple_output(name: &str, type_name: &str, loc: SourceLoc) -> VarInitDecl {
162 VarInitDecl::simple(name, type_name, VariableType::Output, loc)
163 }
164
165 pub fn simple_var(name: &str, type_name: &str, loc: SourceLoc) -> VarInitDecl {
167 VarInitDecl::simple(name, type_name, VariableType::Var, loc)
168 }
169
170 pub fn simple_external(name: &str, type_name: &str, loc: SourceLoc) -> VarInitDecl {
172 VarInitDecl::simple(name, type_name, VariableType::External, loc)
173 }
174
175 pub fn simple(
177 name: &str,
178 type_name: &str,
179 var_type: VariableType,
180 loc: SourceLoc,
181 ) -> VarInitDecl {
182 VarInitDecl {
183 name: Id::from(name),
184 var_type: var_type,
185 storage_class: StorageClass::Unspecified,
186 initializer: TypeInitializer::Simple {
187 type_name: Id::from(type_name),
188 initial_value: None,
189 },
190 position: loc,
191 }
192 }
193
194 pub fn enumerated_input(
196 name: &str,
197 type_name: &str,
198 initial_value: &str,
199 loc: SourceLoc,
200 ) -> VarInitDecl {
201 VarInitDecl {
202 name: Id::from(name),
203 var_type: VariableType::Input,
204 storage_class: StorageClass::Unspecified,
205 initializer: TypeInitializer::EnumeratedType(EnumeratedTypeInitializer {
206 type_name: Id::from(type_name),
207 initial_value: Some(Id::from(initial_value)),
208 }),
209 position: loc,
210 }
211 }
212
213 pub fn function_block_var(name: &str, type_name: &str, loc: SourceLoc) -> VarInitDecl {
215 VarInitDecl {
216 name: Id::from(name),
217 var_type: VariableType::Var,
218 storage_class: StorageClass::Unspecified,
219 initializer: TypeInitializer::FunctionBlock(FunctionBlockTypeInitializer {
220 type_name: Id::from(type_name),
221 }),
222 position: loc,
223 }
224 }
225
226 pub fn late_bound_input(name: &str, type_name: &str, loc: SourceLoc) -> VarInitDecl {
231 VarInitDecl::late_bound(name, type_name, VariableType::Input, loc)
232 }
233
234 pub fn late_bound_var(name: &str, type_name: &str, loc: SourceLoc) -> VarInitDecl {
239 VarInitDecl::late_bound(name, type_name, VariableType::Var, loc)
240 }
241
242 pub fn late_bound(
247 name: &str,
248 type_name: &str,
249 var_type: VariableType,
250 loc: SourceLoc,
251 ) -> VarInitDecl {
252 VarInitDecl {
253 name: Id::from(name),
254 var_type: var_type,
255 storage_class: StorageClass::Unspecified,
256 initializer: TypeInitializer::LateResolvedType(Id::from(type_name)),
257 position: loc,
258 }
259 }
260}
261
262#[derive(Debug, PartialEq, Clone)]
263pub struct LocatedVarInit {
264 pub name: Option<Id>,
265 pub storage_class: StorageClass,
266 pub at: DirectVariable,
267 pub initializer: TypeInitializer,
268}
269
270#[derive(Debug, PartialEq, Clone)]
271pub enum VarInitKind {
272 VarInit(VarInitDecl),
273 LocatedVarInit(LocatedVarInit),
274}
275
276#[derive(Debug, PartialEq, Clone)]
278pub struct At {}
279
280#[derive(Debug, PartialEq)]
282pub struct TaskConfiguration {
283 pub name: Id,
284 pub priority: u32,
285 pub interval: Option<Duration>,
287}
288
289#[derive(PartialEq, Clone, Debug)]
290pub enum Constant {
291 IntegerLiteral(i128),
293 RealLiteral(Float),
294 CharacterString(),
295 Duration(Duration),
296 TimeOfDay(),
297 Date(),
298 DateAndTime(),
299}
300
301#[derive(PartialEq, Clone)]
302pub enum Initializer {
303 Simple(Constant),
304 Subrange(),
305 Enumerated(),
306 Array(),
307 InitializedStructure(),
308 SingleByteString(),
309 DoubleByteString(),
310}
311
312impl fmt::Debug for Initializer {
313 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
314 f.debug_struct("Initializer").finish()
315 }
316}
317
318#[derive(PartialEq, Clone, Debug)]
319pub struct EnumeratedTypeInitializer {
320 pub type_name: Id,
321 pub initial_value: Option<Id>,
322}
323
324#[derive(PartialEq, Clone, Debug)]
325pub struct EnumeratedValuesInitializer {
326 pub values: Vec<Id>,
327 pub initial_value: Option<Id>,
328 pub position: SourceLoc,
329}
330
331#[derive(PartialEq, Clone, Debug)]
332pub struct FunctionBlockTypeInitializer {
333 pub type_name: Id,
334}
335
336#[derive(PartialEq, Clone, Debug)]
337pub enum TypeInitializer {
338 Simple {
339 type_name: Id,
340 initial_value: Option<Initializer>,
341 },
342 EnumeratedValues(EnumeratedValuesInitializer),
343 EnumeratedType(EnumeratedTypeInitializer),
344 FunctionBlock(FunctionBlockTypeInitializer),
345 Structure {
346 type_name: Id,
348 },
349 LateResolvedType(Id),
352}
353
354impl TypeInitializer {
355 pub fn simple_uninitialized(type_name: &str) -> TypeInitializer {
356 TypeInitializer::Simple {
357 type_name: Id::from(type_name),
358 initial_value: None,
359 }
360 }
361
362 pub fn simple(type_name: &str, value: Initializer) -> TypeInitializer {
363 TypeInitializer::Simple {
364 type_name: Id::from(type_name),
365 initial_value: Some(value),
366 }
367 }
368
369 pub fn enumerated_values(
370 values: Vec<Id>,
371 initial_value: Option<Id>,
372 position: SourceLoc,
373 ) -> TypeInitializer {
374 TypeInitializer::EnumeratedValues(EnumeratedValuesInitializer {
375 values: values,
376 initial_value: initial_value,
377 position: position,
378 })
379 }
380}
381
382#[derive(Debug, PartialEq, Clone)]
383pub enum LocationPrefix {
384 I,
385 Q,
386 M,
387}
388
389impl LocationPrefix {
390 pub fn from_char(l: char) -> LocationPrefix {
391 match l {
392 'I' => return LocationPrefix::I,
393 'Q' => return LocationPrefix::Q,
394 'M' => return LocationPrefix::M,
395 _ => panic!(),
397 }
398 }
399}
400
401#[derive(Debug, PartialEq, Clone)]
402pub enum SizePrefix {
403 Nil,
404 X,
405 B,
406 W,
407 D,
408 L,
409}
410
411impl SizePrefix {
412 pub fn from_char(s: char) -> SizePrefix {
413 match s {
414 'X' => return SizePrefix::X,
415 'B' => return SizePrefix::B,
416 'W' => return SizePrefix::W,
417 'D' => return SizePrefix::D,
418 'L' => return SizePrefix::L,
419 _ => panic!(),
421 }
422 }
423}
424
425#[derive(Debug, PartialEq, Clone)]
426pub enum StorageClass {
427 Unspecified,
430 Constant,
431 Retain,
433 NonRetain,
435}
436
437#[derive(Debug, PartialEq)]
439pub struct ResourceDeclaration {
440 pub name: Id,
442 pub resource: Id,
444 pub global_vars: Vec<Declaration>,
448 pub tasks: Vec<TaskConfiguration>,
450 pub programs: Vec<ProgramConfiguration>,
455}
456
457#[derive(Debug, PartialEq)]
458pub struct ProgramConfiguration {
459 pub name: Id,
460 pub task_name: Option<Id>,
461 pub type_name: Id,
462}
463
464#[derive(Debug, PartialEq)]
465pub struct ConfigurationDeclaration {
466 pub name: Id,
467 pub global_var: Vec<Declaration>,
468 pub resource_decl: Vec<ResourceDeclaration>,
469}
470
471#[derive(Debug, PartialEq)]
472pub struct EnumerationDeclaration {
473 pub name: Id,
474 pub spec: EnumeratedSpecificationKind,
476 pub default: Option<Id>,
477}
478
479#[derive(Debug, PartialEq)]
480pub struct EnumeratedSpecificationValues {
481 pub ids: Vec<Id>,
482 pub position: SourceLoc,
483}
484
485#[derive(Debug, PartialEq)]
486pub enum EnumeratedSpecificationKind {
487 TypeName(Id),
488 Values(EnumeratedSpecificationValues),
493}
494
495impl EnumeratedSpecificationKind {
496 pub fn values(values: Vec<Id>, position: SourceLoc) -> EnumeratedSpecificationKind {
497 EnumeratedSpecificationKind::Values(EnumeratedSpecificationValues {
498 ids: values,
499 position: position,
500 })
501 }
502}
503
504#[derive(PartialEq, Clone)]
505pub struct DirectVariable {
506 pub location: LocationPrefix,
507 pub size: SizePrefix,
508 pub address: Vec<u32>,
509}
510
511impl fmt::Debug for DirectVariable {
512 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
513 f.debug_struct("DirectVariable")
514 .field("location", &self.location)
515 .field("size", &self.size)
516 .finish()
517 }
518}
519
520impl fmt::Display for DirectVariable {
521 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
522 f.debug_struct("DirectVariable")
523 .field("location", &self.location)
524 .field("size", &self.size)
525 .finish()
526 }
527}
528
529#[derive(Debug, PartialEq, Clone)]
530pub struct Sfc {
531 pub networks: Vec<Network>,
532}
533
534#[derive(Debug, PartialEq, Clone)]
535pub struct Statements {
536 pub body: Vec<StmtKind>,
537}
538
539#[derive(Debug, PartialEq, Clone)]
540pub enum FunctionBlockBody {
541 Sfc(Sfc),
542 Statements(Statements),
543 Empty(),
548}
549
550impl FunctionBlockBody {
551 pub fn stmts(stmts: Vec<StmtKind>) -> FunctionBlockBody {
552 FunctionBlockBody::Statements(Statements { body: stmts })
553 }
554
555 pub fn sfc(networks: Vec<Network>) -> FunctionBlockBody {
556 FunctionBlockBody::Sfc(Sfc { networks: networks })
557 }
558
559 pub fn empty() -> FunctionBlockBody {
560 FunctionBlockBody::Empty()
561 }
562}
563
564#[derive(Debug, PartialEq, Clone)]
565pub struct FunctionDeclaration {
566 pub name: Id,
567 pub return_type: Id,
568 pub inputs: Vec<VarInitDecl>,
570 pub outputs: Vec<VarInitDecl>,
571 pub inouts: Vec<VarInitDecl>,
572 pub vars: Vec<VarInitDecl>,
573 pub externals: Vec<VarInitDecl>,
574 pub body: Vec<StmtKind>,
576}
577
578#[derive(Debug, PartialEq, Clone)]
579pub struct FunctionBlockDeclaration {
580 pub name: Id,
581 pub inputs: Vec<VarInitDecl>,
582 pub outputs: Vec<VarInitDecl>,
583 pub inouts: Vec<VarInitDecl>,
584 pub vars: Vec<VarInitDecl>,
585 pub externals: Vec<VarInitDecl>,
586 pub body: FunctionBlockBody,
588}
589
590#[derive(Debug, PartialEq)]
591pub struct ProgramDeclaration {
592 pub type_name: Id,
593 pub inputs: Vec<VarInitDecl>,
594 pub outputs: Vec<VarInitDecl>,
595 pub inouts: Vec<VarInitDecl>,
596 pub vars: Vec<VarInitDecl>,
597 pub body: FunctionBlockBody,
601}
602
603#[derive(Debug, PartialEq)]
604pub struct Library {
605 pub elems: Vec<LibraryElement>,
606}
607
608impl Library {
609 pub fn new(elems: Vec<LibraryElement>) -> Self {
610 Library { elems: elems }
611 }
612}