diff --git a/docs/docs.md b/docs/docs.md index b8abf236a..43ff841a4 100644 --- a/docs/docs.md +++ b/docs/docs.md @@ -2049,8 +2049,7 @@ print random() ### Main module. Only the main module can have top-level statements that aren't static declarations. -If an imported module contains top-level statements, they are ignored. -In the future, it may result in a compile error instead: +An imported module containing top-level statements returns an error: ```cy -- main.cy use a 'foo.cy' @@ -2059,11 +2058,7 @@ print a.foo -- foo.cy use 'bar.cy' var .foo = 123 -print foo -- Statement is ignored. - --- bar.cy -var .bar = 321 -print bar -- Statement is ignored. +print foo -- Error: Top-level statement not allowed. ``` ### Circular imports. diff --git a/src/compiler.zig b/src/compiler.zig index d9ae95fee..4105e9c21 100644 --- a/src/compiler.zig +++ b/src/compiler.zig @@ -935,6 +935,31 @@ fn reserveSyms(self: *Compiler, core_sym: *cy.sym.Chunk) !void{ self.sema.list_tmpl = core.getSym("List").?.cast(.template); self.sema.table_type = core.getSym("Table").?.cast(.object_t); } + if (chunk != self.main_chunk) { + // Check for illegal top level statements. + if (chunk.parser.staticDecls.items.len != chunk.ast.root.?.stmts.len) { + for (chunk.ast.root.?.stmts) |stmt| { + switch (stmt.type()) { + .context_decl, + .custom_decl, + .distinct_decl, + .enumDecl, + .funcDecl, + .import_stmt, + .objectDecl, + .specialization, + .staticDecl, + .structDecl, + .table_decl, + .typeAliasDecl, + .template => {}, + else => { + return chunk.reportError("Top level statement is not allowed from imported module.", @ptrCast(stmt)); + } + } + } + } + } } // Check for import tasks. diff --git a/test/behavior_test.zig b/test/behavior_test.zig index 66a2b0452..bc63bc592 100644 --- a/test/behavior_test.zig +++ b/test/behavior_test.zig @@ -219,6 +219,7 @@ if (!aot) { run.case2(Config.initFileModules("./test/modules/import_missing_sym_error.cy").withSilent(), "modules/import_missing_sym_error.cy"); run.case2(Config.initFileModules("./test/modules/import_rel_path.cy"), "modules/import_rel_path.cy"); run.case2(Config.initFileModules("./test/modules/import_implied_rel_path.cy"), "modules/import_implied_rel_path.cy"); + run.case2(Config.initFileModules("./test/modules/import_stmt_error.cy"), "modules/import_stmt_error.cy"); run.case2(Config.initFileModules("./test/modules/import_unresolved_rel_path.cy"), "modules/import_unresolved_rel_path.cy"); // Import when running main script in the cwd. diff --git a/test/modules/import_stmt_error.cy b/test/modules/import_stmt_error.cy new file mode 100644 index 000000000..7ccc6aacb --- /dev/null +++ b/test/modules/import_stmt_error.cy @@ -0,0 +1,9 @@ +use a './test_mods/stmt_error.cy' + +--cytest: error +--CompileError: Top level statement is not allowed from imported module. +-- +--@AbsPath(test/modules/test_mods/stmt_error.cy):1:1: +--print 123 +--^ +-- \ No newline at end of file diff --git a/test/modules/test_mods/a.cy b/test/modules/test_mods/a.cy index 71fe2fcbd..4337c9cd6 100644 --- a/test/modules/test_mods/a.cy +++ b/test/modules/test_mods/a.cy @@ -22,9 +22,6 @@ func fn2(a int, b int): func barNoExport(): return 234 --- Test that there is no main block execution for imported modules. -panic(.ExecutedModuleMain) - func toInt(val any) int: return int(val) diff --git a/test/modules/test_mods/stmt_error.cy b/test/modules/test_mods/stmt_error.cy new file mode 100644 index 000000000..b82330390 --- /dev/null +++ b/test/modules/test_mods/stmt_error.cy @@ -0,0 +1 @@ +print 123 \ No newline at end of file