@@ -269,7 +269,7 @@ class RubyToBlocksConverter {
269269 } ) ;
270270 }
271271
272- _findOrCreateVariable ( name , type = Variable . SCALAR_TYPE ) {
272+ _findOrCreateVariable ( name , type ) {
273273 let scope ;
274274 let store ;
275275 if ( name [ 0 ] === '$' ) {
@@ -285,19 +285,47 @@ class RubyToBlocksConverter {
285285 store = this . _context . localVariables ;
286286 }
287287 if ( store . hasOwnProperty ( name ) ) {
288+ if ( type ) {
289+ store [ name ] . type = type ;
290+ }
288291 return store [ name ] ;
289292 }
290293
291294 const variable = {
292295 id : Blockly . utils . genUid ( ) ,
293296 name : name ,
294297 scope : scope ,
295- type : type
298+ type : type ? type : Variable . SCALAR_TYPE
296299 } ;
297300 store [ variable . name ] = variable ;
298301 return variable ;
299302 }
300303
304+ _changeVariableBlock ( block , opcode , blockType , varType ) {
305+ block . opcode = opcode ;
306+ this . _setBlockType ( block , blockType ) ;
307+
308+ let before ;
309+ let after ;
310+ if ( varType === Variable . SCALAR_TYPE ) {
311+ before = 'LIST' ;
312+ after = 'VARIABLE' ;
313+ } else {
314+ before = 'VARIABLE' ;
315+ after = 'LIST' ;
316+ }
317+ if ( block . fields [ before ] ) {
318+ block . fields [ after ] = block . fields [ before ] ;
319+ block . fields [ after ] . name = after ;
320+ delete block . fields [ before ] ;
321+
322+ const varName = block . fields [ after ] . value ;
323+ const variable = this . instanceVariables [ varName ] || this . globalVariables [ varName ] ;
324+ variable . type = varType ;
325+ }
326+ return block ;
327+ }
328+
301329 _getSource ( node ) {
302330 const expression = node . $loc ( ) . $expression ( ) ;
303331 if ( expression === Opal . nil ) {
@@ -352,6 +380,10 @@ class RubyToBlocksConverter {
352380 return _ . isString ( stringOrBlock ) || this . _isBlock ( stringOrBlock ) ;
353381 }
354382
383+ _isVariableBlock ( block ) {
384+ return this . _isBlock ( block ) && [ 'data_variable' , 'data_listcontents' ] . indexOf ( block . opcode ) >= 0 ;
385+ }
386+
355387 _matchRubyExpression ( block , regexp ) {
356388 if ( ! this . _isBlock ( block ) || block . opcode !== 'ruby_expression' ) {
357389 return false ;
@@ -629,7 +661,7 @@ class RubyToBlocksConverter {
629661 opcode = 'data_hidevariable' ;
630662 break ;
631663 }
632- const variable = this . _findOrCreateVariable ( args [ 0 ] ) ;
664+ const variable = this . _findOrCreateVariable ( args [ 0 ] , Variable . SCALAR_TYPE ) ;
633665 if ( variable . scope !== 'local' ) {
634666 block = this . _createBlock ( opcode , 'statement' , {
635667 fields : {
@@ -643,12 +675,104 @@ class RubyToBlocksConverter {
643675 }
644676 }
645677 break ;
678+ case 'show_list' :
679+ case 'hide_list' :
680+ if ( args . length === 1 && _ . isString ( args [ 0 ] ) ) {
681+ let opcode ;
682+ switch ( name ) {
683+ case 'show_list' :
684+ opcode = 'data_showlist' ;
685+ break ;
686+ case 'hide_list' :
687+ opcode = 'data_hidelist' ;
688+ break ;
689+ }
690+ const variable = this . _findOrCreateVariable ( args [ 0 ] , Variable . LIST_TYPE ) ;
691+ if ( variable . scope !== 'local' ) {
692+ block = this . _createBlock ( opcode , 'statement' , {
693+ fields : {
694+ LIST : {
695+ name : 'LIST' ,
696+ id : variable . id ,
697+ value : variable . name
698+ }
699+ }
700+ } ) ;
701+ }
702+ }
703+ break ;
646704 case 'wait' :
647705 if ( args . length === 0 ) {
648706 block = this . _createBlock ( 'ruby_statement' , 'statement' ) ;
649707 this . _addInput ( block , 'STATEMENT' , this . _createTextBlock ( 'wait' , block . id ) ) ;
650708 }
651709 }
710+ } else if ( this . _isVariableBlock ( receiver ) ) {
711+ switch ( name ) {
712+ case 'push' :
713+ if ( args . length === 1 &&
714+ this . _isStringOrBlock ( args [ 0 ] ) ) {
715+ block = this . _changeVariableBlock ( receiver , 'data_addtolist' , 'statement' , Variable . LIST_TYPE ) ;
716+ this . _addInput ( block , 'ITEM' , this . _createTextBlock ( args [ 0 ] , block . id ) ) ;
717+ }
718+ break ;
719+ case 'delete_at' :
720+ if ( args . length === 1 &&
721+ this . _isNumberOrBlock ( args [ 0 ] ) ) {
722+ block = this . _changeVariableBlock ( receiver , 'data_deleteoflist' , 'statement' , Variable . LIST_TYPE ) ;
723+ this . _addInput ( block , 'INDEX' , this . _createNumberBlock ( 'math_number' , args [ 0 ] , block . id ) ) ;
724+ }
725+ break ;
726+ case 'clear' :
727+ if ( args . length === 0 ) {
728+ block = this . _changeVariableBlock ( receiver , 'data_deletealloflist' , 'statement' , Variable . LIST_TYPE ) ;
729+ }
730+ break ;
731+ case 'insert' :
732+ if ( args . length === 2 &&
733+ this . _isNumberOrBlock ( args [ 0 ] ) &&
734+ this . _isStringOrBlock ( args [ 1 ] ) ) {
735+ block = this . _changeVariableBlock ( receiver , 'data_insertatlist' , 'statement' , Variable . LIST_TYPE ) ;
736+ this . _addInput ( block , 'INDEX' , this . _createNumberBlock ( 'math_number' , args [ 0 ] , block . id ) ) ;
737+ this . _addInput ( block , 'ITEM' , this . _createTextBlock ( args [ 1 ] , block . id ) ) ;
738+ }
739+ break ;
740+ case '[]=' :
741+ if ( args . length === 2 &&
742+ this . _isNumberOrBlock ( args [ 0 ] ) &&
743+ this . _isStringOrBlock ( args [ 1 ] ) ) {
744+ block = this . _changeVariableBlock ( receiver , 'data_replaceitemoflist' , 'statement' , Variable . LIST_TYPE ) ;
745+ this . _addInput ( block , 'INDEX' , this . _createNumberBlock ( 'math_number' , args [ 0 ] , block . id ) ) ;
746+ this . _addInput ( block , 'ITEM' , this . _createTextBlock ( args [ 1 ] , block . id ) ) ;
747+ }
748+ break ;
749+ case '[]' :
750+ if ( args . length === 1 &&
751+ this . _isNumberOrBlock ( args [ 0 ] ) ) {
752+ block = this . _changeVariableBlock ( receiver , 'data_itemoflist' , 'value' , Variable . LIST_TYPE ) ;
753+ this . _addInput ( block , 'INDEX' , this . _createNumberBlock ( 'math_number' , args [ 0 ] , block . id ) ) ;
754+ }
755+ break ;
756+ case 'index' :
757+ if ( args . length === 1 &&
758+ this . _isStringOrBlock ( args [ 0 ] ) ) {
759+ block = this . _changeVariableBlock ( receiver , 'data_itemnumoflist' , 'value' , Variable . LIST_TYPE ) ;
760+ this . _addInput ( block , 'ITEM' , this . _createTextBlock ( args [ 0 ] , block . id ) ) ;
761+ }
762+ break ;
763+ case 'length' :
764+ if ( args . length === 0 ) {
765+ block = this . _changeVariableBlock ( receiver , 'data_lengthoflist' , 'value' , Variable . LIST_TYPE ) ;
766+ }
767+ break ;
768+ case 'include?' :
769+ if ( args . length === 1 &&
770+ this . _isStringOrBlock ( args [ 0 ] ) ) {
771+ block = this . _changeVariableBlock ( receiver , 'data_listcontainsitem' , 'value' , Variable . LIST_TYPE ) ;
772+ this . _addInput ( block , 'ITEM' , this . _createTextBlock ( args [ 0 ] , block . id ) ) ;
773+ }
774+ break ;
775+ }
652776 } else {
653777 switch ( name ) {
654778 case '+' :
@@ -722,8 +846,8 @@ class RubyToBlocksConverter {
722846 }
723847 break ;
724848 case '[]' :
725- if ( args . length === 1 &&
726- this . _isStringOrBlock ( receiver ) && this . _isNumberOrBlock ( args [ 0 ] ) ) {
849+ if ( this . _isStringOrBlock ( receiver ) &&
850+ args . length === 1 && this . _isNumberOrBlock ( args [ 0 ] ) ) {
727851 block = this . _createBlock ( 'operator_letter_of' , 'value' ) ;
728852 this . _addInput ( block , 'STRING' , this . _createTextBlock ( receiver , block . id ) ) ;
729853 this . _addInput ( block , 'LETTER' , this . _createNumberBlock ( 'math_number' , args [ 0 ] , block . id ) ) ;
@@ -813,7 +937,7 @@ class RubyToBlocksConverter {
813937 }
814938 break ;
815939 }
816- case '**' : {
940+ case '**' :
817941 if ( args . length === 1 && this . _isNumberOrBlock ( args [ 0 ] ) ) {
818942 let operator ;
819943 if ( this . _matchRubyExpression ( receiver , / ^ ( : : ) ? M a t h : : E $ / ) ) {
@@ -838,7 +962,6 @@ class RubyToBlocksConverter {
838962 }
839963 break ;
840964 }
841- }
842965 }
843966 if ( ! block ) {
844967 receiverAndArgsBlockIds . forEach ( blockId => {
@@ -1008,7 +1131,7 @@ class RubyToBlocksConverter {
10081131 break ;
10091132 }
10101133 } else if ( _ . isString ( lh ) ) {
1011- const variable = this . _findOrCreateVariable ( lh ) ;
1134+ const variable = this . _findOrCreateVariable ( lh , Variable . SCALAR_TYPE ) ;
10121135 if ( variable . scope !== 'local' ) {
10131136 block = this . _createBlock ( 'data_changevariableby' , 'statement' , {
10141137 fields : {
@@ -1107,10 +1230,19 @@ class RubyToBlocksConverter {
11071230
11081231 const variable = this . _findOrCreateVariable ( node . children [ 0 ] ) ;
11091232 if ( variable . scope !== 'local' ) {
1110- return this . _createBlock ( 'data_variable' , 'value' , {
1233+ let opcode ;
1234+ let name ;
1235+ if ( variable . type === Variable . SCALAR_TYPE ) {
1236+ opcode = 'data_variable' ;
1237+ name = 'VARIABLE' ;
1238+ } else {
1239+ opcode = 'data_listcontents' ;
1240+ name = 'LIST' ;
1241+ }
1242+ return this . _createBlock ( opcode , 'value' , {
11111243 fields : {
1112- VARIABLE : {
1113- name : 'VARIABLE' ,
1244+ [ name ] : {
1245+ name : name ,
11141246 id : variable . id ,
11151247 value : variable . name
11161248 }
@@ -1136,7 +1268,7 @@ class RubyToBlocksConverter {
11361268 return node . children [ 0 ] . toString ( ) ;
11371269 }
11381270
1139- const variable = this . _findOrCreateVariable ( node . children [ 0 ] ) ;
1271+ const variable = this . _findOrCreateVariable ( node . children [ 0 ] , Variable . SCALAR_TYPE ) ;
11401272 if ( variable . scope !== 'local' ) {
11411273 const rh = this . _process ( node . children [ 1 ] ) ;
11421274 const block = this . _createBlock ( 'data_setvariableto' , 'statement' , {
0 commit comments