| 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" |
| } |
| } |