Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions tslang/include/TypeScript/MLIRLogic/MLIRGenStore.h
Original file line number Diff line number Diff line change
Expand Up @@ -1270,6 +1270,9 @@ struct NamespaceInfo

bool isFunctionNamespace;

// `import * as M`: M has nothing in it, its names are the module's, which are at the top level
bool isModuleImport = false;

NamespaceInfo::TypePtr parentNamespace;
};

Expand Down
17 changes: 7 additions & 10 deletions tslang/lib/TypeScript/MLIRGenAccessCall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -341,16 +341,13 @@ namespace mlirgen
assert(namespaceInfo);

MLIRNamespaceGuard ng(currentNamespace);
currentNamespace = namespaceInfo;

// `ns.value` names the namespace's member: look there before the local scope,
// which resolved it to a local variable `value` of the calling function.
if (auto member = resolveIdentifierInNamespace(location, name, genContext))
{
return member;
}

return V(mlirGen(location, name, genContext));
// `ns.value` names the namespace's member and nothing else: a local variable
// `value` of the calling function, or a `value` of an outer namespace, is not
// `ns.value`. A name the namespace hasn't got is the error below. The names of
// `import * as M` are the module's, declared at the top level (see
// mlirGenImportBindings).
currentNamespace = namespaceInfo->isModuleImport ? rootNamespace : namespaceInfo;
return resolveIdentifierInNamespace(location, name, genContext);
})
.Case<mlir_ts::ClassStorageType>([&](auto classStorageType) {
LLVM_DEBUG(llvm::dbgs() << "\n\t...field: \t" << cl.getName(););
Expand Down
1 change: 1 addition & 0 deletions tslang/lib/TypeScript/MLIRGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1678,6 +1678,7 @@ namespace mlirgen
auto namespaceName = MLIRHelper::getName(namedBindings.as<NamespaceImport>()->name, stringAllocator);
MLIRNamespaceGuard nsGuard(currentNamespace);
registerNamespace(namespaceName);
currentNamespace->isModuleImport = true;
return mlir::success();
}

Expand Down
14 changes: 14 additions & 0 deletions tslang/test/tester/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2947,6 +2947,20 @@ set_tests_properties(test-compile-diagnostic-location-implicit-constructor
PROPERTIES PASS_REGULAR_EXPRESSION "implicit_constructor\\.ts:9:1: error: Class constructor is not accessable"
FAIL_REGULAR_EXPRESSION "Stack dump|Assertion failed|implicit_constructor\\.ts:1:")

# `ns.name` is the namespace's member or an error: a local or an outer namespace's `name` isn't it.
foreach(namespace_member_case missing_member outer_member)
add_test(NAME test-compile-namespace-member-${namespace_member_case}
COMMAND $<TARGET_FILE:tslang> --emit=obj --no-default-lib -mm=none
"${PROJECT_SOURCE_DIR}/test/tester/namespace-member/${namespace_member_case}.ts"
-o "${CMAKE_CURRENT_BINARY_DIR}/namespace-member-${namespace_member_case}.obj")
endforeach()
set_tests_properties(test-compile-namespace-member-missing_member
PROPERTIES PASS_REGULAR_EXPRESSION "missing_member\\.ts:12:11: error: Can't resolve property 'missing' of type ns"
FAIL_REGULAR_EXPRESSION "Stack dump|Assertion failed")
set_tests_properties(test-compile-namespace-member-outer_member
PROPERTIES PASS_REGULAR_EXPRESSION "outer_member\\.ts:15:11: error: Can't resolve property 'outer' of type ns"
FAIL_REGULAR_EXPRESSION "Stack dump|Assertion failed")

# A call to the collector's API (GC_gcollect, or the weak-link functions DefaultLib's WeakRef uses)
# is an error under every model but gc, which alone links the collector - it used to reach the
# linker as an unresolved symbol. Under gc the same file compiles.
Expand Down
8 changes: 8 additions & 0 deletions tslang/test/tester/import-bindings/import_namespace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,12 @@ const b = new M.Box<number>(6);
assert(b.v == 6);
assert(M.identity<number>(7) == 7);

// M.ANSWER is the module's, whatever a local ANSWER is
function shadowed() {
const ANSWER = 1;
assert(M.ANSWER == 42);
assert(ANSWER == 1);
}
shadowed();

print("done.");
13 changes: 13 additions & 0 deletions tslang/test/tester/namespace-member/missing_member.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// `ns.missing` is an error when the namespace has no `missing`, even with a local `missing` in
// scope: it used to fall back to the general lookup, which found the local.

namespace ns {
export function value(): int {
return 42;
}
}

function main() {
const missing = 5;
print(ns.missing);
}
16 changes: 16 additions & 0 deletions tslang/test/tester/namespace-member/outer_member.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// `ns.outer()` is an error when only the root namespace has an `outer`: the general lookup the
// access fell back to also searched the outer namespaces.

function outer(): int {
return 1;
}

namespace ns {
export function value(): int {
return 42;
}
}

function main() {
print(ns.outer());
}
19 changes: 19 additions & 0 deletions tslang/test/tester/tests/00ns_member_shadowed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,26 @@ namespace ns {
}
}

// a member declared after its use, and one in a second block of the same namespace
function early(): int {
return ns2.later() + ns2.second();
}

namespace ns2 {
export function later(): int {
return 1;
}
}

namespace ns2 {
export function second(): int {
return 2;
}
}

function main() {
assert(early() == 3);

const value = ns.value();
assert(value == 42);
assert(ns.value() == 42);
Expand Down
Loading