@@ -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
@@ -121,53 +127,60 @@ export class ExtendedPythonGenerator extends PythonGenerator {
121127 }
122128
123129 private produceExportedBlocks ( workspace : Blockly . Workspace ) : Block [ ] {
124- // The exported blocks produced here have the extraState.importModule and fields.MODULE values
125- // set to the MODULE_NAME_PLACEHOLDER. This is so blocks modules can be renamed and copied
126- // without having to change the contents of the modules.
127- // The placeholders will be replaced with the actual module name before they are added to the
128- // toolbox.
130+ // The exported blocks produced here have some values set to placeholders.
131+ // This is so blocks modules can be renamed and copied without having to change the
132+ // contents of the modules. The placeholders will be replaced with the actual module
133+ // name before they are added to the toolbox. See function replacePlaceholders below.
129134
130135 const exportedBlocks = [ ] ;
131136
132- // All functions are exported.
133- // TODO(lizlooney): instead of looking at procedure blocks, this code needs
134- // to look at mrc_class_method_def blocks.
135- const allProcedures = Blockly . Procedures . allProcedures ( workspace ) ;
136- const procedureTuples = allProcedures [ 0 ] . concat ( allProcedures [ 1 ] ) ;
137- for ( const procedureTuple of procedureTuples ) {
138- const functionName = procedureTuple [ 0 ] ;
139- const blockDefinition = Blockly . Procedures . getDefinition ( functionName , workspace ) ;
140- if ( ! blockDefinition || ! blockDefinition . isEnabled ( ) ) {
141- continue ;
137+ // Look at mrc_class_method_def blocks and make corresponding mrc_call_python_function blocks.
138+ workspace . getBlocksByType ( 'mrc_class_method_def' ) . forEach ( ( classMethodDefBlock ) => {
139+ if ( ! classMethodDefBlock . mrcCanBeCalledOutsideClass ||
140+ ! classMethodDefBlock . isEnabled ( ) ) {
141+ return ;
142142 }
143- const actualFunctionName = super . getProcedureName ( functionName ) ;
144- const hasReturnValue = procedureTuple [ 2 ] ;
145143 const args : FunctionArg [ ] = [ ] ;
146- const parameterNames = procedureTuple [ 1 ] ;
147- parameterNames . forEach ( ( parameterName ) => {
144+ args . push ( {
145+ 'name' : INSTANCE_LABEL_PLACEHOLDER ,
146+ 'type' : FULL_CLASS_NAME_PLACEHOLDER ,
147+ } ) ;
148+ classMethodDefBlock . mrcParameters . forEach ( ( param ) => {
148149 args . push ( {
149- 'name' : parameterName ,
150- 'type' : '' ,
151- } )
150+ 'name' : param . name ,
151+ 'type' : param . type ,
152+ } ) ;
152153 } ) ;
153154 const callFunctionBlock : Block = {
154155 'kind' : 'block' ,
155156 'type' : 'mrc_call_python_function' ,
156157 'extraState' : {
157- 'functionKind' : 'module ' ,
158- 'returnType' : hasReturnValue ? '' : 'None' ,
158+ 'functionKind' : 'instance ' ,
159+ 'returnType' : classMethodDefBlock . mrcPythonMethodName ,
159160 'args' : args ,
160- 'importModule' : commonStorage . MODULE_NAME_PLACEHOLDER ,
161- 'actualFunctionName' : actualFunctionName ,
161+ 'importModule' : '' ,
162+ 'actualFunctionName' : classMethodDefBlock . mrcPythonMethodName ,
162163 'exportedFunction' : true ,
163164 } ,
164165 'fields' : {
165- 'MODULE_OR_CLASS' : commonStorage . MODULE_NAME_PLACEHOLDER ,
166- 'FUNC' : functionName ,
166+ 'MODULE_OR_CLASS' : FULL_CLASS_NAME_PLACEHOLDER ,
167+ 'FUNC' : classMethodDefBlock . getFieldValue ( 'NAME' ) ,
167168 } ,
169+ 'inputs' : {
170+ 'ARG0' : {
171+ 'block' : {
172+ 'type' : 'variables_get' ,
173+ 'fields' : {
174+ 'VAR' : {
175+ 'name' : INSTANCE_VARIABLE_NAME_PLACEHOLDER ,
176+ }
177+ }
178+ }
179+ }
180+ }
168181 } ;
169182 exportedBlocks . push ( callFunctionBlock ) ;
170- }
183+ } ) ;
171184
172185 const allVariables = workspace . getAllVariables ( ) ;
173186 for ( const variableModel of allVariables ) {
@@ -197,32 +210,60 @@ export class ExtendedPythonGenerator extends PythonGenerator {
197210 'kind' : 'block' ,
198211 'type' : 'mrc_get_python_variable' ,
199212 'extraState' : {
200- 'varKind' : 'module ' ,
201- 'moduleOrClassName' : commonStorage . MODULE_NAME_PLACEHOLDER ,
202- 'importModule' : commonStorage . MODULE_NAME_PLACEHOLDER ,
213+ 'varKind' : 'instance ' ,
214+ 'moduleOrClassName' : FULL_CLASS_NAME_PLACEHOLDER ,
215+ 'importModule' : '' ,
203216 'actualVariableName' : actualVariableName ,
217+ 'selfLabel' : INSTANCE_LABEL_PLACEHOLDER ,
218+ 'selfType' : FULL_CLASS_NAME_PLACEHOLDER ,
204219 'exportedVariable' : true ,
205220 } ,
206221 'fields' : {
207- 'MODULE_OR_CLASS' : commonStorage . MODULE_NAME_PLACEHOLDER ,
222+ 'MODULE_OR_CLASS' : FULL_CLASS_NAME_PLACEHOLDER ,
208223 'VAR' : variableName ,
209224 } ,
225+ 'inputs' : {
226+ 'SELF' : {
227+ 'block' : {
228+ 'type' : 'variables_get' ,
229+ 'fields' : {
230+ 'VAR' : {
231+ 'name' : INSTANCE_VARIABLE_NAME_PLACEHOLDER ,
232+ }
233+ }
234+ }
235+ }
236+ }
210237 } ;
211238 exportedBlocks . push ( getPythonModuleVariableBlock ) ;
212239 const setPythonModuleVariableBlock = {
213240 'kind' : 'block' ,
214241 'type' : 'mrc_set_python_variable' ,
215242 'extraState' : {
216- 'varKind' : 'module ' ,
217- 'moduleOrClassName' : commonStorage . MODULE_NAME_PLACEHOLDER ,
218- 'importModule' : commonStorage . MODULE_NAME_PLACEHOLDER ,
243+ 'varKind' : 'instance ' ,
244+ 'moduleOrClassName' : FULL_CLASS_NAME_PLACEHOLDER ,
245+ 'importModule' : '' ,
219246 'actualVariableName' : actualVariableName ,
247+ 'selfLabel' : INSTANCE_LABEL_PLACEHOLDER ,
248+ 'selfType' : FULL_CLASS_NAME_PLACEHOLDER ,
220249 'exportedVariable' : true ,
221250 } ,
222251 'fields' : {
223- 'MODULE_OR_CLASS' : commonStorage . MODULE_NAME_PLACEHOLDER ,
252+ 'MODULE_OR_CLASS' : FULL_CLASS_NAME_PLACEHOLDER ,
224253 'VAR' : variableName ,
225254 } ,
255+ 'inputs' : {
256+ 'SELF' : {
257+ 'block' : {
258+ 'type' : 'variables_get' ,
259+ 'fields' : {
260+ 'VAR' : {
261+ 'name' : INSTANCE_VARIABLE_NAME_PLACEHOLDER ,
262+ }
263+ }
264+ }
265+ }
266+ }
226267 } ;
227268 exportedBlocks . push ( setPythonModuleVariableBlock ) ;
228269 }
@@ -232,3 +273,75 @@ export class ExtendedPythonGenerator extends PythonGenerator {
232273}
233274
234275export const extendedPythonGenerator = new ExtendedPythonGenerator ( ) ;
276+
277+ export function replacePlaceholders ( modulePath : string , exportedBlocks : Block [ ] ) {
278+ const moduleName = commonStorage . getModuleName ( modulePath ) ;
279+ const className = commonStorage . moduleNameToClassName ( moduleName ) ;
280+ const fullClassName = moduleName + '.' + className ;
281+ const instanceLabel = className . charAt ( 0 ) . toLowerCase ( ) + className . slice ( 1 ) ;
282+ const instanceVariableName = instanceLabel ;
283+
284+ exportedBlocks . forEach ( ( block ) => {
285+ if ( block . type === 'mrc_call_python_function' ) {
286+ if ( block . extraState . args . length > 0 &&
287+ block . extraState . args [ 0 ] . name === INSTANCE_LABEL_PLACEHOLDER ) {
288+ block . extraState . args [ 0 ] . name = instanceLabel ;
289+ }
290+ if ( block . extraState . args . length > 0 &&
291+ block . extraState . args [ 0 ] . type === FULL_CLASS_NAME_PLACEHOLDER ) {
292+ block . extraState . args [ 0 ] . type = fullClassName ;
293+ }
294+ if ( block . fields . MODULE_OR_CLASS === FULL_CLASS_NAME_PLACEHOLDER ) {
295+ block . fields . MODULE_OR_CLASS = fullClassName ;
296+ }
297+ if ( block . inputs . ARG0 . block . type === 'variables_get' &&
298+ block . inputs . ARG0 . block . fields . VAR . name === INSTANCE_VARIABLE_NAME_PLACEHOLDER ) {
299+ block . inputs . ARG0 . block . fields . VAR . name = instanceVariableName ;
300+ }
301+ } else if ( block . type === 'mrc_get_python_variable' ) {
302+ if ( block . extraState . moduleOrClassName === FULL_CLASS_NAME_PLACEHOLDER ) {
303+ block . extraState . moduleOrClassName = fullClassName ;
304+ }
305+ if ( block . extraState . selfLabel === INSTANCE_LABEL_PLACEHOLDER ) {
306+ block . extraState . selfLabel = instanceLabel ;
307+ }
308+ if ( block . extraState . selfType === FULL_CLASS_NAME_PLACEHOLDER ) {
309+ block . extraState . selfType = fullClassName ;
310+ }
311+ if ( block . fields . MODULE_OR_CLASS === FULL_CLASS_NAME_PLACEHOLDER ) {
312+ block . fields . MODULE_OR_CLASS = fullClassName ;
313+ }
314+ if ( block . inputs . SELF . block . type === 'variables_get' &&
315+ block . inputs . SELF . block . fields . VAR . name === INSTANCE_VARIABLE_NAME_PLACEHOLDER ) {
316+ block . inputs . SELF . block . fields . VAR . name = instanceVariableName ;
317+ }
318+ } else if ( block . type === 'mrc_set_python_variable' ) {
319+ if ( block . extraState . moduleOrClassName === FULL_CLASS_NAME_PLACEHOLDER ) {
320+ block . extraState . moduleOrClassName = fullClassName ;
321+ }
322+ if ( block . extraState . selfLabel === INSTANCE_LABEL_PLACEHOLDER ) {
323+ block . extraState . selfLabel = instanceLabel ;
324+ }
325+ if ( block . extraState . selfType === FULL_CLASS_NAME_PLACEHOLDER ) {
326+ block . extraState . selfType = fullClassName ;
327+ }
328+ if ( block . fields . MODULE_OR_CLASS === FULL_CLASS_NAME_PLACEHOLDER ) {
329+ block . fields . MODULE_OR_CLASS = fullClassName ;
330+ }
331+ if ( block . inputs . SELF . block . type === 'variables_get' &&
332+ block . inputs . SELF . block . fields . VAR . name === INSTANCE_VARIABLE_NAME_PLACEHOLDER ) {
333+ block . inputs . SELF . block . fields . VAR . name = instanceVariableName ;
334+ }
335+ }
336+ } ) ;
337+
338+ // HeyLiz begin
339+ const HeyLiz = JSON . stringify ( exportedBlocks ) ;
340+ if ( HeyLiz . indexOf ( CLASS_NAME_PLACEHOLDER ) !== - 1 ||
341+ HeyLiz . indexOf ( FULL_CLASS_NAME_PLACEHOLDER ) !== - 1 ||
342+ HeyLiz . indexOf ( INSTANCE_LABEL_PLACEHOLDER ) !== - 1 ||
343+ HeyLiz . indexOf ( INSTANCE_VARIABLE_NAME_PLACEHOLDER ) !== - 1 ) {
344+ throw new Error ( 'HeyLiz - A placeholder didn\'t get replaced: ' + HeyLiz ) ;
345+ }
346+ // HeyLiz end
347+ }
0 commit comments