You are working with a toy language grammar that supports three kinds of types: primitives, generics, and tuples. This system is used for defining function signatures. Primitives are lowercase keywords: int, float, char. Generics are uppercase letters followed by an optional digit, e.g. T, T1, U2. Tuples are comma-separated lists of types wrapped in square brackets, and they may be nested arbitrarily, e.g. [int, T1, char] or [int, [float, T2]]. A function signature is written as params -> return, where params is a (possibly empty) tuple of types and return is a single type. Your task is to implement two classes, Node and Function, plus a standalone helper infer_return. Node represents either a primitive, a generic, or a tuple of children Nodes. Function holds a list of param Nodes and a single return Node. Part 1: implement to_str() on both classes so that a Node prints as its literal syntax and a Function prints the entire signature. Part 2: implement infer_return(function, param_values) -> str. Given a Function instance and a list of concrete type strings for its parameters (no generics), substitute every generic in the return type with the concrete type that was bound by the corresponding parameter position, then return the resulting concrete type string. Raise an error if any generic is unbound or if a param_value conflicts with the declared param type (e.g. passing int where char is expected).