Skip to content
This repository has been archived by the owner on Sep 12, 2024. It is now read-only.

Edges modified #170

Merged
merged 22 commits into from
Jan 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions examples/reference/connect_expressions.jac
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
node node_a{
has value:int;
}
walker Creator {
can create with `<root> entry;
can travel with `<root>|node_a entry;
}
edge MyEdge {
has val:int =5;
}
:walker:Creator:can:create{
end = <here>;
for i = 0 to i<7 by i+=1{
if i % 2==0{
end ++> end := node_a(value=i);
}
else{
end +:MyEdge:val=i:+> end := node_a(value=i+10);
}
}
}
:walker:Creator:can:travel{
for i in -:MyEdge:val<=6 :->{
print(i.value);
}
visit-->;
}
with entry{
<root> spawn Creator();
# print(<r>._jac_.gen_dot());
}
33 changes: 0 additions & 33 deletions examples/reference/data_spatial_references.jac
Original file line number Diff line number Diff line change
@@ -1,36 +1,3 @@
import:py random;

node MyNode {
has value: int;

}
edge MyEdge {
has val:int =5;
}
walker Walk {
#has count: int = 0;
can create with `<root> entry;
#can do_something with `<root> entry;
}

:walker:Walk:can:create{
for i=0 to i<5 by i+=1 {
<root> +:MyEdge:val=random.randint(1,10):+> MyNode(value=i+1);
<here> ++> MyNode(value=i+1);
}
visit -->;
}
# :walker:Walk:can:do_something{
# for i in -:MyEdge:val<=5 :->{
# print(i.val);
# }
# }


with entry {
<root> spawn Walk();
#<root>._jac_.gen_dot();

}


21 changes: 0 additions & 21 deletions examples/reference/data_spatial_references.py
Original file line number Diff line number Diff line change
@@ -1,22 +1 @@
"""
need to create some type of edge with fields

edge MyEdge {
has val:int =5;
}

node MyNode {
}

create 10 edges off of root

<root> +:MyEdge:val=randint(0, 10):+> MyNode()

5 of these

<root> ++> MyNode()

then we test the refs
for i in -:MyEdge:val<=5:->:
print i.val;
"""
2 changes: 1 addition & 1 deletion examples/reference/data_spatial_spawn_expressions.jac
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,5 @@ node node_a{
}

with entry{
:> Adder spawn <root>; # spawn will iniiate the walker Adder from root node
Adder() spawn <root>; # spawn will iniiate the walker Adder from root node
}
4 changes: 2 additions & 2 deletions examples/reference/data_spatial_walker_statements.jac
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@ walker walker_2{
visit -->;
}
:node:node_a:can:print_something -> str{
f"walker_1 entered to {<self>}"|>print;
print(f"walker_1 entered to {<self>}");
visit -->;
}

with entry{
:> walker_1 spawn <root>; #walker_1 statrt walking from root node
walker_1() spawn <root>; #walker_1 statrt walking from root node
<root> spawn walker_2(); #after walker_1 finish walking walker_2 start walking to nodes
}
11 changes: 3 additions & 8 deletions jaclang/compiler/passes/main/pyast_gen_pass.py
Original file line number Diff line number Diff line change
Expand Up @@ -2043,18 +2043,13 @@ def translate_edge_op_ref(self, loc: ast3.AST, node: ast.EdgeOpRef) -> ast3.AST:
node.filter_type.gen.py_ast
if node.filter_type
else self.sync(ast3.Constant(value=None)),
node.filter_cond.gen.py_ast
if node.filter_cond
else self.sync(ast3.Constant(value=None)),
],
keywords=[],
)
)
if node.filter_cond:
ret = self.sync(
ast3.Call(
func=node.filter_cond.gen.py_ast,
args=[ret],
keywords=[],
)
)
return ret

def exit_disconnect_op(self, node: ast.DisconnectOp) -> None:
Expand Down
54 changes: 37 additions & 17 deletions jaclang/core/construct.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,24 +40,45 @@ def connect_node(self, nd: NodeArchitype, edg: EdgeArchitype) -> NodeArchitype:
edg._jac_.attach(self.obj, nd)
return self.obj

