List<Type> types = new ArrayList<Type>(size);
if (isAction) {
if (runtime.test("optionVariant")) {
// Strip away any list and action types.
Type t = analyzer.current().type;
if (AST.isList(t)) t = AST.getArgument(t);
if (AST.isAction(t)) t = AST.getArgument(t);
types.add(t);
} else {
types.add(AST.NODE);
}
}
for (Binding b : children) {
types.add(analyzer.type(b.element));
}
// Unify the tuple type with any previous tuple type and update
// its variant.
final TupleT t1 = ast.toTuple(name);
final TupleT t2 = new TupleT(name, types);
final boolean fresh = (null == t1.getTypes());
if (fresh && ! runtime.test("optionVariant")) {
ast.add(t1, ast.toVariant("Node", false));
}
if (DEBUG) {
runtime.console().p(name).p(" : ");
ast.print(t2, runtime.console(), false, true, null);
runtime.console().pln();
}
if (! fresh) {
Type result = ast.combine(t1, t2, flatten, strict);
if (result.isError()) {
runtime.error("unable to consistently type tuple '" + name + "'",
sequence);
runtime.errConsole().loc(sequence).p(": error: 1st type is '");
ast.print(t1, runtime.errConsole(), false, true, null);
runtime.errConsole().pln("'");
runtime.errConsole().loc(sequence).p(": error: 2nd type is '");
ast.print(t2, runtime.errConsole(), false, true, null);
runtime.errConsole().pln("'").flush();
} else {
if (DEBUG) {
runtime.console().p(" -> ");
ast.print(result, runtime.console(), false, true, null);
runtime.console().pln();
}
t1.setTypes(result.toTuple().getTypes());
}
} else if (flatten) {
Type result = ast.flatten(t2, strict);
if (result.isError()) {
runtime.error("unable to flatten tuple '" + name + "'", sequence);
runtime.errConsole().loc(sequence).p(": error: type is '");
ast.print(t2, runtime.errConsole(), false, true, null);
runtime.errConsole().pln("'").flush();
} else {
t1.setTypes(result.toTuple().getTypes());
}
} else {
t1.setTypes(types);
}