Compare commits
No commits in common. "493a11a93bc15f1a06b89261d118c3a7955282c7" and "c92fce8ccb7fbb510852a3f0e811954ad631f931" have entirely different histories.
493a11a93b
...
c92fce8ccb
@ -1,4 +1,3 @@
|
|||||||
import { IdentId } from "../ctx.ts";
|
|
||||||
import { Span } from "../diagnostics.ts";
|
import { Span } from "../diagnostics.ts";
|
||||||
|
|
||||||
export type File = {
|
export type File = {
|
||||||
@ -24,7 +23,7 @@ export type ItemStmt = { item: Item };
|
|||||||
|
|
||||||
export type LetStmt = {
|
export type LetStmt = {
|
||||||
pat: Pat;
|
pat: Pat;
|
||||||
ty?: Ty;
|
ty: Ty;
|
||||||
expr?: Expr;
|
expr?: Expr;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -58,7 +57,7 @@ export type ItemKind =
|
|||||||
| { tag: "use" } & UseItem
|
| { tag: "use" } & UseItem
|
||||||
| { tag: "type_alias" } & TypeAliasItem;
|
| { tag: "type_alias" } & TypeAliasItem;
|
||||||
|
|
||||||
export type ModBlockItem = { block: Block };
|
export type ModBlockItem = { stmts: Stmt[] };
|
||||||
export type ModFileItem = { filePath: string };
|
export type ModFileItem = { filePath: string };
|
||||||
export type EnumItem = { variants: Variant[] };
|
export type EnumItem = { variants: Variant[] };
|
||||||
export type StructItem = { data: VariantData };
|
export type StructItem = { data: VariantData };
|
||||||
@ -123,11 +122,11 @@ export type Expr = {
|
|||||||
|
|
||||||
export type ExprKind =
|
export type ExprKind =
|
||||||
| { tag: "error" }
|
| { tag: "error" }
|
||||||
| { tag: "path" } & PathExpr
|
| { tag: "path" } & Path
|
||||||
| { tag: "null" }
|
| { tag: "null" }
|
||||||
| { tag: "int" } & IntExpr
|
| { tag: "int" } & IntExpr
|
||||||
| { tag: "bool" } & BoolExpr
|
| { tag: "bool" } & BoolExpr
|
||||||
| { tag: "str" } & StringExpr
|
| { tag: "string" } & StringExpr
|
||||||
| { tag: "group" } & GroupExpr
|
| { tag: "group" } & GroupExpr
|
||||||
| { tag: "array" } & ArrayExpr
|
| { tag: "array" } & ArrayExpr
|
||||||
| { tag: "repeat" } & RepeatExpr
|
| { tag: "repeat" } & RepeatExpr
|
||||||
@ -140,14 +139,13 @@ export type ExprKind =
|
|||||||
| { tag: "call" } & CallExpr
|
| { tag: "call" } & CallExpr
|
||||||
| { tag: "unary" } & UnaryExpr
|
| { tag: "unary" } & UnaryExpr
|
||||||
| { tag: "binary" } & BinaryExpr
|
| { tag: "binary" } & BinaryExpr
|
||||||
| { tag: "block" } & BlockExpr
|
| { tag: "block" } & Block
|
||||||
| { tag: "if" } & IfExpr
|
| { tag: "if" } & IfExpr
|
||||||
| { tag: "loop" } & LoopExpr
|
| { tag: "loop" } & LoopExpr
|
||||||
| { tag: "while" } & WhileExpr
|
| { tag: "while" } & WhileExpr
|
||||||
| { tag: "for" } & ForExpr
|
| { tag: "for" } & ForExpr
|
||||||
| { tag: "c_for" } & CForExpr;
|
| { tag: "c_for" } & CForExpr;
|
||||||
|
|
||||||
export type PathExpr = { path: Path };
|
|
||||||
export type IntExpr = { value: number };
|
export type IntExpr = { value: number };
|
||||||
export type BoolExpr = { value: boolean };
|
export type BoolExpr = { value: boolean };
|
||||||
export type StringExpr = { value: string };
|
export type StringExpr = { value: string };
|
||||||
@ -163,7 +161,6 @@ export type IndexExpr = { expr: Expr; index: Expr };
|
|||||||
export type CallExpr = { expr: Expr; args: Expr[] };
|
export type CallExpr = { expr: Expr; args: Expr[] };
|
||||||
export type UnaryExpr = { unaryType: UnaryType; expr: Expr };
|
export type UnaryExpr = { unaryType: UnaryType; expr: Expr };
|
||||||
export type BinaryExpr = { binaryType: BinaryType; left: Expr; right: Expr };
|
export type BinaryExpr = { binaryType: BinaryType; left: Expr; right: Expr };
|
||||||
export type BlockExpr = { block: Block };
|
|
||||||
export type IfExpr = { cond: Expr; truthy: Block; falsy?: Expr };
|
export type IfExpr = { cond: Expr; truthy: Block; falsy?: Expr };
|
||||||
export type LoopExpr = { body: Block };
|
export type LoopExpr = { body: Block };
|
||||||
export type WhileExpr = { cond: Expr; body: Block };
|
export type WhileExpr = { cond: Expr; body: Block };
|
||||||
@ -219,18 +216,13 @@ export type Ty = {
|
|||||||
|
|
||||||
export type TyKind =
|
export type TyKind =
|
||||||
| { tag: "error" }
|
| { tag: "error" }
|
||||||
| { tag: "null" }
|
| { tag: "path" } & Path
|
||||||
| { tag: "int" }
|
|
||||||
| { tag: "bool" }
|
|
||||||
| { tag: "str" }
|
|
||||||
| { tag: "path" } & PathTy
|
|
||||||
| { tag: "ref" } & RefTy
|
| { tag: "ref" } & RefTy
|
||||||
| { tag: "ptr" } & PtrTy
|
| { tag: "ptr" } & PtrTy
|
||||||
| { tag: "slice" } & SliceTy
|
| { tag: "slice" } & SliceTy
|
||||||
| { tag: "array" } & ArrayTy
|
| { tag: "array" } & ArrayTy
|
||||||
| { tag: "anon_struct" } & AnonStructTy;
|
| { tag: "anon_struct" } & AnonStructTy;
|
||||||
|
|
||||||
export type PathTy = { path: Path };
|
|
||||||
export type RefTy = { ty: Ty; mut: boolean };
|
export type RefTy = { ty: Ty; mut: boolean };
|
||||||
export type PtrTy = { ty: Ty; mut: boolean };
|
export type PtrTy = { ty: Ty; mut: boolean };
|
||||||
export type SliceTy = { ty: Ty };
|
export type SliceTy = { ty: Ty };
|
||||||
@ -256,6 +248,6 @@ export type PathSegment = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export type Ident = {
|
export type Ident = {
|
||||||
id: IdentId;
|
text: string;
|
||||||
span: Span;
|
span: Span;
|
||||||
};
|
};
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { exhausted } from "../util.ts";
|
import { exhausted } from "../util.ts";
|
||||||
import { Block, BlockExpr, PathExpr, PathTy } from "./ast.ts";
|
import { Block } from "./ast.ts";
|
||||||
import {
|
import {
|
||||||
AnonStructTy,
|
AnonStructTy,
|
||||||
ArrayExpr,
|
ArrayExpr,
|
||||||
@ -83,7 +83,7 @@ export interface Visitor<
|
|||||||
|
|
||||||
visitExpr?(expr: Expr, ...p: P): R;
|
visitExpr?(expr: Expr, ...p: P): R;
|
||||||
visitErrorExpr?(expr: Expr, ...p: P): R;
|
visitErrorExpr?(expr: Expr, ...p: P): R;
|
||||||
visitPathExpr?(expr: Expr, kind: PathExpr, ...p: P): R;
|
visitPathExpr?(expr: Expr, kind: Path, ...p: P): R;
|
||||||
visitNullExpr?(expr: Expr, ...p: P): R;
|
visitNullExpr?(expr: Expr, ...p: P): R;
|
||||||
visitIntExpr?(expr: Expr, kind: IntExpr, ...p: P): R;
|
visitIntExpr?(expr: Expr, kind: IntExpr, ...p: P): R;
|
||||||
visitBoolExpr?(expr: Expr, kind: BoolExpr, ...p: P): R;
|
visitBoolExpr?(expr: Expr, kind: BoolExpr, ...p: P): R;
|
||||||
@ -100,7 +100,7 @@ export interface Visitor<
|
|||||||
visitCallExpr?(expr: Expr, kind: CallExpr, ...p: P): R;
|
visitCallExpr?(expr: Expr, kind: CallExpr, ...p: P): R;
|
||||||
visitUnaryExpr?(expr: Expr, kind: UnaryExpr, ...p: P): R;
|
visitUnaryExpr?(expr: Expr, kind: UnaryExpr, ...p: P): R;
|
||||||
visitBinaryExpr?(expr: Expr, kind: BinaryExpr, ...p: P): R;
|
visitBinaryExpr?(expr: Expr, kind: BinaryExpr, ...p: P): R;
|
||||||
visitBlockExpr?(expr: Expr, kind: BlockExpr, ...p: P): R;
|
visitBlockExpr?(expr: Expr, kind: Block, ...p: P): R;
|
||||||
visitIfExpr?(expr: Expr, kind: IfExpr, ...p: P): R;
|
visitIfExpr?(expr: Expr, kind: IfExpr, ...p: P): R;
|
||||||
visitLoopExpr?(expr: Expr, kind: LoopExpr, ...p: P): R;
|
visitLoopExpr?(expr: Expr, kind: LoopExpr, ...p: P): R;
|
||||||
visitWhileExpr?(expr: Expr, kind: WhileExpr, ...p: P): R;
|
visitWhileExpr?(expr: Expr, kind: WhileExpr, ...p: P): R;
|
||||||
@ -113,11 +113,7 @@ export interface Visitor<
|
|||||||
|
|
||||||
visitTy?(ty: Ty, ...p: P): R;
|
visitTy?(ty: Ty, ...p: P): R;
|
||||||
visitErrorTy?(ty: Ty, ...p: P): R;
|
visitErrorTy?(ty: Ty, ...p: P): R;
|
||||||
visitNullTy?(ty: Ty, ...p: P): R;
|
visitPathTy?(ty: Ty, kind: Path, ...p: P): R;
|
||||||
visitIntTy?(ty: Ty, ...p: P): R;
|
|
||||||
visitBoolTy?(ty: Ty, ...p: P): R;
|
|
||||||
visitStrTy?(ty: Ty, ...p: P): R;
|
|
||||||
visitPathTy?(ty: Ty, kind: PathTy, ...p: P): R;
|
|
||||||
visitRefTy?(ty: Ty, kind: RefTy, ...p: P): R;
|
visitRefTy?(ty: Ty, kind: RefTy, ...p: P): R;
|
||||||
visitPtrTy?(ty: Ty, kind: PtrTy, ...p: P): R;
|
visitPtrTy?(ty: Ty, kind: PtrTy, ...p: P): R;
|
||||||
visitSliceTy?(ty: Ty, kind: SliceTy, ...p: P): R;
|
visitSliceTy?(ty: Ty, kind: SliceTy, ...p: P): R;
|
||||||
@ -167,41 +163,24 @@ export function visitStmt<
|
|||||||
return;
|
return;
|
||||||
case "item":
|
case "item":
|
||||||
if (v.visitItemStmt?.(stmt, kind, ...p) === "stop") return;
|
if (v.visitItemStmt?.(stmt, kind, ...p) === "stop") return;
|
||||||
visitItem(v, kind.item, ...p);
|
|
||||||
return;
|
return;
|
||||||
case "let":
|
case "let":
|
||||||
if (v.visitLetStmt?.(stmt, kind, ...p) === "stop") return;
|
if (v.visitLetStmt?.(stmt, kind, ...p) === "stop") return;
|
||||||
visitPat(v, kind.pat, ...p);
|
|
||||||
if (kind.ty) {
|
|
||||||
visitTy(v, kind.ty, ...p);
|
|
||||||
}
|
|
||||||
if (kind.expr) {
|
|
||||||
visitExpr(v, kind.expr, ...p);
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
case "return":
|
case "return":
|
||||||
if (v.visitReturnStmt?.(stmt, kind, ...p) === "stop") return;
|
if (v.visitReturnStmt?.(stmt, kind, ...p) === "stop") return;
|
||||||
if (kind.expr) {
|
|
||||||
visitExpr(v, kind.expr, ...p);
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
case "break":
|
case "break":
|
||||||
if (v.visitBreakStmt?.(stmt, kind, ...p) === "stop") return;
|
if (v.visitBreakStmt?.(stmt, kind, ...p) === "stop") return;
|
||||||
if (kind.expr) {
|
|
||||||
visitExpr(v, kind.expr, ...p);
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
case "continue":
|
case "continue":
|
||||||
if (v.visitContinueStmt?.(stmt, ...p) === "stop") return;
|
if (v.visitContinueStmt?.(stmt, ...p) === "stop") return;
|
||||||
return;
|
return;
|
||||||
case "assign":
|
case "assign":
|
||||||
if (v.visitAssignStmt?.(stmt, kind, ...p) === "stop") return;
|
if (v.visitAssignStmt?.(stmt, kind, ...p) === "stop") return;
|
||||||
visitExpr(v, kind.subject, ...p);
|
|
||||||
visitExpr(v, kind.value, ...p);
|
|
||||||
return;
|
return;
|
||||||
case "expr":
|
case "expr":
|
||||||
if (v.visitExprStmt?.(stmt, kind, ...p) === "stop") return;
|
if (v.visitExprStmt?.(stmt, kind, ...p) === "stop") return;
|
||||||
visitExpr(v, kind.expr, ...p);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
exhausted(kind);
|
exhausted(kind);
|
||||||
@ -214,7 +193,6 @@ export function visitItem<
|
|||||||
item: Item,
|
item: Item,
|
||||||
...p: P
|
...p: P
|
||||||
) {
|
) {
|
||||||
visitIdent(v, item.ident, ...p);
|
|
||||||
const kind = item.kind;
|
const kind = item.kind;
|
||||||
switch (kind.tag) {
|
switch (kind.tag) {
|
||||||
case "error":
|
case "error":
|
||||||
@ -259,7 +237,7 @@ export function visitExpr<
|
|||||||
return;
|
return;
|
||||||
case "path":
|
case "path":
|
||||||
if (v.visitPathExpr?.(expr, kind, ...p) === "stop") return;
|
if (v.visitPathExpr?.(expr, kind, ...p) === "stop") return;
|
||||||
visitPath(v, kind.path, ...p);
|
visitPath(v, kind, ...p);
|
||||||
return;
|
return;
|
||||||
case "null":
|
case "null":
|
||||||
if (v.visitNullExpr?.(expr, ...p) === "stop") return;
|
if (v.visitNullExpr?.(expr, ...p) === "stop") return;
|
||||||
@ -267,7 +245,7 @@ export function visitExpr<
|
|||||||
case "int":
|
case "int":
|
||||||
if (v.visitIntExpr?.(expr, kind, ...p) === "stop") return;
|
if (v.visitIntExpr?.(expr, kind, ...p) === "stop") return;
|
||||||
return;
|
return;
|
||||||
case "str":
|
case "string":
|
||||||
if (v.visitStringExpr?.(expr, kind, ...p) === "stop") return;
|
if (v.visitStringExpr?.(expr, kind, ...p) === "stop") return;
|
||||||
return;
|
return;
|
||||||
case "bool":
|
case "bool":
|
||||||
@ -293,7 +271,7 @@ export function visitExpr<
|
|||||||
if (kind.path) {
|
if (kind.path) {
|
||||||
visitPath(v, kind.path, ...p);
|
visitPath(v, kind.path, ...p);
|
||||||
}
|
}
|
||||||
for (const field of kind.fields) {
|
for (const field of kind.field) {
|
||||||
visitIdent(v, field.ident, ...p);
|
visitIdent(v, field.ident, ...p);
|
||||||
visitExpr(v, field.expr, ...p);
|
visitExpr(v, field.expr, ...p);
|
||||||
}
|
}
|
||||||
@ -338,14 +316,14 @@ export function visitExpr<
|
|||||||
return;
|
return;
|
||||||
case "block":
|
case "block":
|
||||||
if (v.visitBlockExpr?.(expr, kind, ...p) === "stop") return;
|
if (v.visitBlockExpr?.(expr, kind, ...p) === "stop") return;
|
||||||
visitBlock(v, kind.block, ...p);
|
visitBlock(v, kind, ...p);
|
||||||
return;
|
return;
|
||||||
case "if":
|
case "if":
|
||||||
if (v.visitIfExpr?.(expr, kind, ...p) === "stop") return;
|
if (v.visitIfExpr?.(expr, kind, ...p) === "stop") return;
|
||||||
visitExpr(v, kind.cond, ...p);
|
visitExpr(v, kind.cond, ...p);
|
||||||
visitBlock(v, kind.truthy, ...p);
|
visitBlock(v, kind.truthy, ...p);
|
||||||
if (kind.falsy) {
|
if (kind.falsy) {
|
||||||
visitExpr(v, kind.falsy, ...p);
|
visitBlock(v, kind.falsy, ...p);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
case "loop":
|
case "loop":
|
||||||
@ -410,21 +388,9 @@ export function visitTy<
|
|||||||
case "error":
|
case "error":
|
||||||
if (v.visitErrorTy?.(ty, ...p) === "stop") return;
|
if (v.visitErrorTy?.(ty, ...p) === "stop") return;
|
||||||
return;
|
return;
|
||||||
case "null":
|
|
||||||
if (v.visitNullTy?.(ty, ...p) === "stop") return;
|
|
||||||
return;
|
|
||||||
case "int":
|
|
||||||
if (v.visitIntTy?.(ty, ...p) === "stop") return;
|
|
||||||
return;
|
|
||||||
case "bool":
|
|
||||||
if (v.visitBoolTy?.(ty, ...p) === "stop") return;
|
|
||||||
return;
|
|
||||||
case "str":
|
|
||||||
if (v.visitStrTy?.(ty, ...p) === "stop") return;
|
|
||||||
return;
|
|
||||||
case "path":
|
case "path":
|
||||||
if (v.visitPathTy?.(ty, kind, ...p) === "stop") return;
|
if (v.visitPathTy?.(ty, kind, ...p) === "stop") return;
|
||||||
v.visitPath?.(kind.path, ...p);
|
v.visitPath?.(kind, ...p);
|
||||||
return;
|
return;
|
||||||
case "ref":
|
case "ref":
|
||||||
if (v.visitRefTy?.(ty, kind, ...p) === "stop") return;
|
if (v.visitRefTy?.(ty, kind, ...p) === "stop") return;
|
||||||
|
100
compiler/ctx.ts
100
compiler/ctx.ts
@ -1,21 +1,14 @@
|
|||||||
import * as ast from "./ast/mod.ts";
|
import * as ast from "./ast/mod.ts";
|
||||||
import {
|
import { Pos, prettyPrintReport, printStackTrace, Report, Span } from "./diagnostics.ts";
|
||||||
Pos,
|
|
||||||
prettyPrintReport,
|
|
||||||
printStackTrace,
|
|
||||||
Report,
|
|
||||||
Span,
|
|
||||||
} from "./diagnostics.ts";
|
|
||||||
import * as hir from "./middle/hir.ts";
|
|
||||||
|
|
||||||
export class Ctx {
|
export class Ctx {
|
||||||
private fileIds = new Ids<File>();
|
private fileIds = new Ids();
|
||||||
private files = new Map<Key<File>, FileInfo>();
|
private files = new Map<Id<File>, FileInfo>();
|
||||||
|
|
||||||
private reports: Report[] = [];
|
private reports: Report[] = [];
|
||||||
|
|
||||||
public fileHasChildWithIdent(file: File, childIdent: string): boolean {
|
public fileHasChildWithIdent(file: File, childIdent: string): boolean {
|
||||||
return this.files.get(idKey(file))!
|
return this.files.get(id(file))!
|
||||||
.subFiles.has(childIdent);
|
.subFiles.has(childIdent);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -27,7 +20,7 @@ export class Ctx {
|
|||||||
text: string,
|
text: string,
|
||||||
): File {
|
): File {
|
||||||
const file = this.fileIds.nextThenStep();
|
const file = this.fileIds.nextThenStep();
|
||||||
this.files.set(idKey(file), {
|
this.files.set(id(file), {
|
||||||
ident,
|
ident,
|
||||||
absPath,
|
absPath,
|
||||||
relPath,
|
relPath,
|
||||||
@ -36,74 +29,38 @@ export class Ctx {
|
|||||||
text,
|
text,
|
||||||
});
|
});
|
||||||
if (superFile) {
|
if (superFile) {
|
||||||
this.files.get(idKey(superFile))!
|
this.files.get(id(superFile))!
|
||||||
.subFiles.set(ident, file);
|
.subFiles.set(ident, file);
|
||||||
}
|
}
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
|
|
||||||
public addFileAst(file: File, ast: ast.File) {
|
public addFileAst(file: File, ast: ast.File) {
|
||||||
this.files.get(idKey(file))!.ast = ast;
|
this.files.get(id(file))!.ast = ast;
|
||||||
}
|
}
|
||||||
|
|
||||||
public fileInfo(file: File): FileInfo {
|
public fileInfo(file: File): FileInfo {
|
||||||
return this.files.get(idKey(file))!;
|
return this.files.get(id(file))!;
|
||||||
}
|
|
||||||
|
|
||||||
public entryFile(): File {
|
|
||||||
return keyId(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public iterFiles(): Iterator<File> {
|
|
||||||
return this.files.keys()
|
|
||||||
.map((key) => keyId(key));
|
|
||||||
}
|
|
||||||
|
|
||||||
private identIds = new Ids<IdentId>();
|
|
||||||
private identStringToId = new Map<string, IdentId>();
|
|
||||||
private identIdToString = new Map<Key<IdentId>, string>();
|
|
||||||
|
|
||||||
public internIdent(ident: string): IdentId {
|
|
||||||
if (this.identStringToId.has(ident)) {
|
|
||||||
return this.identStringToId.get(ident)!;
|
|
||||||
}
|
|
||||||
const id = this.identIds.nextThenStep();
|
|
||||||
this.identStringToId.set(ident, id);
|
|
||||||
this.identIdToString.set(idKey(id), ident);
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public identText(ident: IdentId): string {
|
|
||||||
return this.identIdToString.get(idKey(ident))!;
|
|
||||||
}
|
|
||||||
|
|
||||||
private stmtIds = new Ids<hir.StmtId>();
|
|
||||||
private stmts = new Map<Key<hir.StmtId>, hir.Stmt>();
|
|
||||||
|
|
||||||
public internStmt(kind: hir.StmtKind, span: Span): hir.StmtId {
|
|
||||||
const id = this.stmtIds.nextThenStep();
|
|
||||||
this.stmts.set(idKey(id), { kind, span });
|
|
||||||
return id;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public filePosLineText(file: File, pos: Pos): string {
|
public filePosLineText(file: File, pos: Pos): string {
|
||||||
const fileTextLines = this.fileInfo(file).text.split("\n");
|
const fileTextLines = this.fileInfo(file).text.split("\n")
|
||||||
return fileTextLines[pos.line - 1];
|
return fileTextLines[pos.line-1]
|
||||||
}
|
}
|
||||||
|
|
||||||
public fileSpanText(file: File, span: Span): string {
|
public fileSpanText(file: File, span: Span): string {
|
||||||
let result = "";
|
let result = ""
|
||||||
const fileTextLines = this.fileInfo(file).text.split("\n");
|
const fileTextLines = this.fileInfo(file).text.split("\n")
|
||||||
|
|
||||||
for (let i = 0; i < fileTextLines.length; i++) {
|
for(let i = 0; i < fileTextLines.length; i++) {
|
||||||
if (i > span.end.line - 1) {
|
if (i > span.end.line-1) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (i >= span.begin.line - 1) {
|
if (i >= span.begin.line-1) {
|
||||||
result += fileTextLines[i] + "\n";
|
result += fileTextLines[i] + "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
public report(rep: Report) {
|
public report(rep: Report) {
|
||||||
@ -121,16 +78,9 @@ export class Ctx {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public printAsts() {
|
|
||||||
for (const [_, info] of this.files) {
|
|
||||||
console.log(`${info.absPath}:`);
|
|
||||||
console.log(JSON.stringify(info.ast!, null, 2));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export type File = IdBase & { readonly _: unique symbol };
|
export type File = IdBase;
|
||||||
|
|
||||||
export type FileInfo = {
|
export type FileInfo = {
|
||||||
ident: string;
|
ident: string;
|
||||||
@ -142,22 +92,16 @@ export type FileInfo = {
|
|||||||
ast?: ast.File;
|
ast?: ast.File;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type IdentId = IdBase & { readonly _: unique symbol };
|
export type IdBase = { id: number };
|
||||||
export type DefId = IdBase & { readonly _: unique symbol };
|
|
||||||
|
|
||||||
export type IdBase = { key: number };
|
export type Id<IdType extends IdBase> = IdType["id"];
|
||||||
|
export const id = <IdType extends IdBase>(id: IdType): Id<IdType> => id.id;
|
||||||
export type Key<IdType extends IdBase> = IdType["key"];
|
|
||||||
export const idKey = <IdType extends IdBase>(id: IdType): Key<IdType> => id.key;
|
|
||||||
export const keyId = <IdType extends IdBase>(
|
|
||||||
key: Key<IdType>,
|
|
||||||
): IdType => ({ key } as IdType);
|
|
||||||
|
|
||||||
export class Ids<IdType extends IdBase> {
|
export class Ids<IdType extends IdBase> {
|
||||||
private next = 0;
|
private next = 0;
|
||||||
public nextThenStep(): IdType {
|
public nextThenStep(): IdType {
|
||||||
const key = this.next;
|
const id = this.next;
|
||||||
this.next += 1;
|
this.next += 1;
|
||||||
return { key } as IdType;
|
return { id } as IdType;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,13 +4,6 @@ import * as ast from "./ast/mod.ts";
|
|||||||
import { Ctx } from "./ctx.ts";
|
import { Ctx } from "./ctx.ts";
|
||||||
import { File } from "./ctx.ts";
|
import { File } from "./ctx.ts";
|
||||||
|
|
||||||
async function main() {
|
|
||||||
const filePath = Deno.args[0];
|
|
||||||
const compiler = new PackCompiler(filePath, new NullEmitter());
|
|
||||||
compiler.enableDebug();
|
|
||||||
await compiler.compile();
|
|
||||||
}
|
|
||||||
|
|
||||||
export type Pack = {
|
export type Pack = {
|
||||||
rootMod: Mod;
|
rootMod: Mod;
|
||||||
};
|
};
|
||||||
@ -21,11 +14,6 @@ export interface PackEmitter {
|
|||||||
emit(pack: Pack): void;
|
emit(pack: Pack): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class NullEmitter implements PackEmitter {
|
|
||||||
emit(pack: Pack): void {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class PackCompiler {
|
export class PackCompiler {
|
||||||
private ctx = new Ctx();
|
private ctx = new Ctx();
|
||||||
|
|
||||||
@ -34,16 +22,10 @@ export class PackCompiler {
|
|||||||
private emitter: PackEmitter,
|
private emitter: PackEmitter,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
public async compile() {
|
public compile() {
|
||||||
await FileTreeAstCollector
|
FileTreeAstCollector
|
||||||
.fromEntryFile(this.ctx, this.entryFilePath)
|
.fromEntryFile(this.ctx, this.entryFilePath)
|
||||||
.collect();
|
.collect();
|
||||||
this.ctx.printAsts();
|
|
||||||
}
|
|
||||||
|
|
||||||
public enableDebug() {
|
|
||||||
this.ctx.enableReportImmediately = true;
|
|
||||||
this.ctx.enableStacktrace = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,8 +74,7 @@ export class FileTreeAstCollector implements ast.Visitor<[_P]> {
|
|||||||
kind: ast.ModFileItem,
|
kind: ast.ModFileItem,
|
||||||
{ file }: _P,
|
{ file }: _P,
|
||||||
): ast.VisitRes {
|
): ast.VisitRes {
|
||||||
const ident = this.ctx.identText(item.ident.id);
|
const { ident: { text: ident }, filePath: relPath } = kind;
|
||||||
const { filePath: relPath } = kind;
|
|
||||||
const absPath = path.join(path.dirname(this.absPath), relPath);
|
const absPath = path.join(path.dirname(this.absPath), relPath);
|
||||||
this.subFilePromise = this.subFilePromise
|
this.subFilePromise = this.subFilePromise
|
||||||
.then(() => {
|
.then(() => {
|
||||||
@ -118,5 +99,3 @@ export class FileTreeAstCollector implements ast.Visitor<[_P]> {
|
|||||||
return "stop";
|
return "stop";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
main();
|
|
||||||
|
@ -1,278 +0,0 @@
|
|||||||
import { Span } from "../diagnostics.ts";
|
|
||||||
|
|
||||||
export type StmtId = { key: number; readonly unique: unique symbol };
|
|
||||||
|
|
||||||
export type Stmt = {
|
|
||||||
kind: StmtKind;
|
|
||||||
span: Span;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type StmtKind =
|
|
||||||
| { tag: "error" }
|
|
||||||
| { tag: "item" } & ItemStmt
|
|
||||||
| { tag: "let" } & LetStmt
|
|
||||||
| { tag: "return" } & ReturnStmt
|
|
||||||
| { tag: "break" } & BreakStmt
|
|
||||||
| { tag: "continue" }
|
|
||||||
| { tag: "assign" } & AssignStmt
|
|
||||||
| { tag: "expr" } & ExprStmt;
|
|
||||||
|
|
||||||
export type ItemStmt = { item: ItemId };
|
|
||||||
|
|
||||||
export type LetStmt = {
|
|
||||||
pat: PatId;
|
|
||||||
ty?: TyId;
|
|
||||||
expr?: ExprId;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type ReturnStmt = { expr?: ExprId };
|
|
||||||
export type BreakStmt = { expr?: ExprId };
|
|
||||||
|
|
||||||
export type AssignStmt = {
|
|
||||||
assignType: AssignType;
|
|
||||||
subject: ExprId;
|
|
||||||
value: ExprId;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type AssignType = "=" | "+=" | "-=";
|
|
||||||
|
|
||||||
export type ExprStmt = { expr: ExprId };
|
|
||||||
|
|
||||||
export type ItemId = { key: number; readonly unique: unique symbol };
|
|
||||||
|
|
||||||
export type Item = {
|
|
||||||
kind: ItemKind;
|
|
||||||
span: Span;
|
|
||||||
ident: Ident;
|
|
||||||
pub: boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type ItemKind =
|
|
||||||
| { tag: "error" }
|
|
||||||
| { tag: "mod_block" } & ModBlockItem
|
|
||||||
| { tag: "mod_file" } & ModFileItem
|
|
||||||
| { tag: "enum" } & EnumItem
|
|
||||||
| { tag: "struct" } & StructItem
|
|
||||||
| { tag: "fn" } & FnItem
|
|
||||||
| { tag: "use" } & UseItem
|
|
||||||
| { tag: "type_alias" } & TypeAliasItem;
|
|
||||||
|
|
||||||
export type ModBlockItem = { block: BlockId };
|
|
||||||
export type ModFileItem = { filePath: string };
|
|
||||||
export type EnumItem = { variants: Variant[] };
|
|
||||||
export type StructItem = { data: VariantData };
|
|
||||||
|
|
||||||
export type FnItem = {
|
|
||||||
generics?: Generics;
|
|
||||||
params: Param[];
|
|
||||||
returnTy?: TyId;
|
|
||||||
body: BlockId;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type UseItem = { _: 0 };
|
|
||||||
export type TypeAliasItem = { ty: TyId };
|
|
||||||
|
|
||||||
export type Variant = {
|
|
||||||
ident: Ident;
|
|
||||||
data: VariantData;
|
|
||||||
pub: boolean;
|
|
||||||
span: Span;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type VariantData = {
|
|
||||||
kind: VariantDataKind;
|
|
||||||
span: Span;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type VariantDataKind =
|
|
||||||
| { tag: "error" }
|
|
||||||
| { tag: "unit" }
|
|
||||||
| { tag: "tuple" } & TupleVariantData
|
|
||||||
| { tag: "struct" } & StructVariantData;
|
|
||||||
|
|
||||||
export type TupleVariantData = { elems: VariantData[] };
|
|
||||||
export type StructVariantData = { fields: FieldDef[] };
|
|
||||||
|
|
||||||
export type FieldDef = {
|
|
||||||
ident: Ident;
|
|
||||||
ty: TyId;
|
|
||||||
pub: boolean;
|
|
||||||
span: Span;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type Param = {
|
|
||||||
pat: PatId;
|
|
||||||
ty: TyId;
|
|
||||||
span: Span;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type Generics = {
|
|
||||||
params: GenericParam[];
|
|
||||||
};
|
|
||||||
|
|
||||||
export type GenericParam = {
|
|
||||||
ident: Ident;
|
|
||||||
span: Span;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type ExprId = { key: number; readonly unique: unique symbol };
|
|
||||||
|
|
||||||
export type Expr = {
|
|
||||||
kind: ExprKind;
|
|
||||||
span: Span;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type ExprKind =
|
|
||||||
| { tag: "error" }
|
|
||||||
| { tag: "path" } & PathExpr
|
|
||||||
| { tag: "null" }
|
|
||||||
| { tag: "int" } & IntExpr
|
|
||||||
| { tag: "bool" } & BoolExpr
|
|
||||||
| { tag: "str" } & StringExpr
|
|
||||||
| { tag: "group" } & GroupExpr
|
|
||||||
| { tag: "array" } & ArrayExpr
|
|
||||||
| { tag: "repeat" } & RepeatExpr
|
|
||||||
| { tag: "struct" } & StructExpr
|
|
||||||
| { tag: "ref" } & RefExpr
|
|
||||||
| { tag: "deref" } & DerefExpr
|
|
||||||
| { tag: "elem" } & ElemExpr
|
|
||||||
| { tag: "field" } & FieldExpr
|
|
||||||
| { tag: "index" } & IndexExpr
|
|
||||||
| { tag: "call" } & CallExpr
|
|
||||||
| { tag: "unary" } & UnaryExpr
|
|
||||||
| { tag: "binary" } & BinaryExpr
|
|
||||||
| { tag: "block" } & BlockExpr
|
|
||||||
| { tag: "if" } & IfExpr
|
|
||||||
| { tag: "loop" } & LoopExpr
|
|
||||||
| { tag: "while" } & WhileExpr
|
|
||||||
| { tag: "for" } & ForExpr
|
|
||||||
| { tag: "c_for" } & CForExpr;
|
|
||||||
|
|
||||||
export type PathExpr = { path: Path };
|
|
||||||
export type IntExpr = { value: number };
|
|
||||||
export type BoolExpr = { value: boolean };
|
|
||||||
export type StringExpr = { value: string };
|
|
||||||
export type GroupExpr = { expr: ExprId };
|
|
||||||
export type ArrayExpr = { exprs: ExprId[] };
|
|
||||||
export type RepeatExpr = { expr: ExprId; length: ExprId };
|
|
||||||
export type StructExpr = { path?: Path; fields: ExprField[] };
|
|
||||||
export type RefExpr = { expr: ExprId; refType: RefType; mut: boolean };
|
|
||||||
export type DerefExpr = { expr: ExprId };
|
|
||||||
export type ElemExpr = { expr: ExprId; elem: number };
|
|
||||||
export type FieldExpr = { expr: ExprId; ident: Ident };
|
|
||||||
export type IndexExpr = { expr: ExprId; index: ExprId };
|
|
||||||
export type CallExpr = { expr: ExprId; args: ExprId[] };
|
|
||||||
export type UnaryExpr = { unaryType: UnaryType; expr: ExprId };
|
|
||||||
export type BinaryExpr = {
|
|
||||||
binaryType: BinaryType;
|
|
||||||
left: ExprId;
|
|
||||||
right: ExprId;
|
|
||||||
};
|
|
||||||
export type BlockExpr = { block: BlockId };
|
|
||||||
export type IfExpr = { cond: ExprId; truthy: BlockId; falsy?: ExprId };
|
|
||||||
export type LoopExpr = { body: BlockId };
|
|
||||||
export type WhileExpr = { cond: ExprId; body: BlockId };
|
|
||||||
export type ForExpr = { pat: PatId; expr: ExprId; body: BlockId };
|
|
||||||
export type CForExpr = {
|
|
||||||
decl?: StmtId;
|
|
||||||
cond?: ExprId;
|
|
||||||
incr?: StmtId;
|
|
||||||
body: BlockId;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type RefType = "ref" | "ptr";
|
|
||||||
export type UnaryType = "not" | "-";
|
|
||||||
export type BinaryType =
|
|
||||||
| "+"
|
|
||||||
| "*"
|
|
||||||
| "=="
|
|
||||||
| "-"
|
|
||||||
| "/"
|
|
||||||
| "!="
|
|
||||||
| "<"
|
|
||||||
| ">"
|
|
||||||
| "<="
|
|
||||||
| ">="
|
|
||||||
| "or"
|
|
||||||
| "and";
|
|
||||||
|
|
||||||
export type ExprField = {
|
|
||||||
ident: Ident;
|
|
||||||
expr: ExprId;
|
|
||||||
span: Span;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type BlockId = { key: number; readonly unique: unique symbol };
|
|
||||||
|
|
||||||
export type Block = {
|
|
||||||
stmts: StmtId[];
|
|
||||||
expr?: ExprId;
|
|
||||||
span: Span;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type PatId = { key: number; readonly unique: unique symbol };
|
|
||||||
|
|
||||||
export type Pat = {
|
|
||||||
kind: PatKind;
|
|
||||||
span: Span;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type PatKind =
|
|
||||||
| { tag: "error" }
|
|
||||||
| { tag: "bind" } & BindPat;
|
|
||||||
|
|
||||||
export type BindPat = {
|
|
||||||
ident: Ident;
|
|
||||||
mut: boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type TyId = { key: number; readonly unique: unique symbol };
|
|
||||||
|
|
||||||
export type Ty = {
|
|
||||||
kind: TyKind;
|
|
||||||
span: Span;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type TyKind =
|
|
||||||
| { tag: "error" }
|
|
||||||
| { tag: "null" }
|
|
||||||
| { tag: "int" }
|
|
||||||
| { tag: "bool" }
|
|
||||||
| { tag: "str" }
|
|
||||||
| { tag: "path" } & PathTy
|
|
||||||
| { tag: "ref" } & RefTy
|
|
||||||
| { tag: "ptr" } & PtrTy
|
|
||||||
| { tag: "slice" } & SliceTy
|
|
||||||
| { tag: "array" } & ArrayTy
|
|
||||||
| { tag: "anon_struct" } & AnonStructTy;
|
|
||||||
|
|
||||||
export type PathTy = { path: Path };
|
|
||||||
export type RefTy = { ty: TyId; mut: boolean };
|
|
||||||
export type PtrTy = { ty: TyId; mut: boolean };
|
|
||||||
export type SliceTy = { ty: TyId };
|
|
||||||
export type ArrayTy = { ty: TyId; length: ExprId };
|
|
||||||
export type TupleTy = { elems: TyId[] };
|
|
||||||
export type AnonStructTy = { fields: AnonFieldDef[] };
|
|
||||||
|
|
||||||
export type AnonFieldDef = {
|
|
||||||
ident: Ident;
|
|
||||||
ty: TyId;
|
|
||||||
span: Span;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type Path = {
|
|
||||||
segments: PathSegment[];
|
|
||||||
span: Span;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type PathSegment = {
|
|
||||||
ident: Ident;
|
|
||||||
genericArgs?: TyId[];
|
|
||||||
span: Span;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type Ident = {
|
|
||||||
internId: number;
|
|
||||||
span: Span;
|
|
||||||
};
|
|
||||||
|
|
@ -1,125 +0,0 @@
|
|||||||
import { Ctx, DefId, IdentId } from "../ctx.ts";
|
|
||||||
import * as ast from "../ast/ast.ts";
|
|
||||||
import { ExprId, Ident, ItemId, PatId, StmtId, TyId } from "./hir.ts";
|
|
||||||
import { exhausted, Res as Result, todo } from "../util.ts";
|
|
||||||
|
|
||||||
export class AstLowerer {
|
|
||||||
private ribs: Rib[] = [];
|
|
||||||
|
|
||||||
public constructor(
|
|
||||||
private ctx: Ctx,
|
|
||||||
) {}
|
|
||||||
|
|
||||||
public lower() {
|
|
||||||
const file = this.ctx.entryFile();
|
|
||||||
const ast = this.ctx.fileInfo(file).ast!;
|
|
||||||
this.lowerFile(ast);
|
|
||||||
}
|
|
||||||
|
|
||||||
private lowerFile(file: ast.File) {
|
|
||||||
this.lowerStmts(file.stmts);
|
|
||||||
}
|
|
||||||
|
|
||||||
private lowerStmts(stmts: ast.Stmt[]): StmtId[] {
|
|
||||||
return stmts.map((stmt) => this.lowerStmt(stmt));
|
|
||||||
}
|
|
||||||
|
|
||||||
private lowerStmt(stmt: ast.Stmt): StmtId {
|
|
||||||
const kind = stmt.kind;
|
|
||||||
switch (kind.tag) {
|
|
||||||
case "error":
|
|
||||||
return this.ctx.internStmt(kind, stmt.span);
|
|
||||||
case "item":
|
|
||||||
return this.ctx.internStmt({
|
|
||||||
tag: "item",
|
|
||||||
item: this.lowerItem(kind.item),
|
|
||||||
}, stmt.span);
|
|
||||||
case "let":
|
|
||||||
return this.lowerLetStmt(stmt, kind);
|
|
||||||
case "return":
|
|
||||||
return this.ctx.internStmt({
|
|
||||||
tag: "return",
|
|
||||||
expr: kind.expr && this.lowerExpr(kind.expr),
|
|
||||||
}, stmt.span);
|
|
||||||
case "break":
|
|
||||||
return this.ctx.internStmt({
|
|
||||||
tag: "break",
|
|
||||||
expr: kind.expr && this.lowerExpr(kind.expr),
|
|
||||||
}, stmt.span);
|
|
||||||
case "continue":
|
|
||||||
return this.ctx.internStmt({
|
|
||||||
tag: "continue",
|
|
||||||
}, stmt.span);
|
|
||||||
case "assign":
|
|
||||||
return this.ctx.internStmt({
|
|
||||||
tag: "assign",
|
|
||||||
assignType: kind.assignType,
|
|
||||||
subject: this.lowerExpr(kind.subject),
|
|
||||||
value: this.lowerExpr(kind.value),
|
|
||||||
}, stmt.span);
|
|
||||||
case "expr":
|
|
||||||
return this.ctx.internStmt({
|
|
||||||
tag: "expr",
|
|
||||||
expr: this.lowerExpr(kind.expr),
|
|
||||||
}, stmt.span);
|
|
||||||
}
|
|
||||||
exhausted(kind);
|
|
||||||
}
|
|
||||||
|
|
||||||
private lowerLetStmt(stmt: ast.Stmt, kind: ast.LetStmt): StmtId {
|
|
||||||
return this.ctx.internStmt({
|
|
||||||
tag: "let",
|
|
||||||
pat: this.lowerPat(kind.pat),
|
|
||||||
ty: kind.ty && this.lowerTy(kind.ty),
|
|
||||||
expr: kind.expr && this.lowerExpr(kind.expr),
|
|
||||||
}, stmt.span);
|
|
||||||
}
|
|
||||||
|
|
||||||
private lowerItem(item: ast.Item): ItemId {
|
|
||||||
return todo();
|
|
||||||
}
|
|
||||||
|
|
||||||
private lowerPat(pat: ast.Pat): PatId {
|
|
||||||
return todo();
|
|
||||||
}
|
|
||||||
|
|
||||||
private lowerTy(ty: ast.Ty): TyId {
|
|
||||||
return todo();
|
|
||||||
}
|
|
||||||
|
|
||||||
private lowerExpr(expr: ast.Expr): ExprId {
|
|
||||||
return todo();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://doc.rust-lang.org/nightly/nightly-rustc/rustc_resolve/late/struct.Rib.html
|
|
||||||
type Rib = {
|
|
||||||
kind: RibKind;
|
|
||||||
bindings: Map<IdentId, Res>;
|
|
||||||
};
|
|
||||||
|
|
||||||
// https://doc.rust-lang.org/nightly/nightly-rustc/rustc_resolve/late/enum.RibKind.html
|
|
||||||
type RibKind =
|
|
||||||
| { tag: "normal" }
|
|
||||||
| { tag: "fn" }
|
|
||||||
| { tag: "item"; defKind: DefKind }
|
|
||||||
| { tag: "mod" };
|
|
||||||
|
|
||||||
// https://doc.rust-lang.org/nightly/nightly-rustc/rustc_resolve/late/enum.RibKind.html
|
|
||||||
type Res =
|
|
||||||
| { tag: "error" }
|
|
||||||
| { tag: "def"; kind: DefKind; id: DefId }
|
|
||||||
| { tag: "local"; id: DefId };
|
|
||||||
|
|
||||||
// https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/def/enum.DefKind.html
|
|
||||||
type DefKind =
|
|
||||||
| { type: "mod" }
|
|
||||||
| { type: "struct" }
|
|
||||||
| { type: "enum" }
|
|
||||||
| { type: "variant" }
|
|
||||||
| { type: "ty_alias" }
|
|
||||||
| { type: "ty_param" }
|
|
||||||
| { type: "fn" }
|
|
||||||
| { type: "ctor" }
|
|
||||||
| { type: "use" }
|
|
||||||
| { type: "field" };
|
|
@ -56,7 +56,7 @@ export class Lexer {
|
|||||||
if (keywords.includes(value)) {
|
if (keywords.includes(value)) {
|
||||||
return this.token(value, pos);
|
return this.token(value, pos);
|
||||||
} else {
|
} else {
|
||||||
return { ...this.token("ident", pos), identId: value };
|
return { ...this.token("ident", pos), identValue: value };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (this.test(/[1-9]/)) {
|
if (this.test(/[1-9]/)) {
|
||||||
|
@ -199,7 +199,7 @@ export class Parser {
|
|||||||
this.report("expected 'ident'");
|
this.report("expected 'ident'");
|
||||||
return this.stmt({ type: "error" }, spos);
|
return this.stmt({ type: "error" }, spos);
|
||||||
}
|
}
|
||||||
const ident = this.current().identId!;
|
const ident = this.current().identValue!;
|
||||||
this.step();
|
this.step();
|
||||||
const args: Expr[] = [];
|
const args: Expr[] = [];
|
||||||
if (this.test("(")) {
|
if (this.test("(")) {
|
||||||
@ -250,7 +250,7 @@ export class Parser {
|
|||||||
this.report("expected 'ident'");
|
this.report("expected 'ident'");
|
||||||
return this.stmt({ type: "error" }, pos);
|
return this.stmt({ type: "error" }, pos);
|
||||||
}
|
}
|
||||||
const ident = this.current().identId!;
|
const ident = this.current().identValue!;
|
||||||
this.step();
|
this.step();
|
||||||
if (this.test(";")) {
|
if (this.test(";")) {
|
||||||
this.eatSemicolon();
|
this.eatSemicolon();
|
||||||
@ -290,7 +290,7 @@ export class Parser {
|
|||||||
this.report("expected ident");
|
this.report("expected ident");
|
||||||
return this.stmt({ type: "error" }, pos);
|
return this.stmt({ type: "error" }, pos);
|
||||||
}
|
}
|
||||||
const ident = this.current().identId!;
|
const ident = this.current().identValue!;
|
||||||
this.step();
|
this.step();
|
||||||
let genericParams: GenericParam[] | undefined;
|
let genericParams: GenericParam[] | undefined;
|
||||||
if (this.test("<")) {
|
if (this.test("<")) {
|
||||||
@ -333,7 +333,7 @@ export class Parser {
|
|||||||
private parseETypeParam(index: number): Res<GenericParam> {
|
private parseETypeParam(index: number): Res<GenericParam> {
|
||||||
const pos = this.pos();
|
const pos = this.pos();
|
||||||
if (this.test("ident")) {
|
if (this.test("ident")) {
|
||||||
const ident = this.current().identId!;
|
const ident = this.current().identValue!;
|
||||||
this.step();
|
this.step();
|
||||||
return {
|
return {
|
||||||
ok: true,
|
ok: true,
|
||||||
@ -394,7 +394,7 @@ export class Parser {
|
|||||||
mut = true;
|
mut = true;
|
||||||
this.step();
|
this.step();
|
||||||
}
|
}
|
||||||
const ident = this.current().identId!;
|
const ident = this.current().identValue!;
|
||||||
this.step();
|
this.step();
|
||||||
if (this.test(":")) {
|
if (this.test(":")) {
|
||||||
this.step();
|
this.step();
|
||||||
@ -637,7 +637,7 @@ export class Parser {
|
|||||||
this.report("expected 'ident'");
|
this.report("expected 'ident'");
|
||||||
return { ok: false, pos };
|
return { ok: false, pos };
|
||||||
}
|
}
|
||||||
const ident = this.current().identId!;
|
const ident = this.current().identValue!;
|
||||||
this.step();
|
this.step();
|
||||||
if (!this.test(":")) {
|
if (!this.test(":")) {
|
||||||
this.report("expected ':'");
|
this.report("expected ':'");
|
||||||
@ -856,7 +856,7 @@ export class Parser {
|
|||||||
this.report("expected ident");
|
this.report("expected ident");
|
||||||
return this.expr({ type: "error" }, pos);
|
return this.expr({ type: "error" }, pos);
|
||||||
}
|
}
|
||||||
const ident = this.current().identId!;
|
const ident = this.current().identValue!;
|
||||||
this.step();
|
this.step();
|
||||||
return this.expr({ type: "field", subject, ident }, pos);
|
return this.expr({ type: "field", subject, ident }, pos);
|
||||||
}
|
}
|
||||||
@ -890,7 +890,7 @@ export class Parser {
|
|||||||
this.report("expected ident");
|
this.report("expected ident");
|
||||||
return this.expr({ type: "error" }, pos);
|
return this.expr({ type: "error" }, pos);
|
||||||
}
|
}
|
||||||
const ident = this.current().identId!;
|
const ident = this.current().identValue!;
|
||||||
this.step();
|
this.step();
|
||||||
return this.expr({ type: "path", subject, ident }, pos);
|
return this.expr({ type: "path", subject, ident }, pos);
|
||||||
}
|
}
|
||||||
@ -906,7 +906,7 @@ export class Parser {
|
|||||||
private parseOperand(): Expr {
|
private parseOperand(): Expr {
|
||||||
const pos = this.pos();
|
const pos = this.pos();
|
||||||
if (this.test("ident")) {
|
if (this.test("ident")) {
|
||||||
const ident = this.current().identId!;
|
const ident = this.current().identValue!;
|
||||||
this.step();
|
this.step();
|
||||||
return this.expr({ type: "ident", ident }, pos);
|
return this.expr({ type: "ident", ident }, pos);
|
||||||
}
|
}
|
||||||
@ -975,7 +975,7 @@ export class Parser {
|
|||||||
return this.etype({ type }, pos);
|
return this.etype({ type }, pos);
|
||||||
}
|
}
|
||||||
if (this.test("ident")) {
|
if (this.test("ident")) {
|
||||||
const ident = this.current().identId!;
|
const ident = this.current().identValue!;
|
||||||
this.step();
|
this.step();
|
||||||
return this.etype({ type: "ident", ident: ident }, pos);
|
return this.etype({ type: "ident", ident: ident }, pos);
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@ export class Lexer implements TokenIter {
|
|||||||
? this.token(val, span)
|
? this.token(val, span)
|
||||||
: this.token("ident", span, {
|
: this.token("ident", span, {
|
||||||
type: "ident",
|
type: "ident",
|
||||||
identId: this.ctx.internIdent(val),
|
identValue: val,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
/[a-zA-Z_]/,
|
/[a-zA-Z_]/,
|
||||||
@ -127,8 +127,8 @@ export class Lexer implements TokenIter {
|
|||||||
return this.token("error", { begin, end });
|
return this.token("error", { begin, end });
|
||||||
}
|
}
|
||||||
this.step();
|
this.step();
|
||||||
return this.token("str", { begin, end }, {
|
return this.token("string", { begin, end }, {
|
||||||
type: "str",
|
type: "string",
|
||||||
stringValue: value,
|
stringValue: value,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -275,7 +275,7 @@ const keywords = new Set([
|
|||||||
"null",
|
"null",
|
||||||
"int",
|
"int",
|
||||||
"bool",
|
"bool",
|
||||||
"str",
|
"string",
|
||||||
"return",
|
"return",
|
||||||
"break",
|
"break",
|
||||||
"continue",
|
"continue",
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import {
|
import {
|
||||||
AnonFieldDef,
|
|
||||||
BinaryType,
|
BinaryType,
|
||||||
ExprField,
|
ExprField,
|
||||||
PathSegment,
|
PathSegment,
|
||||||
@ -29,8 +28,6 @@ import { Ctx, File as CtxFile } from "../ctx.ts";
|
|||||||
import { Pos, Span } from "../diagnostics.ts";
|
import { Pos, Span } from "../diagnostics.ts";
|
||||||
import { Res, todo } from "../util.ts";
|
import { Res, todo } from "../util.ts";
|
||||||
import { Lexer } from "./lexer.ts";
|
import { Lexer } from "./lexer.ts";
|
||||||
import { TokenIter } from "./token.ts";
|
|
||||||
import { SigFilter } from "./token.ts";
|
|
||||||
import { Token } from "./token.ts";
|
import { Token } from "./token.ts";
|
||||||
|
|
||||||
type ParseRes<V, E = undefined> = Res<V, E>;
|
type ParseRes<V, E = undefined> = Res<V, E>;
|
||||||
@ -41,14 +38,14 @@ type StmtDetails = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export class Parser {
|
export class Parser {
|
||||||
private lexer: TokenIter;
|
private lexer: Lexer;
|
||||||
private currentToken: Token | null;
|
private currentToken: Token | null;
|
||||||
|
|
||||||
public constructor(
|
public constructor(
|
||||||
private ctx: Ctx,
|
private ctx: Ctx,
|
||||||
private file: CtxFile,
|
private file: CtxFile,
|
||||||
) {
|
) {
|
||||||
this.lexer = new SigFilter(new Lexer(this.ctx, this.file));
|
this.lexer = new Lexer(this.ctx, this.file);
|
||||||
this.currentToken = this.lexer.next();
|
this.currentToken = this.lexer.next();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -206,7 +203,7 @@ export class Parser {
|
|||||||
private parseBlockExpr(): Expr {
|
private parseBlockExpr(): Expr {
|
||||||
const block = this.parseBlock();
|
const block = this.parseBlock();
|
||||||
return block.ok
|
return block.ok
|
||||||
? this.expr({ tag: "block", block: block.val }, this.span())
|
? this.expr({ tag: "block", ...block.val }, this.span())
|
||||||
: this.expr({ tag: "error" }, this.span());
|
: this.expr({ tag: "error" }, this.span());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -280,7 +277,7 @@ export class Parser {
|
|||||||
return this.stmt({ tag: "error" }, pos);
|
return this.stmt({ tag: "error" }, pos);
|
||||||
}
|
}
|
||||||
const ident = this.parseIdent();
|
const ident = this.parseIdent();
|
||||||
if (this.test("str")) {
|
if (this.test("string")) {
|
||||||
const filePath = this.current().stringValue!;
|
const filePath = this.current().stringValue!;
|
||||||
this.step();
|
this.step();
|
||||||
this.eatSemicolon();
|
this.eatSemicolon();
|
||||||
@ -315,13 +312,7 @@ export class Parser {
|
|||||||
return this.stmt({
|
return this.stmt({
|
||||||
tag: "item",
|
tag: "item",
|
||||||
item: this.item(
|
item: this.item(
|
||||||
{
|
{ tag: "mod_block", stmts },
|
||||||
tag: "mod_block",
|
|
||||||
block: {
|
|
||||||
stmts,
|
|
||||||
span: Span.fromto(pos, stmts.at(-1)?.span ?? pos),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
pos,
|
pos,
|
||||||
ident,
|
ident,
|
||||||
details.pub,
|
details.pub,
|
||||||
@ -452,15 +443,18 @@ export class Parser {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private parsePat(): Pat {
|
||||||
|
return todo();
|
||||||
|
}
|
||||||
|
|
||||||
private parseLet(): Stmt {
|
private parseLet(): Stmt {
|
||||||
const pos = this.span();
|
const pos = this.span();
|
||||||
this.step();
|
this.step();
|
||||||
const pat = this.parsePat();
|
const paramResult = this.parseParam();
|
||||||
let ty: Ty | undefined = undefined;
|
if (!paramResult.ok) {
|
||||||
if (this.test(":")) {
|
return this.stmt({ tag: "error" }, pos);
|
||||||
this.step();
|
|
||||||
ty = this.parseTy();
|
|
||||||
}
|
}
|
||||||
|
const { pat, ty } = paramResult.val;
|
||||||
if (!this.test("=")) {
|
if (!this.test("=")) {
|
||||||
this.report("expected '='");
|
this.report("expected '='");
|
||||||
return this.stmt({ tag: "error" }, pos);
|
return this.stmt({ tag: "error" }, pos);
|
||||||
@ -942,33 +936,19 @@ export class Parser {
|
|||||||
private parseOperand(): Expr {
|
private parseOperand(): Expr {
|
||||||
const pos = this.span();
|
const pos = this.span();
|
||||||
if (this.test("ident")) {
|
if (this.test("ident")) {
|
||||||
const pathRes = this.parsePath();
|
const ident = this.current().identValue!;
|
||||||
if (!pathRes.ok) {
|
this.step();
|
||||||
return this.expr({ tag: "error" }, pos);
|
return this.expr({ tag: "ident", ident }, pos);
|
||||||
}
|
|
||||||
if (this.test("{")) {
|
|
||||||
this.step();
|
|
||||||
const fields = this.parseDelimitedList(
|
|
||||||
this.parseExprField,
|
|
||||||
"}",
|
|
||||||
",",
|
|
||||||
);
|
|
||||||
return this.expr(
|
|
||||||
{ tag: "struct", path: pathRes.val, fields },
|
|
||||||
pathRes.val.span,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return this.expr({ tag: "path", path: pathRes.val }, pos);
|
|
||||||
}
|
}
|
||||||
if (this.test("int")) {
|
if (this.test("int")) {
|
||||||
const value = this.current().intValue!;
|
const value = this.current().intValue!;
|
||||||
this.step();
|
this.step();
|
||||||
return this.expr({ tag: "int", value }, pos);
|
return this.expr({ tag: "int", value }, pos);
|
||||||
}
|
}
|
||||||
if (this.test("str")) {
|
if (this.test("string")) {
|
||||||
const value = this.current().stringValue!;
|
const value = this.current().stringValue!;
|
||||||
this.step();
|
this.step();
|
||||||
return this.expr({ tag: "str", value }, pos);
|
return this.expr({ tag: "string", value }, pos);
|
||||||
}
|
}
|
||||||
if (this.test("false")) {
|
if (this.test("false")) {
|
||||||
this.step();
|
this.step();
|
||||||
@ -1013,82 +993,31 @@ export class Parser {
|
|||||||
return this.expr({ tag: "error" }, pos);
|
return this.expr({ tag: "error" }, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
private parseExprField(): ParseRes<ExprField> {
|
|
||||||
if (!this.test("ident")) {
|
|
||||||
this.report("expected 'ident'");
|
|
||||||
return Res.Err(undefined);
|
|
||||||
}
|
|
||||||
const ident = this.parseIdent();
|
|
||||||
if (!this.test(":")) {
|
|
||||||
this.report("expected ':'");
|
|
||||||
return Res.Err(undefined);
|
|
||||||
}
|
|
||||||
this.step();
|
|
||||||
const expr = this.parseExpr();
|
|
||||||
return Res.Ok({
|
|
||||||
ident,
|
|
||||||
expr,
|
|
||||||
span: Span.fromto(ident.span, expr.span),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private parsePat(): Pat {
|
|
||||||
const pos = this.span();
|
|
||||||
if (this.test("ident")) {
|
|
||||||
const ident = this.parseIdent();
|
|
||||||
return this.pat({ tag: "bind", ident, mut: false }, ident.span);
|
|
||||||
}
|
|
||||||
if (this.test("mut")) {
|
|
||||||
this.step();
|
|
||||||
if (!this.test("ident")) {
|
|
||||||
this.report("expected 'ident'");
|
|
||||||
return this.pat({ tag: "error" }, pos);
|
|
||||||
}
|
|
||||||
const ident = this.parseIdent();
|
|
||||||
return this.pat({ tag: "bind", ident, mut: false }, pos);
|
|
||||||
}
|
|
||||||
this.report(`expected pattern, got '${this.current().type}'`, pos);
|
|
||||||
this.step();
|
|
||||||
return this.pat({ tag: "error" }, pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
private parseTy(): Ty {
|
private parseTy(): Ty {
|
||||||
const pos = this.span();
|
const pos = this.span();
|
||||||
if (["null", "int", "bool", "str"].includes(this.current().type)) {
|
if (["null", "int", "bool", "string"].includes(this.current().type)) {
|
||||||
const tag = this.current().type as
|
const tag = this.current().type as
|
||||||
| "null"
|
| "null"
|
||||||
| "int"
|
| "int"
|
||||||
| "bool"
|
| "bool"
|
||||||
| "str";
|
| "string";
|
||||||
this.step();
|
this.step();
|
||||||
return this.ty({ tag }, pos);
|
return this.ty({ tag }, pos);
|
||||||
}
|
}
|
||||||
if (this.test("ident")) {
|
if (this.test("ident")) {
|
||||||
const pathRes = this.parsePath();
|
const ident = this.current().identValue!;
|
||||||
if (!pathRes.ok) {
|
this.step();
|
||||||
return this.ty({ tag: "error" }, pos);
|
return this.ty({ tag: "ident", ident: ident }, pos);
|
||||||
}
|
|
||||||
return this.ty({ tag: "path", path: pathRes.val }, pos);
|
|
||||||
}
|
}
|
||||||
if (this.test("[")) {
|
if (this.test("[")) {
|
||||||
this.step();
|
this.step();
|
||||||
const ty = this.parseTy();
|
const subject = this.parseTy();
|
||||||
if (this.test(";")) {
|
|
||||||
this.step();
|
|
||||||
const length = this.parseExpr();
|
|
||||||
if (!this.test("]")) {
|
|
||||||
this.report("expected ']'", pos);
|
|
||||||
return this.ty({ tag: "error" }, pos);
|
|
||||||
}
|
|
||||||
this.step();
|
|
||||||
return this.ty({ tag: "array", ty, length }, pos);
|
|
||||||
}
|
|
||||||
if (!this.test("]")) {
|
if (!this.test("]")) {
|
||||||
this.report("expected ']' or ';'", pos);
|
this.report("expected ']'", pos);
|
||||||
return this.ty({ tag: "error" }, pos);
|
return this.ty({ tag: "error" }, pos);
|
||||||
}
|
}
|
||||||
this.step();
|
this.step();
|
||||||
return this.ty({ tag: "slice", ty }, pos);
|
return this.ty({ tag: "array", subject }, pos);
|
||||||
}
|
}
|
||||||
if (this.test("struct")) {
|
if (this.test("struct")) {
|
||||||
this.step();
|
this.step();
|
||||||
@ -1096,55 +1025,55 @@ export class Parser {
|
|||||||
this.report("expected '{'");
|
this.report("expected '{'");
|
||||||
return this.ty({ tag: "error" }, pos);
|
return this.ty({ tag: "error" }, pos);
|
||||||
}
|
}
|
||||||
const fields = this.parseAnonFieldDefs();
|
const fields = this.parseTyStructFields();
|
||||||
return this.ty({ tag: "anon_struct", fields }, pos);
|
return this.ty({ tag: "struct", fields }, pos);
|
||||||
}
|
}
|
||||||
if (this.test("&")) {
|
if (this.test("&")) {
|
||||||
this.step();
|
this.step();
|
||||||
let mut = false;
|
let tag: "ref" | "ref_mut" = "ref";
|
||||||
if (this.test("mut")) {
|
if (this.test("mut")) {
|
||||||
this.step();
|
this.step();
|
||||||
mut = true;
|
tag = "ref_mut";
|
||||||
}
|
}
|
||||||
const ty = this.parseTy();
|
const subject = this.parseTy();
|
||||||
return this.ty({ tag: "ref", ty, mut }, pos);
|
return this.ty({ type, subject }, pos);
|
||||||
}
|
}
|
||||||
if (this.test("*")) {
|
if (this.test("*")) {
|
||||||
this.step();
|
this.step();
|
||||||
let mut = false;
|
let tag: "ptr" | "ptr_mut" = "ptr";
|
||||||
if (this.test("mut")) {
|
if (this.test("mut")) {
|
||||||
this.step();
|
this.step();
|
||||||
mut = true;
|
tag = "ptr_mut";
|
||||||
}
|
}
|
||||||
const ty = this.parseTy();
|
const subject = this.parseTy();
|
||||||
return this.ty({ tag: "ptr", ty, mut }, pos);
|
return this.ty({ type, subject }, pos);
|
||||||
}
|
}
|
||||||
this.report("expected type");
|
this.report("expected type");
|
||||||
return this.ty({ tag: "error" }, pos);
|
return this.ty({ tag: "error" }, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
private parseAnonFieldDefs(): AnonFieldDef[] {
|
private parseTyStructFields(): Param[] {
|
||||||
this.step();
|
this.step();
|
||||||
if (this.test("}")) {
|
if (this.test("}")) {
|
||||||
this.step();
|
this.step();
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
const params: AnonFieldDef[] = [];
|
const params: Param[] = [];
|
||||||
const paramResult = this.parseAnonFieldDef();
|
const paramResult = this.parseParam();
|
||||||
if (!paramResult.ok) {
|
if (!paramResult.ok) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
params.push(paramResult.val);
|
params.push(paramResult.value);
|
||||||
while (this.test(",")) {
|
while (this.test(",")) {
|
||||||
this.step();
|
this.step();
|
||||||
if (this.test("}")) {
|
if (this.test("}")) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
const paramResult = this.parseAnonFieldDef();
|
const paramResult = this.parseParam();
|
||||||
if (!paramResult.ok) {
|
if (!paramResult.ok) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
params.push(paramResult.val);
|
params.push(paramResult.value);
|
||||||
}
|
}
|
||||||
if (!this.test("}")) {
|
if (!this.test("}")) {
|
||||||
this.report("expected '}'");
|
this.report("expected '}'");
|
||||||
@ -1154,78 +1083,16 @@ export class Parser {
|
|||||||
return params;
|
return params;
|
||||||
}
|
}
|
||||||
|
|
||||||
private parseAnonFieldDef(): ParseRes<AnonFieldDef> {
|
private parsePath(): Path {
|
||||||
const begin = this.span();
|
|
||||||
const identRes = this.eatIdent();
|
|
||||||
if (!identRes.ok) return Res.Err(undefined);
|
|
||||||
const ident = identRes.val;
|
|
||||||
if (!this.test(":")) {
|
|
||||||
this.report("expected ':'");
|
|
||||||
return Res.Err(undefined);
|
|
||||||
}
|
|
||||||
this.step();
|
|
||||||
const ty = this.parseTy();
|
|
||||||
return Res.Ok({
|
|
||||||
ident,
|
|
||||||
ty,
|
|
||||||
span: Span.fromto(begin, ty.span),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private parsePath(): ParseRes<Path> {
|
|
||||||
const begin = this.span();
|
const begin = this.span();
|
||||||
let end = begin;
|
let end = begin;
|
||||||
const segments: PathSegment[] = [];
|
const segments: PathSegment[] = [];
|
||||||
const identRes = this.eatIdent();
|
|
||||||
if (!identRes.ok) return Res.Err(undefined);
|
|
||||||
const ident = identRes.val;
|
|
||||||
segments.push({ ident, span: Span.fromto(begin, end) });
|
|
||||||
while (this.test("::")) {
|
|
||||||
this.step();
|
|
||||||
if (!this.test("ident")) {
|
|
||||||
this.report("expected 'ident'");
|
|
||||||
return Res.Err(undefined);
|
|
||||||
}
|
|
||||||
end = this.span();
|
|
||||||
const ident = this.parseIdent();
|
|
||||||
let genericArgs: Ty[] | undefined = undefined;
|
|
||||||
if (this.test("::")) {
|
|
||||||
this.step();
|
|
||||||
if (!this.test("<")) {
|
|
||||||
this.report("expected '<'");
|
|
||||||
return Res.Err(undefined);
|
|
||||||
}
|
|
||||||
genericArgs = this.parseDelimitedList(
|
|
||||||
this.parseTyRes,
|
|
||||||
">",
|
|
||||||
",",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
segments.push({
|
|
||||||
ident,
|
|
||||||
genericArgs,
|
|
||||||
span: Span.fromto(begin, end),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return Res.Ok({ segments, span: Span.fromto(begin, end) });
|
|
||||||
}
|
|
||||||
|
|
||||||
private parseTyRes(): ParseRes<Ty> {
|
|
||||||
return Res.Ok(this.parseTy());
|
|
||||||
}
|
|
||||||
|
|
||||||
private eatIdent(): ParseRes<Ident> {
|
|
||||||
if (!this.test("ident")) {
|
|
||||||
this.report("expected 'ident'");
|
|
||||||
return Res.Err(undefined);
|
|
||||||
}
|
|
||||||
return Res.Ok(this.parseIdent());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private parseIdent(): Ident {
|
private parseIdent(): Ident {
|
||||||
const tok = this.current();
|
const tok = this.current();
|
||||||
this.step();
|
this.step();
|
||||||
return { id: tok.identId!, span: tok.span };
|
return { text: tok.identValue!, span: tok.span };
|
||||||
}
|
}
|
||||||
|
|
||||||
private step() {
|
private step() {
|
||||||
@ -1240,12 +1107,11 @@ export class Parser {
|
|||||||
return this.currentToken!;
|
return this.currentToken!;
|
||||||
}
|
}
|
||||||
|
|
||||||
private lastSpan?: Span;
|
|
||||||
private span(): Span {
|
private span(): Span {
|
||||||
if (this.done()) {
|
if (this.done()) {
|
||||||
return this.lastSpan!;
|
throw new Error();
|
||||||
}
|
}
|
||||||
return this.lastSpan = this.current().span;
|
return this.current().span;
|
||||||
}
|
}
|
||||||
|
|
||||||
private test(type: string): boolean {
|
private test(type: string): boolean {
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
import { IdentId } from "../ctx.ts";
|
|
||||||
import { Span } from "../diagnostics.ts";
|
import { Span } from "../diagnostics.ts";
|
||||||
|
|
||||||
export type Token = {
|
export type Token = {
|
||||||
type: string;
|
type: string;
|
||||||
span: Span;
|
span: Span;
|
||||||
length: number;
|
length: number;
|
||||||
identId?: IdentId;
|
identValue?: string;
|
||||||
intValue?: number;
|
intValue?: number;
|
||||||
stringValue?: string;
|
stringValue?: string;
|
||||||
};
|
};
|
||||||
|
@ -1,5 +0,0 @@
|
|||||||
|
|
||||||
fn main() -> int {
|
|
||||||
let a = 5;
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user