diff options
-rw-r--r-- | doc/type-system.md | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/doc/type-system.md b/doc/type-system.md new file mode 100644 index 0000000..d1982a1 --- /dev/null +++ b/doc/type-system.md @@ -0,0 +1,80 @@ +The TA Type System +================== + +Why do we Need a Type System? +----------------------------- + +The purpose of the type system is to have a consistent and +standardized way of type-checking and type-converting the +arguments of blocks. For example, the 'minus' block takes two +arguments of type TYPE_NUMBER. But that doesn't mean that only +number blocks can be attached to its argument docks. In fact, colors, +single characters, and numeric strings (like `"-5.2"`) can easily be converted +to numbers. The type system takes care of this. When e.g., a color is attached +to the argument dock of the 'minus' block, the type system tries to find a +converter from the type TYPE_COLOR (the type of the color block) to the type +TYPE_NUMBER. If it finds one (and in this case it does), then the converter is +applied to the argument. A converter is simply a callable (usually a function) +and applying it simply means calling it and passing it the value of the +argument block as a parameter. The converter returns the number that +corresponds to the color, and the number is passed on to the 'minus' block. +This way, the 'minus' block does not have to know about colors, characters, or +numeric strings. Likewise, the color block also does not have to care about +how its value can be converted to a number. + +Why do some Blocks Need Return Types? +------------------------------------- + +The argument to the 'minus' block (to continue our example) need +not be a simple value block; it can also be the result of a +complex mathematical operation, i.e. the return type of another +block such as 'multiply'. The 'minus' block still demands a +value of type TYPE_NUMBER, so the 'multiply' block must provide +information about its return type. This is why blocks that can +be used as arguments to other blocks must specify a return type. + +What if I want to Specify Two Types at the Same Time? +----------------------------------------------------- + +You can use the function `or_` (defined in `taprimitive.py`) to +create disjunctions of `Primitive`s, argument lists, `ArgSlot`s, +or types. Simply pass the disjuncts to it as its arguments. +E.g., to create a disjunction between the types TYPE_NUMBER and +TYPE_STRING, call + + or_(TYPE_NUMBER, TYPE_STRING) + +The return value of the `or_` function will in this case be a +`TypeDisjunction` object that holds the two types. It means the +same as 'TYPE_NUMBER or TYPE_STRING' in English. The `or_` +function knows automatically from the type of its arguments +which type of object it must return. + +What if it is Impossible to Predict the Return Type of a Block? +--------------------------------------------------------------- + +In the case of the 'box' block, for example, it is impossible to +predict what type it will return at runtime because one cannot +foresee what will be inside the box at runtime. (E.g., the box +contents could depend on input from the keyboard or camera.) +This is where the special type TYPE_BOX comes in handy. It +allows you to postpone the search for a type converter until the +type of the box contents is known. As soon as this is the case, +the type system will automatically apply the appropriate type +converter. + +How to Add a New Type +--------------------- + +To add a new type to the type system, you need to instantiate a +new `Type` object and store it in a constant whose name starts +with `TYPE_`. You would do this in `tatype.py`: + + TYPE_MYTYPE = Type('TYPE_MYTYPE', 99) + +The number argument to the `Type` constructor can have an +arbitrary value, as long as it is different from the value of +every other `Type` object. + +Optionally, you can add converters for the new type. You can do +so by extending the dictionary `TYPE_CONVERTERS` in `tatype.py`. |