From 9c24ddb07e7981fb23bb34acd540001f4a505082 Mon Sep 17 00:00:00 2001 From: Sam Vervaeck Date: Wed, 12 Apr 2023 14:26:39 +0200 Subject: [PATCH 01/10] Move 'type class exists' check to initialze() --- src/checker.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/checker.ts b/src/checker.ts index 8daead5bb..8fea7d7df 100644 --- a/src/checker.ts +++ b/src/checker.ts @@ -1481,10 +1481,6 @@ export class Checker { case SyntaxKind.InstanceDeclaration: { - const cls = node.getScope().lookup(node.name.text, Symkind.Typeclass) as ClassDeclaration | null; - if (cls === null) { - this.diagnostics.add(new TypeclassNotFoundDiagnostic(node.name)); - } for (const element of node.elements) { this.infer(element); } @@ -2008,6 +2004,9 @@ export class Checker { case SyntaxKind.InstanceDeclaration: { + if (!this.classDecls.has(node.name.text)) { + this.diagnostics.add(new TypeclassNotFoundDiagnostic(node.name)); + } const env = node.typeEnv = new TypeEnv(parentEnv); for (const element of node.elements) { this.initialize(element, env); From f2ea45873c6c7aa383dde073d3782553e5bddb4d Mon Sep 17 00:00:00 2001 From: Sam Vervaeck Date: Wed, 12 Apr 2023 14:27:21 +0200 Subject: [PATCH 02/10] Fix minor indentation issue in checker.ts --- src/checker.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/checker.ts b/src/checker.ts index 8fea7d7df..06172cfc6 100644 --- a/src/checker.ts +++ b/src/checker.ts @@ -1106,7 +1106,7 @@ export class Checker { private createSubstitution(scheme: Scheme): TVSub { const sub = new TVSub(); - const tvs = [...scheme.typeVars] + const tvs = [...scheme.typeVars] for (const tv of tvs) { sub.set(tv, this.createTypeVar()); } @@ -2339,7 +2339,6 @@ export class Checker { this.popContext(context); this.solve(new CMany(constraints), this.solution); - } From d6845481410b57ccb52883890341755029865433 Mon Sep 17 00:00:00 2001 From: Sam Vervaeck Date: Wed, 12 Apr 2023 14:29:17 +0200 Subject: [PATCH 03/10] .gitginore: Add some comments and new rules --- .gitignore | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.gitignore b/.gitignore index 9d850e6e8..b4459c051 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,11 @@ + +# populated by npm node_modules/ + +# compiled TypeScript code from src/ /lib/ + +# local development helpers Makefile +/*.bolt +/*.c From 49a83f9a77aaa34bf2736dd1d7e97a51bef5159e Mon Sep 17 00:00:00 2001 From: Sam Vervaeck Date: Wed, 12 Apr 2023 14:29:56 +0200 Subject: [PATCH 04/10] vscode: Add launch.json for running on test file --- .vscode/launch.json | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 .vscode/launch.json diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 000000000..0f42771dd --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,19 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "node", + "request": "launch", + "name": "Launch Program", + "skipFiles": [ + "/**" + ], + "program": "${workspaceFolder}/lib/bin/bolt.js", + "args": [ "test.bolt" ], + "outputCapture": "std" + } + ] +} \ No newline at end of file From 17bdb2d7cb026b7db262a6e79d79a60e12bcf23b Mon Sep 17 00:00:00 2001 From: Sam Vervaeck Date: Wed, 12 Apr 2023 19:38:45 +0200 Subject: [PATCH 05/10] Fix some bugs in textual input/ouput --- src/cst.ts | 5 ++--- src/diagnostics.ts | 4 ++-- src/scanner.ts | 3 +-- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/cst.ts b/src/cst.ts index 76b1db596..a141d7289 100644 --- a/src/cst.ts +++ b/src/cst.ts @@ -39,9 +39,8 @@ export class TextPosition { } else { this.column++; } - this.offset += text.length; } - + this.offset += text.length; } } @@ -617,7 +616,7 @@ export class StringLiteral extends TokenBase { } else if (code <= 127) { out += '\\x' + code.toString(16).padStart(2, '0'); } else { - out += '\\u' + code.toString(17).padStart(4, '0'); + out += '\\u' + code.toString(16).padStart(4, '0'); } } out += '"'; diff --git a/src/diagnostics.ts b/src/diagnostics.ts index 6575fc20f..d7f7ae8ac 100644 --- a/src/diagnostics.ts +++ b/src/diagnostics.ts @@ -331,14 +331,14 @@ export class ConsoleDiagnostics implements Diagnostics { if (leftNode !== null) { this.writer.indent(); this.writer.write(ANSI_FG_YELLOW + ANSI_BOLD + `info: ` + ANSI_RESET); - this.writer.write(`type ` + ANSI_FG_GREEN + describeType(diagnostic.left) + ANSI_RESET + ` was inferred from diagnostic expression:\n\n`); + this.writer.write(`type ` + ANSI_FG_GREEN + describeType(diagnostic.left) + ANSI_RESET + ` was inferred from this expression:\n\n`); this.writer.write(printNode(leftNode) + '\n'); this.writer.dedent(); } if (rightNode !== null) { this.writer.indent(); this.writer.write(ANSI_FG_YELLOW + ANSI_BOLD + `info: ` + ANSI_RESET); - this.writer.write(`type ` + ANSI_FG_GREEN + describeType(diagnostic.right) + ANSI_RESET + ` was inferred from diagnostic expression:\n\n`); + this.writer.write(`type ` + ANSI_FG_GREEN + describeType(diagnostic.right) + ANSI_RESET + ` was inferred from this expression:\n\n`); this.writer.write(printNode(rightNode) + '\n'); this.writer.dedent(); } diff --git a/src/scanner.ts b/src/scanner.ts index 227905f06..301952984 100644 --- a/src/scanner.ts +++ b/src/scanner.ts @@ -46,7 +46,7 @@ import { InstanceKeyword, Backslash, } from "./cst" -import { Diagnostics, UnexpectedCharDiagnostic } from "./diagnostics" +import { Diagnostics } from "./diagnostics" import { Stream, BufferedStream, assert } from "./util"; const EOF = '\uFFFF' @@ -182,7 +182,6 @@ export class Scanner extends BufferedStream { case '"': { - const startPos = this.getCurrentPosition(); let contents = ''; let escaping = false; for (;;) { From e7493d0d49bc43c6b39a97d039d138e2a2d268c4 Mon Sep 17 00:00:00 2001 From: Sam Vervaeck Date: Wed, 12 Apr 2023 21:16:48 +0200 Subject: [PATCH 06/10] Multiple updates to code base - Fix variable polymorphism by addding missing generalization step - Add method for `util.inspect` to make pretty-printing easier - Remove WrappedOperator and replace it with NamedPattern --- src/checker.ts | 469 +++++++++++++++++++++++++++++++++---------------- src/cst.ts | 18 +- src/parser.ts | 2 +- src/scope.ts | 6 +- src/util.ts | 18 +- 5 files changed, 351 insertions(+), 162 deletions(-) diff --git a/src/checker.ts b/src/checker.ts index 06172cfc6..42e4259d2 100644 --- a/src/checker.ts +++ b/src/checker.ts @@ -34,8 +34,9 @@ import { TypeclassNotFoundDiagnostic, TypeclassDeclaredTwiceDiagnostic, } from "./diagnostics"; -import { assert, isDebug, assertNever, first, isEmpty, last, MultiMap } from "./util"; +import { assert, assertNever, first, isEmpty, last, MultiMap, toStringTag, InspectFn } from "./util"; import { Analyser } from "./analysis"; +import { InspectOptions } from "util"; const MAX_TYPE_ERROR_COUNT = 5; @@ -114,6 +115,10 @@ class TVar extends TypeBase { ? this : other.substitute(sub); } + public [toStringTag]() { + return 'a' + this.id; + } + } export class TNil extends TypeBase { @@ -132,6 +137,10 @@ export class TNil extends TypeBase { } + public [toStringTag]() { + return '∂Abs'; + } + } export class TAbsent extends TypeBase { @@ -150,6 +159,10 @@ export class TAbsent extends TypeBase { } + public [toStringTag]() { + return 'Abs'; + } + } export class TPresent extends TypeBase { @@ -175,6 +188,10 @@ export class TPresent extends TypeBase { return new TPresent(this.type, this.node); } + public [toStringTag](_depth: number, options: InspectOptions, inspect: InspectFn) { + return 'Pre ' + inspect(this.type, options); + } + } export class TArrow extends TypeBase { @@ -223,6 +240,10 @@ export class TArrow extends TypeBase { return changed ? new TArrow(newParamType, newReturnType, this.node) : this; } + public [toStringTag](_depth: number, options: InspectOptions, inspect: InspectFn) { + return inspect(this.paramType, options) + ' -> ' + inspect(this.returnType, options); + } + } export class TCon extends TypeBase { @@ -266,6 +287,10 @@ export class TCon extends TypeBase { return changed ? new TCon(this.id, newArgTypes, this.displayName, this.node) : this; } + public [toStringTag](_depth: number, options: InspectOptions, inspect: InspectFn) { + return this.displayName + ' ' + this.argTypes.map(t => inspect(t, options)).join(' '); + } + } class TTuple extends TypeBase { @@ -305,6 +330,10 @@ class TTuple extends TypeBase { return changed ? new TTuple(newElementTypes, this.node) : this; } + public [toStringTag](_depth: number, options: InspectOptions, inspect: InspectFn) { + return this.elementTypes.map(t => inspect(t, options)).join(' × '); + } + } export class TField extends TypeBase { @@ -355,6 +384,10 @@ export class TField extends TypeBase { ? new TField(this.name, newType, newRestType, this.node) : this; } + public [toStringTag](_depth: number, options: InspectOptions, inspect: InspectFn) { + return '{ ' + this.name + ' : ' + inspect(this.type, options) + ' | ' + inspect(this.restType, options) + ' }'; + } + } export class TApp extends TypeBase { @@ -402,6 +435,10 @@ export class TApp extends TypeBase { return changed ? new TApp(newOperatorType, newArgType, this.node) : this; } + public [toStringTag](_depth: number, options: InspectOptions, inspect: InspectFn) { + return inspect(this.left, options) + ' ' + inspect(this.right, options); + } + } export class TNominal extends TypeBase { @@ -430,6 +467,10 @@ export class TNominal extends TypeBase { return this; } + public [toStringTag]() { + return this.decl.name.text; + } + } export type Type @@ -636,6 +677,17 @@ class TVSet { return this.mapping.values(); } + public [toStringTag](_depth: number, options: InspectOptions, inspect: InspectFn) { + let out = '{ '; + let first = true; + for (const tv of this) { + if (first) first = false; + else out += ', '; + out += inspect(tv, options); + } + return out + ' }'; + } + } class TVSub { @@ -667,14 +719,11 @@ class TVSub { const enum ConstraintKind { Equal, Many, - Shaped, - Class, + Empty, } abstract class ConstraintBase { - public abstract substitute(sub: TVSub): Constraint; - public constructor( public node: Syntax | null = null ) { @@ -701,6 +750,10 @@ abstract class ConstraintBase { return first(this.getNodes()[Symbol.iterator]()) ?? null; } + public abstract freeTypeVars(): Iterable; + + public abstract substitute(sub: TVSub, node: Syntax | null): Constraint; + } class CEqual extends ConstraintBase { @@ -710,21 +763,26 @@ class CEqual extends ConstraintBase { public constructor( public left: Type, public right: Type, - public node: Syntax, + public node: Syntax | null, ) { super(); } - public substitute(sub: TVSub): Constraint { + public substitute(sub: TVSub, node: Syntax | null = null): CEqual { return new CEqual( this.left.substitute(sub), this.right.substitute(sub), - this.node, + node, ); } - public dump(): void { - console.error(`${describeType(this.left)} ~ ${describeType(this.right)}`); + public *freeTypeVars(): Iterable { + yield* this.left.getTypeVars(); + yield* this.right.getTypeVars(); + } + + public [toStringTag](_currentDepth: number, options: InspectOptions, inspect: InspectFn): string { + return inspect(this.left, options) + ' ~ ' + inspect(this.right, options); } } @@ -739,19 +797,55 @@ class CMany extends ConstraintBase { super(); } - public substitute(sub: TVSub): Constraint { + public substitute(sub: TVSub, node: Syntax | null = null): CMany { const newElements = []; for (const element of this.elements) { - newElements.push(element.substitute(sub)); + newElements.push(element.substitute(sub, node)); } return new CMany(newElements); } + public *freeTypeVars(): Iterable { + for (const element of this.elements) { + yield* element.freeTypeVars(); + } + } + + public [toStringTag](currentDepth: number, { depth = 2, ...options }: InspectOptions, inspect: InspectFn): string { + if (this.elements.length === 0) { + return '[]'; + } + let out = '[\n'; + const newOptions = { ...options, depth: depth === null ? null : depth - 1 }; + out += this.elements.map(constraint => ' ' + inspect(constraint, newOptions)).join('\n'); + out += '\n]'; + return out; + } + +} + +class CEmpty extends ConstraintBase { + + public readonly kind = ConstraintKind.Empty; + + public substitute(_sub: TVSub, _node: Syntax | null = null): Constraint { + return this; + } + + public *freeTypeVars(): Iterable { + + } + + public [toStringTag]() { + return 'ε'; + } + } type Constraint = CEqual | CMany + | CEmpty class ConstraintSet extends Array { } @@ -761,19 +855,33 @@ abstract class SchemeBase { class Forall extends SchemeBase { - public typeVars: TVSet; - public constructor( - typeVars: Iterable, - public constraints: Iterable, + public typeVars: TVSet, + public constraint: Constraint, public type: Type, ) { super(); - if (typeVars instanceof TVSet) { - this.typeVars = typeVars; - } else { - this.typeVars = new TVSet(typeVars); + } + + public *freeTypeVars(): Iterable { + for (const tv of this.constraint.freeTypeVars()) { + if (!this.typeVars.has(tv)) { + yield tv; + } } + for (const tv of this.type.getTypeVars()) { + if (!this.typeVars.has(tv)) { + yield tv; + } + } + } + + public static mono(type: Type): Forall { + return new Forall(new TVSet, new CEmpty, type); + } + + public static fromArrays(typeVars: TVar[], constraints: Constraint[], type: Type): Forall { + return new Forall(new TVSet(typeVars), new CMany(constraints), type); } } @@ -814,9 +922,6 @@ class TypeEnv { } public add(name: string, scheme: Scheme, kind: Symkind): void { - if (isDebug) { - validateScheme(scheme); - } this.mapping.add(name, [kind, scheme]); } @@ -829,6 +934,17 @@ class TypeEnv { return null; } + public hasTypeVar(seek: TVar): boolean { + for (const [_name, [_kind, scheme]] of this.mapping) { + for (const tv of scheme.freeTypeVars()) { + if (tv.id === seek.id) { + return true; + } + } + } + return false; + } + } class KindEnv { @@ -885,7 +1001,7 @@ export interface InferContext { } function isFunctionDeclarationLike(node: LetDeclaration): boolean { - return node.pattern.kind === SyntaxKind.NamedPattern + return (node.pattern.kind === SyntaxKind.NamedPattern || node.pattern.kind === SyntaxKind.NestedPattern && node.pattern.pattern.kind === SyntaxKind.NamedPattern) && (node.params.length > 0 || (node.body !== null && node.body.kind === SyntaxKind.BlockBody)); } @@ -920,18 +1036,18 @@ export class Checker { const a = new TVar(this.nextTypeVarId++); const b = new TVar(this.nextTypeVarId++); - this.globalTypeEnv.add('$', new Forall([ a, b ], [], new TArrow(new TArrow(new TArrow(a, b), a), b)), Symkind.Var); - this.globalTypeEnv.add('String', new Forall([], [], this.stringType), Symkind.Type); - this.globalTypeEnv.add('Int', new Forall([], [], this.intType), Symkind.Type); - this.globalTypeEnv.add('Bool', new Forall([], [], this.boolType), Symkind.Type); - this.globalTypeEnv.add('True', new Forall([], [], this.boolType), Symkind.Var); - this.globalTypeEnv.add('False', new Forall([], [], this.boolType), Symkind.Var); - this.globalTypeEnv.add('+', new Forall([], [], TArrow.build([ this.intType, this.intType ], this.intType)), Symkind.Var); - this.globalTypeEnv.add('-', new Forall([], [], TArrow.build([ this.intType, this.intType ], this.intType)), Symkind.Var); - this.globalTypeEnv.add('*', new Forall([], [], TArrow.build([ this.intType, this.intType ], this.intType)), Symkind.Var); - this.globalTypeEnv.add('/', new Forall([], [], TArrow.build([ this.intType, this.intType ], this.intType)), Symkind.Var); - this.globalTypeEnv.add('==', new Forall([ a ], [], TArrow.build([ a, a ], this.boolType)), Symkind.Var); - this.globalTypeEnv.add('not', new Forall([], [], new TArrow(this.boolType, this.boolType)), Symkind.Var); + this.globalTypeEnv.add('$', Forall.fromArrays([ a, b ], [], new TArrow(new TArrow(new TArrow(a, b), a), b)), Symkind.Var); + this.globalTypeEnv.add('String', Forall.fromArrays([], [], this.stringType), Symkind.Type); + this.globalTypeEnv.add('Int', Forall.fromArrays([], [], this.intType), Symkind.Type); + this.globalTypeEnv.add('Bool', Forall.fromArrays([], [], this.boolType), Symkind.Type); + this.globalTypeEnv.add('True', Forall.fromArrays([], [], this.boolType), Symkind.Var); + this.globalTypeEnv.add('False', Forall.fromArrays([], [], this.boolType), Symkind.Var); + this.globalTypeEnv.add('+', Forall.fromArrays([], [], TArrow.build([ this.intType, this.intType ], this.intType)), Symkind.Var); + this.globalTypeEnv.add('-', Forall.fromArrays([], [], TArrow.build([ this.intType, this.intType ], this.intType)), Symkind.Var); + this.globalTypeEnv.add('*', Forall.fromArrays([], [], TArrow.build([ this.intType, this.intType ], this.intType)), Symkind.Var); + this.globalTypeEnv.add('/', Forall.fromArrays([], [], TArrow.build([ this.intType, this.intType ], this.intType)), Symkind.Var); + this.globalTypeEnv.add('==', Forall.fromArrays([ a ], [], TArrow.build([ a, a ], this.boolType)), Symkind.Var); + this.globalTypeEnv.add('not', Forall.fromArrays([], [], new TArrow(this.boolType, this.boolType)), Symkind.Var); } @@ -974,6 +1090,23 @@ export class Checker { this.contexts.pop(); } + private generalize(type: Type, constraints: Constraint[], env: TypeEnv): Scheme { + const tvs = new TVSet(); + for (const tv of type.getTypeVars()) { + if (!env.hasTypeVar(tv)) { + tvs.add(tv); + } + } + for (const constraint of constraints) { + for (const tv of constraint.freeTypeVars()) { + if (!env.hasTypeVar(tv)) { + tvs.add(tv); + } + } + } + return new Forall(tvs, new CMany(constraints), type); + } + private lookupKind(env: KindEnv, node: NodeWithReference, emitDiagnostic = true): Kind | null { const [modulePath, name] = splitReferences(node); if (modulePath.length > 0) { @@ -1104,6 +1237,10 @@ export class Checker { return context.returnType; } + private getTypeEnv(): TypeEnv { + return this.getContext().env; + } + private createSubstitution(scheme: Scheme): TVSub { const sub = new TVSub(); const tvs = [...scheme.typeVars] @@ -1114,12 +1251,27 @@ export class Checker { } private instantiate(scheme: Scheme, node: Syntax | null, sub = this.createSubstitution(scheme)): Type { - for (const constraint of scheme.constraints) { - const substituted = constraint.substitute(sub); - substituted.node = node; - substituted.prevInstantiation = constraint; - this.addConstraint(substituted); + const update = (constraint: CEqual) => { + constraint.node = node; + constraint.prevInstantiation = scheme.constraint; } + const transform = (constraint: Constraint): Constraint => { + switch (constraint.kind) { + case ConstraintKind.Many: + const newConstraints: Constraint[] = []; + for (const element of constraint.elements) { + newConstraints.push(transform(element)); + } + return new CMany(newConstraints); + case ConstraintKind.Empty: + return constraint; + case ConstraintKind.Equal: + const newConstraint = constraint.substitute(sub); + update(newConstraint); + return newConstraint; + } + } + this.addConstraint(transform(scheme.constraint)); return scheme.type.substitute(sub); } @@ -1535,34 +1687,23 @@ export class Checker { if (isFunctionDeclarationLike(node)) { break; } + const ctx = this.getContext(); + const constraints: ConstraintSet = []; + const innerCtx: InferContext = { + ...ctx, + constraints, + }; + this.pushContext(innerCtx); let type; - if (node.pattern.kind === SyntaxKind.WrappedOperator) { - type = this.createTypeVar(); - this.addBinding(node.pattern.operator.text, new Forall([], [], type), Symkind.Var); - } else { - type = this.inferBindings(node.pattern, [], []); - } if (node.typeAssert !== null) { - this.addConstraint( - new CEqual( - this.inferTypeExpression(node.typeAssert.typeExpression), - type, - node - ) - ); + type = this.inferTypeExpression(node.typeAssert.typeExpression); } if (node.body !== null) { + let bodyType; switch (node.body.kind) { case SyntaxKind.ExprBody: { - const type2 = this.inferExpression(node.body.expression); - this.addConstraint( - new CEqual( - type, - type2, - node - ) - ); + bodyType = this.inferExpression(node.body.expression); break; } case SyntaxKind.BlockBody: @@ -1571,7 +1712,23 @@ export class Checker { assert(false); } } + if (type === undefined) { + type = bodyType; + } else { + constraints.push( + new CEqual( + type, + bodyType, + node.body + ) + ); + } } + if (type === undefined) { + type = this.createTypeVar(); + } + this.popContext(innerCtx); + this.inferBindings(node.pattern, type, undefined, constraints, true); break; } @@ -1613,9 +1770,11 @@ export class Checker { returnType: context.returnType, }; this.pushContext(newContext); + const armPatternType = this.createTypeVar(); + this.inferBindings(arm.pattern, armPatternType); this.addConstraint( new CEqual( - this.inferBindings(arm.pattern, [], []), + armPatternType, exprType, arm.pattern, ) @@ -1814,10 +1973,10 @@ export class Checker { this.diagnostics.add(new BindingNotFoundDiagnostic([], node.name.text, node.name)); } type = this.createTypeVar(); - this.addBinding(node.name.text, new Forall([], [], type), Symkind.Type); + this.addBinding(node.name.text, Forall.mono(type), Symkind.Type); } else { assert(isEmpty(scheme.typeVars)); - assert(isEmpty(scheme.constraints)); + assert(scheme.constraint.kind === ConstraintKind.Empty); type = scheme.type; } break; @@ -1856,94 +2015,99 @@ export class Checker { } - public inferBindings(pattern: Pattern, typeVars: Iterable, constraints: Iterable): Type { + public inferBindings(pattern: Pattern, type: Type, typeVars = new TVSet, constraints: Constraint[] = [], generalize = false): void { switch (pattern.kind) { case SyntaxKind.NamedPattern: { - const type = this.createTypeVar(); - this.addBinding(pattern.name.text, new Forall(typeVars, constraints, type), Symkind.Var); - return type; + let scheme; + const env = this.getTypeEnv(); + if (generalize) { + scheme = this.generalize(type, constraints, env); + } else { + scheme = new Forall(typeVars, new CMany(constraints), type); + } + this.addBinding(pattern.name.text, scheme, Symkind.Var); + break; } case SyntaxKind.NestedPattern: - return this.inferBindings(pattern.pattern, typeVars, constraints); + this.inferBindings(pattern.pattern, type, typeVars, constraints); + break; - case SyntaxKind.NamedTuplePattern: - { - const scheme = this.lookup(pattern.name, Symkind.Type); - if (scheme === null) { - return this.createTypeVar(); - } - let tupleType = pattern.elements.map(p => this.inferBindings(p, typeVars, constraints)); - // FIXME not tested - return TApp.build( - new TNominal(scheme.type.node as StructDeclaration | EnumDeclaration, pattern), - tupleType - ); - } + // case SyntaxKind.NamedTuplePattern: + // { + // const scheme = this.lookup(pattern.name, Symkind.Type); + // if (scheme === null) { + // return this.createTypeVar(); + // } + // let tupleType = new TTuple(pattern.elements.map(p => + // this.inferBindings(p, this.createTypeVar(), typeVars, constraints)); + // // FIXME not tested + // this.addConstraint(new CEqual(tupleType, type, pattern)); + // return TApp.build( + // new TNominal(scheme.type.node as StructDeclaration | EnumDeclaration, pattern), + // tupleType + // ); + // } case SyntaxKind.LiteralPattern: { - let type; + let literalType; switch (pattern.token.kind) { case SyntaxKind.Integer: - type = this.getIntType(); + literalType = this.getIntType(); break; case SyntaxKind.StringLiteral: - type = this.getStringType(); + literalType = this.getStringType(); break; } - type = type.shallowClone(); - type.node = pattern; - return type; + literalType = literalType.shallowClone(); + literalType.node = pattern; + this.addConstraint( + new CEqual( + literalType, + type, + pattern, + ) + ); + break; } case SyntaxKind.DisjunctivePattern: { - const type = this.createTypeVar(); - this.addConstraint( - new CEqual( - this.inferBindings(pattern.left, typeVars, constraints), - type, - pattern.left - ) - ); - this.addConstraint( - new CEqual( - this.inferBindings(pattern.right, typeVars, constraints), - type, - pattern.left - ) - ); - return type; + this.inferBindings(pattern.left, type, typeVars, constraints), + this.inferBindings(pattern.right, type, typeVars, constraints); + break; } case SyntaxKind.StructPattern: { const variadicMember = getVariadicMember(pattern); - let type: Type; + let structType: Type; if (variadicMember === null) { - type = new TNil(pattern); - } else if (variadicMember.pattern === null) { - type = this.createTypeVar(); + structType = new TNil(pattern); } else { - type = this.inferBindings(variadicMember.pattern, typeVars, constraints); + structType = this.createTypeVar(); + if (variadicMember.pattern !== null) { + this.inferBindings(variadicMember.pattern, structType, typeVars, constraints); + } } for (const member of pattern.members) { switch (member.kind) { case SyntaxKind.StructPatternField: { - const fieldType = this.inferBindings(member.pattern, typeVars, constraints); - type = new TField(member.name.text, new TPresent(fieldType), type, pattern); + const fieldType = this.createTypeVar(); + this.inferBindings(member.pattern, fieldType, typeVars, constraints); + structType = new TField(member.name.text, new TPresent(fieldType), fieldType, pattern); break; } case SyntaxKind.PunnedStructPatternField: { const fieldType = this.createTypeVar(); - this.addBinding(member.name.text, new Forall([], [], fieldType), Symkind.Var); - type = new TField(member.name.text, new TPresent(fieldType), type, pattern); + this.addBinding(member.name.text, Forall.mono(fieldType), Symkind.Var); + structType = new TField(member.name.text, new TPresent(fieldType), fieldType, pattern); break; } case SyntaxKind.VariadicStructPatternElement: @@ -1952,7 +2116,14 @@ export class Checker { assertNever(member); } } - return TField.sort(type); + this.addConstraint( + new CEqual( + type, + TField.sort(structType), + pattern, + ) + ); + break; } default: @@ -1994,7 +2165,7 @@ export class Checker { const env = node.typeEnv = new TypeEnv(parentEnv); for (const tv of node.types) { assert(tv.kind === SyntaxKind.VarTypeExpression); - env.add(tv.name.text, new Forall([], [], this.createTypeVar(tv)), Symkind.Type); + env.add(tv.name.text, Forall.mono(this.createTypeVar(tv)), Symkind.Type); } for (const element of node.elements) { this.initialize(element, env); @@ -2045,11 +2216,11 @@ export class Checker { const kindArgs = []; for (const name of node.varExps) { const kindArg = this.createTypeVar(); - env.add(name.text, new Forall([], [], kindArg), Symkind.Type); + env.add(name.text, Forall.mono(kindArg), Symkind.Type); kindArgs.push(kindArg); } const type = TApp.build(new TNominal(node, node), kindArgs); - parentEnv.add(node.name.text, new Forall(typeVars, constraints, type), Symkind.Type); + parentEnv.add(node.name.text, new Forall(typeVars, new CMany(constraints), type), Symkind.Type); let elementTypes: Type[] = []; if (node.members !== null) { for (const member of node.members) { @@ -2076,7 +2247,7 @@ export class Checker { throw new Error(`Unexpected ${member}`); } // FIXME `typeVars` may contain too much irrelevant type variables - parentEnv.add(member.name.text, new Forall(typeVars, constraints, ctorType), Symkind.Var); + parentEnv.add(member.name.text, new Forall(typeVars, new CMany(constraints), ctorType), Symkind.Var); elementTypes.push(elementType); } } @@ -2100,11 +2271,11 @@ export class Checker { for (const varExpr of node.varExps) { const typeVar = this.createTypeVar(); kindArgs.push(typeVar); - env.add(varExpr.text, new Forall([], [], typeVar), Symkind.Type); + env.add(varExpr.text, Forall.mono(typeVar), Symkind.Type); } const type = this.inferTypeExpression(node.typeExpression); this.popContext(context); - const scheme = new Forall(typeVars, constraints, TApp.build(type, kindArgs)); + const scheme = new Forall(typeVars, new CMany(constraints), TApp.build(type, kindArgs)); parentEnv.add(node.name.text, scheme, Symkind.Type); break; } @@ -2124,7 +2295,7 @@ export class Checker { const kindArgs = []; for (const varExpr of node.varExps) { const kindArg = this.createTypeVar(); - env.add(varExpr.text, new Forall([], [], kindArg), Symkind.Type); + env.add(varExpr.text, Forall.mono(kindArg), Symkind.Type); kindArgs.push(kindArg); } let type: Type = new TNil(node); @@ -2134,7 +2305,7 @@ export class Checker { } } this.popContext(context); - parentEnv.add(node.name.text, new Forall(typeVars, constraints, TField.sort(type)), Symkind.Type); + parentEnv.add(node.name.text, new Forall(typeVars, new CMany(constraints), TField.sort(type)), Symkind.Type); //parentEnv.add(node.name.text, new Forall(typeVars, constraints, new TArrow(type, TApp.build(type, kindArgs))), Symkind.Var); break; } @@ -2189,24 +2360,27 @@ export class Checker { } const env = node.typeEnv!; - const inner: InferContext = { + const innerCtx: InferContext = { typeVars, constraints, env, returnType: null, }; - node.context = inner; + node.context = innerCtx; - this.contexts.push(inner); + this.contexts.push(innerCtx); const returnType = this.createTypeVar(); - inner.returnType = returnType; + innerCtx.returnType = returnType; - const paramTypes = node.params.map( - param => this.inferBindings(param.pattern, [], []) - ); + const paramTypes = node.params.map(param => { + const paramType = this.createTypeVar(); + this.inferBindings(param.pattern, paramType) + return paramType; + }); let type = TArrow.build(paramTypes, returnType, node); + if (node.typeAssert !== null) { this.addConstraint( new CEqual( @@ -2235,20 +2409,13 @@ export class Checker { if (node.parent!.kind !== SyntaxKind.InstanceDeclaration) { const scopeDecl = node.parent!.getScope().node; const outer = { - typeVars: inner.typeVars, - constraints: inner.constraints, + typeVars: innerCtx.typeVars, + constraints: innerCtx.constraints, env: scopeDecl.typeEnv!, returnType: null, }; this.contexts.push(outer) - let ty2; - if (node.pattern.kind === SyntaxKind.WrappedOperator) { - ty2 = this.createTypeVar(); - this.addBinding(node.pattern.operator.text, new Forall([], [], ty2), Symkind.Var); - } else { - ty2 = this.inferBindings(node.pattern, typeVars, constraints); - } - this.addConstraint(new CEqual(ty2, type, node)); + this.inferBindings(node.pattern, type, typeVars, constraints); this.contexts.pop(); } } @@ -2260,18 +2427,17 @@ export class Checker { if (element.kind === SyntaxKind.LetDeclaration && isFunctionDeclarationLike(element)) { if (!this.analyser.isReferencedInParentScope(element)) { - assert(element.pattern.kind === SyntaxKind.NamedPattern); - const scheme = this.lookup(element.pattern.name, Symkind.Var); + const scheme = this.lookup(element.name, Symkind.Var); assert(scheme !== null); this.instantiate(scheme, null); } } else { - const elementHasTypeEnv = hasTypeEnv(element); - if (elementHasTypeEnv) { + const shouldChangeTypeEnv = shouldChangeTypeEnvDuringVisit(element); + if (shouldChangeTypeEnv) { this.pushContext({ ...this.getContext(), env: element.typeEnv! }); } this.infer(element); - if(elementHasTypeEnv) { + if(shouldChangeTypeEnv) { this.contexts.pop(); } } @@ -2443,7 +2609,7 @@ export class Checker { left = find(left); right = find(right); - //console.log(`unify ${describeType(left)} ~ ${describeType(right)}`); + // console.log(`unify ${describeType(left)} @ ${left.node && left.node.constructor && left.node.constructor.name} ~ ${describeType(right)} @ ${right.node && right.node.constructor && right.node.constructor.name}`); const swap = () => { [right, left] = [left, right]; } @@ -2497,9 +2663,9 @@ export class Checker { // into a special chain. TypeBase.join(left, right); - if (left.node !== undefined) { - right.node = left.node; - } + // if (left.node !== null) { + // right.node = left.node; + // } return true; } @@ -2637,7 +2803,7 @@ export class Checker { } -function getVariadicMember(node: StructPattern) { +function getVariadicMember(node: StructPattern) {1713 for (const member of node.members) { if (member.kind === SyntaxKind.VariadicStructPatternElement) { return member; @@ -2653,10 +2819,9 @@ type HasTypeEnv | ModuleDeclaration | SourceFile -function hasTypeEnv(node: Syntax): node is HasTypeEnv { +function shouldChangeTypeEnvDuringVisit(node: Syntax): node is HasTypeEnv { return node.kind === SyntaxKind.ClassDeclaration || node.kind === SyntaxKind.InstanceDeclaration - || node.kind === SyntaxKind.LetDeclaration || node.kind === SyntaxKind.ModuleDeclaration || node.kind === SyntaxKind.SourceFile } diff --git a/src/cst.ts b/src/cst.ts index a141d7289..0161b5843 100644 --- a/src/cst.ts +++ b/src/cst.ts @@ -2,7 +2,7 @@ import type stream from "stream"; import path from "path" -import { assert, implementationLimitation, IndentWriter, JSONObject, JSONValue } from "./util"; +import { assert, implementationLimitation, IndentWriter, JSONObject, JSONValue, unreachable } from "./util"; import { isNodeWithScope, Scope } from "./scope" import { InferContext, Kind, KindEnv, Scheme, Type, TypeEnv } from "./checker" import { Emitter } from "./emitter"; @@ -1385,7 +1385,7 @@ export class NamedPattern extends SyntaxBase { public readonly kind = SyntaxKind.NamedPattern; public constructor( - public name: Identifier, + public name: Identifier | CustomOperator, ) { super(); } @@ -2654,7 +2654,7 @@ export class LetDeclaration extends SyntaxBase { public letKeyword: LetKeyword, public foreignKeyword: ForeignKeyword | null, public mutKeyword: MutKeyword | null, - public pattern: Pattern | WrappedOperator, + public pattern: Pattern, public params: Param[], public typeAssert: TypeAssert | null, public body: Body | null, @@ -2662,6 +2662,18 @@ export class LetDeclaration extends SyntaxBase { super(); } + public get name(): Identifier | CustomOperator { + switch (this.pattern.kind) { + case SyntaxKind.NamedPattern: + return this.pattern.name; + case SyntaxKind.NestedPattern: + assert(this.pattern.pattern.kind === SyntaxKind.NamedPattern); + return this.pattern.pattern.name; + default: + unreachable(); + } + } + public clone(): LetDeclaration { return new LetDeclaration( this.pubKeyword !== null ? this.pubKeyword.clone() : null, diff --git a/src/parser.ts b/src/parser.ts index 159169cf2..d5c9081eb 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -827,7 +827,7 @@ export class Parser { this.getToken() this.getToken(); this.getToken(); - pattern = new WrappedOperator(t1, t2, t3); + pattern = new NestedPattern(t1, new NamedPattern(t2), t3); } else { pattern = this.parsePattern(); } diff --git a/src/scope.ts b/src/scope.ts index 363285bde..7ad132a78 100644 --- a/src/scope.ts +++ b/src/scope.ts @@ -111,11 +111,7 @@ export class Scope { } } } else { - if (node.pattern.kind === SyntaxKind.WrappedOperator) { - this.add(node.pattern.operator.text, node, Symkind.Var); - } else { - this.scanPattern(node.pattern, node); - } + this.scanPattern(node.pattern, node); } break; } diff --git a/src/util.ts b/src/util.ts index bb50abae5..7706d0a93 100644 --- a/src/util.ts +++ b/src/util.ts @@ -1,9 +1,21 @@ import path from "path" import stream from "stream" +import { InspectOptions } from "util"; export const isDebug = true; +export const toStringTag = Symbol.for('nodejs.util.inspect.custom'); + +export type InspectFn = (value: any, options: InspectOptions) => string; + +export function isIterable(value: any): value is Iterable { + if (value === undefined || value === null) { + return false; + } + return typeof(value[Symbol.iterator]) === 'function'; +} + export function first(iter: Iterator): T | undefined { return iter.next().value; } @@ -76,6 +88,10 @@ export function implementationLimitation(test: boolean): asserts test { } } +export function unreachable(): never { + throw new Error(`Code that should never be executed was reached during operation.`); +} + export function assertNever(value: never): never { console.error(value); throw new Error(`Assertion failed. See the stack trace for more information.`); @@ -196,7 +212,7 @@ export class MultiMap { } } - public *[Symbol.iterator](): Iterable<[K, V]> { + public *[Symbol.iterator](): Iterator<[K, V]> { for (const [key, elements] of this.mapping) { for (const value of elements) { yield [key, value]; From 94c9e83d067d38f0999aa97f982c3b5dbe937733 Mon Sep 17 00:00:00 2001 From: Sam Vervaeck Date: Wed, 12 Apr 2023 21:39:06 +0200 Subject: [PATCH 07/10] Fix typo in diagnostic messages --- src/diagnostics.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/diagnostics.ts b/src/diagnostics.ts index d7f7ae8ac..70f90a7d4 100644 --- a/src/diagnostics.ts +++ b/src/diagnostics.ts @@ -361,17 +361,17 @@ export class ConsoleDiagnostics implements Diagnostics { this.writer.indent(); if (diagnostic.missing !== null) { this.writer.write(ANSI_FG_YELLOW + ANSI_BOLD + 'info: ' + ANSI_RESET); - this.writer.write(`field '${diagnostic.fieldName}' is missing in diagnostic construct\n\n`); + this.writer.write(`field '${diagnostic.fieldName}' is missing in this construct\n\n`); this.writer.write(printNode(diagnostic.missing) + '\n'); } if (diagnostic.present !== null) { this.writer.write(ANSI_FG_YELLOW + ANSI_BOLD + 'info: ' + ANSI_RESET); - this.writer.write(`field '${diagnostic.fieldName}' is required in diagnostic construct\n\n`); + this.writer.write(`field '${diagnostic.fieldName}' is required in this construct\n\n`); this.writer.write(printNode(diagnostic.present) + '\n'); } if (diagnostic.cause !== null) { this.writer.write(ANSI_FG_YELLOW + ANSI_BOLD + 'info: ' + ANSI_RESET); - this.writer.write(`because of a constraint on diagnostic node:\n\n`); + this.writer.write(`because of a constraint on this node:\n\n`); this.writer.write(printNode(diagnostic.cause) + '\n'); } this.writer.dedent(); From d19c64845d1a9a6dad97bb83edd9c81306798220 Mon Sep 17 00:00:00 2001 From: Sam Vervaeck Date: Wed, 12 Apr 2023 21:52:10 +0200 Subject: [PATCH 08/10] Add test regarding assignment and polymorphism --- src/test/type-inference.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/test/type-inference.md b/src/test/type-inference.md index 900568fde..e53bcc8e7 100644 --- a/src/test/type-inference.md +++ b/src/test/type-inference.md @@ -195,3 +195,17 @@ mod CD. let alpha: A.Foo ``` + +## A polymorphic function is properly generalized when assigned to a new variable + +``` +let id x = x +let id2 = id +let id3 = id + +id3 1 +id3 "bla" + +id2 1 +id2 "bla" +```` From 78ea550afd395db27c410b14fd93b3507a3ed396 Mon Sep 17 00:00:00 2001 From: Sam Vervaeck Date: Wed, 12 Apr 2023 21:59:33 +0200 Subject: [PATCH 09/10] Fix broken image link in README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a7b71519a..42bf14353 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ Bolt 💬 Got some questions or feedback? Just open an issue and we'll be glad to respond! -![sample code](https://github.com/boltlang/bolt/blob/master/preview-fac.png?raw=true) +![sample code](https://github.com/boltlang/bolt/blob/main/preview-fac.png?raw=true) Bolt is a new strictly-evaluated functional programming language in the making that aims to make writing complex applications dead-simple. It ships with some From 11bae0fed0d58eafebd863b4e3bf117176176cb1 Mon Sep 17 00:00:00 2001 From: Sam Vervaeck Date: Wed, 12 Apr 2023 22:01:39 +0200 Subject: [PATCH 10/10] Update dependencies --- package-lock.json | 229 +++++++++++++++++++++++----------------------- package.json | 14 +-- 2 files changed, 119 insertions(+), 124 deletions(-) diff --git a/package-lock.json b/package-lock.json index ff735ffdb..98679a65d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,36 +9,36 @@ "version": "0.0.1", "license": "MIT", "dependencies": { - "commander": "^9.4.0", + "commander": "^10.0.0", "source-map-support": "^0.5.21", - "tslib": "^2.4.0", + "tslib": "^2.5.0", "yagl": "^0.5.1" }, "bin": { "bolt": "lib/bin/bolt.js" }, "devDependencies": { - "@types/commonmark": "^0.27.5", - "@types/glob": "^8.0.0", - "@types/node": "^18.7.15", - "@types/yargs": "^17.0.12", + "@types/commonmark": "^0.27.6", + "@types/glob": "^8.1.0", + "@types/node": "^18.15.11", + "@types/yargs": "^17.0.24", "commonmark": "^0.30.0", - "glob": "^8.0.3" + "glob": "^10.0.0" } }, "node_modules/@types/commonmark": { - "version": "0.27.5", - "resolved": "https://registry.npmjs.org/@types/commonmark/-/commonmark-0.27.5.tgz", - "integrity": "sha512-vIqgmHyLsc8Or3EWLz6QkhI8/v61FNeH0yxRupA7VqSbA2eFMoHHJAhZSHudplAV89wqg1CKSmShE016ziRXuw==", + "version": "0.27.6", + "resolved": "https://registry.npmjs.org/@types/commonmark/-/commonmark-0.27.6.tgz", + "integrity": "sha512-t3S2hOtSSuBp1H5PTFmekGFu9U9LBzGvHy93zHwusvj4RIGUrBQ4zHvw49CkJtAl6fZvsadKhYbv8WTxJLbBmw==", "dev": true }, "node_modules/@types/glob": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-8.0.0.tgz", - "integrity": "sha512-l6NQsDDyQUVeoTynNpC9uRvCUint/gSUXQA2euwmTuWGvPY5LSDUu6tkCtJB2SvGQlJQzLaKqcGZP4//7EDveA==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-IO+MJPVhoqz+28h1qLAcBEH2+xHMK6MTyHJc7MTnnYb6wsoLR29POVGJ7LycmVXIqyy/4/2ShP5sUwTXuOwb/w==", "dev": true, "dependencies": { - "@types/minimatch": "*", + "@types/minimatch": "^5.1.2", "@types/node": "*" } }, @@ -49,15 +49,15 @@ "dev": true }, "node_modules/@types/node": { - "version": "18.7.15", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.15.tgz", - "integrity": "sha512-XnjpaI8Bgc3eBag2Aw4t2Uj/49lLBSStHWfqKvIuXD7FIrZyMLWp8KuAFHAqxMZYTF9l08N1ctUn9YNybZJVmQ==", + "version": "18.15.11", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.11.tgz", + "integrity": "sha512-E5Kwq2n4SbMzQOn6wnmBjuK9ouqlURrcZDVfbo9ftDDTFt3nk7ZKK4GMOzoYgnpQJKcxwQw+lGaBvvlMo0qN/Q==", "dev": true }, "node_modules/@types/yargs": { - "version": "17.0.12", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.12.tgz", - "integrity": "sha512-Nz4MPhecOFArtm81gFQvQqdV7XYCrWKx5uUt6GNHredFHn1i2mtWqXTON7EPXMtNi1qjtjEM/VCHDhcHsAMLXQ==", + "version": "17.0.24", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz", + "integrity": "sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw==", "dev": true, "dependencies": { "@types/yargs-parser": "*" @@ -90,11 +90,11 @@ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" }, "node_modules/commander": { - "version": "9.4.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-9.4.0.tgz", - "integrity": "sha512-sRPT+umqkz90UA8M1yqYfnHlZA7fF6nSphDtxeywPZ49ysjxDQybzk13CL+mXekDRG92skbcqCLVovuCusNmFw==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.0.tgz", + "integrity": "sha512-zS5PnTI22FIRM6ylNW8G4Ap0IEOyk62fhLSD0+uHRT9McRCLGpkVNvao4bjimpK/GShynyQkFFxHhwMcETmduA==", "engines": { - "node": "^12.20.0 || >=14" + "node": ">=14" } }, "node_modules/commonmark": { @@ -128,40 +128,32 @@ "dev": true }, "node_modules/glob": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.0.3.tgz", - "integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.0.0.tgz", + "integrity": "sha512-zmp9ZDC6NpDNLujV2W2n+3lH+BafIVZ4/ct+Yj3BMZTH/+bgm/eVjHzeFLwxJrrIGgjjS2eiQLlpurHsNlEAtQ==", "dev": true, "dependencies": { "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" + "minimatch": "^9.0.0", + "minipass": "^5.0.0", + "path-scurry": "^1.6.4" }, "engines": { - "node": ">=12" + "node": ">=16 || 14 >=14.17" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "node_modules/lru-cache": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-9.0.1.tgz", + "integrity": "sha512-C8QsKIN1UIXeOs3iWmiZ1lQY+EnKDojWd37fXy1aSbJvH4iSma1uy2OWuoB3m4SYRli5+CUjDv3Dij5DVoetmg==", "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" + "engines": { + "node": "14 || >=16.14" } }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, "node_modules/mdurl": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", @@ -169,15 +161,18 @@ "dev": true }, "node_modules/minimatch": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", - "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.0.tgz", + "integrity": "sha512-0jJj8AvgKqWN05mrwuqi8QYKx1WmYSUoKSxu5Qhs9prezTz10sxAHGNZe9J9cqIJzta8DWsleh2KaVaLl6Ru2w==", "dev": true, "dependencies": { "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=10" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/minimist": { @@ -186,13 +181,29 @@ "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", "dev": true }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-scurry": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.6.4.tgz", + "integrity": "sha512-Qp/9IHkdNiXJ3/Kon++At2nVpnhRiPq/aSvQN+H3U1WZbvNRK0RIQK/o4HMqPoXjpuGJUEWpHSs6Mnjxqh3TQg==", "dev": true, "dependencies": { - "wrappy": "1" + "lru-cache": "^9.0.0", + "minipass": "^5.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/source-map": { @@ -219,15 +230,9 @@ "dev": true }, "node_modules/tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/yagl": { "version": "0.5.1", @@ -237,18 +242,18 @@ }, "dependencies": { "@types/commonmark": { - "version": "0.27.5", - "resolved": "https://registry.npmjs.org/@types/commonmark/-/commonmark-0.27.5.tgz", - "integrity": "sha512-vIqgmHyLsc8Or3EWLz6QkhI8/v61FNeH0yxRupA7VqSbA2eFMoHHJAhZSHudplAV89wqg1CKSmShE016ziRXuw==", + "version": "0.27.6", + "resolved": "https://registry.npmjs.org/@types/commonmark/-/commonmark-0.27.6.tgz", + "integrity": "sha512-t3S2hOtSSuBp1H5PTFmekGFu9U9LBzGvHy93zHwusvj4RIGUrBQ4zHvw49CkJtAl6fZvsadKhYbv8WTxJLbBmw==", "dev": true }, "@types/glob": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-8.0.0.tgz", - "integrity": "sha512-l6NQsDDyQUVeoTynNpC9uRvCUint/gSUXQA2euwmTuWGvPY5LSDUu6tkCtJB2SvGQlJQzLaKqcGZP4//7EDveA==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-IO+MJPVhoqz+28h1qLAcBEH2+xHMK6MTyHJc7MTnnYb6wsoLR29POVGJ7LycmVXIqyy/4/2ShP5sUwTXuOwb/w==", "dev": true, "requires": { - "@types/minimatch": "*", + "@types/minimatch": "^5.1.2", "@types/node": "*" } }, @@ -259,15 +264,15 @@ "dev": true }, "@types/node": { - "version": "18.7.15", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.15.tgz", - "integrity": "sha512-XnjpaI8Bgc3eBag2Aw4t2Uj/49lLBSStHWfqKvIuXD7FIrZyMLWp8KuAFHAqxMZYTF9l08N1ctUn9YNybZJVmQ==", + "version": "18.15.11", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.11.tgz", + "integrity": "sha512-E5Kwq2n4SbMzQOn6wnmBjuK9ouqlURrcZDVfbo9ftDDTFt3nk7ZKK4GMOzoYgnpQJKcxwQw+lGaBvvlMo0qN/Q==", "dev": true }, "@types/yargs": { - "version": "17.0.12", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.12.tgz", - "integrity": "sha512-Nz4MPhecOFArtm81gFQvQqdV7XYCrWKx5uUt6GNHredFHn1i2mtWqXTON7EPXMtNi1qjtjEM/VCHDhcHsAMLXQ==", + "version": "17.0.24", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz", + "integrity": "sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw==", "dev": true, "requires": { "@types/yargs-parser": "*" @@ -300,9 +305,9 @@ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" }, "commander": { - "version": "9.4.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-9.4.0.tgz", - "integrity": "sha512-sRPT+umqkz90UA8M1yqYfnHlZA7fF6nSphDtxeywPZ49ysjxDQybzk13CL+mXekDRG92skbcqCLVovuCusNmFw==" + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.0.tgz", + "integrity": "sha512-zS5PnTI22FIRM6ylNW8G4Ap0IEOyk62fhLSD0+uHRT9McRCLGpkVNvao4bjimpK/GShynyQkFFxHhwMcETmduA==" }, "commonmark": { "version": "0.30.0", @@ -329,32 +334,21 @@ "dev": true }, "glob": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.0.3.tgz", - "integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.0.0.tgz", + "integrity": "sha512-zmp9ZDC6NpDNLujV2W2n+3lH+BafIVZ4/ct+Yj3BMZTH/+bgm/eVjHzeFLwxJrrIGgjjS2eiQLlpurHsNlEAtQ==", "dev": true, "requires": { "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" + "minimatch": "^9.0.0", + "minipass": "^5.0.0", + "path-scurry": "^1.6.4" } }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "lru-cache": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-9.0.1.tgz", + "integrity": "sha512-C8QsKIN1UIXeOs3iWmiZ1lQY+EnKDojWd37fXy1aSbJvH4iSma1uy2OWuoB3m4SYRli5+CUjDv3Dij5DVoetmg==", "dev": true }, "mdurl": { @@ -364,9 +358,9 @@ "dev": true }, "minimatch": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", - "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.0.tgz", + "integrity": "sha512-0jJj8AvgKqWN05mrwuqi8QYKx1WmYSUoKSxu5Qhs9prezTz10sxAHGNZe9J9cqIJzta8DWsleh2KaVaLl6Ru2w==", "dev": true, "requires": { "brace-expansion": "^2.0.1" @@ -378,13 +372,20 @@ "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", "dev": true }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true + }, + "path-scurry": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.6.4.tgz", + "integrity": "sha512-Qp/9IHkdNiXJ3/Kon++At2nVpnhRiPq/aSvQN+H3U1WZbvNRK0RIQK/o4HMqPoXjpuGJUEWpHSs6Mnjxqh3TQg==", "dev": true, "requires": { - "wrappy": "1" + "lru-cache": "^9.0.0", + "minipass": "^5.0.0" } }, "source-map": { @@ -408,15 +409,9 @@ "dev": true }, "tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "yagl": { "version": "0.5.1", diff --git a/package.json b/package.json index 6874b81c7..7b55a400c 100644 --- a/package.json +++ b/package.json @@ -22,17 +22,17 @@ "author": "Sam Vervaeck", "license": "MIT", "dependencies": { - "commander": "^9.4.0", + "commander": "^10.0.0", "source-map-support": "^0.5.21", - "tslib": "^2.4.0", + "tslib": "^2.5.0", "yagl": "^0.5.1" }, "devDependencies": { - "@types/commonmark": "^0.27.5", - "@types/glob": "^8.0.0", - "@types/node": "^18.7.15", - "@types/yargs": "^17.0.12", + "@types/commonmark": "^0.27.6", + "@types/glob": "^8.1.0", + "@types/node": "^18.15.11", + "@types/yargs": "^17.0.24", "commonmark": "^0.30.0", - "glob": "^8.0.3" + "glob": "^10.0.0" } }