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
f8de89ac
Commit
f8de89ac
authored
Feb 04, 2024
by
Tom Niget
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add new generics work
parent
fd777ef8
Changes
22
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
22 changed files
with
2202 additions
and
652 deletions
+2202
-652
.gitignore
.gitignore
+2
-1
typon/trans/stdlib/socket_.py
typon/trans/stdlib/socket_.py
+1
-1
typon/trans/tests/user_generics.py
typon/trans/tests/user_generics.py
+2
-4
typon/trans/transpiler/__init__.py
typon/trans/transpiler/__init__.py
+2
-1
typon/trans/transpiler/phases/typing/__init__.py
typon/trans/transpiler/phases/typing/__init__.py
+31
-38
typon/trans/transpiler/phases/typing/annotations.py
typon/trans/transpiler/phases/typing/annotations.py
+18
-29
typon/trans/transpiler/phases/typing/common.py
typon/trans/transpiler/phases/typing/common.py
+2
-4
typon/trans/transpiler/phases/typing/exceptions.py
typon/trans/transpiler/phases/typing/exceptions.py
+17
-0
typon/trans/transpiler/phases/typing/expr.py
typon/trans/transpiler/phases/typing/expr.py
+1
-3
typon/trans/transpiler/phases/typing/stdlib.py
typon/trans/transpiler/phases/typing/stdlib.py
+97
-66
typon/trans/transpiler/phases/typing/types.py
typon/trans/transpiler/phases/typing/types.py
+183
-504
typon/trans/transpiler/phases/typing2/__init__.py
typon/trans/transpiler/phases/typing2/__init__.py
+78
-0
typon/trans/transpiler/phases/typing2/annotations.py
typon/trans/transpiler/phases/typing2/annotations.py
+56
-0
typon/trans/transpiler/phases/typing2/block.py
typon/trans/transpiler/phases/typing2/block.py
+426
-0
typon/trans/transpiler/phases/typing2/class_.py
typon/trans/transpiler/phases/typing2/class_.py
+36
-0
typon/trans/transpiler/phases/typing2/common.py
typon/trans/transpiler/phases/typing2/common.py
+126
-0
typon/trans/transpiler/phases/typing2/exceptions.py
typon/trans/transpiler/phases/typing2/exceptions.py
+322
-0
typon/trans/transpiler/phases/typing2/expr.py
typon/trans/transpiler/phases/typing2/expr.py
+300
-0
typon/trans/transpiler/phases/typing2/scope.py
typon/trans/transpiler/phases/typing2/scope.py
+95
-0
typon/trans/transpiler/phases/typing2/stdlib.py
typon/trans/transpiler/phases/typing2/stdlib.py
+149
-0
typon/trans/transpiler/phases/typing2/types.py
typon/trans/transpiler/phases/typing2/types.py
+257
-0
typon/trans/transpiler/utils.py
typon/trans/transpiler/utils.py
+1
-1
No files found.
.gitignore
View file @
f8de89ac
.idea
cmake-build-*
typon.egg-info
\ No newline at end of file
typon/trans/stdlib/socket_.py
View file @
f8de89ac
...
...
@@ -36,7 +36,7 @@ class socket:
pass
def
getaddrinfo
(
host
:
str
,
port
:
int
,
family
:
int
=
0
,
type
:
int
=
0
,
proto
:
int
=
0
,
flags
:
int
=
0
)
->
\
Task
[
list
[
tuple
[
int
,
int
,
int
,
str
,
tuple
[
str
,
int
]
|
str
]]]:
Task
[
list
[
tuple
[
int
,
int
,
int
,
str
,
str
]]]:
# todo: incomplete return type
pass
AF_UNIX
:
int
\ No newline at end of file
typon/trans/tests/user_generics.py
View file @
f8de89ac
# coding: utf-8
from
typing
import
TypeVar
,
Generic
from
dataclasses
import
dataclass
T
=
TypeVar
(
"T"
)
@
dataclass
class
Thing
(
Generic
[
T
])
:
class
Thing
[
T
]
:
x
:
T
def
f
(
x
:
T
):
def
f
[
T
]
(
x
:
T
):
pass
...
...
typon/trans/transpiler/__init__.py
View file @
f8de89ac
...
...
@@ -196,7 +196,8 @@ def transpile(source, name: str, path=None):
for
var
in
scope
.
vars
.
items
():
debug
(
" "
*
(
indent
+
1
),
var
)
# disp_scope(res.scope)
disp_scope
(
res
.
scope
)
exit
()
assert
isinstance
(
res
,
ast
.
Module
)
res
.
name
=
"__main__"
...
...
typon/trans/transpiler/phases/typing/__init__.py
View file @
f8de89ac
...
...
@@ -3,48 +3,41 @@ from pathlib import Path
from
logging
import
debug
from
transpiler.phases.typing.scope
import
VarKind
,
VarDecl
,
ScopeKind
,
Scope
from
transpiler.phases.typing.stdlib
import
PRELUDE
,
StdlibVisitor
from
transpiler.phases.typing.types
import
TY_TYPE
,
TY_INT
,
TY_STR
,
TY_BOOL
,
TY_COMPLEX
,
TY_NONE
,
FunctionType
,
\
TypeVariable
,
CppType
,
PyList
,
TypeType
,
Forked
,
Task
,
Future
,
PyIterator
,
TupleType
,
TypeOperator
,
BaseType
,
\
ModuleType
,
TY_BYTES
,
TY_FLOAT
,
PyDict
,
TY_SLICE
,
TY_OBJECT
,
BuiltinFeature
,
UnionType
,
MemberDef
from
transpiler.phases.typing.types
import
TY_TYPE
,
TY_INT
,
TY_STR
,
TY_BOOL
,
TY_COMPLEX
,
TY_NONE
,
ResolvedConcreteType
,
\
MemberDef
PRELUDE
.
vars
.
update
({
# "int": VarDecl(VarKind.LOCAL, TY_TYPE, TY_INT),
# "str": VarDecl(VarKind.LOCAL, TY_TYPE, TY_STR),
# "bool": VarDecl(VarKind.LOCAL, TY_TYPE, TY_BOOL),
# "complex": VarDecl(VarKind.LOCAL, TY_TYPE, TY_COMPLEX),
# "None": VarDecl(VarKind.LOCAL, TY_NONE, None),
# "Callable": VarDecl(VarKind.LOCAL, TY_TYPE, FunctionType),
# "TypeVar": VarDecl(VarKind.LOCAL, TY_TYPE, TypeVariable),
# "CppType": VarDecl(VarKind.LOCAL, TY_TYPE, CppType),
# "list": VarDecl(VarKind.LOCAL, TY_TYPE, PyList),
"int"
:
VarDecl
(
VarKind
.
LOCAL
,
TypeType
(
TY_INT
)),
"float"
:
VarDecl
(
VarKind
.
LOCAL
,
TypeType
(
TY_FLOAT
)),
"str"
:
VarDecl
(
VarKind
.
LOCAL
,
TypeType
(
TY_STR
)),
"bytes"
:
VarDecl
(
VarKind
.
LOCAL
,
TypeType
(
TY_BYTES
)),
"bool"
:
VarDecl
(
VarKind
.
LOCAL
,
TypeType
(
TY_BOOL
)),
"complex"
:
VarDecl
(
VarKind
.
LOCAL
,
TypeType
(
TY_COMPLEX
)),
"None"
:
VarDecl
(
VarKind
.
LOCAL
,
TypeType
(
TY_NONE
)),
"Callable"
:
VarDecl
(
VarKind
.
LOCAL
,
TypeType
(
FunctionType
)),
#"TypeVar": VarDecl(VarKind.LOCAL, TypeType(TypeVariable)),
"CppType"
:
VarDecl
(
VarKind
.
LOCAL
,
TypeType
(
CppType
)),
"list"
:
VarDecl
(
VarKind
.
LOCAL
,
TypeType
(
PyList
)),
"dict"
:
VarDecl
(
VarKind
.
LOCAL
,
TypeType
(
PyDict
)),
"Forked"
:
VarDecl
(
VarKind
.
LOCAL
,
TypeType
(
Forked
)),
"Task"
:
VarDecl
(
VarKind
.
LOCAL
,
TypeType
(
Task
)),
"Future"
:
VarDecl
(
VarKind
.
LOCAL
,
TypeType
(
Future
)),
"Iterator"
:
VarDecl
(
VarKind
.
LOCAL
,
TypeType
(
PyIterator
)),
"tuple"
:
VarDecl
(
VarKind
.
LOCAL
,
TypeType
(
TupleType
)),
"slice"
:
VarDecl
(
VarKind
.
LOCAL
,
TypeType
(
TY_SLICE
)),
"object"
:
VarDecl
(
VarKind
.
LOCAL
,
TypeType
(
TY_OBJECT
)),
"BuiltinFeature"
:
VarDecl
(
VarKind
.
LOCAL
,
TypeType
(
BuiltinFeature
)),
"Any"
:
VarDecl
(
VarKind
.
LOCAL
,
TypeType
(
TY_OBJECT
)),
"Optional"
:
VarDecl
(
VarKind
.
LOCAL
,
TypeType
(
lambda
x
:
UnionType
(
x
,
TY_NONE
))),
})
# PRELUDE.vars.update({
# "int": VarDecl(VarKind.LOCAL, TypeType(TY_INT)),
# "float": VarDecl(VarKind.LOCAL, TypeType(TY_FLOAT)),
# "str": VarDecl(VarKind.LOCAL, TypeType(TY_STR)),
# "bytes": VarDecl(VarKind.LOCAL, TypeType(TY_BYTES)),
# "bool": VarDecl(VarKind.LOCAL, TypeType(TY_BOOL)),
# "complex": VarDecl(VarKind.LOCAL, TypeType(TY_COMPLEX)),
# "None": VarDecl(VarKind.LOCAL, TypeType(TY_NONE)),
# "Callable": VarDecl(VarKind.LOCAL, TypeType(FunctionType)),
# #"TypeVar": VarDecl(VarKind.LOCAL, TypeType(TypeVariable)),
# "CppType": VarDecl(VarKind.LOCAL, TypeType(CppType)),
# "list": VarDecl(VarKind.LOCAL, TypeType(PyList)),
# "dict": VarDecl(VarKind.LOCAL, TypeType(PyDict)),
# "Forked": VarDecl(VarKind.LOCAL, TypeType(Forked)),
# "Task": VarDecl(VarKind.LOCAL, TypeType(Task)),
# "Future": VarDecl(VarKind.LOCAL, TypeType(Future)),
# "Iterator": VarDecl(VarKind.LOCAL, TypeType(PyIterator)),
# "tuple": VarDecl(VarKind.LOCAL, TypeType(TupleType)),
# "slice": VarDecl(VarKind.LOCAL, TypeType(TY_SLICE)),
# "object": VarDecl(VarKind.LOCAL, TypeType(TY_OBJECT)),
# "BuiltinFeature": VarDecl(VarKind.LOCAL, TypeType(BuiltinFeature)),
# "Any": VarDecl(VarKind.LOCAL, TypeType(TY_OBJECT)),
# "Optional": VarDecl(VarKind.LOCAL, TypeType(lambda x: UnionType(x, TY_NONE))),
# })
typon_std
=
Path
(
__file__
).
parent
.
parent
.
parent
.
parent
/
"stdlib"
def
make_module
(
name
:
str
,
scope
:
Scope
)
->
BaseType
:
ty
=
ModuleType
([],
f"
{
name
}
"
)
def
make_module
(
name
:
str
,
scope
:
Scope
)
->
ResolvedConcreteType
:
class
CreatedType
(
ResolvedConcreteType
):
def
__str__
(
self
):
return
name
ty
=
CreatedType
()
for
n
,
v
in
scope
.
vars
.
items
():
ty
.
fields
[
n
]
=
MemberDef
(
v
.
type
,
v
.
val
,
False
)
return
ty
...
...
typon/trans/transpiler/phases/typing/annotations.py
View file @
f8de89ac
...
...
@@ -4,33 +4,20 @@ from dataclasses import dataclass, field
from
typing
import
Optional
,
List
from
transpiler.phases.typing.scope
import
Scope
from
transpiler.phases.typing.types
import
BaseType
,
TY_NONE
,
Type
Type
,
TY_SELF
,
TypeVariable
,
Union
Type
from
transpiler.phases.typing.types
import
BaseType
,
TY_NONE
,
Type
Variable
,
TY_TYPE
,
ResolvedConcreteType
,
TypeList
Type
from
transpiler.phases.utils
import
NodeVisitorSeq
@
dataclass
class
TypeAnnotationVisitor
(
NodeVisitorSeq
):
scope
:
Scope
cur_class
:
Optional
[
TypeType
]
=
None
typevars
:
List
[
TypeVariable
]
=
field
(
default_factory
=
list
)
def
visit_str
(
self
,
node
:
str
)
->
BaseType
:
if
node
in
(
"Self"
,
"self"
)
and
self
.
cur_class
:
if
isinstance
(
self
.
cur_class
.
type_object
,
abc
.
ABCMeta
)
or
self
.
cur_class
.
type_object
.
is_protocol_gen
or
self
.
cur_class
.
type_object
.
is_protocol
:
return
TY_SELF
else
:
return
self
.
cur_class
.
type_object
if
existing
:
=
self
.
scope
.
get
(
node
):
ty
=
existing
.
type
if
isinstance
(
ty
,
TypeType
)
and
isinstance
(
ty
.
type_object
,
TypeVariable
):
if
existing
is
not
self
.
scope
.
vars
.
get
(
node
,
None
):
# Type variable from outer scope, so we copy it
ty
=
TypeVariable
(
ty
.
type_object
.
name
)
self
.
scope
.
declare_local
(
node
,
TypeType
(
ty
))
# todo: unneeded?
self
.
typevars
.
append
(
ty
)
if
isinstance
(
ty
,
TypeType
):
return
ty
.
type_object
return
ty
assert
isinstance
(
ty
,
ResolvedConcreteType
)
assert
ty
.
inherits
(
TY_TYPE
)
return
ty
.
inner_type
from
transpiler.phases.typing.exceptions
import
UnknownNameError
raise
UnknownNameError
(
node
)
...
...
@@ -46,22 +33,24 @@ class TypeAnnotationVisitor(NodeVisitorSeq):
raise
NotImplementedError
def
visit_Subscript
(
self
,
node
:
ast
.
Subscript
)
->
BaseType
:
ty_op
=
self
.
visit
(
node
.
value
)
args
=
list
(
node
.
slice
.
elts
)
if
type
(
node
.
slice
)
==
ast
.
Tuple
else
[
node
.
slice
]
args
=
[
self
.
visit
(
arg
)
for
arg
in
args
]
return
ty_op
(
*
args
)
# ty_op = self.visit(node.value)
# args = list(node.slice.elts) if type(node.slice) == ast.Tuple else [node.slice]
# args = [self.visit(arg) for arg in args]
# return ty_op(*args)
raise
NotImplementedError
()
# return TypeOperator([self.visit(node.value)], self.visit(node.slice.value))
def
visit_List
(
self
,
node
:
ast
.
List
)
->
List
[
BaseType
]
:
return
[
self
.
visit
(
elt
)
for
elt
in
node
.
elts
]
def
visit_List
(
self
,
node
:
ast
.
List
)
->
BaseType
:
return
TypeListType
([
self
.
visit
(
elt
)
for
elt
in
node
.
elts
])
def
visit_Attribute
(
self
,
node
:
ast
.
Attribute
)
->
BaseType
:
left
=
self
.
visit
(
node
.
value
)
res
=
left
.
fields
[
node
.
attr
].
type
assert
isinstance
(
res
,
TypeType
)
return
res
.
type_object
raise
NotImplementedError
()
# left = self.visit(node.value)
# res = left.fields[node.attr].type
# assert isinstance(res, TypeType)
# return res.type_object
def
visit_BinOp
(
self
,
node
:
ast
.
BinOp
)
->
BaseType
:
if
isinstance
(
node
.
op
,
ast
.
BitOr
):
return
UnionType
(
self
.
visit
(
node
.
left
),
self
.
visit
(
node
.
right
))
#
if isinstance(node.op, ast.BitOr):
#
return UnionType(self.visit(node.left), self.visit(node.right))
raise
NotImplementedError
(
node
.
op
)
typon/trans/transpiler/phases/typing/common.py
View file @
f8de89ac
...
...
@@ -5,8 +5,7 @@ from typing import Dict, Optional
from
transpiler.utils
import
highlight
from
transpiler.phases.typing.annotations
import
TypeAnnotationVisitor
from
transpiler.phases.typing.scope
import
Scope
,
ScopeKind
,
VarDecl
,
VarKind
from
transpiler.phases.typing.types
import
BaseType
,
TypeVariable
,
TY_NONE
,
TypeType
,
BuiltinFeature
,
FunctionType
,
\
Promise
,
PromiseKind
from
transpiler.phases.typing.types
import
BaseType
,
TypeVariable
,
TY_NONE
from
transpiler.phases.utils
import
NodeVisitorSeq
,
AnnotationName
PRELUDE
=
Scope
.
make_global
()
...
...
@@ -15,14 +14,13 @@ PRELUDE = Scope.make_global()
class
ScoperVisitor
(
NodeVisitorSeq
):
scope
:
Scope
=
field
(
default_factory
=
lambda
:
PRELUDE
.
child
(
ScopeKind
.
GLOBAL
))
root_decls
:
Dict
[
str
,
VarDecl
]
=
field
(
default_factory
=
dict
)
cur_class
:
Optional
[
TypeType
]
=
None
def
expr
(
self
)
->
"ScoperExprVisitor"
:
from
transpiler.phases.typing.expr
import
ScoperExprVisitor
return
ScoperExprVisitor
(
self
.
scope
,
self
.
root_decls
)
def
anno
(
self
)
->
"TypeAnnotationVisitor"
:
return
TypeAnnotationVisitor
(
self
.
scope
,
self
.
cur_class
)
return
TypeAnnotationVisitor
(
self
.
scope
)
def
visit_annotation
(
self
,
expr
:
Optional
[
ast
.
expr
])
->
BaseType
:
res
=
self
.
anno
().
visit
(
expr
)
if
expr
else
TypeVariable
()
...
...
typon/trans/transpiler/phases/typing/exceptions.py
View file @
f8de89ac
...
...
@@ -303,3 +303,20 @@ class MissingReturnError(CompileError):
{
highlight
(
' return 1'
)
}
{
highlight
(
' # if x <= 0, the function returns nothing'
)
}
"""
@
dataclass
class
InconsistentMroError
(
CompileError
):
bases
:
list
[
BaseType
]
def
__str__
(
self
)
->
str
:
return
f"Cannot create a cnossitent method resolution order (MRO) for bases
{
'
\
n
'
.
join
(
map
(
highlight
,
self
.
bases
))
}
"
def
detail
(
self
,
last_node
:
ast
.
AST
=
None
)
->
str
:
return
f"""
This indicates that a class has an inconsistent method resolution order (MRO).
For example:
{
highlight
(
'class A: pass'
)
}
{
highlight
(
'class B(A): pass'
)
}
{
highlight
(
'class C(B, A): pass'
)
}
"""
\ No newline at end of file
typon/trans/transpiler/phases/typing/expr.py
View file @
f8de89ac
...
...
@@ -5,9 +5,7 @@ from typing import List
from
transpiler.phases.typing
import
ScopeKind
,
VarDecl
,
VarKind
from
transpiler.phases.typing.common
import
ScoperVisitor
,
get_iter
,
get_next
,
is_builtin
from
transpiler.phases.typing.types
import
BaseType
,
TupleType
,
TY_STR
,
TY_BOOL
,
TY_INT
,
\
TY_COMPLEX
,
TY_NONE
,
FunctionType
,
PyList
,
TypeVariable
,
PySet
,
TypeType
,
PyDict
,
Promise
,
PromiseKind
,
UserType
,
\
TY_SLICE
,
TY_FLOAT
,
RuntimeValue
,
BuiltinFeature
from
transpiler.phases.typing.types
import
BaseType
from
transpiler.utils
import
linenodata
DUNDER
=
{
...
...
typon/trans/transpiler/phases/typing/stdlib.py
View file @
f8de89ac
...
...
@@ -2,16 +2,67 @@ import ast
import
dataclasses
from
abc
import
ABCMeta
from
dataclasses
import
dataclass
,
field
from
typing
import
Optional
,
List
,
Dict
from
typing
import
Optional
,
List
,
Dict
,
Callable
from
logging
import
debug
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.scope
import
Scope
,
VarDecl
,
VarKind
,
ScopeKind
from
transpiler.phases.typing.types
import
BaseType
,
TypeOperator
,
FunctionType
,
TY_VARARG
,
TypeType
,
TypeVariable
,
\
MemberDef
,
BuiltinFeature
from
transpiler.phases.typing.types
import
BaseType
,
BuiltinGenericType
,
BuiltinType
,
create_builtin_generic_type
,
\
create_builtin_type
,
ConcreteType
,
GenericInstanceType
,
TypeListType
,
TypeTupleType
,
GenericParameter
,
\
GenericParameterKind
,
TypeVariable
from
transpiler.phases.utils
import
NodeVisitorSeq
def
visit_generic_item
(
visit_nongeneric
:
Callable
[[
Scope
,
ConcreteType
],
None
],
node
,
output_type
:
BuiltinGenericType
,
scope
:
Scope
,
instance_type
=
None
):
if
node
.
type_params
:
output_type
.
parameters
=
[]
for
param
in
node
.
type_params
:
match
param
:
case
ast
.
TypeVar
(
_
,
_
):
kind
=
GenericParameterKind
.
NORMAL
case
ast
.
ParamSpec
(
_
):
kind
=
GenericParameterKind
.
PARAMETERS
case
ast
.
TypeVarTuple
(
_
):
kind
=
GenericParameterKind
.
TUPLE
output_type
.
parameters
.
append
(
GenericParameter
(
param
.
name
,
kind
))
if
instance_type
is
None
:
class
instance_type
(
GenericInstanceType
):
pass
instance_type
.
__name__
=
f"GenericInstance$
{
node
.
name
}
"
def
instantiate
(
args
:
list
[
ConcreteType
])
->
GenericInstanceType
:
new_scope
=
scope
.
child
(
ScopeKind
.
GLOBAL
)
args_iter
=
iter
(
args
)
constraints
=
[]
anno
=
TypeAnnotationVisitor
(
new_scope
)
for
param
in
node
.
type_params
:
op_val
=
next
(
args_iter
,
None
)
if
op_val
is
None
:
op_val
=
TypeVariable
()
match
param
:
case
ast
.
TypeVar
(
name
,
bound
):
new_scope
.
declare_local
(
name
,
op_val
)
if
bound
is
not
None
:
constraints
.
append
((
op_val
,
anno
.
visit
(
bound
)))
case
ast
.
ParamSpec
(
name
):
assert
isinstance
(
op_val
,
TypeListType
)
new_scope
.
declare_local
(
name
,
op_val
)
case
ast
.
TypeVarTuple
(
name
):
new_scope
.
declare_local
(
name
,
TypeTupleType
(
list
(
args_iter
)))
for
a
,
b
in
constraints
:
raise
NotImplementedError
()
new_output_type
=
instance_type
()
visit_nongeneric
(
new_scope
,
new_output_type
)
return
new_output_type
output_type
.
instantiate_
=
instantiate
else
:
visit_nongeneric
(
scope
,
output_type
)
@
dataclass
...
...
@@ -34,9 +85,6 @@ class StdlibVisitor(NodeVisitorSeq):
ty
=
self
.
anno
().
visit
(
node
.
annotation
)
if
self
.
cur_class
:
assert
isinstance
(
self
.
cur_class
,
TypeType
)
if
isinstance
(
self
.
cur_class
.
type_object
,
ABCMeta
):
raise
NotImplementedError
else
:
self
.
cur_class
.
type_object
.
fields
[
node
.
target
.
id
]
=
MemberDef
(
ty
.
gen_sub
(
self
.
cur_class
.
type_object
,
self
.
typevars
))
self
.
scope
.
vars
[
node
.
target
.
id
]
=
VarDecl
(
VarKind
.
LOCAL
,
ty
)
...
...
@@ -48,71 +96,54 @@ class StdlibVisitor(NodeVisitorSeq):
def
visit_ClassDef
(
self
,
node
:
ast
.
ClassDef
):
if
existing
:
=
self
.
scope
.
get
(
node
.
name
):
ty
=
existing
.
type
else
:
class
BuiltinClassType
(
TypeOperator
):
def
__init__
(
self
,
*
args
):
super
().
__init__
(
args
,
node
.
name
,
is_reference
=
True
)
ty
=
TypeType
(
BuiltinClassType
)
self
.
scope
.
vars
[
node
.
name
]
=
VarDecl
(
VarKind
.
LOCAL
,
ty
)
typevars
=
[]
for
b
in
node
.
bases
:
if
isinstance
(
b
,
ast
.
Subscript
):
if
isinstance
(
b
.
slice
,
ast
.
Name
):
sliceval
=
[
b
.
slice
.
id
]
elif
isinstance
(
b
.
slice
,
ast
.
Tuple
):
sliceval
=
[
n
.
id
for
n
in
b
.
slice
.
elts
]
if
isinstance
(
b
.
value
,
ast
.
Name
)
and
b
.
value
.
id
==
"Generic"
:
typevars
=
sliceval
elif
isinstance
(
b
.
value
,
ast
.
Name
)
and
b
.
value
.
id
==
"Protocol"
:
typevars
=
sliceval
ty
.
type_object
.
is_protocol_gen
=
True
NewType
=
existing
.
type
else
:
idxs
=
[
typevars
.
index
(
v
)
for
v
in
sliceval
]
parent
=
self
.
visit
(
b
.
value
)
assert
isinstance
(
parent
,
TypeType
)
assert
isinstance
(
ty
.
type_object
,
ABCMeta
)
ty
.
type_object
.
gen_parents
.
append
(
lambda
selfvars
:
parent
.
type_object
(
*
[
selfvars
[
i
]
for
i
in
idxs
]))
else
:
if
isinstance
(
b
,
ast
.
Name
)
and
b
.
id
==
"Protocol"
:
ty
.
type_object
.
is_protocol_gen
=
True
else
:
parent
=
self
.
visit
(
b
)
assert
isinstance
(
parent
,
TypeType
)
if
isinstance
(
ty
.
type_object
,
ABCMeta
):
ty
.
type_object
.
gen_parents
.
append
(
parent
.
type_object
)
else
:
ty
.
type_object
.
parents
.
append
(
parent
.
type_object
)
if
not
typevars
and
not
existing
:
ty
.
type_object
=
ty
.
type_object
()
cl_scope
=
self
.
scope
.
child
(
ScopeKind
.
CLASS
)
visitor
=
StdlibVisitor
(
cl_scope
,
ty
)
for
var
in
typevars
:
visitor
.
typevars
[
var
]
=
TypeType
(
TypeVariable
(
var
))
base_class
=
create_builtin_generic_type
if
node
.
type_params
else
create_builtin_type
NewType
=
base_class
(
node
.
name
)
self
.
scope
.
vars
[
node
.
name
]
=
VarDecl
(
VarKind
.
LOCAL
,
NewType
.
type_type
())
def
visit_nongeneric
(
scope
,
output
:
ConcreteType
):
cl_scope
=
scope
.
child
(
ScopeKind
.
CLASS
)
visitor
=
StdlibVisitor
(
cl_scope
,
output
)
for
stmt
in
node
.
body
:
visitor
.
visit
(
stmt
)
visit_generic_item
(
visit_nongeneric
,
node
,
NewType
,
self
.
scope
)
def
visit_Pass
(
self
,
node
:
ast
.
Pass
):
pass
def
visit_FunctionDef
(
self
,
node
:
ast
.
FunctionDef
):
tc
=
node
.
type_comment
# todo : lire les commetnaries de type pour les fonctions génériques sinon trouver autre chose
arg_visitor
=
TypeAnnotationVisitor
(
self
.
scope
.
child
(
ScopeKind
.
FUNCTION
),
self
.
cur_class
)
arg_types
=
[
arg_visitor
.
visit
(
arg
.
annotation
or
arg
.
arg
)
for
arg
in
node
.
args
.
args
]
ret_type
=
arg_visitor
.
visit
(
node
.
returns
)
ty
=
FunctionType
(
arg_types
,
ret_type
)
ty
.
typevars
=
arg_visitor
.
typevars
if
node
.
args
.
vararg
:
ty
.
variadic
=
True
ty
.
optional_at
=
1
+
len
(
node
.
args
.
args
)
-
len
(
node
.
args
.
defaults
)
if
self
.
cur_class
:
ty
.
is_method
=
True
assert
isinstance
(
self
.
cur_class
,
TypeType
)
if
isinstance
(
self
.
cur_class
.
type_object
,
ABCMeta
):
self
.
cur_class
.
type_object
.
gen_methods
[
node
.
name
]
=
lambda
t
:
ty
.
gen_sub
(
t
,
self
.
typevars
)
else
:
self
.
cur_class
.
type_object
.
fields
[
node
.
name
]
=
MemberDef
(
ty
.
gen_sub
(
self
.
cur_class
.
type_object
,
self
.
typevars
),
())
self
.
scope
.
vars
[
node
.
name
]
=
VarDecl
(
VarKind
.
LOCAL
,
ty
)
def
visit_nongeneric
(
scope
,
output
:
ConcreteType
):
cl_scope
=
scope
.
child
(
ScopeKind
.
CLASS
)
visitor
=
StdlibVisitor
(
cl_scope
,
output
)
for
stmt
in
node
.
body
:
visitor
.
visit
(
stmt
)
'''
class arguments(__ast.AST):
""" arguments(arg* posonlyargs, arg* args, arg? vararg, arg* kwonlyargs, expr* kw_defaults, arg? kwarg, expr* defaults) """'''
visit_generic_item
(
visit_nongeneric
,
node
,
NewType
,
self
.
scope
)
# tc = node.type_comment # todo : lire les commetnaries de type pour les fonctions génériques sinon trouver autre chose
# arg_visitor = TypeAnnotationVisitor(self.scope.child(ScopeKind.FUNCTION), self.cur_class)
# arg_types = [arg_visitor.visit(arg.annotation or arg.arg) for arg in node.args.args]
# ret_type = arg_visitor.visit(node.returns)
# ty = FunctionType(arg_types, ret_type)
# ty.typevars = arg_visitor.typevars
# if node.args.vararg:
# ty.variadic = True
# ty.optional_at = 1 + len(node.args.args) - len(node.args.defaults)
# if self.cur_class:
# ty.is_method = True
# assert isinstance(self.cur_class, TypeType)
# if isinstance(self.cur_class.type_object, ABCMeta):
# self.cur_class.type_object.gen_methods[node.name] = lambda t: ty.gen_sub(t, self.typevars)
# else:
# self.cur_class.type_object.fields[node.name] = MemberDef(ty.gen_sub(self.cur_class.type_object, self.typevars), ())
# self.scope.vars[node.name] = VarDecl(VarKind.LOCAL, ty)
def
visit_Assert
(
self
,
node
:
ast
.
Assert
):
if
isinstance
(
node
.
test
,
ast
.
UnaryOp
)
and
isinstance
(
node
.
test
.
op
,
ast
.
Not
):
...
...
typon/trans/transpiler/phases/typing/types.py
View file @
f8de89ac
This diff is collapsed.
Click to expand it.
typon/trans/transpiler/phases/typing2/__init__.py
0 → 100644
View file @
f8de89ac
import
ast
from
pathlib
import
Path
from
logging
import
debug
from
transpiler.phases.typing.scope
import
VarKind
,
VarDecl
,
ScopeKind
,
Scope
from
transpiler.phases.typing.stdlib
import
PRELUDE
,
StdlibVisitor
from
transpiler.phases.typing.types
import
TY_TYPE
,
TY_INT
,
TY_STR
,
TY_BOOL
,
TY_COMPLEX
,
TY_NONE
,
FunctionType
,
\
TypeVariable
,
CppType
,
PyList
,
TypeType
,
Forked
,
Task
,
Future
,
PyIterator
,
TupleType
,
TypeOperator
,
BaseType
,
\
ModuleType
,
TY_BYTES
,
TY_FLOAT
,
PyDict
,
TY_SLICE
,
TY_OBJECT
,
BuiltinFeature
,
UnionType
,
MemberDef
PRELUDE
.
vars
.
update
({
# "int": VarDecl(VarKind.LOCAL, TY_TYPE, TY_INT),
# "str": VarDecl(VarKind.LOCAL, TY_TYPE, TY_STR),
# "bool": VarDecl(VarKind.LOCAL, TY_TYPE, TY_BOOL),
# "complex": VarDecl(VarKind.LOCAL, TY_TYPE, TY_COMPLEX),
# "None": VarDecl(VarKind.LOCAL, TY_NONE, None),
# "Callable": VarDecl(VarKind.LOCAL, TY_TYPE, FunctionType),
# "TypeVar": VarDecl(VarKind.LOCAL, TY_TYPE, TypeVariable),
# "CppType": VarDecl(VarKind.LOCAL, TY_TYPE, CppType),
# "list": VarDecl(VarKind.LOCAL, TY_TYPE, PyList),
"int"
:
VarDecl
(
VarKind
.
LOCAL
,
TypeType
(
TY_INT
)),
"float"
:
VarDecl
(
VarKind
.
LOCAL
,
TypeType
(
TY_FLOAT
)),
"str"
:
VarDecl
(
VarKind
.
LOCAL
,
TypeType
(
TY_STR
)),
"bytes"
:
VarDecl
(
VarKind
.
LOCAL
,
TypeType
(
TY_BYTES
)),
"bool"
:
VarDecl
(
VarKind
.
LOCAL
,
TypeType
(
TY_BOOL
)),
"complex"
:
VarDecl
(
VarKind
.
LOCAL
,
TypeType
(
TY_COMPLEX
)),
"None"
:
VarDecl
(
VarKind
.
LOCAL
,
TypeType
(
TY_NONE
)),
"Callable"
:
VarDecl
(
VarKind
.
LOCAL
,
TypeType
(
FunctionType
)),
#"TypeVar": VarDecl(VarKind.LOCAL, TypeType(TypeVariable)),
"CppType"
:
VarDecl
(
VarKind
.
LOCAL
,
TypeType
(
CppType
)),
"list"
:
VarDecl
(
VarKind
.
LOCAL
,
TypeType
(
PyList
)),
"dict"
:
VarDecl
(
VarKind
.
LOCAL
,
TypeType
(
PyDict
)),
"Forked"
:
VarDecl
(
VarKind
.
LOCAL
,
TypeType
(
Forked
)),
"Task"
:
VarDecl
(
VarKind
.
LOCAL
,
TypeType
(
Task
)),
"Future"
:
VarDecl
(
VarKind
.
LOCAL
,
TypeType
(
Future
)),
"Iterator"
:
VarDecl
(
VarKind
.
LOCAL
,
TypeType
(
PyIterator
)),
"tuple"
:
VarDecl
(
VarKind
.
LOCAL
,
TypeType
(
TupleType
)),
"slice"
:
VarDecl
(
VarKind
.
LOCAL
,
TypeType
(
TY_SLICE
)),
"object"
:
VarDecl
(
VarKind
.
LOCAL
,
TypeType
(
TY_OBJECT
)),
"BuiltinFeature"
:
VarDecl
(
VarKind
.
LOCAL
,
TypeType
(
BuiltinFeature
)),
"Any"
:
VarDecl
(
VarKind
.
LOCAL
,
TypeType
(
TY_OBJECT
)),
"Optional"
:
VarDecl
(
VarKind
.
LOCAL
,
TypeType
(
lambda
x
:
UnionType
(
x
,
TY_NONE
))),
})
typon_std
=
Path
(
__file__
).
parent
.
parent
.
parent
.
parent
/
"stdlib"
def
make_module
(
name
:
str
,
scope
:
Scope
)
->
BaseType
:
ty
=
ModuleType
([],
f"
{
name
}
"
)
for
n
,
v
in
scope
.
vars
.
items
():
ty
.
fields
[
n
]
=
MemberDef
(
v
.
type
,
v
.
val
,
False
)
return
ty
def
discover_module
(
path
:
Path
,
scope
):
for
child
in
sorted
(
path
.
iterdir
()):
if
child
.
is_dir
():
mod_scope
=
PRELUDE
.
child
(
ScopeKind
.
GLOBAL
)
discover_module
(
child
,
mod_scope
)
scope
.
vars
[
child
.
name
]
=
make_mod_decl
(
child
.
name
,
mod_scope
)
elif
child
.
name
==
"__init__.py"
:
StdlibVisitor
(
scope
).
visit
(
ast
.
parse
(
child
.
read_text
()))
debug
(
f"Visited
{
child
}
"
)
elif
child
.
suffix
==
".py"
:
mod_scope
=
PRELUDE
.
child
(
ScopeKind
.
GLOBAL
)
StdlibVisitor
(
mod_scope
).
visit
(
ast
.
parse
(
child
.
read_text
()))
if
child
.
stem
[
-
1
]
==
"_"
:
child
=
child
.
with_name
(
child
.
stem
[:
-
1
])
scope
.
vars
[
child
.
stem
]
=
make_mod_decl
(
child
.
name
,
mod_scope
)
debug
(
f"Visited
{
child
}
"
)
def
make_mod_decl
(
child
,
mod_scope
):
return
VarDecl
(
VarKind
.
MODULE
,
make_module
(
child
,
mod_scope
),
{
k
:
v
.
type
for
k
,
v
in
mod_scope
.
vars
.
items
()})
discover_module
(
typon_std
,
PRELUDE
)
debug
(
"Stdlib visited!"
)
#exit()
\ No newline at end of file
typon/trans/transpiler/phases/typing2/annotations.py
0 → 100644
View file @
f8de89ac
import
abc
import
ast
from
dataclasses
import
dataclass
,
field
from
typing
import
Optional
,
List
from
transpiler.phases.typing.scope
import
Scope
from
transpiler.phases.typing.types
import
BaseType
,
TY_NONE
,
TypeVariable
,
TY_TYPE
,
ResolvedConcreteType
,
TypeListType
from
transpiler.phases.utils
import
NodeVisitorSeq
@
dataclass
class
TypeAnnotationVisitor
(
NodeVisitorSeq
):
scope
:
Scope
def
visit_str
(
self
,
node
:
str
)
->
BaseType
:
if
existing
:
=
self
.
scope
.
get
(
node
):
ty
=
existing
.
type
assert
isinstance
(
ty
,
ResolvedConcreteType
)
assert
ty
.
inherits
(
TY_TYPE
)
return
ty
.
inner_type
from
transpiler.phases.typing.exceptions
import
UnknownNameError
raise
UnknownNameError
(
node
)
def
visit_Name
(
self
,
node
:
ast
.
Name
)
->
BaseType
:
return
self
.
visit_str
(
node
.
id
)
def
visit_Constant
(
self
,
node
:
ast
.
Constant
)
->
BaseType
:
if
node
.
value
is
None
:
return
TY_NONE
if
type
(
node
.
value
)
==
str
:
return
node
.
value
raise
NotImplementedError
def
visit_Subscript
(
self
,
node
:
ast
.
Subscript
)
->
BaseType
:
# ty_op = self.visit(node.value)
# args = list(node.slice.elts) if type(node.slice) == ast.Tuple else [node.slice]
# args = [self.visit(arg) for arg in args]
# return ty_op(*args)
raise
NotImplementedError
()
# return TypeOperator([self.visit(node.value)], self.visit(node.slice.value))
def
visit_List
(
self
,
node
:
ast
.
List
)
->
BaseType
:
return
TypeListType
([
self
.
visit
(
elt
)
for
elt
in
node
.
elts
])
def
visit_Attribute
(
self
,
node
:
ast
.
Attribute
)
->
BaseType
:
raise
NotImplementedError
()
# left = self.visit(node.value)
# res = left.fields[node.attr].type
# assert isinstance(res, TypeType)
# return res.type_object
def
visit_BinOp
(
self
,
node
:
ast
.
BinOp
)
->
BaseType
:
# if isinstance(node.op, ast.BitOr):
# return UnionType(self.visit(node.left), self.visit(node.right))
raise
NotImplementedError
(
node
.
op
)
typon/trans/transpiler/phases/typing2/block.py
0 → 100644
View file @
f8de89ac
This diff is collapsed.
Click to expand it.
typon/trans/transpiler/phases/typing2/class_.py
0 → 100644
View file @
f8de89ac
# coding: utf-8
import
ast
from
dataclasses
import
dataclass
,
field
from
transpiler.phases.typing
import
FunctionType
,
ScopeKind
,
VarDecl
,
VarKind
,
TY_NONE
from
transpiler.phases.typing.common
import
ScoperVisitor
from
transpiler.phases.typing.types
import
PromiseKind
,
Promise
,
BaseType
,
MemberDef
@
dataclass
class
ScoperClassVisitor
(
ScoperVisitor
):
fdecls
:
list
[(
ast
.
FunctionDef
,
BaseType
)]
=
field
(
default_factory
=
list
)
def
visit_AnnAssign
(
self
,
node
:
ast
.
AnnAssign
):
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
isinstance
(
node
.
target
,
ast
.
Name
)
self
.
scope
.
obj_type
.
fields
[
node
.
target
.
id
]
=
MemberDef
(
self
.
visit_annotation
(
node
.
annotation
))
def
visit_Assign
(
self
,
node
:
ast
.
Assign
):
assert
len
(
node
.
targets
)
==
1
,
"Can't use destructuring in class static member"
assert
isinstance
(
node
.
targets
[
0
],
ast
.
Name
)
node
.
is_declare
=
True
valtype
=
self
.
expr
().
visit
(
node
.
value
)
node
.
targets
[
0
].
type
=
valtype
self
.
scope
.
obj_type
.
fields
[
node
.
targets
[
0
].
id
]
=
MemberDef
(
valtype
,
node
.
value
)
def
visit_FunctionDef
(
self
,
node
:
ast
.
FunctionDef
):
ftype
=
self
.
parse_function
(
node
)
ftype
.
parameters
[
0
].
unify
(
self
.
scope
.
obj_type
)
inner
=
ftype
.
return_type
if
node
.
name
!=
"__init__"
:
ftype
.
return_type
=
Promise
(
ftype
.
return_type
,
PromiseKind
.
TASK
)
ftype
.
is_method
=
True
self
.
scope
.
obj_type
.
fields
[
node
.
name
]
=
MemberDef
(
ftype
,
node
)
return
(
node
,
inner
)
typon/trans/transpiler/phases/typing2/common.py
0 → 100644
View file @
f8de89ac
import
ast
from
dataclasses
import
dataclass
,
field
from
typing
import
Dict
,
Optional
from
transpiler.utils
import
highlight
from
transpiler.phases.typing.annotations
import
TypeAnnotationVisitor
from
transpiler.phases.typing.scope
import
Scope
,
ScopeKind
,
VarDecl
,
VarKind
from
transpiler.phases.typing.types
import
BaseType
,
TypeVariable
,
TY_NONE
,
TypeType
,
BuiltinFeature
,
FunctionType
,
\
Promise
,
PromiseKind
from
transpiler.phases.utils
import
NodeVisitorSeq
,
AnnotationName
PRELUDE
=
Scope
.
make_global
()
@
dataclass
class
ScoperVisitor
(
NodeVisitorSeq
):
scope
:
Scope
=
field
(
default_factory
=
lambda
:
PRELUDE
.
child
(
ScopeKind
.
GLOBAL
))
root_decls
:
Dict
[
str
,
VarDecl
]
=
field
(
default_factory
=
dict
)
cur_class
:
Optional
[
TypeType
]
=
None
def
expr
(
self
)
->
"ScoperExprVisitor"
:
from
transpiler.phases.typing.expr
import
ScoperExprVisitor
return
ScoperExprVisitor
(
self
.
scope
,
self
.
root_decls
)
def
anno
(
self
)
->
"TypeAnnotationVisitor"
:
return
TypeAnnotationVisitor
(
self
.
scope
,
self
.
cur_class
)
def
visit_annotation
(
self
,
expr
:
Optional
[
ast
.
expr
])
->
BaseType
:
res
=
self
.
anno
().
visit
(
expr
)
if
expr
else
TypeVariable
()
assert
not
isinstance
(
res
,
TypeType
)
return
res
def
annotate_arg
(
self
,
arg
:
ast
.
arg
)
->
BaseType
:
if
arg
.
annotation
is
None
or
isinstance
(
arg
.
annotation
,
AnnotationName
):
res
=
TypeVariable
()
arg
.
annotation
=
AnnotationName
(
res
)
return
res
else
:
return
self
.
visit_annotation
(
arg
.
annotation
)
def
parse_function
(
self
,
node
:
ast
.
FunctionDef
):
argtypes
=
[
self
.
annotate_arg
(
arg
)
for
arg
in
node
.
args
.
args
]
rtype
=
self
.
visit_annotation
(
node
.
returns
)
ftype
=
FunctionType
(
argtypes
,
rtype
)
scope
=
self
.
scope
.
child
(
ScopeKind
.
FUNCTION
)
scope
.
obj_type
=
ftype
scope
.
function
=
scope
node
.
inner_scope
=
scope
node
.
type
=
ftype
ftype
.
optional_at
=
len
(
node
.
args
.
args
)
-
len
(
node
.
args
.
defaults
)
for
ty
,
default
in
zip
(
argtypes
[
ftype
.
optional_at
:],
node
.
args
.
defaults
):
self
.
expr
().
visit
(
default
).
unify
(
ty
)
for
arg
,
ty
in
zip
(
node
.
args
.
args
,
argtypes
):
scope
.
vars
[
arg
.
arg
]
=
VarDecl
(
VarKind
.
LOCAL
,
ty
)
self
.
fdecls
.
append
((
node
,
rtype
))
return
ftype
def
visit_block
(
self
,
block
:
list
[
ast
.
AST
]):
if
not
block
:
return
__TB__
=
f"running type analysis on block starting with
{
highlight
(
block
[
0
])
}
"
self
.
fdecls
=
[]
for
b
in
block
:
self
.
visit
(
b
)
if
self
.
fdecls
:
old_list
=
self
.
fdecls
exc
=
None
while
True
:
new_list
=
[]
for
node
,
rtype
in
old_list
:
from
transpiler.exceptions
import
CompileError
try
:
self
.
visit_function_definition
(
node
,
rtype
)
except
CompileError
as
e
:
new_list
.
append
((
node
,
rtype
))
if
not
exc
or
getattr
(
node
,
"is_main"
,
False
):
exc
=
e
if
len
(
new_list
)
==
len
(
old_list
):
raise
exc
if
not
new_list
:
break
old_list
=
new_list
exc
=
None
def
visit_function_definition
(
self
,
node
,
rtype
):
__TB__
=
f"running type analysis on the body of
{
highlight
(
node
)
}
"
__TB_NODE__
=
node
from
transpiler.phases.typing.block
import
ScoperBlockVisitor
for
b
in
node
.
body
:
decls
=
{}
visitor
=
ScoperBlockVisitor
(
node
.
inner_scope
,
decls
)
visitor
.
fdecls
=
[]
visitor
.
visit
(
b
)
if
len
(
visitor
.
fdecls
)
>
1
:
raise
NotImplementedError
(
"?"
)
elif
len
(
visitor
.
fdecls
)
==
1
:
fnode
,
frtype
=
visitor
.
fdecls
[
0
]
self
.
visit_function_definition
(
fnode
,
frtype
)
#del node.inner_scope.vars[fnode.name]
visitor
.
visit_assign_target
(
ast
.
Name
(
fnode
.
name
),
fnode
.
type
)
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
):
from
transpiler.phases.typing.exceptions
import
TypeMismatchError
try
:
rtype
.
unify
(
TY_NONE
)
except
TypeMismatchError
as
e
:
from
transpiler.phases.typing.exceptions
import
MissingReturnError
raise
MissingReturnError
(
node
)
from
e
def
get_iter
(
seq_type
):
try
:
iter_type
=
seq_type
.
fields
[
"__iter__"
].
type
.
return_type
except
:
from
transpiler.phases.typing.exceptions
import
NotIterableError
raise
NotIterableError
(
seq_type
)
return
iter_type
def
get_next
(
iter_type
):
try
:
next_type
=
iter_type
.
fields
[
"__next__"
].
type
.
return_type
except
:
from
transpiler.phases.typing.exceptions
import
NotIteratorError
raise
NotIteratorError
(
iter_type
)
return
next_type
def
is_builtin
(
x
,
feature
):
return
isinstance
(
x
,
BuiltinFeature
)
and
x
.
val
==
feature
\ No newline at end of file
typon/trans/transpiler/phases/typing2/exceptions.py
0 → 100644
View file @
f8de89ac
This diff is collapsed.
Click to expand it.
typon/trans/transpiler/phases/typing2/expr.py
0 → 100644
View file @
f8de89ac
This diff is collapsed.
Click to expand it.
typon/trans/transpiler/phases/typing2/scope.py
0 → 100644
View file @
f8de89ac
import
ast
from
dataclasses
import
field
,
dataclass
from
enum
import
Enum
from
typing
import
Optional
,
Dict
,
List
,
Any
from
transpiler.phases.typing.types
import
BaseType
,
RuntimeValue
class
VarKind
(
Enum
):
"""Kind of variable."""
LOCAL
=
1
"""`xxx = ...`"""
GLOBAL
=
2
"""`global xxx"""
NONLOCAL
=
3
"""`nonlocal xxx`"""
SELF
=
4
OUTER_DECL
=
5
MODULE
=
6
class
VarType
:
pass
@
dataclass
class
VarDecl
:
kind
:
VarKind
type
:
BaseType
val
:
Any
=
RuntimeValue
()
class
ScopeKind
(
Enum
):
GLOBAL
=
1
"""Global (module) scope"""
FUNCTION
=
2
"""Function scope"""
FUNCTION_INNER
=
3
"""Block (if, for, ...) scope inside a function"""
CLASS
=
4
"""Class scope"""
@
dataclass
class
Scope
:
parent
:
Optional
[
"Scope"
]
=
None
kind
:
ScopeKind
=
ScopeKind
.
GLOBAL
function
:
Optional
[
"Scope"
]
=
None
global_scope
:
Optional
[
"Scope"
]
=
None
vars
:
Dict
[
str
,
VarDecl
]
=
field
(
default_factory
=
dict
)
children
:
List
[
"Scope"
]
=
field
(
default_factory
=
list
)
obj_type
:
Optional
[
BaseType
]
=
None
diverges
:
bool
=
False
class_
:
Optional
[
"Scope"
]
=
None
is_loop
:
Optional
[
ast
.
For
|
ast
.
While
]
=
None
@
staticmethod
def
make_global
():
res
=
Scope
()
res
.
global_scope
=
res
return
res
def
is_in_loop
(
self
)
->
Optional
[
ast
.
For
|
ast
.
While
]:
if
self
.
is_loop
:
return
self
.
is_loop
if
self
.
parent
is
not
None
and
self
.
kind
!=
ScopeKind
.
FUNCTION
:
return
self
.
parent
.
is_in_loop
()
return
None
def
child
(
self
,
kind
:
ScopeKind
):
res
=
Scope
(
self
,
kind
,
self
.
function
,
self
.
global_scope
)
if
kind
==
ScopeKind
.
GLOBAL
:
res
.
global_scope
=
res
self
.
children
.
append
(
res
)
return
res
def
declare_local
(
self
,
name
:
str
,
type
:
BaseType
):
"""Declares a local variable"""
self
.
vars
[
name
]
=
VarDecl
(
VarKind
.
LOCAL
,
type
)
def
get
(
self
,
name
:
str
,
kind
:
VarKind
|
set
[
VarKind
]
=
VarKind
.
LOCAL
,
restrict_function
:
bool
=
False
)
->
Optional
[
VarDecl
]:
"""
Gets the variable declaration of a variable in the current scope or any parent scope.
"""
if
type
(
kind
)
is
VarKind
:
kind
=
{
kind
}
if
(
res
:
=
self
.
vars
.
get
(
name
))
and
res
.
kind
in
kind
:
if
res
.
kind
==
VarKind
.
GLOBAL
:
return
self
.
global_scope
.
get
(
name
,
kind
)
elif
res
.
kind
==
VarKind
.
NONLOCAL
:
return
self
.
function
.
parent
.
get
(
name
,
VarKind
.
LOCAL
,
True
)
return
res
if
self
.
parent
is
not
None
and
not
(
self
.
kind
==
ScopeKind
.
FUNCTION
and
restrict_function
):
return
self
.
parent
.
get
(
name
,
kind
,
restrict_function
)
return
None
typon/trans/transpiler/phases/typing2/stdlib.py
0 → 100644
View file @
f8de89ac
import
ast
import
dataclasses
from
abc
import
ABCMeta
from
dataclasses
import
dataclass
,
field
from
typing
import
Optional
,
List
,
Dict
from
logging
import
debug
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.scope
import
Scope
,
VarDecl
,
VarKind
,
ScopeKind
from
transpiler.phases.typing.types
import
BaseType
,
TypeOperator
,
FunctionType
,
TY_VARARG
,
TypeType
,
TypeVariable
,
\
MemberDef
,
BuiltinFeature
from
transpiler.phases.utils
import
NodeVisitorSeq
@
dataclass
class
StdlibVisitor
(
NodeVisitorSeq
):
scope
:
Scope
=
field
(
default_factory
=
lambda
:
PRELUDE
)
cur_class
:
Optional
[
BaseType
]
=
None
typevars
:
Dict
[
str
,
BaseType
]
=
field
(
default_factory
=
dict
)
def
expr
(
self
)
->
ScoperExprVisitor
:
return
ScoperExprVisitor
(
self
.
scope
)
def
visit_Module
(
self
,
node
:
ast
.
Module
):
for
stmt
in
node
.
body
:
self
.
visit
(
stmt
)
def
visit_Assign
(
self
,
node
:
ast
.
Assign
):
self
.
scope
.
vars
[
node
.
targets
[
0
].
id
]
=
VarDecl
(
VarKind
.
LOCAL
,
self
.
visit
(
node
.
value
))
def
visit_AnnAssign
(
self
,
node
:
ast
.
AnnAssign
):
ty
=
self
.
anno
().
visit
(
node
.
annotation
)
if
self
.
cur_class
:
assert
isinstance
(
self
.
cur_class
,
TypeType
)
if
isinstance
(
self
.
cur_class
.
type_object
,
ABCMeta
):
raise
NotImplementedError
else
:
self
.
cur_class
.
type_object
.
fields
[
node
.
target
.
id
]
=
MemberDef
(
ty
.
gen_sub
(
self
.
cur_class
.
type_object
,
self
.
typevars
))
self
.
scope
.
vars
[
node
.
target
.
id
]
=
VarDecl
(
VarKind
.
LOCAL
,
ty
)
def
visit_ImportFrom
(
self
,
node
:
ast
.
ImportFrom
):
pass
def
visit_Import
(
self
,
node
:
ast
.
Import
):
pass
def
visit_ClassDef
(
self
,
node
:
ast
.
ClassDef
):
if
existing
:
=
self
.
scope
.
get
(
node
.
name
):
ty
=
existing
.
type
else
:
class
BuiltinClassType
(
TypeOperator
):
def
__init__
(
self
,
*
args
):
super
().
__init__
(
args
,
node
.
name
,
is_reference
=
True
)
ty
=
TypeType
(
BuiltinClassType
)
self
.
scope
.
vars
[
node
.
name
]
=
VarDecl
(
VarKind
.
LOCAL
,
ty
)
typevars
=
[]
for
b
in
node
.
bases
:
if
isinstance
(
b
,
ast
.
Subscript
):
if
isinstance
(
b
.
slice
,
ast
.
Name
):
sliceval
=
[
b
.
slice
.
id
]
elif
isinstance
(
b
.
slice
,
ast
.
Tuple
):
sliceval
=
[
n
.
id
for
n
in
b
.
slice
.
elts
]
if
isinstance
(
b
.
value
,
ast
.
Name
)
and
b
.
value
.
id
==
"Generic"
:
typevars
=
sliceval
elif
isinstance
(
b
.
value
,
ast
.
Name
)
and
b
.
value
.
id
==
"Protocol"
:
typevars
=
sliceval
ty
.
type_object
.
is_protocol_gen
=
True
else
:
idxs
=
[
typevars
.
index
(
v
)
for
v
in
sliceval
]
parent
=
self
.
visit
(
b
.
value
)
assert
isinstance
(
parent
,
TypeType
)
assert
isinstance
(
ty
.
type_object
,
ABCMeta
)
ty
.
type_object
.
gen_parents
.
append
(
lambda
selfvars
:
parent
.
type_object
(
*
[
selfvars
[
i
]
for
i
in
idxs
]))
else
:
if
isinstance
(
b
,
ast
.
Name
)
and
b
.
id
==
"Protocol"
:
ty
.
type_object
.
is_protocol_gen
=
True
else
:
parent
=
self
.
visit
(
b
)
assert
isinstance
(
parent
,
TypeType
)
if
isinstance
(
ty
.
type_object
,
ABCMeta
):
ty
.
type_object
.
gen_parents
.
append
(
parent
.
type_object
)
else
:
ty
.
type_object
.
parents
.
append
(
parent
.
type_object
)
if
not
typevars
and
not
existing
:
ty
.
type_object
=
ty
.
type_object
()
cl_scope
=
self
.
scope
.
child
(
ScopeKind
.
CLASS
)
visitor
=
StdlibVisitor
(
cl_scope
,
ty
)
for
var
in
typevars
:
visitor
.
typevars
[
var
]
=
TypeType
(
TypeVariable
(
var
))
for
stmt
in
node
.
body
:
visitor
.
visit
(
stmt
)
def
visit_Pass
(
self
,
node
:
ast
.
Pass
):
pass
def
visit_FunctionDef
(
self
,
node
:
ast
.
FunctionDef
):
tc
=
node
.
type_comment
# todo : lire les commetnaries de type pour les fonctions génériques sinon trouver autre chose
arg_visitor
=
TypeAnnotationVisitor
(
self
.
scope
.
child
(
ScopeKind
.
FUNCTION
),
self
.
cur_class
)
arg_types
=
[
arg_visitor
.
visit
(
arg
.
annotation
or
arg
.
arg
)
for
arg
in
node
.
args
.
args
]
ret_type
=
arg_visitor
.
visit
(
node
.
returns
)
ty
=
FunctionType
(
arg_types
,
ret_type
)
ty
.
typevars
=
arg_visitor
.
typevars
if
node
.
args
.
vararg
:
ty
.
variadic
=
True
ty
.
optional_at
=
1
+
len
(
node
.
args
.
args
)
-
len
(
node
.
args
.
defaults
)
if
self
.
cur_class
:
ty
.
is_method
=
True
assert
isinstance
(
self
.
cur_class
,
TypeType
)
if
isinstance
(
self
.
cur_class
.
type_object
,
ABCMeta
):
self
.
cur_class
.
type_object
.
gen_methods
[
node
.
name
]
=
lambda
t
:
ty
.
gen_sub
(
t
,
self
.
typevars
)
else
:
self
.
cur_class
.
type_object
.
fields
[
node
.
name
]
=
MemberDef
(
ty
.
gen_sub
(
self
.
cur_class
.
type_object
,
self
.
typevars
),
())
self
.
scope
.
vars
[
node
.
name
]
=
VarDecl
(
VarKind
.
LOCAL
,
ty
)
def
visit_Assert
(
self
,
node
:
ast
.
Assert
):
if
isinstance
(
node
.
test
,
ast
.
UnaryOp
)
and
isinstance
(
node
.
test
.
op
,
ast
.
Not
):
oper
=
node
.
test
.
operand
try
:
res
=
self
.
expr
().
visit
(
oper
)
except
:
debug
(
f"Type of
{
ast
.
unparse
(
oper
)
}
:= INVALID"
)
else
:
raise
AssertionError
(
f"Assertion should fail, got
{
res
}
for
{
ast
.
unparse
(
oper
)
}
"
)
else
:
debug
(
f"Type of
{
ast
.
unparse
(
node
.
test
)
}
:=
{
self
.
expr
().
visit
(
node
.
test
)
}
"
)
def
visit_Call
(
self
,
node
:
ast
.
Call
)
->
BaseType
:
ty_op
=
self
.
visit
(
node
.
func
)
if
is_builtin
(
ty_op
,
"TypeVar"
):
return
TypeType
(
TypeVariable
(
*
[
ast
.
literal_eval
(
arg
)
for
arg
in
node
.
args
]))
if
isinstance
(
ty_op
,
TypeType
):
return
TypeType
(
ty_op
.
type_object
(
*
[
ast
.
literal_eval
(
arg
)
for
arg
in
node
.
args
]))
raise
NotImplementedError
(
ast
.
unparse
(
node
))
def
anno
(
self
)
->
"TypeAnnotationVisitor"
:
return
TypeAnnotationVisitor
(
self
.
scope
,
self
.
cur_class
)
def
visit_str
(
self
,
node
:
str
)
->
BaseType
:
if
existing
:
=
self
.
scope
.
get
(
node
):
return
existing
.
type
from
transpiler.phases.typing.exceptions
import
UnknownNameError
raise
UnknownNameError
(
node
)
def
visit_Name
(
self
,
node
:
ast
.
Name
)
->
BaseType
:
if
node
.
id
==
"TypeVar"
:
return
BuiltinFeature
(
"TypeVar"
)
return
self
.
visit_str
(
node
.
id
)
\ No newline at end of file
typon/trans/transpiler/phases/typing2/types.py
0 → 100644
View file @
f8de89ac
import
typing
from
abc
import
ABC
,
abstractmethod
from
dataclasses
import
dataclass
,
field
from
typing
import
Dict
,
Optional
,
Callable
def
get_default_parents
():
if
obj
:
=
globals
().
get
(
"TY_OBJECT"
):
return
[
obj
]
return
[]
class
RuntimeValue
:
pass
@
dataclass
class
MemberDef
:
type
:
"BaseType"
val
:
typing
.
Any
=
RuntimeValue
()
in_class_def
:
bool
=
True
@
dataclass
(
eq
=
False
)
class
BaseType
(
ABC
):
def
resolve
(
self
)
->
"BaseType"
:
return
self
cur_var
=
0
def
next_var_id
():
global
cur_var
cur_var
+=
1
return
cur_var
@
dataclass
(
eq
=
False
)
class
ConcreteType
(
BaseType
):
"""
A concrete type is the type of a concrete value.
It has fields and a list of parent concrete types.
Examples: int, str, list[int]
"""
@
dataclass
(
eq
=
False
)
class
TypeVariable
(
ConcreteType
):
name
:
str
=
field
(
default_factory
=
lambda
:
next_var_id
())
resolved
:
Optional
[
ConcreteType
]
=
None
def
resolve
(
self
)
->
ConcreteType
:
if
self
.
resolved
is
None
:
return
self
return
self
.
resolved
.
resolve
()
def
__str__
(
self
):
if
self
.
resolved
is
None
:
# return f"TypeVar[\"{self.name}\"]"
return
f"_
{
self
.
name
}
"
return
str
(
self
.
resolved
)
def
__eq__
(
self
,
other
):
if
not
isinstance
(
other
,
BaseType
):
return
False
if
self
.
resolved
is
None
:
return
self
==
other
return
self
.
resolved
==
other
.
resolve
()
@
dataclass
(
eq
=
False
)
class
ResolvedConcreteType
(
ConcreteType
):
"""
A concrete type is the type of a concrete value.
It has fields and a list of parent concrete types.
Examples: int, str, list[int]
"""
fields
:
Dict
[
str
,
"MemberDef"
]
=
field
(
default_factory
=
dict
,
init
=
False
)
parents
:
list
[
"ResolvedConcreteType"
]
=
field
(
default_factory
=
lambda
:
[
TY_OBJECT
],
init
=
False
)
def
get_mro
(
self
):
"""
Performs linearization according to the MRO spec.
https://www.python.org/download/releases/2.3/mro/
"""
def
merge
(
*
lists
):
lists
=
[
l
for
l
in
lists
if
len
(
l
)
>
0
]
for
i
,
l
in
enumerate
(
lists
):
first
=
l
[
0
]
for
j
,
l2
in
enumerate
(
lists
):
if
j
==
i
:
continue
if
first
in
l2
:
break
else
:
return
[
first
]
+
merge
(
*
[
x
[
1
:]
for
x
in
lists
if
x
[
0
]
!=
first
])
# unable to find a next element
from
transpiler.phases.typing.exceptions
import
InconsistentMroError
raise
InconsistentMroError
(
self
.
parents
)
return
[
self
]
+
merge
(
*
[
p
.
get_mro
()
for
p
in
self
.
parents
],
self
.
parents
)
def
inherits
(
self
,
parent
:
BaseType
):
return
self
==
parent
or
any
(
p
.
inherits
(
parent
)
for
p
in
self
.
parents
)
@
dataclass
(
eq
=
False
,
init
=
False
)
class
GenericInstanceType
(
ResolvedConcreteType
):
"""
An instance of a generic type.
Examples: list[int], dict[str, object], Callable[[int, int], int]
"""
generic_parent
:
"GenericType"
generic_args
:
list
[
ConcreteType
]
def
__init__
(
self
):
super
().
__init__
()
def
inherits
(
self
,
parent
:
BaseType
):
return
self
.
generic_parent
==
parent
or
super
().
inherits
(
parent
)
def
__eq__
(
self
,
other
):
if
isinstance
(
other
,
GenericInstanceType
):
return
self
.
generic_parent
==
other
.
generic_parent
and
self
.
generic_args
==
other
.
generic_args
return
False
def
__str__
(
self
):
return
f"
{
self
.
generic_parent
}
[
{
', '
.
join
(
map
(
str
,
self
.
generic_args
))
}
]"
@
dataclass
class
GenericConstraint
:
left
:
ResolvedConcreteType
right
:
ResolvedConcreteType
@
dataclass
(
eq
=
False
,
init
=
False
)
class
GenericType
(
BaseType
):
parameters
:
list
[
str
]
def
constraints
(
self
,
args
:
list
[
ConcreteType
])
->
list
[
GenericConstraint
]:
return
[]
@
abstractmethod
def
_instantiate
(
self
,
args
:
list
[
ConcreteType
])
->
GenericInstanceType
:
raise
NotImplementedError
()
def
instantiate
(
self
,
args
:
list
[
ConcreteType
])
->
GenericInstanceType
:
res
=
self
.
_instantiate
(
args
)
res
.
generic_args
=
args
res
.
generic_parent
=
self
return
res
@
dataclass
(
eq
=
False
,
init
=
False
)
class
BuiltinGenericType
(
GenericType
):
constraints_
:
Callable
[[
list
[
ConcreteType
]],
list
[
GenericConstraint
]]
instantiate_
:
Callable
[[
list
[
ConcreteType
]],
GenericInstanceType
]
def
constraints
(
self
,
args
:
list
[
ConcreteType
])
->
list
[
GenericConstraint
]:
return
self
.
constraints_
(
args
)
def
_instantiate
(
self
,
args
:
list
[
ConcreteType
])
->
GenericInstanceType
:
return
self
.
instantiate_
(
args
)
def
create_builtin_type
(
name
:
str
):
class
CreatedType
(
BuiltinGenericType
):
def
__str__
(
self
):
return
name
res
=
CreatedType
()
return
res
TY_OBJECT
=
None
TY_OBJECT
=
create_builtin_type
(
"object"
)
TY_OBJECT
.
parents
=
[]
TY_BOOL
=
create_builtin_type
(
"bool"
)
TY_INT
=
create_builtin_type
(
"int"
)
TY_FLOAT
=
create_builtin_type
(
"float"
)
TY_STR
=
create_builtin_type
(
"str"
)
TY_BYTES
=
create_builtin_type
(
"bytes"
)
TY_COMPLEX
=
create_builtin_type
(
"complex"
)
TY_NONE
=
create_builtin_type
(
"NoneType"
)
def
unimpl
(
*
args
,
**
kwargs
):
raise
NotImplementedError
()
def
create_builtin_generic_type
(
name
:
str
):
class
CreatedType
(
BuiltinGenericType
):
def
__str__
(
self
):
return
name
res
=
CreatedType
()
return
res
TY_LIST
=
create_builtin_generic_type
(
"list"
)
TY_SET
=
create_builtin_generic_type
(
"set"
)
TY_DICT
=
create_builtin_generic_type
(
"dict"
)
TY_TUPLE
=
create_builtin_generic_type
(
"tuple"
)
@
dataclass
(
unsafe_hash
=
False
)
class
TypeListType
(
ConcreteType
):
"""
Special type used to represent a list of types.
Used in function types: Callable[[int, int], int]
"""
contents
:
list
[
ConcreteType
]
def
__str__
(
self
):
return
f"[
{
', '
.
join
(
map
(
str
,
self
.
contents
))
}
]"
@
dataclass
(
eq
=
False
)
class
CallableInstanceType
(
GenericInstanceType
):
parameters
:
list
[
ConcreteType
]
return_type
:
ConcreteType
class
CallableType
(
GenericType
):
def
__str__
(
self
):
return
"Callable"
def
_instantiate
(
self
,
args
:
list
[
ConcreteType
])
->
GenericInstanceType
:
match
args
:
case
[
TypeListType
([
*
args
]),
ret
]:
return
CallableInstanceType
(
args
,
ret
)
case
_
:
raise
ValueError
TY_CALLABLE
=
CallableType
()
@
dataclass
(
eq
=
False
)
class
ClassTypeType
(
GenericInstanceType
):
inner_type
:
BaseType
class
ClassType
(
GenericType
):
def
__str__
(
self
):
return
"Type"
def
_instantiate
(
self
,
args
:
list
[
ConcreteType
])
->
GenericInstanceType
:
return
ClassTypeType
(
*
args
)
TY_TYPE
=
ClassType
()
typon/trans/transpiler/utils.py
View file @
f8de89ac
...
...
@@ -66,7 +66,7 @@ def highlight(code, full=False):
return
cf
.
yellow
(
"<None>"
)
if
type
(
code
)
==
list
:
return
repr
([
highlight
(
x
)
for
x
in
code
])
from
transpiler.phases.typing
import
BaseType
from
transpiler.phases.typing
.types
import
BaseType
if
isinstance
(
code
,
ast
.
AST
):
return
cf
.
italic_grey60
(
f"[
{
type
(
code
).
__name__
}
] "
)
+
highlight
(
ast
.
unparse
(
code
))
elif
isinstance
(
code
,
BaseType
):
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment