Skip to content

Commit 0958335

Browse files
authored
Merge pull request #27 from NACLab/dev
Dev
2 parents 7c08615 + 32c9490 commit 0958335

20 files changed

+936
-551
lines changed

ngcsimlib/__init__.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from . import controller
33
from . import commands
44

5-
import argparse, os, warnings, json
5+
import argparse, os, json
66
from types import SimpleNamespace
77
from importlib import import_module
88
from ngcsimlib.configManager import init_config, get_config
@@ -17,9 +17,9 @@ def preload_modules(path=None):
1717
if path is None:
1818
module_config = get_config("modules")
1919
if module_config is None:
20-
module_path = "json_files/modules.json"
20+
module_path = None
2121
else:
22-
module_path = module_config.get("module_path", "json_files/modules.json")
22+
module_path = module_config.get("module_path", None)
2323

2424
if module_path is None:
2525
return
@@ -37,16 +37,16 @@ def preload_modules(path=None):
3737

3838
for module in modules:
3939
mod = import_module(module.absolute_path)
40-
utils._Loaded_Modules[module.absolute_path] = mod
40+
utils.modules._Loaded_Modules[module.absolute_path] = mod
4141

4242
for attribute in module.attributes:
4343
atr = getattr(mod, attribute.name)
44-
utils._Loaded_Attributes[attribute.name] = atr
44+
utils.modules._Loaded_Attributes[attribute.name] = atr
4545

46-
utils._Loaded_Attributes[".".join([module.absolute_path, attribute.name])] = atr
46+
utils.modules._Loaded_Attributes[".".join([module.absolute_path, attribute.name])] = atr
4747
if hasattr(attribute, "keywords"):
4848
for keyword in attribute.keywords:
49-
utils._Loaded_Attributes[keyword] = atr
49+
utils.modules._Loaded_Attributes[keyword] = atr
5050

5151
utils.set_loaded(True)
5252

ngcsimlib/compartment.py

Lines changed: 45 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,26 @@
11
from ngcsimlib.operations import BaseOp, overwrite
22
from ngcsimlib.utils import Set_Compartment_Batch, get_current_path
3+
from ngcsimlib.logger import error
34
import uuid
45

56

67
class Compartment:
78
"""
8-
Compartments in ngcsimlib are container objects for storing the stateful values of components. Compartments are
9-
tracked globaly and are automatically linked to components and methods during compiling to allow for stateful
10-
mechanics to be run without the need for the class object. Compartments also provide an entry and exit point for
11-
values inside of components allowing for cables to be connected for sending and receiving values.
9+
Compartments in ngcsimlib are container objects for storing the stateful
10+
values of components. Compartments are
11+
tracked globaly and are automatically linked to components and methods
12+
during compiling to allow for stateful
13+
mechanics to be run without the need for the class object. Compartments
14+
also provide an entry and exit point for
15+
values inside of components allowing for cables to be connected for
16+
sending and receiving values.
1217
"""
1318

1419
@classmethod
1520
def is_compartment(cls, obj):
1621
"""
17-
A method for verifying if a provided object is a compartment. All compartments have `_is_compartment` set to
22+
A method for verifying if a provided object is a compartment. All
23+
compartments have `_is_compartment` set to
1824
true by default and this is
1925
2026
Args:
@@ -25,14 +31,18 @@ def is_compartment(cls, obj):
2531
"""
2632
return hasattr(obj, "_is_compartment")
2733

28-
def __init__(self, initial_value=None, static=False):
34+
def __init__(self, initial_value=None, static=False, is_input=False):
2935
"""
30-
Builds a compartment to be used inside a component. It is important to note that building compartments
31-
outside of components may cause unexpected behavior as components interact with their compartments during
36+
Builds a compartment to be used inside a component. It is important
37+
to note that building compartments
38+
outside of components may cause unexpected behavior as components
39+
interact with their compartments during
3240
construction to finish initializing them.
3341
Args:
34-
initial_value: The initial value of the compartment. As a general practice it is a good idea to
35-
provide a value that is similar to the values that will normally be stored here, such as an array of
42+
initial_value: The initial value of the compartment. As a general
43+
practice it is a good idea to
44+
provide a value that is similar to the values that will
45+
normally be stored here, such as an array of
3646
zeros of the correct length. (default: None)
3747
3848
static: a flag to lock a compartment to be static (default: False)
@@ -44,11 +54,14 @@ def __init__(self, initial_value=None, static=False):
4454
self._uid = uuid.uuid4()
4555
self.name = None
4656
self.path = None
57+
self.is_input = is_input
58+
self._is_destination = False
4759

4860
def _setup(self, current_component, key):
4961
"""
50-
Finishes initializing the compartment, called by the component that builds the compartment
51-
(Handel automatically)
62+
Finishes initializing the compartment, called by the component that
63+
builds the compartment
64+
(Handled automatically)
5265
"""
5366
self.__add_connection = current_component.add_connection
5467
self.name = current_component.name + "/" + key
@@ -57,14 +70,15 @@ def _setup(self, current_component, key):
5770

5871
def set(self, value):
5972
"""
60-
Sets the value of the compartment if it not static (Raises a runtime error)
73+
Sets the value of the compartment if it not static (Raises a runtime
74+
error)
6175
Args:
6276
value: the new value to be set
6377
"""
6478
if not self._static:
6579
self.value = value
6680
else:
67-
raise RuntimeError("Can not assign value to static compartment")
81+
error("Can not assign value to static compartment")
6882

6983
def clamp(self, value):
7084
"""
@@ -88,8 +102,10 @@ def __str__(self):
88102

