Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

line numbers in the AST re #732 #750

Draft
wants to merge 8 commits into
base: master
Choose a base branch
from
2 changes: 1 addition & 1 deletion cli/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ func (obj *RunArgs) Run(ctx context.Context, data *cliUtil.Data) (bool, error) {

deploy, err := gapiObj.Cli(info)
if err != nil {
return false, cliUtil.CliParseError(err) // consistent errors
return false, cliUtil.CliParseError(err) // TODO: it seems unlikely that parsing the CLI failed at this stage, and then the error will be misleading
}

if cmd := obj.RunLang; cmd != nil && cmd.OnlyUnify && deploy == nil {
Expand Down
105 changes: 79 additions & 26 deletions lang/ast/structs.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,17 +177,56 @@ var (
orderingGraphSingleton = false
)

// TextArea stores the coordinates of a statement or expression in the form of
// starting line/column and ending line/column
type TextArea struct {
startLine int
startColumn int
endLine int
endColumn int

// Bug5819 works around issue https://github.com/golang/go/issues/5819
Bug5819 interface{} // XXX: workaround
}

// Locate is used by the parser to store the token positions in AST nodes
func (a *TextArea) Locate(line int, col int, endline int, endcol int) {
a.startLine = line
a.startColumn = col
a.endLine = endline
a.endColumn = endcol
}

// LocalNode is the interface implemented by AST nodes that store their code
// position. It is implemented by node types that embed TextArea.
type LocalNode interface {
Locate(int, int, int, int)
GetPosition() (int, int)
GetEndPosition() (int, int)
}

// GetPosition returns the starting line/column of an AST node
func (a TextArea) GetPosition() (int, int) {
return a.startLine, a.startColumn
}

// GetEndPosition returns the end line/column of an AST node
func (a TextArea) GetEndPosition() (int, int) {
return a.endLine, a.endColumn
}

// StmtBind is a representation of an assignment, which binds a variable to an
// expression.
type StmtBind struct {
Ident string
Value interfaces.Expr
Type *types.Type
TextArea
}

// String returns a short representation of this statement.
func (obj *StmtBind) String() string {
return fmt.Sprintf("bind(%s)", obj.Ident)
return fmt.Sprintf("bind(%s) @ (%d %d)", obj.Ident, obj.startLine+1, obj.startColumn+1)
}

// Apply is a general purpose iterator method that operates on any AST node. It
Expand Down Expand Up @@ -220,11 +259,9 @@ func (obj *StmtBind) Interpolate() (interfaces.Stmt, error) {
if err != nil {
return nil, err
}
return &StmtBind{
Ident: obj.Ident,
Value: interpolated,
Type: obj.Type,
}, nil
result := *obj
result.Value = interpolated
return &result, nil
}

// Copy returns a light copy of this struct. Anything static will not be copied.
Expand Down Expand Up @@ -365,6 +402,7 @@ 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
TextArea
}

// String returns a short representation of this statement.
Expand Down Expand Up @@ -2059,6 +2097,7 @@ type StmtEdge struct {

// TODO: should notify be an Expr?
Notify bool // specifies that this edge sends a notification as well
TextArea
}

// String returns a short representation of this statement.
Expand Down Expand Up @@ -2561,6 +2600,7 @@ type StmtIf struct {
conditionPtr interfaces.Func // ptr for table lookup
ThenBranch interfaces.Stmt // optional, but usually present
ElseBranch interfaces.Stmt // optional
TextArea
}

// String returns a short representation of this statement.
Expand All @@ -2576,6 +2616,8 @@ func (obj *StmtIf) String() string {
s += fmt.Sprintf(" else { %s }", obj.ElseBranch.String())
}

s += fmt.Sprintf(" @ (%d %d)", obj.startLine+1, obj.startColumn+1)

return s
}

Expand Down Expand Up @@ -2642,11 +2684,11 @@ func (obj *StmtIf) Interpolate() (interfaces.Stmt, error) {
return nil, errwrap.Wrapf(err, "could not interpolate ElseBranch")
}
}
return &StmtIf{
Condition: condition,
ThenBranch: thenBranch,
ElseBranch: elseBranch,
}, nil
result := *obj
result.Condition = condition
result.ThenBranch = thenBranch
result.ElseBranch = elseBranch
return &result, nil
}

