Skip to content

Commit 1cd7bea

Browse files
committed
Implement advanced structs and global instances
- Allow structs to inherit from a parent struct - Add the Instance component which can be interpreted as a global variable
1 parent 9591b70 commit 1cd7bea

File tree

9 files changed

+3463
-797
lines changed

9 files changed

+3463
-797
lines changed

pfdl_grammar/PFDLParser.g4

+21-3
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,35 @@ options {
55
}
66

77
program:
8-
(NL | struct | task)* EOF;
8+
program_statement* EOF;
9+
10+
program_statement:
11+
NL | struct | task | instance;
912

1013
struct:
11-
STRUCT STARTS_WITH_UPPER_C_STR INDENT (variable_definition NL+)+ DEDENT END;
14+
STRUCT STARTS_WITH_UPPER_C_STR (COLON struct_id)? INDENT (
15+
variable_definition NL+
16+
)+ DEDENT END;
17+
18+
struct_id: STARTS_WITH_UPPER_C_STR;
1219

1320
task:
14-
TASK STARTS_WITH_LOWER_C_STR INDENT task_in? statement+ task_out? DEDENT END;
21+
TASK STARTS_WITH_LOWER_C_STR INDENT task_in? taskStatement+ task_out? DEDENT END;
22+
23+
instance:
24+
struct_id STARTS_WITH_LOWER_C_STR INDENT (
25+
attribute_assignment NL
26+
)+ DEDENT END;
1527

1628
task_in:
1729
IN INDENT (variable_definition NL+)+ DEDENT;
1830

1931
task_out:
2032
OUT INDENT (STARTS_WITH_LOWER_C_STR NL+)+ DEDENT;
2133

34+
taskStatement:
35+
statement;
36+
2237
statement:
2338
service_call
2439
| task_call
@@ -80,6 +95,9 @@ primitive:
8095
attribute_access:
8196
STARTS_WITH_LOWER_C_STR (DOT STARTS_WITH_LOWER_C_STR array?)+;
8297

98+
attribute_assignment:
99+
STARTS_WITH_LOWER_C_STR COLON (value | json_object);
100+
83101
array:
84102
ARRAY_LEFT (INTEGER | STARTS_WITH_LOWER_C_STR)? ARRAY_RIGHT;
85103

pfdl_scheduler/model/instance.py

+94
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
# Copyright The PFDL Contributors
2+
#
3+
# Licensed under the MIT License.
4+
# For details on the licensing terms, see the LICENSE file.
5+
# SPDX-License-Identifier: MIT
6+
7+
"""Contains Instance class."""
8+
9+
# standard libraries
10+
import uuid
11+
from numbers import Number
12+
from typing import Dict, Union
13+
14+
# 3rd party libs
15+
from antlr4.ParserRuleContext import ParserRuleContext
16+
17+
# local sources
18+
## PFDL base sources
19+
from pfdl_scheduler.validation.error_handler import ErrorHandler
20+
21+
22+
class Instance:
23+
"""Represents an Instance in the PFDL.
24+
25+
Attributes:
26+
name: A string representing the name of the Instance.
27+
attributes: A dict mapping the attribute names with their values.
28+
struct_name: A string refering to the Struct this Instance instanciates.
29+
context: ANTLR context object of this class.
30+
attribute_contexts: A dict that maps the attribute names to their ANTLR contexts.
31+
"""
32+
33+
def __init__(
34+
self,
35+
name: str = "",
36+
attributes: Dict[str, Union[str, Number, bool, "Instance"]] = None,
37+
struct_name: str = "",
38+
context: ParserRuleContext = None,
39+
) -> None:
40+
"""Initialize the object.
41+
42+
Args:
43+
name: A string representing the name of the Instance.
44+
attributes: A dict mapping the attribute names with their values.
45+
struct_name: A string refering to the Struct this Instance instanciates.
46+
context: ANTLR context object of this class.
47+
"""
48+
self.name: str = name
49+
50+
if attributes:
51+
self.attributes: Dict[str, Union[str, Number, bool, "Instance"]] = attributes
52+
else:
53+
self.attributes: Dict[str, Union[str, Number, bool, "Instance"]] = {}
54+
55+
self.struct_name: str = struct_name
56+
self.context: ParserRuleContext = context
57+
self.attribute_contexts: Dict = {}
58+
59+
@classmethod
60+
def from_json(
61+
cls,
62+
json_object: Dict,
63+
error_handler: ErrorHandler,
64+
struct_context: ParserRuleContext,
65+
instance_class="Instance",
66+
):
67+
return parse_json(json_object, error_handler, struct_context, instance_class)
68+
69+
70+
def parse_json(
71+
json_object: Dict,
72+
error_handler: ErrorHandler,
73+
instance_context: ParserRuleContext,
74+
instance_class=Instance,
75+
) -> Instance:
76+
"""Parses the JSON Struct initialization.
77+
78+
Returns:
79+
An Instance object representing the initialized instance.
80+
"""
81+
instance = instance_class()
82+
instance.context = instance_context
83+
for identifier, value in json_object.items():
84+
if isinstance(value, (int, str, bool)):
85+
instance.attributes[identifier] = value
86+
elif isinstance(value, list):
87+
if error_handler and instance_context:
88+
error_msg = "Array definition in JSON are not supported in the PFDL."
89+
error_handler.print_error(error_msg, context=instance_context)
90+
elif isinstance(value, dict):
91+
inner_struct = parse_json(value, error_handler, instance_context)
92+
instance.attributes[identifier] = inner_struct
93+
94+
return instance

