@@ -27,6 +27,12 @@ import { FunctionArg } from '../blocks/mrc_call_python_function';
2727import * as MechanismContainerHolder from '../blocks/mrc_mechanism_component_holder' ;
2828import * as commonStorage from '../storage/common_storage' ;
2929
30+
31+ const CLASS_NAME_PLACEHOLDER = '%class_name%' ;
32+ const FULL_CLASS_NAME_PLACEHOLDER = '%full_class_name%' ;
33+ const INSTANCE_LABEL_PLACEHOLDER = '%instance_label%' ;
34+ const INSTANCE_VARIABLE_NAME_PLACEHOLDER = '%instance_var_name%' ;
35+
3036export class OpModeDetails {
3137 constructor ( private name : string , private group : string , private enabled : boolean , private type : string ) { }
3238 annotations ( ) : string {
@@ -56,7 +62,7 @@ export class ExtendedPythonGenerator extends PythonGenerator {
5662 private ports : { [ key : string ] : string } = Object . create ( null ) ;
5763 // Opmode details
5864 private details : OpModeDetails | null = null ;
59-
65+
6066 constructor ( ) {
6167 super ( 'Python' ) ;
6268 }
@@ -180,53 +186,60 @@ export class ExtendedPythonGenerator extends PythonGenerator {
180186 }
181187
182188 private produceExportedBlocks ( workspace : Blockly . Workspace ) : Block [ ] {
183- // The exported blocks produced here have the extraState.importModule and fields.MODULE values
184- // set to the MODULE_NAME_PLACEHOLDER. This is so blocks modules can be renamed and copied
185- // without having to change the contents of the modules.
186- // The placeholders will be replaced with the actual module name before they are added to the
187- // toolbox.
189+ // The exported blocks produced here have some values set to placeholders.
190+ // This is so blocks modules can be renamed and copied without having to change the
191+ // contents of the modules. The placeholders will be replaced with the actual module
192+ // name before they are added to the toolbox. See function replacePlaceholders below.
188193
189194 const exportedBlocks = [ ] ;
190195
191- // All functions are exported.
192- // TODO(lizlooney): instead of looking at procedure blocks, this code needs
193- // to look at mrc_class_method_def blocks.
194- const allProcedures = Blockly . Procedures . allProcedures ( workspace ) ;
195- const procedureTuples = allProcedures [ 0 ] . concat ( allProcedures [ 1 ] ) ;
196- for ( const procedureTuple of procedureTuples ) {
197- const functionName = procedureTuple [ 0 ] ;
198- const blockDefinition = Blockly . Procedures . getDefinition ( functionName , workspace ) ;
199- if ( ! blockDefinition || ! blockDefinition . isEnabled ( ) ) {
200- continue ;
196+ // Look at mrc_class_method_def blocks and make corresponding mrc_call_python_function blocks.
197+ workspace . getBlocksByType ( 'mrc_class_method_def' ) . forEach ( ( classMethodDefBlock ) => {
198+ if ( ! classMethodDefBlock . mrcCanBeCalledOutsideClass ||
199+ ! classMethodDefBlock . isEnabled ( ) ) {
200+ return ;
201201 }
202- const actualFunctionName = super . getProcedureName ( functionName ) ;
203- const hasReturnValue = procedureTuple [ 2 ] ;
204202 const args : FunctionArg [ ] = [ ] ;
205- const parameterNames = procedureTuple [ 1 ] ;
206- parameterNames . forEach ( ( parameterName ) => {
203+ args . push ( {
204+ 'name' : INSTANCE_LABEL_PLACEHOLDER ,
205+ 'type' : FULL_CLASS_NAME_PLACEHOLDER ,
206+ } ) ;
207+ classMethodDefBlock . mrcParameters . forEach ( ( param ) => {
207208 args . push ( {
208- 'name' : parameterName ,
209- 'type' : '' ,
210- } )
209+ 'name' : param . name ,
210+ 'type' : param . type ,
211+ } ) ;
211212 } ) ;
212213 const callFunctionBlock : Block = {
213214 'kind' : 'block' ,
214215 'type' : 'mrc_call_python_function' ,
215216 'extraState' : {
216- 'functionKind' : 'module ' ,
217- 'returnType' : hasReturnValue ? '' : 'None' ,
217+ 'functionKind' : 'instance ' ,
218+ 'returnType' : classMethodDefBlock . mrcPythonMethodName ,
218219 'args' : args ,
219- 'importModule' : commonStorage . MODULE_NAME_PLACEHOLDER ,
220- 'actualFunctionName' : actualFunctionName ,
220+ 'importModule' : '' ,
221+ 'actualFunctionName' : classMethodDefBlock . mrcPythonMethodName ,
221222 'exportedFunction' : true ,
222223 } ,
223224 'fields' : {
224- 'MODULE_OR_CLASS' : commonStorage . MODULE_NAME_PLACEHOLDER ,
225- 'FUNC' : functionName ,
225+ 'MODULE_OR_CLASS' : FULL_CLASS_NAME_PLACEHOLDER ,
226+ 'FUNC' : classMethodDefBlock . getFieldValue ( 'NAME' ) ,
226227 } ,
228+ 'inputs' : {
229+ 'ARG0' : {
230+ 'block' : {
231+ 'type' : 'variables_get' ,
232+ 'fields' : {
233+ 'VAR' : {
234+ 'name' : INSTANCE_VARIABLE_NAME_PLACEHOLDER ,
235+ }
236+ }
237+ }
238+ }
239+ }
227240 } ;
228241 exportedBlocks . push ( callFunctionBlock ) ;
229- }
242+ } ) ;
230243
231244 const allVariables = workspace . getAllVariables ( ) ;
232245 for ( const variableModel of allVariables ) {
@@ -256,32 +269,60 @@ export class ExtendedPythonGenerator extends PythonGenerator {
256269 'kind' : 'block' ,
257270 'type' : 'mrc_get_python_variable' ,
258271 'extraState' : {
259- 'varKind' : 'module ' ,
260- 'moduleOrClassName' : commonStorage . MODULE_NAME_PLACEHOLDER ,
261- 'importModule' : commonStorage . MODULE_NAME_PLACEHOLDER ,
272+ 'varKind' : 'instance ' ,
273+ 'moduleOrClassName' : FULL_CLASS_NAME_PLACEHOLDER ,
274+ 'importModule' : '' ,
262275 'actualVariableName' : actualVariableName ,
276+ 'selfLabel' : INSTANCE_LABEL_PLACEHOLDER ,
277+ 'selfType' : FULL_CLASS_NAME_PLACEHOLDER ,
263278 'exportedVariable' : true ,
264279 } ,
265280 'fields' : {
266- 'MODULE_OR_CLASS' : commonStorage . MODULE_NAME_PLACEHOLDER ,
281+ 'MODULE_OR_CLASS' : FULL_CLASS_NAME_PLACEHOLDER ,
267282 'VAR' : variableName ,
268283 } ,
284+ 'inputs' : {
285+ 'SELF' : {
286+ 'block' : {
287+ 'type' : 'variables_get' ,
288+ 'fields' : {
289+ 'VAR' : {
290+ 'name' : INSTANCE_VARIABLE_NAME_PLACEHOLDER ,
291+ }
292+ }
293+ }
294+ }
295+ }
269296 } ;
270297 exportedBlocks . push ( getPythonModuleVariableBlock ) ;
271298 const setPythonModuleVariableBlock = {
272299 'kind' : 'block' ,
273300 'type' : 'mrc_set_python_variable' ,
274301 'extraState' : {
275- 'varKind' : 'module ' ,
276- 'moduleOrClassName' : commonStorage . MODULE_NAME_PLACEHOLDER ,
277- 'importModule' : commonStorage . MODULE_NAME_PLACEHOLDER ,
302+ 'varKind' : 'instance ' ,
303+ 'moduleOrClassName' : FULL_CLASS_NAME_PLACEHOLDER ,
304+ 'importModule' : '' ,
278305 'actualVariableName' : actualVariableName ,
306+ 'selfLabel' : INSTANCE_LABEL_PLACEHOLDER ,
307+ 'selfType' : FULL_CLASS_NAME_PLACEHOLDER ,
279308 'exportedVariable' : true ,
280309 } ,
281310 'fields' : {
282- 'MODULE_OR_CLASS' : commonStorage . MODULE_NAME_PLACEHOLDER ,
311+ 'MODULE_OR_CLASS' : FULL_CLASS_NAME_PLACEHOLDER ,
283312 'VAR' : variableName ,
284313 } ,
314+ 'inputs' : {
315+ 'SELF' : {
316+ 'block' : {
317+ 'type' : 'variables_get' ,
318+ 'fields' : {
319+ 'VAR' : {
320+ 'name' : INSTANCE_VARIABLE_NAME_PLACEHOLDER ,
321+ }
322+ }
323+ }
324+ }
325+ }
285326 } ;
286327 exportedBlocks . push ( setPythonModuleVariableBlock ) ;
287328 }
@@ -301,3 +342,75 @@ export class ExtendedPythonGenerator extends PythonGenerator {
301342}
302343
303344export const extendedPythonGenerator = new ExtendedPythonGenerator ( ) ;
345+
346+ export function replacePlaceholders ( modulePath : string , exportedBlocks : Block [ ] ) {
347+ const moduleName = commonStorage . getModuleName ( modulePath ) ;
348+ const className = commonStorage . moduleNameToClassName ( moduleName ) ;
349+ const fullClassName = moduleName + '.' + className ;
350+ const instanceLabel = className . charAt ( 0 ) . toLowerCase ( ) + className . slice ( 1 ) ;
351+ const instanceVariableName = instanceLabel ;
352+
353+ exportedBlocks . forEach ( ( block ) => {
354+ if ( block . type === 'mrc_call_python_function' ) {
355+ if ( block . extraState . args . length > 0 &&
356+ block . extraState . args [ 0 ] . name === INSTANCE_LABEL_PLACEHOLDER ) {
357+ block . extraState . args [ 0 ] . name = instanceLabel ;
358+ }
359+ if ( block . extraState . args . length > 0 &&
360+ block . extraState . args [ 0 ] . type === FULL_CLASS_NAME_PLACEHOLDER ) {
361+ block . extraState . args [ 0 ] . type = fullClassName ;
362+ }
363+ if ( block . fields . MODULE_OR_CLASS === FULL_CLASS_NAME_PLACEHOLDER ) {
364+ block . fields . MODULE_OR_CLASS = fullClassName ;
365+ }
366+ if ( block . inputs . ARG0 . block . type === 'variables_get' &&
367+ block . inputs . ARG0 . block . fields . VAR . name === INSTANCE_VARIABLE_NAME_PLACEHOLDER ) {
368+ block . inputs . ARG0 . block . fields . VAR . name = instanceVariableName ;
369+ }
370+ } else if ( block . type === 'mrc_get_python_variable' ) {
371+ if ( block . extraState . moduleOrClassName === FULL_CLASS_NAME_PLACEHOLDER ) {
372+ block . extraState . moduleOrClassName = fullClassName ;
373+ }
374+ if ( block . extraState . selfLabel === INSTANCE_LABEL_PLACEHOLDER ) {
375+ block . extraState . selfLabel = instanceLabel ;
376+ }
377+ if ( block . extraState . selfType === FULL_CLASS_NAME_PLACEHOLDER ) {
378+ block . extraState . selfType = fullClassName ;
379+ }
380+ if ( block . fields . MODULE_OR_CLASS === FULL_CLASS_NAME_PLACEHOLDER ) {
381+ block . fields . MODULE_OR_CLASS = fullClassName ;
382+ }
383+ if ( block . inputs . SELF . block . type === 'variables_get' &&
384+ block . inputs . SELF . block . fields . VAR . name === INSTANCE_VARIABLE_NAME_PLACEHOLDER ) {
385+ block . inputs . SELF . block . fields . VAR . name = instanceVariableName ;
386+ }
387+ } else if ( block . type === 'mrc_set_python_variable' ) {
388+ if ( block . extraState . moduleOrClassName === FULL_CLASS_NAME_PLACEHOLDER ) {
389+ block . extraState . moduleOrClassName = fullClassName ;
390+ }
391+ if ( block . extraState . selfLabel === INSTANCE_LABEL_PLACEHOLDER ) {
392+ block . extraState . selfLabel = instanceLabel ;
393+ }
394+ if ( block . extraState . selfType === FULL_CLASS_NAME_PLACEHOLDER ) {
395+ block . extraState . selfType = fullClassName ;
396+ }
397+ if ( block . fields . MODULE_OR_CLASS === FULL_CLASS_NAME_PLACEHOLDER ) {
398+ block . fields . MODULE_OR_CLASS = fullClassName ;
399+ }
400+ if ( block . inputs . SELF . block . type === 'variables_get' &&
401+ block . inputs . SELF . block . fields . VAR . name === INSTANCE_VARIABLE_NAME_PLACEHOLDER ) {
402+ block . inputs . SELF . block . fields . VAR . name = instanceVariableName ;
403+ }
404+ }
405+ } ) ;
406+
407+ // HeyLiz begin
408+ const HeyLiz = JSON . stringify ( exportedBlocks ) ;
409+ if ( HeyLiz . indexOf ( CLASS_NAME_PLACEHOLDER ) !== - 1 ||
410+ HeyLiz . indexOf ( FULL_CLASS_NAME_PLACEHOLDER ) !== - 1 ||
411+ HeyLiz . indexOf ( INSTANCE_LABEL_PLACEHOLDER ) !== - 1 ||
412+ HeyLiz . indexOf ( INSTANCE_VARIABLE_NAME_PLACEHOLDER ) !== - 1 ) {
413+ throw new Error ( 'HeyLiz - A placeholder didn\'t get replaced: ' + HeyLiz ) ;
414+ }
415+ // HeyLiz end
416+ }
0 commit comments