UNPKG

derw

Version:

An Elm-inspired language that transpiles to TypeScript

1,394 lines (1,393 loc) 49.2 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.FunctionTypeToken = exports.BaseTypeToken = void 0; exports.StringToken = StringToken; exports.FormatStringToken = FormatStringToken; exports.KeywordToken = KeywordToken; exports.IdentifierToken = IdentifierToken; exports.LiteralToken = LiteralToken; exports.ColonToken = ColonToken; exports.ArrowToken = ArrowToken; exports.CommentToken = CommentToken; exports.MultilineCommentToken = MultilineCommentToken; exports.AssignToken = AssignToken; exports.CommaToken = CommaToken; exports.OpenCurlyBracesToken = OpenCurlyBracesToken; exports.CloseCurlyBracesToken = CloseCurlyBracesToken; exports.OpenBracketToken = OpenBracketToken; exports.CloseBracketToken = CloseBracketToken; exports.PipeToken = PipeToken; exports.OperatorToken = OperatorToken; exports.WhitespaceToken = WhitespaceToken; exports.checkKeywordToken = checkKeywordToken; exports.tokenize = tokenize; exports.tokenizeType = tokenizeType; exports.tokensToString = tokensToString; exports.rootTypeTokensToString = rootTypeTokensToString; const Tokens_types_kernel_1 = require("./Tokens_types_kernel"); Object.defineProperty(exports, "BaseTypeToken", { enumerable: true, get: function () { return Tokens_types_kernel_1.BaseTypeToken; } }); Object.defineProperty(exports, "FunctionTypeToken", { enumerable: true, get: function () { return Tokens_types_kernel_1.FunctionTypeToken; } }); const List = __importStar(require("./stdlib/List")); function Empty(args) { return { kind: "Empty", ...args, }; } function InString(args) { return { kind: "InString", ...args, }; } function InFormatString(args) { return { kind: "InFormatString", ...args, }; } function InBracket(args) { return { kind: "InBracket", ...args, }; } function InSquareBracket(args) { return { kind: "InSquareBracket", ...args, }; } function InWhitespace(args) { return { kind: "InWhitespace", ...args, }; } function Keyword(args) { return { kind: "Keyword", ...args, }; } const keywords = ["if", "then", "else", "type", "alias", "import", "exposing", "as", "let", "in", "case", "of", "do", "return", "typeclass", "impl"]; function StringToken(args) { return { kind: "StringToken", ...args, }; } function FormatStringToken(args) { return { kind: "FormatStringToken", ...args, }; } function KeywordToken(args) { return { kind: "KeywordToken", ...args, }; } function IdentifierToken(args) { return { kind: "IdentifierToken", ...args, }; } function LiteralToken(args) { return { kind: "LiteralToken", ...args, }; } function ColonToken(args) { return { kind: "ColonToken", ...args, }; } function ArrowToken(args) { return { kind: "ArrowToken", ...args, }; } function CommentToken(args) { return { kind: "CommentToken", ...args, }; } function MultilineCommentToken(args) { return { kind: "MultilineCommentToken", ...args, }; } function AssignToken(args) { return { kind: "AssignToken", ...args, }; } function CommaToken(args) { return { kind: "CommaToken", ...args, }; } function OpenCurlyBracesToken(args) { return { kind: "OpenCurlyBracesToken", ...args, }; } function CloseCurlyBracesToken(args) { return { kind: "CloseCurlyBracesToken", ...args, }; } function OpenBracketToken(args) { return { kind: "OpenBracketToken", ...args, }; } function CloseBracketToken(args) { return { kind: "CloseBracketToken", ...args, }; } function PipeToken(args) { return { kind: "PipeToken", ...args, }; } function OperatorToken(args) { return { kind: "OperatorToken", ...args, }; } function WhitespaceToken(args) { return { kind: "WhitespaceToken", ...args, }; } function isLiteral(body) { if (body === "true" || body === "false") { return true; } else { if (isNaN(parseFloat(body))) { return false; } else { return true; } ; } } const operators = ["<", "<=", ">", ">=", "==", "!=", "-", "+", "*", "/", "%", "|>", "<|", "&&", "||"]; function isOperator(body) { if (operators.indexOf(body) === -1) { return false; } else { return true; } } function checkKeywordToken(currentToken) { switch (currentToken) { case "=": { return [AssignToken({})]; } case "{": { return [OpenCurlyBracesToken({})]; } case "}": { return [CloseCurlyBracesToken({})]; } case "{}": { return [OpenCurlyBracesToken({}), CloseCurlyBracesToken({})]; } case "--": { return [CommentToken({})]; } case "{-": { return [MultilineCommentToken({ body: "{-" })]; } case "-}": { return [MultilineCommentToken({ body: "-}" })]; } default: { if (keywords.indexOf(currentToken) > -1) { return [KeywordToken({ body: currentToken })]; } else { if (isLiteral(currentToken)) { return [LiteralToken({ body: currentToken })]; } else { if (isOperator(currentToken)) { return [OperatorToken({ body: currentToken })]; } else { return [IdentifierToken({ body: currentToken })]; } ; } ; } ; } } } function TokenizeInfo(args) { return { ...args, }; } function isEscape(char) { return char.charCodeAt(0) === 92; } function not(a) { if (a) { return false; } else { return true; } } function findIndentLevelHelper(tokens) { switch (tokens.length) { case tokens.length: { if (tokens.length === 1) { const [token] = tokens; switch (token.kind) { case "WhitespaceToken": { const { body } = token; if (body.indexOf("\n") > -1) { const split = body.split("\n"); const last = split[split.length - 1]; return last.length; } else { return body.length; } ; } default: { return 0; } } ; } } case tokens.length: { if (tokens.length >= 1) { const [token, ...rest] = tokens; switch (token.kind) { case "WhitespaceToken": { const { body } = token; if (body.indexOf("\n") > -1) { const split = body.split("\n"); const last = split[split.length - 1]; return last.length; } else { return findIndentLevelHelper(rest); } ; } default: { return findIndentLevelHelper(rest); } } ; } } default: { return 0; } } } function findIndentLevel(info) { return findIndentLevelHelper(List.reverse(info.tokens)); } function tokenizeHelpInWhitespaceOrEmpty(initialInfo) { const char = initialInfo.body[initialInfo.index]; const info = char !== " " && char !== "\n" && initialInfo.currentToken.length > 0 ? { ...initialInfo, currentToken: "", state: Empty({}), tokens: List.append(initialInfo.tokens, [WhitespaceToken({ body: initialInfo.currentToken })]), } : initialInfo; const previousChar = info.index === 0 ? "" : info.body[info.index - 1]; const isLast = info.body.length - 1 === info.index; const nextInfo = (function () { switch (char) { case `"`: { return { ...info, state: InString({}), currentToken: info.currentToken + char, }; } case "`": { return { ...info, state: InFormatString({ indentLevel: findIndentLevel(info) }), currentToken: info.currentToken + char, }; } case "(": { return { ...info, state: InBracket({ depth: 0 }), tokens: List.append(info.tokens, [OpenBracketToken({})]), }; } case ")": { return { ...info, state: Empty({}), tokens: List.append(info.tokens, [CloseBracketToken({})]), }; } case "[": { return { ...info, state: InSquareBracket({ depth: 0 }), currentToken: info.currentToken + char, }; } case "\n": { return { ...info, state: InWhitespace({}), currentToken: info.currentToken + char, }; } case " ": { return { ...info, state: InWhitespace({}), currentToken: info.currentToken + char, }; } case ":": { if (info.body[info.index + 1] === ":") { const token = OperatorToken({ body: "::" }); return { ...info, tokens: List.append(info.tokens, [token]), index: info.index + 1, }; } else { return { ...info, tokens: List.append(info.tokens, [ColonToken({})]) }; } ; } case "-": { if (info.body[info.index + 1] === ">") { return info; } else { return { ...info, state: Keyword({}), currentToken: info.currentToken + char, }; } ; } case ">": { switch (previousChar) { case "-": { return { ...info, tokens: List.append(info.tokens, [ArrowToken({})]), currentToken: "", }; } case "|": { return { ...info, tokens: List.append(info.tokens, [OperatorToken({ body: "|>" })]), currentToken: "", }; } default: { return { ...info, state: Keyword({}), currentToken: info.currentToken + char, }; } } ; } case ",": { return { ...info, tokens: List.append(info.tokens, [CommaToken({})]) }; } case "|": { if (info.body[info.index + 1] === ">" || info.body[info.index + 1] === "|") { return info; } else { if (previousChar === "|") { return { ...info, tokens: List.append(info.tokens, [OperatorToken({ body: "||" })]), currentToken: "", }; } else { return { ...info, tokens: List.append(info.tokens, [PipeToken({})]) }; } ; } ; } case "{": { if (info.body[info.index + 1] === "-") { return { ...info, currentToken: info.currentToken + char, state: Keyword({}), }; } else { return { ...info, tokens: List.append(info.tokens, [OpenCurlyBracesToken({})]), currentToken: "", }; } ; } case "}": { return { ...info, tokens: List.append(info.tokens, [CloseCurlyBracesToken({})]), currentToken: "", }; } default: { if (isEscape(char)) { return { ...info, tokens: List.append(info.tokens, [OperatorToken({ body: char })]), currentToken: "", }; } else { const otherTokens = isLast ? checkKeywordToken(info.currentToken + char) : []; return { ...info, tokens: List.append(info.tokens, otherTokens), currentToken: info.currentToken + char, state: Keyword({}), }; } ; } } })(); return { ...nextInfo, index: nextInfo.index + 1 }; } function tokenizeHelp(info) { const char = info.body[info.index]; const previousChar = info.index === 0 ? "" : info.body[info.index - 1]; const isLast = info.body.length - 1 === info.index; if (info.index >= info.body.length) { return info; } else { switch (info.state.kind) { case "InWhitespace": { return tokenizeHelpInWhitespaceOrEmpty(info); } case "Empty": { return tokenizeHelpInWhitespaceOrEmpty(info); } case "InString": { if (char === `"` && not(isEscape(previousChar))) { const token = StringToken({ body: info.currentToken + `"` }); return { ...info, state: Empty({}), currentToken: "", tokens: List.append(info.tokens, [token]), index: info.index + 1, }; } else { return { ...info, currentToken: info.currentToken + char, index: info.index + 1, }; } ; } case "InFormatString": { const { indentLevel } = info.state; if (char === "`" && not(isEscape(previousChar))) { const token = FormatStringToken({ body: info.currentToken + "`", indentLevel, }); return { ...info, state: Empty({}), currentToken: "", tokens: List.append(info.tokens, [token]), index: info.index + 1, }; } else { return { ...info, currentToken: info.currentToken + char, index: info.index + 1, }; } ; } case "InBracket": { const { depth } = info.state; if (char === ")") { if (depth === 0) { const otherTokens = tokenize(info.currentToken); const allTokens = (function (x) { return List.append(x, [CloseBracketToken({})]); })(List.append(info.tokens, otherTokens)); return { ...info, state: Empty({}), currentToken: "", tokens: allTokens, index: info.index + 1, }; } else { return { ...info, state: InBracket({ depth: depth - 1 }), currentToken: info.currentToken + ")", index: info.index + 1, }; } } else { if (char === "(") { return { ...info, state: InBracket({ depth: depth + 1 }), currentToken: info.currentToken + "(", index: info.index + 1, }; } else { return { ...info, currentToken: info.currentToken + char, index: info.index + 1, }; } ; } ; } case "InSquareBracket": { const { depth } = info.state; if (char === "]") { if (depth === 0) { const newToken = LiteralToken({ body: info.currentToken + "]" }); const allTokens = List.append(info.tokens, [newToken]); return { ...info, state: Empty({}), currentToken: "", tokens: allTokens, index: info.index + 1, }; } else { return { ...info, state: InSquareBracket({ depth: depth - 1 }), currentToken: info.currentToken + char, index: info.index + 1, }; } } else { if (char === "[") { return { ...info, state: InSquareBracket({ depth: depth + 1 }), currentToken: info.currentToken + char, index: info.index + 1, }; } else { return { ...info, currentToken: info.currentToken + char, index: info.index + 1, }; } ; } ; } case "Keyword": { const isWhitespace = char === "\n" || char === " "; if (isLast) { if (char === ")") { const otherTokens = checkKeywordToken(info.currentToken); const allTokens = (function (x) { return List.append(x, [CloseBracketToken({})]); })(List.append(info.tokens, otherTokens)); return { ...info, state: Empty({}), currentToken: "", tokens: allTokens, index: info.index + 1, }; } else { const currentToken = isWhitespace ? info.currentToken : info.currentToken + char; const otherTokens = checkKeywordToken(currentToken); const maybeWhiteSpaceToken = isLast && isWhitespace ? [WhitespaceToken({ body: char })] : []; const allTokens = (function (x) { return List.append(x, maybeWhiteSpaceToken); })(List.append(info.tokens, otherTokens)); return { ...info, state: Empty({}), currentToken: "", tokens: allTokens, index: info.index + 1, }; } } else { if (isWhitespace) { const otherTokens = checkKeywordToken(info.currentToken); const maybeWhiteSpaceToken = isLast ? [WhitespaceToken({ body: char })] : []; const allTokens = (function (x) { return List.append(x, maybeWhiteSpaceToken); })(List.append(info.tokens, otherTokens)); const currentToken = isLast ? "" : char; return { ...info, state: Empty({}), currentToken, tokens: allTokens, index: info.index + 1, }; } else { switch (char) { case ":": { if (info.body[info.index + 1] === ":") { const allTokens = List.append(info.tokens, [IdentifierToken({ body: info.currentToken }), OperatorToken({ body: "::" })]); return { ...info, currentToken: "", tokens: allTokens, state: Empty({}), index: info.index + 2, }; } else { const allTokens = List.append(info.tokens, [IdentifierToken({ body: info.currentToken }), ColonToken({})]); return { ...info, currentToken: "", tokens: allTokens, state: Empty({}), index: info.index + 1, }; } ; } case ",": { const allTokens = List.append(info.tokens, [IdentifierToken({ body: info.currentToken }), CommaToken({})]); return { ...info, currentToken: "", tokens: allTokens, state: Empty({}), index: info.index + 1, }; } case "(": { const otherTokens = checkKeywordToken(info.currentToken); const allTokens = (function (x) { return List.append(x, [OpenBracketToken({})]); })(List.append(info.tokens, otherTokens)); return { ...info, currentToken: "", tokens: allTokens, state: Empty({}), index: info.index + 1, }; } case ")": { const allTokens = List.append(info.tokens, [IdentifierToken({ body: info.currentToken }), CloseBracketToken({})]); return { ...info, currentToken: "", tokens: allTokens, state: Empty({}), index: info.index + 1, }; } default: { return { ...info, currentToken: info.currentToken + char, index: info.index + 1, }; } } ; } ; } ; } } ; } } function tokenize(body) { const initialState = { state: Empty({}), currentToken: "", tokens: [], body, index: 0, }; const chars = body.split(""); const calculatedState = List.statefulFold(function (item, state) { return tokenizeHelp(state); }, initialState, chars); return calculatedState.tokens; } function tokenToString(token) { switch (token.kind) { case "ArrowToken": { return "->"; } case "AssignToken": { return "="; } case "CloseBracketToken": { return ")"; } case "CloseCurlyBracesToken": { return "}"; } case "ColonToken": { return ":"; } case "CommaToken": { return ","; } case "CommentToken": { return "--"; } case "FormatStringToken": { const { body } = token; return body; } case "IdentifierToken": { const { body } = token; return body; } case "MultilineCommentToken": { const { body } = token; return body; } case "KeywordToken": { const { body } = token; return body; } case "LiteralToken": { const { body } = token; return body; } case "OpenBracketToken": { return "("; } case "OpenCurlyBracesToken": { return "{"; } case "OperatorToken": { const { body } = token; return body; } case "PipeToken": { return "|"; } case "StringToken": { const { body } = token; return body; } case "WhitespaceToken": { const { body } = token; return body; } } } function tokensToString(tokens) { return (function (x) { return x.join(""); })(List.map(tokenToString, tokens)); } function Ok(args) { return { kind: "Ok", ...args, }; } function Err(args) { return { kind: "Err", ...args, }; } function TokenizeTypeInfo(args) { return { ...args, }; } function ComposeTypeInfo(args) { return { ...args, }; } function finalCompose(info) { if (info.error.length > 0) { return Err({ error: info.error[0] }); } else { const flattened = List.foldl(function (x, xs) { return xs.concat(x); }, [], info.collectedInners); return Ok({ value: [(0, Tokens_types_kernel_1.BaseTypeToken)({ body: [info.buffer[0], ...flattened] })] }); } } function composeType(info) { if (info.index >= info.buffer.length || info.error.length > 0) { return info; } else { const t = info.buffer[info.index]; switch (t.kind) { case "OpenBracketToken": { if (info.depth > 0) { return composeType({ ...info, inner: List.append(info.inner, [t]), depth: info.depth + 1, index: info.index + 1, }); } else { return composeType({ ...info, depth: info.depth + 1, index: info.index + 1, }); } ; } case "CloseBracketToken": { if (info.depth === 1) { const innerTokenized = tokenizeType(info.inner); switch (innerTokenized.kind) { case "Err": { const { error } = innerTokenized; return composeType({ ...info, error: [error] }); } case "Ok": { const { value } = innerTokenized; return composeType({ ...info, collectedInners: List.append(info.collectedInners, [value]), inner: [], depth: 0, index: info.index + 1, }); } } ; } else { if (info.depth === 0) { return composeType({ ...info, index: info.index + 1 }); } else { return composeType({ ...info, index: info.index + 1, inner: List.append(info.inner, [t]), depth: info.depth - 1, }); } ; } ; } case "IdentifierToken": { const { body } = t; if (info.depth === 0) { const tokenized = tokenizeType(tokenize(body)); switch (tokenized.kind) { case "Err": { const { error } = tokenized; return composeType({ ...info, error: [error] }); } case "Ok": { const { value } = tokenized; return composeType({ ...info, index: info.index + 1, collectedInners: List.append(info.collectedInners, [value]), }); } } ; } else { return composeType({ ...info, index: info.index + 1, inner: List.append(info.inner, [t]), }); } ; } case "ArrowToken": { if (info.depth === 0) { return composeType({ ...info, index: info.index + 1 }); } else { return composeType({ ...info, index: info.index + 1, inner: List.append(info.inner, [t]), }); } ; } default: { return composeType({ ...info, index: info.index + 1 }); } } ; } } function processTokenizeTypeInfo(info) { const hasOpenBracketToken = info.currentBuffer.find(function (t) { return t.kind === "OpenBracketToken"; }) ? true : false; const isFunction = info.currentBuffer.find(function (t) { return t.kind === "ArrowToken"; }) ? true : false; switch (info.currentBuffer.length) { case info.currentBuffer.length: { if (info.currentBuffer.length >= 1) { const [first, ...rest] = info.currentBuffer; if (hasOpenBracketToken) { const tokenized = first.kind === "IdentifierToken" && not(isFunction) ? finalCompose(composeType({ buffer: info.currentBuffer, index: 1, depth: 0, inner: [], collectedInners: [], error: [], })) : tokenizeType(info.currentBuffer); switch (tokenized.kind) { case "Err": { const { error } = tokenized; return Err({ error }); } case "Ok": { const { value } = tokenized; if (isFunction) { return Ok({ value: List.append(info.rootTypeTokens, [(0, Tokens_types_kernel_1.FunctionTypeToken)({ body: value })]) }); } else { return Ok({ value: List.append(info.rootTypeTokens, value) }); } ; } } ; } else { if (isFunction) { const tokenized = tokenizeType(info.currentBuffer); switch (tokenized.kind) { case "Err": { const { error } = tokenized; return Err({ error }); } case "Ok": { const { value } = tokenized; return Ok({ value: List.append(info.rootTypeTokens, [(0, Tokens_types_kernel_1.FunctionTypeToken)({ body: value })]) }); } } ; } else { function innerHelp(tokens) { switch (tokens.length) { case 0: { return Ok({ value: [] }); } case tokens.length: { if (tokens.length >= 1) { const [x, ...rest] = tokens; const tokenized = tokenizeType([x]); switch (tokenized.kind) { case "Err": { const { error } = tokenized; return Err({ error }); } case "Ok": { const { value } = tokenized; const _res832456996 = innerHelp(rest); switch (_res832456996.kind) { case "Ok": { const { value: other } = _res832456996; return Ok({ value: List.append(value, other) }); } case "Err": { const { error } = _res832456996; return Err({ error }); } } ; } } ; } } default: { return Ok({ value: [] }); } } } const inner = info.currentBuffer.length > 1 ? innerHelp(info.currentBuffer.slice(1)) : Ok({ value: [] }); const otherTokens = (function () { switch (inner.kind) { case "Ok": { const { value } = inner; return (0, Tokens_types_kernel_1.BaseTypeToken)({ body: List.append([info.currentBuffer[0]], value) }); } case "Err": { const { error } = inner; return []; } } })(); switch (inner.kind) { case "Err": { const { error } = inner; return inner; } case "Ok": { const { value } = inner; return (function (x) { return Ok({ value: x }); })(List.append(info.rootTypeTokens, otherTokens)); } } ; } ; } ; } } default: { return Ok({ value: info.rootTypeTokens }); } } } function finalTokenizeType(info) { if (info.error.length > 0) { return Err({ error: info.error[0] }); } else { return processTokenizeTypeInfo(info); } } function tokenizeTypeHelp(info) { if (info.index >= info.tokens.length || info.error.length > 0) { return info; } else { const token = info.tokens[info.index]; const nextInfo = (function () { switch (token.kind) { case "OpenBracketToken": { if (info.indent > 0 || info.currentBuffer.length > 0) { return { ...info, index: info.index + 1, indent: info.indent + 1, currentBuffer: List.append(info.currentBuffer, [token]), }; } else { return { ...info, index: info.index + 1, indent: info.indent + 1, }; } ; } case "CloseBracketToken": { if (info.indent > 0) { return { ...info, indent: info.indent - 1, index: info.index + 1, currentBuffer: List.append(info.currentBuffer, [token]), }; } else { return { ...info, indent: info.indent - 1, index: info.index + 1, }; } ; } case "ArrowToken": { if (info.indent === 0) { const isFunction = info.currentBuffer.find(function (t) { return t.kind === "ArrowToken"; }) ? true : false; const tokenized = tokenizeType(info.currentBuffer); switch (tokenized.kind) { case "Err": { const { error } = tokenized; return { ...info, error: [error] }; } case "Ok": { const { value } = tokenized; if (isFunction) { return { ...info, index: info.index + 1, rootTypeTokens: List.append(info.rootTypeTokens, [(0, Tokens_types_kernel_1.FunctionTypeToken)({ body: value })]), currentBuffer: [], }; } else { return { ...info, index: info.index + 1, rootTypeTokens: List.append(info.rootTypeTokens, value), currentBuffer: [], }; } ; } } ; } else { return { ...info, index: info.index + 1, currentBuffer: List.append(info.currentBuffer, [token]), }; } ; } case "IdentifierToken": { return { ...info, index: info.index + 1, currentBuffer: List.append(info.currentBuffer, [token]), }; } case "StringToken": { return { ...info, index: info.index + 1, currentBuffer: List.append(info.currentBuffer, [token]), }; } default: { return { ...info, index: info.index + 1 }; } } })(); return nextInfo; } } function tokenizeType(tokens) { const initialState = { rootTypeTokens: [], currentBuffer: [], indent: 0, index: 0, tokens, error: [], }; const calculatedState = List.statefulFold(function (item, state) { return tokenizeTypeHelp(state); }, initialState, tokens); return finalTokenizeType(calculatedState); } function typeTokenToString(token) { switch (token.kind) { case "ArrowToken": { return "->"; } case "BaseTypeToken": { return rootTypeTokensToString([token]); } case "CloseBracketToken": { return ")"; } case "FunctionTypeToken": { return rootTypeTokensToString([token]); } case "IdentifierToken": { return token.body; } case "OpenBracketToken": { return "("; } case "StringToken": { return `${token.body}`; } } } function isNested(token) { switch (token.kind) { case "BaseTypeToken": { const { body } = token; return body.length !== 1; } case "FunctionTypeToken": { return true; } } } function rootTypeTokenToString(token) { switch (token.kind) { case "BaseTypeToken": { function valueToString(value) { switch (value.kind) { case "BaseTypeToken": { const { body } = value; const inner = List.map(typeTokenToString, body); if (isNested(value)) { return (function (x) { return x.join(" "); })((function (x) { return List.append(x, [typeTokenToString(CloseBracketToken({}))]); })(List.append([typeTokenToString(OpenBracketToken({}))], inner))); } else { return (function (x) { return x.join(" "); })(inner); } ; } default: { return typeTokenToString(value); } } } return (function (x) { return x.join(" "); })(List.map(valueToString, token.body)); } case "FunctionTypeToken": { function valueToString(value, index) { if (index < token.body.length - 1) { return (function (x) { return x.join(" "); })([typeTokenToString(value), typeTokenToString(ArrowToken({}))]); } else { return (function (x) { return x.join(" "); })([typeTokenToString(value)]); } } const mapped = List.indexedMap(valueToString, token.body); return (function (xs) { return xs.join(" "); })((function (xs) { return List.append(xs, [typeTokenToString(CloseBracketToken({}))]); })(List.append([typeTokenToString(OpenBracketToken({}))], mapped))); } } } function rootTypeTokensToString(tokens) { const arrow = typeTokenToString(ArrowToken({})); return (function (x) { return x.join(` ${arrow} `); })(List.map(rootTypeTokenToString, tokens)); }