diff --git a/examples/lang/panic0.mcl b/examples/lang/panic0.mcl index e5bbc116..c544f2e2 100644 --- a/examples/lang/panic0.mcl +++ b/examples/lang/panic0.mcl @@ -12,7 +12,6 @@ test "test" { } # this is what we're simulating: -#$_panic1 = panic("whatever1") # this is a function -#_panic $_panic1 {} # this is a resource -#$_panic2 = panic("whatever2") -#_panic $_panic2 {} +#if panic("whatever1") { # this is a function (and an if statement) +# _panic "panic" {} # this is a resource +#} diff --git a/lang/ast/structs.go b/lang/ast/structs.go index f9991aea..76827541 100644 --- a/lang/ast/structs.go +++ b/lang/ast/structs.go @@ -291,8 +291,6 @@ type StmtRes struct { Name interfaces.Expr // unique name for the res of this kind namePtr interfaces.Func // ptr for table lookup Contents []StmtResContents // list of fields/edges in parsed order - - allowUnderscores bool // secret flag to bypass some validation } // String returns a short representation of this statement. @@ -321,10 +319,7 @@ func (obj *StmtRes) Apply(fn func(interfaces.Node) error) error { // Init initializes this branch of the AST, and returns an error if it fails to // validate. func (obj *StmtRes) Init(data *interfaces.Data) error { - - isPanic := obj.allowUnderscores && obj.Kind == interfaces.PanicResKind - - if strings.Contains(obj.Kind, "_") && !isPanic { + if strings.Contains(obj.Kind, "_") && obj.Kind != interfaces.PanicResKind { return fmt.Errorf("kind must not contain underscores") } @@ -384,11 +379,10 @@ func (obj *StmtRes) Interpolate() (interfaces.Stmt, error) { } return &StmtRes{ - data: obj.data, - Kind: obj.Kind, - Name: name, - Contents: contents, - allowUnderscores: obj.allowUnderscores, + data: obj.data, + Kind: obj.Kind, + Name: name, + Contents: contents, }, nil } @@ -425,11 +419,10 @@ func (obj *StmtRes) Copy() (interfaces.Stmt, error) { return obj, nil } return &StmtRes{ - data: obj.data, - Kind: obj.Kind, - Name: name, - Contents: contents, - allowUnderscores: obj.allowUnderscores, + data: obj.data, + Kind: obj.Kind, + Name: name, + Contents: contents, }, nil } @@ -2840,8 +2833,6 @@ type StmtProg struct { importProgs []*StmtProg // list of child programs after running SetScope importFiles []string // list of files seen during the SetScope import - panicCounter uint // number of possible different panics - Body []interfaces.Stmt } @@ -2896,36 +2887,6 @@ func (obj *StmtProg) Interpolate() (interfaces.Stmt, error) { return nil, err } body = append(body, interpolated) - - // If we have the magic bind statement, then add the res. - // NOTE: We could have used a custom StmtPanic instead here... - if bind, ok := interpolated.(*StmtBind); ok && bind.Ident == interfaces.PanicVarName { - // TODO: does it still work if we have multiple StmtProg's? - obj.panicCounter++ - name := fmt.Sprintf("%s%d", interfaces.PanicVarName, obj.panicCounter) - bind.Ident = name // change name to magic name - exprVar := &ExprVar{ - Name: name, // use magic name to match - - allowUnderscores: true, // allow our magic name - } - if err := exprVar.Init(obj.data); err != nil { - return nil, errwrap.Wrapf(err, "special panic ExprVar Init error during interpolate") - } - stmtRes := &StmtRes{ - Kind: interfaces.PanicResKind, // special resource kind - Name: exprVar, - Contents: []StmtResContents{}, - - allowUnderscores: true, // allow our magic kind - } - if err := stmtRes.Init(obj.data); err != nil { - return nil, errwrap.Wrapf(err, "special panic StmtRes Init error during interpolate") - } - - body = append(body, stmtRes) - continue - } } return &StmtProg{ data: obj.data, @@ -8289,8 +8250,6 @@ type ExprVar struct { typ *types.Type Name string // name of the variable - - allowUnderscores bool // secret flag to bypass some validation } // String returns a short representation of this expression. @@ -8306,9 +8265,6 @@ func (obj *ExprVar) Apply(fn func(interfaces.Node) error) error { return fn(obj) // Init initializes this branch of the AST, and returns an error if it fails to // validate. func (obj *ExprVar) Init(*interfaces.Data) error { - if obj.allowUnderscores && strings.HasPrefix(obj.Name, interfaces.PanicVarName) { - return nil - } return langutil.ValidateVarName(obj.Name) } @@ -8319,10 +8275,9 @@ func (obj *ExprVar) Init(*interfaces.Data) error { // support variable, variables or anything crazy like that. func (obj *ExprVar) Interpolate() (interfaces.Expr, error) { return &ExprVar{ - scope: obj.scope, - typ: obj.typ, - Name: obj.Name, - allowUnderscores: obj.allowUnderscores, + scope: obj.scope, + typ: obj.typ, + Name: obj.Name, }, nil } @@ -8333,10 +8288,9 @@ func (obj *ExprVar) Interpolate() (interfaces.Expr, error) { // and they won't be able to have different values. func (obj *ExprVar) Copy() (interfaces.Expr, error) { return &ExprVar{ - scope: obj.scope, - typ: obj.typ, - Name: obj.Name, - allowUnderscores: obj.allowUnderscores, + scope: obj.scope, + typ: obj.typ, + Name: obj.Name, }, nil } diff --git a/lang/funcs/core/panic_func.go b/lang/funcs/core/panic_func.go index a79c863b..f037f87d 100644 --- a/lang/funcs/core/panic_func.go +++ b/lang/funcs/core/panic_func.go @@ -26,21 +26,18 @@ import ( func init() { simple.Register("panic", &types.FuncValue{ - T: types.NewType("func(x str) str"), + T: types.NewType("func(x str) bool"), V: Panic, }) } // Panic returns an error when it receives a non-empty string. The error should -// cause the function engine to shutdown. +// cause the function engine to shutdown. If there's no error, it returns false. func Panic(input []types.Value) (types.Value, error) { if s := input[0].Str(); s != "" { - // This StrValue not really used here, since we error... - return &types.StrValue{ - V: s, - }, fmt.Errorf("panic occurred: %s", s) + return nil, fmt.Errorf("panic occurred: %s", s) } - return &types.StrValue{ - V: "panic", // name can't be empty + return &types.BoolValue{ + V: false, }, nil } diff --git a/lang/interfaces/const.go b/lang/interfaces/const.go index 7026ca4e..f7f73700 100644 --- a/lang/interfaces/const.go +++ b/lang/interfaces/const.go @@ -28,7 +28,4 @@ const ( // PanicResKind is the kind string used for the panic resource. PanicResKind = "_panic" - - // PanicVarName is the magic name used for the panic output var. - PanicVarName = "_panic" ) diff --git a/lang/interpret_test/TestAstFunc2/panic0.txtar b/lang/interpret_test/TestAstFunc2/panic0.txtar index 6235f0e0..9effebda 100644 --- a/lang/interpret_test/TestAstFunc2/panic0.txtar +++ b/lang/interpret_test/TestAstFunc2/panic0.txtar @@ -2,5 +2,5 @@ # This should not panic. panic("") panic("") +# Empty graph, no output. -- OUTPUT -- -Vertex: _panic[panic] diff --git a/lang/interpret_test/TestAstFunc2/panic1.txtar b/lang/interpret_test/TestAstFunc2/panic1.txtar index 946a03cc..9cfb87d3 100644 --- a/lang/interpret_test/TestAstFunc2/panic1.txtar +++ b/lang/interpret_test/TestAstFunc2/panic1.txtar @@ -3,5 +3,4 @@ panic("") test "hello" {} -- OUTPUT -- -Vertex: _panic[panic] Vertex: test[hello] diff --git a/lang/parser/parser.y b/lang/parser/parser.y index 1a7e7062..91215a57 100644 --- a/lang/parser/parser.y +++ b/lang/parser/parser.y @@ -927,17 +927,30 @@ bind: ; panic: // panic("some error") + // generates: + // if panic("some error") { + // _panic "_panic" {} # resource + //} PANIC_IDENTIFIER OPEN_PAREN call_args CLOSE_PAREN { posLast(yylex, yyDollar) // our pos call := &ast.ExprCall{ - Name: $1.str, + Name: $1.str, // the function name Args: $3.exprs, //Var: false, // default } - $$.stmt = &ast.StmtBind{ - Ident: interfaces.PanicVarName, // make up a placeholder var - Value: call, + name := &ast.ExprStr{ + V: $1.str, // any constant, non-empty name + } + res := &ast.StmtRes{ + Kind: interfaces.PanicResKind, + Name: name, + Contents: []ast.StmtResContents{}, + } + $$.stmt = &ast.StmtIf{ + Condition: call, + ThenBranch: res, + //ElseBranch: nil, } } ;