Skip to content

Commit

Permalink
work on validations
Browse files Browse the repository at this point in the history
  • Loading branch information
klpanagi committed Dec 15, 2024
1 parent 5d756e0 commit b864acd
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 117 deletions.
70 changes: 0 additions & 70 deletions examples/complex_goal/target.goal

This file was deleted.

2 changes: 0 additions & 2 deletions goal_dsl/codegen.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,6 @@ def generate(model_fpath: str,
wgoals = scenario.goals

set_defaults(scenario, broker, wgoals)
# report_broker(broker)
# report_goals(scenario)

goals = [goal.goal for goal in wgoals]

Expand Down
2 changes: 1 addition & 1 deletion goal_dsl/grammar/entity.tx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Entity:
(
('type:' etype=EntityType)
('topic:' topic=STRING)?
('source:' broker=EntitySource)
('source:' source=EntitySource)
('description:' description=STRING)?
('freq:' freq=NUMBER)?
('attributes:' '-' attributes*=Attribute['-'])
Expand Down
130 changes: 86 additions & 44 deletions goal_dsl/language.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,11 @@
from os.path import join
from textx import metamodel_from_file, get_children_of_type, metamodel_for_language, get_location
import textx.scoping.providers as scoping_providers
from textx import language
from textx import language, get_model
import statistics

from goal_dsl.definitions import THIS_DIR, MODEL_REPO_PATH, BUILTIN_MODELS

# CURRENT_FPATH = pathlib.Path(__file__).parent.resolve()


class PrimitiveDataType(object):
"""
Expand Down Expand Up @@ -43,25 +41,99 @@ def __str__(self):
CUSTOM_CLASSES = [
]


def class_provider(name):
classes = dict(map(lambda x: (x.__name__, x), CUSTOM_CLASSES))
return classes.get(name)


def time_obj_processor(t):
if t.hour > 24 or t.hour < 0:
raise TextXSemanticError("Time.hours must be in range [0, 24]")
if t.minute > 60 or t.minute < 0:
raise TextXSemanticError("Time.minutes must be in range [0, 60]")
if t.second > 60 or t.second < 0:
raise TextXSemanticError("Time.seconds must be in range [0, 60]")


def process_time_class(model):
types_time = get_children_of_type("Time", model)
for t in types_time:
if t.hour > 24 or t.hour < 0:
raise TextXSemanticError("Time.hours must be in range [0, 24]")
if t.minute > 60 or t.minute < 0:
raise TextXSemanticError("Time.minutes must be in range [0, 60]")
if t.second > 60 or t.second < 0:
raise TextXSemanticError("Time.seconds must be in range [0, 60]")


def verify_broker_names(model):
_ids = []
brokers = get_children_of_type("MQTTBroker", model)
brokers += get_children_of_type("AMQPBroker", model)
brokers += get_children_of_type("RedisBroker", model)
for b in brokers:
if b.name in _ids:
raise TextXSemanticError(
f"Broker with name <{b.name}> already exists", **get_location(b)
)
_ids.append(b.name)


def verify_entity_names(model):
_ids = []
entities = get_children_of_type("Entity", model)
for e in entities:
if e.name in _ids:
raise TextXSemanticError(
f"Entity with name <{e.name}> already exists", **get_location(e)
)
_ids.append(e.name)
verify_entity_attrs(e)


def verify_entity_attrs(entity):
_ids = []
for attr in entity.attributes:
if attr.name in _ids:
raise TextXSemanticError(
f"Entity attribute <{attr.name}> already exists", **get_location(attr)
)
_ids.append(attr.name)


def model_proc(model, metamodel):
pass
process_time_class(model)
verify_entity_names(model)
verify_broker_names(model)


def condition_processor(plot):
pass
def condition_processor(cond):
# Adds a cond.cond_expr property to the Condition instance
print("AAAAAS")
build_cond_expr(cond)
print(cond.cond_expr)


def nid_processor(nid):
nid = nid.replace("\n", "")
return nid


obj_processors = {
'Condition': condition_processor
# 'Condition': condition_processor,
'ConditionList': condition_processor,
# 'ConditionGroup': condition_processor,
# 'PrimitiveCondition': condition_processor,
# 'AdvancedCondition': condition_processor,
# 'BoolCondition': condition_processor,
# 'TimeCondition': condition_processor,
# 'NumericCondition': condition_processor,
# 'StringCondition': condition_processor,
# 'ListCondition': condition_processor,
# 'DictCondition': condition_processor,
# 'InRangeCondition': condition_processor,
# 'MathExpression': condition_processor,
}


Expand Down Expand Up @@ -114,7 +186,7 @@ def build_model(model_path):
model = mm.model_from_file(model_path) # Parse the model from the file
conds = get_top_level_condition(model) # Get the top-level conditions from the model
for cond in conds:
build_cond_expr(cond, model) # Build the condition expressions for each top-level condition
build_cond_expr(cond) # Build the condition expressions for each top-level condition
return model # Return the built model


Expand Down Expand Up @@ -142,8 +214,8 @@ def get_model_goals(model):
return goals


def build_cond_expr(cond, model):
cond_def = get_cond_definition(cond, model)
def build_cond_expr(cond):
cond_def = get_cond_definition(cond)
cond.cond_expr = cond_def
transform_cond(cond)

Expand All @@ -170,9 +242,10 @@ def is_float(string):
return False


def get_cond_definition(cond, model):
line_start, col_start = model._tx_parser.pos_to_linecol(cond._tx_position)
line_end, col_end = model._tx_parser.pos_to_linecol(cond._tx_position_end)
def get_cond_definition(cond):
model = get_model(cond)
line_start, _ = model._tx_parser.pos_to_linecol(cond._tx_position)
line_end, _ = model._tx_parser.pos_to_linecol(cond._tx_position_end)
loc = get_location(cond)
f = open(loc["filename"])
lines = f.readlines()
Expand All @@ -181,37 +254,6 @@ def get_cond_definition(cond, model):
return cond_def


def evaluate_cond(cond):
# Check if condition has been build using build_expression
if cond.cond_expr not in (None, ''):
# Evaluate condition providing the textX model as global context for evaluation
try:
entities = {}
# print(entities['system_clock'].attributes_dict['time'].value.to_int())
print(f"Evaluate Condition: {cond.cond_expr}")
if eval(
cond.cond_expr,
{
'entities': entities
},
{
'std': statistics.stdev,
'var': statistics.variance,
'mean': statistics.mean,
'min': min,
'max': max,
}
):
return True, f"{cond.parent.name}: triggered."
else:
return False, f"{cond.parent.name}: not triggered."
except Exception as e:
print(e)
return False, f"{cond.parent.name}: not triggered."
else:
return False, f"{cond.parent.name}: condition not built."


@language('goal_dsl', '*.goal')
def goaldsl_language():
"Goal-driven CPS Behavior Verification language"
Expand Down

0 comments on commit b864acd

Please sign in to comment.