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
5a645879
Commit
5a645879
authored
Jul 21, 2014
by
Marius Wachtler
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add support for generator arguments
kwargs are unsupported for now
parent
ecfd7589
Changes
22
Hide whitespace changes
Inline
Side-by-side
Showing
22 changed files
with
207 additions
and
106 deletions
+207
-106
src/analysis/function_analysis.cpp
src/analysis/function_analysis.cpp
+0
-19
src/analysis/function_analysis.h
src/analysis/function_analysis.h
+0
-2
src/analysis/scoping_analysis.cpp
src/analysis/scoping_analysis.cpp
+21
-0
src/analysis/scoping_analysis.h
src/analysis/scoping_analysis.h
+9
-0
src/codegen/codegen.h
src/codegen/codegen.h
+1
-1
src/codegen/compvars.cpp
src/codegen/compvars.cpp
+41
-9
src/codegen/compvars.h
src/codegen/compvars.h
+2
-2
src/codegen/irgen.cpp
src/codegen/irgen.cpp
+5
-1
src/codegen/irgen/hooks.cpp
src/codegen/irgen/hooks.cpp
+1
-1
src/codegen/irgen/irgenerator.cpp
src/codegen/irgen/irgenerator.cpp
+30
-25
src/codegen/llvm_interpreter.cpp
src/codegen/llvm_interpreter.cpp
+11
-6
src/codegen/llvm_interpreter.h
src/codegen/llvm_interpreter.h
+2
-1
src/codegen/runtime_hooks.cpp
src/codegen/runtime_hooks.cpp
+2
-2
src/codegen/runtime_hooks.h
src/codegen/runtime_hooks.h
+1
-1
src/core/types.h
src/core/types.h
+3
-0
src/runtime/builtin_modules/builtins.cpp
src/runtime/builtin_modules/builtins.cpp
+3
-1
src/runtime/generator.cpp
src/runtime/generator.cpp
+26
-12
src/runtime/generator.h
src/runtime/generator.h
+2
-2
src/runtime/objmodel.cpp
src/runtime/objmodel.cpp
+20
-6
src/runtime/types.cpp
src/runtime/types.cpp
+7
-5
src/runtime/types.h
src/runtime/types.h
+8
-4
test/tests/generators.py
test/tests/generators.py
+12
-6
No files found.
src/analysis/function_analysis.cpp
View file @
5a645879
...
@@ -31,25 +31,6 @@
...
@@ -31,25 +31,6 @@
namespace
pyston
{
namespace
pyston
{
class
YieldVisitor
:
public
NoopASTVisitor
{
public:
YieldVisitor
()
:
containsYield
(
false
)
{}
virtual
bool
visit_yield
(
AST_Yield
*
)
{
containsYield
=
true
;
return
true
;
}
bool
containsYield
;
};
bool
containsYield
(
AST
*
ast
)
{
YieldVisitor
visitor
;
ast
->
accept
(
&
visitor
);
return
visitor
.
containsYield
;
}
class
LivenessBBVisitor
:
public
NoopASTVisitor
{
class
LivenessBBVisitor
:
public
NoopASTVisitor
{
public:
public:
typedef
llvm
::
SmallSet
<
std
::
string
,
4
>
StrSet
;
typedef
llvm
::
SmallSet
<
std
::
string
,
4
>
StrSet
;
...
...
src/analysis/function_analysis.h
View file @
5a645879
...
@@ -77,8 +77,6 @@ public:
...
@@ -77,8 +77,6 @@ public:
bool
isPotentiallyUndefinedAfter
(
const
std
::
string
&
name
,
CFGBlock
*
block
);
bool
isPotentiallyUndefinedAfter
(
const
std
::
string
&
name
,
CFGBlock
*
block
);
};
};
bool
containsYield
(
AST
*
ast
);
LivenessAnalysis
*
computeLivenessInfo
(
CFG
*
);
LivenessAnalysis
*
computeLivenessInfo
(
CFG
*
);
PhiAnalysis
*
computeRequiredPhis
(
const
SourceInfo
::
ArgNames
&
,
CFG
*
,
LivenessAnalysis
*
,
ScopeInfo
*
scope_Info
);
PhiAnalysis
*
computeRequiredPhis
(
const
SourceInfo
::
ArgNames
&
,
CFG
*
,
LivenessAnalysis
*
,
ScopeInfo
*
scope_Info
);
}
}
...
...
src/analysis/scoping_analysis.cpp
View file @
5a645879
...
@@ -20,6 +20,24 @@
...
@@ -20,6 +20,24 @@
namespace
pyston
{
namespace
pyston
{
class
YieldVisitor
:
public
NoopASTVisitor
{
public:
YieldVisitor
()
:
containsYield
(
false
)
{}
virtual
bool
visit_yield
(
AST_Yield
*
)
{
containsYield
=
true
;
return
true
;
}
bool
containsYield
;
};
bool
containsYield
(
AST
*
ast
)
{
YieldVisitor
visitor
;
ast
->
accept
(
&
visitor
);
return
visitor
.
containsYield
;
}
static
bool
isCompilerCreatedName
(
const
std
::
string
&
name
)
{
static
bool
isCompilerCreatedName
(
const
std
::
string
&
name
)
{
return
name
[
0
]
==
'!'
||
name
[
0
]
==
'#'
;
return
name
[
0
]
==
'!'
||
name
[
0
]
==
'#'
;
}
}
...
@@ -388,6 +406,9 @@ ScopeInfo* ScopingAnalysis::analyzeSubtree(AST* node) {
...
@@ -388,6 +406,9 @@ ScopeInfo* ScopingAnalysis::analyzeSubtree(AST* node) {
ScopeInfo
*
rtn
=
scopes
[
node
];
ScopeInfo
*
rtn
=
scopes
[
node
];
assert
(
rtn
);
assert
(
rtn
);
rtn
->
setTakesGenerator
(
containsYield
(
node
));
return
rtn
;
return
rtn
;
}
}
...
...
src/analysis/scoping_analysis.h
View file @
5a645879
...
@@ -24,12 +24,16 @@ class AST_Module;
...
@@ -24,12 +24,16 @@ class AST_Module;
class
ScopeInfo
{
class
ScopeInfo
{
public:
public:
ScopeInfo
()
:
isGeneratorValue
(
false
)
{}
virtual
~
ScopeInfo
()
{}
virtual
~
ScopeInfo
()
{}
virtual
ScopeInfo
*
getParent
()
=
0
;
virtual
ScopeInfo
*
getParent
()
=
0
;
virtual
bool
createsClosure
()
=
0
;
virtual
bool
createsClosure
()
=
0
;
virtual
bool
takesClosure
()
=
0
;
virtual
bool
takesClosure
()
=
0
;
virtual
bool
takesGenerator
()
{
return
isGeneratorValue
;
}
virtual
void
setTakesGenerator
(
bool
b
=
true
)
{
isGeneratorValue
=
b
;
}
virtual
bool
refersToGlobal
(
const
std
::
string
&
name
)
=
0
;
virtual
bool
refersToGlobal
(
const
std
::
string
&
name
)
=
0
;
virtual
bool
refersToClosure
(
const
std
::
string
name
)
=
0
;
virtual
bool
refersToClosure
(
const
std
::
string
name
)
=
0
;
virtual
bool
saveInClosure
(
const
std
::
string
name
)
=
0
;
virtual
bool
saveInClosure
(
const
std
::
string
name
)
=
0
;
...
@@ -38,6 +42,9 @@ public:
...
@@ -38,6 +42,9 @@ public:
// the metaclass constructor.
// the metaclass constructor.
// An error to call this on a non-classdef node.
// An error to call this on a non-classdef node.
virtual
const
std
::
unordered_set
<
std
::
string
>&
getClassDefLocalNames
()
=
0
;
virtual
const
std
::
unordered_set
<
std
::
string
>&
getClassDefLocalNames
()
=
0
;
protected:
bool
isGeneratorValue
;
};
};
class
ScopingAnalysis
{
class
ScopingAnalysis
{
...
@@ -58,6 +65,8 @@ public:
...
@@ -58,6 +65,8 @@ public:
};
};
ScopingAnalysis
*
runScopingAnalysis
(
AST_Module
*
m
);
ScopingAnalysis
*
runScopingAnalysis
(
AST_Module
*
m
);
bool
containsYield
(
AST
*
ast
);
}
}
#endif
#endif
src/codegen/codegen.h
View file @
5a645879
...
@@ -70,7 +70,7 @@ struct GlobalState {
...
@@ -70,7 +70,7 @@ struct GlobalState {
llvm
::
Type
*
llvm_flavor_type
,
*
llvm_flavor_type_ptr
;
llvm
::
Type
*
llvm_flavor_type
,
*
llvm_flavor_type_ptr
;
llvm
::
Type
*
llvm_opaque_type
;
llvm
::
Type
*
llvm_opaque_type
;
llvm
::
Type
*
llvm_str_type_ptr
;
llvm
::
Type
*
llvm_str_type_ptr
;
llvm
::
Type
*
llvm_clfunction_type_ptr
,
*
llvm_closure_type_ptr
,
*
llvm_
func
_type_ptr
;
llvm
::
Type
*
llvm_clfunction_type_ptr
,
*
llvm_closure_type_ptr
,
*
llvm_
generator
_type_ptr
;
llvm
::
Type
*
llvm_module_type_ptr
,
*
llvm_bool_type_ptr
;
llvm
::
Type
*
llvm_module_type_ptr
,
*
llvm_bool_type_ptr
;
llvm
::
Type
*
i1
,
*
i8
,
*
i8_ptr
,
*
i32
,
*
i64
,
*
void_
,
*
double_
;
llvm
::
Type
*
i1
,
*
i8
,
*
i8_ptr
,
*
i32
,
*
i64
,
*
void_
,
*
double_
;
llvm
::
Type
*
vector_ptr
;
llvm
::
Type
*
vector_ptr
;
...
...
src/codegen/compvars.cpp
View file @
5a645879
...
@@ -519,19 +519,31 @@ ConcreteCompilerVariable* UnknownType::nonzero(IREmitter& emitter, const OpInfo&
...
@@ -519,19 +519,31 @@ ConcreteCompilerVariable* UnknownType::nonzero(IREmitter& emitter, const OpInfo&
}
}
CompilerVariable
*
makeFunction
(
IREmitter
&
emitter
,
CLFunction
*
f
,
CompilerVariable
*
closure
,
CompilerVariable
*
makeFunction
(
IREmitter
&
emitter
,
CLFunction
*
f
,
CompilerVariable
*
closure
,
const
std
::
vector
<
ConcreteCompilerVariable
*>&
defaults
)
{
CompilerVariable
*
generator
,
const
std
::
vector
<
ConcreteCompilerVariable
*>&
defaults
)
{
// Unlike the CLFunction*, which can be shared between recompilations, the Box* around it
// Unlike the CLFunction*, which can be shared between recompilations, the Box* around it
// should be created anew every time the functiondef is encountered
// should be created anew every time the functiondef is encountered
llvm
::
Value
*
closure_v
;
llvm
::
Value
*
closure_v
;
ConcreteCompilerVariable
*
converted
=
NULL
;
ConcreteCompilerVariable
*
converted
Closure
=
NULL
;
if
(
closure
)
{
if
(
closure
)
{
converted
=
closure
->
makeConverted
(
emitter
,
closure
->
getConcreteType
());
converted
Closure
=
closure
->
makeConverted
(
emitter
,
closure
->
getConcreteType
());
closure_v
=
converted
->
getValue
();
closure_v
=
converted
Closure
->
getValue
();
}
else
{
}
else
{
closure_v
=
embedConstantPtr
(
nullptr
,
g
.
llvm_closure_type_ptr
);
closure_v
=
embedConstantPtr
(
nullptr
,
g
.
llvm_closure_type_ptr
);
}
}
llvm
::
Value
*
generator_v
;
ConcreteCompilerVariable
*
convertedGenerator
=
NULL
;
if
(
generator
&&
generator
!=
(
CompilerVariable
*
)
1
)
{
convertedGenerator
=
generator
->
makeConverted
(
emitter
,
generator
->
getConcreteType
());
generator_v
=
convertedGenerator
->
getValue
();
// ugly hack to allow to pass a BoxedFunction* instead of a BoxedGenerator*
generator_v
=
emitter
.
getBuilder
()
->
CreateBitCast
(
generator_v
,
g
.
llvm_generator_type_ptr
);
}
else
{
generator_v
=
embedConstantPtr
(
nullptr
,
g
.
llvm_generator_type_ptr
);
}
llvm
::
Value
*
scratch
;
llvm
::
Value
*
scratch
;
if
(
defaults
.
size
())
{
if
(
defaults
.
size
())
{
scratch
=
emitter
.
getScratch
(
defaults
.
size
()
*
sizeof
(
Box
*
));
scratch
=
emitter
.
getScratch
(
defaults
.
size
()
*
sizeof
(
Box
*
));
...
@@ -548,11 +560,14 @@ CompilerVariable* makeFunction(IREmitter& emitter, CLFunction* f, CompilerVariab
...
@@ -548,11 +560,14 @@ CompilerVariable* makeFunction(IREmitter& emitter, CLFunction* f, CompilerVariab
}
}
llvm
::
Value
*
boxed
=
emitter
.
getBuilder
()
->
CreateCall
(
llvm
::
Value
*
boxed
=
emitter
.
getBuilder
()
->
CreateCall
(
g
.
funcs
.
boxCLFunction
,
std
::
vector
<
llvm
::
Value
*>
{
embedConstantPtr
(
f
,
g
.
llvm_clfunction_type_ptr
),
closure_v
,
g
.
funcs
.
boxCLFunction
,
scratch
,
getConstantInt
(
defaults
.
size
(),
g
.
i64
)
});
std
::
vector
<
llvm
::
Value
*>
{
embedConstantPtr
(
f
,
g
.
llvm_clfunction_type_ptr
),
closure_v
,
generator_v
,
scratch
,
getConstantInt
(
defaults
.
size
(),
g
.
i64
)
});
if
(
converted
)
converted
->
decvref
(
emitter
);
if
(
convertedClosure
)
convertedClosure
->
decvref
(
emitter
);
if
(
convertedGenerator
)
convertedGenerator
->
decvref
(
emitter
);
return
new
ConcreteCompilerVariable
(
typeFromClass
(
function_cls
),
boxed
,
true
);
return
new
ConcreteCompilerVariable
(
typeFromClass
(
function_cls
),
boxed
,
true
);
}
}
...
@@ -1201,6 +1216,23 @@ public:
...
@@ -1201,6 +1216,23 @@ public:
}
_CLOSURE
;
}
_CLOSURE
;
ConcreteCompilerType
*
CLOSURE
=
&
_CLOSURE
;
ConcreteCompilerType
*
CLOSURE
=
&
_CLOSURE
;
class
GeneratorType
:
public
ConcreteCompilerType
{
public:
llvm
::
Type
*
llvmType
()
{
return
g
.
llvm_generator_type_ptr
;
}
std
::
string
debugName
()
{
return
"generator"
;
}
virtual
ConcreteCompilerType
*
getConcreteType
()
{
return
this
;
}
virtual
ConcreteCompilerType
*
getBoxType
()
{
return
GENERATOR
;
}
virtual
void
drop
(
IREmitter
&
emitter
,
VAR
*
var
)
{
// pass
}
virtual
void
grab
(
IREmitter
&
emitter
,
VAR
*
var
)
{
// pass
}
}
_GENERATOR
;
ConcreteCompilerType
*
GENERATOR
=
&
_GENERATOR
;
class
StrConstantType
:
public
ValuedCompilerType
<
std
::
string
*>
{
class
StrConstantType
:
public
ValuedCompilerType
<
std
::
string
*>
{
public:
public:
std
::
string
debugName
()
{
return
"str_constant"
;
}
std
::
string
debugName
()
{
return
"str_constant"
;
}
...
...
src/codegen/compvars.h
View file @
5a645879
...
@@ -29,7 +29,7 @@ class CompilerType;
...
@@ -29,7 +29,7 @@ class CompilerType;
class
IREmitter
;
class
IREmitter
;
extern
ConcreteCompilerType
*
INT
,
*
BOXED_INT
,
*
FLOAT
,
*
BOXED_FLOAT
,
*
VOID
,
*
UNKNOWN
,
*
BOOL
,
*
STR
,
*
NONE
,
*
LIST
,
*
SLICE
,
extern
ConcreteCompilerType
*
INT
,
*
BOXED_INT
,
*
FLOAT
,
*
BOXED_FLOAT
,
*
VOID
,
*
UNKNOWN
,
*
BOOL
,
*
STR
,
*
NONE
,
*
LIST
,
*
SLICE
,
*
MODULE
,
*
DICT
,
*
BOOL
,
*
BOXED_BOOL
,
*
BOXED_TUPLE
,
*
SET
,
*
CLOSURE
;
*
MODULE
,
*
DICT
,
*
BOOL
,
*
BOXED_BOOL
,
*
BOXED_TUPLE
,
*
SET
,
*
CLOSURE
,
*
GENERATOR
;
extern
CompilerType
*
UNDEF
;
extern
CompilerType
*
UNDEF
;
class
CompilerType
{
class
CompilerType
{
...
@@ -316,7 +316,7 @@ ConcreteCompilerVariable* makeInt(int64_t);
...
@@ -316,7 +316,7 @@ ConcreteCompilerVariable* makeInt(int64_t);
ConcreteCompilerVariable
*
makeFloat
(
double
);
ConcreteCompilerVariable
*
makeFloat
(
double
);
ConcreteCompilerVariable
*
makeBool
(
bool
);
ConcreteCompilerVariable
*
makeBool
(
bool
);
CompilerVariable
*
makeStr
(
std
::
string
*
);
CompilerVariable
*
makeStr
(
std
::
string
*
);
CompilerVariable
*
makeFunction
(
IREmitter
&
emitter
,
CLFunction
*
,
CompilerVariable
*
closure
,
CompilerVariable
*
makeFunction
(
IREmitter
&
emitter
,
CLFunction
*
,
CompilerVariable
*
closure
,
CompilerVariable
*
generator
,
const
std
::
vector
<
ConcreteCompilerVariable
*>&
defaults
);
const
std
::
vector
<
ConcreteCompilerVariable
*>&
defaults
);
ConcreteCompilerVariable
*
undefVariable
();
ConcreteCompilerVariable
*
undefVariable
();
CompilerVariable
*
makeTuple
(
const
std
::
vector
<
CompilerVariable
*>&
elts
);
CompilerVariable
*
makeTuple
(
const
std
::
vector
<
CompilerVariable
*>&
elts
);
...
...
src/codegen/irgen.cpp
View file @
5a645879
...
@@ -513,7 +513,7 @@ static void emitBBs(IRGenState* irstate, const char* bb_type, GuardList& out_gua
...
@@ -513,7 +513,7 @@ static void emitBBs(IRGenState* irstate, const char* bb_type, GuardList& out_gua
assert
(
strcmp
(
"opt"
,
bb_type
)
==
0
);
assert
(
strcmp
(
"opt"
,
bb_type
)
==
0
);
if
(
ENABLE_REOPT
&&
effort
<
EffortLevel
::
MAXIMAL
&&
source
->
ast
!=
NULL
if
(
ENABLE_REOPT
&&
effort
<
EffortLevel
::
MAXIMAL
&&
source
->
ast
!=
NULL
&&
source
->
ast
->
type
!=
AST_TYPE
::
Module
&&
!
containsYield
(
source
->
ast
)
)
{
&&
source
->
ast
->
type
!=
AST_TYPE
::
Module
)
{
llvm
::
BasicBlock
*
preentry_bb
llvm
::
BasicBlock
*
preentry_bb
=
llvm
::
BasicBlock
::
Create
(
g
.
context
,
"pre_entry"
,
irstate
->
getLLVMFunction
(),
=
llvm
::
BasicBlock
::
Create
(
g
.
context
,
"pre_entry"
,
irstate
->
getLLVMFunction
(),
llvm_entry_blocks
[
source
->
cfg
->
getStartingBlock
()]);
llvm_entry_blocks
[
source
->
cfg
->
getStartingBlock
()]);
...
@@ -913,10 +913,14 @@ CompiledFunction* doCompile(SourceInfo* source, const OSREntryDescriptor* entry_
...
@@ -913,10 +913,14 @@ CompiledFunction* doCompile(SourceInfo* source, const OSREntryDescriptor* entry_
int
nargs
=
source
->
arg_names
.
totalParameters
();
int
nargs
=
source
->
arg_names
.
totalParameters
();
ASSERT
(
nargs
==
spec
->
arg_types
.
size
(),
"%d %ld"
,
nargs
,
spec
->
arg_types
.
size
());
ASSERT
(
nargs
==
spec
->
arg_types
.
size
(),
"%d %ld"
,
nargs
,
spec
->
arg_types
.
size
());
std
::
vector
<
llvm
::
Type
*>
llvm_arg_types
;
std
::
vector
<
llvm
::
Type
*>
llvm_arg_types
;
if
(
source
->
scoping
->
getScopeInfoForNode
(
source
->
ast
)
->
takesClosure
())
if
(
source
->
scoping
->
getScopeInfoForNode
(
source
->
ast
)
->
takesClosure
())
llvm_arg_types
.
push_back
(
g
.
llvm_closure_type_ptr
);
llvm_arg_types
.
push_back
(
g
.
llvm_closure_type_ptr
);
if
(
source
->
scoping
->
getScopeInfoForNode
(
source
->
ast
)
->
takesGenerator
())
llvm_arg_types
.
push_back
(
g
.
llvm_generator_type_ptr
);
if
(
entry_descriptor
==
NULL
)
{
if
(
entry_descriptor
==
NULL
)
{
for
(
int
i
=
0
;
i
<
nargs
;
i
++
)
{
for
(
int
i
=
0
;
i
<
nargs
;
i
++
)
{
if
(
i
==
3
)
{
if
(
i
==
3
)
{
...
...
src/codegen/irgen/hooks.cpp
View file @
5a645879
...
@@ -238,7 +238,7 @@ void compileAndRunModule(AST_Module* m, BoxedModule* bm) {
...
@@ -238,7 +238,7 @@ void compileAndRunModule(AST_Module* m, BoxedModule* bm) {
}
}
if
(
cf
->
is_interpreted
)
if
(
cf
->
is_interpreted
)
interpretFunction
(
cf
->
func
,
0
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
);
interpretFunction
(
cf
->
func
,
0
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
);
else
else
((
void
(
*
)())
cf
->
code
)();
((
void
(
*
)())
cf
->
code
)();
}
}
...
...
src/codegen/irgen/irgenerator.cpp
View file @
5a645879
...
@@ -206,6 +206,7 @@ static std::vector<const std::string*>* getKeywordNameStorage(AST_Call* node) {
...
@@ -206,6 +206,7 @@ static std::vector<const std::string*>* getKeywordNameStorage(AST_Call* node) {
static
const
std
::
string
CREATED_CLOSURE_NAME
=
"!created_closure"
;
static
const
std
::
string
CREATED_CLOSURE_NAME
=
"!created_closure"
;
static
const
std
::
string
PASSED_CLOSURE_NAME
=
"!passed_closure"
;
static
const
std
::
string
PASSED_CLOSURE_NAME
=
"!passed_closure"
;
static
const
std
::
string
PASSED_GENERATOR_NAME
=
"!passed_generator"
;
class
IRGeneratorImpl
:
public
IRGenerator
{
class
IRGeneratorImpl
:
public
IRGenerator
{
private:
private:
...
@@ -1019,29 +1020,21 @@ private:
...
@@ -1019,29 +1020,21 @@ private:
CompilerVariable
*
evalYield
(
AST_Yield
*
node
,
ExcInfo
exc_info
)
{
CompilerVariable
*
evalYield
(
AST_Yield
*
node
,
ExcInfo
exc_info
)
{
assert
(
state
!=
PARTIAL
);
assert
(
state
!=
PARTIAL
);
/*
AST_Name genName;
CompilerVariable
*
generator
=
_getFake
(
PASSED_GENERATOR_NAME
,
false
);
genName.id = "!__GENERATOR__";
ConcreteCompilerVariable
*
convertedGenerator
=
generator
->
makeConverted
(
emitter
,
generator
->
getBoxType
());
genName.ctx_type = AST_TYPE::Load;
CompilerVariable* generator = evalName(&genName, exc_info);
ConcreteCompilerVariable* convertedGenerator = generator->makeConverted(emitter,
generator->getBoxType());
generator->decvref(emitter);
*/
CompilerVariable
*
value
=
node
->
value
?
evalExpr
(
node
->
value
,
exc_info
)
:
getNone
();
CompilerVariable
*
value
=
node
->
value
?
evalExpr
(
node
->
value
,
exc_info
)
:
getNone
();
ConcreteCompilerVariable
*
convertedValue
=
value
->
makeConverted
(
emitter
,
value
->
getBoxType
());
ConcreteCompilerVariable
*
convertedValue
=
value
->
makeConverted
(
emitter
,
value
->
getBoxType
());
value
->
decvref
(
emitter
);
value
->
decvref
(
emitter
);
llvm
::
Value
*
rtn
=
emitter
.
createCall2
(
exc_info
,
g
.
funcs
.
yield
,
converted
Value
->
getValue
(),
llvm
::
Value
*
rtn
=
emitter
.
createCall2
(
exc_info
,
g
.
funcs
.
yield
,
converted
Generator
->
getValue
(),
convertedValue
->
getValue
()).
getInstruction
();
convertedValue
->
getValue
()).
getInstruction
();
//
convertedGenerator->decvref(emitter);
convertedGenerator
->
decvref
(
emitter
);
convertedValue
->
decvref
(
emitter
);
convertedValue
->
decvref
(
emitter
);
return
new
ConcreteCompilerVariable
(
UNKNOWN
,
rtn
,
true
);
return
new
ConcreteCompilerVariable
(
UNKNOWN
,
rtn
,
true
);
// CompilerVariable* value = evalExpr(node->value, exc_info);
// return getNone();
}
}
ConcreteCompilerVariable
*
unboxVar
(
ConcreteCompilerType
*
t
,
llvm
::
Value
*
v
,
bool
grabbed
)
{
ConcreteCompilerVariable
*
unboxVar
(
ConcreteCompilerType
*
t
,
llvm
::
Value
*
v
,
bool
grabbed
)
{
...
@@ -1481,7 +1474,7 @@ private:
...
@@ -1481,7 +1474,7 @@ private:
// one reason to do this is to pass the closure through if necessary,
// one reason to do this is to pass the closure through if necessary,
// but since the classdef can't create its own closure, shouldn't need to explicitly
// but since the classdef can't create its own closure, shouldn't need to explicitly
// create that scope to pass the closure through.
// create that scope to pass the closure through.
CompilerVariable
*
func
=
makeFunction
(
emitter
,
cl
,
created_closure
,
{});
CompilerVariable
*
func
=
makeFunction
(
emitter
,
cl
,
created_closure
,
0
,
{});
CompilerVariable
*
attr_dict
=
func
->
call
(
emitter
,
getEmptyOpInfo
(
exc_info
),
ArgPassSpec
(
0
),
{},
NULL
);
CompilerVariable
*
attr_dict
=
func
->
call
(
emitter
,
getEmptyOpInfo
(
exc_info
),
ArgPassSpec
(
0
),
{},
NULL
);
...
@@ -1582,19 +1575,21 @@ private:
...
@@ -1582,19 +1575,21 @@ private:
assert
(
created_closure
);
assert
(
created_closure
);
}
}
CompilerVariable
*
func
=
makeFunction
(
emitter
,
cl
,
created_closure
,
defaults
);
CompilerVariable
*
func
=
makeFunction
(
emitter
,
cl
,
created_closure
,
(
ConcreteCompilerVariable
*
)
scope_info
->
takesGenerator
(),
defaults
);
for
(
auto
d
:
defaults
)
{
d
->
decvref
(
emitter
);
}
if
(
containsYield
(
node
))
{
if
(
scope_info
->
takesGenerator
(
))
{
ConcreteCompilerVariable
*
converted
=
func
->
makeConverted
(
emitter
,
func
->
getBoxType
());
ConcreteCompilerVariable
*
converted
=
func
->
makeConverted
(
emitter
,
func
->
getBoxType
());
CLFunction
*
clFunc
=
boxRTFunction
((
void
*
)
createGenerator
,
UNKNOWN
,
1
,
1
,
false
,
false
);
CLFunction
*
clFunc
=
boxRTFunction
((
void
*
)
createGenerator
,
UNKNOWN
,
args
->
args
.
size
(),
func
=
makeFunction
(
emitter
,
clFunc
,
NULL
,
{
converted
});
args
->
defaults
.
size
(),
args
->
vararg
.
size
(),
args
->
kwarg
.
size
());
func
=
makeFunction
(
emitter
,
clFunc
,
NULL
,
(
CompilerVariable
*
)
converted
,
defaults
);
converted
->
decvref
(
emitter
);
converted
->
decvref
(
emitter
);
}
}
for
(
auto
d
:
defaults
)
{
d
->
decvref
(
emitter
);
}
return
func
;
return
func
;
}
}
...
@@ -2039,7 +2034,8 @@ private:
...
@@ -2039,7 +2034,8 @@ private:
}
}
bool
allowableFakeEndingSymbol
(
const
std
::
string
&
name
)
{
bool
allowableFakeEndingSymbol
(
const
std
::
string
&
name
)
{
return
startswith
(
name
,
"!is_defined"
)
||
name
==
PASSED_CLOSURE_NAME
||
name
==
CREATED_CLOSURE_NAME
;
return
startswith
(
name
,
"!is_defined"
)
||
name
==
PASSED_CLOSURE_NAME
||
name
==
CREATED_CLOSURE_NAME
||
name
==
PASSED_GENERATOR_NAME
;
}
}
void
endBlock
(
State
new_state
)
{
void
endBlock
(
State
new_state
)
{
...
@@ -2148,6 +2144,7 @@ public:
...
@@ -2148,6 +2144,7 @@ public:
if
(
myblock
->
successors
.
size
()
==
0
)
{
if
(
myblock
->
successors
.
size
()
==
0
)
{
st
->
erase
(
CREATED_CLOSURE_NAME
);
st
->
erase
(
CREATED_CLOSURE_NAME
);
st
->
erase
(
PASSED_CLOSURE_NAME
);
st
->
erase
(
PASSED_CLOSURE_NAME
);
st
->
erase
(
PASSED_GENERATOR_NAME
);
assert
(
st
->
size
()
==
0
);
// shouldn't have anything live if there are no successors!
assert
(
st
->
size
()
==
0
);
// shouldn't have anything live if there are no successors!
return
EndingState
(
st
,
phi_st
,
curblock
);
return
EndingState
(
st
,
phi_st
,
curblock
);
}
else
if
(
myblock
->
successors
.
size
()
>
1
)
{
}
else
if
(
myblock
->
successors
.
size
()
>
1
)
{
...
@@ -2179,6 +2176,8 @@ public:
...
@@ -2179,6 +2176,8 @@ public:
ending_type
=
getPassedClosureType
();
ending_type
=
getPassedClosureType
();
}
else
if
(
it
->
first
==
CREATED_CLOSURE_NAME
)
{
}
else
if
(
it
->
first
==
CREATED_CLOSURE_NAME
)
{
ending_type
=
getCreatedClosureType
();
ending_type
=
getCreatedClosureType
();
}
else
if
(
it
->
first
==
PASSED_GENERATOR_NAME
)
{
ending_type
=
GENERATOR
;
}
else
{
}
else
{
ending_type
=
types
->
getTypeAtBlockEnd
(
it
->
first
,
myblock
);
ending_type
=
types
->
getTypeAtBlockEnd
(
it
->
first
,
myblock
);
}
}
...
@@ -2231,6 +2230,7 @@ public:
...
@@ -2231,6 +2230,7 @@ public:
llvm
::
Value
*
passed_closure
=
NULL
;
llvm
::
Value
*
passed_closure
=
NULL
;
llvm
::
Function
::
arg_iterator
AI
=
irstate
->
getLLVMFunction
()
->
arg_begin
();
llvm
::
Function
::
arg_iterator
AI
=
irstate
->
getLLVMFunction
()
->
arg_begin
();
if
(
scope_info
->
takesClosure
())
{
if
(
scope_info
->
takesClosure
())
{
passed_closure
=
AI
;
passed_closure
=
AI
;
_setFake
(
PASSED_CLOSURE_NAME
,
new
ConcreteCompilerVariable
(
getPassedClosureType
(),
AI
,
true
));
_setFake
(
PASSED_CLOSURE_NAME
,
new
ConcreteCompilerVariable
(
getPassedClosureType
(),
AI
,
true
));
...
@@ -2245,6 +2245,11 @@ public:
...
@@ -2245,6 +2245,11 @@ public:
_setFake
(
CREATED_CLOSURE_NAME
,
new
ConcreteCompilerVariable
(
getCreatedClosureType
(),
new_closure
,
true
));
_setFake
(
CREATED_CLOSURE_NAME
,
new
ConcreteCompilerVariable
(
getCreatedClosureType
(),
new_closure
,
true
));
}
}
if
(
scope_info
->
takesGenerator
())
{
_setFake
(
PASSED_GENERATOR_NAME
,
new
ConcreteCompilerVariable
(
GENERATOR
,
AI
,
true
));
++
AI
;
}
std
::
vector
<
llvm
::
Value
*>
python_parameters
;
std
::
vector
<
llvm
::
Value
*>
python_parameters
;
for
(
int
i
=
0
;
i
<
arg_types
.
size
();
i
++
)
{
for
(
int
i
=
0
;
i
<
arg_types
.
size
();
i
++
)
{
...
...
src/codegen/llvm_interpreter.cpp
View file @
5a645879
...
@@ -257,7 +257,8 @@ const LineInfo* getLineInfoForInterpretedFrame(void* frame_ptr) {
...
@@ -257,7 +257,8 @@ const LineInfo* getLineInfoForInterpretedFrame(void* frame_ptr) {
}
}
}
}
Box
*
interpretFunction
(
llvm
::
Function
*
f
,
int
nargs
,
Box
*
closure
,
Box
*
arg1
,
Box
*
arg2
,
Box
*
arg3
,
Box
**
args
)
{
Box
*
interpretFunction
(
llvm
::
Function
*
f
,
int
nargs
,
Box
*
closure
,
Box
*
generator
,
Box
*
arg1
,
Box
*
arg2
,
Box
*
arg3
,
Box
**
args
)
{
assert
(
f
);
assert
(
f
);
#ifdef TIME_INTERPRETS
#ifdef TIME_INTERPRETS
...
@@ -281,20 +282,24 @@ Box* interpretFunction(llvm::Function* f, int nargs, Box* closure, Box* arg1, Bo
...
@@ -281,20 +282,24 @@ Box* interpretFunction(llvm::Function* f, int nargs, Box* closure, Box* arg1, Bo
int
arg_num
=
-
1
;
int
arg_num
=
-
1
;
int
closure_indicator
=
closure
?
1
:
0
;
int
closure_indicator
=
closure
?
1
:
0
;
int
generator_indicator
=
generator
?
1
:
0
;
int
argOffset
=
closure_indicator
+
generator_indicator
;
for
(
llvm
::
Argument
&
arg
:
f
->
args
())
{
for
(
llvm
::
Argument
&
arg
:
f
->
args
())
{
arg_num
++
;
arg_num
++
;
if
(
arg_num
==
0
&&
closure
)
if
(
arg_num
==
0
&&
closure
)
symbols
.
insert
(
std
::
make_pair
(
static_cast
<
llvm
::
Value
*>
(
&
arg
),
Val
(
closure
)));
symbols
.
insert
(
std
::
make_pair
(
static_cast
<
llvm
::
Value
*>
(
&
arg
),
Val
(
closure
)));
else
if
(
arg_num
==
0
+
closure_indicator
)
else
if
((
arg_num
==
0
||
(
arg_num
==
1
&&
closure
))
&&
generator
)
symbols
.
insert
(
std
::
make_pair
(
static_cast
<
llvm
::
Value
*>
(
&
arg
),
Val
(
generator
)));
else
if
(
arg_num
==
0
+
argOffset
)
symbols
.
insert
(
std
::
make_pair
(
static_cast
<
llvm
::
Value
*>
(
&
arg
),
Val
(
arg1
)));
symbols
.
insert
(
std
::
make_pair
(
static_cast
<
llvm
::
Value
*>
(
&
arg
),
Val
(
arg1
)));
else
if
(
arg_num
==
1
+
closure_indicator
)
else
if
(
arg_num
==
1
+
argOffset
)
symbols
.
insert
(
std
::
make_pair
(
static_cast
<
llvm
::
Value
*>
(
&
arg
),
Val
(
arg2
)));
symbols
.
insert
(
std
::
make_pair
(
static_cast
<
llvm
::
Value
*>
(
&
arg
),
Val
(
arg2
)));
else
if
(
arg_num
==
2
+
closure_indicator
)
else
if
(
arg_num
==
2
+
argOffset
)
symbols
.
insert
(
std
::
make_pair
(
static_cast
<
llvm
::
Value
*>
(
&
arg
),
Val
(
arg3
)));
symbols
.
insert
(
std
::
make_pair
(
static_cast
<
llvm
::
Value
*>
(
&
arg
),
Val
(
arg3
)));
else
{
else
{
assert
(
arg_num
==
3
+
closure_indicator
);
assert
(
arg_num
==
3
+
argOffset
);
assert
(
f
->
getArgumentList
().
size
()
==
4
+
closure_indicator
);
assert
(
f
->
getArgumentList
().
size
()
==
4
+
argOffset
);
assert
(
f
->
getArgumentList
().
back
().
getType
()
==
g
.
llvm_value_type_ptr
->
getPointerTo
());
assert
(
f
->
getArgumentList
().
back
().
getType
()
==
g
.
llvm_value_type_ptr
->
getPointerTo
());
symbols
.
insert
(
std
::
make_pair
(
static_cast
<
llvm
::
Value
*>
(
&
arg
),
Val
((
int64_t
)
args
)));
symbols
.
insert
(
std
::
make_pair
(
static_cast
<
llvm
::
Value
*>
(
&
arg
),
Val
((
int64_t
)
args
)));
// printf("loading %%4 with %p\n", (void*)args);
// printf("loading %%4 with %p\n", (void*)args);
...
...
src/codegen/llvm_interpreter.h
View file @
5a645879
...
@@ -25,7 +25,8 @@ class Box;
...
@@ -25,7 +25,8 @@ class Box;
class
GCVisitor
;
class
GCVisitor
;
class
LineInfo
;
class
LineInfo
;
Box
*
interpretFunction
(
llvm
::
Function
*
f
,
int
nargs
,
Box
*
closure
,
Box
*
arg1
,
Box
*
arg2
,
Box
*
arg3
,
Box
**
args
);
Box
*
interpretFunction
(
llvm
::
Function
*
f
,
int
nargs
,
Box
*
closure
,
Box
*
generator
,
Box
*
arg1
,
Box
*
arg2
,
Box
*
arg3
,
Box
**
args
);
void
gatherInterpreterRoots
(
GCVisitor
*
visitor
);
void
gatherInterpreterRoots
(
GCVisitor
*
visitor
);
const
LineInfo
*
getLineInfoForInterpretedFrame
(
void
*
frame_ptr
);
const
LineInfo
*
getLineInfoForInterpretedFrame
(
void
*
frame_ptr
);
...
...
src/codegen/runtime_hooks.cpp
View file @
5a645879
...
@@ -142,8 +142,8 @@ void initGlobalFuncs(GlobalState& g) {
...
@@ -142,8 +142,8 @@ void initGlobalFuncs(GlobalState& g) {
g
.
llvm_closure_type_ptr
=
g
.
stdlib_module
->
getTypeByName
(
"class.pyston::BoxedClosure"
)
->
getPointerTo
();
g
.
llvm_closure_type_ptr
=
g
.
stdlib_module
->
getTypeByName
(
"class.pyston::BoxedClosure"
)
->
getPointerTo
();
assert
(
g
.
llvm_closure_type_ptr
);
assert
(
g
.
llvm_closure_type_ptr
);
g
.
llvm_
func_type_ptr
=
g
.
stdlib_module
->
getTypeByName
(
"class.pyston::BoxedFunction
"
)
->
getPointerTo
();
g
.
llvm_
generator_type_ptr
=
g
.
stdlib_module
->
getTypeByName
(
"class.pyston::BoxedGenerator
"
)
->
getPointerTo
();
assert
(
g
.
llvm_
func
_type_ptr
);
assert
(
g
.
llvm_
generator
_type_ptr
);
#define GET(N) g.funcs.N = getFunc((void*)N, STRINGIFY(N))
#define GET(N) g.funcs.N = getFunc((void*)N, STRINGIFY(N))
...
...
src/codegen/runtime_hooks.h
View file @
5a645879
...
@@ -32,7 +32,7 @@ struct GlobalFuncs {
...
@@ -32,7 +32,7 @@ struct GlobalFuncs {
llvm
::
Value
*
boxInt
,
*
unboxInt
,
*
boxFloat
,
*
unboxFloat
,
*
boxStringPtr
,
*
boxCLFunction
,
*
unboxCLFunction
,
llvm
::
Value
*
boxInt
,
*
unboxInt
,
*
boxFloat
,
*
unboxFloat
,
*
boxStringPtr
,
*
boxCLFunction
,
*
unboxCLFunction
,
*
boxInstanceMethod
,
*
boxBool
,
*
unboxBool
,
*
createTuple
,
*
createDict
,
*
createList
,
*
createSlice
,
*
boxInstanceMethod
,
*
boxBool
,
*
unboxBool
,
*
createTuple
,
*
createDict
,
*
createList
,
*
createSlice
,
*
createUserClass
,
*
createClosure
,
*
createGenerator
;
*
createUserClass
,
*
createClosure
,
*
createGenerator
,
*
insideGenerator
;
llvm
::
Value
*
getattr
,
*
setattr
,
*
print
,
*
nonzero
,
*
binop
,
*
compare
,
*
augbinop
,
*
unboxedLen
,
*
getitem
,
*
getclsattr
,
llvm
::
Value
*
getattr
,
*
setattr
,
*
print
,
*
nonzero
,
*
binop
,
*
compare
,
*
augbinop
,
*
unboxedLen
,
*
getitem
,
*
getclsattr
,
*
yield
,
*
getGlobal
,
*
setitem
,
*
delitem
,
*
unaryop
,
*
import
,
*
repr
,
*
isinstance
;
*
yield
,
*
getGlobal
,
*
setitem
,
*
delitem
,
*
unaryop
,
*
import
,
*
repr
,
*
isinstance
;
...
...
src/core/types.h
View file @
5a645879
...
@@ -166,6 +166,7 @@ struct FunctionSpecialization {
...
@@ -166,6 +166,7 @@ struct FunctionSpecialization {
};
};
class
BoxedClosure
;
class
BoxedClosure
;
class
BoxedGenerator
;
struct
CompiledFunction
{
struct
CompiledFunction
{
private:
private:
public:
public:
...
@@ -178,6 +179,8 @@ public:
...
@@ -178,6 +179,8 @@ public:
union
{
union
{
Box
*
(
*
call
)(
Box
*
,
Box
*
,
Box
*
,
Box
**
);
Box
*
(
*
call
)(
Box
*
,
Box
*
,
Box
*
,
Box
**
);
Box
*
(
*
closure_call
)(
BoxedClosure
*
,
Box
*
,
Box
*
,
Box
*
,
Box
**
);
Box
*
(
*
closure_call
)(
BoxedClosure
*
,
Box
*
,
Box
*
,
Box
*
,
Box
**
);
Box
*
(
*
closure_generator_call
)(
BoxedClosure
*
,
BoxedGenerator
*
,
Box
*
,
Box
*
,
Box
*
,
Box
**
);
Box
*
(
*
generator_call
)(
BoxedGenerator
*
,
Box
*
,
Box
*
,
Box
*
,
Box
**
);
void
*
code
;
void
*
code
;
};
};
llvm
::
Value
*
llvm_code
;
// the llvm callable.
llvm
::
Value
*
llvm_code
;
// the llvm callable.
...
...
src/runtime/builtin_modules/builtins.cpp
View file @
5a645879
...
@@ -371,7 +371,8 @@ BoxedModule* builtins_module;
...
@@ -371,7 +371,8 @@ BoxedModule* builtins_module;
// TODO looks like CPython and pypy put this into an "exceptions" module:
// TODO looks like CPython and pypy put this into an "exceptions" module:
BoxedClass
*
Exception
,
*
AssertionError
,
*
AttributeError
,
*
TypeError
,
*
NameError
,
*
KeyError
,
*
IndexError
,
*
IOError
,
BoxedClass
*
Exception
,
*
AssertionError
,
*
AttributeError
,
*
TypeError
,
*
NameError
,
*
KeyError
,
*
IndexError
,
*
IOError
,
*
OSError
,
*
ZeroDivisionError
,
*
ValueError
,
*
UnboundLocalError
,
*
RuntimeError
,
*
ImportError
,
*
StopIteration
;
*
OSError
,
*
ZeroDivisionError
,
*
ValueError
,
*
UnboundLocalError
,
*
RuntimeError
,
*
ImportError
,
*
StopIteration
,
*
GeneratorExit
;
const
ObjectFlavor
exception_flavor
(
&
boxGCHandler
,
NULL
);
const
ObjectFlavor
exception_flavor
(
&
boxGCHandler
,
NULL
);
Box
*
exceptionNew1
(
BoxedClass
*
cls
)
{
Box
*
exceptionNew1
(
BoxedClass
*
cls
)
{
...
@@ -459,6 +460,7 @@ void setupBuiltins() {
...
@@ -459,6 +460,7 @@ void setupBuiltins() {
RuntimeError
=
makeBuiltinException
(
Exception
,
"RuntimeError"
);
RuntimeError
=
makeBuiltinException
(
Exception
,
"RuntimeError"
);
ImportError
=
makeBuiltinException
(
Exception
,
"ImportError"
);
ImportError
=
makeBuiltinException
(
Exception
,
"ImportError"
);
StopIteration
=
makeBuiltinException
(
Exception
,
"StopIteration"
);
StopIteration
=
makeBuiltinException
(
Exception
,
"StopIteration"
);
GeneratorExit
=
makeBuiltinException
(
Exception
,
"GeneratorExit"
);
repr_obj
=
new
BoxedFunction
(
boxRTFunction
((
void
*
)
repr
,
UNKNOWN
,
1
));
repr_obj
=
new
BoxedFunction
(
boxRTFunction
((
void
*
)
repr
,
UNKNOWN
,
1
));
builtins_module
->
giveAttr
(
"repr"
,
repr_obj
);
builtins_module
->
giveAttr
(
"repr"
,
repr_obj
);
...
...
src/runtime/generator.cpp
View file @
5a645879
...
@@ -32,7 +32,6 @@
...
@@ -32,7 +32,6 @@
namespace
pyston
{
namespace
pyston
{
BoxedGenerator
*
g_gen
;
// HACK REMOVE ME!!!
static
void
generatorEntry
(
BoxedGenerator
*
self
)
{
static
void
generatorEntry
(
BoxedGenerator
*
self
)
{
assert
(
self
->
cls
==
generator_cls
);
assert
(
self
->
cls
==
generator_cls
);
...
@@ -40,7 +39,9 @@ static void generatorEntry(BoxedGenerator* self) {
...
@@ -40,7 +39,9 @@ static void generatorEntry(BoxedGenerator* self) {
try
{
try
{
// call body of the generator
// call body of the generator
runtimeCall
(
self
->
function
,
ArgPassSpec
(
0
),
0
,
0
,
0
,
0
,
0
);
ArgPassSpec
argPassSpec
(
self
->
function
->
f
->
num_args
,
0
,
self
->
function
->
f
->
takes_varargs
,
self
->
function
->
f
->
takes_kwargs
);
runtimeCall
(
self
->
function
,
argPassSpec
,
self
->
arg1
,
self
->
arg2
,
self
->
arg3
,
self
->
args
,
0
);
}
catch
(
Box
*
e
)
{
}
catch
(
Box
*
e
)
{
// unhandled exception: propagate the exception to the caller
// unhandled exception: propagate the exception to the caller
self
->
exception
=
e
;
self
->
exception
=
e
;
...
@@ -85,19 +86,29 @@ Box* generatorThrow(Box* s, BoxedClass* e) {
...
@@ -85,19 +86,29 @@ Box* generatorThrow(Box* s, BoxedClass* e) {
return
generatorSend
(
self
,
None
);
return
generatorSend
(
self
,
None
);
}
}
Box
*
generatorClose
(
Box
*
s
)
{
assert
(
s
->
cls
==
generator_cls
);
BoxedGenerator
*
self
=
static_cast
<
BoxedGenerator
*>
(
s
);
// check if the generator already exited
if
(
self
->
entryExited
)
return
None
;
return
generatorThrow
(
self
,
GeneratorExit
);
}
Box
*
generatorNext
(
Box
*
s
)
{
Box
*
generatorNext
(
Box
*
s
)
{
return
generatorSend
(
s
,
None
);
return
generatorSend
(
s
,
None
);
}
}
extern
"C"
Box
*
yield
(
Box
*
obj
,
Box
*
value
)
{
extern
"C"
Box
*
yield
(
BoxedGenerator
*
obj
,
Box
*
value
)
{
obj
=
g_gen
;
assert
(
obj
->
cls
==
generator_cls
);
assert
(
obj
->
cls
==
generator_cls
);
BoxedGenerator
*
self
=
static_cast
<
BoxedGenerator
*>
(
obj
);
BoxedGenerator
*
self
=
static_cast
<
BoxedGenerator
*>
(
obj
);
self
->
returnValue
=
value
;
self
->
returnValue
=
value
;
swapcontext
(
&
self
->
context
,
&
self
->
returnContext
);
swapcontext
(
&
self
->
context
,
&
self
->
returnContext
);
// if the generator receives a exception from the caller we have throw it
// if the generator receives a exception from the caller we have t
o t
hrow it
if
(
self
->
exception
)
{
if
(
self
->
exception
)
{
Box
*
exception
=
self
->
exception
;
Box
*
exception
=
self
->
exception
;
self
->
exception
=
nullptr
;
self
->
exception
=
nullptr
;
...
@@ -106,15 +117,19 @@ extern "C" Box* yield(Box* obj, Box* value) {
...
@@ -106,15 +117,19 @@ extern "C" Box* yield(Box* obj, Box* value) {
return
self
->
returnValue
;
return
self
->
returnValue
;
}
}
extern
"C"
BoxedGenerator
*
createGenerator
(
BoxedFunction
*
function
)
{
extern
"C"
BoxedGenerator
*
createGenerator
(
BoxedFunction
*
function
,
Box
*
arg1
,
Box
*
arg2
,
Box
*
arg3
,
Box
**
args
)
{
assert
(
function
);
assert
(
function
);
assert
(
function
->
cls
==
function_cls
);
assert
(
function
->
cls
==
function_cls
);
return
new
BoxedGenerator
(
function
);
return
new
BoxedGenerator
(
function
,
arg1
,
arg2
,
arg3
,
args
);
}
}
extern
"C"
BoxedGenerator
::
BoxedGenerator
(
BoxedFunction
*
function
)
:
Box
(
&
generator_flavor
,
generator_cls
),
function
(
function
),
entryExited
(
false
),
returnValue
(
nullptr
),
extern
"C"
BoxedGenerator
::
BoxedGenerator
(
BoxedFunction
*
function
,
Box
*
arg1
,
Box
*
arg2
,
Box
*
arg3
,
Box
**
args
)
exception
(
nullptr
)
{
:
Box
(
&
generator_flavor
,
generator_cls
),
function
(
function
),
arg1
(
arg1
),
arg2
(
arg2
),
arg3
(
arg3
),
args
(
args
),
entryExited
(
false
),
returnValue
(
nullptr
),
exception
(
nullptr
)
{
function
->
generator
=
this
;
// HACK: this only alows one active generator
giveAttr
(
"__name__"
,
boxString
(
function
->
f
->
source
->
getName
()));
giveAttr
(
"__name__"
,
boxString
(
function
->
f
->
source
->
getName
()));
...
@@ -123,8 +138,6 @@ extern "C" BoxedGenerator::BoxedGenerator(BoxedFunction* function)
...
@@ -123,8 +138,6 @@ extern "C" BoxedGenerator::BoxedGenerator(BoxedFunction* function)
context
.
uc_stack
.
ss_sp
=
stack
;
context
.
uc_stack
.
ss_sp
=
stack
;
context
.
uc_stack
.
ss_size
=
STACK_SIZE
;
context
.
uc_stack
.
ss_size
=
STACK_SIZE
;
makecontext
(
&
context
,
(
void
(
*
)(
void
))
generatorEntry
,
1
,
this
);
makecontext
(
&
context
,
(
void
(
*
)(
void
))
generatorEntry
,
1
,
this
);
g_gen
=
this
;
}
}
...
@@ -134,6 +147,7 @@ void setupGenerator() {
...
@@ -134,6 +147,7 @@ void setupGenerator() {
generator_cls
->
giveAttr
(
"__iter__"
,
generator_cls
->
giveAttr
(
"__iter__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
generatorIter
,
typeFromClass
(
generator_cls
),
1
)));
new
BoxedFunction
(
boxRTFunction
((
void
*
)
generatorIter
,
typeFromClass
(
generator_cls
),
1
)));
generator_cls
->
giveAttr
(
"close"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
generatorClose
,
UNKNOWN
,
1
)));
generator_cls
->
giveAttr
(
"next"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
generatorNext
,
UNKNOWN
,
1
)));
generator_cls
->
giveAttr
(
"next"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
generatorNext
,
UNKNOWN
,
1
)));
generator_cls
->
giveAttr
(
"send"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
generatorSend
,
UNKNOWN
,
2
)));
generator_cls
->
giveAttr
(
"send"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
generatorSend
,
UNKNOWN
,
2
)));
generator_cls
->
giveAttr
(
"throw"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
generatorThrow
,
UNKNOWN
,
2
)));
generator_cls
->
giveAttr
(
"throw"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
generatorThrow
,
UNKNOWN
,
2
)));
...
...
src/runtime/generator.h
View file @
5a645879
...
@@ -25,8 +25,8 @@ extern "C" const ObjectFlavor generator_flavor;
...
@@ -25,8 +25,8 @@ extern "C" const ObjectFlavor generator_flavor;
void
setupGenerator
();
void
setupGenerator
();
extern
"C"
Box
*
yield
(
Box
*
obj
,
Box
*
value
);
extern
"C"
Box
*
yield
(
Box
edGenerator
*
obj
,
Box
*
value
);
extern
"C"
BoxedGenerator
*
createGenerator
(
BoxedFunction
*
function
);
extern
"C"
BoxedGenerator
*
createGenerator
(
BoxedFunction
*
function
,
Box
*
arg1
,
Box
*
arg2
,
Box
*
arg3
,
Box
**
args
);
}
}
#endif
#endif
src/runtime/objmodel.cpp
View file @
5a645879
...
@@ -818,6 +818,8 @@ Box* getattr_internal(Box* obj, const std::string& attr, bool check_cls, bool al
...
@@ -818,6 +818,8 @@ Box* getattr_internal(Box* obj, const std::string& attr, bool check_cls, bool al
raiseExcHelper
(
NameError
,
"free variable '%s' referenced before assignment in enclosing scope"
,
attr
.
c_str
());
raiseExcHelper
(
NameError
,
"free variable '%s' referenced before assignment in enclosing scope"
,
attr
.
c_str
());
}
}
if
(
obj
->
cls
==
generator_cls
)
{
}
if
(
allow_custom
)
{
if
(
allow_custom
)
{
// Don't need to pass icentry args, since we special-case __getattribtue__ and __getattr__ to use
// Don't need to pass icentry args, since we special-case __getattribtue__ and __getattr__ to use
...
@@ -1715,6 +1717,7 @@ Box* callFunc(BoxedFunction* func, CallRewriteArgs* rewrite_args, ArgPassSpec ar
...
@@ -1715,6 +1717,7 @@ Box* callFunc(BoxedFunction* func, CallRewriteArgs* rewrite_args, ArgPassSpec ar
int
num_passed_args
=
argspec
.
totalPassed
();
int
num_passed_args
=
argspec
.
totalPassed
();
BoxedClosure
*
closure
=
func
->
closure
;
BoxedClosure
*
closure
=
func
->
closure
;
BoxedGenerator
*
generator
=
(
BoxedGenerator
*
)
func
->
generator
;
if
(
argspec
.
has_starargs
||
argspec
.
has_kwargs
||
f
->
takes_kwargs
)
if
(
argspec
.
has_starargs
||
argspec
.
has_kwargs
||
f
->
takes_kwargs
)
rewrite_args
=
NULL
;
rewrite_args
=
NULL
;
...
@@ -1751,21 +1754,26 @@ Box* callFunc(BoxedFunction* func, CallRewriteArgs* rewrite_args, ArgPassSpec ar
...
@@ -1751,21 +1754,26 @@ Box* callFunc(BoxedFunction* func, CallRewriteArgs* rewrite_args, ArgPassSpec ar
if
(
rewrite_args
)
{
if
(
rewrite_args
)
{
int
closure_indicator
=
closure
?
1
:
0
;
int
closure_indicator
=
closure
?
1
:
0
;
int
generator_indicator
=
generator
?
1
:
0
;
int
argOffset
=
closure_indicator
+
generator_indicator
;
if
(
num_passed_args
>=
1
)
if
(
num_passed_args
>=
1
)
rewrite_args
->
arg1
=
rewrite_args
->
arg1
.
move
(
0
+
closure_indicator
);
rewrite_args
->
arg1
=
rewrite_args
->
arg1
.
move
(
0
+
argOffset
);
if
(
num_passed_args
>=
2
)
if
(
num_passed_args
>=
2
)
rewrite_args
->
arg2
=
rewrite_args
->
arg2
.
move
(
1
+
closure_indicator
);
rewrite_args
->
arg2
=
rewrite_args
->
arg2
.
move
(
1
+
argOffset
);
if
(
num_passed_args
>=
3
)
if
(
num_passed_args
>=
3
)
rewrite_args
->
arg3
=
rewrite_args
->
arg3
.
move
(
2
+
closure_indicator
);
rewrite_args
->
arg3
=
rewrite_args
->
arg3
.
move
(
2
+
argOffset
);
if
(
num_passed_args
>=
4
)
if
(
num_passed_args
>=
4
)
rewrite_args
->
args
=
rewrite_args
->
args
.
move
(
3
+
closure_indicator
);
rewrite_args
->
args
=
rewrite_args
->
args
.
move
(
3
+
argOffset
);
// TODO this kind of embedded reference needs to be tracked by the GC somehow?
// TODO this kind of embedded reference needs to be tracked by the GC somehow?
// Or maybe it's ok, since we've guarded on the function object?
// Or maybe it's ok, since we've guarded on the function object?
if
(
closure
)
if
(
closure
)
rewrite_args
->
rewriter
->
loadConst
(
0
,
(
intptr_t
)
closure
);
rewrite_args
->
rewriter
->
loadConst
(
0
,
(
intptr_t
)
closure
);
if
(
generator
)
rewrite_args
->
rewriter
->
loadConst
(
0
,
(
intptr_t
)
generator
);
// We might have trouble if we have more output args than input args,
// We might have trouble if we have more output args than input args,
// such as if we need more space to pass defaults.
// such as if we need more space to pass defaults.
if
(
num_output_args
>
3
&&
num_output_args
>
argspec
.
totalPassed
())
{
if
(
num_output_args
>
3
&&
num_output_args
>
argspec
.
totalPassed
())
{
...
@@ -1955,7 +1963,8 @@ Box* callFunc(BoxedFunction* func, CallRewriteArgs* rewrite_args, ArgPassSpec ar
...
@@ -1955,7 +1963,8 @@ Box* callFunc(BoxedFunction* func, CallRewriteArgs* rewrite_args, ArgPassSpec ar
assert
(
chosen_cf
->
is_interpreted
==
(
chosen_cf
->
code
==
NULL
));
assert
(
chosen_cf
->
is_interpreted
==
(
chosen_cf
->
code
==
NULL
));
if
(
chosen_cf
->
is_interpreted
)
{
if
(
chosen_cf
->
is_interpreted
)
{
return
interpretFunction
(
chosen_cf
->
func
,
num_output_args
,
func
->
closure
,
oarg1
,
oarg2
,
oarg3
,
oargs
);
return
interpretFunction
(
chosen_cf
->
func
,
num_output_args
,
func
->
closure
,
generator
,
oarg1
,
oarg2
,
oarg3
,
oargs
);
}
else
{
}
else
{
if
(
rewrite_args
)
{
if
(
rewrite_args
)
{
rewrite_args
->
rewriter
->
addDependenceOn
(
chosen_cf
->
dependent_callsites
);
rewrite_args
->
rewriter
->
addDependenceOn
(
chosen_cf
->
dependent_callsites
);
...
@@ -1966,8 +1975,13 @@ Box* callFunc(BoxedFunction* func, CallRewriteArgs* rewrite_args, ArgPassSpec ar
...
@@ -1966,8 +1975,13 @@ Box* callFunc(BoxedFunction* func, CallRewriteArgs* rewrite_args, ArgPassSpec ar
rewrite_args
->
out_success
=
true
;
rewrite_args
->
out_success
=
true
;
}
}
if
(
closure
)
if
(
closure
&&
generator
)
return
chosen_cf
->
closure_generator_call
(
closure
,
generator
,
oarg1
,
oarg2
,
oarg3
,
oargs
);
else
if
(
closure
)
return
chosen_cf
->
closure_call
(
closure
,
oarg1
,
oarg2
,
oarg3
,
oargs
);
return
chosen_cf
->
closure_call
(
closure
,
oarg1
,
oarg2
,
oarg3
,
oargs
);
else
if
(
generator
)
return
chosen_cf
->
generator_call
(
generator
,
oarg1
,
oarg2
,
oarg3
,
oargs
);
else
else
return
chosen_cf
->
call
(
oarg1
,
oarg2
,
oarg3
,
oargs
);
return
chosen_cf
->
call
(
oarg1
,
oarg2
,
oarg3
,
oargs
);
}
}
...
...
src/runtime/types.cpp
View file @
5a645879
...
@@ -77,7 +77,7 @@ llvm::iterator_range<BoxIterator> Box::pyElements() {
...
@@ -77,7 +77,7 @@ llvm::iterator_range<BoxIterator> Box::pyElements() {
}
}
extern
"C"
BoxedFunction
::
BoxedFunction
(
CLFunction
*
f
)
extern
"C"
BoxedFunction
::
BoxedFunction
(
CLFunction
*
f
)
:
Box
(
&
function_flavor
,
function_cls
),
f
(
f
),
closure
(
NULL
),
ndefaults
(
0
),
defaults
(
NULL
)
{
:
Box
(
&
function_flavor
,
function_cls
),
f
(
f
),
closure
(
NULL
),
generator
(
nullptr
),
ndefaults
(
0
),
defaults
(
NULL
)
{
if
(
f
->
source
)
{
if
(
f
->
source
)
{
assert
(
f
->
source
->
ast
);
assert
(
f
->
source
->
ast
);
// this->giveAttr("__name__", boxString(&f->source->ast->name));
// this->giveAttr("__name__", boxString(&f->source->ast->name));
...
@@ -90,8 +90,9 @@ extern "C" BoxedFunction::BoxedFunction(CLFunction* f)
...
@@ -90,8 +90,9 @@ extern "C" BoxedFunction::BoxedFunction(CLFunction* f)
assert
(
f
->
num_defaults
==
ndefaults
);
assert
(
f
->
num_defaults
==
ndefaults
);
}
}
extern
"C"
BoxedFunction
::
BoxedFunction
(
CLFunction
*
f
,
std
::
initializer_list
<
Box
*>
defaults
,
BoxedClosure
*
closure
)
extern
"C"
BoxedFunction
::
BoxedFunction
(
CLFunction
*
f
,
std
::
initializer_list
<
Box
*>
defaults
,
BoxedClosure
*
closure
,
:
Box
(
&
function_flavor
,
function_cls
),
f
(
f
),
closure
(
closure
),
ndefaults
(
0
),
defaults
(
NULL
)
{
BoxedGenerator
*
generator
)
:
Box
(
&
function_flavor
,
function_cls
),
f
(
f
),
closure
(
closure
),
generator
(
generator
),
ndefaults
(
0
),
defaults
(
NULL
)
{
if
(
defaults
.
size
())
{
if
(
defaults
.
size
())
{
// make sure to initialize defaults first, since the GC behavior is triggered by ndefaults,
// make sure to initialize defaults first, since the GC behavior is triggered by ndefaults,
// and a GC can happen within this constructor:
// and a GC can happen within this constructor:
...
@@ -147,11 +148,12 @@ std::string BoxedModule::name() {
...
@@ -147,11 +148,12 @@ std::string BoxedModule::name() {
}
}
}
}
extern
"C"
Box
*
boxCLFunction
(
CLFunction
*
f
,
BoxedClosure
*
closure
,
std
::
initializer_list
<
Box
*>
defaults
)
{
extern
"C"
Box
*
boxCLFunction
(
CLFunction
*
f
,
BoxedClosure
*
closure
,
BoxedGenerator
*
generator
,
std
::
initializer_list
<
Box
*>
defaults
)
{
if
(
closure
)
if
(
closure
)
assert
(
closure
->
cls
==
closure_cls
);
assert
(
closure
->
cls
==
closure_cls
);
return
new
BoxedFunction
(
f
,
defaults
,
closure
);
return
new
BoxedFunction
(
f
,
defaults
,
closure
,
generator
);
}
}
extern
"C"
CLFunction
*
unboxCLFunction
(
Box
*
b
)
{
extern
"C"
CLFunction
*
unboxCLFunction
(
Box
*
b
)
{
...
...
src/runtime/types.h
View file @
5a645879
...
@@ -92,7 +92,8 @@ Box* boxString(const std::string& s);
...
@@ -92,7 +92,8 @@ Box* boxString(const std::string& s);
extern
"C"
BoxedString
*
boxStrConstant
(
const
char
*
chars
);
extern
"C"
BoxedString
*
boxStrConstant
(
const
char
*
chars
);
extern
"C"
void
listAppendInternal
(
Box
*
self
,
Box
*
v
);
extern
"C"
void
listAppendInternal
(
Box
*
self
,
Box
*
v
);
extern
"C"
void
listAppendArrayInternal
(
Box
*
self
,
Box
**
v
,
int
nelts
);
extern
"C"
void
listAppendArrayInternal
(
Box
*
self
,
Box
**
v
,
int
nelts
);
extern
"C"
Box
*
boxCLFunction
(
CLFunction
*
f
,
BoxedClosure
*
closure
,
std
::
initializer_list
<
Box
*>
defaults
);
extern
"C"
Box
*
boxCLFunction
(
CLFunction
*
f
,
BoxedClosure
*
closure
,
BoxedGenerator
*
generator
,
std
::
initializer_list
<
Box
*>
defaults
);
extern
"C"
CLFunction
*
unboxCLFunction
(
Box
*
b
);
extern
"C"
CLFunction
*
unboxCLFunction
(
Box
*
b
);
extern
"C"
Box
*
createUserClass
(
std
::
string
*
name
,
Box
*
base
,
Box
*
attr_dict
);
extern
"C"
Box
*
createUserClass
(
std
::
string
*
name
,
Box
*
base
,
Box
*
attr_dict
);
extern
"C"
double
unboxFloat
(
Box
*
b
);
extern
"C"
double
unboxFloat
(
Box
*
b
);
...
@@ -279,12 +280,14 @@ public:
...
@@ -279,12 +280,14 @@ public:
HCAttrs
attrs
;
HCAttrs
attrs
;
CLFunction
*
f
;
CLFunction
*
f
;
BoxedClosure
*
closure
;
BoxedClosure
*
closure
;
BoxedGenerator
*
generator
;
int
ndefaults
;
int
ndefaults
;
GCdArray
*
defaults
;
GCdArray
*
defaults
;
BoxedFunction
(
CLFunction
*
f
);
BoxedFunction
(
CLFunction
*
f
);
BoxedFunction
(
CLFunction
*
f
,
std
::
initializer_list
<
Box
*>
defaults
,
BoxedClosure
*
closure
=
NULL
);
BoxedFunction
(
CLFunction
*
f
,
std
::
initializer_list
<
Box
*>
defaults
,
BoxedClosure
*
closure
=
NULL
,
BoxedGenerator
*
generator
=
nullptr
);
};
};
class
BoxedModule
:
public
Box
{
class
BoxedModule
:
public
Box
{
...
@@ -329,6 +332,7 @@ public:
...
@@ -329,6 +332,7 @@ public:
HCAttrs
attrs
;
HCAttrs
attrs
;
BoxedFunction
*
function
;
BoxedFunction
*
function
;
Box
*
arg1
,
*
arg2
,
*
arg3
,
**
args
;
bool
entryExited
;
bool
entryExited
;
Box
*
returnValue
;
Box
*
returnValue
;
...
@@ -337,7 +341,7 @@ public:
...
@@ -337,7 +341,7 @@ public:
ucontext_t
context
,
returnContext
;
ucontext_t
context
,
returnContext
;
char
stack
[
STACK_SIZE
];
char
stack
[
STACK_SIZE
];
BoxedGenerator
(
BoxedFunction
*
function
);
BoxedGenerator
(
BoxedFunction
*
function
,
Box
*
arg1
,
Box
*
arg2
,
Box
*
arg3
,
Box
**
args
);
};
};
extern
"C"
void
boxGCHandler
(
GCVisitor
*
v
,
void
*
p
);
extern
"C"
void
boxGCHandler
(
GCVisitor
*
v
,
void
*
p
);
...
@@ -347,7 +351,7 @@ Box* exceptionNew2(BoxedClass* cls, Box* message);
...
@@ -347,7 +351,7 @@ Box* exceptionNew2(BoxedClass* cls, Box* message);
extern
BoxedClass
*
Exception
,
*
AssertionError
,
*
AttributeError
,
*
TypeError
,
*
NameError
,
*
KeyError
,
*
IndexError
,
extern
BoxedClass
*
Exception
,
*
AssertionError
,
*
AttributeError
,
*
TypeError
,
*
NameError
,
*
KeyError
,
*
IndexError
,
*
IOError
,
*
OSError
,
*
ZeroDivisionError
,
*
ValueError
,
*
UnboundLocalError
,
*
RuntimeError
,
*
ImportError
,
*
IOError
,
*
OSError
,
*
ZeroDivisionError
,
*
ValueError
,
*
UnboundLocalError
,
*
RuntimeError
,
*
ImportError
,
*
StopIteration
;
*
StopIteration
,
*
GeneratorExit
;
// cls should be obj->cls.
// cls should be obj->cls.
// Added as parameter because it should typically be available
// Added as parameter because it should typically be available
...
...
test/tests/generators.py
View file @
5a645879
def
G1
():
def
G1
(
i
=
0
):
i
=
0
while
True
:
while
True
:
yield
i
yield
i
i
+=
i
i
+=
i
...
@@ -21,8 +20,7 @@ print list(G2())
...
@@ -21,8 +20,7 @@ print list(G2())
def
G3
():
def
G3
(
i
=
0
):
i
=
0
while
True
:
while
True
:
got
=
(
yield
i
**
2
)
got
=
(
yield
i
**
2
)
print
"i="
,
i
,
"got="
,
got
print
"i="
,
i
,
"got="
,
got
...
@@ -36,13 +34,13 @@ for i in range(5):
...
@@ -36,13 +34,13 @@ for i in range(5):
def
G4
():
def
G4
(
i
=
1
):
1
/
0
1
/
0
while
True
:
while
True
:
print
"unreachable"
print
"unreachable"
try
:
try
:
print
list
(
G4
())
print
list
(
G4
(
0
))
except
ZeroDivisionError
:
except
ZeroDivisionError
:
print
"catched a ZeroDivisionError"
print
"catched a ZeroDivisionError"
...
@@ -61,3 +59,11 @@ g5 = G5()
...
@@ -61,3 +59,11 @@ g5 = G5()
for
i
in
range
(
5
):
for
i
in
range
(
5
):
print
g5
.
next
()
print
g5
.
next
()
print
g5
.
throw
(
ZeroDivisionError
)
print
g5
.
throw
(
ZeroDivisionError
)
def
G6
(
a
=
[]):
for
i
in
range
(
2
):
a
.
append
(
i
)
yield
a
print
list
(
G6
())
print
list
(
G6
())
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