// Copy returns a light copy of this struct. Anything static will not be copied.
Expand Down Expand Up @@ -2923,6 +2965,7 @@ type StmtProg struct {
importFiles []string // list of files seen during the SetScope import

Body []interfaces.Stmt
TextArea
}

// String returns a short representation of this statement.
Expand Down Expand Up @@ -4312,6 +4355,7 @@ type StmtFunc struct {
Name string
Func interfaces.Expr
Type *types.Type
TextArea
}

// String returns a short representation of this statement.
Expand Down Expand Up @@ -4518,6 +4562,7 @@ type StmtClass struct {
Name string
Args []*interfaces.Arg
Body interfaces.Stmt // probably a *StmtProg
TextArea
}

// String returns a short representation of this statement.
Expand Down Expand Up @@ -4720,6 +4765,7 @@ type StmtInclude struct {
Name string
Args []interfaces.Expr
Alias string
TextArea
}

// String returns a short representation of this statement.
Expand Down Expand Up @@ -5085,6 +5131,7 @@ func (obj *StmtInclude) Output(table map[interfaces.Func]types.Value) (*interfac
type StmtImport struct {
Name string
Alias string
TextArea
}

// String returns a short representation of this statement.
Expand Down Expand Up @@ -5266,6 +5313,7 @@ type ExprBool struct {
scope *interfaces.Scope // store for referencing this later

V bool
TextArea
}

// String returns a short representation of this expression.
Expand Down Expand Up @@ -5411,6 +5459,7 @@ type ExprStr struct {
scope *interfaces.Scope // store for referencing this later

V string // value of this string
TextArea
}

// String returns a short representation of this expression.
Expand Down Expand Up @@ -5606,6 +5655,7 @@ type ExprInt struct {
scope *interfaces.Scope // store for referencing this later

V int64
TextArea
}

// String returns a short representation of this expression.
Expand Down Expand Up @@ -5749,6 +5799,7 @@ type ExprFloat struct {
scope *interfaces.Scope // store for referencing this later

V float64
TextArea
}

// String returns a short representation of this expression.
Expand Down Expand Up @@ -5896,6 +5947,7 @@ type ExprList struct {

//Elements []*ExprListElement
Elements []interfaces.Expr
TextArea
}

// String returns a short representation of this expression.
Expand Down Expand Up @@ -6249,6 +6301,7 @@ type ExprMap struct {
typ *types.Type

KVs []*ExprMapKV
TextArea
}

// String returns a short representation of this expression.
Expand Down Expand Up @@ -6734,6 +6787,7 @@ type ExprStruct struct {
typ *types.Type

Fields []*ExprStructField // the list (fields) are intentionally ordered!
TextArea
}

// String returns a short representation of this expression.
Expand Down Expand Up @@ -7166,6 +7220,7 @@ type ExprFunc struct {

// XXX: is this necessary?
//V func(interfaces.Txn, []pgraph.Vertex) (pgraph.Vertex, error)
TextArea
}

// String returns a short representation of this expression.
Expand Down Expand Up @@ -7910,6 +7965,7 @@ type ExprCall struct {
Args []interfaces.Expr // list of args in parsed order
// Var specifies whether the function being called is a lambda in a var.
Var bool
TextArea
}

// String returns a short representation of this expression.
Expand All @@ -7918,7 +7974,9 @@ func (obj *ExprCall) String() string {
for _, x := range obj.Args {
s = append(s, fmt.Sprintf("%s", x.String()))
}
return fmt.Sprintf("call:%s(%s)", obj.Name, strings.Join(s, ", "))
result := fmt.Sprintf("call:%s(%s)", obj.Name, strings.Join(s, ", "))
result += fmt.Sprintf(" @ (%d %d)", obj.startLine+1, obj.startColumn+1)
return result
}

// Apply is a general purpose iterator method that operates on any AST node. It
Expand Down Expand Up @@ -7965,19 +8023,11 @@ func (obj *ExprCall) Interpolate() (interfaces.Expr, error) {
orig = obj.orig
}

return &ExprCall{
data: obj.data,
scope: obj.scope,
typ: obj.typ,
// XXX: Copy copies this, do we want to here as well? (or maybe
// we want to do it here, but not in Copy?)
expr: obj.expr,
orig: orig,
V: obj.V,
Name: obj.Name,
Args: args,
Var: obj.Var,
}, nil
result := *obj
result.orig = orig
result.Args = args

return &result, nil
}

