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:
@@ -84,8 +84,9 @@ type LangArgs struct {
|
||||
OnlyDownload bool `arg:"--only-download" help:"stop after downloading any missing imports"`
|
||||
Update bool `arg:"--update" help:"update all dependencies to the latest versions"`
|
||||
|
||||
OnlyUnify bool `arg:"--only-unify" help:"stop after type unification"`
|
||||
SkipUnify bool `arg:"--skip-unify" help:"skip type unification"`
|
||||
OnlyUnify bool `arg:"--only-unify" help:"stop after 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)"`
|
||||
|
||||
|
||||
@@ -70,6 +70,9 @@ func init() {
|
||||
type GAPI struct {
|
||||
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
|
||||
wgRun *sync.WaitGroup
|
||||
ctx context.Context
|
||||
@@ -261,6 +264,11 @@ func (obj *GAPI) Cli(info *gapi.Info) (*gapi.Deploy, error) {
|
||||
return nil, nil // success!
|
||||
}
|
||||
|
||||
unificationStrategy := make(map[string]string)
|
||||
if name := args.UnifySolver; name != nil && *name != "" {
|
||||
unificationStrategy[unification.StrategyNameKey] = *name
|
||||
}
|
||||
|
||||
if !args.SkipUnify {
|
||||
// apply type unification
|
||||
unificationLogf := func(format string, v ...interface{}) {
|
||||
@@ -275,10 +283,11 @@ func (obj *GAPI) Cli(info *gapi.Info) (*gapi.Deploy, error) {
|
||||
return nil, errwrap.Wrapf(err, "could not get default solver")
|
||||
}
|
||||
unifier := &unification.Unifier{
|
||||
AST: iast,
|
||||
Solver: solver,
|
||||
Debug: debug,
|
||||
Logf: unificationLogf,
|
||||
AST: iast,
|
||||
Solver: solver,
|
||||
Strategy: unificationStrategy,
|
||||
Debug: debug,
|
||||
Logf: unificationLogf,
|
||||
}
|
||||
startTime := time.Now()
|
||||
unifyErr := unifier.Unify(context.TODO())
|
||||
@@ -411,7 +420,10 @@ func (obj *GAPI) Cli(info *gapi.Info) (*gapi.Deploy, error) {
|
||||
Sema: info.Flags.Sema,
|
||||
GAPI: &GAPI{
|
||||
InputURI: fs.URI(),
|
||||
// TODO: add properties here...
|
||||
Data: &lang.Data{
|
||||
UnificationStrategy: unificationStrategy,
|
||||
// TODO: add properties here...
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
@@ -451,6 +463,7 @@ func (obj *GAPI) LangInit(ctx context.Context) error {
|
||||
Fs: fs,
|
||||
FsURI: obj.InputURI,
|
||||
Input: input,
|
||||
Data: obj.Data,
|
||||
|
||||
Hostname: obj.data.Hostname,
|
||||
Local: obj.data.Local,
|
||||
|
||||
38
lang/lang.go
38
lang/lang.go
@@ -64,6 +64,18 @@ const (
|
||||
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.
|
||||
type Lang struct {
|
||||
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.
|
||||
Input string
|
||||
|
||||
// Data is some additional data for the lang struct.
|
||||
Data *Data
|
||||
|
||||
Hostname string
|
||||
Local *local.API
|
||||
World engine.World
|
||||
@@ -101,6 +116,12 @@ type Lang struct {
|
||||
// watching them, *before* we pull their values, that way we'll know if they
|
||||
// changed from the values we wanted.
|
||||
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 {
|
||||
obj.Logf("input: %s", obj.Input)
|
||||
tree, err := util.FsTree(obj.Fs, "/") // should look like gapi
|
||||
@@ -227,15 +248,20 @@ func (obj *Lang) Init(ctx context.Context) error {
|
||||
}
|
||||
obj.Logf("running type unification...")
|
||||
|
||||
solver, err := unification.LookupDefault()
|
||||
if err != nil {
|
||||
var solver unification.Solver
|
||||
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")
|
||||
}
|
||||
unifier := &unification.Unifier{
|
||||
AST: obj.ast,
|
||||
Solver: solver,
|
||||
Debug: obj.Debug,
|
||||
Logf: logf,
|
||||
AST: obj.ast,
|
||||
Solver: solver,
|
||||
Strategy: obj.Data.UnificationStrategy,
|
||||
Debug: obj.Debug,
|
||||
Logf: logf,
|
||||
}
|
||||
timing = time.Now()
|
||||
// NOTE: This is the "real" Unify that runs. (This is not for deploy.)
|
||||
|
||||
@@ -137,7 +137,10 @@ func runInterpret(t *testing.T, code string) (_ *pgraph.Graph, reterr error) {
|
||||
lang := &Lang{
|
||||
Fs: fs,
|
||||
Input: "/" + interfaces.MetadataFilename, // start path in fs
|
||||
Debug: testing.Verbose(), // set via the -test.v flag to `go test`
|
||||
Data: &Data{
|
||||
UnificationStrategy: make(map[string]string), // empty
|
||||
},
|
||||
Debug: testing.Verbose(), // set via the -test.v flag to `go test`
|
||||
Logf: logf,
|
||||
}
|
||||
if err := lang.Init(ctx); err != nil {
|
||||
|
||||
@@ -42,11 +42,18 @@ const (
|
||||
// ErrAmbiguous means we couldn't find a solution, but we weren't
|
||||
// inconsistent.
|
||||
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
|
||||
// individual solver can choose to omit using some of the fields.
|
||||
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
|
||||
Logf func(format string, v ...interface{})
|
||||
}
|
||||
|
||||
@@ -75,6 +75,8 @@ type SimpleInvariantSolver struct {
|
||||
|
||||
// Init contains some handles that are used to initialize the solver.
|
||||
func (obj *SimpleInvariantSolver) Init(init *unification.Init) error {
|
||||
obj.Strategy = init.Strategy
|
||||
|
||||
obj.Debug = init.Debug
|
||||
obj.Logf = init.Logf
|
||||
|
||||
|
||||
@@ -48,6 +48,10 @@ type Unifier struct {
|
||||
// Solver is the solver algorithm implementation to use.
|
||||
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
|
||||
Logf func(format string, v ...interface{})
|
||||
}
|
||||
@@ -76,8 +80,9 @@ func (obj *Unifier) Unify(ctx context.Context) error {
|
||||
}
|
||||
|
||||
init := &Init{
|
||||
Logf: obj.Logf,
|
||||
Debug: obj.Debug,
|
||||
Strategy: obj.Strategy,
|
||||
Logf: obj.Logf,
|
||||
Debug: obj.Debug,
|
||||
}
|
||||
if err := obj.Solver.Init(init); err != nil {
|
||||
return err
|
||||
|
||||
Reference in New Issue
Block a user