blob: 0512231e6c128808be5d1f5563850739936b8db1 [file] [log] [blame]
// Copyright (C) 2016 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package semantic
import "android.googlesource.com/platform/tools/gpu/api/ast"
// Statement is the interface implemented by all statement types.
type Statement interface {
Node
isStatement() // A dummy function that's implemented by all semantic statements.
}
// Statements is a list of statements.
type Statements []Statement
func (Statements) isNode() {}
// Replace replaces count statements starting from first with s.
func (l *Statements) Replace(first, count int, s ...Statement) {
newLen := len(*l) - count + len(s)
var n Statements
// ensure the slice is big enough to hold all the new data.
if cap(*l) < newLen {
// l isn't big enough to hold the new elements.
// Create a new buffer, with room to grow.
n = make(Statements, newLen, newLen*2)
copy(n, (*l)[:first])
} else {
n = (*l)[:newLen] // Extend the slice length.
}
// move the part after the insertion to the right by len(s).
copy(n[first+len(s):], (*l)[first+count:])
// copy in s.
copy(n[first:], s)
*l = n
}
// Remove removes all occurances of s from the list of statements.
func (l *Statements) Remove(s Statement) {
out := (*l)[:0]
for _, n := range *l {
if n != s {
out = append(out, n)
}
}
*l = out
}
// InsertBefore inserts the statement s before the i'th statement.
func (l *Statements) InsertBefore(s Statement, i int) {
*l = append(*l, nil) // grow by one
copy((*l)[i+1:], (*l)[i:])
(*l)[i] = s
}
// Append adds the statement s at the end of the list.
func (l *Statements) Append(s Statement) {
*l = append(*l, s)
}
// Last returns the last statement in the list.
func (l Statements) Last() Statement {
if c := len(l); c > 0 {
return l[c-1]
}
return nil
}
// Block represents a collection of statements, used as the body of other
// nodes.
type Block struct {
AST *ast.Block // the underlying syntax node this was built from
Statements Statements // the set of statements this block represents
}
func (*Block) isNode() {}
func (*Block) isStatement() {}
// Branch represents the basic conditional execution statement.
// If Condition is true we use the True block, otherwise the False block.
type Branch struct {
AST *ast.Branch // the underlying syntax node this was built from
Condition Expression // the condition to select on
True *Block // use if Condition is true
False *Block // used if Condition is false
}
func (*Branch) isNode() {}
func (*Branch) isStatement() {}
// Switch represents a resolved ast.Switch statement.
type Switch struct {
AST *ast.Switch // the underlying syntax node this was built from
Value Expression // the value to match the cases against
Cases []*Case // the set of case statements to choose from
Default *Block // the block to use if no condition matches
}
func (*Switch) isNode() {}
func (*Switch) isStatement() {}
// Case represents a possible choice in a switch.
type Case struct {
AST *ast.Case // the underlying syntax node this was built from
Conditions []Expression // the set of expressions to match the switch value against
Block *Block // the block to use if a condition matches
}
func (*Case) isNode() {}
func (*Case) isStatement() {}
// Iteration is the basic looping construct.
// It will set Iterator to each value from Iterable in turn, and run Block for each one.
type Iteration struct {
AST *ast.Iteration // the underlying syntax node this was built from
Iterator *Local // the iteration control variable
From Expression // the expression to iterate from
To Expression // the expression to iterate to
Block *Block // the block to run for each entry from Iterable
}
func (*Iteration) isNode() {}
func (*Iteration) isStatement() {}
// MapIteration is a loop over a map's key-value pairs.
// It will set KeyIterator and ValueIterator to each pair from Map in turn,
// set IndexIterator to 0 and increment on each loop, and run Block for each.
type MapIteration struct {
AST *ast.MapIteration // the underlying syntax node this was built from
IndexIterator *Local // the iteration index control variable
KeyIterator *Local // the iteration key control variable
ValueIterator *Local // the iteration value control variable
Map Expression // the map to iterate over
Block *Block // the block to run for each k-v mapping
}
func (*MapIteration) isNode() {}
func (*MapIteration) isStatement() {}
// Assign is the only "mutating" construct.
// It assigns the value from the rhs into the slot described by the lhs, as defined
// by the operator.
type Assign struct {
AST *ast.Assign // the underlying syntax node this was built from
LHS Expression // the expression that gives the location to store into
Operator string // the assignment operator being applied
RHS Expression // the value to store
}
func (*Assign) isNode() {}
func (*Assign) isStatement() {}
// ArrayAssign represents assigning to a static-array index expression.
type ArrayAssign struct {
AST *ast.Assign // the underlying syntax node this was built from
To *ArrayIndex // the array index to assign to
Operator string // the assignment operator being applied
Value Expression // the value to set in the array
}
func (*ArrayAssign) isNode() {}
func (*ArrayAssign) isStatement() {}
// MapAssign represents assigning to a map index expression.
type MapAssign struct {
AST *ast.Assign // the underlying syntax node this was built from
To *MapIndex // the map index to assign to
Operator string // the assignment operator being applied
Value Expression // the value to set in the map
}
func (*MapAssign) isNode() {}
func (*MapAssign) isStatement() {}
// MapRemove represents removing an element from a map.
type MapRemove struct {
AST *ast.Delete // the underlying syntax node this was built from
Type *Map // the value type of the map
Map Expression // the expression that returns the map holding the key
Key Expression // the map key to remove
}
func (*MapRemove) isNode() {}
func (*MapRemove) isStatement() {}
// SliceAssign represents assigning to a slice index expression.
type SliceAssign struct {
AST *ast.Assign // the underlying syntax node this was built from
To *SliceIndex // the slice index to assign to
Operator string // the assignment operator being applied
Value Expression // the value to set in the slice
}
func (*SliceAssign) isNode() {}
func (*SliceAssign) isStatement() {}
// DeclareLocal represents a local variable declaration statement.
// Variables cannot be modified after declaration.
type DeclareLocal struct {
AST *ast.DeclareLocal // the underlying syntax node this was built from
Local *Local // the local variable that was declared by this statement
}
func (*DeclareLocal) isNode() {}
func (*DeclareLocal) isStatement() {}
// Return represents return statement for a function.
type Return struct {
AST *ast.Return // the underlying syntax node this was built from
Function *Function // the function this statement returns from
Value Expression // the value to be returned
}
func (*Return) isNode() {}
func (*Return) isStatement() {}
// Abort represents the abort statement, used to immediately terminate execution
// of a command, usually because of an error.
type Abort struct {
AST *ast.Abort // the underlying syntax node this was built from
Function *Function // the function this is aborting
Statement Node
}
func (*Abort) isNode() {}
func (*Abort) isStatement() {}
// Fence is a marker to indicate the point between all statements to be
// executed before (pre-fence) the call to the API function and all statements
// to be executed after (post-fence) the call to the API function.
//
// The Statement member is the first statement that is classified as post-fence,
// but may be nil if the fence is being added at the end of a function that has
// no post operations.
//
// Note that some statements are classified as both pre-fence and post-fence,
// and require logic to be executed either side of the API function call.
type Fence struct {
AST *ast.Fence // the underlying syntax node this was built from
Statement Node
Explicit bool // If true, then the fence was explicitly declared in the API file.
}
func (*Fence) isNode() {}
func (*Fence) isStatement() {}