# def edges_to_nodes(
# self, dir: EdgeDir, filter_type: Optional[type], filter_func: Optional[Callable]
# ) -> list[NodeArchitype]:
# """Get set of nodes connected to this node."""
# filter_func = filter_func if filter_func else lambda x: x
# ret_nodes: list[NodeArchitype] = []
# if dir in [EdgeDir.OUT]:
# edge_list = []
# for x in self.edges[EdgeDir.OUT]:
# if x._jac_.target and (not filter_type or isinstance(x, filter_type)):
# edge_list.append(x)
# new_edge = filter_func(edge_list)
# for i in new_edge:
# ret_nodes.append(i._jac_.target)
# elif dir in [EdgeDir.IN]:
# edge_list = []
# for i in self.edges[EdgeDir.IN]:
# if i._jac_.source and (not filter_type or isinstance(i, filter_type)):
# edge_list.append(i)
# new_edge = filter_func(edge_list)
# for i in new_edge:
# ret_nodes.append(i._jac_.source)
# return ret_nodes

def edges_to_nodes(
self, dir: EdgeDir, filter_type: Optional[type]
self, dir: EdgeDir, filter_type: Optional[type], filter_func: Optional[Callable]
) -> list[NodeArchitype]:
"""Get set of nodes connected to this node."""
ret_nodes: list[NodeArchitype] = []
if dir in [EdgeDir.OUT]:
for i in self.edges[EdgeDir.OUT]:
if i._jac_.target and (
not filter_type or isinstance(i._jac_.target, filter_type)
):
ret_nodes.append(i._jac_.target)
elif dir in [EdgeDir.IN]:
for i in self.edges[EdgeDir.IN]:
if i._jac_.source and (
not filter_type or isinstance(i._jac_.source, filter_type)
):
ret_nodes.append(i._jac_.source)
return ret_nodes
filter_func = filter_func or (lambda x: x)
edge_list = [
e
for e in self.edges[dir]
if getattr(e._jac_, "target" if dir == EdgeDir.OUT else "source", None)
and (not filter_type or isinstance(e, filter_type))
]
return [
getattr(e._jac_, "target" if dir == EdgeDir.OUT else "source")
for e in filter_func(edge_list)
]

def gen_dot(self, dot_file: Optional[str] = None) -> str:
"""Generate Dot file for visualizing nodes and edges."""
Expand All @@ -80,8 +101,7 @@ def gen_dot(self, dot_file: Optional[str] = None) -> str:
if dot_file:
with open(dot_file, "w") as f:
f.write(dot_content + "}")
else:
print(dot_content + "}")
return dot_content + "}"


@dataclass(eq=False)
Expand Down
11 changes: 9 additions & 2 deletions jaclang/plugin/default.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,10 +129,11 @@ def edge_ref(
node_obj: NodeArchitype,
dir: EdgeDir,
filter_type: Optional[type],
filter_func: Optional[Callable],
) -> list[NodeArchitype]:
"""Jac's apply_dir stmt feature."""
if isinstance(node_obj, NodeArchitype):
return node_obj._jac_.edges_to_nodes(dir, filter_type)
return node_obj._jac_.edges_to_nodes(dir, filter_type, filter_func)
else:
raise TypeError("Invalid node object")