pfdl_scheduler/model/process.py

+8
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from typing import Dict
1212

1313
# local sources
14+
from pfdl_scheduler.model.instance import Instance
1415
from pfdl_scheduler.model.struct import Struct
1516
from pfdl_scheduler.model.task import Task
1617

@@ -25,20 +26,23 @@ class Process:
2526
Attributes:
2627
structs: A dict for mapping the Struct names to the Struct objects.
2728
task: A dict for mapping the Task names to the Task objects.
29+
instances: A dict for mappign the Instance names to the Instance objects.
2830
start_task_name: the name of the start task of the PFDL program (typically "productionTask").
2931
"""
3032

3133
def __init__(
3234
self,
3335
structs: Dict[str, Struct] = None,
3436
tasks: Dict[str, Task] = None,
37+
instances: Dict[str, Instance] = None,
3538
start_task_name: str = "productionTask",
3639
) -> None:
3740
"""Initialize the object.
3841
3942
Args:
4043
structs: A dict for mapping the Struct names to the Struct objects.
4144
tasks: A dict for mapping the Task names to the Task objects.
45+
instances: A dict for mappign the Instance names to the Instance objects.
4246
start_task_name: the name of the start task of the PFDL program (typically "productionTask").
4347
"""
4448
if structs:
@@ -49,4 +53,8 @@ def __init__(
4953
self.tasks: Dict[str, Task] = tasks
5054
else:
5155
self.tasks: Dict[str, Task] = {}
56+
if instances:
57+
self.instances: Dict[str, Task] = instances
58+
else:
59+
self.instances: Dict[str, Task] = {}
5260
self.start_task_name = start_task_name

pfdl_scheduler/model/struct.py

+6
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ class Struct:
3131
name: A string representing the name of the Struct.
3232
attributes: A dict which maps the attribute names to the defined type
3333
or a value (if its a instantiated struct).
34+
parent_struct_name: A string representin the identifier of the parent struct
35+
from which this struct inherits the attributes
3436
context: ANTLR context object of this class.
3537
context_dict: Maps other attributes with ANTLR context objects.
3638
"""
@@ -39,6 +41,7 @@ def __init__(
3941
self,
4042
name: str = "",
4143
attributes: Dict[str, Union[str, Array, "Struct"]] = None,
44+
parent_struct_name: str = "",
4245
context: ParserRuleContext = None,
4346
) -> None:
4447
"""Initialize the object.
@@ -47,13 +50,16 @@ def __init__(
4750
name: A string representing the name of the Struct.
4851
attributes: A dict which maps the attribute names to the defined type
4952
or a value (if its a instantiated struct).
53+
parent_struct_name: A string representin the identifier of the parent struct
54+
from which this struct inherits the attributes
5055
context: ANTLR context object of this class.
5156
"""
5257
self.name: str = name
5358
if attributes:
5459
self.attributes: Dict[str, Union[str, Array, "Struct"]] = attributes
5560
else:
5661
self.attributes: Dict[str, Union[str, Array, "Struct"]] = {}
62+
self.parent_struct_name: str = parent_struct_name
5763
self.context: ParserRuleContext = context
5864
self.context_dict: Dict = {}
5965

0 commit comments

Comments
 (0)