Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
P
Pyston
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
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Boxiang Sun
Pyston
Commits
ccb7cff9
Commit
ccb7cff9
authored
Aug 18, 2014
by
Travis Hance
Committed by
Travis Hance
Aug 21, 2014
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add __future__ flags, raise syntax errors for bad __future__ imports
parent
fe565665
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
204 additions
and
14 deletions
+204
-14
src/codegen/irgen/future.cpp
src/codegen/irgen/future.cpp
+133
-0
src/codegen/irgen/future.h
src/codegen/irgen/future.h
+58
-0
src/codegen/irgen/hooks.cpp
src/codegen/irgen/hooks.cpp
+3
-0
src/codegen/irgen/irgenerator.cpp
src/codegen/irgen/irgenerator.cpp
+0
-14
test/tests/future_non_existent.py
test/tests/future_non_existent.py
+1
-0
test/tests/future_not_at_beginning.py
test/tests/future_not_at_beginning.py
+5
-0
test/tests/future_not_at_beginning2.py
test/tests/future_not_at_beginning2.py
+4
-0
No files found.
src/codegen/irgen/future.cpp
0 → 100644
View file @
ccb7cff9
// Copyright (c) 2014 Dropbox, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "future.h"
namespace
pyston
{
// Helper function:
void
raiseSyntaxError
(
const
char
*
file
,
AST
*
node_at
,
const
char
*
msg
,
...)
{
va_list
ap
;
va_start
(
ap
,
msg
);
char
buf
[
1024
];
vsnprintf
(
buf
,
sizeof
(
buf
),
msg
,
ap
);
// TODO I'm not sure that it's safe to raise an exception here, since I think
// there will be things that end up not getting cleaned up.
// Then again, there are a huge number of things that don't get cleaned up even
// if an exception doesn't get thrown...
// TODO output is still a little wrong, should be, for example
//
// File "../test/tests/future_non_existent.py", line 1
// from __future__ import rvalue_references # should cause syntax error
//
// but instead it is
//
// Traceback (most recent call last):
// File "../test/tests/future_non_existent.py", line -1, in :
// from __future__ import rvalue_references # should cause syntax error
::
pyston
::
raiseSyntaxError
(
buf
,
node_at
->
lineno
,
node_at
->
col_offset
,
file
,
""
);
}
void
raiseFutureImportErrorNotFound
(
const
char
*
file
,
AST
*
node
,
const
char
*
name
)
{
raiseSyntaxError
(
file
,
node
,
"future feature %s is not defined"
,
name
);
}
void
raiseFutureImportErrorNotBeginning
(
const
char
*
file
,
AST
*
node
)
{
raiseSyntaxError
(
file
,
node
,
"from __future__ imports must occur at the beginning of the file"
);
}
class
BadFutureImportVisitor
:
public
NoopASTVisitor
{
public:
virtual
bool
visit_importfrom
(
AST_ImportFrom
*
node
)
{
if
(
node
->
module
==
"__future__"
)
{
raiseFutureImportErrorNotBeginning
(
file
,
node
);
}
return
true
;
}
// TODO optimization: have it skip things like expressions that you know
// there is no need to descend into
BadFutureImportVisitor
(
const
char
*
file
)
:
file
(
file
)
{}
const
char
*
file
;
};
inline
bool
is_stmt_string
(
AST_stmt
*
stmt
)
{
return
stmt
->
type
==
AST_TYPE
::
Expr
&&
static_cast
<
AST_Expr
*>
(
stmt
)
->
value
->
type
==
AST_TYPE
::
Str
;
}
FutureFlags
getFutureFlags
(
AST_Module
*
m
,
const
char
*
file
)
{
FutureFlags
ff
=
0
;
// Set the defaults for the future flags depending on what version we are
for
(
const
std
::
pair
<
std
::
string
,
FutureOption
>&
p
:
future_options
)
{
if
(
PYTHON_VERSION_HEX
>=
p
.
second
.
mandatory_version_hex
)
{
ff
|=
p
.
second
.
ff_mask
;
}
}
// Find all the __future__ imports, raising an error for those that do not
// occur at the beginning of the file.
bool
future_import_allowed
=
true
;
BadFutureImportVisitor
import_visitor
(
file
);
for
(
int
i
=
0
;
i
<
m
->
body
.
size
();
i
++
)
{
AST_stmt
*
stmt
=
m
->
body
[
i
];
if
(
stmt
->
type
==
AST_TYPE
::
ImportFrom
&&
static_cast
<
AST_ImportFrom
*>
(
stmt
)
->
module
==
"__future__"
)
{
if
(
future_import_allowed
)
{
// We have a `from __future__` import statement, and we are
// still at the top of the file, so just set the appropriate
// future flag for each imported option.
for
(
AST_alias
*
alias
:
static_cast
<
AST_ImportFrom
*>
(
stmt
)
->
names
)
{
const
std
::
string
&
option_name
=
alias
->
name
;
auto
iter
=
future_options
.
find
(
option_name
);
if
(
iter
==
future_options
.
end
())
{
// If it's not one of the available options, throw an error.
// Note: the __future__ module also exposes "all_feature_names",
// but you still can't import that using a from-import, so we
// don't need to worry about that here.
raiseFutureImportErrorNotFound
(
file
,
alias
,
option_name
.
c_str
());
}
else
{
const
FutureOption
&
fo
=
iter
->
second
;
if
(
PYTHON_VERSION_HEX
>=
fo
.
mandatory_version_hex
)
{
ff
|=
fo
.
ff_mask
;
}
else
{
raiseFutureImportErrorNotFound
(
file
,
alias
,
option_name
.
c_str
());
}
}
}
}
else
{
raiseFutureImportErrorNotBeginning
(
file
,
stmt
);
}
}
else
{
// A docstring is allowed at the beginning of a module; otherwise,
// we cannot permit any __future__ import after this point.
if
(
i
>
0
||
!
is_stmt_string
(
stmt
))
{
// Recurse on the node and throw an error if it has any
// `from __future__` import statement.
stmt
->
accept
(
&
import_visitor
);
future_import_allowed
=
false
;
}
}
}
return
ff
;
}
}
src/codegen/irgen/future.h
0 → 100644
View file @
ccb7cff9
// Copyright (c) 2014 Dropbox, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef PYSTON_CODEGEN_IRGEN_FUTURE_H
#define PYSTON_CODEGEN_IRGEN_FUTURE_H
#include <map>
#include "core/ast.h"
#include "core/options.h"
#include "core/types.h"
namespace
pyston
{
#define FF_ABSOLUTE_IMPORT 0x01
#define FF_DIVISION 0x02
#define FF_GENERATOR 0x04
#define FF_UNICODE_LITERALS 0x08
#define FF_PRINT_FUNCTIONS 0x10
#define FF_NESTED_SCOPES 0x20
#define FF_WITH_STATEMENT 0x40
struct
FutureOption
{
int
optional_version_hex
;
int
mandatory_version_hex
;
int
ff_mask
;
};
typedef
int
FutureFlags
;
const
std
::
map
<
std
::
string
,
FutureOption
>
future_options
=
{
{
"absolute_import"
,
{
version_hex
(
2
,
5
,
0
),
version_hex
(
3
,
0
,
0
),
FF_ABSOLUTE_IMPORT
}
},
{
"division"
,
{
version_hex
(
2
,
2
,
0
),
version_hex
(
3
,
0
,
0
),
FF_DIVISION
}
},
{
"generators"
,
{
version_hex
(
2
,
2
,
0
),
version_hex
(
3
,
0
,
0
),
FF_GENERATOR
}
},
{
"unicode_literals"
,
{
version_hex
(
2
,
6
,
0
),
version_hex
(
3
,
0
,
0
),
FF_UNICODE_LITERALS
}
},
{
"print_functions"
,
{
version_hex
(
2
,
6
,
0
),
version_hex
(
3
,
0
,
0
),
FF_PRINT_FUNCTIONS
}
},
{
"nested_scopes"
,
{
version_hex
(
2
,
1
,
0
),
version_hex
(
2
,
2
,
0
),
FF_NESTED_SCOPES
}
},
{
"with_statement"
,
{
version_hex
(
2
,
5
,
0
),
version_hex
(
3
,
6
,
0
),
FF_WITH_STATEMENT
}
}
};
// Loop through import statements to find __future__ imports throwing errors for
// bad __future__ imports. Returns the futures that are turned on. This is used
// for irgeneration; the parser still has to handle some futures on its own,
// when they are relevant for the parser.
FutureFlags
getFutureFlags
(
AST_Module
*
m
,
const
char
*
file
);
}
#endif
src/codegen/irgen/hooks.cpp
View file @
ccb7cff9
...
...
@@ -23,6 +23,7 @@
#include "codegen/codegen.h"
#include "codegen/compvars.h"
#include "codegen/irgen.h"
#include "codegen/irgen/future.h"
#include "codegen/irgen/util.h"
#include "codegen/llvm_interpreter.h"
#include "codegen/osrentry.h"
...
...
@@ -236,6 +237,8 @@ void compileAndRunModule(AST_Module* m, BoxedModule* bm) {
Timer
_t
(
"for compileModule()"
);
FutureFlags
ff
=
getFutureFlags
(
m
,
bm
->
fn
.
c_str
());
ScopingAnalysis
*
scoping
=
runScopingAnalysis
(
m
);
SourceInfo
*
si
=
new
SourceInfo
(
bm
,
scoping
,
m
,
m
->
body
);
...
...
src/codegen/irgen/irgenerator.cpp
View file @
ccb7cff9
...
...
@@ -250,12 +250,6 @@ private:
OpInfo
getEmptyOpInfo
(
ExcInfo
exc_info
)
{
return
OpInfo
(
irstate
->
getEffortLevel
(),
NULL
,
exc_info
);
}
// Helper function:
void
raiseSyntaxError
(
const
char
*
msg
,
AST
*
node_at
)
{
::
pyston
::
raiseSyntaxError
(
msg
,
node_at
->
lineno
,
node_at
->
col_offset
,
irstate
->
getSourceInfo
()
->
parent_module
->
fn
,
irstate
->
getLLVMFunction
()
->
getName
());
}
void
createExprTypeGuard
(
llvm
::
Value
*
check_val
,
AST_expr
*
node
,
CompilerVariable
*
node_value
)
{
assert
(
check_val
->
getType
()
==
g
.
i1
);
...
...
@@ -1579,14 +1573,6 @@ private:
if
(
state
==
PARTIAL
)
return
;
if
(
node
->
module
==
"__future__"
)
{
// TODO I'm not sure that it's safe to raise an exception here, since I think
// there will be things that end up not getting cleaned up.
// Then again, there are a huge number of things that don't get cleaned up even
// if an exception doesn't get thrown...
raiseSyntaxError
(
"the __future__ module is not supported yet"
,
node
);
}
assert
(
node
->
level
==
0
);
llvm
::
Value
*
imported_v
...
...
test/tests/future_non_existent.py
0 → 100644
View file @
ccb7cff9
from
__future__
import
rvalue_references
# should cause syntax error
test/tests/future_not_at_beginning.py
0 → 100644
View file @
ccb7cff9
"docstring"
"not a docstring"
from
__future__
import
division
# should cause syntax error
test/tests/future_not_at_beginning2.py
0 → 100644
View file @
ccb7cff9
"docstring"
def
f
():
from
__future__
import
division
# should cause syntax error
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