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
4dda1cb4
Commit
4dda1cb4
authored
Apr 02, 2024
by
Tom Niget
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Python ext works
parent
fe2492d6
Changes
13
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
158 additions
and
45 deletions
+158
-45
typon/include/python/builtins.hpp
typon/include/python/builtins.hpp
+1
-1
typon/include/python/builtins/dict.hpp
typon/include/python/builtins/dict.hpp
+4
-2
typon/include/python/builtins/list.hpp
typon/include/python/builtins/list.hpp
+8
-0
typon/include/python/dataclasses.hpp
typon/include/python/dataclasses.hpp
+13
-0
typon/include/python/typon.hpp
typon/include/python/typon.hpp
+13
-0
typon/trans/stdlib/typon/__init__.py
typon/trans/stdlib/typon/__init__.py
+2
-0
typon/trans/test_runner.py
typon/trans/test_runner.py
+1
-1
typon/trans/tests/pyext.post.py
typon/trans/tests/pyext.post.py
+4
-4
typon/trans/tests/pyext.py
typon/trans/tests/pyext.py
+16
-12
typon/trans/tests/webserver_eval.py
typon/trans/tests/webserver_eval.py
+0
-1
typon/trans/transpiler/phases/emit_cpp/module.py
typon/trans/transpiler/phases/emit_cpp/module.py
+4
-4
typon/trans/transpiler/phases/typing/stdlib.py
typon/trans/transpiler/phases/typing/stdlib.py
+67
-17
typon/trans/transpiler/transpiler.py
typon/trans/transpiler/transpiler.py
+25
-3
No files found.
typon/include/python/builtins.hpp
View file @
4dda1cb4
...
...
@@ -318,7 +318,7 @@ struct ValueTypeEx {
// has ::iterator type
template
<
typename
T
>
struct
ValueType
{
using
type
=
typename
T
::
iterator
::
value_type
;
using
type
=
decltype
(
*
std
::
declval
<
T
>
().
begin
())
;
};
template
<
typename
T
>
...
...
typon/include/python/builtins/dict.hpp
View file @
4dda1cb4
...
...
@@ -180,8 +180,10 @@ struct TyDict__oo : classtype<_Base0, TyDict__oo<>> {
Obj(std::unordered_map<K, V> &&m)
: _m(std::move(
std::make_shared<std::unordered_map<K, V>>(std::move(m)))) {}*/
Obj
(
std
::
initializer_list
<
typename
map_type
::
value_type
>
&&
m
)
:
_m
(
std
::
make_shared
<
map_type
>
(
std
::
move
(
m
)))
{}
/*Obj(std::initializer_list<typename map_type::value_type> &&m)
: _m(std::make_shared<map_type>(std::move(m))) {}*/
Obj
(
std
::
initializer_list
<
std
::
pair
<
K
,
V
>>
&&
init
)
:
_m
(
std
::
make_shared
<
std
::
unordered_map
<
K
,
V
>>
(
init
.
begin
(),
init
.
end
()))
{}
Obj
()
:
_m
(
std
::
make_shared
<
map_type
>
())
{}
template
<
typename
...
Args
>
...
...
typon/include/python/builtins/list.hpp
View file @
4dda1cb4
...
...
@@ -24,9 +24,17 @@ struct TyList__oo : classtype<_Base0, TyList__oo<>> {
auto
operator
()(
auto
self
,
auto
other
)
const
{
self
->
_v
.
reserve
(
self
->
_v
.
size
()
+
other
.
size
());
self
->
_v
.
insert
(
self
->
_v
.
end
(),
other
.
begin
(),
other
.
end
());
return
None
;
}
}
static
constexpr
extend
{};
// append
struct
:
method
{
auto
operator
()(
auto
self
,
auto
value
)
const
{
self
->
_v
->
push_back
(
value
);
return
None
;
}
}
static
constexpr
append
{};
struct
:
method
{
auto
operator
()(
auto
self
,
auto
other
)
const
{
auto
result
=
TyList__oo
<>
{}(
self
->
_v
);
...
...
typon/include/python/dataclasses.hpp
0 → 100644
View file @
4dda1cb4
#ifndef TYPON_DATACLASSES_HPP
#define TYPON_DATACLASSES_HPP
#include "builtins.hpp"
namespace
py_dataclasses
{
template
<
typename
_Unused
=
void
>
struct
dataclasses__oo
:
referencemodel
::
moduletype
<
dataclasses__oo
<>>
{
};
dataclasses__oo
<>
all
;
}
// namespace py_dataclasses
#endif //TYPON_DATACLASSES_HPP
\ No newline at end of file
typon/include/python/typon.hpp
0 → 100644
View file @
4dda1cb4
#ifndef TYPON_TYPON_HPP
#define TYPON_TYPON_HPP
#include "builtins.hpp"
namespace
py_typon
{
template
<
typename
_Unused
=
void
>
struct
typon__oo
:
referencemodel
::
moduletype
<
typon__oo
<>>
{
};
typon__oo
<>
all
;
}
// namespace py_typon
#endif //TYPON_TYPON_HPP
\ No newline at end of file
typon/trans/stdlib/typon/__init__.py
View file @
4dda1cb4
def
is_cpp
()
->
bool
:
return
False
export
:
BuiltinFeature
[
"PybindExport"
]
\ No newline at end of file
typon/trans/test_runner.py
View file @
4dda1cb4
...
...
@@ -90,7 +90,7 @@ def run_test(path, quiet=True):
if
args
.
compile
:
return
TestStatus
.
SUCCESS
execute_str
=
"true"
if
(
execute
and
not
args
.
generate
)
else
"false"
name_bin
=
path
.
with_suffix
(
""
).
as_posix
()
+
(
"$(python3.12-config --extension-suffix)"
if
extension
else
".exe"
)
name_bin
=
path
.
with_suffix
(
""
).
as_posix
()
+
(
"
\
\
$(python3.12-config --extension-suffix)"
if
extension
else
".exe"
)
if
exec_cmd
(
f'bash -c "export PYTHONPATH=stdlib; if
{
execute_str
}
; then echo python3.12 ./
{
path
.
as_posix
()
}
; fi"'
)
!=
0
:
return
TestStatus
.
PYTHON_ERROR
if
compile
and
(
alt
:
=
environ
.
get
(
"ALT_RUNNER"
)):
...
...
typon/trans/tests/pyext.post.py
View file @
4dda1cb4
import
pyext
p
=
pyext
.
Person
(
"jean"
,
123
)
print
(
"Imported:"
,
pyext
.
add
(
5
,
3
),
pyext
.
fibo
(
10
),
pyext
.
squares
(),
p
)
print
(
p
.
afficher
(
"Bonjour"
))
print
(
p
.
name
,
p
.
age
)
\ No newline at end of file
# p = pyext.Person("jean", 123)
print
(
"Imported:"
,
pyext
.
add
(
5
,
3
),
pyext
.
fibo
(
10
),
pyext
.
squares
())
# print(p.afficher("Bonjour"))
# print(p.name, p.age)
\ No newline at end of file
typon/trans/tests/pyext.py
View file @
4dda1cb4
# coding: utf-8
# extension
from
typon
import
export
import
numpy
as
np
from
dataclasses
import
dataclass
#
from dataclasses import dataclass
@
dataclass
class
Person
:
name
:
str
age
:
int
def
afficher
(
self
,
msg
:
str
):
print
(
msg
,
","
,
self
.
name
,
self
.
age
)
return
123
#
@dataclass
#
class Person:
#
name: str
#
age: int
#
#
def afficher(self, msg: str):
#
print(msg, ",", self.name, self.age)
#
return 123
@
export
([
int
,
int
])
def
add
(
x
,
y
):
return
x
+
y
@
export
([
int
])
def
fibo
(
n
):
res
=
[
0
,
1
]
for
i
in
range
(
2
,
n
):
res
.
append
(
res
[
i
-
1
]
+
res
[
i
-
2
])
return
res
@
export
([])
def
squares
()
->
list
[
int
]:
return
np
.
square
([
x
for
x
in
range
(
5
)])
if
__name__
==
"__main__"
:
p
=
Person
(
"jean"
,
123
)
print
(
"Python:"
,
add
(
5
,
3
),
fibo
(
10
),
squares
(),
p
)
p
.
afficher
(
"Bonjour"
)
\ No newline at end of file
# p = Person("jean", 123)
print
(
"Python:"
,
add
(
5
,
3
),
fibo
(
10
),
squares
())
# p.afficher("Bonjour")
\ No newline at end of file
typon/trans/tests/webserver_eval.py
View file @
4dda1cb4
...
...
@@ -31,7 +31,6 @@ def handle_connection(connfd):
else
:
http_pos
=
buf
.
find
(
"HTTP/1.1
\
r
\
n
"
)
s
=
"str("
+
buf
[
12
:
http_pos
-
1
]
+
")"
#resp = eval(s, {"req": buf})
context
=
{
"req"
:
buf
}
resp
=
eval
(
s
,
context
)
response
=
response_fmt
.
format
(
len
(
resp
),
resp
)
...
...
typon/trans/transpiler/phases/emit_cpp/module.py
View file @
4dda1cb4
...
...
@@ -7,7 +7,7 @@ from transpiler.phases.emit_cpp.function import emit_function, BlockVisitor
from
transpiler.phases.emit_cpp.visitors
import
NodeVisitor
,
CoroutineMode
from
transpiler.phases.typing.modules
import
ModuleType
,
TyponModuleType
,
PythonModuleType
from
transpiler.phases.typing.types
import
CallableInstanceType
,
ClassTypeType
,
TypeVariable
,
BaseType
,
GenericType
,
\
GenericInstanceType
,
UserGenericType
,
RuntimeValue
GenericInstanceType
,
UserGenericType
,
RuntimeValue
,
BuiltinFeatureType
from
transpiler.utils
import
linenodata
...
...
@@ -83,9 +83,9 @@ def emit_module(mod: ModuleType) -> Iterable[str]:
yield
from
emit
(
node
.
module_obj
)
prefix
=
"python_"
if
isinstance
(
node
.
module_obj
,
PythonModuleType
)
else
""
for
alias
in
names
:
if
isinstance
(
node
.
module_obj
,
PythonModuleType
):
if
isinstance
(
node
.
module_obj
.
fields
[
alias
.
name
].
type
.
resolve
(),
TypeVariable
):
continue
# unused function
#
if isinstance(node.module_obj, PythonModuleType):
if
isinstance
(
node
.
module_obj
.
fields
[
alias
.
name
].
type
.
resolve
(),
(
TypeVariable
,
BuiltinFeatureType
)
):
continue
# unused function
incl_vars
.
append
(
f"auto&
{
alias
.
asname
or
alias
.
name
}
= py_
{
prefix
}{
node
.
module_obj
.
name
()
}
::all.
{
alias
.
name
}
;"
)
yield
"namespace PROGRAMNS {"
yield
from
incl_vars
...
...
typon/trans/transpiler/phases/typing/stdlib.py
View file @
4dda1cb4
import
ast
import
copy
import
dataclasses
from
abc
import
ABCMeta
from
dataclasses
import
dataclass
,
field
from
pathlib
import
Path
from
typing
import
Optional
,
List
,
Dict
,
Callable
from
logging
import
debug
from
pathlib
import
Path
from
typing
import
Optional
,
Callable
from
transpiler.phases.typing.modules
import
parse_module
from
transpiler.utils
import
highlight
,
linenodata
from
transpiler.phases.typing.annotations
import
TypeAnnotationVisitor
from
transpiler.phases.typing.common
import
PRELUDE
,
is_builtin
from
transpiler.phases.typing.expr
import
ScoperExprVisitor
from
transpiler.phases.typing.modules
import
parse_module
from
transpiler.phases.typing.scope
import
Scope
,
VarDecl
,
VarKind
,
ScopeKind
from
transpiler.phases.typing.types
import
BaseType
,
BuiltinGenericType
,
BuiltinType
,
create_builtin_generic_type
,
\
create_builtin_type
,
ConcreteType
,
GenericInstanceType
,
TypeListType
,
TypeTupleType
,
GenericParameter
,
\
GenericParameterKind
,
TypeVariable
,
ResolvedConcreteType
,
MemberDef
,
ClassTypeType
,
CallableInstanceType
,
\
MethodType
,
UniqueTypeMixin
,
GenericType
,
BlockData
,
TY_TASK
,
UserGenericType
,
UserType
,
BoundFuncTypeBase
MethodType
,
GenericType
,
BlockData
,
TY_TASK
,
UserGenericType
,
UserType
,
BoundFuncTypeBase
from
transpiler.phases.utils
import
NodeVisitorSeq
from
transpiler.utils
import
highlight
,
linenodata
def
visit_generic_item
(
visit_nongeneric
:
Callable
[[
Scope
,
ResolvedConcreteType
],
None
],
node
,
output_type
:
BuiltinGenericType
,
scope
:
Scope
,
instance_type
=
None
,
force_generic
=
False
):
instance_type
=
None
,
force_generic
=
False
):
if
force_generic
or
node
.
type_params
:
output_type
.
parameters
=
[]
for
param
in
node
.
type_params
:
...
...
@@ -41,6 +40,7 @@ def visit_generic_item(
if
instance_type
is
None
:
class
instance_type
(
GenericInstanceType
):
pass
instance_type
.
__name__
=
f"GenericInstance$
{
node
.
name
}
"
def
instantiate
(
args
:
list
[
ConcreteType
])
->
GenericInstanceType
:
...
...
@@ -64,12 +64,13 @@ def visit_generic_item(
new_scope
.
declare_local
(
name
,
TypeTupleType
(
list
(
args_iter
)).
type_type
())
for
a
,
b
in
constraints
:
assert
b
.
try_assign
(
a
)
# todo
#
todo
new_output_type
=
instance_type
()
new_output_type
.
generic_parent
=
output_type
new_output_type
.
generic_args
=
args
visit_nongeneric
(
new_scope
,
new_output_type
)
return
new_output_type
output_type
.
constraints_
=
[]
output_type
.
instantiate_
=
instantiate
else
:
...
...
@@ -112,7 +113,7 @@ class StdlibVisitor(NodeVisitorSeq):
ty
=
self
.
anno
().
visit
(
node
.
annotation
)
if
self
.
cur_class
:
assert
isinstance
(
self
.
cur_class
,
ResolvedConcreteType
)
self
.
cur_class
.
fields
[
node
.
target
.
id
]
=
MemberDef
(
ty
)
self
.
cur_class
.
fields
[
node
.
target
.
id
]
=
MemberDef
(
ty
,
in_class_def
=
True
,
from_node
=
node
)
self
.
scope
.
vars
[
node
.
target
.
id
]
=
VarDecl
(
VarKind
.
LOCAL
,
ty
)
def
visit_ImportFrom
(
self
,
node
:
ast
.
ImportFrom
):
...
...
@@ -139,7 +140,8 @@ class StdlibVisitor(NodeVisitorSeq):
NewType
=
existing
.
type
.
inner_type
else
:
if
node
.
type_params
or
force_generic
:
base_class
,
base_type
=
create_builtin_generic_type
,
(
BuiltinGenericType
if
self
.
is_native
else
UserGenericType
)
base_class
,
base_type
=
create_builtin_generic_type
,
(
BuiltinGenericType
if
self
.
is_native
else
UserGenericType
)
else
:
base_class
,
base_type
=
create_builtin_type
,
(
BuiltinType
if
self
.
is_native
else
UserType
)
NewType
=
base_class
(
node
.
name
,
...
...
@@ -163,6 +165,36 @@ class StdlibVisitor(NodeVisitorSeq):
raise
NotImplementedError
(
"parents not handled yet: "
+
", "
.
join
(
map
(
ast
.
unparse
,
node
.
bases
)))
for
stmt
in
node
.
body
:
visitor
.
visit
(
stmt
)
for
deco_node
in
node
.
decorator_list
:
deco
=
self
.
expr
().
visit
(
deco_node
)
match
deco
:
case
dc
if
is_builtin
(
dc
,
"dataclass"
):
real_fields
=
{
k
:
m
for
k
,
m
in
output
.
fields
.
items
()
if
not
isinstance
(
m
.
from_node
,
ast
.
FunctionDef
)}
generated_init
=
ast
.
FunctionDef
(
name
=
"__init__"
,
args
=
ast
.
arguments
(
posonlyargs
=
[],
args
=
[
ast
.
arg
(
arg
=
"self"
,
annotation
=
None
)]
+
[
ast
.
arg
(
arg
=
k
,
annotation
=
None
)
for
k
,
m
in
real_fields
.
items
()],
vararg
=
None
,
kwonlyargs
=
[],
kw_defaults
=
[],
kwarg
=
None
,
defaults
=
[]),
body
=
[
ast
.
Assign
(
targets
=
[
ast
.
Attribute
(
value
=
ast
.
Name
(
"self"
,
ast
.
Load
()),
attr
=
k
,
ctx
=
ast
.
Store
())
],
value
=
ast
.
Name
(
k
,
ast
.
Load
()),
type_comment
=
None
,
**
linenodata
(
node
)
)
for
k
in
real_fields
],
decorator_list
=
[],
returns
=
None
,
type_params
=
[],
**
linenodata
(
node
))
visitor
.
visit
(
generated_init
)
case
_
:
raise
NotImplementedError
(
f"Decorator
{
deco
}
not handled yet"
)
if
"__init__"
not
in
output
.
fields
:
visitor
.
visit
(
ast
.
FunctionDef
(
name
=
"__init__"
,
...
...
@@ -226,11 +258,11 @@ class StdlibVisitor(NodeVisitorSeq):
arg_name
=
"Self"
else
:
arg_name
=
f"AutoVar$
{
abs
(
hash
(
arg
.
arg
))
}
"
node
.
type_params
.
append
(
ast
.
TypeVar
(
arg_name
,
None
))
# todo: bounds
node
.
type_params
.
append
(
ast
.
TypeVar
(
arg_name
,
None
))
# todo: bounds
arg
.
annotation
=
ast
.
Name
(
arg_name
,
ast
.
Load
())
else
:
if
isinstance
(
arg
.
annotation
,
ast
.
Name
)
and
(
#
arg.annotation.id == "Self" or
#
arg.annotation.id == "Self" or
any
(
k
.
name
==
arg
.
annotation
.
id
for
k
in
node
.
type_params
)
):
# annotation is type variable so we keep it
...
...
@@ -252,6 +284,7 @@ class StdlibVisitor(NodeVisitorSeq):
cur_class_ref
=
self
.
cur_class
if
cur_class_ref
is
not
None
:
bases
.
append
(
MethodType
)
class
FuncType
(
*
bases
):
def
name
(
self
):
return
f"FuncTypeGen$
{
node
.
name
}
"
...
...
@@ -278,9 +311,26 @@ class StdlibVisitor(NodeVisitorSeq):
NewType
=
base_class
()
FuncType
.
__name__
=
NewType
.
name
()
self
.
scope
.
vars
[
node
.
name
]
=
VarDecl
(
VarKind
.
LOCAL
,
NewType
,
is_item_decl
=
True
)
for
deco_node
in
copy
.
deepcopy
(
node
.
decorator_list
):
if
isinstance
(
deco_node
,
ast
.
Call
):
deco_args
=
deco_node
.
args
deco_node
=
deco_node
.
func
else
:
deco_args
=
[]
deco
=
self
.
expr
().
visit
(
deco_node
)
match
deco
:
case
dc
if
is_builtin
(
dc
,
"PybindExport"
):
assert
len
(
deco_args
)
==
1
export
=
deco_args
[
0
]
assert
isinstance
(
export
,
ast
.
List
)
exports
=
[
self
.
anno
().
visit
(
e
)
for
e
in
export
.
elts
]
NewType
.
pybind_exports
=
exports
case
_
:
raise
NotImplementedError
(
f"Decorator
{
deco
}
not handled yet"
)
self
.
scope
.
vars
[
node
.
name
]
=
VarDecl
(
VarKind
.
LOCAL
,
NewType
,
is_item_decl
=
True
,
from_node
=
node
)
if
self
.
cur_class
is
not
None
:
self
.
cur_class
.
fields
[
node
.
name
]
=
MemberDef
(
NewType
,
node
,
in_class_def
=
True
)
self
.
cur_class
.
fields
[
node
.
name
]
=
MemberDef
(
NewType
,
node
,
in_class_def
=
True
,
from_node
=
node
)
visit_generic_item
(
visit_nongeneric
,
node
,
NewType
,
self
.
scope
,
InstanceType
,
True
)
...
...
@@ -306,4 +356,4 @@ class StdlibVisitor(NodeVisitorSeq):
raise
UnknownNameError
(
node
)
def
visit_Name
(
self
,
node
:
ast
.
Name
)
->
BaseType
:
return
self
.
visit_str
(
node
.
id
)
\ No newline at end of file
return
self
.
visit_str
(
node
.
id
)
typon/trans/transpiler/transpiler.py
View file @
4dda1cb4
...
...
@@ -13,6 +13,7 @@ from transpiler.phases.desugar_op import DesugarOp
from
transpiler.phases.desugar_subscript
import
DesugarSubscript
from
transpiler.phases.desugar_with
import
DesugarWith
from
transpiler.phases.emit_cpp.module
import
emit_module
from
transpiler.phases.emit_cpp.visitors
import
NodeVisitor
from
transpiler.phases.if_main
import
IfMainVisitor
from
transpiler.phases.typing
import
PRELUDE
from
transpiler.phases.typing.modules
import
parse_module
...
...
@@ -54,12 +55,33 @@ def transpile(source, name: str, path: Path):
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}'\";"
yield
f"PYBIND11_MODULE(
{
module
.
name
()
}
, m) {{"
yield
f"m.doc() =
\
"
Typon extension module '
{
module
.
name
()
}
'
\
"
;"
for
n
,
f
in
module
.
fields
.
items
():
if
not
f
.
in_class_def
:
continue
node
=
f
.
from_node
if
getattr
(
node
,
"is_main"
,
False
):
continue
if
isinstance
(
node
,
ast
.
FunctionDef
):
if
(
exports
:
=
getattr
(
f
.
type
,
"pybind_exports"
,
None
))
is
not
None
:
yield
f'm.def("
{
n
}
", []('
for
i
,
ty
in
enumerate
(
exports
):
if
i
!=
0
:
yield
","
yield
from
NodeVisitor
().
visit_BaseType
(
ty
)
yield
f"arg
{
i
}
"
yield
") {"
yield
f"return PROGRAMNS::
{
module
.
name
()
}
.
{
node
.
name
}
("
for
i
,
_
in
enumerate
(
exports
):
if
i
!=
0
:
yield
","
yield
f"arg
{
i
}
"
yield
").call(); });"
# visitor = ModuleVisitorExt(self.scope)
# code = [line for stmt in node.body for line in visitor.visit(stmt)]
# yield from code
#
yield "}"
yield
"}"
yield
"#else"
yield
"typon::Root root() {"
yield
f"co_await dot(PROGRAMNS::
{
module
.
name
()
}
, main)();"
...
...
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