Skip to content

Commit

Permalink
moved function to ast module
Browse files Browse the repository at this point in the history
  • Loading branch information
ascandone committed Jan 19, 2024
1 parent 2120488 commit a1ea483
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 82 deletions.
71 changes: 71 additions & 0 deletions src/ast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,74 @@ export type Statement<Meta = {}> = Meta & {
export type Program<Meta = {}> = {
statements: Statement<Meta>[];
};

export type Span = [startIdx: number, endIdx: number];
export type SpanMeta = { span: Span };

function spanContains([start, end]: Span, offset: number) {
return start <= offset && end >= offset;
}

function exprByOffset<T extends SpanMeta>(
ast: Expr<T>,
offset: number,
): T | undefined {
if (!spanContains(ast.span, offset)) {
return;
}

switch (ast.type) {
case "constant":
case "identifier":
return ast;
case "application":
for (const arg of ast.args) {
const t = exprByOffset(arg, offset);
if (t !== undefined) {
return t;
}
}
return exprByOffset(ast.caller, offset) ?? ast;

case "let":
if (spanContains(ast.binding.span, offset)) {
return ast.binding;
}
return (
exprByOffset(ast.value, offset) ?? exprByOffset(ast.body, offset) ?? ast
);

case "fn":
for (const param of ast.params) {
if (spanContains(param.span, offset)) {
return param;
}
}
return exprByOffset(ast.body, offset) ?? ast;

case "if":
return (
exprByOffset(ast.condition, offset) ??
exprByOffset(ast.then, offset) ??
exprByOffset(ast.else, offset) ??
ast
);
}
}

export function declByOffset<T extends SpanMeta>(
program: Program<T>,
offset: number,
): T | undefined {
for (const st of program.statements) {
if (spanContains(st.binding.span, offset)) {
return st.binding;
}
const e = exprByOffset(st.value, offset);
if (e !== undefined) {
return e;
}
}

return undefined;
}
77 changes: 2 additions & 75 deletions src/cli/commands/lsp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,83 +7,15 @@ import {
createConnection,
} from "vscode-languageserver";
import { TextDocument } from "vscode-languageserver-textdocument";
import { Span, SpanMeta, parse } from "../../parser";
import { parse } from "../../parser";
import { typeErrorPPrint, typePPrint } from "../../typecheck/pretty-printer";
import { TypeMeta, typecheck } from "../../typecheck/typecheck";
import { prelude } from "../../typecheck/prelude";
import { Expr, Program } from "../../ast";
import { Program, SpanMeta, declByOffset } from "../../ast";

const documents = new TextDocuments(TextDocument);
const docs = new Map<string, [TextDocument, Program<SpanMeta & TypeMeta>]>();

function spanContains([start, end]: Span, offset: number) {
return start <= offset && end >= offset;
}

function exprByOffset<T extends SpanMeta>(
ast: Expr<T>,
offset: number,
): T | undefined {
if (!spanContains(ast.span, offset)) {
return;
}

switch (ast.type) {
case "constant":
case "identifier":
return ast;
case "application":
for (const arg of ast.args) {
const t = exprByOffset(arg, offset);
if (t !== undefined) {
return t;
}
}
return exprByOffset(ast.caller, offset) ?? ast;

case "let":
if (spanContains(ast.binding.span, offset)) {
return ast.binding;
}
return (
exprByOffset(ast.value, offset) ?? exprByOffset(ast.body, offset) ?? ast
);

case "fn":
for (const param of ast.params) {
if (spanContains(param.span, offset)) {
return param;
}
}
return exprByOffset(ast.body, offset) ?? ast;

case "if":
return (
exprByOffset(ast.condition, offset) ??
exprByOffset(ast.then, offset) ??
exprByOffset(ast.else, offset) ??
ast
);
}
}

function declByOffset<T extends SpanMeta>(
program: Program<T>,
offset: number,
): T | undefined {
for (const st of program.statements) {
if (spanContains(st.binding.span, offset)) {
return st.binding;
}
const e = exprByOffset(st.value, offset);
if (e !== undefined) {
return e;
}
}

return undefined;
}

export function lspCmd() {
const connection =
// @ts-ignore
Expand All @@ -94,11 +26,6 @@ export function lspCmd() {
textDocumentSync: TextDocumentSyncKind.Incremental,
hoverProvider: true,
documentSymbolProvider: true,
// inlayHintProvider: true,
// codeLensProvider: {
// resolveProvider: true,
// },
// documentSymbolProvider: true,
},
}));

Expand Down
3 changes: 2 additions & 1 deletion src/cli/commands/typecheck.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { readFileSync } from "fs";
import { Span, unsafeParse } from "../../parser";
import { unsafeParse } from "../../parser";
import { typecheck } from "../../typecheck/typecheck";
import { typeErrorPPrint } from "../../typecheck/pretty-printer";
import { prelude } from "../../typecheck/prelude";
import { Span } from "../../ast";

const FgRed = "\x1b[31m";
const Reset = "\x1b[0m";
Expand Down
5 changes: 1 addition & 4 deletions src/parser.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
import grammar from "./parser/grammar.ohm-bundle";
import { ConstLiteral, Program, Expr, Statement } from "./ast";
import { ConstLiteral, Program, Expr, Statement, Span, SpanMeta } from "./ast";
import type {
MatchResult,
NonterminalNode,
Node as OhmNode,
TerminalNode,
} from "ohm-js";

export type Span = [startIdx: number, endIdx: number];
export type SpanMeta = { span: Span };

function getSpan({ source }: OhmNode): Span {
return [source.startIdx, source.endIdx];
}
Expand Down
3 changes: 1 addition & 2 deletions src/typecheck/typecheck.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { ConstLiteral, Expr, Program, Statement } from "../ast";
import { Span, SpanMeta } from "../parser";
import { ConstLiteral, Expr, Program, Statement, Span, SpanMeta } from "../ast";
import { TVar, Type, unify, Context, generalize, instantiate } from "./unify";

export type UnifyErrorType = "type-mismatch" | "occurs-check";
Expand Down

0 comments on commit a1ea483

Please sign in to comment.