216 lines
7.5 KiB
TypeScript
216 lines
7.5 KiB
TypeScript
/* eslint-disable max-classes-per-file */
|
|
import type { IdentifierResolutionType } from '@bitauth/libauth';
|
|
|
|
/**
|
|
* Error thrown when a required variable is missing.
|
|
*/
|
|
export class CashAssemblyRequiredVariableMissingError extends Error {
|
|
/**
|
|
* Variable names that were required but absent from the variables map.
|
|
*/
|
|
readonly variableNames: string[];
|
|
|
|
constructor(variableNames: string[] = []) {
|
|
const defaultMessage = 'Missing required variable';
|
|
if (variableNames.length > 0) {
|
|
super(`${defaultMessage}: variableNames [${variableNames.join(', ')}]`);
|
|
} else {
|
|
super(defaultMessage);
|
|
}
|
|
|
|
this.variableNames = variableNames;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Error thrown when cash assembly compilation fails.
|
|
*/
|
|
export class CashAssemblyCompilationFailedError extends Error {
|
|
constructor(message?: string) {
|
|
const defaultMessage = 'Cash assembly compilation failed';
|
|
super(message ? `${defaultMessage}: ${message}` : defaultMessage);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Error thrown when a quoted string inside `$()` never closes.
|
|
*/
|
|
export class CashAssemblyQuotedLiteralUnclosedError extends Error {
|
|
/**
|
|
* Index of the opening quote that never found a closer.
|
|
*/
|
|
readonly openingQuoteIndex: number;
|
|
|
|
/**
|
|
* Quote character that opened the literal.
|
|
*/
|
|
readonly quoteCharacter: string;
|
|
|
|
/**
|
|
* Text from the opening quote through the end of the scanned string.
|
|
*/
|
|
readonly unclosedText: string;
|
|
|
|
constructor(openingQuoteIndex: number, quoteCharacter: string, cashAssemblyText: string) {
|
|
const unclosedText = cashAssemblyText.slice(openingQuoteIndex);
|
|
const defaultMessage = 'Quoted literal in a CashAssembly evaluation is unclosed';
|
|
const details = [
|
|
`quoteCharacter ${JSON.stringify(quoteCharacter)}`,
|
|
`openingQuoteIndex ${String(openingQuoteIndex)}`,
|
|
`unclosedText ${JSON.stringify(unclosedText)}`,
|
|
].join(', ');
|
|
|
|
super(`${defaultMessage}: ${details}`);
|
|
|
|
this.openingQuoteIndex = openingQuoteIndex;
|
|
this.quoteCharacter = quoteCharacter;
|
|
this.unclosedText = unclosedText;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Error thrown when a block comment inside `$()` never closes.
|
|
*/
|
|
export class CashAssemblyBlockCommentUnclosedError extends Error {
|
|
/**
|
|
* Index of the first slash of the block comment opener.
|
|
*/
|
|
readonly commentStartIndex: number;
|
|
|
|
/**
|
|
* Text from the block comment opener through the end of the scanned string.
|
|
*/
|
|
readonly unclosedText: string;
|
|
|
|
constructor(commentStartIndex: number, cashAssemblyText: string) {
|
|
const unclosedText = cashAssemblyText.slice(commentStartIndex);
|
|
const defaultMessage = 'Block comment in a CashAssembly evaluation is unclosed';
|
|
const details = [ `commentStartIndex ${String(commentStartIndex)}`, `unclosedText ${JSON.stringify(unclosedText)}` ].join(', ');
|
|
|
|
super(`${defaultMessage}: ${details}`);
|
|
|
|
this.commentStartIndex = commentStartIndex;
|
|
this.unclosedText = unclosedText;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Error thrown when a `$()` evaluation never finds its matching closer.
|
|
*/
|
|
export class CashAssemblyEvaluationUnclosedError extends Error {
|
|
/**
|
|
* Index of the `$` that opened the evaluation.
|
|
*/
|
|
readonly evaluationStartIndex: number;
|
|
|
|
/**
|
|
* How many `$()` remain open at the end of the string, including nested evaluations.
|
|
*/
|
|
readonly remainingOpenEvaluations: number;
|
|
|
|
/**
|
|
* Text from the opening `$` through the end of the scanned string.
|
|
*/
|
|
readonly unclosedText: string;
|
|
|
|
constructor(evaluationStartIndex: number, remainingOpenEvaluations: number, cashAssemblyText: string) {
|
|
const unclosedText = cashAssemblyText.slice(evaluationStartIndex);
|
|
const defaultMessage = 'CashAssembly evaluation is unclosed';
|
|
const details = [
|
|
`evaluationStartIndex ${String(evaluationStartIndex)}`,
|
|
`remainingOpenEvaluations ${String(remainingOpenEvaluations)}`,
|
|
`unclosedText ${JSON.stringify(unclosedText)}`,
|
|
].join(', ');
|
|
|
|
super(`${defaultMessage}: ${details}`);
|
|
|
|
this.evaluationStartIndex = evaluationStartIndex;
|
|
this.remainingOpenEvaluations = remainingOpenEvaluations;
|
|
this.unclosedText = unclosedText;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Error thrown when a variable's runtime type does not match the type required for compilation.
|
|
*/
|
|
export class CashAssemblyVariableTypeMismatchError extends Error {
|
|
constructor(variableKey: string, expectedType: string, actualType: string) {
|
|
const defaultMessage = 'Variable type mismatch';
|
|
super(`${defaultMessage}: variableKey "${variableKey}", expected ${expectedType}, got ${actualType}`);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Error thrown when a method resolvable primitive type does not expose the requested method.
|
|
*/
|
|
export class CashAssemblyPrimitiveMethodMissingError extends Error {
|
|
constructor(identifier: string, methodName: string, type: string) {
|
|
const defaultMessage = 'CashAssembly primitive method does not exist';
|
|
super(`${defaultMessage}: identifier "${identifier}", methodName "${methodName}", type "${type}"`);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Error thrown when a value cannot be resolved as bytes.
|
|
*/
|
|
export class CashAssemblyUnsupportedValueTypeError extends Error {
|
|
constructor(identifier: string, returnedType: string) {
|
|
const defaultMessage = 'CashAssembly value type is unsupported for byte resolution';
|
|
super(`${defaultMessage}: identifier "${identifier}", returnedType "${returnedType}"`);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Error thrown when a number cannot be safely encoded as a CashAssembly VM number.
|
|
*/
|
|
export class CashAssemblyNumberNotSafeIntegerError extends Error {
|
|
constructor(identifier: string, value: number) {
|
|
const defaultMessage = 'CashAssembly number is not a safe integer';
|
|
super(`${defaultMessage}: identifier "${identifier}", got ${String(value)}`);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Error thrown when a method resolvable primitive is selected but its value is missing from the variables map.
|
|
*/
|
|
export class CashAssemblyPrimitiveVariableMissingError extends Error {
|
|
constructor(identifier: string, variableName: string) {
|
|
const defaultMessage = 'CashAssembly primitive variable is missing from the variables map';
|
|
super(`${defaultMessage}: identifier "${identifier}", variableName "${variableName}"`);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Error thrown when one identifier would resolve as more than one {@link IdentifierResolutionType}.
|
|
*/
|
|
export class CashAssemblyIdentifierCollisionError extends Error {
|
|
/**
|
|
* Identifier that more than one resolution type would match.
|
|
*/
|
|
readonly identifier: string;
|
|
|
|
/**
|
|
* The list of resolution types that the identifier matches.
|
|
*/
|
|
readonly resolutionTypes: IdentifierResolutionType[];
|
|
|
|
constructor(identifier: string, resolutionTypes: IdentifierResolutionType[]) {
|
|
const defaultMessage = 'CashAssembly identifier exists for more than one resolution type';
|
|
|
|
super(`${defaultMessage}: identifier "${identifier}", resolutionTypes [${resolutionTypes.join(', ')}]`);
|
|
|
|
this.identifier = identifier;
|
|
this.resolutionTypes = resolutionTypes;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Error thrown when compiled evaluation bytes cannot be decoded as a VM number.
|
|
*/
|
|
export class CashAssemblyVmNumberDecodeError extends Error {
|
|
constructor(reason: string) {
|
|
const defaultMessage = 'CashAssembly evaluation could not be decoded as a VM number';
|
|
super(`${defaultMessage}: ${reason}`);
|
|
}
|
|
}
|