Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Throw internal/compiler errors instead Error when possible #669

Merged
merged 8 commits into from
Aug 9, 2024
Merged
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Removed unsupported iterators API: PR [#633](https://github.com/tact-lang/tact/pull/633)
- Created a separate API function to enable compiler features: PR [#647](https://github.com/tact-lang/tact/pull/647)
- Use the `ILogger` interface to enable API users implement their own loggers: PR [#668](https://github.com/tact-lang/tact/pull/668)
- Use specific Internal or Compiler errors when throwing exceptions: PR [#669](https://github.com/tact-lang/tact/pull/669)

### Fixed

Expand Down
13 changes: 7 additions & 6 deletions src/bindings/typescript/serializers.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { ABITypeRef } from "@ton/core";
import { Writer } from "../../utils/Writer";
import { throwInternalCompilerError } from "../../errors";

const primitiveTypes = [
"int",
Expand Down Expand Up @@ -519,27 +520,27 @@ const guard: Serializer<unknown> = {
abiMatcher(src) {
if (src.kind === "simple") {
if (primitiveTypes.includes(src.type)) {
throw Error(
throwInternalCompilerError(
`Unable to resolve serializer for ${src.type} with ${src.format ? src.format : null} format`,
);
}
}
return null;
},
tsType(_v) {
throw Error("Unreachable");
throwInternalCompilerError("Unreachable");
},
tsLoad(_v, _slice, _field, _w) {
throw Error("Unreachable");
throwInternalCompilerError("Unreachable");
},
tsLoadTuple(_v, _reader, _field, _w) {
throw Error("Unreachable");
throwInternalCompilerError("Unreachable");
},
tsStore(_v, _builder, _field, _w) {
throw Error("Unreachable");
throwInternalCompilerError("Unreachable");
},
tsStoreTuple(_v, _to, _field, _w) {
throw Error("Unreachable");
throwInternalCompilerError("Unreachable");
},
};

Expand Down
16 changes: 10 additions & 6 deletions src/bindings/typescript/writeStruct.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
import { ABIType, ABITypeRef } from "@ton/core";
import { serializers } from "./serializers";
import { AllocationCell, AllocationOperation } from "../../storage/operation";
import { throwInternalCompilerError } from "../../errors";
import { Writer } from "../../utils/Writer";

export const maxTupleSize = 15;

function throwUnsupportedType(type: ABITypeRef): never {
throwInternalCompilerError(`Unsupported type: ${JSON.stringify(type)}`);
}

export function writeStruct(
name: string,
fields: { name: string; type: ABITypeRef }[],
Expand All @@ -22,8 +27,7 @@ export function writeStruct(
continue outer;
}
}

throw Error("Unsupported type: " + JSON.stringify(f.type));
throwUnsupportedType(f.type);
}
});
w.append(`}`);
Expand Down Expand Up @@ -78,7 +82,7 @@ function writeParserField(
return;
}
}
throw Error("Unsupported type");
throwUnsupportedType(type);
}

export function writeSerializer(
Expand Down Expand Up @@ -141,7 +145,7 @@ function writeSerializerField(gen: number, s: AllocationOperation, w: Writer) {
return;
}
}
throw Error("Unsupported field type: " + JSON.stringify(type));
throwUnsupportedType(type);
}

export function writeTupleParser(s: ABIType, w: Writer) {
Expand Down Expand Up @@ -189,7 +193,7 @@ function writeTupleFieldParser(
return;
}
}
throw Error("Unsupported field type: " + JSON.stringify(type));
throwUnsupportedType(type);
}

export function writeTupleSerializer(s: ABIType, w: Writer) {
Expand Down Expand Up @@ -217,7 +221,7 @@ function writeVariableToStack(name: string, type: ABITypeRef, w: Writer) {
return;
}
}
throw Error("Unsupported field type: " + JSON.stringify(type));
throwUnsupportedType(type);
}

export function writeDictParser(s: ABIType, w: Writer) {
Expand Down
5 changes: 4 additions & 1 deletion src/bindings/writeTypescript.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
writeTupleSerializer,
} from "./typescript/writeStruct";
import { AllocationCell } from "../storage/operation";
import { throwInternalCompilerError } from "../errors";
import { topologicalSort } from "../utils/utils";
import {
allocate,
Expand All @@ -31,7 +32,9 @@ function writeArguments(args: ABIArgument[]) {
continue outer;
}
}
throw Error("Unsupported type: " + JSON.stringify(f.type));
throwInternalCompilerError(
`Unsupported type: ${JSON.stringify(f.type)}`,
);
}

