Skip to content

Commit ef1e3ed

Browse files
committed
v0.0.2: the widish shell
1 parent 8081442 commit ef1e3ed

File tree

15 files changed

+146
-76
lines changed

15 files changed

+146
-76
lines changed

README.md

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -46,17 +46,6 @@ Programming is hard, but it shouldn't be _that_ hard.
4646

4747
So far widis have mainly shaped the user interface. Widis are also [graphical programming](https://graphicallinearalgebra.net/2015/04/26/adding-part-1-and-mr-fibonacci/) tools and one can work with them in purely mathematical terms. Start with [examples/mascarpone](examples/mascarpone) then take a look at current work in a functional library at [src](src).
4848

49-
# Working with the CLI
50-
Open terminal and run `widip` to start an interactive session. The program `bin/yaml/shell.yaml` prompts for one command per line, so when we hit `↵ Enter` it is evaluated. When hitting `⌁ Ctrl+D` the environment exits.
51-
52-
```yaml
53-
--- !bin/yaml/shell.yaml
54-
!print Hello world!
55-
Hello world!
56-
```
57-
58-
<!-- <img src="examples/hello-world.jpg" width="300"> -->
59-
6049

6150
[UNIX shell]: https://en.wikipedia.org/wiki/Unix_shell
6251
[chatbot]: https://en.wikipedia.org/wiki/chatbot

examples/README.md

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,38 @@
1-
# Examples
1+
# Shell examples
22

33
## Hello world!
44

5+
```
6+
$ python -m widip examples/hello-world.yaml
7+
Hello world!
8+
```
9+
510
![](hello-world.jpg)
611

12+
## Script
13+
14+
```
15+
$ python -m widip examples/shell.yaml
16+
73
17+
23
18+
? !grep grep: !wc -c
19+
? !tail -2
20+
```
21+
22+
![IMG](shell.jpg)
23+
24+
25+
# Working with the CLI
26+
Open terminal and run `widip` to start an interactive session. The program `bin/yaml/shell.yaml` prompts for one command per line, so when we hit `↵ Enter` it is evaluated. When hitting `⌁ Ctrl+D` the environment exits.
27+
28+
```yaml
29+
--- !bin/yaml/shell.yaml
30+
!echo Hello world!
31+
Hello world!
32+
```
33+
34+
# Other examples
35+
736
## React
837
The first example in https://react.dev/ in diagrammatic style.
938

examples/hello-world.jpg

-544 Bytes
Loading

examples/hello-world.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
!print Hello world!
1+
!echo Hello world!

examples/shell.jpg

18.4 KB
Loading

examples/shell.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
!cat examples/shell.yaml:
2+
? !wc -c
3+
? !grep grep: !wc -c
4+
? !tail -2

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ packages = ["."]
77

88
[project]
99
name = "widip"
10-
version = "0.0.1"
10+
version = "0.0.2"
1111
description = "Widip is an interactive environment for computing with wiring diagrams in modern systems"
1212
dependencies = [
1313
"discopy>=1.1.7", "pyyaml>=6.0.1", "watchdog>=4.0.1",

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
setuptools.setup(
77
name="widip",
8-
version="0.0.1",
8+
version="0.0.2",
99
author="Martin Coll",
1010
author_email="[email protected]",
1111
description="Widip is an interactive environment for computing with wiring diagrams in modern systems",

widip/__main__.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
import sys
22
import warnings
33

4-
from .watch import watch_main, shell_main, stream_main
4+
from .watch import watch_main, shell_main
5+
from .widish import widish_main
56

67

78
warnings.filterwarnings("ignore")
89
match sys.argv:
910
case [_]:
1011
watch_main()
1112
shell_main("bin/yaml/shell.yaml")
12-
case [_, file_name]: stream_main(open(file_name))
13+
case [_, file_name]: widish_main(file_name)

widip/widish.py

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
from multiprocessing import Pipe
2+
from pathlib import Path
3+
from subprocess import PIPE, Popen
4+
import sys
5+
6+
from discopy.frobenius import Category, Functor, Ty, Box
7+
from discopy.frobenius import Hypergraph as H, Id, Spider
8+
from discopy import python
9+
10+
from .files import stream_diagram
11+
12+
13+
14+
class IORun(python.Function):
15+
@classmethod
16+
def spiders(cls, n_legs_in: int, n_legs_out: int, typ: Ty):
17+
def step(*processes: IOProcess):
18+
"""
19+
A many-to-many pipe.
20+
"""
21+
assert typ == Ty("io")
22+
assert len(processes) == n_legs_in
23+
return tuple(
24+
IOSpiderProcess(*processes)
25+
for _ in range(n_legs_out))
26+
return IORun(
27+
inside=step,
28+
dom=Ty(*("io" for _ in range(n_legs_in))),
29+
cod=Ty(*("io" for _ in range(n_legs_out))))
30+
31+
32+
def command_io_f(diagram):
33+
"""
34+
close input parameters (constants)
35+
drop outputs matching input parameters
36+
all boxes are io->[io]"""
37+
def command_io(b):
38+
return Id().tensor(*(
39+
Id("io") @ Spider(0, 1, t) >>
40+
Box(b.name,
41+
Ty("io") @ t,
42+
Ty("io")) >>
43+
H.spiders(1, len(b.cod), Ty("io")).to_diagram()
44+
for t in b.dom))
45+
f = Functor(
46+
lambda x: Ty("io"),
47+
lambda b: command_io(b),)
48+
diagram = f(diagram)
49+
return (
50+
# H.spiders(0, len(diagram.dom), Ty("io")).to_diagram() >>
51+
diagram >>
52+
H.spiders(len(diagram.cod), 1, Ty("io")).to_diagram())
53+
54+
55+
class IOProcess:
56+
"""mutual with IOSpiderProcess"""
57+
def __init__(self, box, *spider_processes):
58+
assert box.dom[0] == Ty("io")
59+
assert box.cod == Ty("io")
60+
self.spider_processes = spider_processes
61+
self.popen_args = [box.name, *(t.name for t in box.dom[1:])]
62+
self.pipe_in, self.pipe_out = Pipe(duplex=False)
63+
64+
def communicate(self, input):
65+
# print("process:", self.spider_processes)
66+
# i = self.pipe_in.recv()
67+
o = ""
68+
for p in self.spider_processes:
69+
o += p.communicate(input)
70+
# print(o, self.popen_args)
71+
popen = Popen(self.popen_args, stdin=PIPE, stdout=PIPE, text=True)
72+
(o, _) = popen.communicate(o)
73+
# print(o, self.popen_args)
74+
return o
75+
76+
77+
class IOSpiderProcess:
78+
"""
79+
takes many processes and creates n copies of their joined outputs
80+
mutual with IOSpider"""
81+
def __init__(self, *processes: IOProcess):
82+
self.processes = processes
83+
self.pipe_in, self.pipe_out = Pipe(duplex=False)
84+
85+
def communicate(self, input):
86+
# print("spiderprocess:", [p.popen for p in self.processes])
87+
w = ""
88+
for p in self.processes:
89+
o = p.communicate(input)
90+
w += o
91+
return w
92+
93+
shell_f = Functor(
94+
lambda x: Ty("io"),
95+
lambda b: lambda *p: IOProcess(b, *p),
96+
cod=Category(Ty, IORun))
97+
98+
99+
def widish_main(file_name):
100+
path = Path(file_name)
101+
diagram = stream_diagram(path.open())
102+
diagram = command_io_f(diagram)
103+
diagram.draw(path=path.with_suffix(".jpg"))
104+
process: IOSpiderProcess = shell_f(diagram)()
105+
r = process.communicate("")
106+
sys.stdout.write(r)

0 commit comments

Comments
 (0)