UNPKG

derw

Version:

An Elm-inspired language that transpiles to TypeScript

482 lines (481 loc) 17.6 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 (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.exportTests = exports.typeBlocks = exports.intoBlocks = exports.createUnparsedBlock = exports.blockKind = void 0; const Utils_1 = require("./Utils"); const List = __importStar(require("./stdlib/List")); function Validator(args) { return Object.assign({}, args); } function Ok(args) { return Object.assign({ kind: "Ok" }, args); } function Err(args) { return Object.assign({ kind: "Err" }, args); } function ImportBlock(args) { return Object.assign({ kind: "ImportBlock" }, args); } function ExportBlock(args) { return Object.assign({ kind: "ExportBlock" }, args); } function UnionTypeBlock(args) { return Object.assign({ kind: "UnionTypeBlock" }, args); } function UnionUntaggedTypeBlock(args) { return Object.assign({ kind: "UnionUntaggedTypeBlock" }, args); } function TypeAliasBlock(args) { return Object.assign({ kind: "TypeAliasBlock" }, args); } function TypeclassBlock(args) { return Object.assign({ kind: "TypeclassBlock" }, args); } function ImplBlock(args) { return Object.assign({ kind: "ImplBlock" }, args); } function FunctionBlock(args) { return Object.assign({ kind: "FunctionBlock" }, args); } function ConstBlock(args) { return Object.assign({ kind: "ConstBlock" }, args); } function CommentBlock(args) { return Object.assign({ kind: "CommentBlock" }, args); } function MultilineCommentBlock(args) { return Object.assign({ kind: "MultilineCommentBlock" }, args); } function UnknownBlock(args) { return Object.assign({ kind: "UnknownBlock" }, args); } function hasTypeLine(block) { const _res1328002030 = block.split(":"); switch (_res1328002030.length) { case _res1328002030.length: { if (_res1328002030.length === 1) { const [x] = _res1328002030; return false; } } case _res1328002030.length: { if (_res1328002030.length >= 1) { const [x, ...xs] = _res1328002030; const trimmed = x.trim(); const split = trimmed.split(" "); const length = split.length; return length === 1; } } default: { return false; } } } function isAFunction(block) { const _res1780524276 = block.split("\n"); switch (_res1780524276.length) { case _res1780524276.length: { if (_res1780524276.length >= 1) { const [firstLine, ...xs] = _res1780524276; return (function (y) { return y.length > 1; })(firstLine.split("->")); } } default: { return false; } } } const validators = [{ test: function (x) { return x.startsWith("--"); }, blockKind: "Comment" }, { test: function (x) { return x.startsWith("{-"); }, blockKind: "MultilineComment" }, { test: function (x) { return x.startsWith("type alias"); }, blockKind: "TypeAlias" }, { test: function (x) { return x.startsWith("typeclass "); }, blockKind: "Typeclass" }, { test: function (x) { return x.startsWith("impl "); }, blockKind: "Impl" }, { test: function (x) { return x.startsWith("type ") && x.includes(`"`); }, blockKind: "UnionUntaggedType" }, { test: function (x) { return x.startsWith("type "); }, blockKind: "UnionType" }, { test: function (x) { return x.startsWith(" ") || x.startsWith("}"); }, blockKind: "Indent" }, { test: function (x) { return x.startsWith("import"); }, blockKind: "Import" }, { test: function (x) { return x.startsWith("exposing"); }, blockKind: "Export" }, { test: function (x) { return hasTypeLine(x) && isAFunction(x); }, blockKind: "Function" }, { test: function (x) { return hasTypeLine(x); }, blockKind: "Const" }, { test: function (x) { return (function (y) { return y.length > 1; })(x.split("=")); }, blockKind: "Definition" }]; function blockKindStep(block, validators) { switch (validators.length) { case validators.length: { if (validators.length >= 1) { const [validator, ...ys] = validators; if (validator.test(block)) { return Ok({ value: validator.blockKind }); } else { return blockKindStep(block, ys); } ; } } default: { return Err({ error: "Unknown block type" }); } } } function blockKind(block) { return blockKindStep(block, validators); } exports.blockKind = blockKind; function createUnparsedBlock(blockKind, lineStart, lines) { switch (blockKind) { case "Import": { return ImportBlock({ lineStart, lines }); } case "Export": { return ExportBlock({ lineStart, lines }); } case "Const": { return ConstBlock({ lineStart, lines }); } case "Function": { return FunctionBlock({ lineStart, lines }); } case "UnionType": { return UnionTypeBlock({ lineStart, lines }); } case "UnionUntaggedType": { return UnionUntaggedTypeBlock({ lineStart, lines }); } case "TypeAlias": { return TypeAliasBlock({ lineStart, lines }); } case "Typeclass": { return TypeclassBlock({ lineStart, lines }); } case "Impl": { return ImplBlock({ lineStart, lines }); } case "Indent": { return UnknownBlock({ lineStart, lines }); } case "Definition": { return UnknownBlock({ lineStart, lines }); } case "Comment": { return CommentBlock({ lineStart, lines }); } case "MultilineComment": { return MultilineCommentBlock({ lineStart, lines }); } case "Unknown": { return UnknownBlock({ lineStart, lines }); } } } exports.createUnparsedBlock = createUnparsedBlock; function IntoBlockInfo(args) { return Object.assign({}, args); } function stepMultilineComment(lineNumber, info, line, lines) { if (line === "-}") { const infoWithCurrentLine = Object.assign(Object.assign({}, info), { previousLine: line, currentBlock: List.append(info.currentBlock, [line]) }); const block = createUnparsedBlock("MultilineComment", infoWithCurrentLine.lineStart, infoWithCurrentLine.currentBlock); const nextInfo = { currentBlock: [], previousLine: line, lineStart: lineNumber, currentBlockKind: Err({ error: "Nothing" }) }; return [block, ...intoBlocksStep(lineNumber + 1, nextInfo, lines)]; } else { const infoWithCurrentLine = Object.assign(Object.assign({}, info), { previousLine: line, currentBlock: List.append(info.currentBlock, [line]) }); return intoBlocksStep(lineNumber + 1, infoWithCurrentLine, lines); } } function indentOrDefinitionStep(lineNumber, info, line, lines) { const nextLines = lineNumber > 0 && info.previousLine.trim() === "" ? [info.previousLine, line] : [line]; const nextInfo = Object.assign(Object.assign({}, info), { currentBlock: List.append(info.currentBlock, nextLines), previousLine: line }); return intoBlocksStep(lineNumber + 1, nextInfo, lines); } function intoBlocksStep(lineNumber, info, lines) { switch (lines.length) { case lines.length: { if (lines.length >= 1) { const [line, ...xs] = lines; if (line.trim().length === 0) { const nextInfo = Object.assign(Object.assign({}, info), { previousLine: line }); return intoBlocksStep(lineNumber + 1, nextInfo, xs); } else { switch (info.currentBlock.length) { case 0: { const nextInfo = { previousLine: line, currentBlock: [line], lineStart: lineNumber, currentBlockKind: blockKind(line) }; return intoBlocksStep(lineNumber + 1, nextInfo, xs); } default: { const isInMultilineComment = info.currentBlockKind.kind === "Ok" && info.currentBlockKind.value === "MultilineComment"; if (isInMultilineComment) { return stepMultilineComment(lineNumber, info, line, xs); } else { const currentLineBlockKind = blockKind(line); const isIndent = currentLineBlockKind.kind === "Ok" && currentLineBlockKind.value === "Indent"; const isDefinition = currentLineBlockKind.kind === "Ok" && currentLineBlockKind.value === "Definition"; if (isIndent || isDefinition) { return indentOrDefinitionStep(lineNumber, info, line, xs); } else { switch (info.currentBlockKind.kind) { case "Ok": { const { value } = info.currentBlockKind; const hasSpeech = (function (y) { return y.length > 0; })(info.currentBlock.filter(function (line) { return line.indexOf(`"`) > -1; })); const kind = (function () { switch (value) { case "UnionType": { if (hasSpeech) { return "UnionUntaggedType"; } else { return value; } ; } default: { return value; } } })(); const block = createUnparsedBlock(kind, info.lineStart, info.currentBlock); const nextInfo = { previousLine: line, currentBlock: [line], lineStart: lineNumber, currentBlockKind: currentLineBlockKind }; return [block, ...intoBlocksStep(lineNumber + 1, nextInfo, xs)]; } case "Err": { const nextInfo = Object.assign(Object.assign({}, info), { previousLine: line, currentBlock: List.append(info.currentBlock, [line]) }); return intoBlocksStep(lineNumber + 1, nextInfo, xs); } } ; } ; } ; } } ; } ; } } default: { if (info.currentBlock.length > 0) { switch (info.currentBlockKind.kind) { case "Ok": { const { value } = info.currentBlockKind; const hasSpeech = (function (y) { return y.length > 0; })(info.currentBlock.filter(function (line) { return line.indexOf(`"`) > -1; })); const kind = (function () { switch (value) { case "UnionType": { if (hasSpeech) { return "UnionUntaggedType"; } else { return value; } ; } default: { return value; } } })(); return [createUnparsedBlock(kind, info.lineStart, info.currentBlock)]; } case "Err": { return [createUnparsedBlock("Unknown", info.lineStart, info.currentBlock)]; } } ; } else { return []; } ; } } } function intoBlocks(body) { const lines = body.split("\n"); return intoBlocksStep(0, { previousLine: "", currentBlock: [], currentBlockKind: Err({ error: "Nothing" }), lineStart: 0 }, lines); } exports.intoBlocks = intoBlocks; function typeBlocks(blocks) { return List.filter(function (block) { return block.kind === "UnionType" || block.kind === "TypeAlias" || block.kind === "UnionUntaggedType"; }, blocks); } exports.typeBlocks = typeBlocks; function Export(args) { return Object.assign({ kind: "Export" }, args); } function exportTests(module) { const isTest = (0, Utils_1.isTestFile)(module.name); const namesToExpose = isTest ? List.filter(function (name) { return name.startsWith("test") || name.startsWith("snapshot"); }, List.map(function (block) { return block.name; }, List.filter(function (block) { return block.kind === "Function" || block.kind === "Const"; }, module.body))) : []; const exports = List.filter(function (block) { return block.kind === "Export"; }, module.body); const exportNames = List.foldl(function (export_, allNames) { return List.append(export_.names, allNames); }, [], exports); const exposeWithoutDuplicates = List.filter(function (name) { return !exportNames.includes(name); }, namesToExpose); return Export({ names: exposeWithoutDuplicates }); } exports.exportTests = exportTests;