lang: ast: Allow multiple star imports
If more than one star import is present in the same scope, allow it. If one star import could overwrite something, ordering is not guaranteed. We allow this for now, but we might create a compiler fix to stop it. This adds a test to notice both of these behaviours.
This commit is contained in:
@@ -3791,7 +3791,7 @@ func (obj *StmtProg) SetScope(scope *interfaces.Scope) error {
|
|||||||
}
|
}
|
||||||
newName = name
|
newName = name
|
||||||
}
|
}
|
||||||
if previous, exists := newVariables[newName]; exists {
|
if previous, exists := newVariables[newName]; exists && alias != interfaces.BareSymbol {
|
||||||
// don't overwrite in same scope
|
// don't overwrite in same scope
|
||||||
return fmt.Errorf("can't squash variable `%s` from `%s` by import of `%s`", newName, previous, imp.Name)
|
return fmt.Errorf("can't squash variable `%s` from `%s` by import of `%s`", newName, previous, imp.Name)
|
||||||
}
|
}
|
||||||
@@ -3806,7 +3806,7 @@ func (obj *StmtProg) SetScope(scope *interfaces.Scope) error {
|
|||||||
}
|
}
|
||||||
newName = name
|
newName = name
|
||||||
}
|
}
|
||||||
if previous, exists := newFunctions[newName]; exists {
|
if previous, exists := newFunctions[newName]; exists && alias != interfaces.BareSymbol {
|
||||||
// don't overwrite in same scope
|
// don't overwrite in same scope
|
||||||
return fmt.Errorf("can't squash function `%s` from `%s` by import of `%s`", newName, previous, imp.Name)
|
return fmt.Errorf("can't squash function `%s` from `%s` by import of `%s`", newName, previous, imp.Name)
|
||||||
}
|
}
|
||||||
@@ -3821,7 +3821,7 @@ func (obj *StmtProg) SetScope(scope *interfaces.Scope) error {
|
|||||||
}
|
}
|
||||||
newName = name
|
newName = name
|
||||||
}
|
}
|
||||||
if previous, exists := newClasses[newName]; exists {
|
if previous, exists := newClasses[newName]; exists && alias != interfaces.BareSymbol {
|
||||||
// don't overwrite in same scope
|
// don't overwrite in same scope
|
||||||
return fmt.Errorf("can't squash class `%s` from `%s` by import of `%s`", newName, previous, imp.Name)
|
return fmt.Errorf("can't squash class `%s` from `%s` by import of `%s`", newName, previous, imp.Name)
|
||||||
}
|
}
|
||||||
@@ -3831,7 +3831,9 @@ func (obj *StmtProg) SetScope(scope *interfaces.Scope) error {
|
|||||||
|
|
||||||
// everything has been merged, move on to next import...
|
// everything has been merged, move on to next import...
|
||||||
imports[imp.Name] = struct{}{} // mark as found in scope
|
imports[imp.Name] = struct{}{} // mark as found in scope
|
||||||
aliases[alias] = struct{}{}
|
if alias != interfaces.BareSymbol {
|
||||||
|
aliases[alias] = struct{}{}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: this could be called once at the top-level, and then cached...
|
// TODO: this could be called once at the top-level, and then cached...
|
||||||
@@ -4105,7 +4107,7 @@ func (obj *StmtProg) SetScope(scope *interfaces.Scope) error {
|
|||||||
}
|
}
|
||||||
newName = name
|
newName = name
|
||||||
}
|
}
|
||||||
if previous, exists := newVariables[newName]; exists {
|
if previous, exists := newVariables[newName]; exists && alias != interfaces.BareSymbol {
|
||||||
// don't overwrite in same scope
|
// don't overwrite in same scope
|
||||||
return fmt.Errorf("can't squash variable `%s` from `%s` by include of `%s`", newName, previous, include.Name)
|
return fmt.Errorf("can't squash variable `%s` from `%s` by include of `%s`", newName, previous, include.Name)
|
||||||
}
|
}
|
||||||
@@ -4120,7 +4122,7 @@ func (obj *StmtProg) SetScope(scope *interfaces.Scope) error {
|
|||||||
}
|
}
|
||||||
newName = name
|
newName = name
|
||||||
}
|
}
|
||||||
if previous, exists := newFunctions[newName]; exists {
|
if previous, exists := newFunctions[newName]; exists && alias != interfaces.BareSymbol {
|
||||||
// don't overwrite in same scope
|
// don't overwrite in same scope
|
||||||
return fmt.Errorf("can't squash function `%s` from `%s` by include of `%s`", newName, previous, include.Name)
|
return fmt.Errorf("can't squash function `%s` from `%s` by include of `%s`", newName, previous, include.Name)
|
||||||
}
|
}
|
||||||
@@ -4135,7 +4137,7 @@ func (obj *StmtProg) SetScope(scope *interfaces.Scope) error {
|
|||||||
}
|
}
|
||||||
newName = name
|
newName = name
|
||||||
}
|
}
|
||||||
if previous, exists := newClasses[newName]; exists {
|
if previous, exists := newClasses[newName]; exists && alias != interfaces.BareSymbol {
|
||||||
// don't overwrite in same scope
|
// don't overwrite in same scope
|
||||||
return fmt.Errorf("can't squash class `%s` from `%s` by include of `%s`", newName, previous, include.Name)
|
return fmt.Errorf("can't squash class `%s` from `%s` by include of `%s`", newName, previous, include.Name)
|
||||||
}
|
}
|
||||||
@@ -4145,7 +4147,9 @@ func (obj *StmtProg) SetScope(scope *interfaces.Scope) error {
|
|||||||
|
|
||||||
// everything has been merged, move on to next include...
|
// everything has been merged, move on to next include...
|
||||||
//includes[include.Name] = struct{}{} // don't mark as found in scope
|
//includes[include.Name] = struct{}{} // don't mark as found in scope
|
||||||
aliases[alias] = struct{}{} // do track these as a bonus
|
if alias != interfaces.BareSymbol { // XXX: check if this one and the above ones in this collection are needed too
|
||||||
|
aliases[alias] = struct{}{} // do track these as a bonus
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
-- metadata.yaml --
|
||||||
|
#files: "files/" # these are some extra files we can use (is the default)
|
||||||
|
-- main.mcl --
|
||||||
|
# XXX: When using multiple star imports, a subsequent one may overwrite the
|
||||||
|
# earlier one. We should probably make this a compile error.
|
||||||
|
import "foo.mcl" as *
|
||||||
|
import "bar.mcl" as *
|
||||||
|
|
||||||
|
include foo("hello")
|
||||||
|
include foo("world")
|
||||||
|
-- foo.mcl --
|
||||||
|
class foo($s) {
|
||||||
|
test "foo:${s}" {}
|
||||||
|
}
|
||||||
|
-- bar.mcl --
|
||||||
|
class foo($s) {
|
||||||
|
test "bar:${s}" {}
|
||||||
|
}
|
||||||
|
-- OUTPUT --
|
||||||
|
Vertex: test[bar:hello]
|
||||||
|
Vertex: test[bar:world]
|
||||||
19
lang/interpret_test/TestAstFunc2/import-double-star.txtar
Normal file
19
lang/interpret_test/TestAstFunc2/import-double-star.txtar
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
-- metadata.yaml --
|
||||||
|
#files: "files/" # these are some extra files we can use (is the default)
|
||||||
|
-- main.mcl --
|
||||||
|
import "foo.mcl" as *
|
||||||
|
import "bar.mcl" as *
|
||||||
|
|
||||||
|
include foo("hello")
|
||||||
|
include bar("world")
|
||||||
|
-- foo.mcl --
|
||||||
|
class foo($s) {
|
||||||
|
test "${s}" {}
|
||||||
|
}
|
||||||
|
-- bar.mcl --
|
||||||
|
class bar($s) {
|
||||||
|
test "${s}" {}
|
||||||
|
}
|
||||||
|
-- OUTPUT --
|
||||||
|
Vertex: test[hello]
|
||||||
|
Vertex: test[world]
|
||||||
Reference in New Issue
Block a user