Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
T
typon
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
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Tom Niget
typon
Commits
b5c58745
Commit
b5c58745
authored
Jul 27, 2023
by
Tom Niget
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Continue work on error display
parent
5de0d528
Changes
6
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
93 additions
and
28 deletions
+93
-28
trans/tests/a_a_a_errtest.py
trans/tests/a_a_a_errtest.py
+5
-0
trans/transpiler/__init__.py
trans/transpiler/__init__.py
+22
-14
trans/transpiler/phases/typing/block.py
trans/transpiler/phases/typing/block.py
+9
-1
trans/transpiler/phases/typing/exceptions.py
trans/transpiler/phases/typing/exceptions.py
+24
-2
trans/transpiler/phases/typing/types.py
trans/transpiler/phases/typing/types.py
+7
-2
trans/transpiler/utils.py
trans/transpiler/utils.py
+26
-9
No files found.
trans/tests/a_a_a_errtest.py
0 → 100644
View file @
b5c58745
def
f
(
x
):
return
x
if
__name__
==
"__main__"
:
y
=
f
(
f
)
\ No newline at end of file
trans/transpiler/__init__.py
View file @
b5c58745
...
@@ -3,22 +3,29 @@ import ast
...
@@ -3,22 +3,29 @@ import ast
import
builtins
import
builtins
import
inspect
import
inspect
import
os
os
.
environ
[
"TERM"
]
=
"xterm-256"
import
colorama
colorama
.
init
()
from
transpiler.consts
import
MAPPINGS
from
transpiler.consts
import
MAPPINGS
from
transpiler.exceptions
import
CompileError
from
transpiler.exceptions
import
CompileError
from
transpiler.phases.desugar_with
import
DesugarWith
from
transpiler.phases.desugar_with
import
DesugarWith
#from transpiler.phases import initial_pytype
#
from transpiler.phases import initial_pytype
from
transpiler.phases.emit_cpp.file
import
FileVisitor
from
transpiler.phases.emit_cpp.file
import
FileVisitor
from
transpiler.phases.if_main
import
IfMainVisitor
from
transpiler.phases.if_main
import
IfMainVisitor
from
transpiler.phases.typing.block
import
ScoperBlockVisitor
from
transpiler.phases.typing.block
import
ScoperBlockVisitor
from
transpiler.phases.typing.scope
import
Scope
from
transpiler.phases.typing.scope
import
Scope
import
sys
import
sys
from
colorama
import
Fore
import
color
ama
import
color
ful
as
cf
from
transpiler.utils
import
highlight
from
transpiler.utils
import
highlight
colorama
.
init
()
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
)
...
@@ -41,34 +48,37 @@ def exception_hook(exc_type, exc_value, tb):
...
@@ -41,34 +48,37 @@ def exception_hook(exc_type, exc_value, tb):
filename
=
tb
.
tb_frame
.
f_code
.
co_filename
filename
=
tb
.
tb_frame
.
f_code
.
co_filename
line_no
=
tb
.
tb_lineno
line_no
=
tb
.
tb_lineno
print
(
f"
{
Fore
.
RED
}
File
\
"
{
filename
}\
"
, line
{
line_no
}
, in
{
name
}
"
,
end
=
""
)
print
(
cf
.
red
(
f"File
\
"
{
filename
}\
"
, line
{
line_no
}
, in
{
name
}
"
)
,
end
=
""
)
if
info
:
=
local_vars
.
get
(
"TB"
,
None
):
if
info
:
=
local_vars
.
get
(
"TB"
,
None
):
print
(
f", while
{
Fore
.
MAGENTA
}{
info
}
"
)
print
(
f", while
{
cf
.
magenta
(
info
)
}
"
)
else
:
else
:
print
()
print
()
tb
=
tb
.
tb_next
tb
=
tb
.
tb_next
if
last_node
is
not
None
:
if
last_node
is
not
None
:
print
(
f"In file
\
"
{
Fore
.
RESET
}{
last_file
}{
Fore
.
RED
}\
"
, line
{
last_node
.
lineno
}
"
)
print
(
f"In file
\
"
{
cf
.
white
(
last_file
)
}\
"
, line
{
last_node
.
lineno
}
"
)
print
(
"
\
t
"
+
highlight
(
ast
.
unparse
(
last_node
)))
print
(
"
\
t
"
+
highlight
(
ast
.
unparse
(
last_node
)))
print
()
print
()
print
(
f"
{
Fore
.
RED
}
Error:
{
Fore
.
RESET
}
{
exc_value
}
"
)
print
(
cf
.
red
(
"Error:"
),
exc_value
)
if
isinstance
(
exc_value
,
CompileError
):
if
isinstance
(
exc_value
,
CompileError
):
print
()
print
(
inspect
.
cleandoc
(
exc_value
.
detail
(
last_node
)))
print
(
inspect
.
cleandoc
(
exc_value
.
detail
(
last_node
)))
print
()
print
()
sys
.
excepthook
=
exception_hook
sys
.
excepthook
=
exception_hook
def
transpile
(
source
,
name
=
"<module>"
,
path
=
None
):
def
transpile
(
source
,
name
=
"<module>"
,
path
=
None
):
TB
=
f"transpiling module
{
Fore
.
RESET
}{
name
}
"
TB
=
f"transpiling module
{
cf
.
white
(
name
)
}
"
res
=
ast
.
parse
(
source
,
type_comments
=
True
)
res
=
ast
.
parse
(
source
,
type_comments
=
True
)
#res = initial_pytype.run(source, res)
#
res = initial_pytype.run(source, res)
res
=
DesugarWith
().
visit
(
res
)
res
=
DesugarWith
().
visit
(
res
)
IfMainVisitor
().
visit
(
res
)
IfMainVisitor
().
visit
(
res
)
ScoperBlockVisitor
().
visit
(
res
)
ScoperBlockVisitor
().
visit
(
res
)
#print(res.scope)
# print(res.scope)
# display each scope
# display each scope
def
disp_scope
(
scope
,
indent
=
0
):
def
disp_scope
(
scope
,
indent
=
0
):
...
@@ -78,9 +88,7 @@ def transpile(source, name="<module>", path=None):
...
@@ -78,9 +88,7 @@ def transpile(source, name="<module>", path=None):
for
var
in
scope
.
vars
.
items
():
for
var
in
scope
.
vars
.
items
():
print
(
" "
*
(
indent
+
1
),
var
)
print
(
" "
*
(
indent
+
1
),
var
)
# disp_scope(res.scope)
#disp_scope(res.scope)
code
=
"
\
n
"
.
join
(
filter
(
None
,
map
(
str
,
FileVisitor
(
Scope
()).
visit
(
res
))))
code
=
"
\
n
"
.
join
(
filter
(
None
,
map
(
str
,
FileVisitor
(
Scope
()).
visit
(
res
))))
return
code
return
code
trans/transpiler/phases/typing/block.py
View file @
b5c58745
...
@@ -136,8 +136,16 @@ class ScoperBlockVisitor(ScoperVisitor):
...
@@ -136,8 +136,16 @@ class ScoperBlockVisitor(ScoperVisitor):
else
:
else
:
raise
NotImplementedError
(
ast
.
unparse
(
target
))
raise
NotImplementedError
(
ast
.
unparse
(
target
))
def
annotate_arg
(
self
,
arg
:
ast
.
arg
)
->
BaseType
:
if
arg
.
annotation
is
None
:
res
=
TypeVariable
()
arg
.
annotation
=
ast
.
Name
(
id
=
str
(
res
),
ctx
=
ast
.
Load
())
return
res
else
:
return
self
.
visit_annotation
(
arg
.
annotation
)
def
visit_FunctionDef
(
self
,
node
:
ast
.
FunctionDef
):
def
visit_FunctionDef
(
self
,
node
:
ast
.
FunctionDef
):
argtypes
=
[
self
.
visit_annotation
(
arg
.
annotation
)
for
arg
in
node
.
args
.
args
]
argtypes
=
[
self
.
annotate_arg
(
arg
)
for
arg
in
node
.
args
.
args
]
rtype
=
Promise
(
self
.
visit_annotation
(
node
.
returns
),
PromiseKind
.
TASK
)
rtype
=
Promise
(
self
.
visit_annotation
(
node
.
returns
),
PromiseKind
.
TASK
)
ftype
=
FunctionType
(
argtypes
,
rtype
)
ftype
=
FunctionType
(
argtypes
,
rtype
)
self
.
scope
.
vars
[
node
.
name
]
=
VarDecl
(
VarKind
.
LOCAL
,
ftype
)
self
.
scope
.
vars
[
node
.
name
]
=
VarDecl
(
VarKind
.
LOCAL
,
ftype
)
...
...
trans/transpiler/phases/typing/exceptions.py
View file @
b5c58745
...
@@ -3,7 +3,7 @@ from dataclasses import dataclass
...
@@ -3,7 +3,7 @@ from dataclasses import dataclass
from
transpiler.utils
import
highlight
from
transpiler.utils
import
highlight
from
transpiler.exceptions
import
CompileError
from
transpiler.exceptions
import
CompileError
from
transpiler.phases.typing
import
TypeVariabl
e
from
transpiler.phases.typing
.types
import
TypeVariable
,
BaseTyp
e
@
dataclass
@
dataclass
...
@@ -25,8 +25,30 @@ class UnresolvedTypeVariableError(CompileError):
...
@@ -25,8 +25,30 @@ class UnresolvedTypeVariableError(CompileError):
For example:
For example:
↓↓↓ this tells the compiler that
{
highlight
(
'math.factorial'
)
}
returns an
{
highlight
(
'int'
)
}
↓↓↓ this tells the compiler that
{
highlight
(
'math.factorial'
)
}
returns an
{
highlight
(
'int'
)
}
{
highlight
(
'res: int = math.factorial(5)'
)
}
"""
{
highlight
(
'res: int = math.factorial(5)'
)
}
"""
return
"""
return
f
"""
This generally indicates the compiler was unable to infer the type of a variable or expression.
This generally indicates the compiler was unable to infer the type of a variable or expression.
A common fix is to add a type annotation to the variable or function.
A common fix is to add a type annotation to the variable or function.
For example:
↓↓↓ this tells the compiler that
{
highlight
(
'x'
)
}
is an
{
highlight
(
'int'
)
}
{
highlight
(
'def f(x: int):'
)
}
"""
"""
@
dataclass
class
RecursiveTypeUnificationError
(
CompileError
):
needle
:
BaseType
haystack
:
BaseType
def
__str__
(
self
)
->
str
:
return
f"Recursive type unification:
{
highlight
(
self
.
needle
)
}
and
{
highlight
(
self
.
haystack
)
}
"
def
detail
(
self
,
last_node
:
ast
.
AST
=
None
)
->
str
:
return
f"""
This generally indicates a recursive type definition. Such types are not currently supported.
For example:
{
highlight
(
'T = tuple[T]'
)
}
In the current case,
{
highlight
(
self
.
haystack
)
}
contains type
{
highlight
(
self
.
needle
)
}
, but an attempt was made to
unify them.
"""
\ No newline at end of file
trans/transpiler/phases/typing/types.py
View file @
b5c58745
...
@@ -6,6 +6,8 @@ from enum import Enum
...
@@ -6,6 +6,8 @@ from enum import Enum
from
itertools
import
zip_longest
from
itertools
import
zip_longest
from
typing
import
Dict
,
Optional
,
List
,
ClassVar
,
Callable
from
typing
import
Dict
,
Optional
,
List
,
ClassVar
,
Callable
from
transpiler.utils
import
highlight
class
IncompatibleTypesError
(
Exception
):
class
IncompatibleTypesError
(
Exception
):
pass
pass
...
@@ -31,6 +33,7 @@ class BaseType(ABC):
...
@@ -31,6 +33,7 @@ class BaseType(ABC):
def
unify
(
self
,
other
:
"BaseType"
):
def
unify
(
self
,
other
:
"BaseType"
):
a
,
b
=
self
.
resolve
(),
other
.
resolve
()
a
,
b
=
self
.
resolve
(),
other
.
resolve
()
TB
=
f"unifying
{
highlight
(
a
)
}
and
{
highlight
(
b
)
}
"
if
isinstance
(
b
,
TypeVariable
):
if
isinstance
(
b
,
TypeVariable
):
a
,
b
=
b
,
a
a
,
b
=
b
,
a
a
.
unify_internal
(
b
)
a
.
unify_internal
(
b
)
...
@@ -88,7 +91,8 @@ class TypeVariable(BaseType):
...
@@ -88,7 +91,8 @@ class TypeVariable(BaseType):
def
__str__
(
self
):
def
__str__
(
self
):
if
self
.
resolved
is
None
:
if
self
.
resolved
is
None
:
return
self
.
name
#return f"TypeVar[\"{self.name}\"]"
return
"_"
+
self
.
name
return
str
(
self
.
resolved
)
return
str
(
self
.
resolved
)
def
resolve
(
self
)
->
BaseType
:
def
resolve
(
self
)
->
BaseType
:
...
@@ -99,7 +103,8 @@ class TypeVariable(BaseType):
...
@@ -99,7 +103,8 @@ class TypeVariable(BaseType):
def
unify_internal
(
self
,
other
:
BaseType
):
def
unify_internal
(
self
,
other
:
BaseType
):
if
self
is
not
other
:
if
self
is
not
other
:
if
other
.
contains
(
self
):
if
other
.
contains
(
self
):
raise
ValueError
(
f"Recursive type:
{
self
}
and
{
other
}
"
)
from
transpiler.phases.typing.exceptions
import
RecursiveTypeUnificationError
raise
RecursiveTypeUnificationError
(
self
,
other
)
self
.
resolved
=
other
self
.
resolved
=
other
def
contains_internal
(
self
,
other
:
BaseType
)
->
bool
:
def
contains_internal
(
self
,
other
:
BaseType
)
->
bool
:
...
...
trans/transpiler/utils.py
View file @
b5c58745
...
@@ -3,9 +3,25 @@ import ast
...
@@ -3,9 +3,25 @@ import ast
from
dataclasses
import
dataclass
from
dataclasses
import
dataclass
from
itertools
import
zip_longest
from
itertools
import
zip_longest
from
typing
import
Union
from
typing
import
Union
import
colorful
as
cf
from
colorama
import
Fore
#
# from colorama import Fore, Back
# from colorama.ansi import AnsiCodes
#
#
# class AnsiStyle(AnsiCodes):
# BOLD = 1
# DIM = 2
# ITALIC = 3
# UNDERLINE = 4
# BLINK = 5
# REVERSE = 7
# HIDDEN = 8
# STRIKETHROUGH = 9
#
# RESET = "21;22;23;24;25;27;28;29"
#
# Style = AnsiStyle()
def
highlight
(
code
,
full
=
False
):
def
highlight
(
code
,
full
=
False
):
"""
"""
...
@@ -13,20 +29,21 @@ def highlight(code, full=False):
...
@@ -13,20 +29,21 @@ def highlight(code, full=False):
"""
"""
from
transpiler.phases.typing
import
BaseType
from
transpiler.phases.typing
import
BaseType
if
isinstance
(
code
,
ast
.
AST
):
if
isinstance
(
code
,
ast
.
AST
):
return
f"
{
Fore
.
WHITE
}
[
{
type
(
code
).
__name__
}
] "
+
highlight
(
ast
.
unparse
(
code
))
return
cf
.
italic_darkGrey
(
f"[
{
type
(
code
).
__name__
}
] "
)
+
highlight
(
ast
.
unparse
(
code
))
elif
isinstance
(
code
,
BaseType
):
elif
isinstance
(
code
,
BaseType
):
return
f"
{
Fore
.
WHITE
}
[
{
type
(
code
).
__name__
}
] "
+
highlight
(
str
(
code
))
return
cf
.
italic_grey50
(
f"[
{
type
(
code
).
__name__
}
] "
)
+
highlight
(
str
(
code
))
from
pygments
import
highlight
as
pyg_highlight
from
pygments
import
highlight
as
pyg_highlight
from
pygments.lexers
import
PythonLexer
from
pygments.lexers
import
PythonLexer
from
pygments.formatters
import
TerminalFormatter
from
pygments.formatters
import
TerminalFormatter
items
=
pyg_highlight
(
code
,
PythonLexer
(),
TerminalFormatter
()).
splitlines
()
items
=
pyg_highlight
(
code
,
PythonLexer
(),
TerminalFormatter
()).
replace
(
"
\
x1b
[39;49;00m"
,
"
\
x1b
[39m"
).
splitlines
()
if
full
:
if
full
:
return
Fore
.
RESET
+
"
\
n
"
.
join
(
items
)
return
"
\
n
"
.
join
(
items
)
res
=
items
[
0
]
res
=
items
[
0
]
if
len
(
items
)
>
1
:
if
len
(
items
)
>
1
:
res
+=
Fore
.
WHITE
+
" [...]"
res
+=
cf
.
white
(
" [...]"
)
return
Fore
.
RESET
+
res
#return Back.LIGHTBLACK_EX + Fore.RESET + res + Back.RESET
return
cf
.
on_gray30
(
res
)
def
compare_ast
(
node1
:
Union
[
ast
.
expr
,
list
[
ast
.
expr
]],
node2
:
Union
[
ast
.
expr
,
list
[
ast
.
expr
]])
->
bool
:
def
compare_ast
(
node1
:
Union
[
ast
.
expr
,
list
[
ast
.
expr
]],
node2
:
Union
[
ast
.
expr
,
list
[
ast
.
expr
]])
->
bool
:
...
...
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