Expand Down Expand Up @@ -192,7 +193,7 @@ def get_root() -> Architype:
def build_edge(
edge_dir: EdgeDir,
conn_type: Optional[Type[Architype]],
conn_assign: Optional[tuple],
conn_assign: Optional[tuple[tuple, tuple]],
) -> Architype:
"""Jac's root getter."""
conn_type = conn_type if conn_type else GenericEdge
Expand All @@ -201,4 +202,10 @@ def build_edge(
edge._jac_.dir = edge_dir
else:
raise TypeError("Invalid edge object")
if conn_assign:
for fld, val in zip(conn_assign[0], conn_assign[1]):
if hasattr(edge, fld):
setattr(edge, fld, val)
else:
raise ValueError(f"Invalid attribute: {fld}")
return edge
5 changes: 3 additions & 2 deletions jaclang/plugin/feature.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,11 @@ def edge_ref(
node_obj: NodeArchitype,
dir: EdgeDir,
filter_type: Optional[type],
filter_func: Optional[Callable],
) -> list[NodeArchitype]:
"""Jac's apply_dir stmt feature."""
return JacFeature.pm.hook.edge_ref(
node_obj=node_obj, dir=dir, filter_type=filter_type
node_obj=node_obj, dir=dir, filter_type=filter_type, filter_func=filter_func
)

@staticmethod
Expand Down Expand Up @@ -125,7 +126,7 @@ def get_root() -> Architype:
def build_edge(
edge_dir: EdgeDir,
conn_type: Optional[Type[Architype]],
conn_assign: Optional[tuple],
conn_assign: Optional[tuple[tuple, tuple]],
) -> Architype:
"""Jac's root getter."""
return JacFeature.pm.hook.build_edge(
Expand Down
3 changes: 2 additions & 1 deletion jaclang/plugin/spec.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ def edge_ref(
node_obj: NodeArchitype,
dir: EdgeDir,
filter_type: Optional[type],
filter_func: Optional[Callable],
) -> list[NodeArchitype]:
"""Jac's apply_dir stmt feature."""
raise NotImplementedError
Expand Down Expand Up @@ -152,7 +153,7 @@ def get_root() -> Architype:
def build_edge(
edge_dir: EdgeDir,
conn_type: Optional[Type[Architype]],
conn_assign: Optional[tuple],
conn_assign: Optional[tuple[tuple, tuple]],
) -> Architype:
"""Jac's root getter."""
raise NotImplementedError
43 changes: 43 additions & 0 deletions jaclang/tests/fixtures/edge_ops.jac
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import:py random;

node node_a{
has value:int;
}

walker Creator {
can create with `<root> entry;
can travel with `<root>|node_a entry;
}

edge MyEdge {
has val:int =5,
val2:int = 10;
}

:walker:Creator:can:create{
end = <here>;
for i = 0 to i<5 by i+=1{
end ++> end := node_a(value=i+1);
if i == 2{
for j=0 to j<3 by j+=1 {
end +:MyEdge:val=random.randint(1,15), val2=random.randint(1,5):+> node_a(value=j+10);
}
print([(i.val, i.val2) for i in list(end._jac_.edges.values())[1]]);
}
}
for i=0 to i<3 by i+=1 {
end +:MyEdge:val=random.randint(1,20):+> node_a(value=i+5);
}
}
:walker:Creator:can:travel{
for i in -:MyEdge:val<=5:-> {
print(i.value);
}
visit-->;
}

with entry{
random.seed(1);
<root> spawn Creator();
#print(<root>._jac_.gen_dot());
}
2 changes: 1 addition & 1 deletion jaclang/tests/fixtures/gendot_bubble_sort.jac
Original file line number Diff line number Diff line change
Expand Up @@ -57,5 +57,5 @@ with entry{
<r> spawn walker1();
<r> spawn walker2();
<r> spawn walker3();
<r>._jac_.gen_dot();
print(<r>._jac_.gen_dot());
}
1 change: 0 additions & 1 deletion jaclang/tests/fixtures/semstr.jac
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ enum 'enum' emotion {
Angry
}


node 'personality'
personality{
has
Expand Down
12 changes: 12 additions & 0 deletions jaclang/tests/test_language.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,3 +202,15 @@ def test_has_lambda_goodness(self) -> None:
stdout_value = captured_output.getvalue()
self.assertEqual(stdout_value.split("\n")[0], "mylist: [1, 2, 3]")
self.assertEqual(stdout_value.split("\n")[1], "mydict: {'a': 2, 'b': 4}")

def test_conn_assign_on_edges(self) -> None:
"""Test conn assign on edges."""
construct.root._jac_.edges[construct.EdgeDir.OUT].clear()
captured_output = io.StringIO()
sys.stdout = captured_output
jac_import("edge_ops", self.fixture_abs_path("./"))
sys.stdout = sys.__stdout__
stdout_value = captured_output.getvalue()
self.assertEqual(stdout_value.split("\n")[0], "[(3, 5), (14, 1), (5, 1)]")
self.assertEqual(stdout_value.split("\n")[1], "10")
self.assertEqual(stdout_value.split("\n")[2], "12")
Loading