diff --git a/src/interpreter/index.ts b/src/interpreter/index.ts index 9f2f26ae..299f3269 100644 --- a/src/interpreter/index.ts +++ b/src/interpreter/index.ts @@ -179,7 +179,7 @@ export class Interpreter { for (const node of script) { switch (node.type) { case 'ns': { - await this.collectNsMember(node); + await this.collectNsMember(node, this.scope); break; } @@ -191,10 +191,11 @@ export class Interpreter { } @autobind - private async collectNsMember(ns: Ast.Namespace): Promise { - const scope = this.scope.createChildScope(); + private async collectNsMember(nsNode: Ast.Namespace, parentScope: Scope, parentPrefix?: string): Promise { + const scope = parentScope.createChildScope(); + const prefix = (parentPrefix ?? '') + nsNode.name + ':'; - for (const node of ns.members) { + for (const node of nsNode.members) { switch (node.type) { case 'def': { if (node.mut) { @@ -207,12 +208,13 @@ export class Interpreter { }; scope.add(node.name, variable); - this.scope.add(ns.name + ':' + node.name, variable); + this.scope.add(prefix + node.name, variable); break; } case 'ns': { - break; // TODO + this.collectNsMember(node, scope, prefix); + break; } default: { diff --git a/test/index.ts b/test/index.ts index 5d4634e9..518ee6ee 100644 --- a/test/index.ts +++ b/test/index.ts @@ -1858,6 +1858,21 @@ describe('namespace', () => { eq(res, STR('kawaii')); }); + test.concurrent('recursive', async () => { + const res = await exe(` + <: Foo:Bar:baz() + + :: Foo { + let ai = 'aichan' + :: Bar { + let kawa = 'kawaii' + @baz() { \`{ai} {kawa}\` } + } + } + `); + eq(res, STR('aichan kawaii')); + }); + test.concurrent('cannot declare mutable variable', async () => { try { await exe(`