import type { Opcode } from '../step';
import type { Type } from '../abi';
import type { Add, Div, Exp, Mod, Mul, Sub } from './alu';
import type { And, Byte, Eq, Gt, IsZero, Lt, Not, Or, Sar, Shl, Shr, Xor } from './alu';
import type { DataCopy, Prop, CallDataLoad, CallValue, Fn } from './special';
import type { MLoad, MStore } from './memory';
import type { Call, CallCode, Create, Create2, DelegateCall, Invalid, Return, ReturnData, Revert, SelfDestruct, Sha3, StaticCall, Stop } from './system';
import type { Log } from './log';
import type { Branch, Jump, JumpDest, Jumpi, Sig, SigCase } from './flow';
import type { MappingLoad, MappingStore, SLoad, SStore } from './storage';
/**
 *
 */
export type Expr = Val | Add | Mul | Sub | Div | Mod | Exp | Lt | Gt | Eq | IsZero | And | Or | Xor | Not | Byte | Shl | Shr | Sar | Sig | CallValue | CallDataLoad | Prop | Fn | DataCopy | MLoad | Sha3 | Create | Call | ReturnData | CallCode | Create2 | StaticCall | DelegateCall | SLoad | MappingLoad | Local;
export declare const isExpr: (expr: unknown) => expr is Expr;
export declare const isInst: (inst: unknown) => inst is Inst;
export declare const evalE: (expr: Expr) => Expr;
/**
 * Base definition for any type that is `Stmt`.
 */
export interface IInst {
    /**
     * The `name` tag of this `IStmt`.
     */
    readonly name: string;
    eval(): Inst;
    next?(): Branch[];
}
/**
 *
 */
export type Inst = MStore | Stop | Return | Revert | SelfDestruct | Invalid | Log | Jump | Jumpi | JumpDest | SigCase | SStore | MappingStore | Throw | Locali;
export declare class Throw implements IInst {
    readonly reason: string;
    readonly opcode: Opcode<string>;
    readonly name = "Throw";
    constructor(reason: string, opcode: Opcode<string>);
    eval(): this;
}
/**
 *
 */
export type Stmt = Inst | If | CallSite | Require;
export declare class If {
    readonly condition: Expr;
    readonly trueBlock?: Stmt[] | undefined;
    readonly falseBlock?: Stmt[] | undefined;
    readonly name = "If";
    constructor(condition: Expr, trueBlock?: Stmt[] | undefined, falseBlock?: Stmt[] | undefined);
    eval(): If;
}
export declare class CallSite {
    readonly selector: string;
    readonly name = "CallSite";
    constructor(selector: string);
    eval(): this;
}
export declare class Require {
    readonly condition: Expr;
    readonly selector: string | undefined;
    readonly args: Expr[];
    readonly name = "Require";
    constructor(condition: Expr, selector: string | undefined, args: Expr[]);
    eval(): Require;
}
export declare abstract class Tag {
    readonly depth: number;
    readonly count: number;
    abstract readonly tag: string;
    type?: Type;
    constructor(depth: number, count: number);
    isVal(): this is Val;
    isZero(): this is Val;
    isJumpDest(): this is Val;
    /**
     * Reduce `this` expression.
     */
    abstract eval(): Expr;
    children(): Expr[];
    unwrap(): Expr;
}
export declare const MOD_256: bigint;
export declare class Val extends Tag {
    readonly val: bigint;
    readonly pushStateId?: number | undefined;
    readonly tag = "Val";
    jumpDest: number | null;
    constructor(val: bigint, pushStateId?: number | undefined);
    eval(): Expr;
}
export declare class Local extends Tag {
    #private;
    readonly index: number;
    readonly value: Expr;
    readonly tag = "Local";
    nrefs: number;
    constructor(index: number, value: Expr);
    eval(): Expr;
    unwrap(): Expr;
}
export declare class Locali implements IInst {
    readonly local: Local;
    readonly name = "Local";
    constructor(local: Local);
    eval(): this;
}
export declare function reduce(stmts: Stmt[]): Stmt[];
export declare function inline0(stmts: Stmt[]): Stmt[];
export declare function mem(stmts: Stmt[]): Stmt[];
export * from './alu';
export * from './flow';
export * from './log';
export * from './memory';
export * from './special';
export * from './storage';
export * from './system';
