21
21
22
22
import * as Blockly from 'blockly/core' ;
23
23
import { PythonGenerator } from 'blockly/python' ;
24
- import { Block } from "../toolbox/items" ;
24
+ import { GeneratorContext } from './generator_context' ;
25
+ import { Block } from '../toolbox/items' ;
25
26
import { FunctionArg } from '../blocks/mrc_call_python_function' ;
26
27
import * as commonStorage from '../storage/common_storage' ;
27
28
28
29
// Extends the python generator to collect some information about functions and
29
30
// variables that have been defined so they can be used in other modules.
30
31
31
32
export 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 ;
35
35
36
+ private classMethods : { [ key : string ] : string } = Object . create ( null ) ;
36
37
37
38
constructor ( ) {
38
39
super ( 'Python' ) ;
39
40
}
40
41
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 ;
43
52
}
44
53
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
+ }
47
87
88
+ private produceExportedBlocks ( workspace : Blockly . Workspace ) : Block [ ] {
48
89
// The exported blocks produced here have the extraState.importModule and fields.MODULE values
49
90
// set to the MODULE_NAME_PLACEHOLDER. This is so blocks modules can be renamed and copied
50
91
// without having to change the contents of the modules.
@@ -54,6 +95,8 @@ export class ExtendedPythonGenerator extends PythonGenerator {
54
95
const exportedBlocks = [ ] ;
55
96
56
97
// 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.
57
100
const allProcedures = Blockly . Procedures . allProcedures ( workspace ) ;
58
101
const procedureTuples = allProcedures [ 0 ] . concat ( allProcedures [ 1 ] ) ;
59
102
for ( const procedureTuple of procedureTuples ) {
@@ -149,74 +192,7 @@ export class ExtendedPythonGenerator extends PythonGenerator {
149
192
exportedBlocks . push ( setPythonModuleVariableBlock ) ;
150
193
}
151
194
}
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 ;
220
196
}
221
197
}
222
198
0 commit comments