// Copy returns a light copy of this struct. Anything static will not be copied.
Expand Down Expand Up @@ -8365,7 +8415,7 @@ func (obj *ExprCall) Infer() (*types.Type, []*interfaces.UnificationInvariant, e
var typExpr *types.Type // out

// Look at what kind of function we are calling...
callee := trueCallee(obj.expr)
callee := TrueCallee(obj.expr)
exprFunc, isFn := callee.(*ExprFunc)

argGen := func(x int) (string, error) {
Expand Down Expand Up @@ -8641,6 +8691,7 @@ type ExprVar struct {
typ *types.Type

Name string // name of the variable
TextArea
}

// String returns a short representation of this expression.
Expand Down Expand Up @@ -8904,6 +8955,7 @@ type ExprParam struct {
typ *types.Type

Name string // name of the parameter
TextArea
}

// String returns a short representation of this expression.
Expand Down Expand Up @@ -9616,6 +9668,7 @@ type ExprIf struct {
Condition interfaces.Expr
ThenBranch interfaces.Expr // could be an ExprBranch
ElseBranch interfaces.Expr // could be an ExprBranch
TextArea
}

// String returns a short representation of this expression.
Expand Down
10 changes: 5 additions & 5 deletions lang/ast/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -327,16 +327,16 @@ func getScope(node interfaces.Expr) (*interfaces.Scope, error) {
}
}

// trueCallee is a helper function because ExprTopLevel and ExprSingleton are
// TrueCallee is a helper function because ExprTopLevel and ExprSingleton are
// sometimes added around builtins. This makes it difficult for the type checker
// to check if a particular builtin is the callee or not. This function removes
// the ExprTopLevel and ExprSingleton wrappers, if they exist.
func trueCallee(apparentCallee interfaces.Expr) interfaces.Expr {
func TrueCallee(apparentCallee interfaces.Expr) interfaces.Expr {
switch x := apparentCallee.(type) {
case *ExprTopLevel:
return trueCallee(x.Definition)
return TrueCallee(x.Definition)
case *ExprSingleton:
return trueCallee(x.Definition)
return TrueCallee(x.Definition)
default:
return apparentCallee
}
Expand Down Expand Up @@ -383,7 +383,7 @@ func lambdaScopeFeedback(scope *interfaces.Scope, logf func(format string, v ...
names := []string{}
for name, val := range scope.Variables {
// XXX: Is this a valid way to filter?
if _, ok := trueCallee(val).(*ExprFunc); !ok {
if _, ok := TrueCallee(val).(*ExprFunc); !ok {
continue
}
names = append(names, name)
Expand Down
9 changes: 8 additions & 1 deletion lang/gapi/gapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,12 @@ func (obj *GAPI) Cli(info *gapi.Info) (*gapi.Deploy, error) {
unificationStrategy[unification.StrategyOptimizationsKey] = strings.Join(args.UnifyOptimizations, ",")
}

fmt.Println("The Interpolated Tree: %+v")
iast.Apply(func (n interfaces.Node) error {
fmt.Println(n)
return nil
})

if !args.SkipUnify {
// apply type unification
unificationLogf := func(format string, v ...interface{}) {
Expand Down Expand Up @@ -304,7 +310,8 @@ func (obj *GAPI) Cli(info *gapi.Info) (*gapi.Deploy, error) {
if args.OnlyUnify {
logf("type unification failed after %s", formatted)
}
return nil, errwrap.Wrapf(unifyErr, "could not unify types")
callee := ast.TrueCallee(unifyErr.(*interfaces.UnificationInvariant).Expr)
return nil, errwrap.Wrapf(unifyErr, "could not unify types [[ in expression: %s ]]", callee)
}

if args.OnlyUnify {
Expand Down
7 changes: 7 additions & 0 deletions lang/interfaces/unification.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,13 @@ type UnificationInvariant struct { // formerly the SamInvariant

// Actual is one of the two types to unify.
Actual *types.Type

// An error string to pass along with this
Err string
}

func (obj *UnificationInvariant) Error() string {
return obj.Err
}

// GenericCheck is the generic implementation of the Check Expr interface call.
Expand Down
Loading
Loading