2121
2222import * as Blockly from 'blockly/core' ;
2323import { PythonGenerator } from 'blockly/python' ;
24- import { Block } from "../toolbox/items" ;
24+ import { GeneratorContext } from './generator_context' ;
25+ import { Block } from '../toolbox/items' ;
2526import { FunctionArg } from '../blocks/mrc_call_python_function' ;
2627import * as commonStorage from '../storage/common_storage' ;
2728
2829// Extends the python generator to collect some information about functions and
2930// variables that have been defined so they can be used in other modules.
3031
3132export class ExtendedPythonGenerator extends PythonGenerator {
32- private currentModule : commonStorage . Module | null = null ;
33- private mapWorkspaceIdToExportedBlocks : { [ key : string ] : Block [ ] } = Object . create ( null ) ;
34- protected methods_ : { [ key : string ] : string } = Object . create ( null ) ;
33+ private workspace : Blockly . Workspace | null = null ;
34+ private context : GeneratorContext | null = null ;
3535
36+ private classMethods : { [ key : string ] : string } = Object . create ( null ) ;
3637
3738 constructor ( ) {
3839 super ( 'Python' ) ;
3940 }
4041
41- setCurrentModule ( module : commonStorage . Module | null ) {
42- this . currentModule = module ;
42+ workspaceToCode ( workspace : Blockly . Workspace , context : GeneratorContext ) : string {
43+ this . workspace = workspace ;
44+ this . context = context ;
45+ this . context . clear ( ) ;
46+
47+ const code = super . workspaceToCode ( workspace ) ;
48+
49+ this . workspace = workspace ;
50+ this . context = null ;
51+ return code ;
4352 }
4453
45- init ( workspace : Blockly . Workspace ) {
46- super . init ( workspace ) ;
54+ /**
55+ * Add an import statement for a python module.
56+ */
57+ addImport ( importModule : string ) : void {
58+ this . definitions_ [ 'import_' + importModule ] = 'import ' + importModule ;
59+ }
60+
61+ /**
62+ * Add a class method definition.
63+ */
64+ addClassMethodDefinition ( nameFieldValue : string , methodName : string , code : string ) : void {
65+ this . context . addClassMethodName ( nameFieldValue , methodName ) ;
66+ this . classMethods [ methodName ] = code ;
67+ }
68+
69+ finish ( code : string ) : string {
70+ if ( this . context ) {
71+ const className = this . context . getClassName ( ) ;
72+ const classParent = this . context . getClassParent ( ) ;
73+ this . addImport ( classParent ) ;
74+ const classDef = 'class ' + className + '(' + classParent + '):\n' ;
75+ const classMethods = [ ] ;
76+ for ( let name in this . classMethods ) {
77+ classMethods . push ( this . classMethods [ name ] )
78+ }
79+ this . classMethods = Object . create ( null ) ;
80+ code = classDef + this . prefixLines ( classMethods . join ( '\n\n' ) , this . INDENT ) ;
81+
82+ this . context . setExportedBlocks ( this . produceExportedBlocks ( this . workspace ) ) ;
83+ }
84+
85+ return super . finish ( code ) ;
86+ }
4787
88+ private produceExportedBlocks ( workspace : Blockly . Workspace ) : Block [ ] {
4889 // The exported blocks produced here have the extraState.importModule and fields.MODULE values
4990 // set to the MODULE_NAME_PLACEHOLDER. This is so blocks modules can be renamed and copied
5091 // without having to change the contents of the modules.
@@ -54,6 +95,8 @@ export class ExtendedPythonGenerator extends PythonGenerator {
5495 const exportedBlocks = [ ] ;
5596
5697 // All functions are exported.
98+ // TODO(lizlooney): instead of looking at procedure blocks, this code needs
99+ // to look at mrc_class_method_def blocks.
57100 const allProcedures = Blockly . Procedures . allProcedures ( workspace ) ;
58101 const procedureTuples = allProcedures [ 0 ] . concat ( allProcedures [ 1 ] ) ;
59102 for ( const procedureTuple of procedureTuples ) {
@@ -149,74 +192,7 @@ export class ExtendedPythonGenerator extends PythonGenerator {
149192 exportedBlocks . push ( setPythonModuleVariableBlock ) ;
150193 }
151194 }
152- this . mapWorkspaceIdToExportedBlocks [ workspace . id ] = exportedBlocks ;
153- }
154-
155- getExportedBlocks ( workspace : Blockly . Workspace ) : Block [ ] {
156- return this . mapWorkspaceIdToExportedBlocks [ workspace . id ] ;
157- }
158-
159- // Functions used in python code generation for multiple python blocks.
160- addImport ( importModule : string ) : void {
161- this . definitions_ [ 'import_' + importModule ] = 'import ' + importModule ;
162- }
163- addMethod ( methodName : string , code : string ) : void {
164- this . methods_ [ methodName ] = code ;
165- }
166-
167- classParentFromModuleType ( moduleType : string ) : string {
168- if ( moduleType == commonStorage . MODULE_TYPE_PROJECT ) {
169- return "RobotBase" ;
170- }
171- if ( moduleType == commonStorage . MODULE_TYPE_OPMODE ) {
172- return "OpMode" ;
173- }
174- if ( moduleType == commonStorage . MODULE_TYPE_MECHANISM ) {
175- return "Mechanism" ;
176- }
177- return "" ;
178- }
179-
180- finish ( code : string ) : string {
181- if ( ! this . currentModule ) {
182- return super . finish ( code ) ;
183- }
184- let className = 'Robot' ; // Default for Workspace
185- if ( this . currentModule . moduleType != commonStorage . MODULE_TYPE_WORKSPACE ) {
186- className = this . currentModule . moduleName ;
187- }
188- let classParent = this . classParentFromModuleType ( this . currentModule . moduleType ) ;
189- this . addImport ( classParent ) ;
190-
191- // Convert the definitions dictionary into a list.
192- const imports = [ ] ;
193- const definitions = [ ] ;
194-
195- for ( let name in this . definitions_ ) {
196- const def = this . definitions_ [ name ] ;
197- if ( def . match ( / ^ ( f r o m \s + \S + \s + ) ? i m p o r t \s + \S + / ) ) {
198- imports . push ( def ) ;
199- } else {
200- definitions . push ( def ) ;
201- }
202- }
203- const methods = [ ] ;
204- for ( let name in this . methods_ ) {
205- methods . push ( this . methods_ [ name ] )
206- }
207-
208- this . definitions_ = Object . create ( null ) ;
209- this . functionNames_ = Object . create ( null ) ;
210- this . methods_ = Object . create ( null ) ;
211-
212- this . isInitialized = false ;
213-
214- let class_def = "class " + className + "(" + classParent + "):\n" ;
215-
216- this . nameDB_ ! . reset ( ) ;
217- const allDefs = imports . join ( '\n' ) + '\n\n' + definitions . join ( '\n\n' ) ;
218- return allDefs . replace ( / \n \n + / g, '\n\n' ) . replace ( / \n * $ / , '\n\n\n' ) + class_def +
219- this . prefixLines ( methods . join ( '\n\n' ) , this . INDENT ) ;
195+ return exportedBlocks ;
220196 }
221197}
222198
0 commit comments