import { reduce } from "@cranq/object-utils"; import { mkdirSync, rmdirSync, writeFileSync } from "fs"; import * as path from "path"; import { compilePackageDescriptor } from "./compiler/compilePackageDescriptor"; import { compileScriptDef } from "./compiler/compileScriptDef"; import { expandIncludes } from "./compiler/utils/expandIncludes"; import { getDependenciesFromNodeDef } from "./compiler/utils/getDependenciesFromNodeDef"; import { scriptToScriptChunk } from "./parser/chunks/scriptToScriptChunk"; import { scriptChunkToScriptDef } from "./parser/definition/scriptChunkToScriptDef"; import { DependencyDef } from "./parser/definition/types/DependencyDef"; import { CompilationTargetId } from "./types/CompilationTargetId"; import { compilationTargets } from "./utils/compilationTargets"; import { getPackageDirectoryName } from "./utils/getPackageDirectoryName"; import { createPackageDirectory } from "./utils/createPackageDirectory"; import { convertScriptDefToLegacy } from "./legacy/convertScriptDefToLegacy"; const RE_TARGET = /^--target=(browser|es6|node|python3)$/; const RE_CRANQ = /^.*?\.cranq$/; const RE_DEBUG = /^--debug$/; const RE_LEGACY = /^--legacy$/; process.stdout.write(`CranqLang Compiler Version 0.2.1`); let scriptPath: string | null = null; let targetId: CompilationTargetId = CompilationTargetId.node; let isDebug: boolean = false; let isLegacy: boolean = false; for (const arg of process.argv.slice(2)) { if (RE_TARGET.test(arg)) { const matches = RE_TARGET.exec(arg) as Array; targetId = matches[1] as CompilationTargetId; } else if (RE_CRANQ.test(arg)) { scriptPath = arg; } else if (RE_DEBUG.test(arg)) { isDebug = true; } else if (RE_LEGACY.test(arg)) { isLegacy = true; } else { throw new Error(`Unrecognized argument: "${arg}"`); } } if (scriptPath) { process.stdout.write(` > target ID: ${targetId} > script path: ${JSON.stringify(scriptPath)}`); const mainModuleName = path.basename(scriptPath[0], ".cranq"); createPackageDirectory(); const target = compilationTargets[targetId]; const moduleName = path.basename(scriptPath, ".cranq"); const { extension } = target; const script = expandIncludes(scriptPath); const scriptChunk = scriptToScriptChunk(script); const scriptDef = scriptChunkToScriptDef( scriptChunk, targetId as CompilationTargetId); const { nodeDefs } = scriptDef; const compiledScript = compileScriptDef( scriptDef, targetId as CompilationTargetId); const dependencyDefs = reduce(nodeDefs, (result, nodeDef) => { const dependencies = getDependenciesFromNodeDef(nodeDef); return [...result, ...dependencies]; }, [] as Array); writeFileSync(`./${getPackageDirectoryName()}/${moduleName}.${extension}`, compiledScript); writeFileSync( `./${getPackageDirectoryName()}/package.json`, compilePackageDescriptor( mainModuleName, dependencyDefs, `${moduleName}.${extension}` ), {}); if (isLegacy) { const legacyScript = convertScriptDefToLegacy(scriptDef); writeFileSync(`./${getPackageDirectoryName()}/${moduleName}-legacy.json`, JSON.stringify(legacyScript, null, 2)); } if (isDebug) { writeFileSync(`./${getPackageDirectoryName()}/${moduleName}-chunks.json`, JSON.stringify(scriptChunk, null, 2)); writeFileSync(`./${getPackageDirectoryName()}/${moduleName}-def.json`, JSON.stringify(scriptDef, null, 2)); } process.stdout.write(` Done. `); } else { process.stdout.write(` Syntax: clc [options] [file] Options: --target=TARGET Specify compilation target: 'browser', 'es6', 'node', 'python3'. --debug Outputs intermediate files. `); }