diff --git a/lang/funcs/simple/simple.go b/lang/funcs/simple/simple.go index aab2ee94..f5b049f5 100644 --- a/lang/funcs/simple/simple.go +++ b/lang/funcs/simple/simple.go @@ -97,10 +97,15 @@ func (obj *WrappedFunc) Validate() error { // Info returns some static info about itself. func (obj *WrappedFunc) Info() *interfaces.Info { + var typ *types.Type + if obj.Fn != nil { // don't panic if called speculatively + typ = obj.Fn.Type() + } + return &interfaces.Info{ Pure: true, Memo: false, // TODO: should this be something we specify here? - Sig: obj.Fn.Type(), + Sig: typ, Err: obj.Validate(), } } diff --git a/lang/funcs/simplepoly/simplepoly.go b/lang/funcs/simplepoly/simplepoly.go index 24084254..5816d69f 100644 --- a/lang/funcs/simplepoly/simplepoly.go +++ b/lang/funcs/simplepoly/simplepoly.go @@ -218,14 +218,15 @@ func (obj *WrappedFunc) Validate() error { // Info returns some static info about itself. func (obj *WrappedFunc) Info() *interfaces.Info { - var sig *types.Type + var typ *types.Type if obj.fn != nil { // don't panic if called speculatively - sig = obj.fn.Type() + typ = obj.fn.Type() } + return &interfaces.Info{ Pure: true, Memo: false, // TODO: should this be something we specify here? - Sig: sig, + Sig: typ, Err: obj.Validate(), } } diff --git a/lang/funcs/structs/call.go b/lang/funcs/structs/call.go index 4dd0a599..03e40716 100644 --- a/lang/funcs/structs/call.go +++ b/lang/funcs/structs/call.go @@ -68,23 +68,26 @@ func (obj *CallFunc) Validate() error { // Info returns some static info about itself. func (obj *CallFunc) Info() *interfaces.Info { - typ := &types.Type{ - Kind: types.KindFunc, // function type - Map: make(map[string]*types.Type), - Ord: []string{}, - Out: obj.Type, // this is the output type for the expression - } + var typ *types.Type + if obj.Type != nil { // don't panic if called speculatively + typ = &types.Type{ + Kind: types.KindFunc, // function type + Map: make(map[string]*types.Type), + Ord: []string{}, + Out: obj.Type, // this is the output type for the expression + } - sig := obj.FuncType - if obj.Edge != "" { - typ.Map[obj.Edge] = sig // we get a function in - typ.Ord = append(typ.Ord, obj.Edge) - } + sig := obj.FuncType + if obj.Edge != "" { + typ.Map[obj.Edge] = sig // we get a function in + typ.Ord = append(typ.Ord, obj.Edge) + } - // add any incoming args - for _, key := range sig.Ord { // sig.Out, not sig! - typ.Map[key] = sig.Map[key] - typ.Ord = append(typ.Ord, key) + // add any incoming args + for _, key := range sig.Ord { // sig.Out, not sig! + typ.Map[key] = sig.Map[key] + typ.Ord = append(typ.Ord, key) + } } return &interfaces.Info{ diff --git a/lang/funcs/structs/const.go b/lang/funcs/structs/const.go index 407dcb9c..f93e8f29 100644 --- a/lang/funcs/structs/const.go +++ b/lang/funcs/structs/const.go @@ -42,10 +42,16 @@ func (obj *ConstFunc) Validate() error { // Info returns some static info about itself. func (obj *ConstFunc) Info() *interfaces.Info { + var typ *types.Type + if obj.Value != nil { // don't panic if called speculatively + if t := obj.Value.Type(); t != nil { + typ = types.NewType(fmt.Sprintf("func() %s", t.String())) + } + } return &interfaces.Info{ Pure: true, Memo: false, // TODO: ??? - Sig: types.NewType(fmt.Sprintf("func() %s", obj.Value.Type().String())), + Sig: typ, Err: obj.Validate(), // XXX: implement this and check .Err in engine! } } diff --git a/lang/funcs/structs/function.go b/lang/funcs/structs/function.go index 2e0b9b87..3064a188 100644 --- a/lang/funcs/structs/function.go +++ b/lang/funcs/structs/function.go @@ -82,17 +82,20 @@ func (obj *FunctionFunc) Validate() error { // Info returns some static info about itself. func (obj *FunctionFunc) Info() *interfaces.Info { - typ := &types.Type{ - Kind: types.KindFunc, // function type - Map: make(map[string]*types.Type), - Ord: []string{}, - Out: obj.Type, // after the function is called it's this... - } + var typ *types.Type + if obj.Type != nil { // don't panic if called speculatively + typ = &types.Type{ + Kind: types.KindFunc, // function type + Map: make(map[string]*types.Type), + Ord: []string{}, + Out: obj.Type, // after the function is called it's this... + } - // type of body is what we'd get by running the function (what's inside) - if obj.Edge != "" { - typ.Map[obj.Edge] = obj.Type.Out - typ.Ord = append(typ.Ord, obj.Edge) + // type of body is what we'd get by running the function (what's inside) + if obj.Edge != "" { + typ.Map[obj.Edge] = obj.Type.Out + typ.Ord = append(typ.Ord, obj.Edge) + } } pure := true // assume true diff --git a/lang/funcs/structs/if.go b/lang/funcs/structs/if.go index cca4ab66..f0241794 100644 --- a/lang/funcs/structs/if.go +++ b/lang/funcs/structs/if.go @@ -46,15 +46,18 @@ func (obj *IfFunc) Validate() error { // Info returns some static info about itself. func (obj *IfFunc) Info() *interfaces.Info { - typ := &types.Type{ - Kind: types.KindFunc, // function type - Map: map[string]*types.Type{ - "c": types.TypeBool, // conditional must be a boolean - "a": obj.Type, // true branch must be this type - "b": obj.Type, // false branch must be this type too - }, - Ord: []string{"c", "a", "b"}, // conditional, and two branches - Out: obj.Type, // result type must match + var typ *types.Type + if obj.Type != nil { // don't panic if called speculatively + typ = &types.Type{ + Kind: types.KindFunc, // function type + Map: map[string]*types.Type{ + "c": types.TypeBool, // conditional must be a boolean + "a": obj.Type, // true branch must be this type + "b": obj.Type, // false branch must be this type too + }, + Ord: []string{"c", "a", "b"}, // conditional, and two branches + Out: obj.Type, // result type must match + } } return &interfaces.Info{ diff --git a/lang/funcs/structs/var.go b/lang/funcs/structs/var.go index 2d8bb294..176df0cf 100644 --- a/lang/funcs/structs/var.go +++ b/lang/funcs/structs/var.go @@ -52,11 +52,14 @@ func (obj *VarFunc) Validate() error { // Info returns some static info about itself. func (obj *VarFunc) Info() *interfaces.Info { - typ := &types.Type{ - Kind: types.KindFunc, // function type - Map: map[string]*types.Type{obj.Edge: obj.Type}, - Ord: []string{obj.Edge}, - Out: obj.Type, // this is the output type for the expression + var typ *types.Type + if obj.Type != nil { // don't panic if called speculatively + typ = &types.Type{ + Kind: types.KindFunc, // function type + Map: map[string]*types.Type{obj.Edge: obj.Type}, + Ord: []string{obj.Edge}, + Out: obj.Type, // this is the output type for the expression + } } return &interfaces.Info{