UNPKG

scryptlib

Version:

Javascript SDK for integration of Bitcoin SV Smart Contracts written in sCrypt language.

826 lines 35.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.loadSourceMapfromArtifact = exports.getStaticDeclaration = exports.getAliasDeclaration = exports.getContractDeclaration = exports.getLibraryDeclaration = exports.getStructDeclaration = exports.getABIDeclaration = exports.getContractName = exports.getFullFilePath = exports.compilerVersion = exports.handleCompilerOutput = exports.compile = exports.settings2cmd = exports.compileAsync = exports.doCompileAsync = exports.ABIEntityType = exports.DebugModeTag = exports.CompileResult = exports.BuildType = exports.CompileErrorType = exports.SOURCE_REG = void 0; const child_process_1 = require("child_process"); const fs_1 = require("fs"); const path_1 = require("path"); const internal_1 = require("./internal"); const rimraf = require("rimraf"); const JSONbig = require("json-bigint"); const SYNTAX_ERR_REG = /(?<filePath>[^\s]+):(?<line>\d+):(?<column>\d+):\n([^\n]+\n){3}(unexpected (?<unexpected>[^\n]+)\nexpecting (?<expecting>[^\n]+)|(?<message>[^\n]+))/g; const SEMANTIC_ERR_REG = /Error:(\s|\n)*(?<filePath>[^\s]+):(?<line>\d+):(?<column>\d+):(?<line1>\d+):(?<column1>\d+):*\n(?<message>[^\n]+)\n/g; const INTERNAL_ERR_REG = /Internal error:(?<message>.+)/; const WARNING_REG = /Warning:(\s|\n)*(?<filePath>[^\s]+):(?<line>\d+):(?<column>\d+):(?<line1>\d+):(?<column1>\d+):*\n(?<message>[^\n]+)\n/g; const JSONbigAlways = JSONbig({ alwaysParseAsBig: true, constructorAction: 'preserve' }); //SOURCE_REG parser src eg: [0:6:3:8:4#Bar.constructor:0] exports.SOURCE_REG = /^(?<fileIndex>-?\d+):(?<line>\d+):(?<col>\d+):(?<endLine>\d+):(?<endCol>\d+)(#(?<tagStr>.+))?/; const RELATED_INFORMATION_REG = /(?<filePath>[^\s]+):(?<line>\d+):(?<column>\d+):(?<line1>\d+):(?<column1>\d+)/gi; // see VERSIONLOG.md var CompileErrorType; (function (CompileErrorType) { CompileErrorType["SyntaxError"] = "SyntaxError"; CompileErrorType["SemanticError"] = "SemanticError"; CompileErrorType["InternalError"] = "InternalError"; CompileErrorType["Warning"] = "Warning"; })(CompileErrorType = exports.CompileErrorType || (exports.CompileErrorType = {})); var BuildType; (function (BuildType) { BuildType["Debug"] = "debug"; BuildType["Release"] = "release"; })(BuildType = exports.BuildType || (exports.BuildType = {})); class CompileResult { constructor(errors, warnings) { this.errors = errors; this.warnings = warnings; } toArtifact() { const artifact = { version: internal_1.CURRENT_CONTRACT_ARTIFACT_VERSION, compilerVersion: this.compilerVersion || '0.0.0', contract: this.contract || '', md5: this.md5 || '', structs: this.structs || [], library: this.library || [], alias: this.alias || [], abi: this.abi || [], stateProps: this.stateProps || [], buildType: this.buildType || BuildType.Debug, file: this.file || '', hex: this.hex || '', asm: '', sourceMap: [], sources: [], sourceMapFile: this.sourceMapFile || '', }; return artifact; } } exports.CompileResult = CompileResult; var DebugModeTag; (function (DebugModeTag) { DebugModeTag["FuncStart"] = "F0"; DebugModeTag["FuncEnd"] = "F1"; DebugModeTag["LoopStart"] = "L0"; })(DebugModeTag = exports.DebugModeTag || (exports.DebugModeTag = {})); var ABIEntityType; (function (ABIEntityType) { ABIEntityType["FUNCTION"] = "function"; ABIEntityType["CONSTRUCTOR"] = "constructor"; })(ABIEntityType = exports.ABIEntityType || (exports.ABIEntityType = {})); function toOutputDir(artifactsDir, sourcePath) { return (0, path_1.join)(artifactsDir, (0, path_1.basename)(sourcePath) + '-' + (0, internal_1.hash160)(sourcePath, 'utf-8').substring(0, 10)); } function doCompileAsync(source, settings, callback) { const sourcePath = source.path; const srcDir = (0, path_1.dirname)(sourcePath); const curWorkingDir = settings.cwd || srcDir; const timeout = settings.timeout || 1200000; const sourceContent = source.content !== undefined ? source.content : (0, fs_1.readFileSync)(sourcePath, 'utf8'); const cmd = settings2cmd(sourcePath, settings); const childProcess = (0, child_process_1.exec)(cmd, { cwd: curWorkingDir, timeout, killSignal: 'SIGKILL' }, (error, stdout) => { if (error) { console.error(`exec error: ${error} stdout: ${stdout}`); callback(error, null); return; } callback(null, { path: sourcePath, output: stdout, }); }); childProcess.stdin.write(sourceContent, (error) => { if (error) { callback(error, null); return; } childProcess.stdin.end(); }); return childProcess; } exports.doCompileAsync = doCompileAsync; function compileAsync(source, settings) { settings = Object.assign({}, defaultCompilingSettings, settings); return new Promise((resolve, reject) => { doCompileAsync(source, settings, async (error, data) => { if (error) { reject(error); return; } try { const result = handleCompilerOutput(source.path, settings, data.output); resolve(result); } catch (error) { reject(error); } }); }); } exports.compileAsync = compileAsync; const defaultCompilingSettings = { ast: true, asm: false, hex: true, debug: false, artifact: false, outputDir: '', outputToFiles: false, cwd: '', cmdPrefix: '', cmdArgs: '', buildType: BuildType.Debug, stdout: false, sourceMap: false, timeout: 1200000, optimize: false, }; function settings2cmd(sourcePath, settings) { const srcDir = (0, path_1.dirname)(sourcePath); //dir that store artifact file const artifactDir = settings.outputDir || srcDir; //dir that store ast,asm file const outputDir = toOutputDir(artifactDir, sourcePath); const cmdPrefix = settings.cmdPrefix || (0, internal_1.findCompiler)(); let outOption = `-o "${outputDir}"`; if (settings.stdout) { outOption = '--stdout'; return `"${cmdPrefix}" compile ${settings.asm || settings.artifact ? '--asm' : ''} ${settings.hex ? '--hex' : ''} ${settings.optimize ? '-O' : ''} ${settings.ast || settings.artifact ? '--ast' : ''} ${settings.debug == true ? '--debug' : ''} -r ${outOption} ${settings.cmdArgs ? settings.cmdArgs : ''}`; } else { if (!(0, fs_1.existsSync)(outputDir)) { (0, fs_1.mkdirSync)(outputDir); } } return `"${cmdPrefix}" compile ${settings.hex ? '--hex' : ''} ${settings.optimize ? '-O' : ''} ${settings.ast || settings.artifact ? '--ast' : ''} ${settings.debug == true ? '--debug' : ''} ${settings.sourceMap == true ? '--source-map' : ''} -r ${outOption} ${settings.cmdArgs ? settings.cmdArgs : ''}`; } exports.settings2cmd = settings2cmd; function compile(source, settings) { const sourcePath = source.path; const srcDir = (0, path_1.dirname)(sourcePath); //dir that stores artifact file const curWorkingDir = settings.cwd || srcDir; const sourceContent = source.content !== undefined ? source.content : (0, fs_1.readFileSync)(sourcePath, 'utf8'); const maxBuffer = settings.stdout ? 1024 * 1024 * 100 : 1024 * 1024; settings = Object.assign({}, defaultCompilingSettings, settings); const cmd = settings2cmd(sourcePath, settings); const output = (0, child_process_1.execSync)(cmd, { input: sourceContent, cwd: curWorkingDir, timeout: settings.timeout, maxBuffer: maxBuffer }).toString(); return handleCompilerOutput(sourcePath, settings, output); } exports.compile = compile; function calcHexMd5(hex) { const chex = hex.replace(/<([^>]+)>/g, '<>'); return (0, internal_1.md5)(chex); } function handleCompilerOutput(sourcePath, settings, output) { const srcDir = (0, path_1.dirname)(sourcePath); const sourceFileName = (0, path_1.basename)(sourcePath); const artifactsDir = settings.outputDir || srcDir; const outputDir = toOutputDir(artifactsDir, sourcePath); const outputFiles = {}; try { // Because the output of the compiler on the win32 platform uses crlf as a newline, here we change \r\n to \n. make SYNTAX_ERR_REG、SEMANTIC_ERR_REG、IMPORT_ERR_REG work. output = output.split(/\r?\n/g).join('\n'); const result = new CompileResult([], []); result.compilerVersion = compilerVersion(settings.cmdPrefix ? settings.cmdPrefix : (0, internal_1.findCompiler)()); result.buildType = settings.buildType || BuildType.Debug; if (output.startsWith('Error:') || output.startsWith('Warning:')) { Object.assign(result, getErrorsAndWarnings(output, srcDir, sourceFileName)); if (result.errors.length > 0) { return result; } if (settings.stdout && result.warnings.length > 0) { // stdout not allowed warnings return result; } } if (settings.stdout) { const stdout = JSONbigAlways.parse(output); parserAst(result, stdout.ast, srcDir, sourceFileName, sourcePath); parserASM(result, stdout.asm, settings, srcDir, sourceFileName); } else { if (settings.ast || settings.artifact) { const outputFilePath = getOutputFilePath(outputDir, 'ast'); const astFile = outputFilePath.replace('stdin', (0, path_1.basename)(sourcePath, '.scrypt')); (0, fs_1.renameSync)(outputFilePath, astFile); outputFiles['ast'] = astFile; const ast = JSONbigAlways.parse((0, fs_1.readFileSync)(astFile, 'utf8')); parserAst(result, ast, srcDir, sourceFileName, sourcePath); } if (settings.hex || settings.artifact) { const outputFilePath = getOutputFilePath(outputDir, 'hex'); const hexFile = outputFilePath.replace('stdin', (0, path_1.basename)(sourcePath, '.scrypt')); (0, fs_1.renameSync)(outputFilePath, hexFile); outputFiles['hex'] = hexFile; result.hex = (0, fs_1.readFileSync)(hexFile, 'utf8'); result.md5 = calcHexMd5(result.hex); } if (settings.sourceMap) { const outputFilePath = getOutputFilePath(outputDir, 'map'); if (settings.artifact) { const dist = getOutputFilePath(artifactsDir, 'map'); const sourceMapFile = dist.replace('stdin', (0, path_1.basename)(sourcePath, '.scrypt')); (0, fs_1.renameSync)(outputFilePath, sourceMapFile); result.sourceMapFile = (0, internal_1.path2uri)(sourceMapFile); } else { const sourceMapFile = outputFilePath.replace('stdin', (0, path_1.basename)(sourcePath, '.scrypt')); (0, fs_1.renameSync)(outputFilePath, sourceMapFile); outputFiles['map'] = sourceMapFile; result.sourceMapFile = (0, internal_1.path2uri)(sourceMapFile); } } if (settings.debug) { const outputFilePath = getOutputFilePath(outputDir, 'dbg'); const dbgFile = outputFilePath.replace('stdin', (0, path_1.basename)(sourcePath, '.scrypt')); (0, fs_1.renameSync)(outputFilePath, dbgFile); result.dbgFile = (0, internal_1.path2uri)(dbgFile); } if (settings.artifact) { const outputFilePath = getOutputFilePath(artifactsDir, 'artifact'); const artifactFile = outputFilePath.replace('stdin', (0, path_1.basename)(sourcePath, '.scrypt')); const artifact = result.toArtifact(); (0, fs_1.writeFileSync)(artifactFile, JSON.stringify(artifact, (key, value) => { if (key === 'file') { return (0, path_1.relative)(artifactFile, value); } //ignore deprecated fields if (key == 'sources' || key == 'sourceMap' || key === 'asm') return undefined; else return value; }, 4)); } } return result; } finally { doClean(settings, outputFiles, outputDir); } } exports.handleCompilerOutput = handleCompilerOutput; function compilerVersion(cwd) { try { const text = (0, child_process_1.execSync)(`"${cwd}" version`).toString(); return /Version:\s*([^\s]+)\s*/.exec(text)[1]; } catch (e) { throw new Error(`compilerVersion fail when run: ${cwd} version`); } } exports.compilerVersion = compilerVersion; function addSourceLocation(astRoot, basePath, curFileName) { for (const fileName in astRoot) { if (fileName === 'std') { astRoot['std'] = _addSourceLocationProperty(astRoot['std'], 'std'); } else { const realFileName = fileName === 'stdin' ? curFileName : fileName; const uri = (0, internal_1.path2uri)((0, path_1.join)(basePath, realFileName)); astRoot[uri] = _addSourceLocationProperty(astRoot[fileName], uri); delete astRoot[fileName]; } } return astRoot; } function _addSourceLocationProperty(astObj, uri) { if (!(typeof astObj === 'object')) { return astObj; } for (const field in astObj) { const value = astObj[field]; if (field === 'src') { const matches = /:(\d+):(\d+):(\d+):(\d+)/.exec(value); if (!matches) { astObj.loc = null; } else { astObj.loc = { source: uri, start: { line: parseInt(matches[1]), column: parseInt(matches[2]) }, end: { line: parseInt(matches[3]), column: parseInt(matches[4]) } }; } delete astObj['src']; } else if (typeof value === 'object') { _addSourceLocationProperty(value, uri); } } return astObj; } function getOutputFilePath(baseDir, target) { if (target == 'hex') { return (0, path_1.join)(baseDir, `stdin_${target}.txt`); } else if (target === 'map') { return (0, path_1.join)(baseDir, `stdin.${target}.json`); } else if (target === 'dbg') { return (0, path_1.join)(baseDir, `stdin.${target}.json`); } else if (target === 'artifact') { return (0, path_1.join)(baseDir, 'stdin.json'); } return (0, path_1.join)(baseDir, `stdin_${target}.json`); } function getFullFilePath(relativePath, baseDir, curFileName) { if (relativePath.endsWith('stdin')) { return (0, path_1.join)(baseDir, curFileName); // replace 'stdin' with real current compiling file name. } if (relativePath === 'std') { return 'std'; // } return (0, path_1.join)(baseDir, relativePath); } exports.getFullFilePath = getFullFilePath; function getConstructorDeclaration(mainContract) { // explict constructor if (mainContract['constructor']) { return { type: ABIEntityType.CONSTRUCTOR, params: mainContract['constructor']['params'].map(p => { return { name: p['name'], type: p['type'] }; }), }; } else { // implicit constructor if (mainContract['properties']) { return { type: ABIEntityType.CONSTRUCTOR, params: mainContract['properties'].map(p => { return { name: p['name'].replace('this.', ''), type: p['type'] }; }), }; } } } function getStateProps(astRoot) { const mainContract = astRoot['contracts'][astRoot['contracts'].length - 1]; if (mainContract && mainContract['properties']) { return mainContract['properties'].filter(p => p.state).map(p => { return { name: p['name'].replace('this.', ''), type: p['type'] }; }); } return []; } function getPublicFunctionDeclaration(mainContract) { let pubIndex = 0; const interfaces = mainContract['functions'] .filter(f => f['visibility'] === 'Public') .map(f => { const entity = { type: ABIEntityType.FUNCTION, name: f['name'], index: f['nodeType'] === 'Constructor' ? undefined : pubIndex++, params: f['params'].map(p => { return { name: p['name'], type: p['type'] }; }), }; return entity; }); return interfaces; } function getContractName(astRoot) { const mainContract = astRoot['contracts'][astRoot['contracts'].length - 1]; if (!mainContract) { return ''; } return mainContract['name'] || ''; } exports.getContractName = getContractName; function shortGenericType(genericType) { const m = genericType.match(/__SCRYPT_(\w+)__/); if (m) { return m[1]; } return genericType; } /** * * @param astRoot AST root node after main contract compilation * @param typeResolver a Type Resolver * @returns All function ABIs defined by the main contract, including constructors */ function getABIDeclaration(astRoot, typeResolver) { const mainContract = astRoot['contracts'][astRoot['contracts'].length - 1]; if (!mainContract) { return { contract: '', abi: [] }; } const interfaces = getPublicFunctionDeclaration(mainContract); const constructorABI = getConstructorDeclaration(mainContract); interfaces.push(constructorABI); interfaces.forEach(abi => { abi.params = abi.params.map(param => { return Object.assign(param, { type: typeResolver(param.type).finalType }); }); }); return { contract: getContractName(astRoot), abi: interfaces }; } exports.getABIDeclaration = getABIDeclaration; /** * * @param astRoot AST root node after main contract compilation * @param dependencyAsts AST root node after all dependency contract compilation * @returns all defined structures of the main contract and dependent contracts */ function getStructDeclaration(astRoot, dependencyAsts) { const allAst = [astRoot]; Object.keys(dependencyAsts).forEach(key => { allAst.push(dependencyAsts[key]); }); return allAst.map(ast => { return (ast['structs'] || []).map(s => ({ name: s['name'], params: s['fields'].map(p => { return { name: p['name'], type: p['type'] }; }), genericTypes: s.genericTypes || [], })); }).flat(1); } exports.getStructDeclaration = getStructDeclaration; /** * * @param astRoot AST root node after main contract compilation * @param dependencyAsts AST root node after all dependency contract compilation * @returns all defined Library of the main contract and dependent contracts */ function getLibraryDeclaration(astRoot, dependencyAsts) { const allAst = [astRoot]; Object.keys(dependencyAsts).forEach(key => { if (key !== 'std') { allAst.push(dependencyAsts[key]); } }); return allAst.map(ast => { return (ast['contracts'] || []).filter(c => c.nodeType == 'Library').map(c => { if (c['constructor']) { return { name: c.name, params: c['constructor']['params'].map(p => { return { name: `ctor.${p['name']}`, type: p['type'] }; }), properties: c['properties'].map(p => { return { name: p['name'], type: p['type'] }; }), genericTypes: c.genericTypes || [], }; } else { // implicit constructor if (c['properties']) { return { name: c.name, params: c['properties'].map(p => { return { name: p['name'], type: p['type'] }; }), properties: c['properties'].map(p => { return { name: p['name'], type: p['type'] }; }), genericTypes: c.genericTypes || [], }; } } }); }).flat(1); } exports.getLibraryDeclaration = getLibraryDeclaration; function getContractDeclaration(astRoot, dependencyAsts) { const allAst = [astRoot]; Object.keys(dependencyAsts).forEach(key => { if (key !== 'std') { allAst.push(dependencyAsts[key]); } }); return allAst.map(ast => { return (ast['contracts'] || []).filter(c => c.nodeType == 'Contract').map(c => { if (c['constructor']) { return { name: c.name, params: c['constructor']['params'].map(p => { return { name: `ctor.${p['name']}`, type: p['type'] }; }), properties: c['properties'].map(p => { return { name: p['name'], type: p['type'] }; }), genericTypes: c.genericTypes || [] }; } else { // implicit constructor if (c['properties']) { return { name: c.name, params: c['properties'].map(p => { return { name: p['name'], type: p['type'] }; }), properties: c['properties'].map(p => { return { name: p['name'], type: p['type'] }; }), genericTypes: c.genericTypes || [], }; } } }); }).flat(1); } exports.getContractDeclaration = getContractDeclaration; /** * * @param astRoot AST root node after main contract compilation * @param dependencyAsts AST root node after all dependency contract compilation * @returns all defined type aliaes of the main contract and dependent contracts */ function getAliasDeclaration(astRoot, dependencyAsts) { const allAst = [astRoot]; Object.keys(dependencyAsts).forEach(key => { allAst.push(dependencyAsts[key]); }); return allAst.map(ast => { return (ast['alias'] || []).map(s => ({ name: s['alias'], type: s['type'], })); }).flat(1); } exports.getAliasDeclaration = getAliasDeclaration; /** * * @param astRoot AST root node after main contract compilation * @param dependencyAsts AST root node after all dependency contract compilation * @returns all defined static const int literal of the main contract and dependent contracts */ function getStaticDeclaration(astRoot, dependencyAsts) { const allAst = [astRoot]; Object.keys(dependencyAsts).forEach(key => { allAst.push(dependencyAsts[key]); }); return allAst.map((ast) => { return (ast['contracts'] || []).map(contract => { return (contract.statics || []).map(node => { return { const: node.const, name: `${contract.name}.${node.name}`, type: node.type, value: (0, internal_1.resolveConstValue)(node) }; }); }); }).flat(Infinity).flat(1); } exports.getStaticDeclaration = getStaticDeclaration; function getRelatedInformation(message, srcDir, sourceFileName) { const relatedInformation = []; let result; while ((result = RELATED_INFORMATION_REG.exec(message))) { const relatedFilePath = result.groups.filePath; if (relatedFilePath === 'null') continue; const fullFilePath = getFullFilePath(relatedFilePath, srcDir, sourceFileName); const line = parseInt(result.groups?.line || '-1'); const column = parseInt(result.groups?.column || '-1'); relatedInformation.push({ filePath: fullFilePath, position: [{ line: line, column: column, }, { line: parseInt(result.groups?.line1 || '-1'), column: parseInt(result.groups?.column1 || '-1'), }], message: '' }); message = message.replace(/([^\s]+):(\d+):(\d+):(\d+):(\d+)/, ''); } return { relatedInformation, message }; } function getErrorsAndWarnings(output, srcDir, sourceFileName) { const warnings = [...output.matchAll(WARNING_REG)].map(match => { const filePath = match.groups?.filePath || ''; const origin_message = match.groups?.message || ''; const { message, relatedInformation } = getRelatedInformation(origin_message, srcDir, sourceFileName); return { type: CompileErrorType.Warning, filePath: getFullFilePath(filePath, srcDir, sourceFileName), position: [{ line: parseInt(match.groups?.line || '-1'), column: parseInt(match.groups?.column || '-1'), }, { line: parseInt(match.groups?.line1 || '-1'), column: parseInt(match.groups?.column1 || '-1'), }], message: message, relatedInformation: relatedInformation }; }); if (output.match(INTERNAL_ERR_REG)) { const errors = [{ type: CompileErrorType.InternalError, filePath: getFullFilePath('stdin', srcDir, sourceFileName), message: `Compiler internal error: ${output.match(INTERNAL_ERR_REG).groups?.message || ''}`, position: [{ line: 1, column: 1 }, { line: 1, column: 1 }], relatedInformation: [] }]; return new CompileResult(errors, warnings); } else if (output.includes('Syntax error:')) { const syntaxErrors = [...output.matchAll(SYNTAX_ERR_REG)].map(match => { const filePath = match.groups?.filePath || ''; const unexpected = match.groups?.unexpected || ''; const expecting = match.groups?.expecting || ''; const origin_message = match.groups?.message || `unexpected ${unexpected}\nexpecting ${expecting}`; const { message, relatedInformation } = getRelatedInformation(origin_message, srcDir, sourceFileName); return { type: CompileErrorType.SyntaxError, filePath: getFullFilePath(filePath, srcDir, sourceFileName), position: [{ line: parseInt(match.groups?.line || '-1'), column: parseInt(match.groups?.column || '-1'), }], message: message, unexpected, expecting, relatedInformation: relatedInformation }; }); return new CompileResult(syntaxErrors, warnings); } else { const semanticErrors = [...output.matchAll(SEMANTIC_ERR_REG)].map(match => { const origin_message = match.groups?.message || ''; const filePath = match.groups?.filePath || ''; const { message, relatedInformation } = getRelatedInformation(origin_message, srcDir, sourceFileName); return { type: CompileErrorType.SemanticError, filePath: getFullFilePath(filePath, srcDir, sourceFileName), position: [{ line: parseInt(match.groups?.line || '-1'), column: parseInt(match.groups?.column || '-1'), }, { line: parseInt(match.groups?.line1 || '-1'), column: parseInt(match.groups?.column1 || '-1'), }], message: message, relatedInformation: relatedInformation }; }); return new CompileResult(semanticErrors, warnings); } } function parserAst(result, ast, srcDir, sourceFileName, sourcePath) { const allAst = addSourceLocation(ast, srcDir, sourceFileName); const sourceUri = (0, internal_1.path2uri)(sourcePath); result.file = sourcePath; result.ast = allAst[sourceUri]; delete allAst[sourceUri]; result.dependencyAsts = allAst; const alias = getAliasDeclaration(result.ast, allAst); const structs = getStructDeclaration(result.ast, allAst); const library = getLibraryDeclaration(result.ast, allAst); const statics = getStaticDeclaration(result.ast, allAst); result.contracts = getContractDeclaration(result.ast, allAst); const typeResolver = (0, internal_1.buildTypeResolver)(getContractName(result.ast), alias, structs, library, result.contracts, statics); result.alias = alias.map(a => ({ name: a.name, type: typeResolver(a.type).finalType })); result.structs = structs.map(a => ({ name: a.name, params: a.params.map(p => ({ name: p.name, type: typeResolver(p.type).finalType })), genericTypes: a.genericTypes.map(t => shortGenericType(t)) })); result.library = library.map(a => ({ name: a.name, params: a.params.map(p => ({ name: p.name, type: typeResolver(p.type).finalType })), properties: a.properties.map(p => ({ name: p.name, type: typeResolver(p.type).finalType })), genericTypes: a.genericTypes.map(t => shortGenericType(t)) })); result.statics = statics.map(s => (Object.assign({ ...s }, { type: typeResolver(s.type).finalType }))); const { contract: name, abi } = getABIDeclaration(result.ast, typeResolver); result.stateProps = getStateProps(result.ast).map(p => ({ name: p.name, type: typeResolver(p.type).finalType })); result.abi = abi; result.contract = name; } /** * @deprecated use `--hex` when compiling * @param result * @param asmObj * @param settings * @param srcDir * @param sourceFileName */ function parserASM(result, asmObj, settings, srcDir, sourceFileName) { const sources = asmObj.sources; if (settings.debug) { Object.assign(result, { file: result.file, sources: asmObj.sources.map(source => getFullFilePath(source, srcDir, sourceFileName)), sourceMap: asmObj.output.map(item => item.src), }); } result.hex = settings.hex ? asmObj.output.map(item => item.hex).join('') : ''; result.asm = asmObj.output.map(item => { if (!settings.debug) { return { opcode: item.opcode }; } const match = exports.SOURCE_REG.exec(item.src); if (match && match.groups) { const fileIndex = parseInt(match.groups.fileIndex); let debugInfo; const tagStr = match.groups.tagStr; const m = /^(\w+)\.(\w+):(\d)(#(?<context>.+))?$/.exec(tagStr); if (m) { debugInfo = { contract: m[1], func: m[2], tag: m[3] == '0' ? DebugModeTag.FuncStart : DebugModeTag.FuncEnd, context: m.groups.context }; } else if (/loop:0/.test(tagStr)) { debugInfo = { contract: '', func: '', tag: DebugModeTag.LoopStart, context: '' }; } const pos = sources[fileIndex] ? { file: sources[fileIndex] ? getFullFilePath(sources[fileIndex], srcDir, sourceFileName) : undefined, line: sources[fileIndex] ? parseInt(match.groups.line) : undefined, endLine: sources[fileIndex] ? parseInt(match.groups.endLine) : undefined, column: sources[fileIndex] ? parseInt(match.groups.col) : undefined, endColumn: sources[fileIndex] ? parseInt(match.groups.endCol) : undefined, } : undefined; return { opcode: item.opcode, stack: item.stack, topVars: item.topVars || [], pos: pos, debugInfo }; } throw new Error('Compile Failed: Asm output parsing Error!'); }); if (settings.debug) { result.autoTypedVars = asmObj.autoTypedVars.map(item => { const match = exports.SOURCE_REG.exec(item.src); if (match && match.groups) { const fileIndex = parseInt(match.groups.fileIndex); const pos = sources[fileIndex] ? { file: sources[fileIndex] ? getFullFilePath(sources[fileIndex], srcDir, sourceFileName) : undefined, line: sources[fileIndex] ? parseInt(match.groups.line) : undefined, endLine: sources[fileIndex] ? parseInt(match.groups.endLine) : undefined, column: sources[fileIndex] ? parseInt(match.groups.col) : undefined, endColumn: sources[fileIndex] ? parseInt(match.groups.endCol) : undefined, } : undefined; return { name: item.name, type: item.type, pos: pos }; } }); } } function doClean(settings, outputFiles, outputDir) { if (settings.stdout || settings.outputToFiles || settings.sourceMap) { return; } try { Object.keys(outputFiles).forEach(outputType => { const file = outputFiles[outputType]; if ((0, fs_1.existsSync)(file)) { (0, fs_1.unlinkSync)(file); } }); rimraf.sync(outputDir); } catch (error) { console.error('clean compiler output files failed!'); } // console.log('compile time spent: ', Date.now() - st) } function loadSourceMapfromArtifact(artifact) { const sources = artifact.sources; const asm = artifact.asm.split(' '); if (!artifact.sourceMap || artifact.sourceMap.length == 0) { return []; } return asm.map((opcode, index) => { const item = artifact.sourceMap[index]; const match = exports.SOURCE_REG.exec(item); if (match && match.groups) { const fileIndex = parseInt(match.groups.fileIndex); const pos = sources[fileIndex] ? { file: sources[fileIndex], line: sources[fileIndex] ? parseInt(match.groups.line) : undefined, endLine: sources[fileIndex] ? parseInt(match.groups.endLine) : undefined, column: sources[fileIndex] ? parseInt(match.groups.col) : undefined, endColumn: sources[fileIndex] ? parseInt(match.groups.endCol) : undefined, } : undefined; return { pos: pos, opcode: opcode }; } }); } exports.loadSourceMapfromArtifact = loadSourceMapfromArtifact; //# sourceMappingURL=compilerWrapper.js.map