diff --git a/package.json b/package.json index d8d3b3c433..30e6502430 100644 --- a/package.json +++ b/package.json @@ -58,6 +58,7 @@ "all": "yarn clean && yarn gen && yarn build && yarn coverage && yarn lint:all", "next-version": "ts-node version.build.ts", "random-ast": "ts-node ./src/ast/random-ast.ts", + "gen:make-funs": "ts-node ./src/ast/generated/gen-make-functions-script.ts && yarn prettier -w ./src/ast/generated/make-factory.ts", "top10": "find . -type f -exec du -h {} + | sort -rh | head -n 10" }, "files": [ @@ -106,6 +107,9 @@ "@types/node": "^22.5.0", "@typescript-eslint/eslint-plugin": "^8.21.0", "@typescript-eslint/parser": "^8.21.0", + "@babel/generator": "^7.26.5", + "@babel/parser": "^7.26.5", + "@babel/types": "^7.26.5", "chalk": "4.1.2", "cli-table3": "^0.6.5", "cross-env": "^7.0.3", diff --git a/src/ast/generated/gen-make-functions-script.ts b/src/ast/generated/gen-make-functions-script.ts new file mode 100644 index 0000000000..6cb420179b --- /dev/null +++ b/src/ast/generated/gen-make-functions-script.ts @@ -0,0 +1,308 @@ +import generate from "@babel/generator"; +import type { ParserOptions } from "@babel/parser"; +import { parse } from "@babel/parser"; +import * as t from "@babel/types"; +import * as fs from "fs"; +import * as path from "path"; + +function main() { + const options: ParserOptions = { + sourceType: "module", + plugins: ["typescript"], + }; + + const astModule = fs + .readFileSync(path.join(__dirname, "..", "ast.ts")) + .toString(); + + const astTypeDecls = parse(astModule, options); + const decls = astTypeDecls.program.body + .filter((stmt) => t.isExportNamedDeclaration(stmt)) + .map((stmt) => stmt.declaration) + .filter((stmt) => t.isTSTypeAliasDeclaration(stmt)); + + const declNames = new Set(decls.map((decl) => decl.id.name)); + + const finalFunctions: { name: string; code: string }[] = []; + + // Extract from the declarations all the union types + const unionTypes = decls + .map((decl) => decl.typeAnnotation) + .filter((decl) => t.isTSUnionType(decl)); + + for (const unionType of unionTypes) { + const subtypes = unionType.types + .filter((typeDecl) => t.isTSTypeReference(typeDecl)) + .map((typeDecl) => typeDecl.typeName) + .filter((typeDecl) => t.isIdentifier(typeDecl)); + + for (const subtype of subtypes) { + const subtypeDecl = decls.find( + (decl) => decl.id.name === subtype.name, + ); + if (typeof subtypeDecl === "undefined") { + throw new Error(`${subtype.name} is not declared.`); + } + + const subtypeDeclAnnotation = subtypeDecl.typeAnnotation; + if (t.isTSTypeLiteral(subtypeDeclAnnotation)) { + const genFunctions = createMakeAndDummyFunctions( + subtypeDeclAnnotation, + subtypeDecl.id, + declNames, + ); + const genFunctionsFiltered = genFunctions.filter((genF) => + finalFunctions.every((f) => f.name !== genF.name), + ); + + if (genFunctionsFiltered.length > 0) { + console.log( + `Generated [${genFunctionsFiltered.map((entry) => entry.name).join(", ")}] for ${subtype.name}`, + ); + } + + finalFunctions.push(...genFunctionsFiltered); + } else if (t.isTSUnionType(subtypeDeclAnnotation)) { + // Do nothing, since it will be processed later. + } else { + // Unexpected type + throw new Error( + `${subtype.name} is not a reference to a type literal or a union type.`, + ); + } + } + } + + // Create the make factory file + const makeFactoryTemplate = fs + .readFileSync(path.join(__dirname, "make-factory.template")) + .toString(); + + const functionCodes = finalFunctions + .map((genFun) => genFun.code) + .join("\n\n"); + const functionNames = finalFunctions + .map((genFun) => genFun.name) + .join(",\n"); + + const makeFactoryCode = makeFactoryTemplate + .replace("", functionCodes) + .replace("", functionNames); + + fs.writeFileSync(path.join(__dirname, "make-factory.ts"), makeFactoryCode); + + console.log("Finished."); +} + +function createMakeAndDummyFunctions( + decl: t.TSTypeLiteral, + id: t.Identifier, + decls: Set, +): { name: string; code: string }[] { + const astNamespace = "Ast"; + const astFactoryObject = "astF"; + const createNodeFunName = "createNode"; + const emptySrcInfo = "emptySrcInfo"; + + const rawFieldsArray = decl.members.filter((decl) => + t.isTSPropertySignature(decl), + ); + const generalParams: { id: t.Identifier; type: t.TSType }[] = []; + const paramsWithLiteralTypes: { + id: t.Identifier; + type: t.TSLiteralType; + }[] = []; + + // If there is no loc field, + // the makeDummy function cannot be created + const makeDummy = rawFieldsArray.some( + (f) => t.isIdentifier(f.key) && f.key.name === "loc", + ); + + for (const field of rawFieldsArray) { + if (!t.isIdentifier(field.key)) { + throw new Error( + `Expected identifier in fields, but found ${field.key.type}`, + ); + } + const fieldName = field.key.name; + if (fieldName === "id") { + // The id field should not occur as an argument to the function, + // nor as a parameter to createNode + continue; + } + if (field.typeAnnotation) { + const typeAnnotation = field.typeAnnotation.typeAnnotation; + if (t.isTSLiteralType(typeAnnotation)) { + paramsWithLiteralTypes.push({ + id: field.key, + type: typeAnnotation, + }); + } else { + generalParams.push({ id: field.key, type: typeAnnotation }); + } + } else { + throw new Error( + `Expected field ${fieldName} to have a type annotation`, + ); + } + } + + const makeFunName = `make${id.name}`; + const makeDummyFunName = `makeDummy${id.name}`; + // The params to the make functions do not have fields with literal types + // Also, the dummy function needs to filter the loc parameter + const createParam = (entry: { id: t.Identifier; type: t.TSType }) => { + const newId = t.identifier(`p_${entry.id.name}`); + newId.typeAnnotation = t.tsTypeAnnotation( + qualifyType(astNamespace, entry.type, decls), + ); + return newId; + }; + const makeFunParamsArray = generalParams.map((entry) => createParam(entry)); + const makeDummyFunParamsArray = generalParams + .filter(({ id, type: _ }) => id.name !== "loc") + .map((entry) => createParam(entry)); + + // The arguments with literal values to the createNode call inside the make functions body + const createNodeLiteralArgs = paramsWithLiteralTypes.map(({ id, type }) => + t.objectProperty(id, type.literal), + ); + // The non-literal arguments to the createNode call inside the make functions body + const createNodeArgsForMake = generalParams.map(({ id, type: _ }) => + t.objectProperty(id, t.identifier(`p_${id.name}`)), + ); + const createNodeArgsForMakeDummy = generalParams.map(({ id, type: _ }) => + id.name === "loc" + ? t.objectProperty(id, t.identifier(emptySrcInfo)) + : t.objectProperty(id, t.identifier(`p_${id.name}`)), + ); + const funReturnType = t.tsTypeReference( + t.tsQualifiedName(t.identifier(astNamespace), id), + ); + // Function to create the function codes + const createFun = ( + name: string, + params: t.Identifier[], + createNodeArgs: t.ObjectProperty[], + ) => { + const body = t.returnStatement( + t.tsAsExpression( + t.callExpression( + t.memberExpression( + t.identifier(astFactoryObject), + t.identifier(createNodeFunName), + ), + [t.objectExpression(createNodeArgs)], + ), + funReturnType, + ), + ); + const funDecl = t.functionDeclaration( + t.identifier(name), + params, + t.blockStatement([body]), + ); + funDecl.returnType = t.tsTypeAnnotation(funReturnType); + return funDecl; + }; + + const makeFun = createFun(makeFunName, makeFunParamsArray, [ + ...createNodeLiteralArgs, + ...createNodeArgsForMake, + ]); + const makeDummyFun = createFun(makeDummyFunName, makeDummyFunParamsArray, [ + ...createNodeLiteralArgs, + ...createNodeArgsForMakeDummy, + ]); + + if (makeDummy) { + return [ + { name: makeFunName, code: generate(makeFun).code }, + { name: makeDummyFunName, code: generate(makeDummyFun).code }, + ]; + } else { + console.log( + `[WARNING] Skipped makeDummy for ${id.name}, because there is no loc field in ${id.name}.`, + ); + return [{ name: makeFunName, code: generate(makeFun).code }]; + } +} + +function qualifyType( + namespace: string, + typ: t.TSType, + decls: Set, +): t.TSType { + switch (typ.type) { + case "TSTypeReference": { + if (t.isIdentifier(typ.typeName)) { + if (decls.has(typ.typeName.name)) { + return t.tsTypeReference( + t.tsQualifiedName( + t.identifier(namespace), + typ.typeName, + ), + ); + } else { + // Leave the identifier unchanged, but check if it has type parameters + const typRef = t.tsTypeReference(typ.typeName); + if (typ.typeParameters) { + typRef.typeParameters = t.tsTypeParameterInstantiation( + typ.typeParameters.params.map((t) => + qualifyType(namespace, t, decls), + ), + ); + } + return typRef; + } + } + // Leave the type as is + return typ; + } + case "TSUnionType": { + return t.tsUnionType( + typ.types.map((t) => qualifyType(namespace, t, decls)), + ); + } + case "TSArrayType": { + return t.tsArrayType( + qualifyType(namespace, typ.elementType, decls), + ); + } + case "TSTypeOperator": { + const op = t.tsTypeOperator( + qualifyType(namespace, typ.typeAnnotation, decls), + ); + op.operator = typ.operator; + return op; + } + case "TSTupleType": { + if ( + // Cannot use guard function isTSNamedTupleMember, because compiler cannot deduce the type inside + // the condition if the guard function is used. + typ.elementTypes.every((ty) => ty.type !== "TSNamedTupleMember") + ) { + return t.tsTupleType( + typ.elementTypes.map((t) => + qualifyType(namespace, t, decls), + ), + ); + } else { + // Currently unsupported + throw new Error( + "TSNamedTupleMember is currently not supported in TSTupleType", + ); + } + } + case "TSUndefinedKeyword": + case "TSStringKeyword": + case "TSBooleanKeyword": + case "TSBigIntKeyword": + return typ; + default: + throw new Error(`${typ.type} is not supported`); + } +} + +main(); diff --git a/src/ast/generated/make-factory.template b/src/ast/generated/make-factory.template new file mode 100644 index 0000000000..cfda1e463c --- /dev/null +++ b/src/ast/generated/make-factory.template @@ -0,0 +1,20 @@ +// THIS IS AN AUTOGENERATED FILE. TO GENERATE IT AGAIN, EXECUTE yarn gen:make-funs + +import type { FactoryAst } from "@/ast/ast-helpers"; +import type * as Ast from "@/ast/ast"; +import type { SrcInfo } from "@/grammar"; +import type * as TonCore from "@ton/core"; +import { getSrcInfo } from "@/grammar/src-info"; + +export const getMakeAst = (astF: FactoryAst) => { + + const emptySrcInfo = getSrcInfo(" ", 0, 0, null, "user"); + + + + return { + + }; +}; + +export type MakeAstFactory = ReturnType; \ No newline at end of file diff --git a/src/ast/generated/make-factory.ts b/src/ast/generated/make-factory.ts new file mode 100644 index 0000000000..2b61d29399 --- /dev/null +++ b/src/ast/generated/make-factory.ts @@ -0,0 +1,1711 @@ +// THIS IS AN AUTOGENERATED FILE. TO GENERATE IT AGAIN, EXECUTE yarn gen:make-funs + +import type { FactoryAst } from "@/ast/ast-helpers"; +import type * as Ast from "@/ast/ast"; +import type { SrcInfo } from "@/grammar"; +import type * as TonCore from "@ton/core"; +import { getSrcInfo } from "@/grammar/src-info"; + +export const getMakeAst = (astF: FactoryAst) => { + const emptySrcInfo = getSrcInfo(" ", 0, 0, null, "user"); + + function makePrimitiveTypeDecl( + p_name: Ast.Id, + p_loc: SrcInfo, + ): Ast.PrimitiveTypeDecl { + return astF.createNode({ + kind: "primitive_type_decl", + name: p_name, + loc: p_loc, + }) as Ast.PrimitiveTypeDecl; + } + + function makeDummyPrimitiveTypeDecl(p_name: Ast.Id): Ast.PrimitiveTypeDecl { + return astF.createNode({ + kind: "primitive_type_decl", + name: p_name, + loc: emptySrcInfo, + }) as Ast.PrimitiveTypeDecl; + } + + function makeFunctionDef( + p_attributes: readonly Ast.FunctionAttribute[], + p_name: Ast.Id, + p_return: Ast.Type | undefined, + p_params: readonly Ast.TypedParameter[], + p_statements: readonly Ast.Statement[], + p_loc: SrcInfo, + ): Ast.FunctionDef { + return astF.createNode({ + kind: "function_def", + attributes: p_attributes, + name: p_name, + return: p_return, + params: p_params, + statements: p_statements, + loc: p_loc, + }) as Ast.FunctionDef; + } + + function makeDummyFunctionDef( + p_attributes: readonly Ast.FunctionAttribute[], + p_name: Ast.Id, + p_return: Ast.Type | undefined, + p_params: readonly Ast.TypedParameter[], + p_statements: readonly Ast.Statement[], + ): Ast.FunctionDef { + return astF.createNode({ + kind: "function_def", + attributes: p_attributes, + name: p_name, + return: p_return, + params: p_params, + statements: p_statements, + loc: emptySrcInfo, + }) as Ast.FunctionDef; + } + + function makeAsmFunctionDef( + p_shuffle: Ast.AsmShuffle, + p_attributes: readonly Ast.FunctionAttribute[], + p_name: Ast.Id, + p_return: Ast.Type | undefined, + p_params: readonly Ast.TypedParameter[], + p_instructions: readonly Ast.AsmInstruction[], + p_loc: SrcInfo, + ): Ast.AsmFunctionDef { + return astF.createNode({ + kind: "asm_function_def", + shuffle: p_shuffle, + attributes: p_attributes, + name: p_name, + return: p_return, + params: p_params, + instructions: p_instructions, + loc: p_loc, + }) as Ast.AsmFunctionDef; + } + + function makeDummyAsmFunctionDef( + p_shuffle: Ast.AsmShuffle, + p_attributes: readonly Ast.FunctionAttribute[], + p_name: Ast.Id, + p_return: Ast.Type | undefined, + p_params: readonly Ast.TypedParameter[], + p_instructions: readonly Ast.AsmInstruction[], + ): Ast.AsmFunctionDef { + return astF.createNode({ + kind: "asm_function_def", + shuffle: p_shuffle, + attributes: p_attributes, + name: p_name, + return: p_return, + params: p_params, + instructions: p_instructions, + loc: emptySrcInfo, + }) as Ast.AsmFunctionDef; + } + + function makeNativeFunctionDecl( + p_attributes: readonly Ast.FunctionAttribute[], + p_name: Ast.Id, + p_nativeName: Ast.FuncId, + p_params: readonly Ast.TypedParameter[], + p_return: Ast.Type | undefined, + p_loc: SrcInfo, + ): Ast.NativeFunctionDecl { + return astF.createNode({ + kind: "native_function_decl", + attributes: p_attributes, + name: p_name, + nativeName: p_nativeName, + params: p_params, + return: p_return, + loc: p_loc, + }) as Ast.NativeFunctionDecl; + } + + function makeDummyNativeFunctionDecl( + p_attributes: readonly Ast.FunctionAttribute[], + p_name: Ast.Id, + p_nativeName: Ast.FuncId, + p_params: readonly Ast.TypedParameter[], + p_return: Ast.Type | undefined, + ): Ast.NativeFunctionDecl { + return astF.createNode({ + kind: "native_function_decl", + attributes: p_attributes, + name: p_name, + nativeName: p_nativeName, + params: p_params, + return: p_return, + loc: emptySrcInfo, + }) as Ast.NativeFunctionDecl; + } + + function makeConstantDef( + p_attributes: readonly Ast.ConstantAttribute[], + p_name: Ast.Id, + p_type: Ast.Type, + p_initializer: Ast.Expression, + p_loc: SrcInfo, + ): Ast.ConstantDef { + return astF.createNode({ + kind: "constant_def", + attributes: p_attributes, + name: p_name, + type: p_type, + initializer: p_initializer, + loc: p_loc, + }) as Ast.ConstantDef; + } + + function makeDummyConstantDef( + p_attributes: readonly Ast.ConstantAttribute[], + p_name: Ast.Id, + p_type: Ast.Type, + p_initializer: Ast.Expression, + ): Ast.ConstantDef { + return astF.createNode({ + kind: "constant_def", + attributes: p_attributes, + name: p_name, + type: p_type, + initializer: p_initializer, + loc: emptySrcInfo, + }) as Ast.ConstantDef; + } + + function makeStructDecl( + p_name: Ast.Id, + p_fields: readonly Ast.FieldDecl[], + p_loc: SrcInfo, + ): Ast.StructDecl { + return astF.createNode({ + kind: "struct_decl", + name: p_name, + fields: p_fields, + loc: p_loc, + }) as Ast.StructDecl; + } + + function makeDummyStructDecl( + p_name: Ast.Id, + p_fields: readonly Ast.FieldDecl[], + ): Ast.StructDecl { + return astF.createNode({ + kind: "struct_decl", + name: p_name, + fields: p_fields, + loc: emptySrcInfo, + }) as Ast.StructDecl; + } + + function makeMessageDecl( + p_name: Ast.Id, + p_opcode: Ast.Expression | undefined, + p_fields: readonly Ast.FieldDecl[], + p_loc: SrcInfo, + ): Ast.MessageDecl { + return astF.createNode({ + kind: "message_decl", + name: p_name, + opcode: p_opcode, + fields: p_fields, + loc: p_loc, + }) as Ast.MessageDecl; + } + + function makeDummyMessageDecl( + p_name: Ast.Id, + p_opcode: Ast.Expression | undefined, + p_fields: readonly Ast.FieldDecl[], + ): Ast.MessageDecl { + return astF.createNode({ + kind: "message_decl", + name: p_name, + opcode: p_opcode, + fields: p_fields, + loc: emptySrcInfo, + }) as Ast.MessageDecl; + } + + function makeContract( + p_name: Ast.Id, + p_traits: readonly Ast.Id[], + p_attributes: readonly Ast.ContractAttribute[], + p_params: undefined | readonly Ast.FieldDecl[], + p_declarations: readonly Ast.ContractDeclaration[], + p_loc: SrcInfo, + ): Ast.Contract { + return astF.createNode({ + kind: "contract", + name: p_name, + traits: p_traits, + attributes: p_attributes, + params: p_params, + declarations: p_declarations, + loc: p_loc, + }) as Ast.Contract; + } + + function makeDummyContract( + p_name: Ast.Id, + p_traits: readonly Ast.Id[], + p_attributes: readonly Ast.ContractAttribute[], + p_params: undefined | readonly Ast.FieldDecl[], + p_declarations: readonly Ast.ContractDeclaration[], + ): Ast.Contract { + return astF.createNode({ + kind: "contract", + name: p_name, + traits: p_traits, + attributes: p_attributes, + params: p_params, + declarations: p_declarations, + loc: emptySrcInfo, + }) as Ast.Contract; + } + + function makeTrait( + p_name: Ast.Id, + p_traits: readonly Ast.Id[], + p_attributes: readonly Ast.ContractAttribute[], + p_declarations: readonly Ast.TraitDeclaration[], + p_loc: SrcInfo, + ): Ast.Trait { + return astF.createNode({ + kind: "trait", + name: p_name, + traits: p_traits, + attributes: p_attributes, + declarations: p_declarations, + loc: p_loc, + }) as Ast.Trait; + } + + function makeDummyTrait( + p_name: Ast.Id, + p_traits: readonly Ast.Id[], + p_attributes: readonly Ast.ContractAttribute[], + p_declarations: readonly Ast.TraitDeclaration[], + ): Ast.Trait { + return astF.createNode({ + kind: "trait", + name: p_name, + traits: p_traits, + attributes: p_attributes, + declarations: p_declarations, + loc: emptySrcInfo, + }) as Ast.Trait; + } + + function makeFieldDecl( + p_name: Ast.Id, + p_type: Ast.Type, + p_initializer: Ast.Expression | undefined, + p_as: Ast.Id | undefined, + p_loc: SrcInfo, + ): Ast.FieldDecl { + return astF.createNode({ + kind: "field_decl", + name: p_name, + type: p_type, + initializer: p_initializer, + as: p_as, + loc: p_loc, + }) as Ast.FieldDecl; + } + + function makeDummyFieldDecl( + p_name: Ast.Id, + p_type: Ast.Type, + p_initializer: Ast.Expression | undefined, + p_as: Ast.Id | undefined, + ): Ast.FieldDecl { + return astF.createNode({ + kind: "field_decl", + name: p_name, + type: p_type, + initializer: p_initializer, + as: p_as, + loc: emptySrcInfo, + }) as Ast.FieldDecl; + } + + function makeContractInit( + p_params: readonly Ast.TypedParameter[], + p_statements: readonly Ast.Statement[], + p_loc: SrcInfo, + ): Ast.ContractInit { + return astF.createNode({ + kind: "contract_init", + params: p_params, + statements: p_statements, + loc: p_loc, + }) as Ast.ContractInit; + } + + function makeDummyContractInit( + p_params: readonly Ast.TypedParameter[], + p_statements: readonly Ast.Statement[], + ): Ast.ContractInit { + return astF.createNode({ + kind: "contract_init", + params: p_params, + statements: p_statements, + loc: emptySrcInfo, + }) as Ast.ContractInit; + } + + function makeReceiver( + p_selector: Ast.ReceiverKind, + p_statements: readonly Ast.Statement[], + p_loc: SrcInfo, + ): Ast.Receiver { + return astF.createNode({ + kind: "receiver", + selector: p_selector, + statements: p_statements, + loc: p_loc, + }) as Ast.Receiver; + } + + function makeDummyReceiver( + p_selector: Ast.ReceiverKind, + p_statements: readonly Ast.Statement[], + ): Ast.Receiver { + return astF.createNode({ + kind: "receiver", + selector: p_selector, + statements: p_statements, + loc: emptySrcInfo, + }) as Ast.Receiver; + } + + function makeFunctionDecl( + p_attributes: readonly Ast.FunctionAttribute[], + p_name: Ast.Id, + p_return: Ast.Type | undefined, + p_params: readonly Ast.TypedParameter[], + p_loc: SrcInfo, + ): Ast.FunctionDecl { + return astF.createNode({ + kind: "function_decl", + attributes: p_attributes, + name: p_name, + return: p_return, + params: p_params, + loc: p_loc, + }) as Ast.FunctionDecl; + } + + function makeDummyFunctionDecl( + p_attributes: readonly Ast.FunctionAttribute[], + p_name: Ast.Id, + p_return: Ast.Type | undefined, + p_params: readonly Ast.TypedParameter[], + ): Ast.FunctionDecl { + return astF.createNode({ + kind: "function_decl", + attributes: p_attributes, + name: p_name, + return: p_return, + params: p_params, + loc: emptySrcInfo, + }) as Ast.FunctionDecl; + } + + function makeConstantDecl( + p_attributes: readonly Ast.ConstantAttribute[], + p_name: Ast.Id, + p_type: Ast.Type, + p_loc: SrcInfo, + ): Ast.ConstantDecl { + return astF.createNode({ + kind: "constant_decl", + attributes: p_attributes, + name: p_name, + type: p_type, + loc: p_loc, + }) as Ast.ConstantDecl; + } + + function makeDummyConstantDecl( + p_attributes: readonly Ast.ConstantAttribute[], + p_name: Ast.Id, + p_type: Ast.Type, + ): Ast.ConstantDecl { + return astF.createNode({ + kind: "constant_decl", + attributes: p_attributes, + name: p_name, + type: p_type, + loc: emptySrcInfo, + }) as Ast.ConstantDecl; + } + + function makeStatementLet( + p_name: Ast.OptionalId, + p_type: Ast.Type | undefined, + p_expression: Ast.Expression, + p_loc: SrcInfo, + ): Ast.StatementLet { + return astF.createNode({ + kind: "statement_let", + name: p_name, + type: p_type, + expression: p_expression, + loc: p_loc, + }) as Ast.StatementLet; + } + + function makeDummyStatementLet( + p_name: Ast.OptionalId, + p_type: Ast.Type | undefined, + p_expression: Ast.Expression, + ): Ast.StatementLet { + return astF.createNode({ + kind: "statement_let", + name: p_name, + type: p_type, + expression: p_expression, + loc: emptySrcInfo, + }) as Ast.StatementLet; + } + + function makeStatementReturn( + p_expression: Ast.Expression | undefined, + p_loc: SrcInfo, + ): Ast.StatementReturn { + return astF.createNode({ + kind: "statement_return", + expression: p_expression, + loc: p_loc, + }) as Ast.StatementReturn; + } + + function makeDummyStatementReturn( + p_expression: Ast.Expression | undefined, + ): Ast.StatementReturn { + return astF.createNode({ + kind: "statement_return", + expression: p_expression, + loc: emptySrcInfo, + }) as Ast.StatementReturn; + } + + function makeStatementExpression( + p_expression: Ast.Expression, + p_loc: SrcInfo, + ): Ast.StatementExpression { + return astF.createNode({ + kind: "statement_expression", + expression: p_expression, + loc: p_loc, + }) as Ast.StatementExpression; + } + + function makeDummyStatementExpression( + p_expression: Ast.Expression, + ): Ast.StatementExpression { + return astF.createNode({ + kind: "statement_expression", + expression: p_expression, + loc: emptySrcInfo, + }) as Ast.StatementExpression; + } + + function makeStatementAssign( + p_path: Ast.Expression, + p_expression: Ast.Expression, + p_loc: SrcInfo, + ): Ast.StatementAssign { + return astF.createNode({ + kind: "statement_assign", + path: p_path, + expression: p_expression, + loc: p_loc, + }) as Ast.StatementAssign; + } + + function makeDummyStatementAssign( + p_path: Ast.Expression, + p_expression: Ast.Expression, + ): Ast.StatementAssign { + return astF.createNode({ + kind: "statement_assign", + path: p_path, + expression: p_expression, + loc: emptySrcInfo, + }) as Ast.StatementAssign; + } + + function makeStatementAugmentedAssign( + p_op: Ast.AugmentedAssignOperation, + p_path: Ast.Expression, + p_expression: Ast.Expression, + p_loc: SrcInfo, + ): Ast.StatementAugmentedAssign { + return astF.createNode({ + kind: "statement_augmentedassign", + op: p_op, + path: p_path, + expression: p_expression, + loc: p_loc, + }) as Ast.StatementAugmentedAssign; + } + + function makeDummyStatementAugmentedAssign( + p_op: Ast.AugmentedAssignOperation, + p_path: Ast.Expression, + p_expression: Ast.Expression, + ): Ast.StatementAugmentedAssign { + return astF.createNode({ + kind: "statement_augmentedassign", + op: p_op, + path: p_path, + expression: p_expression, + loc: emptySrcInfo, + }) as Ast.StatementAugmentedAssign; + } + + function makeStatementCondition( + p_condition: Ast.Expression, + p_trueStatements: readonly Ast.Statement[], + p_falseStatements: readonly Ast.Statement[] | undefined, + p_loc: SrcInfo, + ): Ast.StatementCondition { + return astF.createNode({ + kind: "statement_condition", + condition: p_condition, + trueStatements: p_trueStatements, + falseStatements: p_falseStatements, + loc: p_loc, + }) as Ast.StatementCondition; + } + + function makeDummyStatementCondition( + p_condition: Ast.Expression, + p_trueStatements: readonly Ast.Statement[], + p_falseStatements: readonly Ast.Statement[] | undefined, + ): Ast.StatementCondition { + return astF.createNode({ + kind: "statement_condition", + condition: p_condition, + trueStatements: p_trueStatements, + falseStatements: p_falseStatements, + loc: emptySrcInfo, + }) as Ast.StatementCondition; + } + + function makeStatementWhile( + p_condition: Ast.Expression, + p_statements: readonly Ast.Statement[], + p_loc: SrcInfo, + ): Ast.StatementWhile { + return astF.createNode({ + kind: "statement_while", + condition: p_condition, + statements: p_statements, + loc: p_loc, + }) as Ast.StatementWhile; + } + + function makeDummyStatementWhile( + p_condition: Ast.Expression, + p_statements: readonly Ast.Statement[], + ): Ast.StatementWhile { + return astF.createNode({ + kind: "statement_while", + condition: p_condition, + statements: p_statements, + loc: emptySrcInfo, + }) as Ast.StatementWhile; + } + + function makeStatementUntil( + p_condition: Ast.Expression, + p_statements: readonly Ast.Statement[], + p_loc: SrcInfo, + ): Ast.StatementUntil { + return astF.createNode({ + kind: "statement_until", + condition: p_condition, + statements: p_statements, + loc: p_loc, + }) as Ast.StatementUntil; + } + + function makeDummyStatementUntil( + p_condition: Ast.Expression, + p_statements: readonly Ast.Statement[], + ): Ast.StatementUntil { + return astF.createNode({ + kind: "statement_until", + condition: p_condition, + statements: p_statements, + loc: emptySrcInfo, + }) as Ast.StatementUntil; + } + + function makeStatementRepeat( + p_iterations: Ast.Expression, + p_statements: readonly Ast.Statement[], + p_loc: SrcInfo, + ): Ast.StatementRepeat { + return astF.createNode({ + kind: "statement_repeat", + iterations: p_iterations, + statements: p_statements, + loc: p_loc, + }) as Ast.StatementRepeat; + } + + function makeDummyStatementRepeat( + p_iterations: Ast.Expression, + p_statements: readonly Ast.Statement[], + ): Ast.StatementRepeat { + return astF.createNode({ + kind: "statement_repeat", + iterations: p_iterations, + statements: p_statements, + loc: emptySrcInfo, + }) as Ast.StatementRepeat; + } + + function makeStatementTry( + p_statements: readonly Ast.Statement[], + p_catchBlock: Ast.CatchBlock | undefined, + p_loc: SrcInfo, + ): Ast.StatementTry { + return astF.createNode({ + kind: "statement_try", + statements: p_statements, + catchBlock: p_catchBlock, + loc: p_loc, + }) as Ast.StatementTry; + } + + function makeDummyStatementTry( + p_statements: readonly Ast.Statement[], + p_catchBlock: Ast.CatchBlock | undefined, + ): Ast.StatementTry { + return astF.createNode({ + kind: "statement_try", + statements: p_statements, + catchBlock: p_catchBlock, + loc: emptySrcInfo, + }) as Ast.StatementTry; + } + + function makeStatementForEach( + p_keyName: Ast.OptionalId, + p_valueName: Ast.OptionalId, + p_map: Ast.Expression, + p_statements: readonly Ast.Statement[], + p_loc: SrcInfo, + ): Ast.StatementForEach { + return astF.createNode({ + kind: "statement_foreach", + keyName: p_keyName, + valueName: p_valueName, + map: p_map, + statements: p_statements, + loc: p_loc, + }) as Ast.StatementForEach; + } + + function makeDummyStatementForEach( + p_keyName: Ast.OptionalId, + p_valueName: Ast.OptionalId, + p_map: Ast.Expression, + p_statements: readonly Ast.Statement[], + ): Ast.StatementForEach { + return astF.createNode({ + kind: "statement_foreach", + keyName: p_keyName, + valueName: p_valueName, + map: p_map, + statements: p_statements, + loc: emptySrcInfo, + }) as Ast.StatementForEach; + } + + function makeStatementDestruct( + p_type: Ast.TypeId, + p_identifiers: ReadonlyMap, + p_ignoreUnspecifiedFields: boolean, + p_expression: Ast.Expression, + p_loc: SrcInfo, + ): Ast.StatementDestruct { + return astF.createNode({ + kind: "statement_destruct", + type: p_type, + identifiers: p_identifiers, + ignoreUnspecifiedFields: p_ignoreUnspecifiedFields, + expression: p_expression, + loc: p_loc, + }) as Ast.StatementDestruct; + } + + function makeDummyStatementDestruct( + p_type: Ast.TypeId, + p_identifiers: ReadonlyMap, + p_ignoreUnspecifiedFields: boolean, + p_expression: Ast.Expression, + ): Ast.StatementDestruct { + return astF.createNode({ + kind: "statement_destruct", + type: p_type, + identifiers: p_identifiers, + ignoreUnspecifiedFields: p_ignoreUnspecifiedFields, + expression: p_expression, + loc: emptySrcInfo, + }) as Ast.StatementDestruct; + } + + function makeStatementBlock( + p_statements: readonly Ast.Statement[], + p_loc: SrcInfo, + ): Ast.StatementBlock { + return astF.createNode({ + kind: "statement_block", + statements: p_statements, + loc: p_loc, + }) as Ast.StatementBlock; + } + + function makeDummyStatementBlock( + p_statements: readonly Ast.Statement[], + ): Ast.StatementBlock { + return astF.createNode({ + kind: "statement_block", + statements: p_statements, + loc: emptySrcInfo, + }) as Ast.StatementBlock; + } + + function makeTypeId(p_text: string, p_loc: SrcInfo): Ast.TypeId { + return astF.createNode({ + kind: "type_id", + text: p_text, + loc: p_loc, + }) as Ast.TypeId; + } + + function makeDummyTypeId(p_text: string): Ast.TypeId { + return astF.createNode({ + kind: "type_id", + text: p_text, + loc: emptySrcInfo, + }) as Ast.TypeId; + } + + function makeOptionalType( + p_typeArg: Ast.Type, + p_loc: SrcInfo, + ): Ast.OptionalType { + return astF.createNode({ + kind: "optional_type", + typeArg: p_typeArg, + loc: p_loc, + }) as Ast.OptionalType; + } + + function makeDummyOptionalType(p_typeArg: Ast.Type): Ast.OptionalType { + return astF.createNode({ + kind: "optional_type", + typeArg: p_typeArg, + loc: emptySrcInfo, + }) as Ast.OptionalType; + } + + function makeMapType( + p_keyType: Ast.TypeId, + p_keyStorageType: Ast.Id | undefined, + p_valueType: Ast.TypeId, + p_valueStorageType: Ast.Id | undefined, + p_loc: SrcInfo, + ): Ast.MapType { + return astF.createNode({ + kind: "map_type", + keyType: p_keyType, + keyStorageType: p_keyStorageType, + valueType: p_valueType, + valueStorageType: p_valueStorageType, + loc: p_loc, + }) as Ast.MapType; + } + + function makeDummyMapType( + p_keyType: Ast.TypeId, + p_keyStorageType: Ast.Id | undefined, + p_valueType: Ast.TypeId, + p_valueStorageType: Ast.Id | undefined, + ): Ast.MapType { + return astF.createNode({ + kind: "map_type", + keyType: p_keyType, + keyStorageType: p_keyStorageType, + valueType: p_valueType, + valueStorageType: p_valueStorageType, + loc: emptySrcInfo, + }) as Ast.MapType; + } + + function makeBouncedMessageType( + p_messageType: Ast.TypeId, + p_loc: SrcInfo, + ): Ast.BouncedMessageType { + return astF.createNode({ + kind: "bounced_message_type", + messageType: p_messageType, + loc: p_loc, + }) as Ast.BouncedMessageType; + } + + function makeDummyBouncedMessageType( + p_messageType: Ast.TypeId, + ): Ast.BouncedMessageType { + return astF.createNode({ + kind: "bounced_message_type", + messageType: p_messageType, + loc: emptySrcInfo, + }) as Ast.BouncedMessageType; + } + + function makeOpBinary( + p_op: Ast.BinaryOperation, + p_left: Ast.Expression, + p_right: Ast.Expression, + p_loc: SrcInfo, + ): Ast.OpBinary { + return astF.createNode({ + kind: "op_binary", + op: p_op, + left: p_left, + right: p_right, + loc: p_loc, + }) as Ast.OpBinary; + } + + function makeDummyOpBinary( + p_op: Ast.BinaryOperation, + p_left: Ast.Expression, + p_right: Ast.Expression, + ): Ast.OpBinary { + return astF.createNode({ + kind: "op_binary", + op: p_op, + left: p_left, + right: p_right, + loc: emptySrcInfo, + }) as Ast.OpBinary; + } + + function makeOpUnary( + p_op: Ast.UnaryOperation, + p_operand: Ast.Expression, + p_loc: SrcInfo, + ): Ast.OpUnary { + return astF.createNode({ + kind: "op_unary", + op: p_op, + operand: p_operand, + loc: p_loc, + }) as Ast.OpUnary; + } + + function makeDummyOpUnary( + p_op: Ast.UnaryOperation, + p_operand: Ast.Expression, + ): Ast.OpUnary { + return astF.createNode({ + kind: "op_unary", + op: p_op, + operand: p_operand, + loc: emptySrcInfo, + }) as Ast.OpUnary; + } + + function makeConditional( + p_condition: Ast.Expression, + p_thenBranch: Ast.Expression, + p_elseBranch: Ast.Expression, + p_loc: SrcInfo, + ): Ast.Conditional { + return astF.createNode({ + kind: "conditional", + condition: p_condition, + thenBranch: p_thenBranch, + elseBranch: p_elseBranch, + loc: p_loc, + }) as Ast.Conditional; + } + + function makeDummyConditional( + p_condition: Ast.Expression, + p_thenBranch: Ast.Expression, + p_elseBranch: Ast.Expression, + ): Ast.Conditional { + return astF.createNode({ + kind: "conditional", + condition: p_condition, + thenBranch: p_thenBranch, + elseBranch: p_elseBranch, + loc: emptySrcInfo, + }) as Ast.Conditional; + } + + function makeMethodCall( + p_self: Ast.Expression, + p_method: Ast.Id, + p_args: readonly Ast.Expression[], + p_loc: SrcInfo, + ): Ast.MethodCall { + return astF.createNode({ + kind: "method_call", + self: p_self, + method: p_method, + args: p_args, + loc: p_loc, + }) as Ast.MethodCall; + } + + function makeDummyMethodCall( + p_self: Ast.Expression, + p_method: Ast.Id, + p_args: readonly Ast.Expression[], + ): Ast.MethodCall { + return astF.createNode({ + kind: "method_call", + self: p_self, + method: p_method, + args: p_args, + loc: emptySrcInfo, + }) as Ast.MethodCall; + } + + function makeFieldAccess( + p_aggregate: Ast.Expression, + p_field: Ast.Id, + p_loc: SrcInfo, + ): Ast.FieldAccess { + return astF.createNode({ + kind: "field_access", + aggregate: p_aggregate, + field: p_field, + loc: p_loc, + }) as Ast.FieldAccess; + } + + function makeDummyFieldAccess( + p_aggregate: Ast.Expression, + p_field: Ast.Id, + ): Ast.FieldAccess { + return astF.createNode({ + kind: "field_access", + aggregate: p_aggregate, + field: p_field, + loc: emptySrcInfo, + }) as Ast.FieldAccess; + } + + function makeStaticCall( + p_function: Ast.Id, + p_args: readonly Ast.Expression[], + p_loc: SrcInfo, + ): Ast.StaticCall { + return astF.createNode({ + kind: "static_call", + function: p_function, + args: p_args, + loc: p_loc, + }) as Ast.StaticCall; + } + + function makeDummyStaticCall( + p_function: Ast.Id, + p_args: readonly Ast.Expression[], + ): Ast.StaticCall { + return astF.createNode({ + kind: "static_call", + function: p_function, + args: p_args, + loc: emptySrcInfo, + }) as Ast.StaticCall; + } + + function makeStructInstance( + p_type: Ast.Id, + p_args: readonly Ast.StructFieldInitializer[], + p_loc: SrcInfo, + ): Ast.StructInstance { + return astF.createNode({ + kind: "struct_instance", + type: p_type, + args: p_args, + loc: p_loc, + }) as Ast.StructInstance; + } + + function makeDummyStructInstance( + p_type: Ast.Id, + p_args: readonly Ast.StructFieldInitializer[], + ): Ast.StructInstance { + return astF.createNode({ + kind: "struct_instance", + type: p_type, + args: p_args, + loc: emptySrcInfo, + }) as Ast.StructInstance; + } + + function makeId(p_text: string, p_loc: SrcInfo): Ast.Id { + return astF.createNode({ + kind: "id", + text: p_text, + loc: p_loc, + }) as Ast.Id; + } + + function makeDummyId(p_text: string): Ast.Id { + return astF.createNode({ + kind: "id", + text: p_text, + loc: emptySrcInfo, + }) as Ast.Id; + } + + function makeInitOf( + p_contract: Ast.Id, + p_args: readonly Ast.Expression[], + p_loc: SrcInfo, + ): Ast.InitOf { + return astF.createNode({ + kind: "init_of", + contract: p_contract, + args: p_args, + loc: p_loc, + }) as Ast.InitOf; + } + + function makeDummyInitOf( + p_contract: Ast.Id, + p_args: readonly Ast.Expression[], + ): Ast.InitOf { + return astF.createNode({ + kind: "init_of", + contract: p_contract, + args: p_args, + loc: emptySrcInfo, + }) as Ast.InitOf; + } + + function makeCodeOf(p_contract: Ast.Id, p_loc: SrcInfo): Ast.CodeOf { + return astF.createNode({ + kind: "code_of", + contract: p_contract, + loc: p_loc, + }) as Ast.CodeOf; + } + + function makeDummyCodeOf(p_contract: Ast.Id): Ast.CodeOf { + return astF.createNode({ + kind: "code_of", + contract: p_contract, + loc: emptySrcInfo, + }) as Ast.CodeOf; + } + + function makeNumber( + p_base: Ast.NumberBase, + p_value: bigint, + p_loc: SrcInfo, + ): Ast.Number { + return astF.createNode({ + kind: "number", + base: p_base, + value: p_value, + loc: p_loc, + }) as Ast.Number; + } + + function makeDummyNumber( + p_base: Ast.NumberBase, + p_value: bigint, + ): Ast.Number { + return astF.createNode({ + kind: "number", + base: p_base, + value: p_value, + loc: emptySrcInfo, + }) as Ast.Number; + } + + function makeBoolean(p_value: boolean, p_loc: SrcInfo): Ast.Boolean { + return astF.createNode({ + kind: "boolean", + value: p_value, + loc: p_loc, + }) as Ast.Boolean; + } + + function makeDummyBoolean(p_value: boolean): Ast.Boolean { + return astF.createNode({ + kind: "boolean", + value: p_value, + loc: emptySrcInfo, + }) as Ast.Boolean; + } + + function makeNull(p_loc: SrcInfo): Ast.Null { + return astF.createNode({ + kind: "null", + loc: p_loc, + }) as Ast.Null; + } + + function makeDummyNull(): Ast.Null { + return astF.createNode({ + kind: "null", + loc: emptySrcInfo, + }) as Ast.Null; + } + + function makeString(p_value: string, p_loc: SrcInfo): Ast.String { + return astF.createNode({ + kind: "string", + value: p_value, + loc: p_loc, + }) as Ast.String; + } + + function makeDummyString(p_value: string): Ast.String { + return astF.createNode({ + kind: "string", + value: p_value, + loc: emptySrcInfo, + }) as Ast.String; + } + + function makeAddress( + p_value: TonCore.Address, + p_loc: SrcInfo, + ): Ast.Address { + return astF.createNode({ + kind: "address", + value: p_value, + loc: p_loc, + }) as Ast.Address; + } + + function makeDummyAddress(p_value: TonCore.Address): Ast.Address { + return astF.createNode({ + kind: "address", + value: p_value, + loc: emptySrcInfo, + }) as Ast.Address; + } + + function makeCell(p_value: TonCore.Cell, p_loc: SrcInfo): Ast.Cell { + return astF.createNode({ + kind: "cell", + value: p_value, + loc: p_loc, + }) as Ast.Cell; + } + + function makeDummyCell(p_value: TonCore.Cell): Ast.Cell { + return astF.createNode({ + kind: "cell", + value: p_value, + loc: emptySrcInfo, + }) as Ast.Cell; + } + + function makeSlice(p_value: TonCore.Slice, p_loc: SrcInfo): Ast.Slice { + return astF.createNode({ + kind: "slice", + value: p_value, + loc: p_loc, + }) as Ast.Slice; + } + + function makeDummySlice(p_value: TonCore.Slice): Ast.Slice { + return astF.createNode({ + kind: "slice", + value: p_value, + loc: emptySrcInfo, + }) as Ast.Slice; + } + + function makeStructValue( + p_type: Ast.Id, + p_args: readonly Ast.StructFieldValue[], + p_loc: SrcInfo, + ): Ast.StructValue { + return astF.createNode({ + kind: "struct_value", + type: p_type, + args: p_args, + loc: p_loc, + }) as Ast.StructValue; + } + + function makeDummyStructValue( + p_type: Ast.Id, + p_args: readonly Ast.StructFieldValue[], + ): Ast.StructValue { + return astF.createNode({ + kind: "struct_value", + type: p_type, + args: p_args, + loc: emptySrcInfo, + }) as Ast.StructValue; + } + + function makeWildcard(p_loc: SrcInfo): Ast.Wildcard { + return astF.createNode({ + kind: "wildcard", + loc: p_loc, + }) as Ast.Wildcard; + } + + function makeDummyWildcard(): Ast.Wildcard { + return astF.createNode({ + kind: "wildcard", + loc: emptySrcInfo, + }) as Ast.Wildcard; + } + + function makeFunctionAttributeGet( + p_methodId: Ast.Expression | undefined, + p_loc: SrcInfo, + ): Ast.FunctionAttributeGet { + return astF.createNode({ + kind: "function_attribute", + type: "get", + methodId: p_methodId, + loc: p_loc, + }) as Ast.FunctionAttributeGet; + } + + function makeDummyFunctionAttributeGet( + p_methodId: Ast.Expression | undefined, + ): Ast.FunctionAttributeGet { + return astF.createNode({ + kind: "function_attribute", + type: "get", + methodId: p_methodId, + loc: emptySrcInfo, + }) as Ast.FunctionAttributeGet; + } + + function makeFunctionAttributeRest( + p_type: Ast.FunctionAttributeName, + p_loc: SrcInfo, + ): Ast.FunctionAttributeRest { + return astF.createNode({ + kind: "function_attribute", + type: p_type, + loc: p_loc, + }) as Ast.FunctionAttributeRest; + } + + function makeDummyFunctionAttributeRest( + p_type: Ast.FunctionAttributeName, + ): Ast.FunctionAttributeRest { + return astF.createNode({ + kind: "function_attribute", + type: p_type, + loc: emptySrcInfo, + }) as Ast.FunctionAttributeRest; + } + + function makeReceiverSimple( + p_param: Ast.TypedParameter, + ): Ast.ReceiverSimple { + return astF.createNode({ + kind: "simple", + param: p_param, + }) as Ast.ReceiverSimple; + } + + function makeReceiverFallback(): Ast.ReceiverFallback { + return astF.createNode({ + kind: "fallback", + }) as Ast.ReceiverFallback; + } + + function makeReceiverComment(p_comment: Ast.String): Ast.ReceiverComment { + return astF.createNode({ + kind: "comment", + comment: p_comment, + }) as Ast.ReceiverComment; + } + + function makeReceiverInternal( + p_subKind: Ast.ReceiverSubKind, + p_loc: SrcInfo, + ): Ast.ReceiverInternal { + return astF.createNode({ + kind: "internal", + subKind: p_subKind, + loc: p_loc, + }) as Ast.ReceiverInternal; + } + + function makeDummyReceiverInternal( + p_subKind: Ast.ReceiverSubKind, + ): Ast.ReceiverInternal { + return astF.createNode({ + kind: "internal", + subKind: p_subKind, + loc: emptySrcInfo, + }) as Ast.ReceiverInternal; + } + + function makeReceiverExternal( + p_subKind: Ast.ReceiverSubKind, + p_loc: SrcInfo, + ): Ast.ReceiverExternal { + return astF.createNode({ + kind: "external", + subKind: p_subKind, + loc: p_loc, + }) as Ast.ReceiverExternal; + } + + function makeDummyReceiverExternal( + p_subKind: Ast.ReceiverSubKind, + ): Ast.ReceiverExternal { + return astF.createNode({ + kind: "external", + subKind: p_subKind, + loc: emptySrcInfo, + }) as Ast.ReceiverExternal; + } + + function makeReceiverBounce( + p_param: Ast.TypedParameter, + p_loc: SrcInfo, + ): Ast.ReceiverBounce { + return astF.createNode({ + kind: "bounce", + param: p_param, + loc: p_loc, + }) as Ast.ReceiverBounce; + } + + function makeDummyReceiverBounce( + p_param: Ast.TypedParameter, + ): Ast.ReceiverBounce { + return astF.createNode({ + kind: "bounce", + param: p_param, + loc: emptySrcInfo, + }) as Ast.ReceiverBounce; + } + + function makeFuncId(p_text: string, p_loc: SrcInfo): Ast.FuncId { + return astF.createNode({ + kind: "func_id", + text: p_text, + loc: p_loc, + }) as Ast.FuncId; + } + + function makeDummyFuncId(p_text: string): Ast.FuncId { + return astF.createNode({ + kind: "func_id", + text: p_text, + loc: emptySrcInfo, + }) as Ast.FuncId; + } + + function makeDestructMapping( + p_field: Ast.Id, + p_name: Ast.Id, + p_loc: SrcInfo, + ): Ast.DestructMapping { + return astF.createNode({ + kind: "destruct_mapping", + field: p_field, + name: p_name, + loc: p_loc, + }) as Ast.DestructMapping; + } + + function makeDummyDestructMapping( + p_field: Ast.Id, + p_name: Ast.Id, + ): Ast.DestructMapping { + return astF.createNode({ + kind: "destruct_mapping", + field: p_field, + name: p_name, + loc: emptySrcInfo, + }) as Ast.DestructMapping; + } + + function makeDestructEnd( + p_ignoreUnspecifiedFields: boolean, + p_loc: SrcInfo, + ): Ast.DestructEnd { + return astF.createNode({ + kind: "destruct_end", + ignoreUnspecifiedFields: p_ignoreUnspecifiedFields, + loc: p_loc, + }) as Ast.DestructEnd; + } + + function makeDummyDestructEnd( + p_ignoreUnspecifiedFields: boolean, + ): Ast.DestructEnd { + return astF.createNode({ + kind: "destruct_end", + ignoreUnspecifiedFields: p_ignoreUnspecifiedFields, + loc: emptySrcInfo, + }) as Ast.DestructEnd; + } + + function makeTypedParameter( + p_name: Ast.OptionalId, + p_type: Ast.Type, + p_loc: SrcInfo, + ): Ast.TypedParameter { + return astF.createNode({ + kind: "typed_parameter", + name: p_name, + type: p_type, + loc: p_loc, + }) as Ast.TypedParameter; + } + + function makeDummyTypedParameter( + p_name: Ast.OptionalId, + p_type: Ast.Type, + ): Ast.TypedParameter { + return astF.createNode({ + kind: "typed_parameter", + name: p_name, + type: p_type, + loc: emptySrcInfo, + }) as Ast.TypedParameter; + } + + function makeModule( + p_imports: readonly Ast.Import[], + p_items: readonly Ast.ModuleItem[], + ): Ast.Module { + return astF.createNode({ + kind: "module", + imports: p_imports, + items: p_items, + }) as Ast.Module; + } + + function makeStructFieldInitializer( + p_field: Ast.Id, + p_initializer: Ast.Expression, + p_loc: SrcInfo, + ): Ast.StructFieldInitializer { + return astF.createNode({ + kind: "struct_field_initializer", + field: p_field, + initializer: p_initializer, + loc: p_loc, + }) as Ast.StructFieldInitializer; + } + + function makeDummyStructFieldInitializer( + p_field: Ast.Id, + p_initializer: Ast.Expression, + ): Ast.StructFieldInitializer { + return astF.createNode({ + kind: "struct_field_initializer", + field: p_field, + initializer: p_initializer, + loc: emptySrcInfo, + }) as Ast.StructFieldInitializer; + } + + function makeStructFieldValue( + p_field: Ast.Id, + p_initializer: Ast.Literal, + p_loc: SrcInfo, + ): Ast.StructFieldValue { + return astF.createNode({ + kind: "struct_field_value", + field: p_field, + initializer: p_initializer, + loc: p_loc, + }) as Ast.StructFieldValue; + } + + function makeDummyStructFieldValue( + p_field: Ast.Id, + p_initializer: Ast.Literal, + ): Ast.StructFieldValue { + return astF.createNode({ + kind: "struct_field_value", + field: p_field, + initializer: p_initializer, + loc: emptySrcInfo, + }) as Ast.StructFieldValue; + } + + function makeImport( + p_importPath: Ast.ImportPath, + p_loc: SrcInfo, + ): Ast.Import { + return astF.createNode({ + kind: "import", + importPath: p_importPath, + loc: p_loc, + }) as Ast.Import; + } + + function makeDummyImport(p_importPath: Ast.ImportPath): Ast.Import { + return astF.createNode({ + kind: "import", + importPath: p_importPath, + loc: emptySrcInfo, + }) as Ast.Import; + } + + return { + makePrimitiveTypeDecl, + makeDummyPrimitiveTypeDecl, + makeFunctionDef, + makeDummyFunctionDef, + makeAsmFunctionDef, + makeDummyAsmFunctionDef, + makeNativeFunctionDecl, + makeDummyNativeFunctionDecl, + makeConstantDef, + makeDummyConstantDef, + makeStructDecl, + makeDummyStructDecl, + makeMessageDecl, + makeDummyMessageDecl, + makeContract, + makeDummyContract, + makeTrait, + makeDummyTrait, + makeFieldDecl, + makeDummyFieldDecl, + makeContractInit, + makeDummyContractInit, + makeReceiver, + makeDummyReceiver, + makeFunctionDecl, + makeDummyFunctionDecl, + makeConstantDecl, + makeDummyConstantDecl, + makeStatementLet, + makeDummyStatementLet, + makeStatementReturn, + makeDummyStatementReturn, + makeStatementExpression, + makeDummyStatementExpression, + makeStatementAssign, + makeDummyStatementAssign, + makeStatementAugmentedAssign, + makeDummyStatementAugmentedAssign, + makeStatementCondition, + makeDummyStatementCondition, + makeStatementWhile, + makeDummyStatementWhile, + makeStatementUntil, + makeDummyStatementUntil, + makeStatementRepeat, + makeDummyStatementRepeat, + makeStatementTry, + makeDummyStatementTry, + makeStatementForEach, + makeDummyStatementForEach, + makeStatementDestruct, + makeDummyStatementDestruct, + makeStatementBlock, + makeDummyStatementBlock, + makeTypeId, + makeDummyTypeId, + makeOptionalType, + makeDummyOptionalType, + makeMapType, + makeDummyMapType, + makeBouncedMessageType, + makeDummyBouncedMessageType, + makeOpBinary, + makeDummyOpBinary, + makeOpUnary, + makeDummyOpUnary, + makeConditional, + makeDummyConditional, + makeMethodCall, + makeDummyMethodCall, + makeFieldAccess, + makeDummyFieldAccess, + makeStaticCall, + makeDummyStaticCall, + makeStructInstance, + makeDummyStructInstance, + makeId, + makeDummyId, + makeInitOf, + makeDummyInitOf, + makeCodeOf, + makeDummyCodeOf, + makeNumber, + makeDummyNumber, + makeBoolean, + makeDummyBoolean, + makeNull, + makeDummyNull, + makeString, + makeDummyString, + makeAddress, + makeDummyAddress, + makeCell, + makeDummyCell, + makeSlice, + makeDummySlice, + makeStructValue, + makeDummyStructValue, + makeWildcard, + makeDummyWildcard, + makeFunctionAttributeGet, + makeDummyFunctionAttributeGet, + makeFunctionAttributeRest, + makeDummyFunctionAttributeRest, + makeReceiverSimple, + makeReceiverFallback, + makeReceiverComment, + makeReceiverInternal, + makeDummyReceiverInternal, + makeReceiverExternal, + makeDummyReceiverExternal, + makeReceiverBounce, + makeDummyReceiverBounce, + makeFuncId, + makeDummyFuncId, + makeDestructMapping, + makeDummyDestructMapping, + makeDestructEnd, + makeDummyDestructEnd, + makeTypedParameter, + makeDummyTypedParameter, + makeModule, + makeStructFieldInitializer, + makeDummyStructFieldInitializer, + makeStructFieldValue, + makeDummyStructFieldValue, + makeImport, + makeDummyImport, + }; +}; + +export type MakeAstFactory = ReturnType; diff --git a/src/context/store.ts b/src/context/store.ts index c52bc5bb28..3246952ea6 100644 --- a/src/context/store.ts +++ b/src/context/store.ts @@ -53,17 +53,15 @@ export function parseModules(sources: Source[], parser: Parser): Ast.Module[] { * Extends the compiler context by adding AST entries and source information from * given sources and parsed programs. * @public - * @param parsedModules An optional array of previously parsed programs. If not defined, they will be parsed from `sources`. + * @param modules Previously parsed sources. * @returns The updated compiler context. */ export function openContext( ctx: CompilerContext, sources: Source[], funcSources: { code: string; path: string }[], - parser: Parser, - parsedModules?: Ast.Module[], + modules: Ast.Module[], ): CompilerContext { - const modules = parsedModules ?? parseModules(sources, parser); const types: Ast.TypeDecl[] = []; const functions: ( | Ast.NativeFunctionDecl diff --git a/src/generator/writers/resolveFuncType.spec.ts b/src/generator/writers/resolveFuncType.spec.ts index 00401ca0ca..4e797583c2 100644 --- a/src/generator/writers/resolveFuncType.spec.ts +++ b/src/generator/writers/resolveFuncType.spec.ts @@ -2,9 +2,10 @@ import { getAstFactory } from "@/ast/ast-helpers"; import { resolveDescriptors } from "@/types/resolveDescriptors"; import { WriterContext } from "@/generator/Writer"; import { resolveFuncType } from "@/generator/writers/resolveFuncType"; -import { openContext } from "@/context/store"; +import { openContext, parseModules } from "@/context/store"; import { CompilerContext } from "@/context/context"; import { getParser } from "@/grammar"; +import type { Source } from "@/imports/source"; const primitiveCode = ` primitive Int; @@ -48,11 +49,14 @@ contract Contract2 { describe("resolveFuncType", () => { it("should process primitive types", () => { const ast = getAstFactory(); + const sources: Source[] = [ + { code: primitiveCode, path: "", origin: "user" }, + ]; let ctx = openContext( new CompilerContext(), - [{ code: primitiveCode, path: "", origin: "user" }], + sources, [], - getParser(ast), + parseModules(sources, getParser(ast)), ); ctx = resolveDescriptors(ctx, ast); const wCtx = new WriterContext(ctx, "Contract1"); @@ -117,11 +121,14 @@ describe("resolveFuncType", () => { it("should process contract and struct types", () => { const ast = getAstFactory(); + const sources: Source[] = [ + { code: primitiveCode, path: "", origin: "user" }, + ]; let ctx = openContext( new CompilerContext(), - [{ code: primitiveCode, path: "", origin: "user" }], + sources, [], - getParser(ast), + parseModules(sources, getParser(ast)), ); ctx = resolveDescriptors(ctx, ast); const wCtx = new WriterContext(ctx, "Contract1"); diff --git a/src/generator/writers/writeExpression.spec.ts b/src/generator/writers/writeExpression.spec.ts index b7caf0d338..615ca374dc 100644 --- a/src/generator/writers/writeExpression.spec.ts +++ b/src/generator/writers/writeExpression.spec.ts @@ -4,11 +4,12 @@ import { } from "@/types/resolveDescriptors"; import { WriterContext } from "@/generator/Writer"; import { writeExpression } from "@/generator/writers/writeExpression"; -import { openContext } from "@/context/store"; +import { openContext, parseModules } from "@/context/store"; import { resolveStatements } from "@/types/resolveStatements"; import { CompilerContext } from "@/context/context"; import { getParser } from "@/grammar"; import { getAstFactory } from "@/ast/ast-helpers"; +import type { Source } from "@/imports/source"; const code = ` @@ -71,11 +72,14 @@ const golden: string[] = [ describe("writeExpression", () => { it("should write expression", () => { const ast = getAstFactory(); + const sources: Source[] = [ + { code: code, path: "", origin: "user" }, + ]; let ctx = openContext( new CompilerContext(), - [{ code: code, path: "", origin: "user" }], + sources, [], - getParser(ast), + parseModules(sources, getParser(ast)), ); ctx = resolveDescriptors(ctx, ast); ctx = resolveStatements(ctx); diff --git a/src/generator/writers/writeSerialization.spec.ts b/src/generator/writers/writeSerialization.spec.ts index 01decf1a26..82d3cb1299 100644 --- a/src/generator/writers/writeSerialization.spec.ts +++ b/src/generator/writers/writeSerialization.spec.ts @@ -11,10 +11,11 @@ import { writeSerializer, } from "@/generator/writers/writeSerialization"; import { writeStdlib } from "@/generator/writers/writeStdlib"; -import { openContext } from "@/context/store"; +import { openContext, parseModules } from "@/context/store"; import { writeAccessors } from "@/generator/writers/writeAccessors"; import { getParser } from "@/grammar"; import { getAstFactory } from "@/ast/ast-helpers"; +import type { Source } from "@/imports/source"; const code = ` primitive Int; @@ -60,11 +61,14 @@ describe("writeSerialization", () => { for (const s of ["A", "B", "C"]) { it("should write serializer for " + s, () => { const ast = getAstFactory(); + const sources: Source[] = [ + { code, path: "", origin: "user" }, + ]; let ctx = openContext( new CompilerContext(), - [{ code, path: "", origin: "user" }], + sources, [], - getParser(ast), + parseModules(sources, getParser(ast)), ); ctx = resolveDescriptors(ctx, ast); ctx = resolveAllocations(ctx); diff --git a/src/optimizer/test/interpreter-eval-failed.spec.ts b/src/optimizer/test/interpreter-eval-failed.spec.ts index e5f22ebeeb..8240679e13 100644 --- a/src/optimizer/test/interpreter-eval-failed.spec.ts +++ b/src/optimizer/test/interpreter-eval-failed.spec.ts @@ -1,7 +1,8 @@ import { getAstFactory } from "@/ast/ast-helpers"; import { CompilerContext } from "@/context/context"; -import { openContext } from "@/context/store"; +import { openContext, parseModules } from "@/context/store"; import { getParser } from "@/grammar"; +import type { Source } from "@/imports/source"; import { evalComptimeExpressions } from "@/types/evalComptimeExpressions"; import { resolveDescriptors } from "@/types/resolveDescriptors"; import { resolveSignatures } from "@/types/resolveSignatures"; @@ -12,11 +13,14 @@ describe("interpreter-evaluation", () => { for (const r of loadCases(__dirname + "/failed/")) { it(`${r.name} should fail compilation`, () => { const Ast = getAstFactory(); + const sources: Source[] = [ + { code: r.code, path: "", origin: "user" }, + ]; let ctx = openContext( new CompilerContext(), - [{ code: r.code, path: "", origin: "user" }], + sources, [], - getParser(Ast), + parseModules(sources, getParser(Ast)), ); expect(() => { ctx = resolveDescriptors(ctx, Ast); diff --git a/src/optimizer/test/interpreter-eval-success.spec.ts b/src/optimizer/test/interpreter-eval-success.spec.ts index 76436178af..da9ce1444e 100644 --- a/src/optimizer/test/interpreter-eval-success.spec.ts +++ b/src/optimizer/test/interpreter-eval-success.spec.ts @@ -1,7 +1,8 @@ import { getAstFactory } from "@/ast/ast-helpers"; import { CompilerContext } from "@/context/context"; -import { openContext } from "@/context/store"; +import { openContext, parseModules } from "@/context/store"; import { getParser } from "@/grammar"; +import type { Source } from "@/imports/source"; import { evalComptimeExpressions } from "@/types/evalComptimeExpressions"; import { resolveDescriptors } from "@/types/resolveDescriptors"; import { getAllExpressionTypes } from "@/types/resolveExpression"; @@ -13,11 +14,14 @@ describe("interpreter-evaluation", () => { for (const r of loadCases(__dirname + "/success/")) { it(`${r.name} should pass compilation`, () => { const Ast = getAstFactory(); + const sources: Source[] = [ + { code: r.code, path: "", origin: "user" }, + ]; let ctx = openContext( new CompilerContext(), - [{ code: r.code, path: "", origin: "user" }], + sources, [], - getParser(Ast), + parseModules(sources, getParser(Ast)), ); ctx = resolveDescriptors(ctx, Ast); ctx = resolveStatements(ctx); diff --git a/src/pipeline/precompile.ts b/src/pipeline/precompile.ts index d2a10d98a4..3c1d455155 100644 --- a/src/pipeline/precompile.ts +++ b/src/pipeline/precompile.ts @@ -1,7 +1,7 @@ import type { CompilerContext } from "@/context/context"; import { resolveDescriptors } from "@/types/resolveDescriptors"; import { resolveAllocations } from "@/storage/resolveAllocation"; -import { openContext } from "@/context/store"; +import { openContext, parseModules } from "@/context/store"; import { resolveStatements } from "@/types/resolveStatements"; import { resolveErrors } from "@/types/resolveErrors"; import { resolveSignatures } from "@/types/resolveSignatures"; @@ -25,8 +25,14 @@ export function precompile( // Load all sources const imported = resolveImports({ entrypoint, project, stdlib, parser }); + // Parse the sources and attach the given parsed modules + const finalModules = [ + ...parseModules(imported.tact, parser), + ...(parsedModules ?? []), + ]; + // Add information about all the source code entries to the context - ctx = openContext(ctx, imported.tact, imported.func, parser, parsedModules); + ctx = openContext(ctx, imported.tact, imported.func, finalModules); // First load type descriptors and check that // they all have valid signatures diff --git a/src/storage/resolveAllocation.spec.ts b/src/storage/resolveAllocation.spec.ts index 20b6ecd68b..76e0de5cc9 100644 --- a/src/storage/resolveAllocation.spec.ts +++ b/src/storage/resolveAllocation.spec.ts @@ -4,7 +4,7 @@ import { getAllocations, resolveAllocations, } from "@/storage/resolveAllocation"; -import { openContext } from "@/context/store"; +import { openContext, parseModules } from "@/context/store"; import { resolveStatements } from "@/types/resolveStatements"; import { CompilerContext } from "@/context/context"; import { resolveSignatures } from "@/types/resolveSignatures"; @@ -12,6 +12,7 @@ import path from "path"; import { getParser } from "@/grammar"; import { getAstFactory } from "@/ast/ast-helpers"; import { stdlibPath } from "@/stdlib/path"; +import type { Source } from "@/imports/source"; const primitivesPath = path.join(stdlibPath, "/std/internal/primitives.tact"); const stdlib = fs.readFileSync(primitivesPath, "utf-8"); @@ -68,14 +69,15 @@ contract Sample { describe("resolveAllocation", () => { it("should write program", () => { const ast = getAstFactory(); + const sources: Source[] = [ + { code: stdlib, path: primitivesPath, origin: "stdlib" }, + { code: src, path: "", origin: "user" }, + ]; let ctx = openContext( new CompilerContext(), - [ - { code: stdlib, path: primitivesPath, origin: "stdlib" }, - { code: src, path: "", origin: "user" }, - ], + sources, [], - getParser(ast), + parseModules(sources, getParser(ast)), ); ctx = resolveDescriptors(ctx, ast); ctx = resolveSignatures(ctx, ast); diff --git a/src/test/pipeline/__snapshots__/precompile-ast.spec.ts.snap b/src/test/pipeline/__snapshots__/precompile-ast.spec.ts.snap new file mode 100644 index 0000000000..045489dd1f --- /dev/null +++ b/src/test/pipeline/__snapshots__/precompile-ast.spec.ts.snap @@ -0,0 +1,8 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`pre-compilation of ASTs should fail pre-compilation when source files and a manual AST have declaration clashes 1`] = ` +"Type "Test" already exists +> 1 | + ^ +" +`; diff --git a/src/test/pipeline/dummy.tact b/src/test/pipeline/dummy.tact new file mode 100644 index 0000000000..427f3123d8 --- /dev/null +++ b/src/test/pipeline/dummy.tact @@ -0,0 +1,7 @@ +contract Test { + f: StateInit; + + init() { + self.f = initOf Test(); + } +} \ No newline at end of file diff --git a/src/test/pipeline/precompile-ast.spec.ts b/src/test/pipeline/precompile-ast.spec.ts new file mode 100644 index 0000000000..c148db032e --- /dev/null +++ b/src/test/pipeline/precompile-ast.spec.ts @@ -0,0 +1,115 @@ +import path from "path"; +import type * as A from "@/ast/ast"; +import { getAstFactory } from "@/ast/ast-helpers"; +import { CompilerContext } from "@/context/context"; +import { precompile } from "@/pipeline/precompile"; +import files from "@/stdlib/stdlib"; +import { createVirtualFileSystem } from "@/vfs/createVirtualFileSystem"; +import fs from "fs"; +import { getParser } from "@/grammar"; +import { getMakeAst } from "@/ast/generated/make-factory"; +import type { MakeAstFactory } from "@/ast/generated/make-factory"; + +// This function manually creates a module containing a contract with a reference to StateInit in its single field. +// StateInit is declared in stdlib. +// +// contract Test { +// f: StateInit; +// +// init() { +// self.f = initOf Test(); +// } +// } + +function makeModule(mF: MakeAstFactory): A.Module { + // The contract field + const field = mF.makeDummyFieldDecl( + mF.makeDummyId("f"), + mF.makeDummyTypeId("StateInit"), + undefined, + undefined, + ); + // The contract init function + const initOfExpr = mF.makeDummyInitOf(mF.makeDummyId("Test"), []); + const path = mF.makeDummyFieldAccess( + mF.makeDummyId("self"), + mF.makeDummyId("f"), + ); + const assignStmt = mF.makeDummyStatementAssign(path, initOfExpr); + const init = mF.makeDummyContractInit([], [assignStmt]); + + // The contract + const contract = mF.makeDummyContract( + mF.makeDummyId("Test"), + [], + [], + undefined, + [field, init], + ); + + return mF.makeModule([], [contract]); +} + +describe("pre-compilation of ASTs", () => { + const astF = getAstFactory(); + const mF = getMakeAst(astF); + + it("should pass pre-compilation of AST with references to stdlib", () => { + const ctx = new CompilerContext(); + + // An empty tact file is required so that pre-compile does not complain about + // non-existence of an entry point. + const fileSystem = { + ["empty.tact"]: "", + }; + + const project = createVirtualFileSystem("/", fileSystem, false); + const stdlib = createVirtualFileSystem("@stdlib", files); + const parser = getParser(astF); + + precompile(ctx, project, stdlib, "empty.tact", parser, astF, [ + makeModule(mF), + ]); + }); + + it("should pass pre-compilation with no manual AST", () => { + const ctx = new CompilerContext(); + + // The dummy.tact file contains exactly the same declarations + // carried out by the function makeModule() + const fileSystem = { + ["dummy.tact"]: fs + .readFileSync(path.join(__dirname, "dummy.tact")) + .toString("base64"), + }; + + const project = createVirtualFileSystem("/", fileSystem, false); + const stdlib = createVirtualFileSystem("@stdlib", files); + const parser = getParser(astF); + + precompile(ctx, project, stdlib, "dummy.tact", parser, astF, []); + }); + + it("should fail pre-compilation when source files and a manual AST have declaration clashes", () => { + const ctx = new CompilerContext(); + + // The dummy.tact file contains exactly the same declarations + // carried out by the function makeModule() + const fileSystem = { + ["dummy.tact"]: fs + .readFileSync(path.join(__dirname, "dummy.tact")) + .toString("base64"), + }; + + const project = createVirtualFileSystem("/", fileSystem, false); + const stdlib = createVirtualFileSystem("@stdlib", files); + const parser = getParser(astF); + + // So, a clash should occur here, since dummy.tact and makeModule() both declare the contract Test. + expect(() => + precompile(ctx, project, stdlib, "dummy.tact", parser, astF, [ + makeModule(mF), + ]), + ).toThrowErrorMatchingSnapshot(); + }); +}); diff --git a/src/types/effects.spec.ts b/src/types/effects.spec.ts index c97de02db0..e6f453867f 100644 --- a/src/types/effects.spec.ts +++ b/src/types/effects.spec.ts @@ -1,28 +1,30 @@ import { getAllTypes, resolveDescriptors } from "@/types/resolveDescriptors"; import { loadCases } from "@/utils/loadCases"; -import { openContext } from "@/context/store"; +import { openContext, parseModules } from "@/context/store"; import { resolveStatements } from "@/types/resolveStatements"; import { CompilerContext } from "@/context/context"; import { featureEnable } from "@/config/features"; import { getParser } from "@/grammar"; import { getAstFactory } from "@/ast/ast-helpers"; import { computeReceiversEffects } from "@/types/effects"; +import type { Source } from "@/imports/source"; describe("effects", () => { for (const testContract of loadCases(__dirname + "/effects/")) { it(`should correctly compute effects: ${testContract.name}`, () => { const Ast = getAstFactory(); + const sources: Source[] = [ + { + code: testContract.code, + path: "", + origin: "user", + }, + ]; let ctx = openContext( new CompilerContext(), - [ - { - code: testContract.code, - path: "", - origin: "user", - }, - ], + sources, [], - getParser(Ast), + parseModules(sources, getParser(Ast)), ); ctx = featureEnable(ctx, "external"); ctx = resolveDescriptors(ctx, Ast); diff --git a/src/types/resolveDescriptors.spec.ts b/src/types/resolveDescriptors.spec.ts index bb2da86251..edffd63943 100644 --- a/src/types/resolveDescriptors.spec.ts +++ b/src/types/resolveDescriptors.spec.ts @@ -6,7 +6,7 @@ import { } from "@/types/resolveDescriptors"; import { resolveSignatures } from "@/types/resolveSignatures"; import { loadCases } from "@/utils/loadCases"; -import { openContext } from "@/context/store"; +import { openContext, parseModules } from "@/context/store"; import { featureEnable } from "@/config/features"; import type { SrcInfo } from "@/grammar"; import { getParser } from "@/grammar"; @@ -14,6 +14,7 @@ import { getAstFactory } from "@/ast/ast-helpers"; import { isSrcInfo } from "@/grammar/src-info"; import { resolveStatements } from "@/types/resolveStatements"; import { evalComptimeExpressions } from "@/types/evalComptimeExpressions"; +import type { Source } from "@/imports/source"; expect.addSnapshotSerializer({ test: (src) => isSrcInfo(src), @@ -24,11 +25,14 @@ describe("resolveDescriptors", () => { for (const r of loadCases(__dirname + "/test/")) { it("should resolve descriptors for " + r.name, () => { const Ast = getAstFactory(); + const sources: Source[] = [ + { code: r.code, path: "", origin: "user" }, + ]; let ctx = openContext( new CompilerContext(), - [{ code: r.code, path: "", origin: "user" }], + sources, [], - getParser(Ast), + parseModules(sources, getParser(Ast)), ); ctx = featureEnable(ctx, "external"); ctx = resolveDescriptors(ctx, Ast); @@ -40,11 +44,14 @@ describe("resolveDescriptors", () => { for (const r of loadCases(__dirname + "/test-failed/")) { it("should fail descriptors for " + r.name, () => { const Ast = getAstFactory(); + const sources: Source[] = [ + { code: r.code, path: "", origin: "user" }, + ]; let ctx = openContext( new CompilerContext(), - [{ code: r.code, path: "", origin: "user" }], + sources, [], - getParser(Ast), + parseModules(sources, getParser(Ast)), ); ctx = featureEnable(ctx, "external"); expect(() => { diff --git a/src/types/resolveStatements.spec.ts b/src/types/resolveStatements.spec.ts index ba19655387..fe635a9b0d 100644 --- a/src/types/resolveStatements.spec.ts +++ b/src/types/resolveStatements.spec.ts @@ -1,23 +1,27 @@ import { getAllExpressionTypes } from "@/types/resolveExpression"; import { resolveDescriptors } from "@/types/resolveDescriptors"; import { loadCases } from "@/utils/loadCases"; -import { openContext } from "@/context/store"; +import { openContext, parseModules } from "@/context/store"; import { resolveStatements } from "@/types/resolveStatements"; import { CompilerContext } from "@/context/context"; import { featureEnable } from "@/config/features"; import { getParser } from "@/grammar"; import { getAstFactory } from "@/ast/ast-helpers"; import { evalComptimeExpressions } from "@/types/evalComptimeExpressions"; +import type { Source } from "@/imports/source"; describe("resolveStatements", () => { for (const r of loadCases(__dirname + "/stmts/")) { it("should resolve statements for " + r.name, () => { const Ast = getAstFactory(); + const sources: Source[] = [ + { code: r.code, path: "", origin: "user" }, + ]; let ctx = openContext( new CompilerContext(), - [{ code: r.code, path: "", origin: "user" }], + sources, [], - getParser(Ast), + parseModules(sources, getParser(Ast)), ); ctx = featureEnable(ctx, "external"); ctx = resolveDescriptors(ctx, Ast); @@ -29,11 +33,14 @@ describe("resolveStatements", () => { for (const r of loadCases(__dirname + "/stmts-failed/")) { it("should fail statements for " + r.name, () => { const Ast = getAstFactory(); + const sources: Source[] = [ + { code: r.code, path: "", origin: "user" }, + ]; let ctx = openContext( new CompilerContext(), - [{ code: r.code, path: "", origin: "user" }], + sources, [], - getParser(Ast), + parseModules(sources, getParser(Ast)), ); ctx = featureEnable(ctx, "external"); ctx = resolveDescriptors(ctx, Ast);