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

Commit

Permalink
Merge pull request #170 from Jaseci-Labs/edges_modified
Browse files Browse the repository at this point in the history
Edges modified
  • Loading branch information
marsninja authored Jan 28, 2024
2 parents ef109b1 + 1dd3369 commit 6a5b595
Show file tree
Hide file tree
Showing 14 changed files with 144 additions and 89 deletions.
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")

0 comments on commit 6a5b595

Please sign in to comment.