Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion contrib/generated/errorCodes.json

Large diffs are not rendered by default.

21 changes: 21 additions & 0 deletions src/ast.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
export type CompilerAST = CompilerAST[] | CompilerNode | string | null;
export type CompilerSpan = { name: 'Pos'; args: [string, string, string] };

/** Opaque expression object from the Motoko compiler - do not construct manually */
export type RawExp = unknown & { readonly __brand: 'RawExp' };

const rawExpSymbol = Symbol('rawExp');

export interface CompilerNode {
name: string;
args: CompilerAST[];
rawExp?: RawExp;
}

export type Span = [number, number];
Expand All @@ -25,6 +31,19 @@ export interface Node extends Partial<Source> {
args?: AST[];
}

/**
* Safely retrieves the raw expression from a node.
*
* The raw expression is stored internally using a Symbol to prevent accidental access,
* which can break property descriptors on child nodes (e.g., when logging).
*
* @param node The node to get the raw expression from
* @returns The raw expression, or undefined if not available
*/
export function getRawExp(node: Node): RawExp | undefined {
return (node as any)[rawExpSymbol];
}

export function asNode(ast: AST | undefined): Node | undefined {
if (ast && typeof ast === 'object' && !Array.isArray(ast)) {
return ast;
Expand Down Expand Up @@ -103,6 +122,8 @@ export function simplifyAST(ast: CompilerAST, parent?: Node | undefined): AST {
const node: Node = {
name: ast.name,
};
// Store rawExp using a Symbol to prevent accidental access, e.g. in logs which destroys the type annotations in the AST...
(node as any)[rawExpSymbol] = ast.rawExp;
Object.defineProperty(node, 'parent', {
value: parent,
enumerable: false,
Expand Down
36 changes: 27 additions & 9 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { CompilerNode, Node, simplifyAST } from './ast';
import { CompilerNode, Node, RawExp, simplifyAST } from './ast';
import { Scope, file } from './file';
import {
Package,
Expand All @@ -14,6 +14,9 @@ export type Motoko = ReturnType<typeof wrapMotoko>;

type Compiler = any; // TODO: generate from `js_of_ocaml`?

/** Opaque scope object from the Motoko compiler - do not construct manually */
export type RawScope = unknown & { readonly __brand: 'RawScope' };

export type Diagnostic = {
source: string;
range: {
Expand Down Expand Up @@ -63,8 +66,8 @@ export default function wrapMotoko(compiler: Compiler) {
throw new Error(
result.diagnostics
? result.diagnostics
.map(({ message }: Diagnostic) => message)
.join('; ')
.map(({ message }: Diagnostic) => message)
.join('; ')
: '(no diagnostics)',
);
}
Expand Down Expand Up @@ -98,6 +101,7 @@ export default function wrapMotoko(compiler: Compiler) {
ast: Node;
type: Node;
immediateImports: string[];
scope: RawScope;
};
function parseMotokoTypedWithScopeCache(
paths: string,
Expand All @@ -114,12 +118,12 @@ export default function wrapMotoko(compiler: Compiler) {
scopeCache: Map<string, Scope>,
enableRecovery?: boolean,
): [
(
| ParseMotokoTypedWithScopeCacheResult
| ParseMotokoTypedWithScopeCacheResult[]
),
Map<string, Scope>,
] {
(
| ParseMotokoTypedWithScopeCacheResult
| ParseMotokoTypedWithScopeCacheResult[]
),
Map<string, Scope>,
] {
if (enableRecovery === undefined) {
enableRecovery = false;
}
Expand All @@ -142,15 +146,18 @@ export default function wrapMotoko(compiler: Compiler) {
ast,
typ,
immediateImports,
scope,
}: {
ast: CompilerNode;
typ: CompilerNode;
immediateImports: string[];
scope: RawScope;
}) => {
return {
ast: simplifyAST(ast),
type: simplifyAST(typ),
immediateImports,
scope,
};
},
),
Expand Down Expand Up @@ -278,6 +285,17 @@ export default function wrapMotoko(compiler: Compiler) {
},
parseMotokoTyped,
parseMotokoTypedWithScopeCache,
resolveDotCandidates(
scope: RawScope,
rawExp: RawExp,
): {
name: string;
type: string;
moduleName?: string;
}[] {
// TODO: consider not exposing the RawScope nor RawExp outside of this library...
return invoke('resolveDotCandidates', false, [scope, rawExp]);
},
resolveMain(directory: string = ''): string | undefined {
return resolveMain(mo, directory);
},
Expand Down
239,951 changes: 239,950 additions & 1 deletion versions/latest/moc.min.js

Large diffs are not rendered by default.

115,693 changes: 115,692 additions & 1 deletion versions/latest/moc_interpreter.min.js

Large diffs are not rendered by default.