forked from RaspberryPiFoundation/blockly
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathvariable_map.js
More file actions
238 lines (222 loc) · 8.04 KB
/
Copy pathvariable_map.js
File metadata and controls
238 lines (222 loc) · 8.04 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
/**
* @license
* Visual Blocks Editor
*
* Copyright 2017 Google Inc.
* https://developers.google.com/blockly/
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @fileoverview Object representing a map of variables and their types.
* @author [email protected] (Marisa Leung)
*/
'use strict';
goog.provide('Blockly.VariableMap');
/**
* Class for a variable map. This contains a dictionary data structure with
* variable types as keys and lists of variables as values. The list of
* variables are the type indicated by the key.
* @param {!Blockly.Workspace} workspace The workspace this map belongs to.
* @constructor
*/
Blockly.VariableMap = function(workspace) {
/**
* A map from variable type to list of variable names. The lists contain all
* of the named variables in the workspace, including variables
* that are not currently in use.
* @type {!Object<string, !Array.<Blockly.VariableModel>>}
* @private
*/
this.variableMap_ = {};
/**
* The workspace this map belongs to.
* @type {!Blockly.Workspace}
*/
this.workspace = workspace;
};
/**
* Clear the variable map.
*/
Blockly.VariableMap.prototype.clear = function() {
this.variableMap_ = new Object(null);
};
/**
* Rename the given variable by updating its name in the variable map.
* @param {?Blockly.VariableModel} variable Variable to rename.
* @param {string} newName New variable name.
*/
Blockly.VariableMap.prototype.renameVariable = function(variable, newName) {
var newVariable = this.getVariable(newName);
var variableIndex = -1;
var newVariableIndex = -1;
var type = '';
if (variable || newVariable) {
type = (variable || newVariable).type;
}
var variableList = this.getVariablesOfType(type);
if (variable) {
variableIndex = variableList.indexOf(variable);
}
if (newVariable){ // see if I can get rid of newVariable dependency
newVariableIndex = variableList.indexOf(newVariable);
}
if (variableIndex == -1 && newVariableIndex == -1) {
this.createVariable(newName, '');
console.log('Tried to rename an non-existent variable.');
} else if (variableIndex == newVariableIndex ||
variableIndex != -1 && newVariableIndex == -1) {
// Only changing case, or renaming to a completely novel name.
var variableToRename = this.variableMap_[type][variableIndex];
Blockly.Events.fire(new Blockly.Events.VarRename(variableToRename,
newName));
variableToRename.name = newName;
} else if (variableIndex != -1 && newVariableIndex != -1) {
// Renaming one existing variable to another existing variable.
// The case might have changed, so we update the destination ID.
var variableToRename = this.variableMap_[type][newVariableIndex];
Blockly.Events.fire(new Blockly.Events.VarRename(variableToRename,
newName));
var variableToDelete = this.variableMap_[type][variableIndex];
Blockly.Events.fire(new Blockly.Events.VarDelete(variableToDelete));
variableToRename.name = newName;
this.variableMap_[type].splice(variableIndex, 1);
}
};
/**
* Create a variable with a given name, optional type, and optional id.
* @param {!string} name The name of the variable. This must be unique across
* variables and procedures.
* @param {?string} opt_type The type of the variable like 'int' or 'string'.
* Does not need to be unique. Field_variable can filter variables based on
* their type. This will default to '' which is a specific type.
* @param {?string} opt_id The unique id of the variable. This will default to
* a UUID.
* @return {?Blockly.VariableModel} The newly created variable.
*/
Blockly.VariableMap.prototype.createVariable = function(name, opt_type, opt_id) {
var variable = this.getVariable(name);
if (variable) {
if (opt_type && variable.type != opt_type) {
throw Error('Variable "' + name + '" is already in use and its type is "'
+ variable.type + '" which conflicts with the passed in ' +
'type, "' + opt_type + '".');
}
if (opt_id && variable.getId() != opt_id) {
throw Error('Variable "' + name + '" is already in use and its id is "'
+ variable.getId() + '" which conflicts with the passed in ' +
'id, "' + opt_id + '".');
}
// The variable already exists and has the same id and type.
return variable;
}
if (opt_id && this.getVariableById(opt_id)) {
throw Error('Variable id, "' + opt_id + '", is already in use.');
}
opt_id = opt_id || Blockly.utils.genUid();
opt_type = opt_type || '';
variable = new Blockly.VariableModel(this.workspace, name, opt_type, opt_id);
// If opt_type is not a key, create a new list.
if (!this.variableMap_[opt_type]) {
this.variableMap_[opt_type] = [variable];
} else {
// Else append the variable to the preexisting list.
this.variableMap_[opt_type].push(variable);
}
return variable;
};
/**
* Delete a variable.
* @param {Blockly.VariableModel} variable Variable to delete.
*/
Blockly.VariableMap.prototype.deleteVariable = function(variable) {
var variableList = this.variableMap_[variable.type];
for (var i = 0, tempVar; tempVar = variableList[i]; i++) {
if (tempVar.getId() == variable.getId()) {
variableList.splice(i, 1);
Blockly.Events.fire(new Blockly.Events.VarDelete(variable));
return;
}
}
};
/**
* Find the variable by the given name and return it. Return null if it is not
* found.
* @param {!string} name The name to check for.
* @return {?Blockly.VariableModel} The variable with the given name, or null if
* it was not found.
*/
Blockly.VariableMap.prototype.getVariable = function(name) {
var keys = Object.keys(this.variableMap_);
for (var i = 0; i < keys.length; i++ ) {
var key = keys[i];
for (var j = 0, variable; variable = this.variableMap_[key][j]; j++) {
if (Blockly.Names.equals(variable.name, name)) {
return variable;
}
}
}
return null;
};
/**
* Find the variable by the given id and return it. Return null if it is not
* found.
* @param {!string} id The id to check for.
* @return {?Blockly.VariableModel} The variable with the given id.
*/
Blockly.VariableMap.prototype.getVariableById = function(id) {
var keys = Object.keys(this.variableMap_);
for (var i = 0; i < keys.length; i++ ) {
var key = keys[i];
for (var j = 0, variable; variable = this.variableMap_[key][j]; j++) {
if (variable.getId() == id) {
return variable;
}
}
}
return null;
};
/**
* Get a list containing all of the variables of a specified type. If type is
* null, return list of variables with empty string type.
* @param {?string} type Type of the variables to find.
* @return {Array.<Blockly.VariableModel>} The sought after variables of the
* passed in type. An empty array if none are found.
*/
Blockly.VariableMap.prototype.getVariablesOfType = function(type) {
type = type || '';
var variable_list = this.variableMap_[type];
if (variable_list) {
return variable_list.slice();
}
return [];
};
/**
* Return all variable types.
* @return {!Array.<string>} List of variable types.
*/
Blockly.VariableMap.prototype.getVariableTypes = function() {
return Object.keys(this.variableMap_);
};
/**
* Return all variables of all types.
* @return {!Array.<Blockly.VariableModel>} List of variable models.
*/
Blockly.VariableMap.prototype.getAllVariables = function() {
var all_variables = [];
var keys = Object.keys(this.variableMap_);
for (var i = 0; i < keys.length; i++ ) {
all_variables = all_variables.concat(this.variableMap_[keys[i]]);
}
return all_variables;
};