import * as Show from './Show';
import { type Show as ShowType } from './Show';
import * as ArrayUtil from '../core/ArrayUtil';
import * as ObjectUtil from '../core/ObjectUtil';
import * as StringUtil from '../core/StringUtil';
import * as Type from '../core/Type';
import * as Pnode from './Pnode';
import { type Pnode as PnodeType } from './Pnode';
export interface Pprint {
pprint: (a: A) => PnodeType;
}
export const pprint = (f: (a: A) => PnodeType): Pprint => ({ pprint: f });
export const render = (a: A, pp: Pprint): string => {
const n = pp.pprint(a);
return Pnode.render(n);
};
export const pprintShow = (show: ShowType): Pprint =>
pprint((a) => Pnode.single(show.show(a)));
export const pprintUndefined: Pprint = pprintShow(Show.showUndefined);
export const pprintNull: Pprint = pprintShow(Show.showNull);
export const pprintString: Pprint = pprintShow(Show.showString);
export const pprintBoolean: Pprint = pprintShow(Show.showBoolean);
export const pprintNumber: Pprint = pprintShow(Show.showNumber);
export const pprintFunction: Pprint = pprintShow(Show.showFunction);
export const pprintStringCtor: Pprint = pprintShow(Show.showStringCtor);
export const pprintJsonStringify: Pprint = pprintShow(Show.showJsonStringify);
export const pprintArray = (pprintA: Pprint): Pprint> => pprint((xs) => {
const c = ArrayUtil.mapDelimit(xs, pprintA.pprint, Pnode.appendEnd(','));
return Pnode.pnode('[', c, ']');
});
export const pprintRecord = (pprintA: Pprint): Pprint> => pprint((r) => {
const tuples = ObjectUtil.toTuples(r);
const cnode: (t: [string, A]) => PnodeType = ([ k, v ]) => {
const pv = pprintA.pprint(v);
const start = StringUtil.doubleQuote(k) + ': ';
return Pnode.prependStart(start)(pv);
};
const c = ArrayUtil.mapDelimit(tuples, cnode, Pnode.appendEnd(','));
return Pnode.pnode('{', c, '}');
});
export const pprintAny: Pprint = pprint((a) => {
if (Type.isUndefined(a)) {
return pprintUndefined.pprint(a);
} else if (Type.isNull(a)) {
return pprintNull.pprint(a);
} else if (Type.isNumber(a)) {
return pprintNumber.pprint(a);
} else if (Type.isBoolean(a)) {
return pprintBoolean.pprint(a);
} else if (Type.isFunction(a)) {
return pprintFunction.pprint(a);
} else if (Type.isString(a)) {
return pprintString.pprint(a);
} else if (Type.isArray(a)) {
return pprintArray(pprintAny).pprint(a);
} else if (Type.isObject(a)) {
return pprintRecord(pprintAny).pprint(a);
} else {
return pprintStringCtor.pprint(a);
}
});