Merge pull request #863 from larsclausen/export
Add support for package export
This commit is contained in:
commit
4643f57edb
|
|
@ -24,6 +24,7 @@
|
||||||
# include "LineInfo.h"
|
# include "LineInfo.h"
|
||||||
# include "StringHeap.h"
|
# include "StringHeap.h"
|
||||||
# include <iostream>
|
# include <iostream>
|
||||||
|
# include <vector>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* SystemVerilog supports class declarations with their own lexical
|
* SystemVerilog supports class declarations with their own lexical
|
||||||
|
|
@ -42,6 +43,13 @@ class PPackage : public PScopeExtra, public LineInfo {
|
||||||
bool elaborate(Design*des, NetScope*scope) const;
|
bool elaborate(Design*des, NetScope*scope) const;
|
||||||
|
|
||||||
void pform_dump(std::ostream&out) const;
|
void pform_dump(std::ostream&out) const;
|
||||||
|
|
||||||
|
struct export_t {
|
||||||
|
PPackage *pkg;
|
||||||
|
perm_string name;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<export_t> exports;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* IVL_PPackage_H */
|
#endif /* IVL_PPackage_H */
|
||||||
|
|
|
||||||
10
PScope.h
10
PScope.h
|
|
@ -25,6 +25,7 @@
|
||||||
# include "ivl_target.h"
|
# include "ivl_target.h"
|
||||||
# include <map>
|
# include <map>
|
||||||
# include <set>
|
# include <set>
|
||||||
|
# include <unordered_set>
|
||||||
# include <vector>
|
# include <vector>
|
||||||
|
|
||||||
class PEvent;
|
class PEvent;
|
||||||
|
|
@ -67,9 +68,14 @@ class LexicalScope {
|
||||||
// Symbols that are defined or declared in this scope.
|
// Symbols that are defined or declared in this scope.
|
||||||
std::map<perm_string,PNamedItem*>local_symbols;
|
std::map<perm_string,PNamedItem*>local_symbols;
|
||||||
|
|
||||||
// Symbols that are explicitly imported. Bind the imported name
|
// Symbols that are explicitly imported. This contains the package where
|
||||||
// to the package from which the name is imported.
|
// the symbol has been decelared. When using exports, this might not be
|
||||||
|
// the same as the package where it has been imported from.
|
||||||
std::map<perm_string,PPackage*>explicit_imports;
|
std::map<perm_string,PPackage*>explicit_imports;
|
||||||
|
// Symbols that are explicitly imported. This contains the set of
|
||||||
|
// packages from which the symbol has been imported. When using exports
|
||||||
|
// the same identifier can be imported via multiple packages.
|
||||||
|
std::map<perm_string,std::unordered_set<PPackage*>> explicit_imports_from;
|
||||||
|
|
||||||
// Packages that are wildcard imported. When identifiers from
|
// Packages that are wildcard imported. When identifiers from
|
||||||
// these packages are referenced, they will be added to the
|
// these packages are referenced, they will be added to the
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
// Check that it is possible to explicitly export an identifier and import it
|
||||||
|
// from another scope.
|
||||||
|
|
||||||
|
package P1;
|
||||||
|
integer x = 123;
|
||||||
|
endpackage
|
||||||
|
|
||||||
|
package P2;
|
||||||
|
import P1::x;
|
||||||
|
export P1::x;
|
||||||
|
endpackage
|
||||||
|
|
||||||
|
module test;
|
||||||
|
|
||||||
|
import P2::x;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
if (x == 123) begin
|
||||||
|
$display("PASSED");
|
||||||
|
end else begin
|
||||||
|
$display("FAILED");
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
// Check that it is possible use package wildcard export an identifier and
|
||||||
|
// import it from another scope.
|
||||||
|
|
||||||
|
package P1;
|
||||||
|
integer x = 123;
|
||||||
|
endpackage
|
||||||
|
|
||||||
|
package P2;
|
||||||
|
import P1::x;
|
||||||
|
export P1::*;
|
||||||
|
endpackage
|
||||||
|
|
||||||
|
module test;
|
||||||
|
|
||||||
|
import P2::x;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
if (x == 123) begin
|
||||||
|
$display("PASSED");
|
||||||
|
end else begin
|
||||||
|
$display("FAILED");
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
// Check that it is possible use full wildcard export an identifier and import
|
||||||
|
// it from another scope.
|
||||||
|
|
||||||
|
package P1;
|
||||||
|
integer x = 123;
|
||||||
|
endpackage
|
||||||
|
|
||||||
|
package P2;
|
||||||
|
import P1::x;
|
||||||
|
export *::*;
|
||||||
|
endpackage
|
||||||
|
|
||||||
|
module test;
|
||||||
|
|
||||||
|
import P2::x;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
if (x == 123) begin
|
||||||
|
$display("PASSED");
|
||||||
|
end else begin
|
||||||
|
$display("FAILED");
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
// Check that it is possible to export an implicitly imported identifier and
|
||||||
|
// import it again from another scope.
|
||||||
|
|
||||||
|
package P1;
|
||||||
|
integer x = 123;
|
||||||
|
endpackage
|
||||||
|
|
||||||
|
package P2;
|
||||||
|
import P1::*;
|
||||||
|
export P1::x;
|
||||||
|
endpackage
|
||||||
|
|
||||||
|
module test;
|
||||||
|
|
||||||
|
import P2::x;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
if (x == 123) begin
|
||||||
|
$display("PASSED");
|
||||||
|
end else begin
|
||||||
|
$display("FAILED");
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
// Check that implicitly imported identifiers can be exported through a package
|
||||||
|
// wildcard export.
|
||||||
|
|
||||||
|
package P1;
|
||||||
|
integer x = 123;
|
||||||
|
endpackage
|
||||||
|
|
||||||
|
package P2;
|
||||||
|
import P1::*;
|
||||||
|
export P1::*;
|
||||||
|
integer y = x; // Creates an import for P1::x
|
||||||
|
endpackage
|
||||||
|
|
||||||
|
module test;
|
||||||
|
|
||||||
|
import P2::x;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
if (x == 123) begin
|
||||||
|
$display("PASSED");
|
||||||
|
end else begin
|
||||||
|
$display("FAILED");
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
// Check that it is possible to implicitly import the same identifier through
|
||||||
|
// multiple paths without causing a conflict.
|
||||||
|
|
||||||
|
package P1;
|
||||||
|
integer x = 123;
|
||||||
|
endpackage
|
||||||
|
|
||||||
|
package P2;
|
||||||
|
import P1::x;
|
||||||
|
export P1::x;
|
||||||
|
endpackage
|
||||||
|
|
||||||
|
module test;
|
||||||
|
|
||||||
|
// P1::x is visible through either of the imports below. This should not
|
||||||
|
// create a conflict since it is the same identifier.
|
||||||
|
import P1::*;
|
||||||
|
import P2::*;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
if (x == 123) begin
|
||||||
|
$display("PASSED");
|
||||||
|
end else begin
|
||||||
|
$display("FAILED");
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
// Check that it is an error to export an identifier from a package from which
|
||||||
|
// it has not been imported from.
|
||||||
|
|
||||||
|
package P1;
|
||||||
|
integer x;
|
||||||
|
endpackage
|
||||||
|
|
||||||
|
package P2;
|
||||||
|
import P1::x;
|
||||||
|
export P1::x;
|
||||||
|
endpackage
|
||||||
|
|
||||||
|
package P3;
|
||||||
|
import P1::x;
|
||||||
|
export P2::x; // This should fail, even though P2::x is the same as P1::x
|
||||||
|
endpackage
|
||||||
|
|
||||||
|
module test;
|
||||||
|
initial begin
|
||||||
|
$display("FAILED");
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
// Check that it is an error to export an identifier that has not been imported.
|
||||||
|
|
||||||
|
package P1;
|
||||||
|
integer x;
|
||||||
|
integer y;
|
||||||
|
endpackage
|
||||||
|
|
||||||
|
package P2;
|
||||||
|
import P1::x;
|
||||||
|
export P1::y; // Should fail, P1::y has not been imported.
|
||||||
|
endpackage
|
||||||
|
|
||||||
|
module test;
|
||||||
|
initial begin
|
||||||
|
$display("FAILED");
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
// Check that an identifier importable through a wildcard import is not exported
|
||||||
|
// through a wildcard export if the identifier has not been referenced in
|
||||||
|
// package.
|
||||||
|
|
||||||
|
package P1;
|
||||||
|
integer x = 123;
|
||||||
|
endpackage
|
||||||
|
|
||||||
|
package P2;
|
||||||
|
import P1::*;
|
||||||
|
export *::*;
|
||||||
|
endpackage
|
||||||
|
|
||||||
|
module test;
|
||||||
|
|
||||||
|
import P2::x; // This should fail, P1::x is not referenced in P2 and hence not
|
||||||
|
// exportable through P2
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
$display("FAILED");
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
// Check that it is an error to export an identifier that is importable through
|
||||||
|
// a wildcard import if it creates a conflict with a local identifier.
|
||||||
|
|
||||||
|
package P1;
|
||||||
|
integer x = 123;
|
||||||
|
endpackage
|
||||||
|
|
||||||
|
package P2;
|
||||||
|
import P1::*;
|
||||||
|
integer x = 456;
|
||||||
|
export P1::x; // This should fail, P1::x can not be imported into this scope
|
||||||
|
// since the name already exists.
|
||||||
|
endpackage
|
||||||
|
|
||||||
|
module test;
|
||||||
|
|
||||||
|
import P2::x;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
$display("FAILED");
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
// Check that it is an error to export an identifier that is importable through
|
||||||
|
// a wildcard import if it creates a conflict with a local identifier, even if
|
||||||
|
// the local identifier is declared after the export.
|
||||||
|
|
||||||
|
package P1;
|
||||||
|
integer x = 123;
|
||||||
|
endpackage
|
||||||
|
|
||||||
|
package P2;
|
||||||
|
import P1::*;
|
||||||
|
export P1::x; // This should fail, P1::x can not be imported into this scope
|
||||||
|
// since the there is a local symbol with the same name. Even if
|
||||||
|
// it is declared after the export.
|
||||||
|
integer x = 456;
|
||||||
|
endpackage
|
||||||
|
|
||||||
|
module test;
|
||||||
|
|
||||||
|
import P2::x;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
$display("FAILED");
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
// Check that an error is reported if trying to export an identifier that is
|
||||||
|
// declared outside of a package
|
||||||
|
|
||||||
|
integer x = 123;
|
||||||
|
|
||||||
|
package P1;
|
||||||
|
endpackage
|
||||||
|
|
||||||
|
package P2;
|
||||||
|
import P1::*;
|
||||||
|
export P1::x; // This should fail. x is visible in P1, but not declared in P1
|
||||||
|
endpackage
|
||||||
|
|
||||||
|
module test;
|
||||||
|
|
||||||
|
import P2::x;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
$display("FAILED");
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -668,6 +668,18 @@ sv_end_labels normal,-g2009 ivltests
|
||||||
sv_end_labels_bad CE,-g2009 ivltests gold=sv_end_labels_bad.gold
|
sv_end_labels_bad CE,-g2009 ivltests gold=sv_end_labels_bad.gold
|
||||||
sv_end_labels_unnamed CE,-g2009 ivltests gold=sv_end_labels_unnamed.gold
|
sv_end_labels_unnamed CE,-g2009 ivltests gold=sv_end_labels_unnamed.gold
|
||||||
sv_enum1 normal,-g2009 ivltests
|
sv_enum1 normal,-g2009 ivltests
|
||||||
|
sv_export1 normal,-g2009 ivltests
|
||||||
|
sv_export2 normal,-g2009 ivltests
|
||||||
|
sv_export3 normal,-g2009 ivltests
|
||||||
|
sv_export4 normal,-g2009 ivltests
|
||||||
|
sv_export5 normal,-g2009 ivltests
|
||||||
|
sv_export6 normal,-g2009 ivltests
|
||||||
|
sv_export_fail1 CE,-g2009 ivltests
|
||||||
|
sv_export_fail2 CE,-g2009 ivltests
|
||||||
|
sv_export_fail3 CE,-g2009 ivltests
|
||||||
|
sv_export_fail4 CE,-g2009 ivltests
|
||||||
|
sv_export_fail5 CE,-g2009 ivltests
|
||||||
|
sv_export_fail6 CE,-g2009 ivltests
|
||||||
sv_for_variable normal,-g2009 ivltests
|
sv_for_variable normal,-g2009 ivltests
|
||||||
sv_foreach1 normal,-g2009 ivltests
|
sv_foreach1 normal,-g2009 ivltests
|
||||||
sv_foreach2 normal,-g2009 ivltests
|
sv_foreach2 normal,-g2009 ivltests
|
||||||
|
|
|
||||||
25
parse.y
25
parse.y
|
|
@ -2053,6 +2053,30 @@ package_import_item_list
|
||||||
| package_import_item
|
| package_import_item
|
||||||
;
|
;
|
||||||
|
|
||||||
|
package_export_declaration /* IEEE1800-2017 A.2.1.3 */
|
||||||
|
: K_export package_export_item_list ';'
|
||||||
|
| K_export '*' K_SCOPE_RES '*' ';' { pform_package_export(@$, nullptr, nullptr); }
|
||||||
|
;
|
||||||
|
|
||||||
|
package_export_item
|
||||||
|
: PACKAGE_IDENTIFIER K_SCOPE_RES IDENTIFIER
|
||||||
|
{ pform_package_export(@2, $1, $3);
|
||||||
|
delete[] $3;
|
||||||
|
}
|
||||||
|
| PACKAGE_IDENTIFIER K_SCOPE_RES TYPE_IDENTIFIER
|
||||||
|
{ pform_package_export(@2, $1, $3.text);
|
||||||
|
delete[] $3.text;
|
||||||
|
}
|
||||||
|
| PACKAGE_IDENTIFIER K_SCOPE_RES '*'
|
||||||
|
{ pform_package_export(@2, $1, nullptr);
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
package_export_item_list
|
||||||
|
: package_export_item_list ',' package_export_item
|
||||||
|
| package_export_item
|
||||||
|
;
|
||||||
|
|
||||||
package_item /* IEEE1800-2005 A.1.10 */
|
package_item /* IEEE1800-2005 A.1.10 */
|
||||||
: timeunits_declaration
|
: timeunits_declaration
|
||||||
| parameter_declaration
|
| parameter_declaration
|
||||||
|
|
@ -2061,6 +2085,7 @@ package_item /* IEEE1800-2005 A.1.10 */
|
||||||
| task_declaration
|
| task_declaration
|
||||||
| data_declaration
|
| data_declaration
|
||||||
| class_declaration
|
| class_declaration
|
||||||
|
| package_export_declaration
|
||||||
;
|
;
|
||||||
|
|
||||||
package_item_list
|
package_item_list
|
||||||
|
|
|
||||||
39
pform.cc
39
pform.cc
|
|
@ -472,41 +472,6 @@ static void add_local_symbol(LexicalScope*scope, perm_string name, PNamedItem*it
|
||||||
scope->local_symbols[name] = item;
|
scope->local_symbols[name] = item;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PPackage*find_potential_import(const struct vlltype&loc, LexicalScope*scope,
|
|
||||||
perm_string name, bool tf_call, bool make_explicit)
|
|
||||||
{
|
|
||||||
assert(scope);
|
|
||||||
|
|
||||||
PPackage*found_pkg = 0;
|
|
||||||
for (list<PPackage*>::const_iterator cur_pkg = scope->potential_imports.begin();
|
|
||||||
cur_pkg != scope->potential_imports.end(); ++cur_pkg) {
|
|
||||||
PPackage*search_pkg = *cur_pkg;
|
|
||||||
map<perm_string,PNamedItem*>::const_iterator cur_sym
|
|
||||||
= search_pkg->local_symbols.find(name);
|
|
||||||
if (cur_sym != search_pkg->local_symbols.end()) {
|
|
||||||
if (found_pkg && make_explicit) {
|
|
||||||
cerr << loc.get_fileline() << ": error: "
|
|
||||||
"Ambiguous use of '" << name << "'. "
|
|
||||||
"It is exported by both '"
|
|
||||||
<< found_pkg->pscope_name()
|
|
||||||
<< "' and by '"
|
|
||||||
<< search_pkg->pscope_name()
|
|
||||||
<< "'." << endl;
|
|
||||||
error_count += 1;
|
|
||||||
} else {
|
|
||||||
found_pkg = search_pkg;
|
|
||||||
if (make_explicit) {
|
|
||||||
if (tf_call)
|
|
||||||
scope->possible_imports[name] = found_pkg;
|
|
||||||
else
|
|
||||||
scope->explicit_imports[name] = found_pkg;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return found_pkg;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void check_potential_imports(const struct vlltype&loc, perm_string name, bool tf_call)
|
static void check_potential_imports(const struct vlltype&loc, perm_string name, bool tf_call)
|
||||||
{
|
{
|
||||||
LexicalScope*scope = lexical_scope;
|
LexicalScope*scope = lexical_scope;
|
||||||
|
|
@ -515,7 +480,7 @@ static void check_potential_imports(const struct vlltype&loc, perm_string name,
|
||||||
return;
|
return;
|
||||||
if (scope->explicit_imports.find(name) != scope->explicit_imports.end())
|
if (scope->explicit_imports.find(name) != scope->explicit_imports.end())
|
||||||
return;
|
return;
|
||||||
if (find_potential_import(loc, scope, name, tf_call, true))
|
if (pform_find_potential_import(loc, scope, name, tf_call, true))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
scope = scope->parent_scope();
|
scope = scope->parent_scope();
|
||||||
|
|
@ -938,7 +903,7 @@ typedef_t* pform_test_type_identifier(const struct vlltype&loc, const char*txt)
|
||||||
if (cur != cur_scope->typedefs.end())
|
if (cur != cur_scope->typedefs.end())
|
||||||
return cur->second;
|
return cur->second;
|
||||||
|
|
||||||
PPackage*pkg = find_potential_import(loc, cur_scope, name, false, false);
|
PPackage*pkg = pform_find_potential_import(loc, cur_scope, name, false, false);
|
||||||
if (pkg) {
|
if (pkg) {
|
||||||
cur = pkg->typedefs.find(name);
|
cur = pkg->typedefs.find(name);
|
||||||
if (cur != pkg->typedefs.end())
|
if (cur != pkg->typedefs.end())
|
||||||
|
|
|
||||||
6
pform.h
6
pform.h
|
|
@ -203,6 +203,12 @@ extern void pform_start_package_declaration(const struct vlltype&loc,
|
||||||
extern void pform_end_package_declaration(const struct vlltype&loc);
|
extern void pform_end_package_declaration(const struct vlltype&loc);
|
||||||
extern void pform_package_import(const struct vlltype&loc,
|
extern void pform_package_import(const struct vlltype&loc,
|
||||||
PPackage*pkg, const char*ident);
|
PPackage*pkg, const char*ident);
|
||||||
|
extern void pform_package_export(const struct vlltype &loc, PPackage *pkg,
|
||||||
|
const char *ident);
|
||||||
|
PPackage *pform_package_importable(PPackage *pkg, perm_string name);
|
||||||
|
PPackage *pform_find_potential_import(const struct vlltype&loc, LexicalScope*scope,
|
||||||
|
perm_string name, bool tf_call, bool make_explicit);
|
||||||
|
|
||||||
|
|
||||||
extern PExpr* pform_package_ident(const struct vlltype&loc,
|
extern PExpr* pform_package_ident(const struct vlltype&loc,
|
||||||
PPackage*pkg, pform_name_t*ident);
|
PPackage*pkg, pform_name_t*ident);
|
||||||
|
|
|
||||||
108
pform_package.cc
108
pform_package.cc
|
|
@ -72,6 +72,64 @@ void pform_end_package_declaration(const struct vlltype&loc)
|
||||||
pform_pop_scope();
|
pform_pop_scope();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PPackage *pform_find_potential_import(const struct vlltype&loc, LexicalScope*scope,
|
||||||
|
perm_string name, bool tf_call, bool make_explicit)
|
||||||
|
{
|
||||||
|
assert(scope);
|
||||||
|
|
||||||
|
PPackage *found_pkg = nullptr;
|
||||||
|
for (auto search_pkg : scope->potential_imports) {
|
||||||
|
PPackage *decl_pkg = pform_package_importable(search_pkg, name);
|
||||||
|
if (!decl_pkg)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (found_pkg && found_pkg != decl_pkg && make_explicit) {
|
||||||
|
cerr << loc.get_fileline() << ": error: "
|
||||||
|
"Ambiguous use of '" << name << "'. "
|
||||||
|
"It is exported by both '"
|
||||||
|
<< found_pkg->pscope_name()
|
||||||
|
<< "' and by '"
|
||||||
|
<< search_pkg->pscope_name()
|
||||||
|
<< "'." << endl;
|
||||||
|
error_count++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
found_pkg = decl_pkg;
|
||||||
|
if (make_explicit) {
|
||||||
|
if (tf_call)
|
||||||
|
scope->possible_imports[name] = found_pkg;
|
||||||
|
else {
|
||||||
|
scope->explicit_imports[name] = found_pkg;
|
||||||
|
scope->explicit_imports_from[name].insert(search_pkg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return found_pkg;
|
||||||
|
}
|
||||||
|
|
||||||
|
PPackage *pform_package_importable(PPackage *pkg, perm_string name)
|
||||||
|
{
|
||||||
|
if (pkg->local_symbols.find(name) != pkg->local_symbols.end())
|
||||||
|
return pkg;
|
||||||
|
|
||||||
|
auto import_pkg = pkg->explicit_imports.find(name);
|
||||||
|
if (import_pkg == pkg->explicit_imports.end())
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
for (auto &exp : pkg->exports) {
|
||||||
|
// *::* will match all imports, P::* will match all imports
|
||||||
|
// from a package and P::ID will match a specific identifier
|
||||||
|
// from a package.
|
||||||
|
if ((!exp.pkg || exp.pkg == import_pkg->second) &&
|
||||||
|
(exp.name.nil() || exp.name == name))
|
||||||
|
return import_pkg->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Do the import early, during processing. This requires that the
|
* Do the import early, during processing. This requires that the
|
||||||
* package is declared in pform ahead of time (it is) and that we can
|
* package is declared in pform ahead of time (it is) and that we can
|
||||||
|
|
@ -85,9 +143,8 @@ void pform_package_import(const struct vlltype&loc, PPackage*pkg, const char*ide
|
||||||
perm_string use_ident = lex_strings.make(ident);
|
perm_string use_ident = lex_strings.make(ident);
|
||||||
|
|
||||||
// Check that the requested symbol is available.
|
// Check that the requested symbol is available.
|
||||||
map<perm_string,PNamedItem*>::const_iterator cur_sym
|
PPackage *pkg_decl = pform_package_importable(pkg, use_ident);
|
||||||
= pkg->local_symbols.find(use_ident);
|
if (!pkg_decl) {
|
||||||
if (cur_sym == pkg->local_symbols.end()) {
|
|
||||||
cerr << loc.get_fileline() << ": error: "
|
cerr << loc.get_fileline() << ": error: "
|
||||||
"'" << use_ident << "' is not exported by '"
|
"'" << use_ident << "' is not exported by '"
|
||||||
<< pkg->pscope_name() << "'." << endl;
|
<< pkg->pscope_name() << "'." << endl;
|
||||||
|
|
@ -96,7 +153,7 @@ void pform_package_import(const struct vlltype&loc, PPackage*pkg, const char*ide
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for conflict with local symbol.
|
// Check for conflict with local symbol.
|
||||||
cur_sym = scope->local_symbols.find(use_ident);
|
auto cur_sym = scope->local_symbols.find(use_ident);
|
||||||
if (cur_sym != scope->local_symbols.end()) {
|
if (cur_sym != scope->local_symbols.end()) {
|
||||||
cerr << loc.get_fileline() << ": error: "
|
cerr << loc.get_fileline() << ": error: "
|
||||||
"'" << use_ident << "' has already been declared "
|
"'" << use_ident << "' has already been declared "
|
||||||
|
|
@ -112,17 +169,17 @@ void pform_package_import(const struct vlltype&loc, PPackage*pkg, const char*ide
|
||||||
map<perm_string,PPackage*>::const_iterator cur_pkg
|
map<perm_string,PPackage*>::const_iterator cur_pkg
|
||||||
= scope->explicit_imports.find(use_ident);
|
= scope->explicit_imports.find(use_ident);
|
||||||
if (cur_pkg != scope->explicit_imports.end()) {
|
if (cur_pkg != scope->explicit_imports.end()) {
|
||||||
if (cur_pkg->second != pkg) {
|
if (cur_pkg->second != pkg_decl) {
|
||||||
cerr << loc.get_fileline() << ": error: "
|
cerr << loc.get_fileline() << ": error: "
|
||||||
"'" << use_ident << "' has already been "
|
"'" << use_ident << "' has already been "
|
||||||
"imported into this scope from package '"
|
"imported into this scope from package '"
|
||||||
<< cur_pkg->second->pscope_name() << "'." << endl;
|
<< cur_pkg->second->pscope_name() << "'." << endl;
|
||||||
error_count += 1;
|
error_count += 1;
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
scope->explicit_imports[use_ident] = pkg;
|
scope->explicit_imports[use_ident] = pkg_decl;
|
||||||
|
scope->explicit_imports_from[use_ident].insert(pkg);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
list<PPackage*>::const_iterator cur_pkg
|
list<PPackage*>::const_iterator cur_pkg
|
||||||
|
|
@ -134,6 +191,43 @@ void pform_package_import(const struct vlltype&loc, PPackage*pkg, const char*ide
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool pform_package_exportable(const struct vlltype &loc, PPackage *pkg,
|
||||||
|
const perm_string &ident)
|
||||||
|
{
|
||||||
|
auto import_pkg = pform_cur_package->explicit_imports_from.find(ident);
|
||||||
|
if (import_pkg != pform_cur_package->explicit_imports_from.end()) {
|
||||||
|
auto &pkg_list = import_pkg->second;
|
||||||
|
if (pkg_list.find(pkg) != pkg_list.end())
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pform_cur_package->local_symbols.find(ident) == pform_cur_package->local_symbols.end()) {
|
||||||
|
if (pform_find_potential_import(loc, pform_cur_package,
|
||||||
|
ident, false, true))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
cerr << loc.get_fileline() << ": error: "
|
||||||
|
"`" << ident << "` has not been imported from "
|
||||||
|
<< pkg->pscope_name() << "." << endl;
|
||||||
|
error_count++;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pform_package_export(const struct vlltype &loc, PPackage *pkg, const char *ident)
|
||||||
|
{
|
||||||
|
assert(pform_cur_package);
|
||||||
|
|
||||||
|
perm_string use_ident;
|
||||||
|
if (ident) {
|
||||||
|
use_ident = lex_strings.make(ident);
|
||||||
|
if (!pform_package_exportable(loc, pkg, use_ident))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pform_cur_package->exports.push_back(PPackage::export_t{pkg, use_ident});
|
||||||
|
}
|
||||||
|
|
||||||
PExpr* pform_package_ident(const struct vlltype&loc,
|
PExpr* pform_package_ident(const struct vlltype&loc,
|
||||||
PPackage*pkg, pform_name_t*ident_name)
|
PPackage*pkg, pform_name_t*ident_name)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue