Skip to content

Commit

Permalink
feat: new asm parser
Browse files Browse the repository at this point in the history
WIP WIP WIP
  • Loading branch information
novusnota committed Nov 22, 2024
1 parent 6320faa commit f1562ff
Show file tree
Hide file tree
Showing 12 changed files with 343 additions and 3,126 deletions.
5 changes: 3 additions & 2 deletions src/generator/writers/writeFunction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import { resolveFuncTupleType } from "./resolveFuncTupleType";
import { ops } from "./ops";
import { freshIdentifier } from "./freshIdentifier";
import { idTextErr, throwInternalCompilerError } from "../../errors";
import { ppAsmShuffle } from "../../prettyPrinter";
import { ppAsmShuffle, ppAsmExpressionsBlock } from "../../prettyPrinter";

export function writeCastedExpression(
expression: AstExpression,
Expand Down Expand Up @@ -581,7 +581,8 @@ export function writeFunction(f: FunctionDescription, ctx: WriterContext) {
};
ctx.asm(
ppAsmShuffle(asmShuffleEscaped),
fAst.instructions.join(" "),
ppAsmExpressionsBlock(fAst.expressions),

Check failure on line 584 in src/generator/writers/writeFunction.ts

View workflow job for this annotation

GitHub Actions / test-blueprint (22, macos-latest, yarn)

Argument of type '<U>(ctx: Context<U>) => U' is not assignable to parameter of type 'string'.

Check failure on line 584 in src/generator/writers/writeFunction.ts

View workflow job for this annotation

GitHub Actions / test-blueprint (22, ubuntu-latest, bun)

Argument of type '<U>(ctx: Context<U>) => U' is not assignable to parameter of type 'string'.

Check failure on line 584 in src/generator/writers/writeFunction.ts

View workflow job for this annotation

GitHub Actions / test-blueprint (22, ubuntu-latest, yarn)

Argument of type '<U>(ctx: Context<U>) => U' is not assignable to parameter of type 'string'.

Check failure on line 584 in src/generator/writers/writeFunction.ts

View workflow job for this annotation

GitHub Actions / test-blueprint (22, ubuntu-latest, pnpm)

Argument of type '<U>(ctx: Context<U>) => U' is not assignable to parameter of type 'string'.

Check failure on line 584 in src/generator/writers/writeFunction.ts

View workflow job for this annotation

GitHub Actions / test-blueprint (22, ubuntu-latest, npm)

Argument of type '<U>(ctx: Context<U>) => U' is not assignable to parameter of type 'string'.

Check failure on line 584 in src/generator/writers/writeFunction.ts

View workflow job for this annotation

GitHub Actions / test (22, ubuntu-latest)

Argument of type '<U>(ctx: Context<U>) => U' is not assignable to parameter of type 'string'.

Check failure on line 584 in src/generator/writers/writeFunction.ts

View workflow job for this annotation

GitHub Actions / test (22, macos-latest)

Argument of type '<U>(ctx: Context<U>) => U' is not assignable to parameter of type 'string'.

Check failure on line 584 in src/generator/writers/writeFunction.ts

View workflow job for this annotation

GitHub Actions / test-blueprint (22, macos-latest, bun)

Argument of type '<U>(ctx: Context<U>) => U' is not assignable to parameter of type 'string'.

Check failure on line 584 in src/generator/writers/writeFunction.ts

View workflow job for this annotation

GitHub Actions / test-blueprint (22, macos-latest, npm)

Argument of type '<U>(ctx: Context<U>) => U' is not assignable to parameter of type 'string'.

Check failure on line 584 in src/generator/writers/writeFunction.ts

View workflow job for this annotation

GitHub Actions / test-blueprint (22, macos-latest, pnpm)

Argument of type '<U>(ctx: Context<U>) => U' is not assignable to parameter of type 'string'.

Check failure on line 584 in src/generator/writers/writeFunction.ts

View workflow job for this annotation

GitHub Actions / test-blueprint (22, windows-latest, bun)

Argument of type '<U>(ctx: Context<U>) => U' is not assignable to parameter of type 'string'.

Check failure on line 584 in src/generator/writers/writeFunction.ts

View workflow job for this annotation

GitHub Actions / test-blueprint (22, windows-latest, bun)

Argument of type '<U>(ctx: Context<U>) => U' is not assignable to parameter of type 'string'.

Check failure on line 584 in src/generator/writers/writeFunction.ts

View workflow job for this annotation

GitHub Actions / test-blueprint (22, windows-latest, pnpm)

Argument of type '<U>(ctx: Context<U>) => U' is not assignable to parameter of type 'string'.

Check failure on line 584 in src/generator/writers/writeFunction.ts

View workflow job for this annotation

GitHub Actions / test-blueprint (22, windows-latest, pnpm)

Argument of type '<U>(ctx: Context<U>) => U' is not assignable to parameter of type 'string'.

Check failure on line 584 in src/generator/writers/writeFunction.ts

View workflow job for this annotation

GitHub Actions / test-blueprint (22, windows-latest, npm)

Argument of type '<U>(ctx: Context<U>) => U' is not assignable to parameter of type 'string'.

Check failure on line 584 in src/generator/writers/writeFunction.ts

View workflow job for this annotation

GitHub Actions / test-blueprint (22, windows-latest, npm)

Argument of type '<U>(ctx: Context<U>) => U' is not assignable to parameter of type 'string'.

Check failure on line 584 in src/generator/writers/writeFunction.ts

View workflow job for this annotation

GitHub Actions / test-blueprint (22, windows-latest, yarn)

Argument of type '<U>(ctx: Context<U>) => U' is not assignable to parameter of type 'string'.

Check failure on line 584 in src/generator/writers/writeFunction.ts

View workflow job for this annotation

GitHub Actions / test-blueprint (22, windows-latest, yarn)

Argument of type '<U>(ctx: Context<U>) => U' is not assignable to parameter of type 'string'.

Check failure on line 584 in src/generator/writers/writeFunction.ts

View workflow job for this annotation

GitHub Actions / test (22, windows-latest)

Argument of type '<U>(ctx: Context<U>) => U' is not assignable to parameter of type 'string'.

Check failure on line 584 in src/generator/writers/writeFunction.ts

View workflow job for this annotation

GitHub Actions / test (22, windows-latest)

Argument of type '<U>(ctx: Context<U>) => U' is not assignable to parameter of type 'string'.

Check failure on line 584 in src/generator/writers/writeFunction.ts

View workflow job for this annotation

GitHub Actions / test (22, windows-latest)

Argument of type '<U>(ctx: Context<U>) => U' is not assignable to parameter of type 'string'.

Check failure on line 584 in src/generator/writers/writeFunction.ts

View workflow job for this annotation

GitHub Actions / test (22, windows-latest)

Argument of type '<U>(ctx: Context<U>) => U' is not assignable to parameter of type 'string'.
// fAst.instructions.join(" "),
);
});
if (f.isMutating) {
Expand Down
111 changes: 108 additions & 3 deletions src/grammar/ast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,17 +57,120 @@ export type AstAsmFunctionDef = {
name: AstId;
return: AstType | null;
params: AstTypedParameter[];
instructions: AstAsmInstruction[];
expressions: AstAsmExpression[];
id: number;
loc: SrcInfo;
};

export type AstAsmInstruction = string;
export type AstAsmShuffle = {
args: AstId[];
ret: AstNumber[];
};

// NOTE: should it be added to AstNode?
export type AstAsmExpression =
| AstAsmExpressionDef
| AstAsmExpressionList
| AstAsmPrimitive;

/** `{ AstAsmExpression* } : AstAsmInstruction` */
export type AstAsmExpressionDef = {
kind: "asm_expr_def";
expressions: AstAsmExpression[];
name: AstAsmInstruction;
loc: SrcInfo;
};

/** `{ AstAsmExpression* }` */
export type AstAsmExpressionList = {
kind: "asm_expr_list";
expressions: AstAsmExpression[];
loc: SrcInfo;
};

export type AstAsmPrimitive =
| AstAsmString
| AstAsmHex
| AstAsmBin
| AstAsmControlReg
| AstAsmStackReg
| AstAsmNumber
| AstAsmInstruction;

/** `"..."` */
export type AstAsmString = {
kind: "asm_string";
value: string;
loc: SrcInfo;
};

/** `x{babe...cafe_}` */
export type AstAsmHex = {
kind: "asm_hex";
/**
* Stores everything inside braces `{}` as is
*
* NOTE: May (?) be changed to bigint or even removed in favor of changed AstAsmNumber
*/
value: string;
/** Does it have an _ right before the } or not? */
isPadded: boolean;
loc: SrcInfo;
};

/** `b{0101...0101}` */
export type AstAsmBin = {
kind: "asm_bin";
/**
* Stores everything inside braces `{}` as is
*
* NOTE: May (?) be changed to bigint or even removed in favor of changed AstAsmNumber
*/
value: string;
loc: SrcInfo;
};

/** `c0`, `c1`, ..., `c15` */
export type AstAsmControlReg = {
kind: "asm_control_reg";
value: bigint;
loc: SrcInfo;
};

/**
* `s0`, `s1`, ..., `s15`
* or `i s()`,
* where i ∈ [0, 255]
*/
export type AstAsmStackReg = {
kind: "asm_stack_reg";
value: bigint;
/**
* Is it either of `s0`, `s1`, ..., `s15`?
* If not, then it's `i s()`, where i ∈ [0, 255]
*/
isLiteral: boolean;
loc: SrcInfo;
};

/** NOTE: can later be aliased to Tact number literals */
export type AstAsmNumber = {
kind: "asm_number";
value: bigint;
loc: SrcInfo;
};

export function astAsmNumberToString(n: AstAsmNumber): string {
return n.value.toString(10);
}

/** `MYCODE`, `ADDRSHIFT#MOD`, `IF:`, `XCHG3_l`, `2SWAP`, `-ROT`, etc. */
export type AstAsmInstruction = {
kind: "asm_instruction";
text: string;
loc: SrcInfo;
};

export type AstFunctionDecl = {
kind: "function_decl";
attributes: AstFunctionAttribute[];
Expand Down Expand Up @@ -507,7 +610,9 @@ export type AstFuncId = {
loc: SrcInfo;
};

export function idText(ident: AstId | AstFuncId | AstTypeId): string {
export function idText(
ident: AstId | AstFuncId | AstTypeId | AstAsmInstruction,
): string {
return ident.text;
}

Expand Down
6 changes: 3 additions & 3 deletions src/grammar/compare.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ import {
AstNode,
AstFuncId,
AstAsmFunctionDef,
AstAsmInstruction,
AstAsmExpression,
AstDestructMapping,
AstStatementDestruct,
} from "./ast";
Expand Down Expand Up @@ -850,8 +850,8 @@ export class AstComparator {
}

private compareAsmInstructions(
instructions1: AstAsmInstruction[],
instructions2: AstAsmInstruction[],
instructions1: AstAsmExpression[],
instructions2: AstAsmExpression[],
): boolean {
if (instructions1.length !== instructions2.length) {
return false;
Expand Down
41 changes: 25 additions & 16 deletions src/grammar/grammar.ohm
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ Tact {
ModuleFunction = FunctionDefinition
| AsmFunction

AsmFunction = "asm" AsmShuffle? FunctionAttribute* fun id Parameters (":" Type)? "{" AsmInstruction* "}"
AsmFunction = "asm" AsmShuffle? FunctionAttribute* fun id Parameters (":" Type)? "{" AsmExpression* "}"

ModuleConstant = ConstantDefinition

Expand Down Expand Up @@ -99,21 +99,30 @@ Tact {
| external "(" Parameter? ")" "{" Statement* "}" --externalRegular
| external "(" stringLiteral ")" "{" Statement* "}" --externalComment

AsmInstruction = "[" &#whiteSpace AsmInstruction* "]" &#whiteSpace --internal
| "{" &#whiteSpace AsmInstruction* "}" &#whiteSpace --list
| "({)" &#whiteSpace AsmInstruction* "(})" &#whiteSpace --listNoStateCheck
| ("abort\"" | ".\"" | "+\"" | "\"") (~"\"" any)* "\"" &#whiteSpace --string
| "'" &#whiteSpace asmInstruction --tick
| "char" &#whiteSpace (~whiteSpace any) &#whiteSpace --char
| ("x{" | "B{") ~#whiteSpace hexDigit* ~#whiteSpace ("_" ~#whiteSpace)? "}" &#whiteSpace --hexLiteral
| "b{" ~#whiteSpace binDigit* ~#whiteSpace "}" &#whiteSpace --binLiteral
| asmInstruction --custom

// Instructions exclude some begin and end words to ensure correct parse
asmInstruction = ~(("[" | "]" | "{" | "}" | "({)" | "(})") ~asmWord) asmWord

// A chunk of non-whitespace characters forms a word in Fift
asmWord = (~whiteSpace any)+
// FIXME: prettyPrinter.ts → writeFunction.ts, hash.ts, compare.ts
AsmExpression = "{" AsmExpression* "}" ":" asmInstruction --definition
| "{" AsmExpression* "}" --list
| asmPrimitive

// Various instructions not forming a block
asmPrimitive = "\"" (~"\"" any)* "\"" --string
| "x{" hexDigit* "_"? "}" --hex
| "b{" binDigit* "}" --bin
| "c" digit digit? --controlRegister
| "s" digit digit? --stackRegister
| digit digit? digit? whiteSpace+ "s()" --stackRegister255
| "-"? digit+ --number
| asmInstruction --custom

// To ensure correct parse,
// 1. instructions cannot contain braces
// 2. and cannot be braces themselves
asmInstruction = ~(("{" | "}") ~asmWord) asmWord

// Additionally, the minimal word length is 2 characters,
// not including the optional minus at the start
asmWord = "-"? asmWordPart asmWordPart+
asmWordPart = (letterAscii | digit | "_" | "#" | ":")

Statement = StatementLet
| StatementBlock
Expand Down
16 changes: 1 addition & 15 deletions src/grammar/grammar.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { parse } from "./grammar";
import { AstModule, SrcInfo, __DANGER_resetNodeId } from "./ast";
import { SrcInfo, __DANGER_resetNodeId } from "./ast";
import { loadCases } from "../utils/loadCases";

expect.addSnapshotSerializer({
Expand All @@ -12,20 +12,6 @@ describe("grammar", () => {
__DANGER_resetNodeId();
});

// Test parsing of known Fift projects, wrapped in asm functions of Tact
for (const r of loadCases(__dirname + "/test-asm/")) {
it("should parse " + r.name, () => {
const parsed: AstModule | undefined = parse(
r.code,
"<unknown>",
"user",
);

// Don't produce snapshots
expect(parsed).toBeDefined();
});
}

for (const r of loadCases(__dirname + "/test/")) {
it("should parse " + r.name, () => {
expect(parse(r.code, "<unknown>", "user")).toMatchSnapshot();
Expand Down
Loading

0 comments on commit f1562ff

Please sign in to comment.