lang: Print a clear message on module import containing unused stmt
If you run an import, you only include everything that's part of a scope. This includes, variables, classes, and functions. Anything else should cause a compile error. This cleans up the error by adding a String() method to each Stmt in our AST.
This commit is contained in:
@@ -40,6 +40,7 @@ type Node interface {
|
|||||||
// expression.)
|
// expression.)
|
||||||
type Stmt interface {
|
type Stmt interface {
|
||||||
Node
|
Node
|
||||||
|
fmt.Stringer // String() string
|
||||||
Init(*Data) error // initialize the populated node and validate
|
Init(*Data) error // initialize the populated node and validate
|
||||||
Interpolate() (Stmt, error) // return expanded form of AST as a new AST
|
Interpolate() (Stmt, error) // return expanded form of AST as a new AST
|
||||||
SetScope(*Scope) error // set the scope here and propagate it downwards
|
SetScope(*Scope) error // set the scope here and propagate it downwards
|
||||||
@@ -54,6 +55,7 @@ type Stmt interface {
|
|||||||
// these can be stored as pointers in our graph data structure.
|
// these can be stored as pointers in our graph data structure.
|
||||||
type Expr interface {
|
type Expr interface {
|
||||||
Node
|
Node
|
||||||
|
//fmt.Stringer // already provided by pgraph.Vertex
|
||||||
pgraph.Vertex // must implement this since we store these in our graphs
|
pgraph.Vertex // must implement this since we store these in our graphs
|
||||||
Init(*Data) error // initialize the populated node and validate
|
Init(*Data) error // initialize the populated node and validate
|
||||||
Interpolate() (Expr, error) // return expanded form of AST as a new AST
|
Interpolate() (Expr, error) // return expanded form of AST as a new AST
|
||||||
|
|||||||
1
lang/interpret_test/TestAstFunc1/unused1.graph
Normal file
1
lang/interpret_test/TestAstFunc1/unused1.graph
Normal file
@@ -0,0 +1 @@
|
|||||||
|
# err: import scope `something.mcl` failed: local import of `something.mcl` failed: module contains unused statements: found stmt: res(print)
|
||||||
7
lang/interpret_test/TestAstFunc1/unused1/main.mcl
Normal file
7
lang/interpret_test/TestAstFunc1/unused1/main.mcl
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
import "fmt"
|
||||||
|
import "something.mcl"
|
||||||
|
|
||||||
|
include something.someclass
|
||||||
|
print "p1" {
|
||||||
|
msg => fmt.printf("someint: %d", $something.someint),
|
||||||
|
}
|
||||||
11
lang/interpret_test/TestAstFunc1/unused1/something.mcl
Normal file
11
lang/interpret_test/TestAstFunc1/unused1/something.mcl
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
$someint = 42
|
||||||
|
class someclass {
|
||||||
|
print "p2" {
|
||||||
|
msg => "i'm inside of someclass",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# this should generate a compile error
|
||||||
|
print "unused" {
|
||||||
|
msg => "i'm unused because i'm inside an imported module",
|
||||||
|
}
|
||||||
@@ -90,6 +90,11 @@ func (obj *StmtBind) Apply(fn func(interfaces.Node) error) error {
|
|||||||
return fn(obj)
|
return fn(obj)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// String returns a short representation of this statement.
|
||||||
|
func (obj *StmtBind) String() string {
|
||||||
|
return fmt.Sprintf("bind(%s)", obj.Ident)
|
||||||
|
}
|
||||||
|
|
||||||
// Init initializes this branch of the AST, and returns an error if it fails to
|
// Init initializes this branch of the AST, and returns an error if it fails to
|
||||||
// validate.
|
// validate.
|
||||||
func (obj *StmtBind) Init(data *interfaces.Data) error {
|
func (obj *StmtBind) Init(data *interfaces.Data) error {
|
||||||
@@ -181,6 +186,11 @@ func (obj *StmtRes) Apply(fn func(interfaces.Node) error) error {
|
|||||||
return fn(obj)
|
return fn(obj)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// String returns a short representation of this statement.
|
||||||
|
func (obj *StmtRes) String() string {
|
||||||
|
return fmt.Sprintf("res(%s)", obj.Kind)
|
||||||
|
}
|
||||||
|
|
||||||
// Init initializes this branch of the AST, and returns an error if it fails to
|
// Init initializes this branch of the AST, and returns an error if it fails to
|
||||||
// validate.
|
// validate.
|
||||||
func (obj *StmtRes) Init(data *interfaces.Data) error {
|
func (obj *StmtRes) Init(data *interfaces.Data) error {
|
||||||
@@ -1406,6 +1416,11 @@ func (obj *StmtEdge) Apply(fn func(interfaces.Node) error) error {
|
|||||||
return fn(obj)
|
return fn(obj)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// String returns a short representation of this statement.
|
||||||
|
func (obj *StmtEdge) String() string {
|
||||||
|
return "edge" // TODO: improve this
|
||||||
|
}
|
||||||
|
|
||||||
// Init initializes this branch of the AST, and returns an error if it fails to
|
// Init initializes this branch of the AST, and returns an error if it fails to
|
||||||
// validate.
|
// validate.
|
||||||
func (obj *StmtEdge) Init(data *interfaces.Data) error {
|
func (obj *StmtEdge) Init(data *interfaces.Data) error {
|
||||||
@@ -1731,6 +1746,11 @@ func (obj *StmtIf) Apply(fn func(interfaces.Node) error) error {
|
|||||||
return fn(obj)
|
return fn(obj)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// String returns a short representation of this statement.
|
||||||
|
func (obj *StmtIf) String() string {
|
||||||
|
return "if" // TODO: improve this
|
||||||
|
}
|
||||||
|
|
||||||
// Init initializes this branch of the AST, and returns an error if it fails to
|
// Init initializes this branch of the AST, and returns an error if it fails to
|
||||||
// validate.
|
// validate.
|
||||||
func (obj *StmtIf) Init(data *interfaces.Data) error {
|
func (obj *StmtIf) Init(data *interfaces.Data) error {
|
||||||
@@ -1948,6 +1968,11 @@ func (obj *StmtProg) Apply(fn func(interfaces.Node) error) error {
|
|||||||
return fn(obj)
|
return fn(obj)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// String returns a short representation of this statement.
|
||||||
|
func (obj *StmtProg) String() string {
|
||||||
|
return "prog" // TODO: improve this
|
||||||
|
}
|
||||||
|
|
||||||
// Init initializes this branch of the AST, and returns an error if it fails to
|
// Init initializes this branch of the AST, and returns an error if it fails to
|
||||||
// validate.
|
// validate.
|
||||||
func (obj *StmtProg) Init(data *interfaces.Data) error {
|
func (obj *StmtProg) Init(data *interfaces.Data) error {
|
||||||
@@ -2678,8 +2703,8 @@ func (obj *StmtProg) IsModuleUnsafe() error { // TODO: rename this function?
|
|||||||
case *StmtComment: // possibly not even parsed
|
case *StmtComment: // possibly not even parsed
|
||||||
// all of these are safe
|
// all of these are safe
|
||||||
default:
|
default:
|
||||||
// something else unsafe
|
// something else unsafe (unused)
|
||||||
return fmt.Errorf("found unsafe stmt: %v", x)
|
return fmt.Errorf("found stmt: %s", x.String())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@@ -2706,6 +2731,11 @@ func (obj *StmtFunc) Apply(fn func(interfaces.Node) error) error {
|
|||||||
return fn(obj)
|
return fn(obj)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// String returns a short representation of this statement.
|
||||||
|
func (obj *StmtFunc) String() string {
|
||||||
|
return fmt.Sprintf("func(%s)", obj.Name)
|
||||||
|
}
|
||||||
|
|
||||||
// Init initializes this branch of the AST, and returns an error if it fails to
|
// Init initializes this branch of the AST, and returns an error if it fails to
|
||||||
// validate.
|
// validate.
|
||||||
func (obj *StmtFunc) Init(data *interfaces.Data) error {
|
func (obj *StmtFunc) Init(data *interfaces.Data) error {
|
||||||
@@ -2787,6 +2817,11 @@ func (obj *StmtClass) Apply(fn func(interfaces.Node) error) error {
|
|||||||
return fn(obj)
|
return fn(obj)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// String returns a short representation of this statement.
|
||||||
|
func (obj *StmtClass) String() string {
|
||||||
|
return fmt.Sprintf("class(%s)", obj.Name)
|
||||||
|
}
|
||||||
|
|
||||||
// Init initializes this branch of the AST, and returns an error if it fails to
|
// Init initializes this branch of the AST, and returns an error if it fails to
|
||||||
// validate.
|
// validate.
|
||||||
func (obj *StmtClass) Init(data *interfaces.Data) error {
|
func (obj *StmtClass) Init(data *interfaces.Data) error {
|
||||||
@@ -2879,6 +2914,11 @@ func (obj *StmtInclude) Apply(fn func(interfaces.Node) error) error {
|
|||||||
return fn(obj)
|
return fn(obj)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// String returns a short representation of this statement.
|
||||||
|
func (obj *StmtInclude) String() string {
|
||||||
|
return fmt.Sprintf("include(%s)", obj.Name)
|
||||||
|
}
|
||||||
|
|
||||||
// Init initializes this branch of the AST, and returns an error if it fails to
|
// Init initializes this branch of the AST, and returns an error if it fails to
|
||||||
// validate.
|
// validate.
|
||||||
func (obj *StmtInclude) Init(data *interfaces.Data) error {
|
func (obj *StmtInclude) Init(data *interfaces.Data) error {
|
||||||
@@ -3089,6 +3129,11 @@ type StmtImport struct {
|
|||||||
// a select number of node types, since they won't need extra noop iterators...
|
// a select number of node types, since they won't need extra noop iterators...
|
||||||
func (obj *StmtImport) Apply(fn func(interfaces.Node) error) error { return fn(obj) }
|
func (obj *StmtImport) Apply(fn func(interfaces.Node) error) error { return fn(obj) }
|
||||||
|
|
||||||
|
// String returns a short representation of this statement.
|
||||||
|
func (obj *StmtImport) String() string {
|
||||||
|
return fmt.Sprintf("import(%s)", obj.Name)
|
||||||
|
}
|
||||||
|
|
||||||
// Init initializes this branch of the AST, and returns an error if it fails to
|
// Init initializes this branch of the AST, and returns an error if it fails to
|
||||||
// validate.
|
// validate.
|
||||||
func (obj *StmtImport) Init(*interfaces.Data) error { return nil }
|
func (obj *StmtImport) Init(*interfaces.Data) error { return nil }
|
||||||
@@ -3155,6 +3200,11 @@ type StmtComment struct {
|
|||||||
// a select number of node types, since they won't need extra noop iterators...
|
// a select number of node types, since they won't need extra noop iterators...
|
||||||
func (obj *StmtComment) Apply(fn func(interfaces.Node) error) error { return fn(obj) }
|
func (obj *StmtComment) Apply(fn func(interfaces.Node) error) error { return fn(obj) }
|
||||||
|
|
||||||
|
// String returns a short representation of this statement.
|
||||||
|
func (obj *StmtComment) String() string {
|
||||||
|
return fmt.Sprintf("comment(%s)", obj.Value)
|
||||||
|
}
|
||||||
|
|
||||||
// Init initializes this branch of the AST, and returns an error if it fails to
|
// Init initializes this branch of the AST, and returns an error if it fails to
|
||||||
// validate.
|
// validate.
|
||||||
func (obj *StmtComment) Init(*interfaces.Data) error {
|
func (obj *StmtComment) Init(*interfaces.Data) error {
|
||||||
|
|||||||
Reference in New Issue
Block a user