@@ -26,6 +26,12 @@ import { Block } from '../toolbox/items';
2626import { FunctionArg } from '../blocks/mrc_call_python_function' ;
2727import * as commonStorage from '../storage/common_storage' ;
2828
29+
30+ const CLASS_NAME_PLACEHOLDER = '%class_name%' ;
31+ const FULL_CLASS_NAME_PLACEHOLDER = '%full_class_name%' ;
32+ const INSTANCE_LABEL_PLACEHOLDER = '%instance_label%' ;
33+ const INSTANCE_VARIABLE_NAME_PLACEHOLDER = '%instance_var_name%' ;
34+
2935// Extends the python generator to collect some information about functions and
3036// variables that have been defined so they can be used in other modules.
3137
@@ -123,53 +129,60 @@ export class ExtendedPythonGenerator extends PythonGenerator {
123129 }
124130
125131 private produceExportedBlocks ( workspace : Blockly . Workspace ) : Block [ ] {
126- // The exported blocks produced here have the extraState.importModule and fields.MODULE values
127- // set to the MODULE_NAME_PLACEHOLDER. This is so blocks modules can be renamed and copied
128- // without having to change the contents of the modules.
129- // The placeholders will be replaced with the actual module name before they are added to the
130- // toolbox.
132+ // The exported blocks produced here have some values set to placeholders.
133+ // This is so blocks modules can be renamed and copied without having to change the
134+ // contents of the modules. The placeholders will be replaced with the actual module
135+ // name before they are added to the toolbox. See function replacePlaceholders below.
131136
132137 const exportedBlocks = [ ] ;
133138
134- // All functions are exported.
135- // TODO(lizlooney): instead of looking at procedure blocks, this code needs
136- // to look at mrc_class_method_def blocks.
137- const allProcedures = Blockly . Procedures . allProcedures ( workspace ) ;
138- const procedureTuples = allProcedures [ 0 ] . concat ( allProcedures [ 1 ] ) ;
139- for ( const procedureTuple of procedureTuples ) {
140- const functionName = procedureTuple [ 0 ] ;
141- const blockDefinition = Blockly . Procedures . getDefinition ( functionName , workspace ) ;
142- if ( ! blockDefinition || ! blockDefinition . isEnabled ( ) ) {
143- continue ;
139+ // Look at mrc_class_method_def blocks and make corresponding mrc_call_python_function blocks.
140+ workspace . getBlocksByType ( 'mrc_class_method_def' ) . forEach ( ( classMethodDefBlock ) => {
141+ if ( ! classMethodDefBlock . mrcCanBeCalledOutsideClass ||
142+ ! classMethodDefBlock . isEnabled ( ) ) {
143+ return ;
144144 }
145- const actualFunctionName = super . getProcedureName ( functionName ) ;
146- const hasReturnValue = procedureTuple [ 2 ] ;
147145 const args : FunctionArg [ ] = [ ] ;
148- const parameterNames = procedureTuple [ 1 ] ;
149- parameterNames . forEach ( ( parameterName ) => {
146+ args . push ( {
147+ 'name' : INSTANCE_LABEL_PLACEHOLDER ,
148+ 'type' : FULL_CLASS_NAME_PLACEHOLDER ,
149+ } ) ;
150+ classMethodDefBlock . mrcParameters . forEach ( ( param ) => {
150151 args . push ( {
151- 'name' : parameterName ,
152- 'type' : '' ,
153- } )
152+ 'name' : param . name ,
153+ 'type' : param . type ,
154+ } ) ;
154155 } ) ;
155156 const callFunctionBlock : Block = {
156157 'kind' : 'block' ,
157158 'type' : 'mrc_call_python_function' ,
158159 'extraState' : {
159- 'functionKind' : 'module ' ,
160- 'returnType' : hasReturnValue ? '' : 'None' ,
160+ 'functionKind' : 'instance ' ,
161+ 'returnType' : classMethodDefBlock . mrcPythonMethodName ,
161162 'args' : args ,
162- 'importModule' : commonStorage . MODULE_NAME_PLACEHOLDER ,
163- 'actualFunctionName' : actualFunctionName ,
163+ 'importModule' : '' ,
164+ 'actualFunctionName' : classMethodDefBlock . mrcPythonMethodName ,
164165 'exportedFunction' : true ,
165166 } ,
166167 'fields' : {
167- 'MODULE_OR_CLASS' : commonStorage . MODULE_NAME_PLACEHOLDER ,
168- 'FUNC' : functionName ,
168+ 'MODULE_OR_CLASS' : FULL_CLASS_NAME_PLACEHOLDER ,
169+ 'FUNC' : classMethodDefBlock . getFieldValue ( 'NAME' ) ,
169170 } ,
171+ 'inputs' : {
172+ 'ARG0' : {
173+ 'block' : {
174+ 'type' : 'variables_get' ,
175+ 'fields' : {
176+ 'VAR' : {
177+ 'name' : INSTANCE_VARIABLE_NAME_PLACEHOLDER ,
178+ }
179+ }
180+ }
181+ }
182+ }
170183 } ;
171184 exportedBlocks . push ( callFunctionBlock ) ;
172- }
185+ } ) ;
173186
174187 const allVariables = workspace . getAllVariables ( ) ;
175188 for ( const variableModel of allVariables ) {
@@ -199,32 +212,60 @@ export class ExtendedPythonGenerator extends PythonGenerator {
199212 'kind' : 'block' ,
200213 'type' : 'mrc_get_python_variable' ,
201214 'extraState' : {
202- 'varKind' : 'module ' ,
203- 'moduleOrClassName' : commonStorage . MODULE_NAME_PLACEHOLDER ,
204- 'importModule' : commonStorage . MODULE_NAME_PLACEHOLDER ,
215+ 'varKind' : 'instance ' ,
216+ 'moduleOrClassName' : FULL_CLASS_NAME_PLACEHOLDER ,
217+ 'importModule' : '' ,
205218 'actualVariableName' : actualVariableName ,
219+ 'selfLabel' : INSTANCE_LABEL_PLACEHOLDER ,
220+ 'selfType' : FULL_CLASS_NAME_PLACEHOLDER ,
206221 'exportedVariable' : true ,
207222 } ,
208223 'fields' : {
209- 'MODULE_OR_CLASS' : commonStorage . MODULE_NAME_PLACEHOLDER ,
224+ 'MODULE_OR_CLASS' : FULL_CLASS_NAME_PLACEHOLDER ,
210225 'VAR' : variableName ,
211226 } ,
227+ 'inputs' : {
228+ 'SELF' : {
229+ 'block' : {
230+ 'type' : 'variables_get' ,
231+ 'fields' : {
232+ 'VAR' : {
233+ 'name' : INSTANCE_VARIABLE_NAME_PLACEHOLDER ,
234+ }
235+ }
236+ }
237+ }
238+ }
212239 } ;
213240 exportedBlocks . push ( getPythonModuleVariableBlock ) ;
214241 const setPythonModuleVariableBlock = {
215242 'kind' : 'block' ,
216243 'type' : 'mrc_set_python_variable' ,
217244 'extraState' : {
218- 'varKind' : 'module ' ,
219- 'moduleOrClassName' : commonStorage . MODULE_NAME_PLACEHOLDER ,
220- 'importModule' : commonStorage . MODULE_NAME_PLACEHOLDER ,
245+ 'varKind' : 'instance ' ,
246+ 'moduleOrClassName' : FULL_CLASS_NAME_PLACEHOLDER ,
247+ 'importModule' : '' ,
221248 'actualVariableName' : actualVariableName ,
249+ 'selfLabel' : INSTANCE_LABEL_PLACEHOLDER ,
250+ 'selfType' : FULL_CLASS_NAME_PLACEHOLDER ,
222251 'exportedVariable' : true ,
223252 } ,
224253 'fields' : {
225- 'MODULE_OR_CLASS' : commonStorage . MODULE_NAME_PLACEHOLDER ,
254+ 'MODULE_OR_CLASS' : FULL_CLASS_NAME_PLACEHOLDER ,
226255 'VAR' : variableName ,
227256 } ,
257+ 'inputs' : {
258+ 'SELF' : {
259+ 'block' : {
260+ 'type' : 'variables_get' ,
261+ 'fields' : {
262+ 'VAR' : {
263+ 'name' : INSTANCE_VARIABLE_NAME_PLACEHOLDER ,
264+ }
265+ }
266+ }
267+ }
268+ }
228269 } ;
229270 exportedBlocks . push ( setPythonModuleVariableBlock ) ;
230271 }
@@ -234,3 +275,75 @@ export class ExtendedPythonGenerator extends PythonGenerator {
234275}
235276
236277export const extendedPythonGenerator = new ExtendedPythonGenerator ( ) ;
278+
279+ export function replacePlaceholders ( modulePath : string , exportedBlocks : Block [ ] ) {
280+ const moduleName = commonStorage . getModuleName ( modulePath ) ;
281+ const className = commonStorage . moduleNameToClassName ( moduleName ) ;
282+ const fullClassName = moduleName + '.' + className ;
283+ const instanceLabel = className . charAt ( 0 ) . toLowerCase ( ) + className . slice ( 1 ) ;
284+ const instanceVariableName = instanceLabel ;
285+
286+ exportedBlocks . forEach ( ( block ) => {
287+ if ( block . type === 'mrc_call_python_function' ) {
288+ if ( block . extraState . args . length > 0 &&
289+ block . extraState . args [ 0 ] . name === INSTANCE_LABEL_PLACEHOLDER ) {
290+ block . extraState . args [ 0 ] . name = instanceLabel ;
291+ }
292+ if ( block . extraState . args . length > 0 &&
293+ block . extraState . args [ 0 ] . type === FULL_CLASS_NAME_PLACEHOLDER ) {
294+ block . extraState . args [ 0 ] . type = fullClassName ;
295+ }
296+ if ( block . fields . MODULE_OR_CLASS === FULL_CLASS_NAME_PLACEHOLDER ) {
297+ block . fields . MODULE_OR_CLASS = fullClassName ;
298+ }
299+ if ( block . inputs . ARG0 . block . type === 'variables_get' &&
300+ block . inputs . ARG0 . block . fields . VAR . name === INSTANCE_VARIABLE_NAME_PLACEHOLDER ) {
301+ block . inputs . ARG0 . block . fields . VAR . name = instanceVariableName ;
302+ }
303+ } else if ( block . type === 'mrc_get_python_variable' ) {
304+ if ( block . extraState . moduleOrClassName === FULL_CLASS_NAME_PLACEHOLDER ) {
305+ block . extraState . moduleOrClassName = fullClassName ;
306+ }
307+ if ( block . extraState . selfLabel === INSTANCE_LABEL_PLACEHOLDER ) {
308+ block . extraState . selfLabel = instanceLabel ;
309+ }
310+ if ( block . extraState . selfType === FULL_CLASS_NAME_PLACEHOLDER ) {
311+ block . extraState . selfType = fullClassName ;
312+ }
313+ if ( block . fields . MODULE_OR_CLASS === FULL_CLASS_NAME_PLACEHOLDER ) {
314+ block . fields . MODULE_OR_CLASS = fullClassName ;
315+ }
316+ if ( block . inputs . SELF . block . type === 'variables_get' &&
317+ block . inputs . SELF . block . fields . VAR . name === INSTANCE_VARIABLE_NAME_PLACEHOLDER ) {
318+ block . inputs . SELF . block . fields . VAR . name = instanceVariableName ;
319+ }
320+ } else if ( block . type === 'mrc_set_python_variable' ) {
321+ if ( block . extraState . moduleOrClassName === FULL_CLASS_NAME_PLACEHOLDER ) {
322+ block . extraState . moduleOrClassName = fullClassName ;
323+ }
324+ if ( block . extraState . selfLabel === INSTANCE_LABEL_PLACEHOLDER ) {
325+ block . extraState . selfLabel = instanceLabel ;
326+ }
327+ if ( block . extraState . selfType === FULL_CLASS_NAME_PLACEHOLDER ) {
328+ block . extraState . selfType = fullClassName ;
329+ }
330+ if ( block . fields . MODULE_OR_CLASS === FULL_CLASS_NAME_PLACEHOLDER ) {
331+ block . fields . MODULE_OR_CLASS = fullClassName ;
332+ }
333+ if ( block . inputs . SELF . block . type === 'variables_get' &&
334+ block . inputs . SELF . block . fields . VAR . name === INSTANCE_VARIABLE_NAME_PLACEHOLDER ) {
335+ block . inputs . SELF . block . fields . VAR . name = instanceVariableName ;
336+ }
337+ }
338+ } ) ;
339+
340+ // HeyLiz begin
341+ const HeyLiz = JSON . stringify ( exportedBlocks ) ;
342+ if ( HeyLiz . indexOf ( CLASS_NAME_PLACEHOLDER ) !== - 1 ||
343+ HeyLiz . indexOf ( FULL_CLASS_NAME_PLACEHOLDER ) !== - 1 ||
344+ HeyLiz . indexOf ( INSTANCE_LABEL_PLACEHOLDER ) !== - 1 ||
345+ HeyLiz . indexOf ( INSTANCE_VARIABLE_NAME_PLACEHOLDER ) !== - 1 ) {
346+ throw new Error ( 'HeyLiz - A placeholder didn\'t get replaced: ' + HeyLiz ) ;
347+ }
348+ // HeyLiz end
349+ }
0 commit comments