fork
and
sync
def f():
# - before -
fork(lambda: child())
# - continuation -
def f():
# - before -
fork(lambda: child())
# - continuation -
def f():
# - before -
fork(lambda: child())
# - continuation -
def f():
# - before -
result = fork(lambda: child())
# - continuation -
sync()
# - joined -
return result
def f():
# - before -
result = fork(lambda: child())
# - continuation -
sync()
# - joined -
return result
def f():
# - before -
result = fork(lambda: child())
# - continuation -
sync()
# - joined -
return result
def f():
# - before -
result = fork(lambda: child())
# - continuation -
sync()
# - joined -
return result
def f():
# ...
fork(lambda: child())
# ...
# implicit sync (even if exception)
f() # no concurrency leak
def server(sock):
while True:
conn = sock.accept()[0]
handle(conn) # only one connection at a time
def handle(conn):
msg = conn.recv(1024) # python: classic thread-blocking I/O
#...
def server(sock):
while True:
conn = sock.accept()[0]
fork(lambda: handle(conn)) # C10K capable :)
def handle(conn):
msg = conn.recv(1024) # typon: asynchronous I/O by io_uring
#...
import ast
import ast
source = """
a = 1 + 2
"""
print(
ast.dump(
ast.parse(source),
annotate_fields=False,
indent=2,
)
)
import ast
source = """
a = 1 + 2
"""
print(
ast.dump(
ast.parse(source),
annotate_fields=False,
indent=2,
)
)
Module(
[
Assign(
[
Name('a', Store())],
BinOp(
Constant(1),
Add(),
Constant(2)))],
[])
import ast
source = """
def f(x):
return x.y
"""
print(
ast.dump(
ast.parse(source),
annotate_fields=False,
indent=2,
)
)
Module(
[
FunctionDef(
'f',
arguments(
[],
[
arg('x')],
kwonlyargs=[],
kw_defaults=[],
defaults=[]),
[
Return(
Attribute(
Name('x', Load()),
'y',
Load()))],
[])],
[])
import ast
def compile(source: str):
tree = ast.parse(source)
# [...]
TypeInferer().visit(tree)
# [...]
CodeGenerator().visit(tree)
from ast import NodeVisitor
class TypeInferer(NodeVisitor):
def visit_Module(self, node):
# [...]
def visit_FuncDef(self, node):
# [...]
def visit_Call(self, node):
# [...]
def visit_Name(self, node):
# [...]
class NodeVisitor(ast.NodeVisitor):
def visit(self, node):
for cls in node.__class__.__mro__:
name = 'visit_' + class.__name__
if visitor := getattr(self, name, None):
visitor(node)
else:
self.generic_visit(node)
class TypeInferer(NodeVisitor):
def visit_Module(self, node):
# [...]
def visit_FuncDef(self, node):
# [...]
def visit_Call(self, node):
# [...]
def visit_Name(self, node):
# [...]
class NodeVisitor(ast.NodeVisitor):
def visit(self, node):
if isinstance(node, list):
for n in node:
self.visit(n)
for cls in node.__class__.__mro__:
name = 'visit_' + class.__name__
if visitor := getattr(self, name, None):
visitor(node)
else:
self.generic_visit(node)
class TypeInferer(NodeVisitor):
def add(a, b):
return a + b
add(1, 2) # ok
add("hello", "world") # ok
add(1, "world") # error
def add(a, b):
return a + b
add(1, 2) # ok
add("hello", "world") # ok
add(1, "world") # error
class Weird:
def __add__(self, whatever):
return str(whatever)
s = add(Weird(), 1) # ok, s: str
l = [] # list[T]
l.append(1) # T = int
def f():
pass
void f() {}
def f():
pass
a = f
struct {
void operator() () {}
} f {};
auto a = f;
def f(x):
pass
a = f
struct {
void operator() (auto x) {}
} f {};
auto a = f;
def f(x):
return x.y
a = f
class X:
pass
def f(x):
return x.y
a = f
class X:
pass
def f(x):
return x.y
class X:
y : int
def f(x):
return x.y
class X:
def y(self):
pass
def f(x):
return x.y
class X:
def y(self):
pass
def f(x):
# what if x.y is
# a boundmethod?
return x.y
x_dot_y = f(X())
import numpy
if __name__ == "__main__":
x = [i for i in range(5)]
y = numpy.square(x)
z : list[int] = y
print(x, y)
# via pybind11, 'numpy' is a Python object
import numpy
if __name__ == "__main__":
# list[int], pure C++
x = [i for i in range(5)]
# convert 'x' to Python, get a Python object
y = numpy.square(x)
# convert Python object to list[int]
z : list[int] = y
# pure C++
print(x, y)
builtins
:
list
, dict
, str
,
print
, open
, ...socket
:
io_uring
os
(some):
io_uring