@@ -250,6 +250,7 @@ impl Compiler {
250250 self . emit ( Instruction :: ForIter ) ;
251251
252252 // Start of loop iteration, set targets:
253+ // TODO: can we use compile_store here?
253254 for t in target {
254255 match t {
255256 ast:: Expression :: Identifier { name } => {
@@ -878,6 +879,107 @@ impl Compiler {
878879 flags : bytecode:: FunctionOpArg :: empty ( ) ,
879880 } ) ;
880881 }
882+ ast:: Expression :: ListComprehension {
883+ element,
884+ generators,
885+ } => {
886+ // Okay, compile a new function which can be called
887+
888+ // For now only support one generator:
889+ if generators. len ( ) != 1 {
890+ unimplemented ! ( "Only 1 level deep list comprehensions are implemented now" ) ;
891+ }
892+ let generator = & generators[ 0 ] ;
893+
894+ // Create magnificent function <listcomp>:
895+ self . code_object_stack . push ( CodeObject :: new (
896+ vec ! [ ".0" . to_string( ) ] ,
897+ self . source_path . clone ( ) ,
898+ "<listcomp>" . to_string ( ) ,
899+ ) ) ;
900+
901+ // Create empty list:
902+ self . emit ( Instruction :: BuildList { size : 0 } ) ;
903+
904+ // Load 'append' method:
905+ //self.emit(Instruction::LoadAttr {
906+ // name: "append".to_string(),
907+ //});
908+
909+ // Load iterator onto stack:
910+ self . emit ( Instruction :: LoadName {
911+ name : String :: from ( ".0" ) ,
912+ } ) ;
913+
914+ // Setup for loop:
915+ let start_label = self . new_label ( ) ;
916+ let end_label = self . new_label ( ) ;
917+ self . emit ( Instruction :: SetupLoop {
918+ start : start_label,
919+ end : end_label,
920+ } ) ;
921+ self . set_label ( start_label) ;
922+ self . emit ( Instruction :: ForIter ) ;
923+
924+ // TODO: can we use compile_store here?
925+ for t in & generator. target {
926+ match t {
927+ ast:: Expression :: Identifier { name } => {
928+ self . emit ( Instruction :: StoreName {
929+ name : name. to_string ( ) ,
930+ } ) ;
931+ }
932+ _ => panic ! ( "Not impl" ) ,
933+ }
934+ }
935+
936+ // Evaluate element:
937+ self . compile_expression ( element) ;
938+
939+ // List append:
940+ self . emit ( Instruction :: ListAppend { i : 2 } ) ;
941+
942+ // Repeat:
943+ self . emit ( Instruction :: Jump {
944+ target : start_label,
945+ } ) ;
946+
947+ // End of for loop:
948+ self . set_label ( end_label) ;
949+ self . emit ( Instruction :: PopBlock ) ;
950+
951+ // Return freshly filled list:
952+ self . emit ( Instruction :: ReturnValue ) ;
953+
954+ // Fetch code for listcomp function:
955+ let code = self . code_object_stack . pop ( ) . unwrap ( ) ;
956+
957+ // List comprehension code:
958+ self . emit ( Instruction :: LoadConst {
959+ value : bytecode:: Constant :: Code { code : code } ,
960+ } ) ;
961+
962+ // List comprehension function name:
963+ self . emit ( Instruction :: LoadConst {
964+ value : bytecode:: Constant :: String {
965+ value : String :: from ( "<listcomp>" ) ,
966+ } ,
967+ } ) ;
968+
969+ // Turn code object into function object:
970+ self . emit ( Instruction :: MakeFunction {
971+ flags : bytecode:: FunctionOpArg :: empty ( ) ,
972+ } ) ;
973+
974+ // Evaluate iterated item:
975+ self . compile_expression ( & generator. iter ) ;
976+
977+ // Get iterator / turn item into an iterator
978+ self . emit ( Instruction :: GetIter ) ;
979+
980+ // Call just created <listcomp> function:
981+ self . emit ( Instruction :: CallFunction { count : 1 } ) ;
982+ }
881983 ast:: Expression :: IfExpression { test, body, orelse } => {
882984 let no_label = self . new_label ( ) ;
883985 let end_label = self . new_label ( ) ;
0 commit comments