scryptlib
Version:
Javascript SDK for integration of Bitcoin SV Smart Contracts written in sCrypt language.
826 lines • 35.2 kB
JavaScript
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
;