lang: Plumb data and unification strategy through the lang struct
This adds some plumbing to pass values into the lang struct.
This commit is contained in:
@@ -86,6 +86,7 @@ type LangArgs struct {
|
|||||||
|
|
||||||
OnlyUnify bool `arg:"--only-unify" help:"stop after type unification"`
|
OnlyUnify bool `arg:"--only-unify" help:"stop after type unification"`
|
||||||
SkipUnify bool `arg:"--skip-unify" help:"skip type unification"`
|
SkipUnify bool `arg:"--skip-unify" help:"skip type unification"`
|
||||||
|
UnifySolver *string `arg:"--unify-name" help:"pick a specific unification solver"`
|
||||||
|
|
||||||
Depth int `arg:"--depth" default:"-1" help:"max recursion depth limit (-1 is unlimited)"`
|
Depth int `arg:"--depth" default:"-1" help:"max recursion depth limit (-1 is unlimited)"`
|
||||||
|
|
||||||
|
|||||||
@@ -70,6 +70,9 @@ func init() {
|
|||||||
type GAPI struct {
|
type GAPI struct {
|
||||||
InputURI string // input URI of code file system to run
|
InputURI string // input URI of code file system to run
|
||||||
|
|
||||||
|
// Data is some additional data for the lang struct.
|
||||||
|
Data *lang.Data
|
||||||
|
|
||||||
lang *lang.Lang // lang struct
|
lang *lang.Lang // lang struct
|
||||||
wgRun *sync.WaitGroup
|
wgRun *sync.WaitGroup
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
@@ -261,6 +264,11 @@ func (obj *GAPI) Cli(info *gapi.Info) (*gapi.Deploy, error) {
|
|||||||
return nil, nil // success!
|
return nil, nil // success!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unificationStrategy := make(map[string]string)
|
||||||
|
if name := args.UnifySolver; name != nil && *name != "" {
|
||||||
|
unificationStrategy[unification.StrategyNameKey] = *name
|
||||||
|
}
|
||||||
|
|
||||||
if !args.SkipUnify {
|
if !args.SkipUnify {
|
||||||
// apply type unification
|
// apply type unification
|
||||||
unificationLogf := func(format string, v ...interface{}) {
|
unificationLogf := func(format string, v ...interface{}) {
|
||||||
@@ -277,6 +285,7 @@ func (obj *GAPI) Cli(info *gapi.Info) (*gapi.Deploy, error) {
|
|||||||
unifier := &unification.Unifier{
|
unifier := &unification.Unifier{
|
||||||
AST: iast,
|
AST: iast,
|
||||||
Solver: solver,
|
Solver: solver,
|
||||||
|
Strategy: unificationStrategy,
|
||||||
Debug: debug,
|
Debug: debug,
|
||||||
Logf: unificationLogf,
|
Logf: unificationLogf,
|
||||||
}
|
}
|
||||||
@@ -411,8 +420,11 @@ func (obj *GAPI) Cli(info *gapi.Info) (*gapi.Deploy, error) {
|
|||||||
Sema: info.Flags.Sema,
|
Sema: info.Flags.Sema,
|
||||||
GAPI: &GAPI{
|
GAPI: &GAPI{
|
||||||
InputURI: fs.URI(),
|
InputURI: fs.URI(),
|
||||||
|
Data: &lang.Data{
|
||||||
|
UnificationStrategy: unificationStrategy,
|
||||||
// TODO: add properties here...
|
// TODO: add properties here...
|
||||||
},
|
},
|
||||||
|
},
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -451,6 +463,7 @@ func (obj *GAPI) LangInit(ctx context.Context) error {
|
|||||||
Fs: fs,
|
Fs: fs,
|
||||||
FsURI: obj.InputURI,
|
FsURI: obj.InputURI,
|
||||||
Input: input,
|
Input: input,
|
||||||
|
Data: obj.Data,
|
||||||
|
|
||||||
Hostname: obj.data.Hostname,
|
Hostname: obj.data.Hostname,
|
||||||
Local: obj.data.Local,
|
Local: obj.data.Local,
|
||||||
|
|||||||
30
lang/lang.go
30
lang/lang.go
@@ -64,6 +64,18 @@ const (
|
|||||||
EngineStartupStatsTimeout = 10
|
EngineStartupStatsTimeout = 10
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Data is some data that is passed into the Lang struct. It is presented here
|
||||||
|
// as a single struct with room for multiple fields so that it can be changed or
|
||||||
|
// extended in the future without having to re-plumb through all the fields it
|
||||||
|
// contains
|
||||||
|
type Data struct {
|
||||||
|
// UnificationStrategy is a hack to tune unification performance until
|
||||||
|
// we have an overall cleaner unification algorithm in place.
|
||||||
|
UnificationStrategy map[string]string
|
||||||
|
|
||||||
|
// TODO: Add other fields here if necessary.
|
||||||
|
}
|
||||||
|
|
||||||
// Lang is the main language lexer/parser object.
|
// Lang is the main language lexer/parser object.
|
||||||
type Lang struct {
|
type Lang struct {
|
||||||
Fs engine.Fs // connected fs where input dir or metadata exists
|
Fs engine.Fs // connected fs where input dir or metadata exists
|
||||||
@@ -79,6 +91,9 @@ type Lang struct {
|
|||||||
// run the raw string as mcl code.
|
// run the raw string as mcl code.
|
||||||
Input string
|
Input string
|
||||||
|
|
||||||
|
// Data is some additional data for the lang struct.
|
||||||
|
Data *Data
|
||||||
|
|
||||||
Hostname string
|
Hostname string
|
||||||
Local *local.API
|
Local *local.API
|
||||||
World engine.World
|
World engine.World
|
||||||
@@ -101,6 +116,12 @@ type Lang struct {
|
|||||||
// watching them, *before* we pull their values, that way we'll know if they
|
// watching them, *before* we pull their values, that way we'll know if they
|
||||||
// changed from the values we wanted.
|
// changed from the values we wanted.
|
||||||
func (obj *Lang) Init(ctx context.Context) error {
|
func (obj *Lang) Init(ctx context.Context) error {
|
||||||
|
if obj.Data == nil {
|
||||||
|
return fmt.Errorf("lang struct was not built properly")
|
||||||
|
}
|
||||||
|
if obj.Data.UnificationStrategy == nil {
|
||||||
|
return fmt.Errorf("lang struct was not built properly")
|
||||||
|
}
|
||||||
if obj.Debug {
|
if obj.Debug {
|
||||||
obj.Logf("input: %s", obj.Input)
|
obj.Logf("input: %s", obj.Input)
|
||||||
tree, err := util.FsTree(obj.Fs, "/") // should look like gapi
|
tree, err := util.FsTree(obj.Fs, "/") // should look like gapi
|
||||||
@@ -227,13 +248,18 @@ func (obj *Lang) Init(ctx context.Context) error {
|
|||||||
}
|
}
|
||||||
obj.Logf("running type unification...")
|
obj.Logf("running type unification...")
|
||||||
|
|
||||||
solver, err := unification.LookupDefault()
|
var solver unification.Solver
|
||||||
if err != nil {
|
if name, exists := obj.Data.UnificationStrategy["solver"]; exists && name != "" {
|
||||||
|
if solver, err = unification.Lookup(name); err != nil {
|
||||||
|
return errwrap.Wrapf(err, "could not get solver: %s", name)
|
||||||
|
}
|
||||||
|
} else if solver, err = unification.LookupDefault(); err != nil {
|
||||||
return errwrap.Wrapf(err, "could not get default solver")
|
return errwrap.Wrapf(err, "could not get default solver")
|
||||||
}
|
}
|
||||||
unifier := &unification.Unifier{
|
unifier := &unification.Unifier{
|
||||||
AST: obj.ast,
|
AST: obj.ast,
|
||||||
Solver: solver,
|
Solver: solver,
|
||||||
|
Strategy: obj.Data.UnificationStrategy,
|
||||||
Debug: obj.Debug,
|
Debug: obj.Debug,
|
||||||
Logf: logf,
|
Logf: logf,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -137,6 +137,9 @@ func runInterpret(t *testing.T, code string) (_ *pgraph.Graph, reterr error) {
|
|||||||
lang := &Lang{
|
lang := &Lang{
|
||||||
Fs: fs,
|
Fs: fs,
|
||||||
Input: "/" + interfaces.MetadataFilename, // start path in fs
|
Input: "/" + interfaces.MetadataFilename, // start path in fs
|
||||||
|
Data: &Data{
|
||||||
|
UnificationStrategy: make(map[string]string), // empty
|
||||||
|
},
|
||||||
Debug: testing.Verbose(), // set via the -test.v flag to `go test`
|
Debug: testing.Verbose(), // set via the -test.v flag to `go test`
|
||||||
Logf: logf,
|
Logf: logf,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,11 +42,18 @@ const (
|
|||||||
// ErrAmbiguous means we couldn't find a solution, but we weren't
|
// ErrAmbiguous means we couldn't find a solution, but we weren't
|
||||||
// inconsistent.
|
// inconsistent.
|
||||||
ErrAmbiguous = interfaces.Error("can't unify, no equalities were consumed, we're ambiguous")
|
ErrAmbiguous = interfaces.Error("can't unify, no equalities were consumed, we're ambiguous")
|
||||||
|
|
||||||
|
// StrategyNameKey is the string key used when choosing a solver name.
|
||||||
|
StrategyNameKey = "name"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Init contains some handles that are used to initialize every solver. Each
|
// Init contains some handles that are used to initialize every solver. Each
|
||||||
// individual solver can choose to omit using some of the fields.
|
// individual solver can choose to omit using some of the fields.
|
||||||
type Init struct {
|
type Init struct {
|
||||||
|
// Strategy is a hack to tune unification performance until we have an
|
||||||
|
// overall cleaner unification algorithm in place.
|
||||||
|
Strategy map[string]string
|
||||||
|
|
||||||
Debug bool
|
Debug bool
|
||||||
Logf func(format string, v ...interface{})
|
Logf func(format string, v ...interface{})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,6 +75,8 @@ type SimpleInvariantSolver struct {
|
|||||||
|
|
||||||
// Init contains some handles that are used to initialize the solver.
|
// Init contains some handles that are used to initialize the solver.
|
||||||
func (obj *SimpleInvariantSolver) Init(init *unification.Init) error {
|
func (obj *SimpleInvariantSolver) Init(init *unification.Init) error {
|
||||||
|
obj.Strategy = init.Strategy
|
||||||
|
|
||||||
obj.Debug = init.Debug
|
obj.Debug = init.Debug
|
||||||
obj.Logf = init.Logf
|
obj.Logf = init.Logf
|
||||||
|
|
||||||
|
|||||||
@@ -48,6 +48,10 @@ type Unifier struct {
|
|||||||
// Solver is the solver algorithm implementation to use.
|
// Solver is the solver algorithm implementation to use.
|
||||||
Solver Solver
|
Solver Solver
|
||||||
|
|
||||||
|
// Strategy is a hack to tune unification performance until we have an
|
||||||
|
// overall cleaner unification algorithm in place.
|
||||||
|
Strategy map[string]string
|
||||||
|
|
||||||
Debug bool
|
Debug bool
|
||||||
Logf func(format string, v ...interface{})
|
Logf func(format string, v ...interface{})
|
||||||
}
|
}
|
||||||
@@ -76,6 +80,7 @@ func (obj *Unifier) Unify(ctx context.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
init := &Init{
|
init := &Init{
|
||||||
|
Strategy: obj.Strategy,
|
||||||
Logf: obj.Logf,
|
Logf: obj.Logf,
|
||||||
Debug: obj.Debug,
|
Debug: obj.Debug,
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user