Skip to content

Commit

Permalink
Implement advanced structs and global instances
Browse files Browse the repository at this point in the history
- Allow structs to inherit from a parent struct
- Add the Instance component which can be interpreted as a global variable
  • Loading branch information
maxhoerstr committed Oct 15, 2024
1 parent 9591b70 commit 1cd7bea
Show file tree
Hide file tree
Showing 9 changed files with 3,463 additions and 797 deletions.
24 changes: 21 additions & 3 deletions pfdl_grammar/PFDLParser.g4
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,35 @@ options {
}

program:
(NL | struct | task)* EOF;
program_statement* EOF;

program_statement:
NL | struct | task | instance;

struct:
STRUCT STARTS_WITH_UPPER_C_STR INDENT (variable_definition NL+)+ DEDENT END;
STRUCT STARTS_WITH_UPPER_C_STR (COLON struct_id)? INDENT (
variable_definition NL+
)+ DEDENT END;

struct_id: STARTS_WITH_UPPER_C_STR;

task:
TASK STARTS_WITH_LOWER_C_STR INDENT task_in? statement+ task_out? DEDENT END;
TASK STARTS_WITH_LOWER_C_STR INDENT task_in? taskStatement+ task_out? DEDENT END;

instance:
struct_id STARTS_WITH_LOWER_C_STR INDENT (
attribute_assignment NL
)+ DEDENT END;

task_in:
IN INDENT (variable_definition NL+)+ DEDENT;

task_out:
OUT INDENT (STARTS_WITH_LOWER_C_STR NL+)+ DEDENT;

taskStatement:
statement;

statement:
service_call
| task_call
Expand Down Expand Up @@ -80,6 +95,9 @@ primitive:
attribute_access:
STARTS_WITH_LOWER_C_STR (DOT STARTS_WITH_LOWER_C_STR array?)+;

attribute_assignment:
STARTS_WITH_LOWER_C_STR COLON (value | json_object);

array:
ARRAY_LEFT (INTEGER | STARTS_WITH_LOWER_C_STR)? ARRAY_RIGHT;

Expand Down
94 changes: 94 additions & 0 deletions pfdl_scheduler/model/instance.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# Copyright The PFDL Contributors
#
# Licensed under the MIT License.
# For details on the licensing terms, see the LICENSE file.
# SPDX-License-Identifier: MIT

"""Contains Instance class."""

# standard libraries
import uuid
from numbers import Number
from typing import Dict, Union

# 3rd party libs
from antlr4.ParserRuleContext import ParserRuleContext

# local sources
## PFDL base sources
from pfdl_scheduler.validation.error_handler import ErrorHandler


class Instance:
"""Represents an Instance in the PFDL.
Attributes:
name: A string representing the name of the Instance.
attributes: A dict mapping the attribute names with their values.
struct_name: A string refering to the Struct this Instance instanciates.
context: ANTLR context object of this class.
attribute_contexts: A dict that maps the attribute names to their ANTLR contexts.
"""

def __init__(
self,
name: str = "",
attributes: Dict[str, Union[str, Number, bool, "Instance"]] = None,
struct_name: str = "",
context: ParserRuleContext = None,
) -> None:
"""Initialize the object.
Args:
name: A string representing the name of the Instance.
attributes: A dict mapping the attribute names with their values.
struct_name: A string refering to the Struct this Instance instanciates.
context: ANTLR context object of this class.
"""
self.name: str = name

if attributes:
self.attributes: Dict[str, Union[str, Number, bool, "Instance"]] = attributes
else:
self.attributes: Dict[str, Union[str, Number, bool, "Instance"]] = {}

self.struct_name: str = struct_name
self.context: ParserRuleContext = context
self.attribute_contexts: Dict = {}

@classmethod
def from_json(
cls,
json_object: Dict,
error_handler: ErrorHandler,
struct_context: ParserRuleContext,
instance_class="Instance",
):
return parse_json(json_object, error_handler, struct_context, instance_class)


def parse_json(
json_object: Dict,
error_handler: ErrorHandler,
instance_context: ParserRuleContext,
instance_class=Instance,
) -> Instance:
"""Parses the JSON Struct initialization.
Returns:
An Instance object representing the initialized instance.
"""
instance = instance_class()
instance.context = instance_context
for identifier, value in json_object.items():
if isinstance(value, (int, str, bool)):
instance.attributes[identifier] = value
elif isinstance(value, list):
if error_handler and instance_context:
error_msg = "Array definition in JSON are not supported in the PFDL."
error_handler.print_error(error_msg, context=instance_context)
elif isinstance(value, dict):
inner_struct = parse_json(value, error_handler, instance_context)
instance.attributes[identifier] = inner_struct

return instance
8 changes: 8 additions & 0 deletions pfdl_scheduler/model/process.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from typing import Dict

# local sources
from pfdl_scheduler.model.instance import Instance
from pfdl_scheduler.model.struct import Struct
from pfdl_scheduler.model.task import Task

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

def __init__(
self,
structs: Dict[str, Struct] = None,
tasks: Dict[str, Task] = None,
instances: Dict[str, Instance] = None,
start_task_name: str = "productionTask",
) -> None:
"""Initialize the object.
Args:
structs: A dict for mapping the Struct names to the Struct objects.
tasks: A dict for mapping the Task names to the Task objects.
instances: A dict for mappign the Instance names to the Instance objects.
start_task_name: the name of the start task of the PFDL program (typically "productionTask").
"""
if structs:
Expand All @@ -49,4 +53,8 @@ def __init__(
self.tasks: Dict[str, Task] = tasks
else:
self.tasks: Dict[str, Task] = {}
if instances:
self.instances: Dict[str, Task] = instances
else:
self.instances: Dict[str, Task] = {}
self.start_task_name = start_task_name
6 changes: 6 additions & 0 deletions pfdl_scheduler/model/struct.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ class Struct:
name: A string representing the name of the Struct.
attributes: A dict which maps the attribute names to the defined type
or a value (if its a instantiated struct).
parent_struct_name: A string representin the identifier of the parent struct
from which this struct inherits the attributes
context: ANTLR context object of this class.
context_dict: Maps other attributes with ANTLR context objects.
"""
Expand All @@ -39,6 +41,7 @@ def __init__(
self,
name: str = "",
attributes: Dict[str, Union[str, Array, "Struct"]] = None,
parent_struct_name: str = "",
context: ParserRuleContext = None,
) -> None:
"""Initialize the object.
Expand All @@ -47,13 +50,16 @@ def __init__(
name: A string representing the name of the Struct.
attributes: A dict which maps the attribute names to the defined type
or a value (if its a instantiated struct).
parent_struct_name: A string representin the identifier of the parent struct
from which this struct inherits the attributes
context: ANTLR context object of this class.
"""
self.name: str = name
if attributes:
self.attributes: Dict[str, Union[str, Array, "Struct"]] = attributes
else:
self.attributes: Dict[str, Union[str, Array, "Struct"]] = {}
self.parent_struct_name: str = parent_struct_name
self.context: ParserRuleContext = context
self.context_dict: Dict = {}

Expand Down
Loading

0 comments on commit 1cd7bea

Please sign in to comment.