Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion server_python_scripts/blocks_base_classes/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@
from .robot_base import RobotBase

__all__ = ['OpMode', 'Teleop', 'Auto', 'Test', 'Name', 'Group'
'Mechanism', 'RobotBase']
'Mechanism', 'RobotBase']
25 changes: 25 additions & 0 deletions server_python_scripts/blocks_base_classes/robot_base.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,39 @@
# This is the class all robots derive from

from typing import Callable

class RobotBase:
def __init__(self):
self.hardware = []
# In self.event_handlers, the keys are the event names, the values are a list of handlers.
self.event_handlers = {}

def register_event_handler(self, event_name: str, event_handler: Callable) -> None:
if event_name in self.event_handlers:
self.event_handlers[event_name].append(event_handler)
else:
self.event_handlers[event_name] = [event_handler]

def unregister_event_handler(self, event_name: str, event_handler: Callable) -> None:
if event_name in self.event_handlers:
if event_handler in self.event_handlers[event_name]:
self.event_handlers[event_name].remove(event_handler)
if not self.event_handlers[event_name]:
del self.event_handlers[event_name]

def fire_event(self, event_name: str, *args) -> None:
if event_name in self.event_handlers:
for event_handler in self.event_handlers[event_name]:
event_handler(*args)

def start(self) -> None:
for hardware in self.hardware:
hardware.start()

def update(self) -> None:
for hardware in self.hardware:
hardware.update()

