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.)
|
||||
type Stmt interface {
|
||||
Node
|
||||
fmt.Stringer // String() string
|
||||
Init(*Data) error // initialize the populated node and validate
|
||||
Interpolate() (Stmt, error) // return expanded form of AST as a new AST
|
||||
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.
|
||||
type Expr interface {
|
||||
Node
|
||||
//fmt.Stringer // already provided by pgraph.Vertex
|
||||
pgraph.Vertex // must implement this since we store these in our graphs
|
||||
Init(*Data) error // initialize the populated node and validate
|
||||
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)
|
||||
}
|
||||
|
||||
// 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
|
||||
// validate.
|
||||
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)
|
||||
}
|
||||
|
||||
// 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
|
||||
// validate.
|
||||
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)
|
||||
}
|
||||
|
||||
// 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
|
||||
// validate.
|
||||
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)
|
||||
}
|
||||
|
||||
// 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
|
||||
// validate.
|
||||
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)
|
||||
}
|
||||
|
||||
// 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
|
||||
// validate.
|
||||
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
|
||||
// all of these are safe
|
||||
default:
|
||||
// something else unsafe
|
||||
return fmt.Errorf("found unsafe stmt: %v", x)
|
||||
// something else unsafe (unused)
|
||||
return fmt.Errorf("found stmt: %s", x.String())
|
||||
}
|
||||
}
|
||||
return nil
|
||||
@@ -2706,6 +2731,11 @@ func (obj *StmtFunc) Apply(fn func(interfaces.Node) error) error {
|
||||
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
|
||||
// validate.
|
||||
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)
|
||||
}
|
||||
|
||||
// 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
|
||||
// validate.
|
||||
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)
|
||||
}
|
||||
|
||||
// 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
|
||||
// validate.
|
||||
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...
|
||||
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
|
||||
// validate.
|
||||
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...
|
||||
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
|
||||
// validate.
|
||||
func (obj *StmtComment) Init(*interfaces.Data) error {
|
||||
|
||||
Reference in New Issue
Block a user