89103
def __lshift__(self, other) -> None:
90104
"""
91-
Overrides the left shift operation to be used for wiring compartments into one another
92-
if other is not an Operation it will create an overwrite operation with other as the argument,
105+
Overrides the left shift operation to be used for wiring compartments
106+
into one another
107+
if other is not an Operation it will create an overwrite operation
108+
with other as the argument,
93109
otherwise it will use the provided operation
94110
95111
Args:
@@ -102,3 +118,16 @@ def __lshift__(self, other) -> None:
102118
op = overwrite(other)
103119
op.set_destination(self)
104120
self.__add_connection(op)
121+
122+
self._is_destination = True
123+
124+
def is_wired(self):
125+
"""
126+
Returns: if this compartment not marked as an input, or is marked and
127+
has an input
128+
129+
"""
130+
if not self.is_input:
131+
return True
132+
133+
return self._is_destination

ngcsimlib/compilers/command_compiler.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,18 +66,18 @@ def _compile(compile_key, components):
6666

6767
for c_name, component in components.items():
6868
_, outs, args, params, comps = resolvers[c_name]
69-
for _, a in args:
69+
for a in args:
7070
if a not in needed_args:
7171
needed_args.append(a)
7272

7373
for connection in component.connections:
74-
inputs, outputs = parse_connection(connection)
74+
inputs, _ = parse_connection(connection)
7575
ncs = [str(i) for i in inputs]
7676
for nc in ncs:
7777
if nc not in needed_comps:
7878
needed_comps.append(nc)
7979

80-
for _, comp in comps:
80+
for comp in comps:
8181
path = str(component.__dict__[comp].path)
8282
if path not in needed_comps:
8383
needed_comps.append(path)

ngcsimlib/compilers/component_compiler.py

Lines changed: 35 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,24 @@
11
"""
22
This is the file that contains the code to compile a component for a command.
33
4-
There are two primary method provided in this file. The first of them is the parse command. This command is designed
5-
to provide everything that is needed to compile the component down without actually doing so. This is generally used
6-
by the command compiler to produce a working list of everything that is needed prior to the actual compiling of all
7-
components.
8-
9-
The second method that is provided in this file the actual method for compiling the component. This method takes in
10-
the component, the parsed component, and the global argument order for the compiled method. The result of this method
11-
is the execution order needed to be run to compute the compiled method over this component. This execution order is
12-
consistent with the same pattern used by the command compiler.
4+
There are two primary methods provided in this file. The first of them is the
5+
parse command. This command is designed to provide everything that is needed
6+
to compile the component down without actually doing so. This is generally
7+
used by the command compiler to produce a working list of everything that is
8+
needed prior to the actual compiling of all components.
9+
10+
The second method that is provided in this file the actual method for
11+
compiling the component. This method takes in the component, the parsed
12+
component, and the global argument order for the compiled method. The result
13+
of this method is the execution order needed to be run to compute the
14+
compiled method over this component. This execution order is consistent with
15+
the same pattern used by the command compiler.
1316
1417
"""
1518
from ngcsimlib.compilers.op_compiler import compile as op_compile
1619
from ngcsimlib.utils import get_resolver
1720
from ngcsimlib.compartment import Compartment
21+
from ngcsimlib.logger import critical
1822

1923

2024
def parse(component, compile_key):
@@ -33,26 +37,36 @@ def parse(component, compile_key):
3337
the compartments needed
3438
3539
"""
36-
(pure_fn, output_compartments), (args, parameters, compartments, parse_varnames) = \
40+
(pure_fn, output_compartments), (
41+
args, parameters, compartments, parse_varnames) = \
3742
get_resolver(component.__class__, compile_key)
3843