def stop(self) -> None:
for hardware in self.hardware:
hardware.stop()
27 changes: 18 additions & 9 deletions src/blocks/mrc_call_python_function.ts
Original file line number Diff line number Diff line change
Expand Up @@ -588,6 +588,8 @@ export const pythonFromBlock = function(
generator.addImport(callPythonFunctionBlock.mrcImportModule);
}
let code;
let needOpenParen = true;
let delimiterBeforeArgs = '';
let argStartIndex = 0;
switch (callPythonFunctionBlock.mrcFunctionKind) {
case FunctionKind.BUILT_IN: {
Expand Down Expand Up @@ -637,9 +639,9 @@ export const pythonFromBlock = function(
}
case FunctionKind.EVENT: {
const eventName = block.getFieldValue(FIELD_EVENT_NAME);
code =
'if self.events.get("' + eventName + '", None):\n' +
generator.INDENT + 'self.events["' + eventName + '"]';
code = 'self.fire_event("' + eventName + '"';
needOpenParen = false;
delimiterBeforeArgs = ', ';
break;
}
case FunctionKind.INSTANCE_COMPONENT: {
Expand Down Expand Up @@ -671,7 +673,14 @@ export const pythonFromBlock = function(
default:
throw new Error('mrcFunctionKind has unexpected value: ' + callPythonFunctionBlock.mrcFunctionKind)
}
code += '(' + generateCodeForArguments(callPythonFunctionBlock, generator, argStartIndex) + ')';
if (needOpenParen) {
code += '(';
}
const codeForArgs = generateCodeForArguments(callPythonFunctionBlock, generator, argStartIndex);
if (codeForArgs) {
code += delimiterBeforeArgs + codeForArgs;
}
code += ')';
if (block.outputConnection) {
return [code, Order.FUNCTION_CALL];
} else {
Expand Down Expand Up @@ -699,22 +708,22 @@ function generateCodeForArguments(
}

function getMethodCallers(workspace: Blockly.Workspace, otherBlockId: string): Blockly.Block[] {
return workspace.getBlocksByType('mrc_call_python_function').filter((block) => {
return workspace.getBlocksByType(BLOCK_NAME).filter((block) => {
return (block as CallPythonFunctionBlock).mrcOtherBlockId === otherBlockId;
});
}

export function renameMethodCallers(workspace: Blockly.Workspace, otherBlockId: string, newName: string): void {
for (const block of getMethodCallers(workspace, otherBlockId)) {
getMethodCallers(workspace, otherBlockId).forEach(block => {
(block as CallPythonFunctionBlock).renameMethodCaller(newName);
}
});
}

export function mutateMethodCallers(
workspace: Blockly.Workspace, otherBlockId: string, methodOrEvent: commonStorage.Method | commonStorage.Event) {
const oldRecordUndo = Blockly.Events.getRecordUndo();

for (const block of getMethodCallers(workspace, otherBlockId)) {
getMethodCallers(workspace, otherBlockId).forEach(block => {
const callBlock = block as CallPythonFunctionBlock;
// Get the extra state before changing the call block.
const oldExtraState = callBlock.saveExtraState();
Expand All @@ -738,7 +747,7 @@ export function mutateMethodCallers(
);
Blockly.Events.setRecordUndo(oldRecordUndo);
}
}
});
}

// Functions used for creating blocks for the toolbox.
Expand Down
43 changes: 40 additions & 3 deletions src/blocks/mrc_class_method_def.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ import { MUTATOR_BLOCK_NAME, PARAM_CONTAINER_BLOCK_NAME, MethodMutatorArgBlock }

export const BLOCK_NAME = 'mrc_class_method_def';

const FIELD_METHOD_NAME = 'NAME';
export const FIELD_METHOD_NAME = 'NAME';

type Parameter = {
name: string,
Expand Down Expand Up @@ -347,7 +347,7 @@ function findLegalMethodName(name: string, block: ClassMethodDefBlock): string {
function isMethodNameUsed(
name: string, workspace: Blockly.Workspace, opt_exclude?: Blockly.Block): boolean {
const nameLowerCase = name.toLowerCase();
for (const block of workspace.getBlocksByType('mrc_class_method_def')) {
for (const block of workspace.getBlocksByType(BLOCK_NAME)) {
if (block === opt_exclude) {
continue;
}
Expand Down Expand Up @@ -409,7 +409,7 @@ export const pythonFromBlock = function (
if (block.mrcPythonMethodName == '__init__') {
let class_specific = generator.getClassSpecificForInit();
branch = generator.INDENT + 'super().__init__(' + class_specific + ')\n' +
generator.defineClassVariables() + branch;
generator.generateInitStatements() + branch;
}
else if (generator.inBaseClassMethod(blocklyName)){
// Special case for methods inherited from the based class: generate the
Expand Down Expand Up @@ -510,3 +510,40 @@ function createClassMethodDefBlock(
fields[FIELD_METHOD_NAME] = functionData.functionName;
return new toolboxItems.Block(BLOCK_NAME, extraState, fields, null);
}

// Misc

export function getMethodsForWithin(
workspace: Blockly.Workspace,
methods: commonStorage.Method[]): void {
workspace.getBlocksByType(BLOCK_NAME).forEach(block => {
const method = (block as ClassMethodDefBlock).getMethodForWithin();
if (method) {
methods.push(method);
}
});
}

export function getMethodsForOutside(
workspace: Blockly.Workspace,
methods: commonStorage.Method[]): void {
workspace.getBlocksByType(BLOCK_NAME).forEach(block => {
const method = (block as ClassMethodDefBlock).getMethodForOutside();
if (method) {
methods.push(method);
}
});
}

export function getMethodNamesAlreadyOverriddenInWorkspace(
workspace: Blockly.Workspace,
methodNamesAlreadyOverridden: string[]): void {
workspace.getBlocksByType(BLOCK_NAME).forEach(block => {
const methodDefBlock = block as ClassMethodDefBlock;
// If the user cannot change the signature, it means the block defines a method that overrides a baseclass method.
// That's what we are looking for here.
if (!methodDefBlock.canChangeSignature()) {
methodNamesAlreadyOverridden.push(methodDefBlock.getMethodName());
}
});
}
27 changes: 19 additions & 8 deletions src/blocks/mrc_component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export const OUTPUT_NAME = 'mrc_component';
export const FIELD_NAME = 'NAME';
export const FIELD_TYPE = 'TYPE';

export type ConstructorArg = {
type ConstructorArg = {
name: string,
type: string,
};
Expand Down Expand Up @@ -146,6 +146,23 @@ const COMPONENT = {
className: componentType,
};
},
getNewPort: function (this: ComponentBlock, i: number): string {
let extension = '';
if (i != 0) {
extension = '_' + (i + 1).toString();
}
return this.getFieldValue(FIELD_NAME) + extension + '_port';
},
getHardwarePorts: function (this: ComponentBlock, ports: {[key: string]: string}): void {
// Collect the hardware ports for this component block that are needed to generate
// the define_hardware method. (The key is the port, the value is the type.)
if (this.hideParams) {
for (let i = 0; i < this.mrcArgs.length; i++) {
const newPort = this.getNewPort(i);
ports[newPort] = this.mrcArgs[i].type;
}
}
},
}

export const setup = function () {
Expand All @@ -171,13 +188,7 @@ export const pythonFromBlock = function (
code += ', '
}
if (block.hideParams) {
let extension = '';
if (i != 0) {
extension = '_' + (i + 1).toString();
}
const newPort = block.getFieldValue(FIELD_NAME) + extension + '_port';
generator.addHardwarePort(newPort, block.mrcArgs[i].type);
code += block.mrcArgs[i].name + ' = ' + newPort;
code += block.mrcArgs[i].name + ' = ' + block.getNewPort(i);
} else {
code += block.mrcArgs[i].name + ' = ' + generator.valueToCode(block, fieldName, Order.NONE);
}
Expand Down
4 changes: 2 additions & 2 deletions src/blocks/mrc_event.ts
Original file line number Diff line number Diff line change
Expand Up @@ -230,8 +230,8 @@ export const setup = function () {
}

export const pythonFromBlock = function (
block: EventBlock,
generator: ExtendedPythonGenerator) {
_block: EventBlock,
_generator: ExtendedPythonGenerator) {
// TODO (Alan): What should this do here??
return '';
}
Expand Down
Loading