@@ -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,122 @@ 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 (
716+ receiver , 'data_addtolist' , 'statement' , Variable . LIST_TYPE
717+ ) ;
718+ this . _addInput ( block , 'ITEM' , this . _createTextBlock ( args [ 0 ] , block . id ) ) ;
719+ }
720+ break ;
721+ case 'delete_at' :
722+ if ( args . length === 1 &&
723+ this . _isNumberOrBlock ( args [ 0 ] ) ) {
724+ block = this . _changeVariableBlock (
725+ receiver , 'data_deleteoflist' , 'statement' , Variable . LIST_TYPE
726+ ) ;
727+ this . _addInput ( block , 'INDEX' , this . _createNumberBlock ( 'math_number' , args [ 0 ] , block . id ) ) ;
728+ }
729+ break ;
730+ case 'clear' :
731+ if ( args . length === 0 ) {
732+ block = this . _changeVariableBlock (
733+ receiver , 'data_deletealloflist' , 'statement' , Variable . LIST_TYPE
734+ ) ;
735+ }
736+ break ;
737+ case 'insert' :
738+ if ( args . length === 2 &&
739+ this . _isNumberOrBlock ( args [ 0 ] ) &&
740+ this . _isStringOrBlock ( args [ 1 ] ) ) {
741+ block = this . _changeVariableBlock (
742+ receiver , 'data_insertatlist' , 'statement' , Variable . LIST_TYPE
743+ ) ;
744+ this . _addInput ( block , 'INDEX' , this . _createNumberBlock ( 'math_number' , args [ 0 ] , block . id ) ) ;
745+ this . _addInput ( block , 'ITEM' , this . _createTextBlock ( args [ 1 ] , block . id ) ) ;
746+ }
747+ break ;
748+ case '[]=' :
749+ if ( args . length === 2 &&
750+ this . _isNumberOrBlock ( args [ 0 ] ) &&
751+ this . _isStringOrBlock ( args [ 1 ] ) ) {
752+ block = this . _changeVariableBlock (
753+ receiver , 'data_replaceitemoflist' , 'statement' , Variable . LIST_TYPE
754+ ) ;
755+ this . _addInput ( block , 'INDEX' , this . _createNumberBlock ( 'math_number' , args [ 0 ] , block . id ) ) ;
756+ this . _addInput ( block , 'ITEM' , this . _createTextBlock ( args [ 1 ] , block . id ) ) ;
757+ }
758+ break ;
759+ case '[]' :
760+ if ( args . length === 1 &&
761+ this . _isNumberOrBlock ( args [ 0 ] ) ) {
762+ block = this . _changeVariableBlock (
763+ receiver , 'data_itemoflist' , 'value' , Variable . LIST_TYPE
764+ ) ;
765+ this . _addInput ( block , 'INDEX' , this . _createNumberBlock ( 'math_number' , args [ 0 ] , block . id ) ) ;
766+ }
767+ break ;
768+ case 'index' :
769+ if ( args . length === 1 &&
770+ this . _isStringOrBlock ( args [ 0 ] ) ) {
771+ block = this . _changeVariableBlock (
772+ receiver , 'data_itemnumoflist' , 'value' , Variable . LIST_TYPE
773+ ) ;
774+ this . _addInput ( block , 'ITEM' , this . _createTextBlock ( args [ 0 ] , block . id ) ) ;
775+ }
776+ break ;
777+ case 'length' :
778+ if ( args . length === 0 ) {
779+ block = this . _changeVariableBlock (
780+ receiver , 'data_lengthoflist' , 'value' , Variable . LIST_TYPE
781+ ) ;
782+ }
783+ break ;
784+ case 'include?' :
785+ if ( args . length === 1 &&
786+ this . _isStringOrBlock ( args [ 0 ] ) ) {
787+ block = this . _changeVariableBlock (
788+ receiver , 'data_listcontainsitem' , 'value' , Variable . LIST_TYPE
789+ ) ;
790+ this . _addInput ( block , 'ITEM' , this . _createTextBlock ( args [ 0 ] , block . id ) ) ;
791+ }
792+ break ;
793+ }
652794 } else {
653795 switch ( name ) {
654796 case '+' :
@@ -722,8 +864,8 @@ class RubyToBlocksConverter {
722864 }
723865 break ;
724866 case '[]' :
725- if ( args . length === 1 &&
726- this . _isStringOrBlock ( receiver ) && this . _isNumberOrBlock ( args [ 0 ] ) ) {
867+ if ( this . _isStringOrBlock ( receiver ) &&
868+ args . length === 1 && this . _isNumberOrBlock ( args [ 0 ] ) ) {
727869 block = this . _createBlock ( 'operator_letter_of' , 'value' ) ;
728870 this . _addInput ( block , 'STRING' , this . _createTextBlock ( receiver , block . id ) ) ;
729871 this . _addInput ( block , 'LETTER' , this . _createNumberBlock ( 'math_number' , args [ 0 ] , block . id ) ) ;
@@ -813,7 +955,7 @@ class RubyToBlocksConverter {
813955 }
814956 break ;
815957 }
816- case '**' : {
958+ case '**' :
817959 if ( args . length === 1 && this . _isNumberOrBlock ( args [ 0 ] ) ) {
818960 let operator ;
819961 if ( this . _matchRubyExpression ( receiver , / ^ ( : : ) ? M a t h : : E $ / ) ) {
@@ -838,7 +980,6 @@ class RubyToBlocksConverter {
838980 }
839981 break ;
840982 }
841- }
842983 }
843984 if ( ! block ) {
844985 receiverAndArgsBlockIds . forEach ( blockId => {
@@ -1008,7 +1149,7 @@ class RubyToBlocksConverter {
10081149 break ;
10091150 }
10101151 } else if ( _ . isString ( lh ) ) {
1011- const variable = this . _findOrCreateVariable ( lh ) ;
1152+ const variable = this . _findOrCreateVariable ( lh , Variable . SCALAR_TYPE ) ;
10121153 if ( variable . scope !== 'local' ) {
10131154 block = this . _createBlock ( 'data_changevariableby' , 'statement' , {
10141155 fields : {
@@ -1107,10 +1248,19 @@ class RubyToBlocksConverter {
11071248
11081249 const variable = this . _findOrCreateVariable ( node . children [ 0 ] ) ;
11091250 if ( variable . scope !== 'local' ) {
1110- return this . _createBlock ( 'data_variable' , 'value' , {
1251+ let opcode ;
1252+ let name ;
1253+ if ( variable . type === Variable . SCALAR_TYPE ) {
1254+ opcode = 'data_variable' ;
1255+ name = 'VARIABLE' ;
1256+ } else {
1257+ opcode = 'data_listcontents' ;
1258+ name = 'LIST' ;
1259+ }
1260+ return this . _createBlock ( opcode , 'value' , {
11111261 fields : {
1112- VARIABLE : {
1113- name : 'VARIABLE' ,
1262+ [ name ] : {
1263+ name : name ,
11141264 id : variable . id ,
11151265 value : variable . name
11161266 }
@@ -1136,7 +1286,7 @@ class RubyToBlocksConverter {
11361286 return node . children [ 0 ] . toString ( ) ;
11371287 }
11381288
1139- const variable = this . _findOrCreateVariable ( node . children [ 0 ] ) ;
1289+ const variable = this . _findOrCreateVariable ( node . children [ 0 ] , Variable . SCALAR_TYPE ) ;
11401290 if ( variable . scope !== 'local' ) {
11411291 const rh = this . _process ( node . children [ 1 ] ) ;
11421292 const block = this . _createBlock ( 'data_setvariableto' , 'statement' , {
0 commit comments