(code: string, compilerOptions: CompileOptions = {})
| 43 | * @throws If the source code contains a syntax, semantic, or type error. |
| 44 | */ |
| 45 | export function compileString(code: string, compilerOptions: CompileOptions = {}): Artifact { |
| 46 | const { errorListener, ...artifactCompilerOptions } = compilerOptions; |
| 47 | const mergedCompilerOptions = { ...DEFAULT_COMPILER_OPTIONS, ...artifactCompilerOptions }; |
| 48 | |
| 49 | // Lexing + parsing |
| 50 | let ast = parseCode(code, errorListener); |
| 51 | |
| 52 | // Semantic analysis |
| 53 | ast = ast.accept(new SymbolTableTraversal()) as Ast; |
| 54 | ast = ast.accept(new TypeCheckTraversal()) as Ast; |
| 55 | ast = ast.accept(new EnsureFinalRequireTraversal()) as Ast; |
| 56 | if (mergedCompilerOptions.enforceLocktimeGuard) { |
| 57 | ast = ast.accept(new InjectLocktimeGuardTraversal()) as Ast; |
| 58 | } |
| 59 | |
| 60 | // Code generation |
| 61 | const traversal = new GenerateTargetTraversal(mergedCompilerOptions); |
| 62 | ast = ast.accept(traversal) as Ast; |
| 63 | |
| 64 | const constructorParamLength = ast.contract.parameters.length; |
| 65 | |
| 66 | // Bytecode optimisation |
| 67 | const optimisedBytecodeOld = optimiseBytecodeOld(traversal.output); |
| 68 | const optimisationResult = optimiseBytecode( |
| 69 | traversal.output, |
| 70 | sourceMapToLocationData(traversal.sourceMap), |
| 71 | traversal.consoleLogs, |
| 72 | traversal.requires, |
| 73 | traversal.sourceTags, |
| 74 | constructorParamLength, |
| 75 | ); |
| 76 | |
| 77 | if (scriptToAsm(optimisedBytecodeOld) !== scriptToAsm(optimisationResult.script)) { |
| 78 | console.error(scriptToAsm(optimisedBytecodeOld)); |
| 79 | console.error(scriptToAsm(optimisationResult.script)); |
| 80 | throw new Error('New bytecode optimisation is not backwards compatible, please report this issue to the CashScript team'); |
| 81 | } |
| 82 | |
| 83 | // Attach debug information |
| 84 | const sourceTags = generateSourceTags(optimisationResult.sourceTags); |
| 85 | const debug = { |
| 86 | bytecode: binToHex(scriptToBytecode(optimisationResult.script)), |
| 87 | sourceMap: generateSourceMap(optimisationResult.locationData), |
| 88 | logs: optimisationResult.logs, |
| 89 | requires: optimisationResult.requires, |
| 90 | ...(sourceTags ? { sourceTags } : {}), |
| 91 | }; |
| 92 | |
| 93 | const fingerprint = computeBytecodeFingerprintWithConstructorArgs(optimisationResult.script, constructorParamLength); |
| 94 | |
| 95 | return generateArtifact(ast, optimisationResult.script, code, debug, mergedCompilerOptions, fingerprint); |
| 96 | } |
| 97 | |
| 98 | /** |
| 99 | * Read a `.cash` source file from disk and compile it to an `Artifact`. |
no test coverage detected