3944
if parse_varnames:
4045
args = []
4146
parameters = []
4247
compartments = []
43-
varnames = pure_fn.__func__.__code__.co_varnames[:pure_fn.__func__.__code__.co_argcount]
44-
45-
for idx, n in enumerate(varnames):
46-
if n not in component.__dict__.keys():
47-
args.append((idx, n))
48-
elif Compartment.is_compartment(component.__dict__[n]):
49-
compartments.append((idx, n))
48+
varnames = pure_fn.__func__.__code__.co_varnames[
49+
:pure_fn.__func__.__code__.co_argcount]
50+
51+
for name in varnames:
52+
if name not in component.__dict__.keys():
53+
args.append(name)
54+
elif Compartment.is_compartment(component.__dict__[name]):
55+
compartments.append(name)
5056
else:
51-
parameters.append((idx, n))
57+
parameters.append(name)
5258

5359
if output_compartments is None:
5460
output_compartments = compartments[:]
5561

62+
for comp in output_compartments:
63+
if not Compartment.is_compartment(component.__dict__[comp]):
64+
critical(
65+
f"When attempting to compile "
66+
f"\"{component.__class__.__name__}\", with the key "
67+
f"\"{compile_key}\", the located output value \"{comp}\" "
68+
f"is not a compartment object.")
69+
5670
return (pure_fn, output_compartments, args, parameters, compartments)
5771

5872

@@ -76,13 +90,13 @@ def compile(component, resolver):
7690
exc_order.append(op_compile(connection))
7791

7892
### Component resolve
79-
comp_ids = [str(component.__dict__[comp].path) for _, comp in comps]
93+
comp_ids = [str(component.__dict__[comp].path) for comp in comps]
8094
out_ids = [str(component.__dict__[comp].path) for comp in outs]
8195

82-
funParams = {narg: component.__dict__[narg] for _, narg in (list(params))}
96+
funParams = {narg: component.__dict__[narg] for narg in params}
8397

8498
def compiled(**kwargs):
85-
funArgs = {narg: kwargs.get(narg) for _, narg in (list(_args))}
99+
funArgs = {narg: kwargs.get(narg) for narg in _args}
86100
funComps = {narg.split('/')[-1]: kwargs.get(narg) for narg in comp_ids}
87101

88102
return pure_fn.__func__(**funParams, **funArgs, **funComps)

ngcsimlib/compilers/op_compiler.py

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,20 @@
11
"""
2-
This file contains the logic needed to compile down an operation and produce an execution order that is compatible
3-
with the order found in the command compiler.
4-
5-
This file contains two methods a parse and a compile method for operations. The parse method returns the metadata
6-
needed by the command compiler to know what values the operation will use.
7-
8-
The second one is the compile method which returns the execution order for the compile operation. It is important to
9-
know that all operation should have an `is_compilable` flag set to true if they are compilable. Some operations such
10-
as the `add` operation are not compilable as their resolve method contains execution logic that will not be captured
11-
by the compiled command.
2+
This file contains the logic needed to compile down an operation and produce
3+
an execution order that is compatible with the order found in the command
4+
compiler.
5+
6+
This file contains two methods a parse and a compile method for operations.
7+
The parse method returns the metadata needed by the command compiler to know
8+
what values the operation will use.
9+
10+
The second one is the compile method which returns the execution order for
11+
the compile operation. It is important to know that all operation should have
12+
an `is_compilable` flag set to true if they are compilable. Some operations
13+
such as the `add` operation are not compilable as their resolve method
14+
contains execution logic that will not be captured by the compiled command.
1215
"""
1316
from ngcsimlib.operations.baseOp import BaseOp
17+
from ngcsimlib.compartment import Compartment
1418
from ngcsimlib.logger import critical
1519

1620

@@ -24,19 +28,31 @@ def parse(op):
2428
Returns:
2529
the parsed operation
2630
"""
27-
assert op.is_compilable
31+
assert op.is_compilable, ("Trying to compile an operation that is flagged "
32+
"as not compilable")
33+
if op.destination is not None and not Compartment.is_compartment(
34+
op.destination):
35+
critical(
36+
f"An operation that is being compiled has an invalid destination,"
37+
f" {op.destination}")
38+
2839
inputs = []
2940
for s in op.sources:
3041
if isinstance(s, BaseOp):
3142
needed_inputs, dest = parse(s)
3243
if dest is not None:
3344
critical(
34-
"An operation with a destination compartment is being used as a source object for another "
45+
"An operation with a destination compartment is being "
46+
"used as a source object for another "
3547
"operation")
3648
for inp in needed_inputs:
3749
if inp not in inputs:
3850
inputs.append(inp)
3951
else:
52+
if not Compartment.is_compartment(s):
53+
critical(
54+
"An operation has source that is not a compartment or "
55+
"instance of BaseOp")
4056
inputs.append(s.path)
4157

4258
return inputs, op.destination.name if op.destination is not None else None

0 commit comments

Comments
 (0)