Skip to content

Commit

Permalink
Add flags to bind symbol
Browse files Browse the repository at this point in the history
  • Loading branch information
imteekay committed Jul 9, 2023
1 parent 0c43054 commit 926bcd2
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 24 deletions.
37 changes: 19 additions & 18 deletions src/bind.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
import { Declaration, Module, Node, Statement, Table } from './types';
import {
Declaration,
Module,
Node,
Statement,
SymbolFlags,
Table,
} from './types';
import { error } from './error';

export function bind(m: Module) {
Expand All @@ -12,6 +19,7 @@ export function bind(m: Module) {
statement.kind === Node.TypeAlias ||
statement.kind === Node.Let
) {
const isValue = isVariableDeclaration(statement.kind);
const symbol = locals.get(statement.name.text);
if (symbol) {
const other = symbol.declarations.find(
Expand All @@ -27,21 +35,25 @@ export function bind(m: Module) {
);
} else {
symbol.declarations.push(statement);
if ([Node.Var, Node.Let].includes(statement.kind)) {
if (isValue) {
symbol.valueDeclaration ||= statement;
symbol.flags |= SymbolFlags.Value;
}
}
} else {
locals.set(statement.name.text, {
declarations: [statement],
valueDeclaration: [Node.Var, Node.Let].includes(statement.kind)
? statement
: undefined,
valueDeclaration: isValue ? statement : undefined,
flags: isValue ? SymbolFlags.Value : SymbolFlags.Type,
});
}
}
}

function isVariableDeclaration(kind: Statement['kind']) {
return [Node.Var, Node.Let].includes(kind);
}

function hasEqualKindButNotVar(
declaration: Declaration,
statement: Statement,
Expand All @@ -64,20 +76,9 @@ export function bind(m: Module) {
}
}

export enum Meaning {
Value,
Type,
}

export function resolve(locals: Table, name: string, meaning: Meaning) {
export function resolve(locals: Table, name: string, meaning: SymbolFlags) {
const symbol = locals.get(name);
if (
symbol?.declarations.some((d) =>
meaning === Meaning.Value
? [Node.Var, Node.Let].includes(d.kind)
: d.kind === Node.TypeAlias,
)
) {
if (symbol && symbol.flags & meaning) {
return symbol;
}
}
14 changes: 8 additions & 6 deletions src/check.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ import {
Expression,
Identifier,
TypeAlias,
SymbolFlags,
} from './types';
import { error } from './error';
import { Meaning, resolve } from './bind';
import { resolve } from './bind';

const stringType: Type = { id: 'string' };
const numberType: Type = { id: 'number' };
Expand Down Expand Up @@ -51,10 +52,11 @@ export function check(module: Module) {
function checkExpression(expression: Expression): Type {
switch (expression.kind) {
case Node.Identifier:
const resolveExpression = (meaning: Meaning) =>
resolve(module.locals, expression.text, meaning);

const symbol = resolveExpression(Meaning.Value);
const symbol = resolve(
module.locals,
expression.text,
SymbolFlags.Value,
);

if (symbol?.valueDeclaration?.kind === Node.Let) {
if (symbol.valueDeclaration.pos < expression.pos) {
Expand Down Expand Up @@ -100,7 +102,7 @@ export function check(module: Module) {
case 'number':
return numberType;
default:
const symbol = resolve(module.locals, name.text, Meaning.Type);
const symbol = resolve(module.locals, name.text, SymbolFlags.Type);
if (symbol) {
return checkType(
(
Expand Down
7 changes: 7 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ export type Declaration = Var | Let | TypeAlias; // plus others, like function
export type Symbol = {
valueDeclaration: Declaration | undefined;
declarations: Declaration[];
flags: SymbolFlags;
};

export type Table = Map<string, Symbol>;
Expand All @@ -142,3 +143,9 @@ type CompilerTarget = 'es5' | 'es2015' | 'es2017' | 'es2022';
export interface CompilerOptions {
target: CompilerTarget;
}

export const enum SymbolFlags {
None = 0,
Value = 1 << 1,
Type = 1 << 2,
}

0 comments on commit 926bcd2

Please sign in to comment.