Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
T
typon-compiler
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
typon
typon-compiler
Commits
90409113
Commit
90409113
authored
Feb 08, 2024
by
Tom Niget
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
work
parent
8fd5e9fb
Changes
21
Hide whitespace changes
Inline
Side-by-side
Showing
21 changed files
with
1019 additions
and
679 deletions
+1019
-679
notes2.txt
notes2.txt
+2
-0
typon/trans/tests/user_generics.py
typon/trans/tests/user_generics.py
+4
-0
typon/trans/transpiler/__init__.py
typon/trans/transpiler/__init__.py
+34
-11
typon/trans/transpiler/phases/emit_cpp/__init__.py
typon/trans/transpiler/phases/emit_cpp/__init__.py
+0
-154
typon/trans/transpiler/phases/emit_cpp/class_.py
typon/trans/transpiler/phases/emit_cpp/class_.py
+34
-137
typon/trans/transpiler/phases/emit_cpp/function.py
typon/trans/transpiler/phases/emit_cpp/function.py
+161
-108
typon/trans/transpiler/phases/emit_cpp/module.py
typon/trans/transpiler/phases/emit_cpp/module.py
+30
-222
typon/trans/transpiler/phases/emit_cpp/visitors.py
typon/trans/transpiler/phases/emit_cpp/visitors.py
+92
-0
typon/trans/transpiler/phases/emit_cpp2/__init__.py
typon/trans/transpiler/phases/emit_cpp2/__init__.py
+133
-0
typon/trans/transpiler/phases/emit_cpp2/block.py
typon/trans/transpiler/phases/emit_cpp2/block.py
+1
-1
typon/trans/transpiler/phases/emit_cpp2/class_.py
typon/trans/transpiler/phases/emit_cpp2/class_.py
+137
-0
typon/trans/transpiler/phases/emit_cpp2/consts.py
typon/trans/transpiler/phases/emit_cpp2/consts.py
+0
-0
typon/trans/transpiler/phases/emit_cpp2/expr.py
typon/trans/transpiler/phases/emit_cpp2/expr.py
+6
-24
typon/trans/transpiler/phases/emit_cpp2/file.py
typon/trans/transpiler/phases/emit_cpp2/file.py
+0
-0
typon/trans/transpiler/phases/emit_cpp2/function.py
typon/trans/transpiler/phases/emit_cpp2/function.py
+126
-0
typon/trans/transpiler/phases/emit_cpp2/module.py
typon/trans/transpiler/phases/emit_cpp2/module.py
+224
-0
typon/trans/transpiler/phases/emit_cpp2/search.py
typon/trans/transpiler/phases/emit_cpp2/search.py
+0
-0
typon/trans/transpiler/phases/typing/modules.py
typon/trans/transpiler/phases/typing/modules.py
+13
-11
typon/trans/transpiler/phases/typing/scope.py
typon/trans/transpiler/phases/typing/scope.py
+1
-0
typon/trans/transpiler/phases/typing/stdlib.py
typon/trans/transpiler/phases/typing/stdlib.py
+16
-10
typon/trans/transpiler/phases/typing/types.py
typon/trans/transpiler/phases/typing/types.py
+5
-1
No files found.
notes2.txt
View file @
90409113
...
@@ -64,3 +64,5 @@ fonction : type concret qui a un type caché qui correspond à ce qui sera gén
...
@@ -64,3 +64,5 @@ fonction : type concret qui a un type caché qui correspond à ce qui sera gén
pareil pour les classes
pareil pour les classes
donc on peut passer des types génériques puisqu'ils sont wrappés par un type concret
donc on peut passer des types génériques puisqu'ils sont wrappés par un type concret
----------------
faire des tags v0.1 v0.2 pour proto 1 et version qui marche
\ No newline at end of file
typon/trans/tests/user_generics.py
View file @
90409113
...
@@ -20,3 +20,7 @@
...
@@ -20,3 +20,7 @@
# b = Thing[str]("abc")
# b = Thing[str]("abc")
# print(a)
# print(a)
# print(b)
# print(b)
if
__name__
==
"__main__"
:
x
=
5
\ No newline at end of file
typon/trans/transpiler/__init__.py
View file @
90409113
...
@@ -13,8 +13,10 @@ import colorama
...
@@ -13,8 +13,10 @@ import colorama
from
transpiler.phases.desugar_compare
import
DesugarCompare
from
transpiler.phases.desugar_compare
import
DesugarCompare
from
transpiler.phases.desugar_op
import
DesugarOp
from
transpiler.phases.desugar_op
import
DesugarOp
from
transpiler.phases.emit_cpp.module
import
emit_module
from
transpiler.phases.typing
import
PRELUDE
from
transpiler.phases.typing
import
PRELUDE
from
transpiler.phases.typing.modules
import
parse_module
from
transpiler.phases.typing.modules
import
parse_module
from
transpiler.phases.typing.stdlib
import
StdlibVisitor
colorama
.
init
()
colorama
.
init
()
...
@@ -182,19 +184,18 @@ typon_std = Path(__file__).parent.parent / "stdlib"
...
@@ -182,19 +184,18 @@ typon_std = Path(__file__).parent.parent / "stdlib"
parse_module
(
"builtins"
,
typon_std
,
PRELUDE
)
parse_module
(
"builtins"
,
typon_std
,
PRELUDE
)
def
transpile
(
source
,
name
:
str
,
path
=
None
):
def
transpile
(
source
,
name
:
str
,
path
:
Path
):
__TB__
=
f"transpiling module
{
cf
.
white
(
name
)
}
"
__TB__
=
f"transpiling module
{
cf
.
white
(
name
)
}
"
res
=
ast
.
parse
(
source
,
type_comments
=
True
)
exit
()
IfMainVisitor
().
visit
(
res
)
res
=
DesugarWith
().
visit
(
res
)
res
=
DesugarCompare
().
visit
(
res
)
res
=
DesugarOp
().
visit
(
res
)
#ScoperBlockVisitor().visit(res)
# print(res.scope)
def
preprocess
(
node
):
IfMainVisitor
().
visit
(
node
)
node
=
DesugarWith
().
visit
(
node
)
node
=
DesugarCompare
().
visit
(
node
)
node
=
DesugarOp
().
visit
(
node
)
return
node
module
=
parse_module
(
path
.
stem
,
path
.
parent
,
preprocess
=
preprocess
)
# display each scope
def
disp_scope
(
scope
,
indent
=
0
):
def
disp_scope
(
scope
,
indent
=
0
):
debug
(
" "
*
indent
,
scope
.
kind
)
debug
(
" "
*
indent
,
scope
.
kind
)
for
child
in
scope
.
children
:
for
child
in
scope
.
children
:
...
@@ -202,7 +203,29 @@ def transpile(source, name: str, path=None):
...
@@ -202,7 +203,29 @@ def transpile(source, name: str, path=None):
for
var
in
scope
.
vars
.
items
():
for
var
in
scope
.
vars
.
items
():
debug
(
" "
*
(
indent
+
1
),
var
)
debug
(
" "
*
(
indent
+
1
),
var
)
disp_scope
(
res
.
scope
)
def
main_module
():
yield
from
emit_module
(
module
)
yield
"#ifdef TYPON_EXTENSION"
# yield f"PYBIND11_MODULE({self.module_name}, m) {{"
# yield f"m.doc() = \"Typon extension module '{self.module_name}'\";"
# visitor = ModuleVisitorExt(self.scope)
# code = [line for stmt in node.body for line in visitor.visit(stmt)]
# yield from code
# yield "}"
yield
"#else"
yield
"typon::Root root() const {"
yield
f"co_await dot(PROGRAMNS::
{
module
.
name
()
}
, main)();"
yield
"}"
yield
"int main(int argc, char* argv[]) {"
yield
"py_sys::all.argv = typon::PyList<PyStr>(std::vector<PyStr>(argv, argv + argc));"
yield
f"root().call();"
yield
"}"
yield
"#endif"
code
=
"
\
n
"
.
join
(
filter
(
None
,
main_module
()))
return
code
exit
()
exit
()
assert
isinstance
(
res
,
ast
.
Module
)
assert
isinstance
(
res
,
ast
.
Module
)
...
...
typon/trans/transpiler/phases/emit_cpp/__init__.py
View file @
90409113
# coding: utf-8
import
ast
import
enum
from
enum
import
Flag
from
itertools
import
chain
from
typing
import
Iterable
from
transpiler.phases.emit_cpp.consts
import
MAPPINGS
from
transpiler.phases.typing
import
TypeVariable
from
transpiler.phases.typing.exceptions
import
UnresolvedTypeVariableError
from
transpiler.phases.typing.types
import
BaseType
,
TY_INT
,
TY_BOOL
,
TY_NONE
,
Promise
,
PromiseKind
,
TY_STR
,
UserType
,
\
TypeType
,
TypeOperator
,
TY_FLOAT
,
FunctionType
,
UnionType
from
transpiler.utils
import
UnsupportedNodeError
,
highlight
class
UniversalVisitor
:
def
visit
(
self
,
node
):
"""Visit a node."""
__TB__
=
f"emitting C++ code for
{
highlight
(
node
)
}
"
# __TB_SKIP__ = True
if
type
(
node
)
==
list
:
for
n
in
node
:
yield
from
self
.
visit
(
n
)
else
:
for
parent
in
node
.
__class__
.
__mro__
:
if
visitor
:
=
getattr
(
self
,
'visit_'
+
parent
.
__name__
,
None
):
yield
from
visitor
(
node
)
break
else
:
yield
from
self
.
missing_impl
(
node
)
def
missing_impl
(
self
,
node
):
raise
UnsupportedNodeError
(
node
)
class
NodeVisitor
(
UniversalVisitor
):
def
process_args
(
self
,
node
:
ast
.
arguments
)
->
(
str
,
str
,
str
):
for
field
in
(
"posonlyargs"
,
"vararg"
,
"kwonlyargs"
,
"kw_defaults"
,
"kwarg"
,
"defaults"
):
if
getattr
(
node
,
field
,
None
):
raise
NotImplementedError
(
node
,
field
)
if
not
node
.
args
:
return
""
,
"()"
,
[]
f_args
=
[(
self
.
fix_name
(
arg
.
arg
),
f"T
{
i
+
1
}
"
)
for
i
,
arg
in
enumerate
(
node
.
args
)]
return
(
"<"
+
", "
.
join
(
f"typename
{
t
}
"
for
_
,
t
in
f_args
)
+
">"
,
"("
+
", "
.
join
(
f"
{
t
}
{
n
}
"
for
n
,
t
in
f_args
)
+
")"
,
[
n
for
n
,
_
in
f_args
]
)
def
fix_name
(
self
,
name
:
str
)
->
str
:
if
name
.
startswith
(
"__"
)
and
name
.
endswith
(
"__"
):
return
f"py_
{
name
[
2
:
-
2
]
}
"
return
MAPPINGS
.
get
(
name
,
name
)
def
visit_BaseType
(
self
,
node
:
BaseType
)
->
Iterable
[
str
]:
node
=
node
.
resolve
()
if
node
is
TY_INT
:
yield
"int"
elif
node
is
TY_FLOAT
:
yield
"double"
elif
node
is
TY_BOOL
:
yield
"bool"
elif
node
is
TY_NONE
:
yield
"void"
elif
node
is
TY_STR
:
yield
"PyStr"
elif
isinstance
(
node
,
UserType
):
# if node.is_reference:
# yield "PyObj<"
#yield "auto"
yield
f"referencemodel::Rc<__main____oo<>::
{
node
.
name
}
__oo<>::Obj>"
# if node.is_reference:
# yield "::py_type>"
elif
isinstance
(
node
,
TypeType
):
yield
"auto"
# TODO
elif
isinstance
(
node
,
FunctionType
):
yield
"std::function<"
yield
from
self
.
visit
(
node
.
return_type
)
yield
"("
yield
from
join
(
", "
,
map
(
self
.
visit
,
node
.
parameters
))
yield
")>"
elif
isinstance
(
node
,
Promise
):
yield
"typon::"
if
node
.
kind
==
PromiseKind
.
TASK
:
yield
"Task"
elif
node
.
kind
==
PromiseKind
.
JOIN
:
yield
"Join"
elif
node
.
kind
==
PromiseKind
.
FUTURE
:
yield
"Future"
elif
node
.
kind
==
PromiseKind
.
FORKED
:
yield
"Forked"
elif
node
.
kind
==
PromiseKind
.
GENERATOR
:
yield
"Generator"
else
:
raise
NotImplementedError
(
node
)
yield
"<"
yield
from
self
.
visit
(
node
.
return_type
)
yield
">"
elif
isinstance
(
node
,
TypeVariable
):
# yield f"TYPEVAR_{node.name}";return
raise
UnresolvedTypeVariableError
(
node
)
elif
isinstance
(
node
,
UnionType
)
and
(
ty
:
=
node
.
is_optional
()):
yield
"std::optional<"
yield
from
self
.
visit
(
ty
)
yield
">"
elif
isinstance
(
node
,
TypeOperator
):
yield
"typon::Py"
+
node
.
name
.
title
()
if
node
.
args
:
yield
"<"
yield
from
join
(
", "
,
map
(
self
.
visit
,
node
.
args
))
yield
">"
else
:
raise
NotImplementedError
(
node
)
class
CoroutineMode
(
Flag
):
SYNC
=
1
FAKE
=
2
|
SYNC
ASYNC
=
4
GENERATOR
=
8
|
ASYNC
TASK
=
16
|
ASYNC
JOIN
=
32
|
ASYNC
class
FunctionEmissionKind
(
enum
.
Enum
):
DECLARATION
=
enum
.
auto
()
DEFINITION
=
enum
.
auto
()
METHOD
=
enum
.
auto
()
LAMBDA
=
enum
.
auto
()
def
join
(
sep
:
str
,
items
:
Iterable
[
Iterable
[
str
]])
->
Iterable
[
str
]:
items
=
iter
(
items
)
try
:
it
=
next
(
items
)
if
type
(
it
)
is
str
:
yield
it
else
:
yield
from
it
for
item
in
items
:
yield
sep
it
=
item
if
type
(
it
)
is
str
:
yield
it
else
:
yield
from
it
except
StopIteration
:
return
def
flatmap
(
f
,
items
):
return
chain
.
from_iterable
(
map
(
f
,
items
))
typon/trans/transpiler/phases/emit_cpp/class_.py
View file @
90409113
# coding: utf-8
from
typing
import
Iterable
import
ast
from
typing
import
Iterable
def
emit_class
(
clazz
)
->
Iterable
[
str
]:
from
dataclasses
import
dataclass
yield
f"template <typename _Base0 = referencemodel::object>"
from
transpiler.phases.typing.scope
import
Scope
yield
f"struct
{
node
.
name
}
__oo : referencemodel::classtype<_Base0,
{
node
.
name
}
__oo<>> {{"
from
transpiler.phases.emit_cpp
import
NodeVisitor
,
FunctionEmissionKind
yield
f"static constexpr std::string_view name =
\
"
{
node
.
name
}\
"
;"
inner
=
ClassInnerVisitor2
(
node
.
inner_scope
)
class
ClassVisitor
(
NodeVisitor
):
for
stmt
in
node
.
body
:
def
visit_ClassDef
(
self
,
node
:
ast
.
ClassDef
)
->
Iterable
[
str
]:
yield
from
inner
.
visit
(
stmt
)
if
gen_instances
:
=
getattr
(
node
,
"gen_instances"
,
None
):
for
args
,
inst
in
gen_instances
.
items
():
yield
f"struct Obj : referencemodel::instance<
{
node
.
name
}
__oo<>, Obj> {{"
yield
from
self
.
visit_ClassDef
(
inst
)
return
inner
=
ClassInnerVisitor4
(
node
.
inner_scope
)
for
stmt
in
node
.
body
:
yield
f"struct
{
node
.
name
}
_s;"
yield
from
inner
.
visit
(
stmt
)
yield
f"extern
{
node
.
name
}
_s
{
node
.
name
}
;"
yield
f"struct
{
node
.
name
}
_s {{"
yield
"template <typename... U>"
yield
"Obj(U&&... args) {"
yield
"struct py_type {"
yield
"dot(this, __init__)(this, std::forward<U>(args)...);"
inner
=
ClassInnerVisitor
(
node
.
inner_scope
)
yield
"}"
for
stmt
in
node
.
body
:
yield
from
inner
.
visit
(
stmt
)
yield
"};"
yield
"template<typename... T> py_type(T&&... args) {"
yield
"__init__(this, std::forward<T>(args)...);"
yield
"template <typename... T>"
yield
"}"
yield
"auto operator() (T&&... args) const {"
yield
"py_type() {}"
yield
"return referencemodel::rc(Obj{std::forward<T>(args)...});"
yield
"py_type(const py_type&) = delete;"
yield
"}"
yield
"py_type(py_type&&) = delete;"
yield
f"}};"
if
getattr
(
node
.
type
,
"is_enum"
,
False
):
yield
f"static constexpr
{
node
.
name
}
__oo<>
{
node
.
name
}
{{}};"
yield
"int value;"
yield
f"static_assert(sizeof
{
node
.
name
}
== 1);"
yield
"operator int() const { return value; }"
\ No newline at end of file
yield
"void py_repr(std::ostream &s) const {"
yield
f's << "
{
node
.
name
}
.";'
yield
"}"
else
:
yield
"void py_repr(std::ostream &s) const {"
yield
f's << "
{
node
.
name
}
(";'
for
i
,
(
name
,
memb
)
in
enumerate
(
node
.
type
.
get_members
().
items
()):
if
i
!=
0
:
yield
's << ", ";'
yield
f's << "
{
name
}
=";'
yield
f"repr_to(
{
name
}
, s);"
yield
"s << ')';"
yield
"}"
yield
"void py_print(std::ostream &s) const {"
yield
"py_repr(s);"
yield
"}"
yield
"};"
yield
"template<typename... T> auto operator()(T&&... args) {"
yield
"return pyobj<py_type>(std::forward<T>(args)...);"
yield
"}"
# outer = ClassOuterVisitor(node.inner_scope)
# for stmt in node.body:
# yield from outer.visit(stmt)
yield
f"}}
{
node
.
name
}
;"
@
dataclass
class
ClassInnerVisitor
(
NodeVisitor
):
scope
:
Scope
def
visit_AnnAssign
(
self
,
node
:
ast
.
AnnAssign
)
->
Iterable
[
str
]:
member
=
self
.
scope
.
obj_type
.
fields
[
node
.
target
.
id
]
yield
from
self
.
visit
(
member
.
type
)
yield
node
.
target
.
id
yield
";"
def
visit_Assign
(
self
,
node
:
ast
.
Assign
)
->
Iterable
[
str
]:
yield
"static constexpr"
from
transpiler.phases.emit_cpp.block
import
BlockVisitor
yield
from
BlockVisitor
(
self
.
scope
).
visit_Assign
(
node
)
def
visit_FunctionDef
(
self
,
node
:
ast
.
FunctionDef
)
->
Iterable
[
str
]:
# yield "struct {"
# yield "type* self;"
# from transpiler.phases.emit_cpp.block import BlockVisitor
# yield from BlockVisitor(self.scope).visit_func_new(node, FunctionEmissionKind.METHOD, True)
# yield f"}} {node.name} {{ this }};"
yield
f"struct
{
node
.
name
}
_m_s : referencemodel::method {{"
from
transpiler.phases.emit_cpp.block
import
BlockVisitor
yield
from
BlockVisitor
(
self
.
scope
).
visit_func_new
(
node
,
FunctionEmissionKind
.
METHOD
)
yield
f"}} static constexpr
{
node
.
name
}
{{}};"
yield
""
@
dataclass
class
ClassOuterVisitor
(
NodeVisitor
):
scope
:
Scope
def
visit_AnnAssign
(
self
,
node
:
ast
.
AnnAssign
)
->
Iterable
[
str
]:
yield
""
def
visit_FunctionDef
(
self
,
node
:
ast
.
FunctionDef
)
->
Iterable
[
str
]:
yield
"struct {"
yield
"template<typename Self, typename... T>"
yield
"auto operator()(Self self, T&&... args) {"
yield
f"return dotp(self,
{
node
.
name
}
)(std::forward<T>(args)...);"
yield
"}"
yield
f"}}
{
node
.
name
}
;"
yield
""
# yield "struct : function {"
# from transpiler.phases.emit_cpp.block import BlockVisitor
# yield from BlockVisitor(self.scope).visit_func_new(node, FunctionEmissionKind.METHOD)
# yield f"}} static constexpr {node.name} {{}};"
@
dataclass
class
ClassInnerVisitor2
(
NodeVisitor
):
scope
:
Scope
def
visit_AnnAssign
(
self
,
node
:
ast
.
AnnAssign
)
->
Iterable
[
str
]:
yield
""
def
visit_FunctionDef
(
self
,
node
:
ast
.
FunctionDef
)
->
Iterable
[
str
]:
yield
"struct : referencemodel::method {"
from
transpiler.phases.emit_cpp.block
import
BlockVisitor
yield
from
BlockVisitor
(
self
.
scope
).
visit_func_new
(
node
,
FunctionEmissionKind
.
METHOD
)
yield
f"}} static constexpr
{
node
.
name
}
{{}};"
@
dataclass
class
ClassInnerVisitor4
(
NodeVisitor
):
scope
:
Scope
def
visit_AnnAssign
(
self
,
node
:
ast
.
AnnAssign
)
->
Iterable
[
str
]:
member
=
self
.
scope
.
obj_type
.
fields
[
node
.
target
.
id
]
yield
from
self
.
visit
(
member
.
type
)
yield
node
.
target
.
id
yield
";"
def
visit_FunctionDef
(
self
,
node
:
ast
.
FunctionDef
)
->
Iterable
[
str
]:
yield
""
\ No newline at end of file
typon/trans/transpiler/phases/emit_cpp/function.py
View file @
90409113
# coding: utf-8
import
ast
import
ast
from
dataclasses
import
dataclass
from
dataclasses
import
dataclass
from
typing
import
Iterable
from
typing
import
Iterable
from
transpiler.phases.emit_cpp.consts
import
SYMBOLS
from
transpiler
import
Scope
from
transpiler.phases.emit_cpp
import
CoroutineMode
,
FunctionEmissionKind
from
transpiler.phases.emit_cpp.visitors
import
NodeVisitor
,
flatmap
from
transpiler.phases.emit_cpp.block
import
BlockVisitor
from
transpiler.phases.typing.types
import
CallableInstanceType
from
transpiler.phases.typing.scope
import
Scope
from
transpiler.phases.utils
import
PlainBlock
# noinspection PyPep8Naming
def
emit_function
(
name
:
str
,
func
:
CallableInstanceType
)
->
Iterable
[
str
]:
yield
f"struct : function {{"
yield
"typon::Task<void> operator()() const {"
yield
"}"
yield
f"}} static constexpr
{
name
}
{{}};"
yield
f"static_assert(sizeof
{
name
}
== 1);"
@
dataclass
@
dataclass
class
FunctionVisitor
(
BlockVisitor
):
class
BlockVisitor
(
NodeVisitor
):
def
visit_Expr
(
self
,
node
:
ast
.
Expr
)
->
Iterable
[
str
]:
scope
:
Scope
yield
from
self
.
expr
().
visit
(
node
.
value
)
#generator: CoroutineMode = field(default=CoroutineMode.SYNC, kw_only=True)
yield
";"
def
visit_AugAssign
(
self
,
node
:
ast
.
AugAssign
)
->
Iterable
[
str
]
:
def
expr
(
self
)
->
ExpressionVisitor
:
yield
from
self
.
visit_lvalue
(
node
.
target
,
False
)
return
ExpressionVisitor
(
self
.
scope
,
self
.
generator
)
yield
SYMBOLS
[
type
(
node
.
op
)]
+
"="
yield
from
self
.
expr
().
visit
(
node
.
value
)
def
visit_Pass
(
self
,
node
:
ast
.
Pass
)
->
Iterable
[
str
]:
yield
";"
yield
";"
def
visit_For
(
self
,
node
:
ast
.
For
)
->
Iterable
[
str
]:
# def visit_FunctionDef(self, node: ast.FunctionDef) -> Iterable[str]:
if
not
isinstance
(
node
.
target
,
ast
.
Name
):
# yield from self.visit_free_func(node)
raise
NotImplementedError
(
node
)
if
node
.
orelse
:
def
visit_free_func
(
self
,
node
:
ast
.
FunctionDef
,
emission
:
FunctionEmissionKind
)
->
Iterable
[
str
]:
yield
"auto"
if
getattr
(
node
,
"is_main"
,
False
):
yield
node
.
orelse_variable
if
emission
==
FunctionEmissionKind
.
DECLARATION
:
yield
"= true;"
return
yield
f"for (auto
{
node
.
target
.
id
}
: "
# Special case handling for Python's interesting way of defining an entry point.
yield
from
self
.
expr
().
visit
(
node
.
iter
)
# I mean, it's not *that* bad, it's just an attempt at retrofitting an "entry point" logic in a scripting
yield
")"
# language that, by essence, uses "the start of the file" as the implicit entry point, since files are
yield
from
self
.
emit_block
(
node
.
inner_scope
,
node
.
body
)
# TODO: why not reuse the scope used for analysis? same in while
# read and executed line-by-line, contrary to usual structured languages that mark a distinction between
if
node
.
orelse
:
# declarations (functions, classes, modules, ...) and code.
yield
"if ("
# Also, for nitpickers, the C++ standard explicitly allows for omitting a `return` statement in the `main`.
yield
node
.
orelse_variable
# 0 is returned by default.
yield
")"
yield
"typon::Root root() const"
yield
from
self
.
emit_block
(
node
.
inner_scope
,
node
.
orelse
)
def
block
():
def
visit_If
(
self
,
node
:
ast
.
If
)
->
Iterable
[
str
]:
yield
from
node
.
body
yield
"if ("
yield
ast
.
Return
()
yield
from
self
.
expr
().
visit
(
node
.
test
)
yield
")"
from
transpiler.phases.emit_cpp.function
import
FunctionVisitor
yield
from
self
.
emit_block
(
node
.
inner_scope
,
node
.
body
)
yield
"{"
if
node
.
orelse
:
yield
from
self
.
visit_func_decls
(
block
(),
node
.
scope
,
CoroutineMode
.
TASK
)
yield
"else "
yield
"}"
if
isinstance
(
node
.
orelse
,
ast
.
If
):
return
yield
from
self
.
visit
(
node
.
orelse
)
if
emission
==
FunctionEmissionKind
.
DECLARATION
:
yield
f"struct
{
node
.
name
}
_inner {{"
yield
from
self
.
visit_func_new
(
node
,
emission
)
if
emission
==
FunctionEmissionKind
.
DECLARATION
:
yield
f"}}
{
node
.
name
}
;"
def
visit_func_decls
(
self
,
body
:
list
[
ast
.
stmt
],
inner_scope
:
Scope
,
mode
=
CoroutineMode
.
ASYNC
)
->
Iterable
[
str
]:
for
child
in
body
:
from
transpiler.phases.emit_cpp.function
import
FunctionVisitor
child_visitor
=
FunctionVisitor
(
inner_scope
,
generator
=
mode
)
for
name
,
decl
in
getattr
(
child
,
"decls"
,
{}).
items
():
#yield f"decltype({' '.join(self.expr().visit(decl.type))}) {name};"
yield
from
self
.
visit
(
decl
.
type
)
yield
f"
{
name
}
;"
yield
from
child_visitor
.
visit
(
child
)
def
visit_func_params
(
self
,
args
:
Iterable
[
tuple
[
str
,
BaseType
,
Optional
[
ast
.
expr
]]],
emission
:
FunctionEmissionKind
)
->
Iterable
[
str
]:
for
i
,
(
arg
,
argty
,
default
)
in
enumerate
(
args
):
if
i
!=
0
:
yield
", "
if
emission
==
FunctionEmissionKind
.
METHOD
and
i
==
0
:
yield
"Self"
else
:
else
:
yield
from
self
.
emit_block
(
node
.
orelse_scope
,
node
.
orelse
)
yield
from
self
.
visit
(
argty
)
yield
arg
if
emission
in
{
FunctionEmissionKind
.
DECLARATION
,
FunctionEmissionKind
.
LAMBDA
,
FunctionEmissionKind
.
METHOD
}
and
default
:
yield
" = "
yield
from
self
.
expr
().
visit
(
default
)
def
visit_func_new
(
self
,
node
:
ast
.
FunctionDef
,
emission
:
FunctionEmissionKind
,
skip_first_arg
:
bool
=
False
)
->
Iterable
[
str
]:
if
emission
==
FunctionEmissionKind
.
LAMBDA
:
yield
"[&]"
else
:
if
emission
==
FunctionEmissionKind
.
METHOD
:
yield
"template <typename Self>"
yield
from
self
.
visit
(
node
.
type
.
return_type
)
if
emission
==
FunctionEmissionKind
.
DEFINITION
:
yield
f"
{
node
.
name
}
_inner::"
yield
"operator()"
yield
"("
padded_defaults
=
[
None
]
*
(
len
(
node
.
args
.
args
)
if
node
.
type
.
optional_at
is
None
else
node
.
type
.
optional_at
)
+
node
.
args
.
defaults
args_iter
=
zip
(
node
.
args
.
args
,
node
.
type
.
parameters
,
padded_defaults
)
if
skip_first_arg
:
next
(
args_iter
)
yield
from
self
.
visit_func_params
(((
arg
.
arg
,
argty
,
default
)
for
arg
,
argty
,
default
in
args_iter
),
emission
)
yield
")"
def
visit_PlainBlock
(
self
,
node
:
PlainBlock
)
->
Iterable
[
str
]
:
if
emission
==
FunctionEmissionKind
.
METHOD
:
yield
from
self
.
emit_block
(
node
.
inner_scope
,
node
.
body
)
yield
"const"
def
visit_Return
(
self
,
node
:
ast
.
Return
)
->
Iterable
[
str
]:
inner_scope
=
node
.
inner_scope
if
CoroutineMode
.
ASYNC
in
self
.
generator
:
yield
"co_return "
if
emission
==
FunctionEmissionKind
.
DECLARATION
:
else
:
yield
";"
yield
"return "
return
if
node
.
value
:
yield
from
self
.
expr
().
visit
(
node
.
value
)
if
emission
==
FunctionEmissionKind
.
LAMBDA
:
yield
";"
yield
"->"
yield
from
self
.
visit
(
node
.
type
.
return_type
)
def
visit_While
(
self
,
node
:
ast
.
While
)
->
Iterable
[
str
]:
if
node
.
orelse
:
yield
"auto"
yield
node
.
orelse_variable
yield
"= true;"
yield
"while ("
yield
from
self
.
expr
().
visit
(
node
.
test
)
yield
")"
yield
from
self
.
emit_block
(
node
.
inner_scope
,
node
.
body
)
if
node
.
orelse
:
yield
"if ("
yield
node
.
orelse_variable
yield
")"
yield
from
self
.
emit_block
(
node
.
inner_scope
,
node
.
orelse
)
def
visit_Global
(
self
,
node
:
ast
.
Global
)
->
Iterable
[
str
]:
yield
""
def
visit_Nonlocal
(
self
,
node
:
ast
.
Nonlocal
)
->
Iterable
[
str
]:
yield
""
def
block2
(
self
)
->
"FunctionVisitor"
:
# See the comments in visit_FunctionDef.
# A Python code block does not introduce a new scope, so we create a new `Scope` object that shares the same
# variables as the parent scope.
return
FunctionVisitor
(
self
.
scope
.
child_share
(),
generator
=
self
.
generator
)
def
emit_block
(
self
,
scope
:
Scope
,
items
:
Iterable
[
ast
.
stmt
])
->
Iterable
[
str
]:
yield
"{"
yield
"{"
for
child
in
items
:
yield
from
FunctionVisitor
(
scope
,
generator
=
self
.
generator
).
visit
(
child
)
class
ReturnVisitor
(
SearchVisitor
):
def
visit_Return
(
self
,
node
:
ast
.
Return
)
->
bool
:
yield
True
def
visit_Yield
(
self
,
node
:
ast
.
Yield
)
->
bool
:
yield
True
def
visit_FunctionDef
(
self
,
node
:
ast
.
FunctionDef
):
yield
from
()
def
visit_ClassDef
(
self
,
node
:
ast
.
ClassDef
):
yield
from
()
has_return
=
ReturnVisitor
().
match
(
node
.
body
)
yield
from
self
.
visit_func_decls
(
node
.
body
,
inner_scope
)
# if not has_return and isinstance(node.type.return_type, Promise):
# yield "co_return;"
yield
"}"
yield
"}"
def
visit_Break
(
self
,
node
:
ast
.
Break
)
->
Iterable
[
str
]:
def
visit_lvalue
(
self
,
lvalue
:
ast
.
expr
,
declare
:
bool
|
list
[
bool
]
=
False
)
->
Iterable
[
str
]:
if
(
loop
:
=
self
.
scope
.
is_in_loop
()).
orelse
:
if
isinstance
(
lvalue
,
ast
.
Tuple
):
yield
loop
.
orelse_variable
for
name
,
decl
,
ty
in
zip
(
lvalue
.
elts
,
declare
,
lvalue
.
type
.
args
):
yield
" = false;"
if
decl
:
yield
"break;"
yield
from
self
.
visit_lvalue
(
name
,
True
)
yield
";"
def
visit_Try
(
self
,
node
:
ast
.
Try
)
->
Iterable
[
str
]:
yield
f"std::tie(
{
', '
.
join
(
flatmap
(
self
.
visit_lvalue
,
lvalue
.
elts
))
}
)"
yield
from
self
.
emit_block
(
node
.
inner_scope
,
node
.
body
)
elif
isinstance
(
lvalue
,
ast
.
Name
):
if
node
.
orelse
:
if
lvalue
.
id
==
"_"
:
raise
NotImplementedError
(
node
,
"orelse"
)
if
not
declare
:
if
node
.
finalbody
:
yield
"std::ignore"
raise
NotImplementedError
(
node
,
"finalbody"
)
return
for
handler
in
node
.
handlers
:
name
=
self
.
fix_name
(
lvalue
.
id
)
#yield from self.visit(handler)
# if name not in self._scope.vars:
pass
# if not self.scope.exists_local(name):
# todo
# yield self.scope.declare(name, (" ".join(self.expr().visit(val)), val) if val else None,
# getattr(val, "is_future", False))
def
visit_Raise
(
self
,
node
:
ast
.
Raise
)
->
Iterable
[
str
]:
if
declare
:
yield
"// raise"
yield
from
self
.
visit
(
lvalue
.
type
)
# TODO
yield
name
elif
isinstance
(
lvalue
,
ast
.
Subscript
):
def
visit_FunctionDef
(
self
,
node
:
ast
.
FunctionDef
)
->
Iterable
[
str
]:
yield
from
self
.
expr
().
visit
(
lvalue
)
yield
"auto"
elif
isinstance
(
lvalue
,
ast
.
Attribute
):
yield
self
.
fix_name
(
node
.
name
)
yield
from
self
.
expr
().
visit
(
lvalue
)
yield
"="
else
:
yield
from
self
.
visit_func_new
(
node
,
FunctionEmissionKind
.
LAMBDA
)
raise
NotImplementedError
(
lvalue
)
def
visit_Assign
(
self
,
node
:
ast
.
Assign
)
->
Iterable
[
str
]:
if
len
(
node
.
targets
)
!=
1
:
raise
NotImplementedError
(
node
)
yield
from
self
.
visit_lvalue
(
node
.
targets
[
0
],
node
.
is_declare
)
yield
" = "
yield
from
self
.
expr
().
visit
(
node
.
value
)
yield
";"
def
visit_AnnAssign
(
self
,
node
:
ast
.
AnnAssign
)
->
Iterable
[
str
]:
yield
from
self
.
visit_lvalue
(
node
.
target
,
node
.
is_declare
)
if
node
.
value
:
yield
" = "
yield
from
self
.
expr
().
visit
(
node
.
value
)
yield
";"
yield
";"
typon/trans/transpiler/phases/emit_cpp/module.py
View file @
90409113
# coding: utf-8
import
ast
from
typing
import
Iterable
from
typing
import
Iterable
from
dataclasses
import
dataclass
,
field
from
transpiler.phases.emit_cpp.class_
import
emit_class
from
transpiler.phases.emit_cpp.function
import
emit_function
from
transpiler.phases.typing
import
FunctionType
from
transpiler.phases.typing.modules
import
ModuleType
from
transpiler.phases.typing.scope
import
Scope
from
transpiler.phases.typing.types
import
CallableInstanceType
,
ClassTypeType
from
transpiler.phases.emit_cpp
import
CoroutineMode
,
FunctionEmissionKind
,
NodeVisitor
,
join
from
transpiler.phases.emit_cpp.block
import
BlockVisitor
from
transpiler.phases.emit_cpp.class_
import
ClassVisitor
,
ClassInnerVisitor
,
ClassInnerVisitor2
,
ClassInnerVisitor4
def
emit_module
(
mod
:
ModuleType
)
->
Iterable
[
str
]:
from
transpiler.phases.emit_cpp.function
import
FunctionVisitor
yield
"#include <python/builtins.hpp>"
from
transpiler.utils
import
compare_ast
,
highlight
yield
"#include <python/sys.hpp>"
yield
"namespace PROGRAMNS {"
IGNORED_IMPORTS
=
{
"typon"
,
"typing"
,
"__future__"
,
"dataclasses"
,
"enum"
}
yield
"template <typename _Unused = void>"
yield
f"struct
{
mod
.
name
()
}
__oo : referencemodel::moduletype<
{
mod
.
name
()
}
__oo<>>"
# noinspection PyPep8Naming
yield
"{"
@
dataclass
for
name
,
field
in
mod
.
fields
.
items
():
class
ModuleVisitor
(
BlockVisitor
):
if
not
field
.
in_class_def
:
includes
:
list
[
str
]
=
field
(
default_factory
=
list
)
continue
def
visit_Import
(
self
,
node
:
ast
.
Import
)
->
Iterable
[
str
]:
ty
=
field
.
type
.
deref
()
__TB__
=
f"emitting C++ code for
{
highlight
(
node
)
}
"
x
=
5
for
alias
in
node
.
names
:
match
ty
:
concrete
=
self
.
fix_name
(
alias
.
asname
or
alias
.
name
)
case
CallableInstanceType
():
if
alias
.
module_obj
.
is_python
:
yield
from
emit_function
(
name
,
ty
)
yield
f"namespace py_
{
concrete
}
{{"
case
ClassTypeType
():
yield
f"struct
{
concrete
}
_t {{"
yield
from
emit_class
(
ty
)
case
_
:
for
name
,
obj
in
alias
.
module_obj
.
fields
.
items
():
raise
NotImplementedError
(
f"Unsupported module item type
{
ty
}
"
)
ty
=
obj
.
type
.
resolve
()
if
getattr
(
ty
,
"python_func_used"
,
False
):
yield
"};"
yield
from
self
.
emit_python_func
(
alias
.
name
,
name
,
name
,
ty
)
yield
f"constexpr
{
mod
.
name
()
}
__oo<>
{
mod
.
name
()
}
;"
yield
f"static_assert(sizeof
{
mod
.
name
()
}
== 1);"
yield
"} all;"
yield
"}"
yield
f"auto& get_all() {{ return all; }}"
yield
"}"
yield
f'auto&
{
concrete
}
= py_
{
concrete
}
::get_all();'
elif
alias
.
name
in
IGNORED_IMPORTS
:
yield
""
else
:
yield
from
self
.
import_module
(
alias
.
name
)
yield
f'auto&
{
concrete
}
= py_
{
alias
.
name
}
::get_all();'
def
import_module
(
self
,
name
:
str
)
->
Iterable
[
str
]:
self
.
includes
.
append
(
f'#include <python/
{
name
}
.hpp>'
)
yield
""
def
emit_python_func
(
self
,
mod
:
str
,
name
:
str
,
alias
:
str
,
fty
:
FunctionType
)
->
Iterable
[
str
]:
__TB__
=
f"emitting C++ code for Python function
{
highlight
(
f'
{
mod
}
.
{
name
}
')
}
"
yield
"struct {"
yield
f"auto operator()("
for
i
,
argty
in
enumerate
(
fty
.
parameters
):
if
i
!=
0
:
yield
", "
yield
"lvalue_or_rvalue<"
yield
from
self
.
visit
(
argty
)
yield
f"> arg
{
i
}
"
yield
") {"
yield
"InterpGuard guard{};"
yield
"try {"
yield
f"return py::module_::import(
\
"
{
mod
}\
"
).attr(
\
"
{
name
}\
"
)("
for
i
,
argty
in
enumerate
(
fty
.
parameters
):
if
i
!=
0
:
yield
", "
yield
f"*arg
{
i
}
"
yield
").cast<"
yield
from
self
.
visit
(
fty
.
return_type
)
yield
">();"
yield
"} catch (py::error_already_set& e) {"
yield
'std::cerr << "Python exception: " << e.what() << std::endl;'
yield
"throw;"
yield
"}"
yield
"}"
yield
f"}}
{
alias
}
;"
def
visit_ImportFrom
(
self
,
node
:
ast
.
ImportFrom
)
->
Iterable
[
str
]:
if
node
.
module
in
IGNORED_IMPORTS
:
yield
""
elif
node
.
module_obj
.
is_python
:
for
alias
in
node
.
names
:
fty
=
alias
.
item_obj
.
resolve
()
#assert isinstance(fty, FunctionType)
yield
from
self
.
emit_python_func
(
node
.
module
,
alias
.
name
,
alias
.
asname
or
alias
.
name
,
fty
)
else
:
yield
from
self
.
import_module
(
node
.
module
)
for
alias
in
node
.
names
:
yield
f"auto&
{
alias
.
asname
or
alias
.
name
}
= py_
{
node
.
module
}
::get_all().
{
alias
.
name
}
;"
def
visit_Expr
(
self
,
node
:
ast
.
Expr
)
->
Iterable
[
str
]:
if
isinstance
(
node
.
value
,
ast
.
Str
):
if
"
\
n
"
in
node
.
value
.
s
:
yield
f"/*
{
node
.
value
.
s
}
*/"
else
:
yield
f"//
{
node
.
value
.
s
}
"
else
:
raise
NotImplementedError
(
node
)
def
visit_ClassDef
(
self
,
node
:
ast
.
ClassDef
)
->
Iterable
[
str
]:
#yield from ClassVisitor().visit(node)
yield
from
()
def
visit_FunctionDef
(
self
,
node
:
ast
.
FunctionDef
)
->
Iterable
[
str
]:
yield
from
super
().
visit_free_func
(
node
,
FunctionEmissionKind
.
DECLARATION
)
@
dataclass
class
ModuleVisitor2
(
NodeVisitor
):
scope
:
Scope
def
visit_FunctionDef
(
self
,
node
:
ast
.
FunctionDef
)
->
Iterable
[
str
]:
yield
from
BlockVisitor
(
self
.
scope
).
visit_free_func
(
node
,
FunctionEmissionKind
.
DEFINITION
)
def
visit_AST
(
self
,
node
:
ast
.
AST
)
->
Iterable
[
str
]:
yield
""
pass
@
dataclass
class
ModuleVisitor3
(
NodeVisitor
):
scope
:
Scope
def
visit_ClassDef
(
self
,
node
:
ast
.
ClassDef
)
->
Iterable
[
str
]:
yield
from
()
return
if
gen_instances
:
=
getattr
(
node
,
"gen_instances"
,
None
):
for
args
,
inst
in
gen_instances
.
items
():
yield
from
self
.
visit_ClassDef
(
inst
)
return
yield
f"static constexpr _detail_<__main__>::
{
node
.
name
}
<>
{
node
.
name
}
{{}};"
def
visit_FunctionDef
(
self
,
node
:
ast
.
FunctionDef
)
->
Iterable
[
str
]:
yield
from
BlockVisitor
(
self
.
scope
).
visit_free_func
(
node
,
FunctionEmissionKind
.
DEFINITION
)
@
dataclass
class
ModuleVisitor4
(
NodeVisitor
):
scope
:
Scope
def
visit_ClassDef
(
self
,
node
:
ast
.
ClassDef
)
->
Iterable
[
str
]:
if
gen_instances
:
=
getattr
(
node
,
"gen_instances"
,
None
):
for
args
,
inst
in
gen_instances
.
items
():
yield
from
self
.
visit_ClassDef
(
inst
)
return
yield
f"template <typename _Base0 = referencemodel::object>"
yield
f"struct
{
node
.
name
}
__oo : referencemodel::classtype<_Base0,
{
node
.
name
}
__oo<>> {{"
yield
f"static constexpr std::string_view name =
\
"
{
node
.
name
}\
"
;"
inner
=
ClassInnerVisitor2
(
node
.
inner_scope
)
for
stmt
in
node
.
body
:
yield
from
inner
.
visit
(
stmt
)
yield
f"struct Obj : referencemodel::instance<
{
node
.
name
}
__oo<>, Obj> {{"
inner
=
ClassInnerVisitor4
(
node
.
inner_scope
)
for
stmt
in
node
.
body
:
yield
from
inner
.
visit
(
stmt
)
yield
"template <typename... U>"
yield
"Obj(U&&... args) {"
yield
"dot(this, __init__)(this, std::forward<U>(args)...);"
yield
"}"
yield
"};"
yield
"template <typename... T>"
yield
"auto operator() (T&&... args) const {"
yield
"return referencemodel::rc(Obj{std::forward<T>(args)...});"
yield
"}"
yield
f"}};"
yield
f"static constexpr
{
node
.
name
}
__oo<>
{
node
.
name
}
{{}};"
yield
f"static_assert(sizeof
{
node
.
name
}
== 1);"
def
visit_FunctionDef
(
self
,
node
:
ast
.
FunctionDef
)
->
Iterable
[
str
]:
yield
from
()
@
dataclass
class
ModuleVisitorExt
(
NodeVisitor
):
scope
:
Scope
def
visit_FunctionDef
(
self
,
node
:
ast
.
FunctionDef
)
->
Iterable
[
str
]:
if
getattr
(
node
,
"is_main"
,
False
):
yield
from
()
return
#yield from BlockVisitor(self.scope).visit_free_func(node, FunctionEmissionKind.DEFINITION)
#yield f'm.def("{node.name}", CoroWrapper(PROGRAMNS::{node.name}));'
yield
f'm.def("
{
node
.
name
}
", PROGRAMNS::
{
node
.
name
}
);'
def
visit_ClassDef
(
self
,
node
:
ast
.
ClassDef
)
->
Iterable
[
str
]:
if
gen_instances
:
=
getattr
(
node
,
"gen_instances"
,
None
):
for
args
,
inst
in
gen_instances
.
items
():
yield
from
self
.
visit_ClassDef
(
inst
)
return
yield
f"py::class_<PROGRAMNS::
{
node
.
name
}
_s::py_type>(m,
\
"
{
node
.
name
}\
"
)"
if
init
:
=
node
.
type
.
fields
.
get
(
"__init__"
,
None
):
init
=
init
.
type
.
resolve
().
remove_self
()
init_params
=
init
.
parameters
yield
".def(py::init<"
yield
from
join
(
", "
,
map
(
self
.
visit
,
init_params
))
yield
">())"
yield
f'.def("__repr__", [](const PROGRAMNS::
{
node
.
name
}
_s::py_type& self)'
yield
"{ return repr(self); })"
for
f
,
v
in
node
.
type
.
fields
.
items
():
if
f
==
"__init__"
:
continue
if
isinstance
(
v
.
type
,
FunctionType
):
meth
=
v
.
type
.
remove_self
()
yield
f'.def("
{
f
}
", [](const PROGRAMNS::
{
node
.
name
}
_s::py_type& a'
if
meth
.
parameters
:
yield
","
vis
=
BlockVisitor
(
node
.
scope
)
yield
from
vis
.
visit_func_params
(((
f"arg
{
i
}
"
,
ty
,
None
)
for
i
,
ty
in
enumerate
(
meth
.
parameters
)),
FunctionEmissionKind
.
LAMBDA
)
yield
f') {{ return dotp(&a,
{
f
}
)('
if
meth
.
parameters
:
yield
from
join
(
", "
,
(
f"arg
{
i
}
"
for
i
,
_
in
enumerate
(
meth
.
parameters
)))
yield
').call(); })'
else
:
yield
f'.def_readwrite("
{
f
}
", &PROGRAMNS::
{
node
.
name
}
_s::py_type::
{
f
}
)'
yield
";"
pass
def
visit_AST
(
self
,
node
:
ast
.
AST
)
->
Iterable
[
str
]:
yield
from
()
pass
typon/trans/transpiler/phases/emit_cpp/visitors.py
0 → 100644
View file @
90409113
import
ast
from
itertools
import
chain
from
typing
import
Iterable
from
transpiler
import
highlight
import
transpiler.phases.typing.types
as
types
from
transpiler.phases.typing.exceptions
import
UnresolvedTypeVariableError
from
transpiler.phases.typing.types
import
BaseType
from
transpiler.utils
import
UnsupportedNodeError
class
UniversalVisitor
:
def
visit
(
self
,
node
):
"""Visit a node."""
__TB__
=
f"emitting C++ code for
{
highlight
(
node
)
}
"
# __TB_SKIP__ = True
if
type
(
node
)
==
list
:
for
n
in
node
:
yield
from
self
.
visit
(
n
)
else
:
for
parent
in
node
.
__class__
.
__mro__
:
if
visitor
:
=
getattr
(
self
,
'visit_'
+
parent
.
__name__
,
None
):
yield
from
visitor
(
node
)
break
else
:
yield
from
self
.
missing_impl
(
node
)
def
missing_impl
(
self
,
node
):
raise
UnsupportedNodeError
(
node
)
class
NodeVisitor
(
UniversalVisitor
):
def
process_args
(
self
,
node
:
ast
.
arguments
)
->
(
str
,
str
,
str
):
for
field
in
(
"posonlyargs"
,
"vararg"
,
"kwonlyargs"
,
"kw_defaults"
,
"kwarg"
,
"defaults"
):
if
getattr
(
node
,
field
,
None
):
raise
NotImplementedError
(
node
,
field
)
if
not
node
.
args
:
return
""
,
"()"
,
[]
f_args
=
[(
self
.
fix_name
(
arg
.
arg
),
f"T
{
i
+
1
}
"
)
for
i
,
arg
in
enumerate
(
node
.
args
)]
return
(
"<"
+
", "
.
join
(
f"typename
{
t
}
"
for
_
,
t
in
f_args
)
+
">"
,
"("
+
", "
.
join
(
f"
{
t
}
{
n
}
"
for
n
,
t
in
f_args
)
+
")"
,
[
n
for
n
,
_
in
f_args
]
)
def
fix_name
(
self
,
name
:
str
)
->
str
:
if
name
.
startswith
(
"__"
)
and
name
.
endswith
(
"__"
):
return
f"py_
{
name
[
2
:
-
2
]
}
"
return
MAPPINGS
.
get
(
name
,
name
)
def
visit_BaseType
(
self
,
node
:
BaseType
)
->
Iterable
[
str
]:
node
=
node
.
resolve
()
match
node
:
case
types
.
TY_INT
:
yield
"int"
case
types
.
TY_FLOAT
:
yield
"double"
case
types
.
TY_BOOL
:
yield
"bool"
case
types
.
TY_NONE
:
yield
"void"
case
types
.
TY_STR
:
yield
"PyStr"
case
types
.
TypeVariable
(
name
):
raise
UnresolvedTypeVariableError
(
node
)
case
_
:
raise
NotImplementedError
(
node
)
def
join
(
sep
:
str
,
items
:
Iterable
[
Iterable
[
str
]])
->
Iterable
[
str
]:
items
=
iter
(
items
)
try
:
it
=
next
(
items
)
if
type
(
it
)
is
str
:
yield
it
else
:
yield
from
it
for
item
in
items
:
yield
sep
it
=
item
if
type
(
it
)
is
str
:
yield
it
else
:
yield
from
it
except
StopIteration
:
return
def
flatmap
(
f
,
items
):
return
chain
.
from_iterable
(
map
(
f
,
items
))
typon/trans/transpiler/phases/emit_cpp2/__init__.py
0 → 100644
View file @
90409113
# coding: utf-8
import
ast
import
enum
from
enum
import
Flag
from
itertools
import
chain
from
typing
import
Iterable
from
transpiler.phases.emit_cpp.consts
import
MAPPINGS
from
transpiler.phases.typing
import
TypeVariable
from
transpiler.phases.typing.exceptions
import
UnresolvedTypeVariableError
from
transpiler.phases.typing.types
import
BaseType
,
TY_INT
,
TY_BOOL
,
TY_NONE
,
Promise
,
PromiseKind
,
TY_STR
,
UserType
,
\
TypeType
,
TypeOperator
,
TY_FLOAT
,
FunctionType
,
UnionType
from
transpiler.utils
import
UnsupportedNodeError
,
highlight
class
UniversalVisitor
:
def
visit
(
self
,
node
):
"""Visit a node."""
__TB__
=
f"emitting C++ code for
{
highlight
(
node
)
}
"
# __TB_SKIP__ = True
if
type
(
node
)
==
list
:
for
n
in
node
:
yield
from
self
.
visit
(
n
)
else
:
for
parent
in
node
.
__class__
.
__mro__
:
if
visitor
:
=
getattr
(
self
,
'visit_'
+
parent
.
__name__
,
None
):
yield
from
visitor
(
node
)
break
else
:
yield
from
self
.
missing_impl
(
node
)
def
missing_impl
(
self
,
node
):
raise
UnsupportedNodeError
(
node
)
class
NodeVisitor
(
UniversalVisitor
):
def
process_args
(
self
,
node
:
ast
.
arguments
)
->
(
str
,
str
,
str
):
for
field
in
(
"posonlyargs"
,
"vararg"
,
"kwonlyargs"
,
"kw_defaults"
,
"kwarg"
,
"defaults"
):
if
getattr
(
node
,
field
,
None
):
raise
NotImplementedError
(
node
,
field
)
if
not
node
.
args
:
return
""
,
"()"
,
[]
f_args
=
[(
self
.
fix_name
(
arg
.
arg
),
f"T
{
i
+
1
}
"
)
for
i
,
arg
in
enumerate
(
node
.
args
)]
return
(
"<"
+
", "
.
join
(
f"typename
{
t
}
"
for
_
,
t
in
f_args
)
+
">"
,
"("
+
", "
.
join
(
f"
{
t
}
{
n
}
"
for
n
,
t
in
f_args
)
+
")"
,
[
n
for
n
,
_
in
f_args
]
)
def
fix_name
(
self
,
name
:
str
)
->
str
:
if
name
.
startswith
(
"__"
)
and
name
.
endswith
(
"__"
):
return
f"py_
{
name
[
2
:
-
2
]
}
"
return
MAPPINGS
.
get
(
name
,
name
)
def
visit_BaseType
(
self
,
node
:
BaseType
)
->
Iterable
[
str
]:
node
=
node
.
resolve
()
if
node
is
TY_INT
:
yield
"int"
elif
node
is
TY_FLOAT
:
yield
"double"
elif
node
is
TY_BOOL
:
yield
"bool"
elif
node
is
TY_NONE
:
yield
"void"
elif
node
is
TY_STR
:
yield
"PyStr"
elif
isinstance
(
node
,
UserType
):
# if node.is_reference:
# yield "PyObj<"
#yield "auto"
yield
f"referencemodel::Rc<__main____oo<>::
{
node
.
name
}
__oo<>::Obj>"
# if node.is_reference:
# yield "::py_type>"
elif
isinstance
(
node
,
TypeType
):
yield
"auto"
# TODO
elif
isinstance
(
node
,
FunctionType
):
yield
"std::function<"
yield
from
self
.
visit
(
node
.
return_type
)
yield
"("
yield
from
join
(
", "
,
map
(
self
.
visit
,
node
.
parameters
))
yield
")>"
elif
isinstance
(
node
,
Promise
):
yield
"typon::"
if
node
.
kind
==
PromiseKind
.
TASK
:
yield
"Task"
elif
node
.
kind
==
PromiseKind
.
JOIN
:
yield
"Join"
elif
node
.
kind
==
PromiseKind
.
FUTURE
:
yield
"Future"
elif
node
.
kind
==
PromiseKind
.
FORKED
:
yield
"Forked"
elif
node
.
kind
==
PromiseKind
.
GENERATOR
:
yield
"Generator"
else
:
raise
NotImplementedError
(
node
)
yield
"<"
yield
from
self
.
visit
(
node
.
return_type
)
yield
">"
elif
isinstance
(
node
,
TypeVariable
):
# yield f"TYPEVAR_{node.name}";return
raise
UnresolvedTypeVariableError
(
node
)
elif
isinstance
(
node
,
UnionType
)
and
(
ty
:
=
node
.
is_optional
()):
yield
"std::optional<"
yield
from
self
.
visit
(
ty
)
yield
">"
elif
isinstance
(
node
,
TypeOperator
):
yield
"typon::Py"
+
node
.
name
.
title
()
if
node
.
args
:
yield
"<"
yield
from
join
(
", "
,
map
(
self
.
visit
,
node
.
args
))
yield
">"
else
:
raise
NotImplementedError
(
node
)
class
CoroutineMode
(
Flag
):
SYNC
=
1
FAKE
=
2
|
SYNC
ASYNC
=
4
GENERATOR
=
8
|
ASYNC
TASK
=
16
|
ASYNC
JOIN
=
32
|
ASYNC
class
FunctionEmissionKind
(
enum
.
Enum
):
DECLARATION
=
enum
.
auto
()
DEFINITION
=
enum
.
auto
()
METHOD
=
enum
.
auto
()
LAMBDA
=
enum
.
auto
()
typon/trans/transpiler/phases/emit_cpp/block.py
→
typon/trans/transpiler/phases/emit_cpp
2
/block.py
View file @
90409113
...
@@ -5,7 +5,7 @@ from typing import Iterable, Optional
...
@@ -5,7 +5,7 @@ from typing import Iterable, Optional
from
transpiler.phases.typing.common
import
is_builtin
from
transpiler.phases.typing.common
import
is_builtin
from
transpiler.phases.typing.scope
import
Scope
from
transpiler.phases.typing.scope
import
Scope
from
transpiler.phases.typing.types
import
BaseType
,
TY_INT
,
TY_BOOL
,
TypeVariable
,
Promise
,
TypeType
from
transpiler.phases.typing.types
import
BaseType
,
TY_INT
,
TY_BOOL
,
TypeVariable
from
transpiler.utils
import
compare_ast
from
transpiler.utils
import
compare_ast
from
transpiler.phases.emit_cpp
import
NodeVisitor
,
CoroutineMode
,
flatmap
,
FunctionEmissionKind
from
transpiler.phases.emit_cpp
import
NodeVisitor
,
CoroutineMode
,
flatmap
,
FunctionEmissionKind
from
transpiler.phases.emit_cpp.expr
import
ExpressionVisitor
from
transpiler.phases.emit_cpp.expr
import
ExpressionVisitor
...
...
typon/trans/transpiler/phases/emit_cpp2/class_.py
0 → 100644
View file @
90409113
# coding: utf-8
import
ast
from
typing
import
Iterable
from
dataclasses
import
dataclass
from
transpiler.phases.typing.scope
import
Scope
from
transpiler.phases.emit_cpp
import
NodeVisitor
,
FunctionEmissionKind
class
ClassVisitor
(
NodeVisitor
):
def
visit_ClassDef
(
self
,
node
:
ast
.
ClassDef
)
->
Iterable
[
str
]:
if
gen_instances
:
=
getattr
(
node
,
"gen_instances"
,
None
):
for
args
,
inst
in
gen_instances
.
items
():
yield
from
self
.
visit_ClassDef
(
inst
)
return
yield
f"struct
{
node
.
name
}
_s;"
yield
f"extern
{
node
.
name
}
_s
{
node
.
name
}
;"
yield
f"struct
{
node
.
name
}
_s {{"
yield
"struct py_type {"
inner
=
ClassInnerVisitor
(
node
.
inner_scope
)
for
stmt
in
node
.
body
:
yield
from
inner
.
visit
(
stmt
)
yield
"template<typename... T> py_type(T&&... args) {"
yield
"__init__(this, std::forward<T>(args)...);"
yield
"}"
yield
"py_type() {}"
yield
"py_type(const py_type&) = delete;"
yield
"py_type(py_type&&) = delete;"
if
getattr
(
node
.
type
,
"is_enum"
,
False
):
yield
"int value;"
yield
"operator int() const { return value; }"
yield
"void py_repr(std::ostream &s) const {"
yield
f's << "
{
node
.
name
}
.";'
yield
"}"
else
:
yield
"void py_repr(std::ostream &s) const {"
yield
f's << "
{
node
.
name
}
(";'
for
i
,
(
name
,
memb
)
in
enumerate
(
node
.
type
.
get_members
().
items
()):
if
i
!=
0
:
yield
's << ", ";'
yield
f's << "
{
name
}
=";'
yield
f"repr_to(
{
name
}
, s);"
yield
"s << ')';"
yield
"}"
yield
"void py_print(std::ostream &s) const {"
yield
"py_repr(s);"
yield
"}"
yield
"};"
yield
"template<typename... T> auto operator()(T&&... args) {"
yield
"return pyobj<py_type>(std::forward<T>(args)...);"
yield
"}"
# outer = ClassOuterVisitor(node.inner_scope)
# for stmt in node.body:
# yield from outer.visit(stmt)
yield
f"}}
{
node
.
name
}
;"
@
dataclass
class
ClassInnerVisitor
(
NodeVisitor
):
scope
:
Scope
def
visit_AnnAssign
(
self
,
node
:
ast
.
AnnAssign
)
->
Iterable
[
str
]:
member
=
self
.
scope
.
obj_type
.
fields
[
node
.
target
.
id
]
yield
from
self
.
visit
(
member
.
type
)
yield
node
.
target
.
id
yield
";"
def
visit_Assign
(
self
,
node
:
ast
.
Assign
)
->
Iterable
[
str
]:
yield
"static constexpr"
from
transpiler.phases.emit_cpp.block
import
BlockVisitor
yield
from
BlockVisitor
(
self
.
scope
).
visit_Assign
(
node
)
def
visit_FunctionDef
(
self
,
node
:
ast
.
FunctionDef
)
->
Iterable
[
str
]:
# yield "struct {"
# yield "type* self;"
# from transpiler.phases.emit_cpp.block import BlockVisitor
# yield from BlockVisitor(self.scope).visit_func_new(node, FunctionEmissionKind.METHOD, True)
# yield f"}} {node.name} {{ this }};"
yield
f"struct
{
node
.
name
}
_m_s : referencemodel::method {{"
from
transpiler.phases.emit_cpp.block
import
BlockVisitor
yield
from
BlockVisitor
(
self
.
scope
).
visit_func_new
(
node
,
FunctionEmissionKind
.
METHOD
)
yield
f"}} static constexpr
{
node
.
name
}
{{}};"
yield
""
@
dataclass
class
ClassOuterVisitor
(
NodeVisitor
):
scope
:
Scope
def
visit_AnnAssign
(
self
,
node
:
ast
.
AnnAssign
)
->
Iterable
[
str
]:
yield
""
def
visit_FunctionDef
(
self
,
node
:
ast
.
FunctionDef
)
->
Iterable
[
str
]:
yield
"struct {"
yield
"template<typename Self, typename... T>"
yield
"auto operator()(Self self, T&&... args) {"
yield
f"return dotp(self,
{
node
.
name
}
)(std::forward<T>(args)...);"
yield
"}"
yield
f"}}
{
node
.
name
}
;"
yield
""
# yield "struct : function {"
# from transpiler.phases.emit_cpp.block import BlockVisitor
# yield from BlockVisitor(self.scope).visit_func_new(node, FunctionEmissionKind.METHOD)
# yield f"}} static constexpr {node.name} {{}};"
@
dataclass
class
ClassInnerVisitor2
(
NodeVisitor
):
scope
:
Scope
def
visit_AnnAssign
(
self
,
node
:
ast
.
AnnAssign
)
->
Iterable
[
str
]:
yield
""
def
visit_FunctionDef
(
self
,
node
:
ast
.
FunctionDef
)
->
Iterable
[
str
]:
yield
"struct : referencemodel::method {"
from
transpiler.phases.emit_cpp.block
import
BlockVisitor
yield
from
BlockVisitor
(
self
.
scope
).
visit_func_new
(
node
,
FunctionEmissionKind
.
METHOD
)
yield
f"}} static constexpr
{
node
.
name
}
{{}};"
@
dataclass
class
ClassInnerVisitor4
(
NodeVisitor
):
scope
:
Scope
def
visit_AnnAssign
(
self
,
node
:
ast
.
AnnAssign
)
->
Iterable
[
str
]:
member
=
self
.
scope
.
obj_type
.
fields
[
node
.
target
.
id
]
yield
from
self
.
visit
(
member
.
type
)
yield
node
.
target
.
id
yield
";"
def
visit_FunctionDef
(
self
,
node
:
ast
.
FunctionDef
)
->
Iterable
[
str
]:
yield
""
\ No newline at end of file
typon/trans/transpiler/phases/emit_cpp/consts.py
→
typon/trans/transpiler/phases/emit_cpp
2
/consts.py
View file @
90409113
File moved
typon/trans/transpiler/phases/emit_cpp/expr.py
→
typon/trans/transpiler/phases/emit_cpp
2
/expr.py
View file @
90409113
...
@@ -219,30 +219,12 @@ class ExpressionVisitor(NodeVisitor):
...
@@ -219,30 +219,12 @@ class ExpressionVisitor(NodeVisitor):
yield
")"
yield
")"
def
visit_Attribute
(
self
,
node
:
ast
.
Attribute
)
->
Iterable
[
str
]:
def
visit_Attribute
(
self
,
node
:
ast
.
Attribute
)
->
Iterable
[
str
]:
use_dot
=
None
yield
"dot"
if
type
(
node
.
value
.
type
)
==
TypeType
:
yield
"(("
use_dot
=
"dots"
yield
from
self
.
visit
(
node
.
value
)
elif
isinstance
(
node
.
type
,
FunctionType
)
and
node
.
type
.
is_method
and
not
isinstance
(
node
.
value
.
type
,
Promise
):
yield
"), "
if
node
.
value
.
type
.
resolve
().
is_reference
:
yield
self
.
fix_name
(
node
.
attr
)
use_dot
=
"dotp"
yield
")"
else
:
use_dot
=
"dot"
if
use_dot
:
use_dot
=
"dot"
if
use_dot
:
yield
use_dot
yield
"(("
yield
from
self
.
visit
(
node
.
value
)
yield
"), "
yield
self
.
fix_name
(
node
.
attr
)
yield
")"
else
:
yield
from
self
.
prec
(
"."
).
visit
(
node
.
value
)
if
node
.
value
.
type
.
resolve
().
is_reference
:
yield
"->"
else
:
yield
"."
yield
self
.
fix_name
(
node
.
attr
)
def
visit_List
(
self
,
node
:
ast
.
List
)
->
Iterable
[
str
]:
def
visit_List
(
self
,
node
:
ast
.
List
)
->
Iterable
[
str
]:
if
node
.
elts
:
if
node
.
elts
:
...
...
typon/trans/transpiler/phases/emit_cpp/file.py
→
typon/trans/transpiler/phases/emit_cpp
2
/file.py
View file @
90409113
File moved
typon/trans/transpiler/phases/emit_cpp2/function.py
0 → 100644
View file @
90409113
# coding: utf-8
import
ast
from
dataclasses
import
dataclass
from
typing
import
Iterable
from
transpiler.phases.emit_cpp.consts
import
SYMBOLS
from
transpiler.phases.emit_cpp
import
CoroutineMode
,
FunctionEmissionKind
from
transpiler.phases.emit_cpp.block
import
BlockVisitor
from
transpiler.phases.typing.scope
import
Scope
from
transpiler.phases.utils
import
PlainBlock
# noinspection PyPep8Naming
@
dataclass
class
FunctionVisitor
(
BlockVisitor
):
def
visit_Expr
(
self
,
node
:
ast
.
Expr
)
->
Iterable
[
str
]:
yield
from
self
.
expr
().
visit
(
node
.
value
)
yield
";"
def
visit_AugAssign
(
self
,
node
:
ast
.
AugAssign
)
->
Iterable
[
str
]:
yield
from
self
.
visit_lvalue
(
node
.
target
,
False
)
yield
SYMBOLS
[
type
(
node
.
op
)]
+
"="
yield
from
self
.
expr
().
visit
(
node
.
value
)
yield
";"
def
visit_For
(
self
,
node
:
ast
.
For
)
->
Iterable
[
str
]:
if
not
isinstance
(
node
.
target
,
ast
.
Name
):
raise
NotImplementedError
(
node
)
if
node
.
orelse
:
yield
"auto"
yield
node
.
orelse_variable
yield
"= true;"
yield
f"for (auto
{
node
.
target
.
id
}
: "
yield
from
self
.
expr
().
visit
(
node
.
iter
)
yield
")"
yield
from
self
.
emit_block
(
node
.
inner_scope
,
node
.
body
)
# TODO: why not reuse the scope used for analysis? same in while
if
node
.
orelse
:
yield
"if ("
yield
node
.
orelse_variable
yield
")"
yield
from
self
.
emit_block
(
node
.
inner_scope
,
node
.
orelse
)
def
visit_If
(
self
,
node
:
ast
.
If
)
->
Iterable
[
str
]:
yield
"if ("
yield
from
self
.
expr
().
visit
(
node
.
test
)
yield
")"
yield
from
self
.
emit_block
(
node
.
inner_scope
,
node
.
body
)
if
node
.
orelse
:
yield
"else "
if
isinstance
(
node
.
orelse
,
ast
.
If
):
yield
from
self
.
visit
(
node
.
orelse
)
else
:
yield
from
self
.
emit_block
(
node
.
orelse_scope
,
node
.
orelse
)
def
visit_PlainBlock
(
self
,
node
:
PlainBlock
)
->
Iterable
[
str
]:
yield
from
self
.
emit_block
(
node
.
inner_scope
,
node
.
body
)
def
visit_Return
(
self
,
node
:
ast
.
Return
)
->
Iterable
[
str
]:
if
CoroutineMode
.
ASYNC
in
self
.
generator
:
yield
"co_return "
else
:
yield
"return "
if
node
.
value
:
yield
from
self
.
expr
().
visit
(
node
.
value
)
yield
";"
def
visit_While
(
self
,
node
:
ast
.
While
)
->
Iterable
[
str
]:
if
node
.
orelse
:
yield
"auto"
yield
node
.
orelse_variable
yield
"= true;"
yield
"while ("
yield
from
self
.
expr
().
visit
(
node
.
test
)
yield
")"
yield
from
self
.
emit_block
(
node
.
inner_scope
,
node
.
body
)
if
node
.
orelse
:
yield
"if ("
yield
node
.
orelse_variable
yield
")"
yield
from
self
.
emit_block
(
node
.
inner_scope
,
node
.
orelse
)
def
visit_Global
(
self
,
node
:
ast
.
Global
)
->
Iterable
[
str
]:
yield
""
def
visit_Nonlocal
(
self
,
node
:
ast
.
Nonlocal
)
->
Iterable
[
str
]:
yield
""
def
block2
(
self
)
->
"FunctionVisitor"
:
# See the comments in visit_FunctionDef.
# A Python code block does not introduce a new scope, so we create a new `Scope` object that shares the same
# variables as the parent scope.
return
FunctionVisitor
(
self
.
scope
.
child_share
(),
generator
=
self
.
generator
)
def
emit_block
(
self
,
scope
:
Scope
,
items
:
Iterable
[
ast
.
stmt
])
->
Iterable
[
str
]:
yield
"{"
for
child
in
items
:
yield
from
FunctionVisitor
(
scope
,
generator
=
self
.
generator
).
visit
(
child
)
yield
"}"
def
visit_Break
(
self
,
node
:
ast
.
Break
)
->
Iterable
[
str
]:
if
(
loop
:
=
self
.
scope
.
is_in_loop
()).
orelse
:
yield
loop
.
orelse_variable
yield
" = false;"
yield
"break;"
def
visit_Try
(
self
,
node
:
ast
.
Try
)
->
Iterable
[
str
]:
yield
from
self
.
emit_block
(
node
.
inner_scope
,
node
.
body
)
if
node
.
orelse
:
raise
NotImplementedError
(
node
,
"orelse"
)
if
node
.
finalbody
:
raise
NotImplementedError
(
node
,
"finalbody"
)
for
handler
in
node
.
handlers
:
#yield from self.visit(handler)
pass
# todo
def
visit_Raise
(
self
,
node
:
ast
.
Raise
)
->
Iterable
[
str
]:
yield
"// raise"
# TODO
def
visit_FunctionDef
(
self
,
node
:
ast
.
FunctionDef
)
->
Iterable
[
str
]:
yield
"auto"
yield
self
.
fix_name
(
node
.
name
)
yield
"="
yield
from
self
.
visit_func_new
(
node
,
FunctionEmissionKind
.
LAMBDA
)
yield
";"
typon/trans/transpiler/phases/emit_cpp2/module.py
0 → 100644
View file @
90409113
# coding: utf-8
import
ast
from
typing
import
Iterable
from
dataclasses
import
dataclass
,
field
from
transpiler.phases.typing
import
FunctionType
from
transpiler.phases.typing.scope
import
Scope
from
transpiler.phases.emit_cpp
import
CoroutineMode
,
FunctionEmissionKind
,
NodeVisitor
,
join
from
transpiler.phases.emit_cpp.block
import
BlockVisitor
from
transpiler.phases.emit_cpp.class_
import
ClassVisitor
,
ClassInnerVisitor
,
ClassInnerVisitor2
,
ClassInnerVisitor4
from
transpiler.phases.emit_cpp.function
import
FunctionVisitor
from
transpiler.utils
import
compare_ast
,
highlight
IGNORED_IMPORTS
=
{
"typon"
,
"typing"
,
"__future__"
,
"dataclasses"
,
"enum"
}
# noinspection PyPep8Naming
@
dataclass
class
ModuleVisitor
(
BlockVisitor
):
includes
:
list
[
str
]
=
field
(
default_factory
=
list
)
def
visit_Import
(
self
,
node
:
ast
.
Import
)
->
Iterable
[
str
]:
__TB__
=
f"emitting C++ code for
{
highlight
(
node
)
}
"
for
alias
in
node
.
names
:
concrete
=
self
.
fix_name
(
alias
.
asname
or
alias
.
name
)
if
alias
.
module_obj
.
is_python
:
yield
f"namespace py_
{
concrete
}
{{"
yield
f"struct
{
concrete
}
_t {{"
for
name
,
obj
in
alias
.
module_obj
.
fields
.
items
():
ty
=
obj
.
type
.
resolve
()
if
getattr
(
ty
,
"python_func_used"
,
False
):
yield
from
self
.
emit_python_func
(
alias
.
name
,
name
,
name
,
ty
)
yield
"} all;"
yield
f"auto& get_all() {{ return all; }}"
yield
"}"
yield
f'auto&
{
concrete
}
= py_
{
concrete
}
::get_all();'
elif
alias
.
name
in
IGNORED_IMPORTS
:
yield
""
else
:
yield
from
self
.
import_module
(
alias
.
name
)
yield
f'auto&
{
concrete
}
= py_
{
alias
.
name
}
::get_all();'
def
import_module
(
self
,
name
:
str
)
->
Iterable
[
str
]:
self
.
includes
.
append
(
f'#include <python/
{
name
}
.hpp>'
)
yield
""
def
emit_python_func
(
self
,
mod
:
str
,
name
:
str
,
alias
:
str
,
fty
:
FunctionType
)
->
Iterable
[
str
]:
__TB__
=
f"emitting C++ code for Python function
{
highlight
(
f'
{
mod
}
.
{
name
}
')
}
"
yield
"struct {"
yield
f"auto operator()("
for
i
,
argty
in
enumerate
(
fty
.
parameters
):
if
i
!=
0
:
yield
", "
yield
"lvalue_or_rvalue<"
yield
from
self
.
visit
(
argty
)
yield
f"> arg
{
i
}
"
yield
") {"
yield
"InterpGuard guard{};"
yield
"try {"
yield
f"return py::module_::import(
\
"
{
mod
}\
"
).attr(
\
"
{
name
}\
"
)("
for
i
,
argty
in
enumerate
(
fty
.
parameters
):
if
i
!=
0
:
yield
", "
yield
f"*arg
{
i
}
"
yield
").cast<"
yield
from
self
.
visit
(
fty
.
return_type
)
yield
">();"
yield
"} catch (py::error_already_set& e) {"
yield
'std::cerr << "Python exception: " << e.what() << std::endl;'
yield
"throw;"
yield
"}"
yield
"}"
yield
f"}}
{
alias
}
;"
def
visit_ImportFrom
(
self
,
node
:
ast
.
ImportFrom
)
->
Iterable
[
str
]:
if
node
.
module
in
IGNORED_IMPORTS
:
yield
""
elif
node
.
module_obj
.
is_python
:
for
alias
in
node
.
names
:
fty
=
alias
.
item_obj
.
resolve
()
#assert isinstance(fty, FunctionType)
yield
from
self
.
emit_python_func
(
node
.
module
,
alias
.
name
,
alias
.
asname
or
alias
.
name
,
fty
)
else
:
yield
from
self
.
import_module
(
node
.
module
)
for
alias
in
node
.
names
:
yield
f"auto&
{
alias
.
asname
or
alias
.
name
}
= py_
{
node
.
module
}
::get_all().
{
alias
.
name
}
;"
def
visit_Expr
(
self
,
node
:
ast
.
Expr
)
->
Iterable
[
str
]:
if
isinstance
(
node
.
value
,
ast
.
Str
):
if
"
\
n
"
in
node
.
value
.
s
:
yield
f"/*
{
node
.
value
.
s
}
*/"
else
:
yield
f"//
{
node
.
value
.
s
}
"
else
:
raise
NotImplementedError
(
node
)
def
visit_ClassDef
(
self
,
node
:
ast
.
ClassDef
)
->
Iterable
[
str
]:
#yield from ClassVisitor().visit(node)
yield
from
()
def
visit_FunctionDef
(
self
,
node
:
ast
.
FunctionDef
)
->
Iterable
[
str
]:
yield
from
super
().
visit_free_func
(
node
,
FunctionEmissionKind
.
DECLARATION
)
@
dataclass
class
ModuleVisitor2
(
NodeVisitor
):
scope
:
Scope
def
visit_FunctionDef
(
self
,
node
:
ast
.
FunctionDef
)
->
Iterable
[
str
]:
yield
from
BlockVisitor
(
self
.
scope
).
visit_free_func
(
node
,
FunctionEmissionKind
.
DEFINITION
)
def
visit_AST
(
self
,
node
:
ast
.
AST
)
->
Iterable
[
str
]:
yield
""
pass
@
dataclass
class
ModuleVisitor3
(
NodeVisitor
):
scope
:
Scope
def
visit_ClassDef
(
self
,
node
:
ast
.
ClassDef
)
->
Iterable
[
str
]:
yield
from
()
return
if
gen_instances
:
=
getattr
(
node
,
"gen_instances"
,
None
):
for
args
,
inst
in
gen_instances
.
items
():
yield
from
self
.
visit_ClassDef
(
inst
)
return
yield
f"static constexpr _detail_<__main__>::
{
node
.
name
}
<>
{
node
.
name
}
{{}};"
def
visit_FunctionDef
(
self
,
node
:
ast
.
FunctionDef
)
->
Iterable
[
str
]:
yield
from
BlockVisitor
(
self
.
scope
).
visit_free_func
(
node
,
FunctionEmissionKind
.
DEFINITION
)
@
dataclass
class
ModuleVisitor4
(
NodeVisitor
):
scope
:
Scope
def
visit_ClassDef
(
self
,
node
:
ast
.
ClassDef
)
->
Iterable
[
str
]:
if
gen_instances
:
=
getattr
(
node
,
"gen_instances"
,
None
):
for
args
,
inst
in
gen_instances
.
items
():
yield
from
self
.
visit_ClassDef
(
inst
)
return
yield
f"template <typename _Base0 = referencemodel::object>"
yield
f"struct
{
node
.
name
}
__oo : referencemodel::classtype<_Base0,
{
node
.
name
}
__oo<>> {{"
yield
f"static constexpr std::string_view name =
\
"
{
node
.
name
}\
"
;"
inner
=
ClassInnerVisitor2
(
node
.
inner_scope
)
for
stmt
in
node
.
body
:
yield
from
inner
.
visit
(
stmt
)
yield
f"struct Obj : referencemodel::instance<
{
node
.
name
}
__oo<>, Obj> {{"
inner
=
ClassInnerVisitor4
(
node
.
inner_scope
)
for
stmt
in
node
.
body
:
yield
from
inner
.
visit
(
stmt
)
yield
"template <typename... U>"
yield
"Obj(U&&... args) {"
yield
"dot(this, __init__)(this, std::forward<U>(args)...);"
yield
"}"
yield
"};"
yield
"template <typename... T>"
yield
"auto operator() (T&&... args) const {"
yield
"return referencemodel::rc(Obj{std::forward<T>(args)...});"
yield
"}"
yield
f"}};"
yield
f"static constexpr
{
node
.
name
}
__oo<>
{
node
.
name
}
{{}};"
yield
f"static_assert(sizeof
{
node
.
name
}
== 1);"
def
visit_FunctionDef
(
self
,
node
:
ast
.
FunctionDef
)
->
Iterable
[
str
]:
yield
from
()
@
dataclass
class
ModuleVisitorExt
(
NodeVisitor
):
scope
:
Scope
def
visit_FunctionDef
(
self
,
node
:
ast
.
FunctionDef
)
->
Iterable
[
str
]:
if
getattr
(
node
,
"is_main"
,
False
):
yield
from
()
return
#yield from BlockVisitor(self.scope).visit_free_func(node, FunctionEmissionKind.DEFINITION)
#yield f'm.def("{node.name}", CoroWrapper(PROGRAMNS::{node.name}));'
yield
f'm.def("
{
node
.
name
}
", PROGRAMNS::
{
node
.
name
}
);'
def
visit_ClassDef
(
self
,
node
:
ast
.
ClassDef
)
->
Iterable
[
str
]:
if
gen_instances
:
=
getattr
(
node
,
"gen_instances"
,
None
):
for
args
,
inst
in
gen_instances
.
items
():
yield
from
self
.
visit_ClassDef
(
inst
)
return
yield
f"py::class_<PROGRAMNS::
{
node
.
name
}
_s::py_type>(m,
\
"
{
node
.
name
}\
"
)"
if
init
:
=
node
.
type
.
fields
.
get
(
"__init__"
,
None
):
init
=
init
.
type
.
resolve
().
remove_self
()
init_params
=
init
.
parameters
yield
".def(py::init<"
yield
from
join
(
", "
,
map
(
self
.
visit
,
init_params
))
yield
">())"
yield
f'.def("__repr__", [](const PROGRAMNS::
{
node
.
name
}
_s::py_type& self)'
yield
"{ return repr(self); })"
for
f
,
v
in
node
.
type
.
fields
.
items
():
if
f
==
"__init__"
:
continue
if
isinstance
(
v
.
type
,
FunctionType
):
meth
=
v
.
type
.
remove_self
()
yield
f'.def("
{
f
}
", [](const PROGRAMNS::
{
node
.
name
}
_s::py_type& a'
if
meth
.
parameters
:
yield
","
vis
=
BlockVisitor
(
node
.
scope
)
yield
from
vis
.
visit_func_params
(((
f"arg
{
i
}
"
,
ty
,
None
)
for
i
,
ty
in
enumerate
(
meth
.
parameters
)),
FunctionEmissionKind
.
LAMBDA
)
yield
f') {{ return dotp(&a,
{
f
}
)('
if
meth
.
parameters
:
yield
from
join
(
", "
,
(
f"arg
{
i
}
"
for
i
,
_
in
enumerate
(
meth
.
parameters
)))
yield
').call(); })'
else
:
yield
f'.def_readwrite("
{
f
}
", &PROGRAMNS::
{
node
.
name
}
_s::py_type::
{
f
}
)'
yield
";"
pass
def
visit_AST
(
self
,
node
:
ast
.
AST
)
->
Iterable
[
str
]:
yield
from
()
pass
typon/trans/transpiler/phases/emit_cpp/search.py
→
typon/trans/transpiler/phases/emit_cpp
2
/search.py
View file @
90409113
File moved
typon/trans/transpiler/phases/typing/modules.py
View file @
90409113
...
@@ -5,18 +5,21 @@ from transpiler.phases.typing.scope import Scope, VarKind, VarDecl, ScopeKind
...
@@ -5,18 +5,21 @@ from transpiler.phases.typing.scope import Scope, VarKind, VarDecl, ScopeKind
from
transpiler.phases.typing.types
import
MemberDef
,
ResolvedConcreteType
,
UniqueTypeMixin
from
transpiler.phases.typing.types
import
MemberDef
,
ResolvedConcreteType
,
UniqueTypeMixin
def
make_module
(
name
:
str
,
scope
:
Scope
)
->
ResolvedConcreteType
:
class
ModuleType
(
UniqueTypeMixin
,
ResolvedConcreteType
):
class
CreatedType
(
UniqueTypeMixin
,
ResolvedConcreteType
):
pass
def
make_module
(
name
:
str
,
scope
:
Scope
)
->
ModuleType
:
class
CreatedType
(
ModuleType
):
def
name
(
self
):
def
name
(
self
):
return
name
return
name
ty
=
CreatedType
()
ty
=
CreatedType
()
for
n
,
v
in
scope
.
vars
.
items
():
for
n
,
v
in
scope
.
vars
.
items
():
ty
.
fields
[
n
]
=
MemberDef
(
v
.
type
,
v
.
val
,
False
)
ty
.
fields
[
n
]
=
MemberDef
(
v
.
type
,
v
.
val
,
v
.
is_item_decl
)
return
ty
return
ty
visited_modules
=
{}
visited_modules
=
{}
def
parse_module
(
mod_name
:
str
,
python_path
:
Path
,
scope
=
None
):
def
parse_module
(
mod_name
:
str
,
python_path
:
Path
,
scope
=
None
,
preprocess
=
None
):
path
=
python_path
/
mod_name
path
=
python_path
/
mod_name
if
not
path
.
exists
():
if
not
path
.
exists
():
...
@@ -41,12 +44,15 @@ def parse_module(mod_name: str, python_path: Path, scope=None):
...
@@ -41,12 +44,15 @@ def parse_module(mod_name: str, python_path: Path, scope=None):
if
real_path
.
suffix
==
".py"
:
if
real_path
.
suffix
==
".py"
:
from
transpiler.phases.typing.stdlib
import
StdlibVisitor
from
transpiler.phases.typing.stdlib
import
StdlibVisitor
StdlibVisitor
(
python_path
,
mod_scope
).
visit
(
ast
.
parse
(
real_path
.
read_text
()))
node
=
ast
.
parse
(
real_path
.
read_text
())
if
preprocess
:
node
=
preprocess
(
node
)
StdlibVisitor
(
python_path
,
mod_scope
).
visit
(
node
)
else
:
else
:
raise
NotImplementedError
(
f"Unsupported file type
{
path
.
suffix
}
"
)
raise
NotImplementedError
(
f"Unsupported file type
{
path
.
suffix
}
"
)
mod
=
make_mod
_decl
(
mod_name
,
mod_scope
)
mod
=
make_mod
ule
(
mod_name
,
mod_scope
)
visited_modules
[
real_path
.
as_posix
()]
=
mod
visited_modules
[
real_path
.
as_posix
()]
=
VarDecl
(
VarKind
.
LOCAL
,
mod
,
{
k
:
v
.
type
for
k
,
v
in
mod_scope
.
vars
.
items
()})
return
mod
return
mod
# def process_module(mod_path: Path, scope):
# def process_module(mod_path: Path, scope):
...
@@ -82,7 +88,3 @@ def parse_module(mod_name: str, python_path: Path, scope=None):
...
@@ -82,7 +88,3 @@ def parse_module(mod_name: str, python_path: Path, scope=None):
# child_mod = process_module(child, scope)
# child_mod = process_module(child, scope)
# visited_modules[child.as_posix()] = child_mod
# visited_modules[child.as_posix()] = child_mod
# return mod
# return mod
def
make_mod_decl
(
child
,
mod_scope
):
return
VarDecl
(
VarKind
.
LOCAL
,
make_module
(
child
,
mod_scope
),
{
k
:
v
.
type
for
k
,
v
in
mod_scope
.
vars
.
items
()})
\ No newline at end of file
typon/trans/transpiler/phases/typing/scope.py
View file @
90409113
...
@@ -28,6 +28,7 @@ class VarDecl:
...
@@ -28,6 +28,7 @@ class VarDecl:
kind
:
VarKind
kind
:
VarKind
type
:
BaseType
type
:
BaseType
val
:
Any
=
RuntimeValue
()
val
:
Any
=
RuntimeValue
()
is_item_decl
:
bool
=
False
class
ScopeKind
(
Enum
):
class
ScopeKind
(
Enum
):
...
...
typon/trans/transpiler/phases/typing/stdlib.py
View file @
90409113
...
@@ -15,7 +15,7 @@ from transpiler.phases.typing.scope import Scope, VarDecl, VarKind, ScopeKind
...
@@ -15,7 +15,7 @@ from transpiler.phases.typing.scope import Scope, VarDecl, VarKind, ScopeKind
from
transpiler.phases.typing.types
import
BaseType
,
BuiltinGenericType
,
BuiltinType
,
create_builtin_generic_type
,
\
from
transpiler.phases.typing.types
import
BaseType
,
BuiltinGenericType
,
BuiltinType
,
create_builtin_generic_type
,
\
create_builtin_type
,
ConcreteType
,
GenericInstanceType
,
TypeListType
,
TypeTupleType
,
GenericParameter
,
\
create_builtin_type
,
ConcreteType
,
GenericInstanceType
,
TypeListType
,
TypeTupleType
,
GenericParameter
,
\
GenericParameterKind
,
TypeVariable
,
ResolvedConcreteType
,
MemberDef
,
ClassTypeType
,
CallableInstanceType
,
\
GenericParameterKind
,
TypeVariable
,
ResolvedConcreteType
,
MemberDef
,
ClassTypeType
,
CallableInstanceType
,
\
MethodType
,
UniqueTypeMixin
,
GenericType
MethodType
,
UniqueTypeMixin
,
GenericType
,
BlockData
from
transpiler.phases.utils
import
NodeVisitorSeq
from
transpiler.phases.utils
import
NodeVisitorSeq
def
visit_generic_item
(
def
visit_generic_item
(
...
@@ -79,7 +79,7 @@ class StdlibVisitor(NodeVisitorSeq):
...
@@ -79,7 +79,7 @@ class StdlibVisitor(NodeVisitorSeq):
scope
:
Scope
=
field
(
default_factory
=
lambda
:
PRELUDE
)
scope
:
Scope
=
field
(
default_factory
=
lambda
:
PRELUDE
)
cur_class
:
Optional
[
ResolvedConcreteType
]
=
None
cur_class
:
Optional
[
ResolvedConcreteType
]
=
None
def
resolve_module_import
(
self
,
name
:
str
)
->
VarDecl
:
def
resolve_module_import
(
self
,
name
:
str
):
# tries = [
# tries = [
# self.python_path.parent / f"{name}.py",
# self.python_path.parent / f"{name}.py",
# self.python_path.parent / name
# self.python_path.parent / name
...
@@ -109,19 +109,19 @@ class StdlibVisitor(NodeVisitorSeq):
...
@@ -109,19 +109,19 @@ class StdlibVisitor(NodeVisitorSeq):
def
visit_ImportFrom
(
self
,
node
:
ast
.
ImportFrom
):
def
visit_ImportFrom
(
self
,
node
:
ast
.
ImportFrom
):
module
=
self
.
resolve_module_import
(
node
.
module
)
module
=
self
.
resolve_module_import
(
node
.
module
)
node
.
module_obj
=
module
.
type
node
.
module_obj
=
module
for
alias
in
node
.
names
:
for
alias
in
node
.
names
:
thing
=
module
.
val
.
get
(
alias
.
name
)
thing
=
module
.
fields
.
get
(
alias
.
name
)
if
not
thing
:
if
not
thing
:
from
transpiler.phases.typing.exceptions
import
UnknownModuleMemberError
from
transpiler.phases.typing.exceptions
import
UnknownModuleMemberError
raise
UnknownModuleMemberError
(
node
.
module
,
alias
.
name
)
raise
UnknownModuleMemberError
(
node
.
module
,
alias
.
name
)
alias
.
item_obj
=
thing
alias
.
item_obj
=
thing
.
type
self
.
scope
.
vars
[
alias
.
asname
or
alias
.
name
]
=
VarDecl
(
VarKind
.
LOCAL
,
thing
)
self
.
scope
.
vars
[
alias
.
asname
or
alias
.
name
]
=
VarDecl
(
VarKind
.
LOCAL
,
thing
.
type
)
def
visit_Import
(
self
,
node
:
ast
.
Import
):
def
visit_Import
(
self
,
node
:
ast
.
Import
):
for
alias
in
node
.
names
:
for
alias
in
node
.
names
:
mod
=
self
.
resolve_module_import
(
alias
.
name
)
mod
=
self
.
resolve_module_import
(
alias
.
name
)
alias
.
module_obj
=
mod
.
type
alias
.
module_obj
=
mod
self
.
scope
.
vars
[
alias
.
asname
or
alias
.
name
]
=
mod
self
.
scope
.
vars
[
alias
.
asname
or
alias
.
name
]
=
mod
def
visit_ClassDef
(
self
,
node
:
ast
.
ClassDef
):
def
visit_ClassDef
(
self
,
node
:
ast
.
ClassDef
):
...
@@ -131,11 +131,12 @@ class StdlibVisitor(NodeVisitorSeq):
...
@@ -131,11 +131,12 @@ class StdlibVisitor(NodeVisitorSeq):
else
:
else
:
base_class
=
create_builtin_generic_type
if
node
.
type_params
else
create_builtin_type
base_class
=
create_builtin_generic_type
if
node
.
type_params
else
create_builtin_type
NewType
=
base_class
(
node
.
name
)
NewType
=
base_class
(
node
.
name
)
self
.
scope
.
vars
[
node
.
name
]
=
VarDecl
(
VarKind
.
LOCAL
,
NewType
.
type_type
())
self
.
scope
.
vars
[
node
.
name
]
=
VarDecl
(
VarKind
.
LOCAL
,
NewType
.
type_type
()
,
is_item_decl
=
True
)
def
visit_nongeneric
(
scope
:
Scope
,
output
:
ResolvedConcreteType
):
def
visit_nongeneric
(
scope
:
Scope
,
output
:
ResolvedConcreteType
):
cl_scope
=
scope
.
child
(
ScopeKind
.
CLASS
)
cl_scope
=
scope
.
child
(
ScopeKind
.
CLASS
)
cl_scope
.
declare_local
(
"Self"
,
output
.
type_type
())
cl_scope
.
declare_local
(
"Self"
,
output
.
type_type
())
output
.
block_data
=
BlockData
(
node
,
scope
)
visitor
=
StdlibVisitor
(
self
.
python_path
,
cl_scope
,
output
)
visitor
=
StdlibVisitor
(
self
.
python_path
,
cl_scope
,
output
)
bases
=
[
self
.
anno
().
visit
(
base
)
for
base
in
node
.
bases
]
bases
=
[
self
.
anno
().
visit
(
base
)
for
base
in
node
.
bases
]
match
bases
:
match
bases
:
...
@@ -157,6 +158,7 @@ class StdlibVisitor(NodeVisitorSeq):
...
@@ -157,6 +158,7 @@ class StdlibVisitor(NodeVisitorSeq):
def
visit_nongeneric
(
scope
,
output
:
CallableInstanceType
):
def
visit_nongeneric
(
scope
,
output
:
CallableInstanceType
):
scope
=
scope
.
child
(
ScopeKind
.
FUNCTION
)
scope
=
scope
.
child
(
ScopeKind
.
FUNCTION
)
arg_visitor
=
TypeAnnotationVisitor
(
scope
)
arg_visitor
=
TypeAnnotationVisitor
(
scope
)
output
.
block_data
=
BlockData
(
node
,
scope
)
output
.
parameters
=
[
arg_visitor
.
visit
(
arg
.
annotation
)
for
arg
in
node
.
args
.
args
]
output
.
parameters
=
[
arg_visitor
.
visit
(
arg
.
annotation
)
for
arg
in
node
.
args
.
args
]
output
.
return_type
=
arg_visitor
.
visit
(
node
.
returns
)
output
.
return_type
=
arg_visitor
.
visit
(
node
.
returns
)
output
.
optional_at
=
len
(
node
.
args
.
args
)
-
len
(
node
.
args
.
defaults
)
output
.
optional_at
=
len
(
node
.
args
.
args
)
-
len
(
node
.
args
.
defaults
)
...
@@ -198,6 +200,10 @@ class StdlibVisitor(NodeVisitorSeq):
...
@@ -198,6 +200,10 @@ class StdlibVisitor(NodeVisitorSeq):
node
.
type_params
.
append
(
ast
.
TypeVar
(
arg_name
,
arg
.
annotation
))
node
.
type_params
.
append
(
ast
.
TypeVar
(
arg_name
,
arg
.
annotation
))
arg
.
annotation
=
ast
.
Name
(
arg_name
,
ast
.
Load
())
arg
.
annotation
=
ast
.
Name
(
arg_name
,
ast
.
Load
())
if
node
.
returns
is
None
:
node
.
returns
=
ast
.
Name
(
"AutoVar$return"
,
ast
.
Load
())
node
.
type_params
.
append
(
ast
.
TypeVar
(
"AutoVar$return"
,
None
))
# if self.cur_class is not None:
# if self.cur_class is not None:
# node.type_params.append(ast.TypeVar("Self", None))
# node.type_params.append(ast.TypeVar("Self", None))
...
@@ -232,9 +238,9 @@ class StdlibVisitor(NodeVisitorSeq):
...
@@ -232,9 +238,9 @@ class StdlibVisitor(NodeVisitorSeq):
NewType
=
base_class
()
NewType
=
base_class
()
FuncType
.
__name__
=
NewType
.
name
()
FuncType
.
__name__
=
NewType
.
name
()
self
.
scope
.
vars
[
node
.
name
]
=
VarDecl
(
VarKind
.
LOCAL
,
NewType
)
self
.
scope
.
vars
[
node
.
name
]
=
VarDecl
(
VarKind
.
LOCAL
,
NewType
,
is_item_decl
=
True
)
if
self
.
cur_class
is
not
None
:
if
self
.
cur_class
is
not
None
:
self
.
cur_class
.
fields
[
node
.
name
]
=
MemberDef
(
NewType
,
node
)
self
.
cur_class
.
fields
[
node
.
name
]
=
MemberDef
(
NewType
,
node
,
in_class_def
=
True
)
visit_generic_item
(
visit_nongeneric
,
node
,
NewType
,
self
.
scope
,
InstanceType
,
True
)
visit_generic_item
(
visit_nongeneric
,
node
,
NewType
,
self
.
scope
,
InstanceType
,
True
)
...
...
typon/trans/transpiler/phases/typing/types.py
View file @
90409113
...
@@ -287,7 +287,9 @@ class GenericParameterKind(enum.Enum):
...
@@ -287,7 +287,9 @@ class GenericParameterKind(enum.Enum):
@
dataclass
@
dataclass
class
GenericParameter
:
class
GenericParameter
:
name
:
str
name
:
str
kind
:
GenericParameterKind
kind
:
GenericParameterKind
=
GenericParameterKind
.
NORMAL
gparam
=
GenericParameter
@
dataclass
@
dataclass
class
GenericConstraint
:
class
GenericConstraint
:
...
@@ -589,6 +591,8 @@ class ClassTypeType(GenericInstanceType):
...
@@ -589,6 +591,8 @@ class ClassTypeType(GenericInstanceType):
inner_type
:
BaseType
inner_type
:
BaseType
class
ClassType
(
UniqueTypeMixin
,
GenericType
):
class
ClassType
(
UniqueTypeMixin
,
GenericType
):
parameters
=
[
gparam
(
"T"
)]
def
name
(
self
):
def
name
(
self
):
return
"Type"
return
"Type"
...
...
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