blob: c6350f8bbae3d955c227e63cfc9bf30a14419570 [file] [log] [blame]
package ast
import (
"fmt"
)
// Node is the interface that all AST nodes must implement.
type Node interface {
// Accept is called to dispatch to the visitors. It must return the
// resulting Node (which might be different in an AST transform).
Accept(Visitor) Node
// Pos returns the position of this node in some source.
Pos() Pos
// Type returns the type of this node for the given context.
Type(Scope) (Type, error)
}
// Pos is the starting position of an AST node
type Pos struct {
Column, Line int // Column/Line number, starting at 1
Filename string // Optional source filename, if known
}
func (p Pos) String() string {
if p.Filename == "" {
return fmt.Sprintf("%d:%d", p.Line, p.Column)
} else {
return fmt.Sprintf("%s:%d:%d", p.Filename, p.Line, p.Column)
}
}
// InitPos is an initiaial position value. This should be used as
// the starting position (presets the column and line to 1).
var InitPos = Pos{Column: 1, Line: 1}
// Visitors are just implementations of this function.
//
// The function must return the Node to replace this node with. "nil" is
// _not_ a valid return value. If there is no replacement, the original node
// should be returned. We build this replacement directly into the visitor
// pattern since AST transformations are a common and useful tool and
// building it into the AST itself makes it required for future Node
// implementations and very easy to do.
//
// Note that this isn't a true implementation of the visitor pattern, which
// generally requires proper type dispatch on the function. However,
// implementing this basic visitor pattern style is still very useful even
// if you have to type switch.
type Visitor func(Node) Node
//go:generate stringer -type=Type
// Type is the type of any value.
type Type uint32
const (
TypeInvalid Type = 0
TypeAny Type = 1 << iota
TypeBool
TypeString
TypeInt
TypeFloat
TypeList
TypeMap
// This is a special type used by Terraform to mark "unknown" values.
// It is impossible for this type to be introduced into your HIL programs
// unless you explicitly set a variable to this value. In that case,
// any operation including the variable will return "TypeUnknown" as the
// type.
TypeUnknown
)
func (t Type) Printable() string {
switch t {
case TypeInvalid:
return "invalid type"
case TypeAny:
return "any type"
case TypeBool:
return "type bool"
case TypeString:
return "type string"
case TypeInt:
return "type int"
case TypeFloat:
return "type float"
case TypeList:
return "type list"
case TypeMap:
return "type map"
case TypeUnknown:
return "type unknown"
default:
return "unknown type"
}
}