return res;
Expand Down
35 changes: 20 additions & 15 deletions src/check.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { precompile } from "./pipeline/precompile";
export type CheckResultItem = {
type: "error" | "warning";
message: string;
location: {
location?: {
file: string;
line: number;
column: number;
Expand Down Expand Up @@ -44,20 +44,25 @@ export function check(args: {
items.push({
type: "error",
message: e.message,
location: e.loc.file
? {
file: e.loc.file,
line: e.loc.interval.getLineAndColumn().lineNum,
column: e.loc.interval.getLineAndColumn().colNum,
length:
e.loc.interval.endIdx - e.loc.interval.startIdx,
}
: {
file: args.entrypoint,
line: 0,
column: 0,
length: 0,
},
location:
e.loc === undefined
? undefined
: e.loc.file
? {
file: e.loc.file,
line: e.loc.interval.getLineAndColumn().lineNum,
column: e.loc.interval.getLineAndColumn()
.colNum,
length:
e.loc.interval.endIdx -
e.loc.interval.startIdx,
}
: {
file: args.entrypoint,
line: 0,
column: 0,
length: 0,
},
});
} else {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
Expand Down
35 changes: 21 additions & 14 deletions src/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import { AstFuncId, AstId, AstTypeId, SrcInfo } from "./grammar/ast";
import { ItemOrigin } from "./grammar/grammar";

export class TactError extends Error {
readonly loc: SrcInfo;
constructor(message: string, loc: SrcInfo) {
readonly loc?: SrcInfo;
constructor(message: string, loc?: SrcInfo) {
super(message);
this.loc = loc;
}
Expand All @@ -26,13 +26,13 @@ export class TactSyntaxError extends TactError {

/// This will be split at least into two categories: typechecking and codegen errors
export class TactCompilationError extends TactError {
constructor(message: string, loc: SrcInfo) {
constructor(message: string, loc?: SrcInfo) {
super(message, loc);
}
}

export class TactInternalCompilerError extends TactError {
constructor(message: string, loc: SrcInfo) {
constructor(message: string, loc?: SrcInfo) {
super(message, loc);
}
}
Expand Down Expand Up @@ -80,21 +80,28 @@ export function throwSyntaxError(message: string, source: SrcInfo): never {
);
}

export function throwCompilationError(message: string, source: SrcInfo): never {
throw new TactCompilationError(
`${locationStr(source)}${message}\n${source.interval.getLineAndColumnMessage()}`,
source,
);
export function throwCompilationError(
message: string,
source?: SrcInfo,
): never {
const loc =
Copy link
Member

@Gusarich Gusarich Aug 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's now less informative in some cases. For example, when trying to compile non-existing project source:

💼 Compiling project getters ...
Tact compilation failed
Error
    at throwCompilationError (/Users/daniil/Coding/tact/src/errors.ts:91:11)
    at resolveImports (/Users/daniil/Coding/tact/src/imports/resolveImports.ts:28:30)
    at precompile (/Users/daniil/Coding/tact/src/pipeline/precompile.ts:18:36)
    at build (/Users/daniil/Coding/tact/src/pipeline/build.ts:73:25)
    at run (/Users/daniil/Coding/tact/src/node.ts:130:34)
    at async /Users/daniil/Coding/tact/scripts/prepare.ts:20:31
Error: Tact projects compilation failed
    at /Users/daniil/Coding/tact/scripts/prepare.ts:24:19
error Command failed with exit code 1.

while before it would throw Could not find entrypoint XXX.

I think the problem is here, because it ignores message in case if no source location was provided.

source === undefined
? ""
: `${locationStr(source)}${message}\n${source.interval.getLineAndColumnMessage()}`;
throw new TactCompilationError(loc, source);
}

export function throwInternalCompilerError(
message: string,
source: SrcInfo,
source?: SrcInfo,
): never {
throw new TactInternalCompilerError(
`${locationStr(source)}\n[INTERNAL COMPILER ERROR]: ${message}\nPlease report at https://github.com/tact-lang/tact/issues\n${source.interval.getLineAndColumnMessage()}`,
source,
);
const msg = `[INTERNAL COMPILER ERROR]: ${message}\nPlease report at https://github.com/tact-lang/tact/issues`;
throw source === undefined
? new TactInternalCompilerError(msg)
: new TactInternalCompilerError(
`${locationStr(source)}\n${msg}\n${source.interval.getLineAndColumnMessage()}`,
source,
);
}

export function throwConstEvalError(
Expand Down
3 changes: 2 additions & 1 deletion src/grammar/clone.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { AstNode, cloneAstNode } from "./ast";
import { throwInternalCompilerError } from "../errors";

export function cloneNode<T extends AstNode>(src: T): T {
if (src.kind === "boolean") {
Expand Down Expand Up @@ -174,5 +175,5 @@ export function cloneNode<T extends AstNode>(src: T): T {
});
}

throw Error("Not implemented for " + src.kind);
throwInternalCompilerError(`Not implemented for ${src.kind}`);
}
5 changes: 3 additions & 2 deletions src/grammar/grammar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
Grammar,
} from "ohm-js";
import tactGrammar from "./grammar.ohm-bundle";
import { throwInternalCompilerError } from "../errors";
import {
AstAugmentedAssignOperation,
AstConstantAttribute,
Expand Down Expand Up @@ -675,8 +676,8 @@ semantics.addOperation<AstNode>("astOfStatement", {
op = "^";
break;
default:
throw Error(
"Internal compiler error: unreachable augmented assignment operator. Please report at https://github.com/tact-lang/tact/issues",
throwInternalCompilerError(
"Unreachable augmented assignment operator.",
);
}
return createAstNode({
Expand Down
3 changes: 2 additions & 1 deletion src/grammar/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
AstNativeFunctionDecl,
AstTypeDecl,
} from "./ast";
import { throwInternalCompilerError } from "../errors";
import { CompilerContext, createContextStore } from "../context";
import { ItemOrigin, parse } from "./grammar";

Expand Down Expand Up @@ -40,7 +41,7 @@ const store = createContextStore<AstStore>();
export function getRawAST(ctx: CompilerContext): AstStore {
const r = store.get(ctx, "types");
if (!r) {
throw Error("No AST found in context");
throwInternalCompilerError("No AST found in context");
}
return r;
}
Expand Down
15 changes: 11 additions & 4 deletions src/imports/resolveImports.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { ItemOrigin, parseImports } from "../grammar/grammar";
import { VirtualFileSystem } from "../vfs/VirtualFileSystem";
import { throwCompilationError } from "../errors";
import { resolveLibrary } from "./resolveLibrary";

export function resolveImports(args: {
Expand All @@ -16,13 +17,15 @@ export function resolveImports(args: {

const stdlibTactPath = args.stdlib.resolve("stdlib.tact");
if (!args.stdlib.exists(stdlibTactPath)) {
throw new Error(`Could not find stdlib.tact at ${stdlibTactPath}`);
throwCompilationError(
`Could not find stdlib.tact at ${stdlibTactPath}`,
);
}
const stdlibTact = args.stdlib.readFile(stdlibTactPath).toString();

const codePath = args.project.resolve(args.entrypoint);
if (!args.project.exists(codePath)) {
throw new Error(`Could not find entrypoint ${args.entrypoint}`);
throwCompilationError(`Could not find entrypoint ${args.entrypoint}`);
}
const code = args.project.readFile(codePath).toString();

Expand All @@ -47,7 +50,9 @@ export function resolveImports(args: {
stdlib: args.stdlib,
});
if (!resolved.ok) {
throw new Error(`Could not resolve import "${i}" in ${path}`);
throwCompilationError(
`Could not resolve import "${i}" in ${path}`,
);
}

// Check if already imported
Expand All @@ -65,7 +70,9 @@ export function resolveImports(args: {
const vfs =
resolved.source === "project" ? args.project : args.stdlib;
if (!vfs.exists(resolved.path)) {
throw new Error(`Could not find source file ${resolved.path}`);
throwCompilationError(
`Could not find source file ${resolved.path}`,
);
}
const code: string = vfs.readFile(resolved.path).toString();

Expand Down
3 changes: 2 additions & 1 deletion src/optimizer/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
isValue,
} from "../grammar/ast";
import { dummySrcInfo } from "../grammar/grammar";
import { throwInternalCompilerError } from "../errors";
import { Value } from "../types/types";

export function extractValue(ast: AstValue): Value {
Expand Down Expand Up @@ -56,7 +57,7 @@ export function makeValueExpression(value: Value): AstValue {
});
return result as AstValue;
}
throw new Error(
throwInternalCompilerError(
`structs, addresses, cells, and comment values are not supported at the moment.`,
);
}
Expand Down
3 changes: 2 additions & 1 deletion src/prettyPrinter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import {
AstFuncId,
idText,
} from "./grammar/ast";
import { throwInternalCompilerError } from "./errors";
import JSONbig from "json-bigint";

/**
Expand Down Expand Up @@ -728,7 +729,7 @@ export function prettyPrint(node: AstNode): string {
case "import":
return pp.ppAstImport(node);
default:
throw new Error(
throwInternalCompilerError(
`Unsupported AST type: ${JSONbig.stringify(node, null, 2)}`,
);
}
Expand Down
Loading
Loading