Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
T
typon-concurrency
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Xavier Thompson
typon-concurrency
Commits
a89e5d44
Commit
a89e5d44
authored
May 25, 2023
by
Tom Niget
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add support for generators
parent
aacd2fb0
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
88 additions
and
14 deletions
+88
-14
trans/stdlib/__init__.py
trans/stdlib/__init__.py
+9
-0
trans/transpiler/phases/emit_cpp/__init__.py
trans/transpiler/phases/emit_cpp/__init__.py
+2
-0
trans/transpiler/phases/emit_cpp/expr.py
trans/transpiler/phases/emit_cpp/expr.py
+10
-8
trans/transpiler/phases/typing/__init__.py
trans/transpiler/phases/typing/__init__.py
+2
-1
trans/transpiler/phases/typing/block.py
trans/transpiler/phases/typing/block.py
+18
-1
trans/transpiler/phases/typing/expr.py
trans/transpiler/phases/typing/expr.py
+12
-4
trans/transpiler/phases/typing/types.py
trans/transpiler/phases/typing/types.py
+35
-0
No files found.
trans/stdlib/__init__.py
View file @
a89e5d44
...
...
@@ -25,4 +25,13 @@ class list(Generic[U]):
assert
list
[
int
].
first
class
Iterator
(
Generic
[
U
]):
def
__iter__
(
self
)
->
Self
:
...
def
__next__
(
self
)
->
U
:
...
def
next
(
it
:
Iterator
[
U
],
default
:
None
)
->
U
:
...
def
print
(
*
args
)
->
None
:
...
def
range
(
*
args
)
->
Iterator
[
int
]:
...
\ No newline at end of file
trans/transpiler/phases/emit_cpp/__init__.py
View file @
a89e5d44
...
...
@@ -65,6 +65,8 @@ class NodeVisitor(UniversalVisitor):
yield
"Future"
elif
node
.
kind
==
PromiseKind
.
FORKED
:
yield
"Forked"
elif
node
.
kind
==
PromiseKind
.
GENERATOR
:
yield
"Generator"
else
:
raise
NotImplementedError
(
node
)
yield
"<"
...
...
trans/transpiler/phases/emit_cpp/expr.py
View file @
a89e5d44
...
...
@@ -210,11 +210,13 @@ class ExpressionVisitor(NodeVisitor):
yield
from
self
.
visit
(
node
.
orelse
)
def
visit_Yield
(
self
,
node
:
ast
.
Yield
)
->
Iterable
[
str
]:
if
CoroutineMode
.
GENERATOR
in
self
.
generator
:
yield
"co_yield"
yield
from
self
.
prec
(
"co_yield"
).
visit
(
node
.
value
)
elif
CoroutineMode
.
FAKE
in
self
.
generator
:
yield
"return"
yield
from
self
.
visit
(
node
.
value
)
else
:
raise
NotImplementedError
(
node
)
#if CoroutineMode.GENERATOR in self.generator:
# yield "co_yield"
# yield from self.prec("co_yield").visit(node.value)
#elif CoroutineMode.FAKE in self.generator:
# yield "return"
# yield from self.visit(node.value)
#else:
# raise NotImplementedError(node)
yield
"co_yield"
yield
from
self
.
prec
(
"co_yield"
).
visit
(
node
.
value
)
trans/transpiler/phases/typing/__init__.py
View file @
a89e5d44
...
...
@@ -4,7 +4,7 @@ from pathlib import Path
from
transpiler.phases.typing.scope
import
VarKind
,
VarDecl
,
ScopeKind
from
transpiler.phases.typing.stdlib
import
PRELUDE
,
StdlibVisitor
from
transpiler.phases.typing.types
import
TY_TYPE
,
TY_INT
,
TY_STR
,
TY_BOOL
,
TY_COMPLEX
,
TY_NONE
,
FunctionType
,
\
TypeVariable
,
TY_MODULE
,
CppType
,
PyList
,
TypeType
,
Forked
,
Task
,
Future
TypeVariable
,
TY_MODULE
,
CppType
,
PyList
,
TypeType
,
Forked
,
Task
,
Future
,
PyIterator
PRELUDE
.
vars
.
update
({
# "int": VarDecl(VarKind.LOCAL, TY_TYPE, TY_INT),
...
...
@@ -28,6 +28,7 @@ PRELUDE.vars.update({
"Forked"
:
VarDecl
(
VarKind
.
LOCAL
,
TypeType
(
Forked
)),
"Task"
:
VarDecl
(
VarKind
.
LOCAL
,
TypeType
(
Task
)),
"Future"
:
VarDecl
(
VarKind
.
LOCAL
,
TypeType
(
Future
)),
"Iterator"
:
VarDecl
(
VarKind
.
LOCAL
,
TypeType
(
PyIterator
))
})
typon_std
=
Path
(
__file__
).
parent
.
parent
.
parent
.
parent
/
"stdlib"
...
...
trans/transpiler/phases/typing/block.py
View file @
a89e5d44
...
...
@@ -7,7 +7,7 @@ from transpiler.phases.typing.common import ScoperVisitor
from
transpiler.phases.typing.expr
import
ScoperExprVisitor
from
transpiler.phases.typing.scope
import
VarDecl
,
VarKind
,
ScopeKind
from
transpiler.phases.typing.types
import
BaseType
,
TypeVariable
,
FunctionType
,
IncompatibleTypesError
,
TY_MODULE
,
\
Promise
,
TY_NONE
,
PromiseKind
Promise
,
TY_NONE
,
PromiseKind
,
TupleType
@
dataclass
...
...
@@ -64,6 +64,10 @@ class ScoperBlockVisitor(ScoperVisitor):
if
self
.
scope
.
kind
==
ScopeKind
.
FUNCTION_INNER
:
self
.
root_decls
[
target
.
id
]
=
VarDecl
(
VarKind
.
OUTER_DECL
,
decl_val
)
return
True
elif
isinstance
(
target
,
ast
.
Tuple
):
if
not
(
isinstance
(
decl_val
,
TupleType
)
and
len
(
target
.
elts
)
==
len
(
decl_val
.
args
)):
raise
IncompatibleTypesError
(
f"Cannot unpack
{
decl_val
}
into
{
target
}
"
)
return
any
(
self
.
visit_assign_target
(
t
,
ty
)
for
t
,
ty
in
zip
(
target
.
elts
,
decl_val
.
args
))
else
:
raise
NotImplementedError
(
target
)
...
...
@@ -118,6 +122,19 @@ class ScoperBlockVisitor(ScoperVisitor):
if
node
.
orelse
:
raise
NotImplementedError
(
node
.
orelse
)
def
visit_For
(
self
,
node
:
ast
.
For
):
scope
=
self
.
scope
.
child
(
ScopeKind
.
FUNCTION_INNER
)
node
.
inner_scope
=
scope
assert
isinstance
(
node
.
target
,
ast
.
Name
)
scope
.
vars
[
node
.
target
.
id
]
=
VarDecl
(
VarKind
.
LOCAL
,
TypeVariable
())
self
.
expr
().
visit
(
node
.
iter
)
body_scope
=
scope
.
child
(
ScopeKind
.
FUNCTION_INNER
)
body_visitor
=
ScoperBlockVisitor
(
body_scope
,
self
.
root_decls
)
for
b
in
node
.
body
:
body_visitor
.
visit
(
b
)
if
node
.
orelse
:
raise
NotImplementedError
(
node
.
orelse
)
def
visit_Expr
(
self
,
node
:
ast
.
Expr
):
self
.
expr
().
visit
(
node
.
value
)
...
...
trans/transpiler/phases/typing/expr.py
View file @
a89e5d44
...
...
@@ -44,6 +44,17 @@ class ScoperExprVisitor(ScoperVisitor):
def
visit_Tuple
(
self
,
node
:
ast
.
Tuple
)
->
BaseType
:
return
TupleType
([
self
.
visit
(
e
)
for
e
in
node
.
elts
])
def
visit_Yield
(
self
,
node
:
ast
.
Yield
)
->
BaseType
:
ytype
=
self
.
visit
(
node
.
value
)
ftype
=
self
.
scope
.
function
.
obj_type
.
return_type
assert
isinstance
(
ftype
,
Promise
)
assert
ftype
.
kind
==
PromiseKind
.
TASK
ftype
.
kind
=
PromiseKind
.
GENERATOR
ftype
.
return_type
.
unify
(
ytype
)
return
TY_NONE
def
visit_Constant
(
self
,
node
:
ast
.
Constant
)
->
BaseType
:
if
isinstance
(
node
.
value
,
str
):
return
TY_STR
...
...
@@ -77,7 +88,7 @@ class ScoperExprVisitor(ScoperVisitor):
rtype
=
self
.
visit_function_call
(
ftype
,
[
self
.
visit
(
arg
)
for
arg
in
node
.
args
])
actual
=
rtype
node
.
is_await
=
False
if
isinstance
(
actual
,
Promise
):
if
isinstance
(
actual
,
Promise
)
and
actual
.
kind
!=
PromiseKind
.
GENERATOR
:
node
.
is_await
=
True
actual
=
actual
.
return_type
.
resolve
()
...
...
@@ -202,6 +213,3 @@ class ScoperExprVisitor(ScoperVisitor):
if
then
!=
else_
:
raise
NotImplementedError
(
"IfExp with different types not handled yet"
)
return
then
def
visit_Yield
(
self
,
node
:
ast
.
Yield
)
->
BaseType
:
raise
NotImplementedError
(
node
)
trans/transpiler/phases/typing/types.py
View file @
a89e5d44
...
...
@@ -13,6 +13,10 @@ class IncompatibleTypesError(Exception):
class
BaseType
(
ABC
):
members
:
Dict
[
str
,
"BaseType"
]
=
field
(
default_factory
=
dict
,
init
=
False
)
methods
:
Dict
[
str
,
"FunctionType"
]
=
field
(
default_factory
=
dict
,
init
=
False
)
parents
:
List
[
"BaseType"
]
=
field
(
default_factory
=
list
,
init
=
False
)
def
get_parents
(
self
)
->
List
[
"BaseType"
]:
return
self
.
parents
def
resolve
(
self
)
->
"BaseType"
:
return
self
...
...
@@ -117,6 +121,22 @@ class TypeOperator(BaseType, ABC):
def
unify_internal
(
self
,
other
:
BaseType
):
if
not
isinstance
(
other
,
TypeOperator
):
raise
IncompatibleTypesError
()
if
type
(
self
)
!=
type
(
other
):
for
parent
in
other
.
get_parents
():
try
:
self
.
unify
(
parent
)
except
IncompatibleTypesError
:
pass
else
:
return
for
parent
in
self
.
get_parents
():
try
:
parent
.
unify
(
other
)
except
IncompatibleTypesError
:
pass
else
:
return
raise
IncompatibleTypesError
(
f"Cannot unify
{
self
}
and
{
other
}
with different type and no common parents"
)
if
len
(
self
.
args
)
!=
len
(
other
.
args
)
and
not
(
self
.
variadic
or
other
.
variadic
):
raise
IncompatibleTypesError
(
f"Cannot unify
{
self
}
and
{
other
}
with different number of arguments"
)
for
a
,
b
in
zip
(
self
.
args
,
other
.
args
):
...
...
@@ -241,6 +261,15 @@ class PyDict(TypeOperator):
def
value_type
(
self
):
return
self
.
args
[
1
]
class
PyIterator
(
TypeOperator
):
def
__init__
(
self
,
arg
:
BaseType
):
super
().
__init__
([
arg
],
"iter"
)
@
property
def
element_type
(
self
):
return
self
.
args
[
0
]
class
TupleType
(
TypeOperator
):
def
__init__
(
self
,
args
:
List
[
BaseType
]):
...
...
@@ -252,6 +281,7 @@ class PromiseKind(Enum):
JOIN
=
1
FUTURE
=
2
FORKED
=
3
GENERATOR
=
4
class
Promise
(
TypeOperator
,
ABC
):
...
...
@@ -273,6 +303,11 @@ class Promise(TypeOperator, ABC):
def
__str__
(
self
):
return
f"
{
self
.
kind
.
name
.
lower
()
}
<
{
self
.
return_type
}
>"
def
get_parents
(
self
)
->
List
[
"BaseType"
]:
if
self
.
kind
==
PromiseKind
.
GENERATOR
:
return
[
PyIterator
(
self
.
return_type
),
*
super
().
get_parents
()]
return
super
().
get_parents
()
class
Forked
(
Promise
):
"""Only use this for type specs"""
def
__init__
(
self
,
ret
:
BaseType
):
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment