1 of 55

Adventures in type checking

Blockly User Summit 2019

Mark Gibson

2 of 55

About Us

TODO:

Who Adaptavist are (GROUP PHOTO)

3 of 55

AutoBlocks

Why are types important to us?

4 of 55

Type checking in Blockly

5 of 55

Type checking in Blockly

{

"type": "mouth",

"message0": "mouth %1",

"args0": [

{

"type": "input_value",

"name": "CONSUME",

"check": [

"Air",

"Food",

"Drink"

]

}

]

}

{

"type": "peas",

"message0": "peas",

"output": [

"Nutritious",

"Vegetable",

"Food",

"Legume",

"Healthy"

]

}

6 of 55

It's all about the Venn

Input Output

7 of 55

It's all about the Venn

Input Output

mouth peas

Nutritious

Air Vegetable

Food

Drink Legume

Healthy

8 of 55

It's all about the Venn

Input Output

fussy mouth peas

Air Vegetable

Potato Nutritious

Breaded Food

Sugary Healthy

Unhealthy Legume

9 of 55

Examples from AutoBlocks

10 of 55

Examples from AutoBlocks

Input:

Output:

11 of 55

Examples from AutoBlocks

Input:

["Project", "String"]

Output:

["String"]

12 of 55

Examples from AutoBlocks

Input:

["IssueType", "String"]

Output:

["IssueType"]

13 of 55

Examples from AutoBlocks

Input:

["Issue", "String"]

Output:

["Issue"]

from a variable

14 of 55

Lists and loops

15 of 55

Lists and loops

No items = unknown types

any

?

List of ?

16 of 55

Lists and loops

Types flow from right to left

Issue

Issue

List of Issues

17 of 55

Lists and loops

What other items can we add?

List of Issues and ?

?

?

18 of 55

Lists and loops

NO!

List of Issues and ?

?

?

19 of 55

Lists and loops

Restricted inputs

List of Issues

Issue

Issue

20 of 55

How did we implement this?

21 of 55

How did we implement this?

  • Higher Types

22 of 55

How did we implement this?

  • Higher Types
  • Blockly extension: type_from

23 of 55

Higher Types

Inputs

Outputs

24 of 55

Higher Types

Inputs

Accept a list of anything:

["List:*"]

Outputs

25 of 55

Higher Types

Inputs

Accept a list of anything:

["List:*"]

Only accept a list of a specific type:

["List:Issue"]

Outputs

26 of 55

Higher Types

Inputs

Accept a list of anything:

["List:*"]

Only accept a list of a specific type:

["List:Issue"]

Accept one or many of a specific type:

["Issue", "List:Issue"]

Outputs

27 of 55

Higher Types

Inputs

Accept a list of anything:

["List:*"]

Only accept a list of a specific type:

["List:Issue"]

Accept one or many of a specific type:

["Issue", "List:Issue"]

Outputs

Returning a specific type:

["List:Issue", "List:*"]

Allows connection to input:

  • only accepts a list of Issue
  • that accepts a list of anything

28 of 55

Higher Types

Input Output

for each create list with

List:* List:Issue

29 of 55

Higher Types - wild ideas

One

["1:*"]

["1:Something"]

Many

["N:*"]

["N:Something"]

One or Many

Input:

["X:*"]

["X:Something"]

Output:

["1:Something", "X:Something", "1:*", "X:*"]

["N:Something", "X:Something", "N:*", "X:*"]

30 of 55

type_from - Blockly Extension

31 of 55

type_from - Blockly Extension

Inherit an input check, output type, or variable field type from�the output of the block connected to another input!

["From:INPUT"]

["From:INPUT+HigherType"]

["From:INPUT-HigherType"]

["From:INPUT^HigherType"]

32 of 55

type_from - Blockly Extension

{

"type": "loop_foreach",

"message0": "for each %1 in %2",

"args0": [{

"type": "field_variable",

"name": "ITEM",

"variable": "item_#",

"variableTypes": [

"From:LIST-List"

],

"defaultType": [

"From:LIST-List"

],

"definition": true

}, {

"type": "input_value",

"name": "LIST",

"check": "List:*"

}],

"extensions": [

"type_from"

]

}

{

"type": "list_create_with",

"output": "From:ADD0+List",

"extensions": [

"type_from"

],

"mutator": "create_with_list_mutator"

}

The ADD0 input will be added by the mutator

33 of 55

BUT...

34 of 55

Lists as inputs

35 of 55

Lists as inputs

36 of 55

Lists as inputs

Types should flow left to right

List of Components

37 of 55

Lists as inputs

Types should flow left to right

List of Components

Component

38 of 55

Lists as inputs

But they don't 😒

39 of 55

Lists as inputs

🤷

40 of 55

Variables in Blockly

  • Already supports typed variables

41 of 55

Variables in Blockly

  • Already supports typed variables
  • BUT, only a single type

42 of 55

Variables in Blockly

  • Already supports typed variables
  • BUT, only a single type

Why is this problem?

43 of 55

Variables in Blockly

  • Already supports typed variables
  • BUT, only a single type

Why is this problem?

  • type_from - transfering types to a variable field

44 of 55

Variables in Blockly

  • Already supports typed variables
  • BUT, only a single type

Why is this problem?

  • type_from - transfering types to a variable field
  • and event triggers...

45 of 55

Variables in Blockly

Variable Field

["Issue", "IssueEvent"]

46 of 55

Variables in Blockly

Output

["Issue", "IssueEvent"]

47 of 55

Variables in Blockly

48 of 55

Multi-type Variables - Monkey Patch

  • Blockly.FieldVariable
  • Blockly.VariableMap
  • Blockly.Xml.domToVariables

Issue #1997

https://github.com/google/blockly/issues/1997

49 of 55

Conclusion

50 of 55

Conclusion

Types are hard

51 of 55

Conclusion

Types are hard

The current type system in Blockly is not enough

52 of 55

Conclusion

Types are hard

The current type system in Blockly is not enough

Need a variable type model consistent with connection type checking

53 of 55

Conclusion

Types are hard

The current type system in Blockly is not enough

Need a variable type model consistent with connection type checking

And/or…

  • A standard way to enhance core functionality
  • Plugin points (or listeners) for connections
  • Pluggable connection checking system (like the new renderer)

54 of 55

Questions?

55 of 55

Adventures in type checking

Blockly User Summit 2019

Mark Gibson