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
b738512a
Commit
b738512a
authored
Feb 28, 2024
by
Tom Niget
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Builtin things work
parent
85f54768
Changes
26
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
26 changed files
with
696 additions
and
446 deletions
+696
-446
.gitignore
.gitignore
+2
-1
typon/include/python/basedef.hpp
typon/include/python/basedef.hpp
+2
-0
typon/include/python/builtins.hpp
typon/include/python/builtins.hpp
+31
-8
typon/include/python/builtins/int.hpp
typon/include/python/builtins/int.hpp
+134
-0
typon/include/python/builtins/print.hpp
typon/include/python/builtins/print.hpp
+3
-2
typon/include/python/builtins/range.hpp
typon/include/python/builtins/range.hpp
+5
-5
typon/include/python/referencemodel.hpp
typon/include/python/referencemodel.hpp
+79
-5
typon/runtime
typon/runtime
+1
-1
typon/trans/stdlib/builtins_.py
typon/trans/stdlib/builtins_.py
+6
-2
typon/trans/stdlib/typing_.py
typon/trans/stdlib/typing_.py
+2
-1
typon/trans/test_runner.py
typon/trans/test_runner.py
+3
-3
typon/trans/tests/builtins_test.py
typon/trans/tests/builtins_test.py
+27
-22
typon/trans/transpiler/error_display.py
typon/trans/transpiler/error_display.py
+41
-32
typon/trans/transpiler/phases/desugar_op/__init__.py
typon/trans/transpiler/phases/desugar_op/__init__.py
+17
-12
typon/trans/transpiler/phases/emit_cpp/class_.py
typon/trans/transpiler/phases/emit_cpp/class_.py
+2
-1
typon/trans/transpiler/phases/emit_cpp/expr.py
typon/trans/transpiler/phases/emit_cpp/expr.py
+86
-32
typon/trans/transpiler/phases/emit_cpp/function.py
typon/trans/transpiler/phases/emit_cpp/function.py
+56
-27
typon/trans/transpiler/phases/emit_cpp/visitors.py
typon/trans/transpiler/phases/emit_cpp/visitors.py
+17
-3
typon/trans/transpiler/phases/typing/block.py
typon/trans/transpiler/phases/typing/block.py
+51
-197
typon/trans/transpiler/phases/typing/class_.py
typon/trans/transpiler/phases/typing/class_.py
+35
-35
typon/trans/transpiler/phases/typing/common.py
typon/trans/transpiler/phases/typing/common.py
+30
-19
typon/trans/transpiler/phases/typing/expr.py
typon/trans/transpiler/phases/typing/expr.py
+18
-8
typon/trans/transpiler/phases/typing/modules.py
typon/trans/transpiler/phases/typing/modules.py
+27
-22
typon/trans/transpiler/phases/typing/stdlib.py
typon/trans/transpiler/phases/typing/stdlib.py
+6
-4
typon/trans/transpiler/phases/typing/types.py
typon/trans/transpiler/phases/typing/types.py
+7
-1
typon/trans/transpiler/transpiler.py
typon/trans/transpiler/transpiler.py
+8
-3
No files found.
.gitignore
View file @
b738512a
.idea
.idea
cmake-build-*
cmake-build-*
typon.egg-info
typon.egg-info
\ No newline at end of file
build
\ No newline at end of file
typon/include/python/basedef.hpp
View file @
b738512a
...
@@ -20,6 +20,8 @@ public:
...
@@ -20,6 +20,8 @@ public:
return
sync_wrapper
(
std
::
forward
<
Args
>
(
args
)...);
return
sync_wrapper
(
std
::
forward
<
Args
>
(
args
)...);
}
}
};
};
/*
/*
struct method {};
struct method {};
...
...
typon/include/python/builtins.hpp
View file @
b738512a
...
@@ -59,6 +59,8 @@ template <PySmartPtr T> struct RealType<T> {
...
@@ -59,6 +59,8 @@ template <PySmartPtr T> struct RealType<T> {
using
type
=
typename
T
::
element_type
;
using
type
=
typename
T
::
element_type
;
};
};
namespace
typon
{
//template <typename T> using TyObj = std::shared_ptr<typename RealType<T>::type>;
//template <typename T> using TyObj = std::shared_ptr<typename RealType<T>::type>;
template
<
typename
T
>
template
<
typename
T
>
...
@@ -135,6 +137,11 @@ template <typename T, typename... Args> auto pyobj_agg(Args &&...args) -> TyObj<
...
@@ -135,6 +137,11 @@ template <typename T, typename... Args> auto pyobj_agg(Args &&...args) -> TyObj<
return
std
::
make_shared
<
typename
RealType
<
T
>::
type
>
((
typename
RealType
<
T
>::
type
)
{
std
::
forward
<
Args
>
(
args
)...
});
return
std
::
make_shared
<
typename
RealType
<
T
>::
type
>
((
typename
RealType
<
T
>::
type
)
{
std
::
forward
<
Args
>
(
args
)...
});
}
}
class
TyNone
{
};
}
// typon_len
// typon_len
template
<
typename
T
>
template
<
typename
T
>
...
@@ -199,6 +206,7 @@ static constexpr auto PyNone = std::nullopt;
...
@@ -199,6 +206,7 @@ static constexpr auto PyNone = std::nullopt;
#include "builtins/bool.hpp"
#include "builtins/bool.hpp"
#include "builtins/complex.hpp"
#include "builtins/complex.hpp"
#include "builtins/dict.hpp"
#include "builtins/dict.hpp"
#include "builtins/int.hpp"
#include "builtins/list.hpp"
#include "builtins/list.hpp"
#include "builtins/print.hpp"
#include "builtins/print.hpp"
#include "builtins/range.hpp"
#include "builtins/range.hpp"
...
@@ -307,7 +315,7 @@ typon::Task<typon::PyFile> open(const TyStr &path, std::string_view mode) {
...
@@ -307,7 +315,7 @@ typon::Task<typon::PyFile> open(const TyStr &path, std::string_view mode) {
std
::
cerr
<<
path
<<
","
<<
flags
<<
std
::
endl
;
std
::
cerr
<<
path
<<
","
<<
flags
<<
std
::
endl
;
system_error
(
-
fd
,
"openat()"
);
system_error
(
-
fd
,
"openat()"
);
}
}
co_return
tyObj
<
typon
::
PyFile
>
(
fd
,
len
);
co_return
ty
pon
::
ty
Obj
<
typon
::
PyFile
>
(
fd
,
len
);
}
}
#include <typon/generator.hpp>
#include <typon/generator.hpp>
...
@@ -349,9 +357,9 @@ template<PySmartPtr T>
...
@@ -349,9 +357,9 @@ template<PySmartPtr T>
auto
&
iter_fix_ref
(
T
&
obj
)
{
return
*
obj
;
}
auto
&
iter_fix_ref
(
T
&
obj
)
{
return
*
obj
;
}
namespace
std
{
namespace
std
{
template
<
class
T
>
auto
begin
(
std
::
shared_ptr
<
T
>
&
obj
)
{
return
dot
p
(
obj
,
begin
)();
}
template
<
class
T
>
auto
begin
(
std
::
shared_ptr
<
T
>
&
obj
)
{
return
dot
(
obj
,
begin
)();
}
template
<
class
T
>
auto
end
(
std
::
shared_ptr
<
T
>
&
obj
)
{
return
dot
p
(
obj
,
end
)();
}
template
<
class
T
>
auto
end
(
std
::
shared_ptr
<
T
>
&
obj
)
{
return
dot
(
obj
,
end
)();
}
}
}
template
<
typename
T
>
template
<
typename
T
>
...
@@ -365,18 +373,33 @@ struct ValueTypeEx {
...
@@ -365,18 +373,33 @@ struct ValueTypeEx {
using
type
=
decltype
(
*
std
::
begin
(
std
::
declval
<
Seq
&>
()));
using
type
=
decltype
(
*
std
::
begin
(
std
::
declval
<
Seq
&>
()));
};
};
// (2)
// (2)
template
<
typename
Map
,
typename
Seq
,
typename
Filt
=
AlwaysTrue
<
typename
ValueTypeEx
<
Seq
>
::
type
>>
/*
template <typename Map, typename Seq, typename Filt = AlwaysTrue<typename ValueTypeEx<Seq>::type>>
auto
mapFilter
(
Map
map
,
Seq
seq
,
Filt
filt
=
Filt
())
{
typon::Task<
mapFilter(Map map, Seq seq, Filt filt = Filt()) {
//typedef typename Seq::value_type value_type;
//typedef typename Seq::value_type value_type;
using value_type = typename ValueTypeEx<Seq>::type;
using value_type = typename ValueTypeEx<Seq>::type;
using return_type = decltype(map(std::declval<value_type>()));
using return_type = decltype(map(std::declval<value_type>()));
std::vector<return_type> result{};
std::vector<return_type> result{};
for
(
auto
i
:
seq
|
std
::
views
::
filter
(
filt
)
for (auto i : seq) {
|
std
::
views
::
transform
(
map
))
result
.
push_back
(
i
);
if (co_await filt(i)) {
result.push_back(co_await map(i));
}
}
return typon::TyList(std::move(result));
return typon::TyList(std::move(result));
}
}*/
#define MAP_FILTER(item, seq, map, filter) ({\
using value_type = typename ValueTypeEx<decltype(seq)>::type;\
value_type item;\
std::vector<decltype(map)> result{};\
for (auto item : seq) {\
if (filter) {\
result.push_back(map);\
}\
}\
typon::TyList(std::move(result));\
})
namespace
PYBIND11_NAMESPACE
{
namespace
PYBIND11_NAMESPACE
{
namespace
detail
{
namespace
detail
{
...
...
typon/include/python/builtins/int.hpp
0 → 100644
View file @
b738512a
//
// Created by Tom on 08/03/2023.
//
#ifndef TYPON_INT_HPP
#define TYPON_INT_HPP
#include <sstream>
#include <string>
#include <algorithm>
using
namespace
std
::
literals
;
#include "bytes.hpp"
#include "print.hpp"
#include "slice.hpp"
// #include <format>
#include <fmt/format.h>
#include <pybind11/cast.h>
namespace
typon
{
/*template <typename _Base0 = object>
class TyInt__oo : classtype<_Base0, Integer__oo<>> {
public:
struct : method {
auto operator()(auto self, int value) const {
self->value = value;
}
} static constexpr oo__init__oo {};
struct : method {
auto operator()(auto self, auto other) const {
return Integer(dot(self, value) + dot(other, value));
}
} static constexpr oo__add__oo {};
auto operator () (int value) const {
struct Obj : instance<Integer__oo<>, Obj> {
int value;
};
auto obj = rc(Obj{});
dot(obj, oo__init__oo)(value);
return obj;
}
constexpr TyInt(int value) : value(value) {}
constexpr TyInt() : value(0) {}
operator int() const { return value; }
// operators
template <typename T> TyInt operator+(T x) const { return value + x; }
template <typename T> TyInt operator-(T x) const { return value - x; }
template <typename T> TyInt operator*(T x) const { return value * x; }
template <typename T> TyInt operator/(T x) const { return value / x; }
template <typename T> TyInt operator%(T x) const { return value % x; }
template <typename T> TyInt operator&(T x) const { return value & x; }
template <typename T> TyInt operator|(T x) const { return value | x; }
template <typename T> TyInt operator^(T x) const { return value ^ x; }
template <typename T> TyInt operator<<(T x) const { return value << x; }
template <typename T> TyInt operator>>(T x) const { return value >> x; }
template <typename T> TyInt operator&&(T x) const { return value && x; }
template <typename T> TyInt operator||(T x) const { return value || x; }
template <typename T> TyInt operator==(T x) const { return value == x; }
template <typename T> TyInt operator<(T x) const { return value < x; }
TyInt operator-() const { return -value; }
private:
int value;
};*/
using
namespace
referencemodel
;
template
<
typename
_Base0
=
object
>
struct
Integer__oo
:
classtype
<
_Base0
,
Integer__oo
<>>
{
static
constexpr
std
::
string_view
name
=
"Integer"
;
struct
:
method
{
auto
operator
()(
auto
self
,
int
value
)
const
{
self
->
value
=
value
;
}
}
static
constexpr
oo__init__oo
{};
struct
:
method
{
auto
operator
()(
auto
self
,
auto
other
)
const
{
return
TyInt
(
dot
(
self
,
value
)
+
dot
(
other
,
value
));
}
}
static
constexpr
oo__add__oo
{};
struct
Obj
:
value
<
Integer__oo
<>
,
Obj
>
{
int
value
;
Obj
(
int
value
=
0
)
:
value
(
value
)
{}
operator
int
()
const
{
return
value
;
}
};
auto
operator
()
(
int
value
)
const
{
auto
obj
=
rc
(
Obj
{});
dot
(
obj
,
oo__init__oo
)(
value
);
return
obj
;
}
};
static
constexpr
Integer__oo
<>
TyInt
{};
}
inline
auto
operator
""
_pi
(
unsigned
long
long
int
v
)
noexcept
{
return
typon
::
TyInt
(
v
);
}
template
<
>
struct
std
::
hash
<
decltype
(
0
_pi
)
>
{
std
::
size_t
operator
()(
const
decltype
(
0
_pi
)
&
s
)
const
noexcept
{
return
std
::
hash
<
int
>
()(
s
);
}
};
namespace
PYBIND11_NAMESPACE
{
namespace
detail
{
template
<
>
struct
type_caster
<
decltype
(
0
_pi
)
>
:
type_caster
<
int
>
{};
}}
template
<
>
void
repr_to
(
const
decltype
(
0
_pi
)
&
x
,
std
::
ostream
&
s
)
{
s
<<
x
;
}
template
<
>
void
print_to
<
decltype
(
0
_pi
)
>
(
const
decltype
(
0
_pi
)
&
x
,
std
::
ostream
&
s
)
{
s
<<
x
;
}
#endif // TYPON_INT_HPP
typon/include/python/builtins/print.hpp
View file @
b738512a
...
@@ -86,13 +86,14 @@ typon::Task<void> print(T const &head, Args const &...args) {
...
@@ -86,13 +86,14 @@ typon::Task<void> print(T const &head, Args const &...args) {
}*/
}*/
struct
{
struct
{
void
operator
()()
{
std
::
cout
<<
'\n'
;
}
typon
::
TyNone
operator
()()
{
std
::
cout
<<
'\n'
;
return
{}
;
}
template
<
Printable
T
,
Printable
...
Args
>
template
<
Printable
T
,
Printable
...
Args
>
void
operator
()(
T
const
&
head
,
Args
const
&
...
args
)
{
typon
::
TyNone
operator
()(
T
const
&
head
,
Args
const
&
...
args
)
{
print_to
(
head
,
std
::
cout
);
print_to
(
head
,
std
::
cout
);
(((
std
::
cout
<<
' '
),
print_to
(
args
,
std
::
cout
)),
...);
(((
std
::
cout
<<
' '
),
print_to
(
args
,
std
::
cout
)),
...);
std
::
cout
<<
'\n'
;
std
::
cout
<<
'\n'
;
return
{};
}
}
}
print
;
}
print
;
// typon::Task<void> print() { std::cout << '\n'; co_return; }
// typon::Task<void> print() { std::cout << '\n'; co_return; }
...
...
typon/include/python/builtins/range.hpp
View file @
b738512a
...
@@ -18,11 +18,7 @@ auto stride = [](int n) {
...
@@ -18,11 +18,7 @@ auto stride = [](int n) {
// todo: proper range support
// todo: proper range support
struct
range_s
:
TyBuiltin
<
range_s
>
struct
range_s
:
TyBuiltin
<
range_s
>
{
{
template
<
typename
T
>
auto
sync
(
int
start
,
int
stop
,
int
step
=
1
)
{
auto
sync
(
T
stop
)
{
return
sync
(
0
,
stop
);
}
template
<
typename
T
>
auto
sync
(
T
start
,
T
stop
,
T
step
=
1
)
{
// https://www.modernescpp.com/index.php/c-20-pythons-map-function/
// https://www.modernescpp.com/index.php/c-20-pythons-map-function/
if
(
step
==
0
)
{
if
(
step
==
0
)
{
throw
std
::
invalid_argument
(
"Step cannot be 0"
);
throw
std
::
invalid_argument
(
"Step cannot be 0"
);
...
@@ -36,6 +32,10 @@ struct range_s : TyBuiltin<range_s>
...
@@ -36,6 +32,10 @@ struct range_s : TyBuiltin<range_s>
return
start
<
stop
?
i
:
stop
-
(
i
-
start
);
return
start
<
stop
?
i
:
stop
-
(
i
-
start
);
});
});
}
}
auto
sync
(
int
stop
)
{
return
sync
(
0
,
stop
);
}
}
range
;
}
range
;
#endif // TYPON_RANGE_HPP
#endif // TYPON_RANGE_HPP
typon/include/python/referencemodel.hpp
View file @
b738512a
...
@@ -23,6 +23,9 @@ struct object;
...
@@ -23,6 +23,9 @@ struct object;
template
<
typename
T
,
typename
O
>
template
<
typename
T
,
typename
O
>
struct
instance
;
struct
instance
;
template
<
typename
T
,
typename
O
>
struct
value
;
template
<
typename
B
,
typename
T
>
template
<
typename
B
,
typename
T
>
struct
classtype
;
struct
classtype
;
...
@@ -168,6 +171,10 @@ using unwrap_pack = typename unwrap_pack_s<std::remove_cvref_t<T>>::type;
...
@@ -168,6 +171,10 @@ using unwrap_pack = typename unwrap_pack_s<std::remove_cvref_t<T>>::type;
/* Meta-programming utilities for object model */
/* Meta-programming utilities for object model */
template
<
typename
T
>
concept
object
=
std
::
derived_from
<
unwrap_all
<
T
>
,
referencemodel
::
object
>
;
template
<
typename
T
>
template
<
typename
T
>
concept
instance
=
std
::
derived_from
<
concept
instance
=
std
::
derived_from
<
unwrap_all
<
T
>
,
unwrap_all
<
T
>
,
...
@@ -215,7 +222,26 @@ concept boundmethod = boundmethod_s<std::remove_cvref_t<T>>::value;
...
@@ -215,7 +222,26 @@ concept boundmethod = boundmethod_s<std::remove_cvref_t<T>>::value;
template
<
typename
T
>
template
<
typename
T
>
concept
value
=
!
instance
<
T
>
&&
!
boundmethod
<
T
>
;
struct
value_s
{
static
constexpr
bool
value
=
true
;
};
template
<
instance
T
>
struct
value_s
<
T
>
{
static
constexpr
bool
value
=
std
::
derived_from
<
unwrap_all
<
T
>
,
referencemodel
::
value
<
typename
unwrap_all
<
T
>::
type
,
unwrap_all
<
T
>>
>
;
};
template
<
typename
S
,
typename
F
>
struct
value_s
<
referencemodel
::
boundmethod
<
S
,
F
>>
{
static
constexpr
bool
value
=
value_s
<
S
>::
value
;
};
template
<
typename
T
>
concept
value
=
value_s
<
std
::
remove_cvref_t
<
T
>>::
value
;
/* Meta-programming utilities: wrapped and unwrapped */
/* Meta-programming utilities: wrapped and unwrapped */
...
@@ -963,6 +989,10 @@ struct instance : T {
...
@@ -963,6 +989,10 @@ struct instance : T {
};
};
template
<
typename
T
,
typename
O
>
struct
value
:
instance
<
T
,
O
>
{};
template
<
typename
B
,
typename
T
>
template
<
typename
B
,
typename
T
>
struct
classtype
:
B
{
struct
classtype
:
B
{
using
base
=
B
;
using
base
=
B
;
...
@@ -1193,14 +1223,58 @@ decltype(auto) bind(S &&, const A & attr, T...) {
...
@@ -1193,14 +1223,58 @@ decltype(auto) bind(S &&, const A & attr, T...) {
return
attr
;
return
attr
;
}
}
}
// namespace referencemodel
#define dot(OBJ, NAME)\
#define dot(OBJ, NAME)\
[](auto && obj) -> decltype(auto) {\
[](auto && obj) -> decltype(auto) {\
return referencemodel::bind(std::forward<decltype(obj)>(obj), obj->NAME);\
return referencemodel::bind(std::forward<decltype(obj)>(obj), obj->NAME);\
}(OBJ)
}(OBJ)
/* Operators */
namespace
meta
{
/* + */
template
<
typename
Left
,
typename
Right
>
concept
LeftAddable
=
requires
(
Left
left
,
Right
right
)
{
// note: using dot here would cause hard failure instead of invalid constraint
left
->
oo__add__oo
(
left
,
right
);
};
template
<
typename
Left
,
typename
Right
>
concept
RightAddable
=
requires
(
Left
left
,
Right
right
)
{
// note: using dot here would cause hard failure instead of invalid constraint
right
->
oo__radd__oo
(
right
,
left
);
};
template
<
typename
Left
,
typename
Right
>
concept
Addable
=
LeftAddable
<
Left
,
Right
>
||
RightAddable
<
Left
,
Right
>
;
}
/* + */
template
<
meta
::
object
Left
,
meta
::
object
Right
>
requires
meta
::
Addable
<
Left
,
Right
>
auto
operator
+
(
Left
&&
left
,
Right
&&
right
)
{
if
constexpr
(
meta
::
LeftAddable
<
Left
,
Right
>
)
{
return
dot
(
std
::
forward
<
Left
>
(
left
),
oo__add__oo
)(
std
::
forward
<
Right
>
(
right
));
}
else
{
if
constexpr
(
meta
::
RightAddable
<
Left
,
Right
>
)
{
return
dot
(
std
::
forward
<
Right
>
(
right
),
oo__radd__oo
)(
std
::
forward
<
Left
>
(
left
));
}
}
}
}
// namespace referencemodel
#endif // REFERENCEMODEL_H
#endif // REFERENCEMODEL_H
runtime
@
26c320d7
Subproject commit
79677d125f915f7c61492d8d1d8cde9fc6a11875
Subproject commit
26c320d77d368d0f482684ebd653d1702c75a7f2
typon/trans/stdlib/builtins_.py
View file @
b738512a
...
@@ -3,8 +3,8 @@ from typing import Self, Protocol, Optional
...
@@ -3,8 +3,8 @@ from typing import Self, Protocol, Optional
assert
5
assert
5
class
object
:
class
object
:
def
__eq__
(
self
,
other
:
Self
)
->
bool
:
...
def
__eq__
[
T
](
self
,
other
:
T
)
->
bool
:
...
def
__ne__
(
self
,
other
:
Self
)
->
bool
:
...
def
__ne__
[
T
](
self
,
other
:
T
)
->
bool
:
...
class
int
:
class
int
:
def
__add__
(
self
,
other
:
Self
)
->
Self
:
...
def
__add__
(
self
,
other
:
Self
)
->
Self
:
...
...
@@ -96,6 +96,10 @@ assert [].__getitem__
...
@@ -96,6 +96,10 @@ assert [].__getitem__
assert
[
4
].
__getitem__
assert
[
4
].
__getitem__
assert
[
1
,
2
,
3
][
1
]
assert
[
1
,
2
,
3
][
1
]
class
set
[
U
]:
def
__len__
(
self
)
->
int
:
...
def
__contains__
(
self
,
item
:
U
)
->
bool
:
...
def
iter
[
U
](
x
:
Iterable
[
U
])
->
Iterator
[
U
]:
def
iter
[
U
](
x
:
Iterable
[
U
])
->
Iterator
[
U
]:
...
...
...
...
typon/trans/stdlib/typing_.py
View file @
b738512a
...
@@ -2,4 +2,5 @@
...
@@ -2,4 +2,5 @@
Protocol
=
BuiltinFeature
[
"Protocol"
]
Protocol
=
BuiltinFeature
[
"Protocol"
]
Self
=
BuiltinFeature
[
"Self"
]
Self
=
BuiltinFeature
[
"Self"
]
Optional
=
BuiltinFeature
[
"Optional"
]
Optional
=
BuiltinFeature
[
"Optional"
]
\ No newline at end of file
Callable
=
BuiltinFeature
[
"Callable"
]
\ No newline at end of file
typon/trans/test_runner.py
View file @
b738512a
...
@@ -88,15 +88,15 @@ def run_test(path, quiet=True):
...
@@ -88,15 +88,15 @@ def run_test(path, quiet=True):
if
args
.
compile
:
if
args
.
compile
:
return
TestStatus
.
SUCCESS
return
TestStatus
.
SUCCESS
execute_str
=
"true"
if
(
execute
and
not
args
.
generate
)
else
"false"
execute_str
=
"true"
if
(
execute
and
not
args
.
generate
)
else
"false"
name_bin
=
path
.
with_suffix
(
""
).
as_posix
()
+
(
"$(python3-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
python3
./
{
path
.
as_posix
()
}
; fi"'
)
!=
0
:
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
return
TestStatus
.
PYTHON_ERROR
if
compile
and
(
alt
:
=
environ
.
get
(
"ALT_RUNNER"
)):
if
compile
and
(
alt
:
=
environ
.
get
(
"ALT_RUNNER"
)):
if
(
code
:
=
exec_cmd
(
alt
.
format
(
if
(
code
:
=
exec_cmd
(
alt
.
format
(
name_bin
=
name_bin
,
name_bin
=
name_bin
,
name_cpp_posix
=
name_cpp
.
as_posix
(),
name_cpp_posix
=
name_cpp
.
as_posix
(),
run_file
=
execute_str
,
run_file
=
execute_str
,
test_exec
=
f"python3
{
path
.
with_suffix
(
'.post.py'
).
as_posix
()
}
"
if
extension
else
name_bin
,
test_exec
=
f"python3
.12
{
path
.
with_suffix
(
'.post.py'
).
as_posix
()
}
"
if
extension
else
name_bin
,
bonus_flags
=
"-e"
if
extension
else
""
bonus_flags
=
"-e"
if
extension
else
""
)))
!=
0
:
)))
!=
0
:
return
TestStatus
(
code
)
return
TestStatus
(
code
)
...
...
typon/trans/tests/builtins_test.py
View file @
b738512a
...
@@ -4,9 +4,9 @@ from typon import is_cpp
...
@@ -4,9 +4,9 @@ from typon import is_cpp
import
sys
as
sis
import
sys
as
sis
from
sys
import
stdout
as
truc
from
sys
import
stdout
as
truc
foo
=
123
#
foo = 123
test
=
(
2
+
3
)
*
4
#
test = (2 + 3) * 4
glob
=
5
#
glob = 5
# def g():
# def g():
# a = 8
# a = 8
...
@@ -20,32 +20,37 @@ glob = 5
...
@@ -20,32 +20,37 @@ glob = 5
# e = d + 1
# e = d + 1
# print(e)
# print(e)
def
f
(
x
):
#
def f(x):
return
x
+
1
#
return x + 1
#
#
def
fct
(
param
:
int
):
#
def fct(param: int):
loc
=
f
(
456
)
#
loc = f(456)
global
glob
#
global glob
loc
=
789
#
loc = 789
glob
=
123
#
glob = 123
#
def
fct2
():
#
def fct2():
global
glob
#
global glob
glob
+=
5
#
glob += 5
if
__name__
==
"__main__"
:
if
__name__
==
"__main__"
:
print
(
is_cpp
)
print
(
"is c++:"
,
is_cpp
()
)
# TODO: doesn't compile under G++ 12.2, fixed in trunk on March 15
# TODO: doesn't compile under G++ 12.2, fixed in trunk on March 15
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98056
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98056
sum
=
0
sum
=
0
for
i
in
range
(
15
):
for
i
in
range
(
15
):
sum
+=
i
sum
=
sum
+
i
a
=
[
n
for
n
in
range
(
10
)]
a
=
[
n
for
n
in
range
(
10
)]
b
=
[
x
for
x
in
a
if
x
%
2
==
0
]
#
b = [x for x in a if x % 2 == 0]
c
=
[
y
*
y
for
y
in
b
]
#
c = [y * y for y in b]
print
(
"C++ "
if
is_cpp
()
else
"Python"
,
print
(
"C++ "
if
is_cpp
()
else
"Python"
,
"res="
,
5
,
"."
,
True
,
[
4
,
5
,
6
],
{
7
,
8
,
9
},
[
1
,
2
]
+
[
3
,
4
],
[
5
,
6
]
*
3
,
{
1
:
7
,
9
:
3
},
0x55
&
7
==
5
,
"res="
,
5
,
"."
,
True
,
[
4
,
5
,
6
],
{
7
,
8
,
9
},
3j
,
sum
,
a
,
b
,
c
)
#[1, 2] + [3, 4], [5, 6] * 3, {1: 7, 9: 3},
#0x55 & 7 == 5,
#3j,
sum
,
a
)
print
(
"Typon"
)
print
()
print
()
typon/trans/transpiler/error_display.py
View file @
b738512a
...
@@ -2,10 +2,15 @@
...
@@ -2,10 +2,15 @@
import
ast
import
ast
import
builtins
import
builtins
import
importlib
import
importlib
import
inspect
import
sys
import
sys
import
traceback
import
traceback
import
colorful
as
cf
import
colorful
as
cf
from
transpiler.exceptions
import
CompileError
from
transpiler.utils
import
highlight
def
exception_hook
(
exc_type
,
exc_value
,
tb
):
def
exception_hook
(
exc_type
,
exc_value
,
tb
):
print
=
lambda
*
args
,
**
kwargs
:
builtins
.
print
(
*
args
,
**
kwargs
,
file
=
sys
.
stderr
)
print
=
lambda
*
args
,
**
kwargs
:
builtins
.
print
(
*
args
,
**
kwargs
,
file
=
sys
.
stderr
)
last_node
=
None
last_node
=
None
...
@@ -49,40 +54,44 @@ def exception_hook(exc_type, exc_value, tb):
...
@@ -49,40 +54,44 @@ def exception_hook(exc_type, exc_value, tb):
return
return
print
(
f"In file
{
cf
.
white
(
last_file
)
}
:
{
last_node
.
lineno
}
"
)
print
(
f"In file
{
cf
.
white
(
last_file
)
}
:
{
last_node
.
lineno
}
"
)
#print(f"From {last_node.lineno}:{last_node.col_offset} to {last_node.end_lineno}:{last_node.end_col_offset}")
#print(f"From {last_node.lineno}:{last_node.col_offset} to {last_node.end_lineno}:{last_node.end_col_offset}")
with
open
(
last_file
,
"r"
,
encoding
=
"utf-8"
)
as
f
:
try
:
code
=
f
.
read
()
with
open
(
last_file
,
"r"
,
encoding
=
"utf-8"
)
as
f
:
hg
=
(
str
(
highlight
(
code
,
True
))
code
=
f
.
read
()
.
replace
(
"
\
x1b
[04m"
,
""
)
except
Exception
:
.
replace
(
"
\
x1b
[24m"
,
""
)
pass
.
replace
(
"
\
x1b
[39;24m"
,
"
\
x1b
[39m"
)
.
splitlines
())
if
last_node
.
lineno
==
last_node
.
end_lineno
:
old
=
hg
[
last_node
.
lineno
-
1
]
start
,
end
=
find_indices
(
old
,
[
last_node
.
col_offset
,
last_node
.
end_col_offset
])
hg
[
last_node
.
lineno
-
1
]
=
old
[:
start
]
+
"
\
x1b
[4m"
+
old
[
start
:
end
]
+
"
\
x1b
[24m"
+
old
[
end
:]
else
:
else
:
old
=
hg
[
last_node
.
lineno
-
1
]
hg
=
(
str
(
highlight
(
code
,
True
))
[
start
]
=
find_indices
(
old
,
[
last_node
.
col_offset
])
.
replace
(
"
\
x1b
[04m"
,
""
)
hg
[
last_node
.
lineno
-
1
]
=
old
[:
start
]
+
"
\
x1b
[4m"
+
old
[
start
:]
.
replace
(
"
\
x1b
[24m"
,
""
)
for
lineid
in
range
(
last_node
.
lineno
,
last_node
.
end_lineno
-
1
):
.
replace
(
"
\
x1b
[39;24m"
,
"
\
x1b
[39m"
)
old
=
hg
[
lineid
]
.
splitlines
())
if
last_node
.
lineno
==
last_node
.
end_lineno
:
old
=
hg
[
last_node
.
lineno
-
1
]
start
,
end
=
find_indices
(
old
,
[
last_node
.
col_offset
,
last_node
.
end_col_offset
])
hg
[
last_node
.
lineno
-
1
]
=
old
[:
start
]
+
"
\
x1b
[4m"
+
old
[
start
:
end
]
+
"
\
x1b
[24m"
+
old
[
end
:]
else
:
old
=
hg
[
last_node
.
lineno
-
1
]
[
start
]
=
find_indices
(
old
,
[
last_node
.
col_offset
])
hg
[
last_node
.
lineno
-
1
]
=
old
[:
start
]
+
"
\
x1b
[4m"
+
old
[
start
:]
for
lineid
in
range
(
last_node
.
lineno
,
last_node
.
end_lineno
-
1
):
old
=
hg
[
lineid
]
first_nonspace
=
len
(
old
)
-
len
(
old
.
lstrip
())
hg
[
lineid
]
=
old
[:
first_nonspace
]
+
"
\
x1b
[4m"
+
old
[
first_nonspace
:]
+
"
\
x1b
[24m"
old
=
hg
[
last_node
.
end_lineno
-
1
]
first_nonspace
=
len
(
old
)
-
len
(
old
.
lstrip
())
first_nonspace
=
len
(
old
)
-
len
(
old
.
lstrip
())
hg
[
lineid
]
=
old
[:
first_nonspace
]
+
"
\
x1b
[4m"
+
old
[
first_nonspace
:]
+
"
\
x1b
[24m"
[
end
]
=
find_indices
(
old
,
[
last_node
.
end_col_offset
])
old
=
hg
[
last_node
.
end_lineno
-
1
]
hg
[
last_node
.
end_lineno
-
1
]
=
old
[:
first_nonspace
]
+
"
\
x1b
[4m"
+
old
[
first_nonspace
:
end
]
+
"
\
x1b
[24m"
+
old
[
end
:]
first_nonspace
=
len
(
old
)
-
len
(
old
.
lstrip
())
CONTEXT_SIZE
=
2
[
end
]
=
find_indices
(
old
,
[
last_node
.
end_col_offset
])
start
=
max
(
0
,
last_node
.
lineno
-
CONTEXT_SIZE
-
1
)
hg
[
last_node
.
end_lineno
-
1
]
=
old
[:
first_nonspace
]
+
"
\
x1b
[4m"
+
old
[
first_nonspace
:
end
]
+
"
\
x1b
[24m"
+
old
[
end
:]
offset
=
start
+
1
CONTEXT_SIZE
=
2
for
i
,
line
in
enumerate
(
hg
[
start
:
last_node
.
end_lineno
+
CONTEXT_SIZE
]):
start
=
max
(
0
,
last_node
.
lineno
-
CONTEXT_SIZE
-
1
)
erroneous
=
last_node
.
lineno
<=
offset
+
i
<=
last_node
.
end_lineno
offset
=
start
+
1
indicator
=
cf
.
white
(
" →"
)
if
erroneous
else
" "
for
i
,
line
in
enumerate
(
hg
[
start
:
last_node
.
end_lineno
+
CONTEXT_SIZE
]):
bar
=
" ▎"
erroneous
=
last_node
.
lineno
<=
offset
+
i
<=
last_node
.
end_lineno
# bar = "│" if erroneous else "┊"
indicator
=
cf
.
white
(
" →"
)
if
erroneous
else
" "
disp
=
f"
\
x1b
[24m
{
indicator
}{
cf
.
white
}{
(
offset
+
i
):
>
4
}{
cf
.
red
if
erroneous
else
cf
.
reset
}{
bar
}{
cf
.
reset
}
{
line
}\
x1b
[24m"
bar
=
" ▎"
print
(
disp
)
# bar = "│" if erroneous else "┊"
# print(repr(disp))
disp
=
f"
\
x1b
[24m
{
indicator
}{
cf
.
white
}{
(
offset
+
i
):
>
4
}{
cf
.
red
if
erroneous
else
cf
.
reset
}{
bar
}{
cf
.
reset
}
{
line
}\
x1b
[24m"
print
(
disp
)
# print(repr(disp))
print
()
print
()
if
isinstance
(
exc_value
,
CompileError
):
if
isinstance
(
exc_value
,
CompileError
):
print
(
cf
.
red
(
"Error:"
),
exc_value
)
print
(
cf
.
red
(
"Error:"
),
exc_value
)
...
...
typon/trans/transpiler/phases/desugar_op/__init__.py
View file @
b738512a
...
@@ -24,7 +24,7 @@ DUNDER = {
...
@@ -24,7 +24,7 @@ DUNDER = {
class
DesugarOp
(
ast
.
NodeTransformer
):
class
DesugarOp
(
ast
.
NodeTransformer
):
def
visit_BinOp
(
self
,
node
:
ast
.
BinOp
):
def
visit_BinOp
(
self
,
node
:
ast
.
BinOp
):
lnd
=
linenodata
(
node
)
lnd
=
linenodata
(
node
)
re
turn
ast
.
Call
(
re
s
=
ast
.
Call
(
func
=
ast
.
Attribute
(
func
=
ast
.
Attribute
(
value
=
self
.
visit
(
node
.
left
),
value
=
self
.
visit
(
node
.
left
),
attr
=
f"__
{
DUNDER
[
type
(
node
.
op
)]
}
__"
,
attr
=
f"__
{
DUNDER
[
type
(
node
.
op
)]
}
__"
,
...
@@ -35,26 +35,31 @@ class DesugarOp(ast.NodeTransformer):
...
@@ -35,26 +35,31 @@ class DesugarOp(ast.NodeTransformer):
keywords
=
{},
keywords
=
{},
**
lnd
**
lnd
)
)
res
.
orig_node
=
node
return
res
def
visit_UnaryOp
(
self
,
node
:
ast
.
UnaryOp
):
def
visit_UnaryOp
(
self
,
node
:
ast
.
UnaryOp
):
lnd
=
linenodata
(
node
)
lnd
=
linenodata
(
node
)
if
type
(
node
.
op
)
==
ast
.
Not
:
if
type
(
node
.
op
)
==
ast
.
Not
:
re
turn
ast
.
UnaryOp
(
re
s
=
ast
.
UnaryOp
(
operand
=
self
.
visit
(
node
.
operand
),
operand
=
self
.
visit
(
node
.
operand
),
op
=
node
.
op
,
op
=
node
.
op
,
**
lnd
**
lnd
)
)
return
ast
.
Call
(
else
:
func
=
ast
.
Attribute
(
res
=
ast
.
Call
(
value
=
self
.
visit
(
node
.
operand
),
func
=
ast
.
Attribute
(
attr
=
f"__
{
DUNDER
[
type
(
node
.
op
)]
}
__"
,
value
=
self
.
visit
(
node
.
operand
),
ctx
=
ast
.
Load
(),
attr
=
f"__
{
DUNDER
[
type
(
node
.
op
)]
}
__"
,
ctx
=
ast
.
Load
(),
**
lnd
),
args
=
[],
keywords
=
{},
**
lnd
**
lnd
),
)
args
=
[],
res
.
orig_node
=
node
keywords
=
{},
return
res
**
lnd
)
# def visit_AugAssign(self, node: ast.AugAssign):
# def visit_AugAssign(self, node: ast.AugAssign):
# return
# return
typon/trans/transpiler/phases/emit_cpp/class_.py
View file @
b738512a
import
ast
from
typing
import
Iterable
from
typing
import
Iterable
def
emit_class
(
clazz
)
->
Iterable
[
str
]:
def
emit_class
(
node
:
ast
.
ClassDef
)
->
Iterable
[
str
]:
yield
f"template <typename _Base0 = referencemodel::object>"
yield
f"template <typename _Base0 = referencemodel::object>"
yield
f"struct
{
node
.
name
}
__oo : referencemodel::classtype<_Base0,
{
node
.
name
}
__oo<>> {{"
yield
f"struct
{
node
.
name
}
__oo : referencemodel::classtype<_Base0,
{
node
.
name
}
__oo<>> {{"
yield
f"static constexpr std::string_view name =
\
"
{
node
.
name
}\
"
;"
yield
f"static constexpr std::string_view name =
\
"
{
node
.
name
}\
"
;"
...
...
typon/trans/transpiler/phases/emit_cpp/expr.py
View file @
b738512a
...
@@ -5,8 +5,35 @@ from typing import Iterable
...
@@ -5,8 +5,35 @@ from typing import Iterable
from
transpiler.phases.emit_cpp.visitors
import
NodeVisitor
,
CoroutineMode
,
join
from
transpiler.phases.emit_cpp.visitors
import
NodeVisitor
,
CoroutineMode
,
join
from
transpiler.phases.typing.scope
import
Scope
from
transpiler.phases.typing.scope
import
Scope
from
transpiler.phases.utils
import
make_lnd
from
transpiler.utils
import
linenodata
SYMBOLS
=
{
ast
.
Eq
:
"=="
,
ast
.
NotEq
:
'!='
,
ast
.
Pass
:
'/* pass */'
,
ast
.
Mult
:
'*'
,
ast
.
Add
:
'+'
,
ast
.
Sub
:
'-'
,
ast
.
Div
:
'/'
,
ast
.
FloorDiv
:
'/'
,
# TODO
ast
.
Mod
:
'%'
,
ast
.
Lt
:
'<'
,
ast
.
Gt
:
'>'
,
ast
.
GtE
:
'>='
,
ast
.
LtE
:
'<='
,
ast
.
LShift
:
'<<'
,
ast
.
RShift
:
'>>'
,
ast
.
BitXor
:
'^'
,
ast
.
BitOr
:
'|'
,
ast
.
BitAnd
:
'&'
,
ast
.
Not
:
'!'
,
ast
.
IsNot
:
'!='
,
ast
.
USub
:
'-'
,
ast
.
And
:
'&&'
,
ast
.
Or
:
'||'
}
"""Mapping of Python AST nodes to C++ symbols."""
# noinspection PyPep8Naming
# noinspection PyPep8Naming
@
dataclass
@
dataclass
...
@@ -33,7 +60,7 @@ class ExpressionVisitor(NodeVisitor):
...
@@ -33,7 +60,7 @@ class ExpressionVisitor(NodeVisitor):
yield
str
(
node
.
value
).
lower
()
yield
str
(
node
.
value
).
lower
()
elif
isinstance
(
node
.
value
,
int
):
elif
isinstance
(
node
.
value
,
int
):
# TODO: bigints
# TODO: bigints
yield
str
(
node
.
value
)
yield
str
(
node
.
value
)
+
"_pi"
elif
isinstance
(
node
.
value
,
float
):
elif
isinstance
(
node
.
value
,
float
):
yield
repr
(
node
.
value
)
yield
repr
(
node
.
value
)
elif
isinstance
(
node
.
value
,
complex
):
elif
isinstance
(
node
.
value
,
complex
):
...
@@ -44,7 +71,7 @@ class ExpressionVisitor(NodeVisitor):
...
@@ -44,7 +71,7 @@ class ExpressionVisitor(NodeVisitor):
raise
NotImplementedError
(
node
,
type
(
node
))
raise
NotImplementedError
(
node
,
type
(
node
))
def
visit_Slice
(
self
,
node
:
ast
.
Slice
)
->
Iterable
[
str
]:
def
visit_Slice
(
self
,
node
:
ast
.
Slice
)
->
Iterable
[
str
]:
yield
"TySlice("
yield
"
typon::
TySlice("
yield
from
join
(
", "
,
(
self
.
visit
(
x
or
ast
.
Constant
(
value
=
None
))
for
x
in
(
node
.
lower
,
node
.
upper
,
node
.
step
)))
yield
from
join
(
", "
,
(
self
.
visit
(
x
or
ast
.
Constant
(
value
=
None
))
for
x
in
(
node
.
lower
,
node
.
upper
,
node
.
step
)))
yield
")"
yield
")"
...
@@ -79,22 +106,22 @@ class ExpressionVisitor(NodeVisitor):
...
@@ -79,22 +106,22 @@ class ExpressionVisitor(NodeVisitor):
# yield from self.visit_binary_operation(op, left, right, make_lnd(left, right))
# yield from self.visit_binary_operation(op, left, right, make_lnd(left, right))
def
visit_BoolOp
(
self
,
node
:
ast
.
BoolOp
)
->
Iterable
[
str
]:
def
visit_BoolOp
(
self
,
node
:
ast
.
BoolOp
)
->
Iterable
[
str
]:
raise
NotImplementedError
()
if
len
(
node
.
values
)
==
1
:
yield
from
self
.
visit
(
node
.
values
[
0
])
# if len(node.values) == 1:
return
# yield from self.visit(node.values[0])
cpp_op
=
{
# return
ast
.
And
:
"&&"
,
# cpp_op = {
ast
.
Or
:
"||"
# ast.And: "&&",
}[
type
(
node
.
op
)]
# ast.Or: "||"
yield
"("
# }[type(node.op)]
yield
from
self
.
visit_binary_operation
(
cpp_op
,
node
.
values
[
0
],
node
.
values
[
1
],
make_lnd
(
node
.
values
[
0
],
node
.
values
[
1
]))
# with self.prec_ctx(cpp_op):
for
left
,
right
in
zip
(
node
.
values
[
1
:],
node
.
values
[
2
:]):
# yield from self.visit_binary_operation(cpp_op, node.values[0], node.values[1], make_lnd(node.values[0], node.values[1]))
yield
f"
{
cpp_op
}
"
# for left, right in zip(node.values[1:], node.values[2:]):
yield
from
self
.
visit_binary_operation
(
cpp_op
,
left
,
right
,
make_lnd
(
left
,
right
))
# yield f" {cpp_op} "
yield
")"
# yield from self.visit_binary_operation(cpp_op, left, right, make_lnd(left, right))
def
visit_Call
(
self
,
node
:
ast
.
Call
)
->
Iterable
[
str
]:
def
visit_Call
(
self
,
node
:
ast
.
Call
)
->
Iterable
[
str
]:
yield
"co_await"
yield
"("
yield
"("
yield
from
self
.
visit
(
node
.
func
)
yield
from
self
.
visit
(
node
.
func
)
yield
")("
yield
")("
...
@@ -158,6 +185,8 @@ class ExpressionVisitor(NodeVisitor):
...
@@ -158,6 +185,8 @@ class ExpressionVisitor(NodeVisitor):
templ
,
args
,
_
=
self
.
process_args
(
node
.
args
)
templ
,
args
,
_
=
self
.
process_args
(
node
.
args
)
yield
templ
yield
templ
yield
args
yield
args
yield
"->"
yield
from
self
.
visit
(
node
.
type
.
deref
().
return_type
)
yield
"{"
yield
"{"
yield
"return"
yield
"return"
yield
from
self
.
reset
().
visit
(
node
.
body
)
yield
from
self
.
reset
().
visit
(
node
.
body
)
...
@@ -165,14 +194,20 @@ class ExpressionVisitor(NodeVisitor):
...
@@ -165,14 +194,20 @@ class ExpressionVisitor(NodeVisitor):
yield
"}"
yield
"}"
def
visit_BinOp
(
self
,
node
:
ast
.
BinOp
)
->
Iterable
[
str
]:
def
visit_BinOp
(
self
,
node
:
ast
.
BinOp
)
->
Iterable
[
str
]:
raise
NotImplementedError
()
yield
from
self
.
visit_binary_operation
(
node
.
op
,
node
.
left
,
node
.
right
,
linenodata
(
node
))
yield
from
self
.
visit_binary_operation
(
node
.
op
,
node
.
left
,
node
.
right
,
linenodata
(
node
))
def
visit_Compare
(
self
,
node
:
ast
.
Compare
)
->
Iterable
[
str
]:
def
visit_Compare
(
self
,
node
:
ast
.
Compare
)
->
Iterable
[
str
]:
raise
NotImplementedError
()
yield
from
self
.
visit_binary_operation
(
node
.
ops
[
0
],
node
.
left
,
node
.
comparators
[
0
],
linenodata
(
node
))
yield
from
self
.
visit_binary_operation
(
node
.
ops
[
0
],
node
.
left
,
node
.
comparators
[
0
],
linenodata
(
node
))
def
visit_binary_operation
(
self
,
op
,
left
:
ast
.
AST
,
right
:
ast
.
AST
,
lnd
:
dict
)
->
Iterable
[
str
]:
def
visit_binary_operation
(
self
,
op
,
left
:
ast
.
AST
,
right
:
ast
.
AST
,
lnd
:
dict
)
->
Iterable
[
str
]:
yield
"(co_await ("
yield
from
self
.
visit
(
left
)
yield
" "
yield
SYMBOLS
[
type
(
op
)]
yield
" "
yield
from
self
.
visit
(
right
)
yield
"))"
return
raise
NotImplementedError
()
raise
NotImplementedError
()
# if type(op) == ast.In:
# if type(op) == ast.In:
# call = ast.Call(ast.Attribute(right, "__contains__", **lnd), [left], [], **lnd)
# call = ast.Call(ast.Attribute(right, "__contains__", **lnd), [left], [], **lnd)
...
@@ -205,7 +240,7 @@ class ExpressionVisitor(NodeVisitor):
...
@@ -205,7 +240,7 @@ class ExpressionVisitor(NodeVisitor):
def
visit_List
(
self
,
node
:
ast
.
List
)
->
Iterable
[
str
]:
def
visit_List
(
self
,
node
:
ast
.
List
)
->
Iterable
[
str
]:
if
node
.
elts
:
if
node
.
elts
:
yield
"typon::TyList{"
yield
"typon::TyList{"
yield
from
join
(
", "
,
map
(
self
.
reset
().
visit
,
node
.
elts
))
yield
from
join
(
", "
,
map
(
self
.
visit
,
node
.
elts
))
yield
"}"
yield
"}"
else
:
else
:
yield
from
self
.
visit
(
node
.
type
)
yield
from
self
.
visit
(
node
.
type
)
...
@@ -214,7 +249,7 @@ class ExpressionVisitor(NodeVisitor):
...
@@ -214,7 +249,7 @@ class ExpressionVisitor(NodeVisitor):
def
visit_Set
(
self
,
node
:
ast
.
Set
)
->
Iterable
[
str
]:
def
visit_Set
(
self
,
node
:
ast
.
Set
)
->
Iterable
[
str
]:
if
node
.
elts
:
if
node
.
elts
:
yield
"typon::TySet{"
yield
"typon::TySet{"
yield
from
join
(
", "
,
map
(
self
.
reset
().
visit
,
node
.
elts
))
yield
from
join
(
", "
,
map
(
self
.
visit
,
node
.
elts
))
yield
"}"
yield
"}"
else
:
else
:
yield
from
self
.
visit
(
node
.
type
)
yield
from
self
.
visit
(
node
.
type
)
...
@@ -223,9 +258,9 @@ class ExpressionVisitor(NodeVisitor):
...
@@ -223,9 +258,9 @@ class ExpressionVisitor(NodeVisitor):
def
visit_Dict
(
self
,
node
:
ast
.
Dict
)
->
Iterable
[
str
]:
def
visit_Dict
(
self
,
node
:
ast
.
Dict
)
->
Iterable
[
str
]:
def
visit_item
(
key
,
value
):
def
visit_item
(
key
,
value
):
yield
"std::pair {"
yield
"std::pair {"
yield
from
self
.
reset
().
visit
(
key
)
yield
from
self
.
visit
(
key
)
yield
", "
yield
", "
yield
from
self
.
reset
().
visit
(
value
)
yield
from
self
.
visit
(
value
)
yield
"}"
yield
"}"
if
node
.
keys
:
if
node
.
keys
:
...
@@ -256,12 +291,13 @@ class ExpressionVisitor(NodeVisitor):
...
@@ -256,12 +291,13 @@ class ExpressionVisitor(NodeVisitor):
yield
from
self
.
prec
(
"unary"
).
visit
(
operand
)
yield
from
self
.
prec
(
"unary"
).
visit
(
operand
)
def
visit_IfExp
(
self
,
node
:
ast
.
IfExp
)
->
Iterable
[
str
]:
def
visit_IfExp
(
self
,
node
:
ast
.
IfExp
)
->
Iterable
[
str
]:
with
self
.
prec_ctx
(
"?:"
):
yield
"("
yield
from
self
.
visit
(
node
.
test
)
yield
from
self
.
visit
(
node
.
test
)
yield
" ? "
yield
" ? "
yield
from
self
.
visit
(
node
.
body
)
yield
from
self
.
visit
(
node
.
body
)
yield
" : "
yield
" : "
yield
from
self
.
visit
(
node
.
orelse
)
yield
from
self
.
visit
(
node
.
orelse
)
yield
")"
def
visit_Yield
(
self
,
node
:
ast
.
Yield
)
->
Iterable
[
str
]:
def
visit_Yield
(
self
,
node
:
ast
.
Yield
)
->
Iterable
[
str
]:
#if CoroutineMode.GENERATOR in self.generator:
#if CoroutineMode.GENERATOR in self.generator:
...
@@ -279,8 +315,23 @@ class ExpressionVisitor(NodeVisitor):
...
@@ -279,8 +315,23 @@ class ExpressionVisitor(NodeVisitor):
if
len
(
node
.
generators
)
!=
1
:
if
len
(
node
.
generators
)
!=
1
:
raise
NotImplementedError
(
"Multiple generators not handled yet"
)
raise
NotImplementedError
(
"Multiple generators not handled yet"
)
gen
:
ast
.
comprehension
=
node
.
generators
[
0
]
gen
:
ast
.
comprehension
=
node
.
generators
[
0
]
yield
"MAP_FILTER("
yield
from
self
.
visit
(
gen
.
target
)
yield
","
yield
from
self
.
visit
(
gen
.
iter
)
yield
", "
yield
from
self
.
visit
(
node
.
elt
)
yield
", "
if
gen
.
ifs
:
yield
from
self
.
visit
(
gen
.
ifs_node
)
else
:
yield
"true"
yield
")"
return
yield
"mapFilter([]("
yield
"mapFilter([]("
yield
from
self
.
visit
(
node
.
input_item_type
)
#yield from self.visit(node.input_item_type)
yield
"auto"
yield
from
self
.
visit
(
gen
.
target
)
yield
from
self
.
visit
(
gen
.
target
)
yield
") { return "
yield
") { return "
yield
from
self
.
visit
(
node
.
elt
)
yield
from
self
.
visit
(
node
.
elt
)
...
@@ -289,9 +340,12 @@ class ExpressionVisitor(NodeVisitor):
...
@@ -289,9 +340,12 @@ class ExpressionVisitor(NodeVisitor):
if
gen
.
ifs
:
if
gen
.
ifs
:
yield
", "
yield
", "
yield
"[]("
yield
"[]("
yield
from
self
.
visit
(
node
.
input_item_type
)
#yield from self.visit(node.input_item_type)
yield
"auto"
yield
from
self
.
visit
(
gen
.
target
)
yield
from
self
.
visit
(
gen
.
target
)
yield
") { return "
yield
") -> typon::Task<"
yield
from
self
.
visit
(
gen
.
ifs_node
.
type
)
yield
"> { return "
yield
from
self
.
visit
(
gen
.
ifs_node
)
yield
from
self
.
visit
(
gen
.
ifs_node
)
yield
"; }"
yield
"; }"
yield
")"
yield
")"
...
...
typon/trans/transpiler/phases/emit_cpp/function.py
View file @
b738512a
...
@@ -3,6 +3,7 @@ from dataclasses import dataclass, field
...
@@ -3,6 +3,7 @@ from dataclasses import dataclass, field
from
typing
import
Iterable
,
Optional
from
typing
import
Iterable
,
Optional
from
transpiler.phases.emit_cpp.expr
import
ExpressionVisitor
from
transpiler.phases.emit_cpp.expr
import
ExpressionVisitor
from
transpiler.phases.typing.common
import
IsDeclare
from
transpiler.phases.typing.scope
import
Scope
from
transpiler.phases.typing.scope
import
Scope
from
transpiler.phases.emit_cpp.visitors
import
NodeVisitor
,
flatmap
,
CoroutineMode
from
transpiler.phases.emit_cpp.visitors
import
NodeVisitor
,
flatmap
,
CoroutineMode
from
transpiler.phases.typing.types
import
CallableInstanceType
,
BaseType
from
transpiler.phases.typing.types
import
CallableInstanceType
,
BaseType
...
@@ -10,7 +11,7 @@ from transpiler.phases.typing.types import CallableInstanceType, BaseType
...
@@ -10,7 +11,7 @@ from transpiler.phases.typing.types import CallableInstanceType, BaseType
def
emit_function
(
name
:
str
,
func
:
CallableInstanceType
)
->
Iterable
[
str
]:
def
emit_function
(
name
:
str
,
func
:
CallableInstanceType
)
->
Iterable
[
str
]:
yield
f"struct : referencemodel::function {{"
yield
f"struct : referencemodel::function {{"
yield
"typon::Task<
void
> operator()("
yield
"typon::Task<
typon::TyNone
> operator()("
for
arg
,
ty
in
zip
(
func
.
block_data
.
node
.
args
.
args
,
func
.
parameters
):
for
arg
,
ty
in
zip
(
func
.
block_data
.
node
.
args
.
args
,
func
.
parameters
):
yield
"auto "
yield
"auto "
...
@@ -151,32 +152,36 @@ class BlockVisitor(NodeVisitor):
...
@@ -151,32 +152,36 @@ class BlockVisitor(NodeVisitor):
#
#
# yield "}"
# yield "}"
#
#
# def visit_lvalue(self, lvalue: ast.expr, declare: bool | list[bool] = False) -> Iterable[str]:
def
visit_lvalue
(
self
,
lvalue
:
ast
.
expr
,
declare
:
IsDeclare
)
->
Iterable
[
str
]:
# if isinstance(lvalue, ast.Tuple):
if
isinstance
(
lvalue
,
ast
.
Tuple
):
# for name, decl, ty in zip(lvalue.elts, declare, lvalue.type.args):
raise
NotImplementedError
()
# if decl:
# for name, decl, ty in zip(lvalue.elts, declare, lvalue.type.args):
# yield from self.visit_lvalue(name, True)
# if decl:
# yield ";"
# yield from self.visit_lvalue(name, True)
# yield f"std::tie({', '.join(flatmap(self.visit_lvalue, lvalue.elts))})"
# yield ";"
# elif isinstance(lvalue, ast.Name):
# yield f"std::tie({', '.join(flatmap(self.visit_lvalue, lvalue.elts))})"
# if lvalue.id == "_":
elif
isinstance
(
lvalue
,
ast
.
Name
):
# if not declare:
if
lvalue
.
id
==
"_"
:
# yield "std::ignore"
if
not
declare
:
# return
yield
"std::ignore"
# name = self.fix_name(lvalue.id)
return
# # if name not in self._scope.vars:
name
=
self
.
fix_name
(
lvalue
.
id
)
# # if not self.scope.exists_local(name):
# if name not in self._scope.vars:
# # yield self.scope.declare(name, (" ".join(self.expr().visit(val)), val) if val else None,
# if not self.scope.exists_local(name):
# # getattr(val, "is_future", False))
# yield self.scope.declare(name, (" ".join(self.expr().visit(val)), val) if val else None,
# if declare:
# getattr(val, "is_future", False))
# yield from self.visit(lvalue.type)
if
declare
:
# yield name
yield
"decltype("
# elif isinstance(lvalue, ast.Subscript):
yield
from
self
.
expr
().
visit
(
declare
.
initial_value
)
# yield from self.expr().visit(lvalue)
yield
")"
# elif isinstance(lvalue, ast.Attribute):
#yield from self.visit(lvalue.type)
# yield from self.expr().visit(lvalue)
yield
name
# else:
elif
isinstance
(
lvalue
,
ast
.
Subscript
):
# raise NotImplementedError(lvalue)
yield
from
self
.
expr
().
visit
(
lvalue
)
elif
isinstance
(
lvalue
,
ast
.
Attribute
):
yield
from
self
.
expr
().
visit
(
lvalue
)
else
:
raise
NotImplementedError
(
lvalue
)
def
visit_Assign
(
self
,
node
:
ast
.
Assign
)
->
Iterable
[
str
]:
def
visit_Assign
(
self
,
node
:
ast
.
Assign
)
->
Iterable
[
str
]:
if
len
(
node
.
targets
)
!=
1
:
if
len
(
node
.
targets
)
!=
1
:
...
@@ -192,3 +197,27 @@ class BlockVisitor(NodeVisitor):
...
@@ -192,3 +197,27 @@ class BlockVisitor(NodeVisitor):
yield
" = "
yield
" = "
yield
from
self
.
expr
().
visit
(
node
.
value
)
yield
from
self
.
expr
().
visit
(
node
.
value
)
yield
";"
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
emit_block
(
self
,
scope
:
Scope
,
items
:
Iterable
[
ast
.
stmt
])
->
Iterable
[
str
]:
yield
"{"
for
child
in
items
:
yield
from
BlockVisitor
(
scope
,
generator
=
self
.
generator
).
visit
(
child
)
yield
"}"
typon/trans/transpiler/phases/emit_cpp/visitors.py
View file @
b738512a
...
@@ -15,6 +15,9 @@ class UniversalVisitor:
...
@@ -15,6 +15,9 @@ class UniversalVisitor:
__TB__
=
f"emitting C++ code for
{
highlight
(
node
)
}
"
__TB__
=
f"emitting C++ code for
{
highlight
(
node
)
}
"
# __TB_SKIP__ = True
# __TB_SKIP__ = True
if
orig
:
=
getattr
(
node
,
"orig_node"
,
None
):
node
=
orig
if
type
(
node
)
==
list
:
if
type
(
node
)
==
list
:
for
n
in
node
:
for
n
in
node
:
yield
from
self
.
visit
(
n
)
yield
from
self
.
visit
(
n
)
...
@@ -56,17 +59,28 @@ class NodeVisitor(UniversalVisitor):
...
@@ -56,17 +59,28 @@ class NodeVisitor(UniversalVisitor):
match
node
:
match
node
:
case
types
.
TY_INT
:
case
types
.
TY_INT
:
yield
"
int
"
yield
"
decltype(0_pi)
"
case
types
.
TY_FLOAT
:
case
types
.
TY_FLOAT
:
yield
"double"
yield
"double"
case
types
.
TY_BOOL
:
case
types
.
TY_BOOL
:
yield
"bool"
yield
"bool"
case
types
.
TY_NONE
:
case
types
.
TY_NONE
:
yield
"
void
"
yield
"
typon::TyNone
"
case
types
.
TY_STR
:
case
types
.
TY_STR
:
yield
"TyStr"
yield
"
typon::
TyStr"
case
types
.
TypeVariable
(
name
):
case
types
.
TypeVariable
(
name
):
raise
UnresolvedTypeVariableError
(
node
)
raise
UnresolvedTypeVariableError
(
node
)
case
types
.
GenericInstanceType
():
yield
from
self
.
visit
(
node
.
generic_parent
)
yield
"<"
yield
from
join
(
","
,
map
(
self
.
visit
,
node
.
generic_args
))
yield
">"
case
types
.
TY_LIST
:
yield
"typon::TyList"
case
types
.
TY_DICT
:
yield
"typon::TyDict"
case
types
.
TY_SET
:
yield
"typon::TySet"
case
_
:
case
_
:
raise
NotImplementedError
(
node
)
raise
NotImplementedError
(
node
)
...
...
typon/trans/transpiler/phases/typing/block.py
View file @
b738512a
This diff is collapsed.
Click to expand it.
typon/trans/transpiler/phases/typing/class_.py
View file @
b738512a
# coding: utf-8
# coding: utf-8
import
ast
#
import ast
from
dataclasses
import
dataclass
,
field
#
from dataclasses import dataclass, field
#
from
transpiler.phases.typing
import
FunctionType
,
ScopeKind
,
VarDecl
,
VarKind
,
TY_NONE
#
from transpiler.phases.typing import FunctionType, ScopeKind, VarDecl, VarKind, TY_NONE
from
transpiler.phases.typing.common
import
ScoperVisitor
#
from transpiler.phases.typing.common import ScoperVisitor
from
transpiler.phases.typing.types
import
PromiseKind
,
Promise
,
BaseType
,
MemberDef
#
from transpiler.phases.typing.types import PromiseKind, Promise, BaseType, MemberDef
#
#
@
dataclass
#
@dataclass
class
ScoperClassVisitor
(
ScoperVisitor
):
#
class ScoperClassVisitor(ScoperVisitor):
fdecls
:
list
[(
ast
.
FunctionDef
,
BaseType
)]
=
field
(
default_factory
=
list
)
#
fdecls: list[(ast.FunctionDef, BaseType)] = field(default_factory=list)
#
def
visit_AnnAssign
(
self
,
node
:
ast
.
AnnAssign
):
#
def visit_AnnAssign(self, node: ast.AnnAssign):
assert
node
.
value
is
None
,
"Class field should not have a value"
#
assert node.value is None, "Class field should not have a value"
assert
node
.
simple
==
1
,
"Class field should be simple (identifier, not parenthesized)"
#
assert node.simple == 1, "Class field should be simple (identifier, not parenthesized)"
assert
isinstance
(
node
.
target
,
ast
.
Name
)
#
assert isinstance(node.target, ast.Name)
self
.
scope
.
obj_type
.
fields
[
node
.
target
.
id
]
=
MemberDef
(
self
.
visit_annotation
(
node
.
annotation
))
#
self.scope.obj_type.fields[node.target.id] = MemberDef(self.visit_annotation(node.annotation))
#
def
visit_Assign
(
self
,
node
:
ast
.
Assign
):
#
def visit_Assign(self, node: ast.Assign):
assert
len
(
node
.
targets
)
==
1
,
"Can't use destructuring in class static member"
#
assert len(node.targets) == 1, "Can't use destructuring in class static member"
assert
isinstance
(
node
.
targets
[
0
],
ast
.
Name
)
#
assert isinstance(node.targets[0], ast.Name)
node
.
is_declare
=
True
#
node.is_declare = True
valtype
=
self
.
expr
().
visit
(
node
.
value
)
#
valtype = self.expr().visit(node.value)
node
.
targets
[
0
].
type
=
valtype
#
node.targets[0].type = valtype
self
.
scope
.
obj_type
.
fields
[
node
.
targets
[
0
].
id
]
=
MemberDef
(
valtype
,
node
.
value
)
#
self.scope.obj_type.fields[node.targets[0].id] = MemberDef(valtype, node.value)
#
def
visit_FunctionDef
(
self
,
node
:
ast
.
FunctionDef
):
#
def visit_FunctionDef(self, node: ast.FunctionDef):
ftype
=
self
.
parse_function
(
node
)
#
ftype = self.parse_function(node)
ftype
.
parameters
[
0
].
unify
(
self
.
scope
.
obj_type
)
#
ftype.parameters[0].unify(self.scope.obj_type)
inner
=
ftype
.
return_type
#
inner = ftype.return_type
if
node
.
name
!=
"__init__"
:
#
if node.name != "__init__":
ftype
.
return_type
=
Promise
(
ftype
.
return_type
,
PromiseKind
.
TASK
)
#
ftype.return_type = Promise(ftype.return_type, PromiseKind.TASK)
ftype
.
is_method
=
True
#
ftype.is_method = True
self
.
scope
.
obj_type
.
fields
[
node
.
name
]
=
MemberDef
(
ftype
,
node
)
#
self.scope.obj_type.fields[node.name] = MemberDef(ftype, node)
return
(
node
,
inner
)
#
return (node, inner)
typon/trans/transpiler/phases/typing/common.py
View file @
b738512a
import
ast
import
ast
from
dataclasses
import
dataclass
,
field
from
dataclasses
import
dataclass
,
field
from
typing
import
Dict
,
Optional
from
typing
import
Dict
,
Optional
,
TYPE_CHECKING
if
TYPE_CHECKING
:
from
transpiler.phases.typing.expr
import
ScoperExprVisitor
from
transpiler.utils
import
highlight
from
transpiler.utils
import
highlight
from
transpiler.phases.typing.annotations
import
TypeAnnotationVisitor
from
transpiler.phases.typing.annotations
import
TypeAnnotationVisitor
from
transpiler.phases.typing.scope
import
Scope
,
ScopeKind
,
VarDecl
,
VarKind
from
transpiler.phases.typing.scope
import
Scope
,
ScopeKind
,
VarDecl
,
VarKind
...
@@ -10,6 +12,7 @@ from transpiler.phases.utils import NodeVisitorSeq, AnnotationName
...
@@ -10,6 +12,7 @@ from transpiler.phases.utils import NodeVisitorSeq, AnnotationName
PRELUDE
=
Scope
.
make_global
()
PRELUDE
=
Scope
.
make_global
()
@
dataclass
@
dataclass
class
ScoperVisitor
(
NodeVisitorSeq
):
class
ScoperVisitor
(
NodeVisitorSeq
):
scope
:
Scope
=
field
(
default_factory
=
lambda
:
PRELUDE
.
child
(
ScopeKind
.
GLOBAL
))
scope
:
Scope
=
field
(
default_factory
=
lambda
:
PRELUDE
.
child
(
ScopeKind
.
GLOBAL
))
...
@@ -93,10 +96,11 @@ class ScoperVisitor(NodeVisitorSeq):
...
@@ -93,10 +96,11 @@ class ScoperVisitor(NodeVisitorSeq):
elif
len
(
visitor
.
fdecls
)
==
1
:
elif
len
(
visitor
.
fdecls
)
==
1
:
fnode
,
frtype
=
visitor
.
fdecls
[
0
]
fnode
,
frtype
=
visitor
.
fdecls
[
0
]
self
.
visit_function_definition
(
fnode
,
frtype
)
self
.
visit_function_definition
(
fnode
,
frtype
)
#del node.inner_scope.vars[fnode.name]
#
del node.inner_scope.vars[fnode.name]
visitor
.
visit_assign_target
(
ast
.
Name
(
fnode
.
name
),
fnode
.
type
)
visitor
.
visit_assign_target
(
ast
.
Name
(
fnode
.
name
),
fnode
.
type
)
b
.
decls
=
decls
b
.
decls
=
decls
if
not
node
.
inner_scope
.
diverges
and
not
(
isinstance
(
node
.
type
.
return_type
,
Promise
)
and
node
.
type
.
return_type
.
kind
==
PromiseKind
.
GENERATOR
):
if
not
node
.
inner_scope
.
diverges
and
not
(
isinstance
(
node
.
type
.
return_type
,
Promise
)
and
node
.
type
.
return_type
.
kind
==
PromiseKind
.
GENERATOR
):
from
transpiler.phases.typing.exceptions
import
TypeMismatchError
from
transpiler.phases.typing.exceptions
import
TypeMismatchError
try
:
try
:
rtype
.
unify
(
TY_NONE
)
rtype
.
unify
(
TY_NONE
)
...
@@ -104,21 +108,28 @@ class ScoperVisitor(NodeVisitorSeq):
...
@@ -104,21 +108,28 @@ class ScoperVisitor(NodeVisitorSeq):
from
transpiler.phases.typing.exceptions
import
MissingReturnError
from
transpiler.phases.typing.exceptions
import
MissingReturnError
raise
MissingReturnError
(
node
)
from
e
raise
MissingReturnError
(
node
)
from
e
def
get_iter
(
seq_type
):
def
get_iter
(
self
,
seq_type
):
try
:
try
:
iter_type
=
seq_type
.
fields
[
"__iter__"
].
type
.
return_type
return
self
.
expr
().
visit_function_call
(
self
.
expr
().
visit_getattr
(
seq_type
,
"__iter__"
),
[])
except
:
except
:
from
transpiler.phases.typing.exceptions
import
NotIterableError
from
transpiler.phases.typing.exceptions
import
NotIterableError
raise
NotIterableError
(
seq_type
)
raise
NotIterableError
(
seq_type
)
return
iter_type
def
get_next
(
self
,
iter_type
):
def
get_next
(
iter_type
):
try
:
try
:
return
self
.
expr
().
visit_function_call
(
self
.
expr
().
visit_getattr
(
iter_type
,
"__next__"
),
[])
next_type
=
iter_type
.
fields
[
"__next__"
].
type
.
return_type
except
:
except
:
from
transpiler.phases.typing.exceptions
import
NotIterableError
from
transpiler.phases.typing.exceptions
import
NotIteratorError
raise
NotIterableError
(
iter_type
)
raise
NotIteratorError
(
iter_type
)
return
next_type
def
is_builtin
(
x
,
feature
):
def
is_builtin
(
x
,
feature
):
return
isinstance
(
x
,
BuiltinFeatureType
)
and
x
.
feature
()
==
feature
return
isinstance
(
x
,
BuiltinFeatureType
)
and
x
.
feature
()
==
feature
\ No newline at end of file
@
dataclass
class
DeclareInfo
:
initial_value
:
Optional
[
ast
.
expr
]
=
None
IsDeclare
=
None
|
DeclareInfo
typon/trans/transpiler/phases/typing/expr.py
View file @
b738512a
...
@@ -4,7 +4,7 @@ import inspect
...
@@ -4,7 +4,7 @@ import inspect
from
itertools
import
zip_longest
from
itertools
import
zip_longest
from
typing
import
List
from
typing
import
List
from
transpiler.phases.typing.common
import
ScoperVisitor
,
get_iter
,
get_next
,
is_builtin
from
transpiler.phases.typing.common
import
ScoperVisitor
,
is_builtin
from
transpiler.phases.typing.exceptions
import
ArgumentCountMismatchError
,
TypeMismatchKind
,
TypeMismatchError
from
transpiler.phases.typing.exceptions
import
ArgumentCountMismatchError
,
TypeMismatchKind
,
TypeMismatchError
from
transpiler.phases.typing.types
import
BaseType
,
TY_STR
,
TY_BOOL
,
TY_INT
,
TY_COMPLEX
,
TY_FLOAT
,
TY_NONE
,
\
from
transpiler.phases.typing.types
import
BaseType
,
TY_STR
,
TY_BOOL
,
TY_INT
,
TY_COMPLEX
,
TY_FLOAT
,
TY_NONE
,
\
ClassTypeType
,
ResolvedConcreteType
,
GenericType
,
CallableInstanceType
,
TY_LIST
,
TY_SET
,
TY_DICT
,
RuntimeValue
,
\
ClassTypeType
,
ResolvedConcreteType
,
GenericType
,
CallableInstanceType
,
TY_LIST
,
TY_SET
,
TY_DICT
,
RuntimeValue
,
\
...
@@ -141,7 +141,12 @@ class ScoperExprVisitor(ScoperVisitor):
...
@@ -141,7 +141,12 @@ class ScoperExprVisitor(ScoperVisitor):
if
not
a
.
try_assign
(
b
):
if
not
a
.
try_assign
(
b
):
raise
TypeMismatchError
(
a
,
b
,
TypeMismatchKind
.
DIFFERENT_TYPE
)
raise
TypeMismatchError
(
a
,
b
,
TypeMismatchKind
.
DIFFERENT_TYPE
)
return
ftype
.
return_type
if
not
ftype
.
is_native
:
from
transpiler.phases.typing.block
import
ScoperBlockVisitor
vis
=
ScoperBlockVisitor
(
ftype
.
block_data
.
scope
)
for
stmt
in
ftype
.
block_data
.
node
.
body
:
vis
.
visit
(
stmt
)
return
ftype
.
return_type
.
resolve
()
# if isinstance(ftype, TypeType):# and isinstance(ftype.type_object, UserType):
# if isinstance(ftype, TypeType):# and isinstance(ftype.type_object, UserType):
# init: FunctionType = self.visit_getattr(ftype, "__init__").remove_self()
# init: FunctionType = self.visit_getattr(ftype, "__init__").remove_self()
# init.return_type = ftype.type_object
# init.return_type = ftype.type_object
...
@@ -176,6 +181,10 @@ class ScoperExprVisitor(ScoperVisitor):
...
@@ -176,6 +181,10 @@ class ScoperExprVisitor(ScoperVisitor):
node
.
body
.
decls
=
decls
node
.
body
.
decls
=
decls
return
ftype
return
ftype
def
visit_BinOp
(
self
,
node
:
ast
.
BinOp
)
->
BaseType
:
left
,
right
=
map
(
self
.
visit
,
(
node
.
left
,
node
.
right
))
return
TypeVariable
()
# TODO
# def visit_BinOp(self, node: ast.BinOp) -> BaseType:
# def visit_BinOp(self, node: ast.BinOp) -> BaseType:
# left, right = map(self.visit, (node.left, node.right))
# left, right = map(self.visit, (node.left, node.right))
# return self.make_dunder([left, right], DUNDER[type(node.op)])
# return self.make_dunder([left, right], DUNDER[type(node.op)])
...
@@ -300,14 +309,15 @@ class ScoperExprVisitor(ScoperVisitor):
...
@@ -300,14 +309,15 @@ class ScoperExprVisitor(ScoperVisitor):
if
len
(
node
.
generators
)
!=
1
:
if
len
(
node
.
generators
)
!=
1
:
raise
NotImplementedError
(
"Multiple generators not handled yet"
)
raise
NotImplementedError
(
"Multiple generators not handled yet"
)
gen
:
ast
.
comprehension
=
node
.
generators
[
0
]
gen
:
ast
.
comprehension
=
node
.
generators
[
0
]
iter_type
=
get_iter
(
self
.
visit
(
gen
.
iter
))
iter_type
=
self
.
get_iter
(
self
.
visit
(
gen
.
iter
))
node
.
input_item_type
=
get_next
(
iter_type
)
node
.
input_item_type
=
self
.
get_next
(
iter_type
)
virt_scope
=
self
.
scope
.
child
(
ScopeKind
.
FUNCTION_INNER
)
virt_scope
=
self
.
scope
.
child
(
ScopeKind
.
FUNCTION_INNER
)
from
transpiler
import
ScoperBlockVisitor
from
transpiler
.phases.typing.block
import
ScoperBlockVisitor
visitor
=
ScoperBlockVisitor
(
virt_scope
)
visitor
=
ScoperBlockVisitor
(
virt_scope
)
visitor
.
visit_assign_target
(
gen
.
target
,
node
.
input_item_type
)
visitor
.
visit_assign_target
(
gen
.
target
,
node
.
input_item_type
)
node
.
item_type
=
visitor
.
expr
().
visit
(
node
.
elt
)
node
.
item_type
=
visitor
.
expr
().
visit
(
node
.
elt
)
for
if_
in
gen
.
ifs
:
#
for if_ in gen.ifs:
visitor
.
expr
().
visit
(
if_
)
#
visitor.expr().visit(if_)
gen
.
ifs_node
=
ast
.
BoolOp
(
ast
.
And
(),
gen
.
ifs
,
**
linenodata
(
node
))
gen
.
ifs_node
=
ast
.
BoolOp
(
ast
.
And
(),
gen
.
ifs
,
**
linenodata
(
node
))
return
TyList
(
node
.
item_type
)
visitor
.
expr
().
visit
(
gen
.
ifs_node
)
\ No newline at end of file
return
TY_LIST
.
instantiate
([
node
.
item_type
])
\ No newline at end of file
typon/trans/transpiler/phases/typing/modules.py
View file @
b738512a
...
@@ -4,7 +4,7 @@ from logging import debug
...
@@ -4,7 +4,7 @@ from logging import debug
from
transpiler.phases.typing
import
PRELUDE
from
transpiler.phases.typing
import
PRELUDE
from
transpiler.phases.typing.scope
import
Scope
,
VarKind
,
VarDecl
,
ScopeKind
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
,
BlockData
class
ModuleType
(
UniqueTypeMixin
,
ResolvedConcreteType
):
class
ModuleType
(
UniqueTypeMixin
,
ResolvedConcreteType
):
...
@@ -21,39 +21,44 @@ def make_module(name: str, scope: Scope) -> ModuleType:
...
@@ -21,39 +21,44 @@ def make_module(name: str, scope: Scope) -> ModuleType:
visited_modules
=
{}
visited_modules
=
{}
def
parse_module
(
mod_name
:
str
,
python_path
:
Path
,
scope
=
None
,
preprocess
=
None
):
def
parse_module
(
mod_name
:
str
,
python_path
:
list
[
Path
],
scope
=
None
,
preprocess
=
None
)
->
ModuleType
:
path
=
python_path
/
mod_name
for
path
in
python_path
:
path
=
path
/
mod_name
if
not
path
.
exists
():
if
not
path
.
exists
():
path
=
path
.
with_suffix
(
".py"
)
path
=
path
.
with_suffix
(
".py"
)
if
not
path
.
exists
():
if
not
path
.
exists
():
path
=
path
.
with_stem
(
mod_name
+
"_"
)
path
=
path
.
with_stem
(
mod_name
+
"_"
)
if
not
path
.
exists
():
if
not
path
.
exists
():
raise
FileNotFoundError
(
f"Could not find
{
path
}
"
)
continue
if
path
.
is_dir
():
break
real_path
=
path
/
"__init__.py"
else
:
else
:
real_path
=
path
raise
FileNotFoundError
(
f"Could not find
{
mod_name
}
"
)
if
path
.
is_dir
():
path
=
path
/
"__init__.py"
if
mod
:
=
visited_modules
.
get
(
real_
path
.
as_posix
()):
if
mod
:
=
visited_modules
.
get
(
path
.
as_posix
()):
return
mod
return
mod
.
type
mod_scope
=
scope
or
PRELUDE
.
child
(
ScopeKind
.
GLOBAL
)
mod_scope
=
scope
or
PRELUDE
.
child
(
ScopeKind
.
GLOBAL
)
if
real_path
.
suffix
==
".py"
:
if
path
.
suffix
!=
".py"
:
from
transpiler.phases.typing.stdlib
import
StdlibVisitor
node
=
ast
.
parse
(
real_path
.
read_text
())
if
preprocess
:
node
=
preprocess
(
node
)
StdlibVisitor
(
python_path
,
mod_scope
).
visit
(
node
)
else
:
raise
NotImplementedError
(
f"Unsupported file type
{
path
.
suffix
}
"
)
raise
NotImplementedError
(
f"Unsupported file type
{
path
.
suffix
}
"
)
from
transpiler.phases.typing.stdlib
import
StdlibVisitor
node
=
ast
.
parse
(
path
.
read_text
())
if
preprocess
:
node
=
preprocess
(
node
)
from
transpiler.transpiler
import
TYPON_STD
StdlibVisitor
(
python_path
,
mod_scope
,
is_native
=
TYPON_STD
in
path
.
parents
).
visit
(
node
)
mod
=
make_module
(
mod_name
,
mod_scope
)
mod
=
make_module
(
mod_name
,
mod_scope
)
visited_modules
[
real_path
.
as_posix
()]
=
VarDecl
(
VarKind
.
LOCAL
,
mod
,
{
k
:
v
.
type
for
k
,
v
in
mod_scope
.
vars
.
items
()})
mod
.
block_data
=
BlockData
(
node
,
mod_scope
)
visited_modules
[
path
.
as_posix
()]
=
VarDecl
(
VarKind
.
LOCAL
,
mod
)
return
mod
return
mod
# def process_module(mod_path: Path, scope):
# def process_module(mod_path: Path, scope):
...
...
typon/trans/transpiler/phases/typing/stdlib.py
View file @
b738512a
...
@@ -75,9 +75,10 @@ def visit_generic_item(
...
@@ -75,9 +75,10 @@ def visit_generic_item(
@
dataclass
@
dataclass
class
StdlibVisitor
(
NodeVisitorSeq
):
class
StdlibVisitor
(
NodeVisitorSeq
):
python_path
:
Path
python_path
:
list
[
Path
]
scope
:
Scope
=
field
(
default_factory
=
lambda
:
PRELUDE
)
scope
:
Scope
=
field
(
default_factory
=
lambda
:
PRELUDE
)
cur_class
:
Optional
[
ResolvedConcreteType
]
=
None
cur_class
:
Optional
[
ResolvedConcreteType
]
=
None
is_native
:
bool
=
False
def
resolve_module_import
(
self
,
name
:
str
):
def
resolve_module_import
(
self
,
name
:
str
):
# tries = [
# tries = [
...
@@ -88,7 +89,7 @@ class StdlibVisitor(NodeVisitorSeq):
...
@@ -88,7 +89,7 @@ class StdlibVisitor(NodeVisitorSeq):
# if path.exists():
# if path.exists():
# return path
# return path
# raise FileNotFoundError(f"Could not find module {name}")
# raise FileNotFoundError(f"Could not find module {name}")
return
parse_module
(
name
,
self
.
python_path
)
return
parse_module
(
name
,
self
.
python_path
,
self
.
scope
.
child
(
ScopeKind
.
GLOBAL
)
)
def
expr
(
self
)
->
ScoperExprVisitor
:
def
expr
(
self
)
->
ScoperExprVisitor
:
return
ScoperExprVisitor
(
self
.
scope
)
return
ScoperExprVisitor
(
self
.
scope
)
...
@@ -122,7 +123,7 @@ class StdlibVisitor(NodeVisitorSeq):
...
@@ -122,7 +123,7 @@ class StdlibVisitor(NodeVisitorSeq):
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
alias
.
module_obj
=
mod
self
.
scope
.
vars
[
alias
.
asname
or
alias
.
name
]
=
mod
self
.
scope
.
vars
[
alias
.
asname
or
alias
.
name
]
=
VarDecl
(
VarKind
.
LOCAL
,
mod
)
def
visit_ClassDef
(
self
,
node
:
ast
.
ClassDef
):
def
visit_ClassDef
(
self
,
node
:
ast
.
ClassDef
):
if
existing
:
=
self
.
scope
.
get
(
node
.
name
):
if
existing
:
=
self
.
scope
.
get
(
node
.
name
):
...
@@ -137,7 +138,7 @@ class StdlibVisitor(NodeVisitorSeq):
...
@@ -137,7 +138,7 @@ class StdlibVisitor(NodeVisitorSeq):
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
)
output
.
block_data
=
BlockData
(
node
,
scope
)
visitor
=
StdlibVisitor
(
self
.
python_path
,
cl_scope
,
output
)
visitor
=
StdlibVisitor
(
self
.
python_path
,
cl_scope
,
output
,
self
.
is_native
)
bases
=
[
self
.
anno
().
visit
(
base
)
for
base
in
node
.
bases
]
bases
=
[
self
.
anno
().
visit
(
base
)
for
base
in
node
.
bases
]
match
bases
:
match
bases
:
case
[]:
case
[]:
...
@@ -163,6 +164,7 @@ class StdlibVisitor(NodeVisitorSeq):
...
@@ -163,6 +164,7 @@ class StdlibVisitor(NodeVisitorSeq):
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
)
output
.
is_variadic
=
args
.
vararg
is
not
None
output
.
is_variadic
=
args
.
vararg
is
not
None
output
.
is_native
=
self
.
is_native
@
dataclass
(
eq
=
False
,
init
=
False
)
@
dataclass
(
eq
=
False
,
init
=
False
)
class
InstanceType
(
CallableInstanceType
):
class
InstanceType
(
CallableInstanceType
):
...
...
typon/trans/transpiler/phases/typing/types.py
View file @
b738512a
...
@@ -78,7 +78,10 @@ class BaseType(ABC):
...
@@ -78,7 +78,10 @@ class BaseType(ABC):
return
(
needle
is
haystack
)
or
haystack
.
contains_internal
(
needle
)
return
(
needle
is
haystack
)
or
haystack
.
contains_internal
(
needle
)
def
try_assign
(
self
,
other
:
"BaseType"
)
->
bool
:
def
try_assign
(
self
,
other
:
"BaseType"
)
->
bool
:
return
self
.
resolve
().
try_assign_internal
(
other
.
resolve
())
target
,
value
=
self
.
resolve
(),
other
.
resolve
()
if
type
(
value
)
==
TypeVariable
:
return
BaseType
.
try_assign_internal
(
target
,
other
)
return
target
.
try_assign_internal
(
other
)
def
try_assign_internal
(
self
,
other
:
"BaseType"
)
->
bool
:
def
try_assign_internal
(
self
,
other
:
"BaseType"
)
->
bool
:
...
@@ -489,6 +492,7 @@ class CallableInstanceType(GenericInstanceType, MethodType):
...
@@ -489,6 +492,7 @@ class CallableInstanceType(GenericInstanceType, MethodType):
return_type
:
ConcreteType
return_type
:
ConcreteType
optional_at
:
int
=
None
optional_at
:
int
=
None
is_variadic
:
bool
=
False
is_variadic
:
bool
=
False
is_native
:
bool
=
False
def
__post_init__
(
self
):
def
__post_init__
(
self
):
if
self
.
optional_at
is
None
and
self
.
parameters
is
not
None
:
if
self
.
optional_at
is
None
and
self
.
parameters
is
not
None
:
...
@@ -560,6 +564,8 @@ def make_builtin_feature(name: str):
...
@@ -560,6 +564,8 @@ def make_builtin_feature(name: str):
return
TY_OPTIONAL
return
TY_OPTIONAL
case
"Union"
:
case
"Union"
:
return
TY_UNION
return
TY_UNION
case
"Callable"
:
return
TY_CALLABLE
case
_
:
case
_
:
class
CreatedType
(
BuiltinFeatureType
):
class
CreatedType
(
BuiltinFeatureType
):
def
name
(
self
):
def
name
(
self
):
...
...
typon/trans/transpiler/transpiler.py
View file @
b738512a
# coding: utf-8
# coding: utf-8
import
ast
from
pathlib
import
Path
from
pathlib
import
Path
import
colorama
import
colorama
...
@@ -14,14 +15,16 @@ from transpiler.phases.emit_cpp.module import emit_module
...
@@ -14,14 +15,16 @@ from transpiler.phases.emit_cpp.module import emit_module
from
transpiler.phases.if_main
import
IfMainVisitor
from
transpiler.phases.if_main
import
IfMainVisitor
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
TYPON_STD
=
Path
(
__file__
).
parent
.
parent
/
"stdlib"
def
init
():
def
init
():
error_display
.
init
()
error_display
.
init
()
colorama
.
init
()
colorama
.
init
()
typon_std
=
Path
(
__file__
).
parent
.
parent
/
"stdlib"
#discover_module(typon_std, PRELUDE.child(ScopeKind.GLOBAL))
#discover_module(typon_std, PRELUDE.child(ScopeKind.GLOBAL))
parse_module
(
"builtins"
,
typon_std
,
PRELUDE
)
parse_module
(
"builtins"
,
[
TYPON_STD
]
,
PRELUDE
)
...
@@ -35,7 +38,7 @@ def transpile(source, name: str, path: Path):
...
@@ -35,7 +38,7 @@ def transpile(source, name: str, path: Path):
node
=
DesugarOp
().
visit
(
node
)
node
=
DesugarOp
().
visit
(
node
)
return
node
return
node
module
=
parse_module
(
path
.
stem
,
path
.
parent
,
preprocess
=
preprocess
)
module
=
parse_module
(
path
.
stem
,
[
path
.
parent
,
TYPON_STD
]
,
preprocess
=
preprocess
)
def
disp_scope
(
scope
,
indent
=
0
):
def
disp_scope
(
scope
,
indent
=
0
):
debug
(
" "
*
indent
,
scope
.
kind
)
debug
(
" "
*
indent
,
scope
.
kind
)
...
@@ -44,6 +47,8 @@ def transpile(source, name: str, path: Path):
...
@@ -44,6 +47,8 @@ def transpile(source, name: str, path: Path):
for
var
in
scope
.
vars
.
items
():
for
var
in
scope
.
vars
.
items
():
debug
(
" "
*
(
indent
+
1
),
var
)
debug
(
" "
*
(
indent
+
1
),
var
)
StdlibVisitor
([],
module
.
block_data
.
scope
).
expr
().
visit
(
ast
.
parse
(
"main()"
,
mode
=
"eval"
).
body
)
def
main_module
():
def
main_module
():
yield
from
emit_module
(
module
)
yield
from
emit_module
(
module
)
yield
"#ifdef TYPON_EXTENSION"
yield
"#ifdef TYPON_EXTENSION"
...
...
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