func (l *FaultListener) ExitOpInstance(c *parser.OpInstanceContext) {
	token := ast.Token{
		Type:    "IDENT",
		Literal: "IDENT",
		Position: []int{c.GetStart().GetLine(),
			c.GetStart().GetColumn(),
			c.GetStop().GetLine(),
			c.GetStop().GetColumn(),
		},
	}
	ident := &ast.Identifier{
		Token: token,
	}
	id := c.AllIDENT()
	switch len(id) {
	case 1:
		ident.Spec = l.currSpec
		ident.Value = id[0].GetText()
	case 2:
		ident.Spec = id[0].GetText()
		ident.Value = id[1].GetText()
	default:
		panic(fmt.Sprintf("%s is an invalid identifier line: %d col:%d", id, c.GetStart().GetLine(), c.GetStart().GetColumn()))
	}
	l.push(&ast.Instance{
		Token: token,
		Value: ident,
	},
	)
}
/*func (l *FaultListener) ExitOpParam(c *parser.OpParamContext) {
token := ast.Token{
Type:    "IDENT",
Literal: "IDENT",
Position: []int{c.GetStart().GetLine(),
c.GetStart().GetColumn(),
c.GetStop().GetLine(),
c.GetStop().GetColumn(),
},
}
v := c.GetText()
param := strings.Split(v, ".")

l.push(&ast.ParameterCall{
Token: token,
Value: param,
},
)
}
package listener
import (
	"fault/ast"
	"fault/parser"
	"fmt"
	"os"
	gopath "path"
	"strconv"
	"strings"
	"github.com/antlr/antlr4/runtime/Go/antlr"
)
type FaultListener struct {
	*parser.BaseFaultParserListener
	stack    []interface{}
	AST      *ast.Spec
	scope    string
	currSpec string
	skipRun  bool
	Path     string  
}
func (l *FaultListener) push(n interface{}) {
	l.stack = append(l.stack, n)
}
func (l *FaultListener) pop() interface{} {
	var s interface{}
	s, l.stack = l.stack[len(l.stack)-1], l.stack[:len(l.stack)-1]
	return s
}
func (l *FaultListener) ExitSpec(c *parser.SpecContext) {
	var spec = &ast.Spec{}
	for _, v := range l.stack {
		spec.Statements = append(spec.Statements, v.(ast.Statement))
	}
	l.AST = spec
}
func (l *FaultListener) EnterSpecClause(c *parser.SpecClauseContext) {
	l.currSpec = c.IDENT().GetText()
}
func (l *FaultListener) ExitSpecClause(c *parser.SpecClauseContext) {
	token := ast.Token{
		Type:    "SPEC_DECL",
		Literal: "SPEC_DECL",
		Position: []int{c.GetStart().GetLine(),
			c.GetStart().GetColumn(),
			c.GetStop().GetLine(),
			c.GetStop().GetColumn(),
		},
	}
	iden_token := ast.Token{
		Type:    "IDENT",
		Literal: "IDENT",
		Position: []int{c.GetStart().GetLine(),
			c.GetStart().GetColumn(),
			c.GetStop().GetLine(),
			c.GetStop().GetColumn(),
		},
	}
	l.push(
		&ast.SpecDeclStatement{
			Token: token,
			Name: &ast.Identifier{
				Token: iden_token,
				Value: c.IDENT().GetText(),
			},
		},
	)
}
func (l *FaultListener) ExitImportDecl(c *parser.ImportDeclContext) {
	items := len(c.AllImportSpec())
	var itemList []interface{}
	for i := 0; i < items; i++ {
		right := l.pop()
		var temp []interface{}
		temp = append(temp, right)
		itemList = append(temp, itemList...)
	}
	for _, v := range itemList {
		l.push(v)
	}
}
func (l *FaultListener) ExitImportSpec(c *parser.ImportSpecContext) {
	token := ast.Token{
		Type:    "IMPORT_DECL",
		Literal: "IMPORT_DECL",
		Position: []int{c.GetStart().GetLine(),
			c.GetStart().GetColumn(),
			c.GetStop().GetLine(),
			c.GetStop().GetColumn(),
		},
	}
	val := l.pop()
	if val == nil {
		panic(fmt.Sprintf("top of stack not an expression: line %d col %d type %T", c.GetStart().GetLine(), c.GetStart().GetColumn(), val))
	}
	fpath, ok := val.(*ast.StringLiteral)
	if !ok {
		panic(fmt.Sprintf("import path not a string: line %d col %d type %T", c.GetStart().GetLine(), c.GetStart().GetColumn(), val))
	}
	trimmedFP := fpath.Value[1 : len(fpath.Value)-1]
	fp := gopath.Join(l.Path, trimmedFP)
	importFile, err := os.ReadFile(fp)
	if err != nil {
		panic(fmt.Sprintf("spec file %s not found\n", fpath))
	}
	tree := l.parseImport(string(importFile))
	var ident *ast.Identifier
	if len(c.GetChildren()) == 2 {
		ident = &ast.Identifier{
			Token: token,
			Value: c.IDENT().GetText(),
		}
	} else {
		ident = &ast.Identifier{
			Token: token,
			Value: pathToIdent(fpath.String()),
		}
	}
	l.push(&ast.ImportStatement{
		Token: token,
		Name:  ident,
		Path:  fpath,
		Tree:  tree,
	})
}
func (l *FaultListener) ExitConstSpec(c *parser.ConstSpecContext) {
	token := ast.Token{
		Type:    "CONST_DECL",
		Literal: "CONST_DECL",
		Position: []int{c.GetStart().GetLine(),
			c.GetStart().GetColumn(),
			c.GetStop().GetLine(),
			c.GetStop().GetColumn(),
		},
	}
	right := l.pop()
	val := right
	if val == nil {
		panic(fmt.Sprintf("top of stack not an expression: line %d col %d type %T", c.GetStart().GetLine(), c.GetStart().GetColumn(), right))
	}
	var items int
	identlist, ok := c.GetChild(0).(*parser.IdentListContext)
	if ok {
		items = len(identlist.AllOperandName())
	} else {
		items = 1
	}
	var itemList []interface{}
	for i := 0; i < items; i++ {
		left := l.pop()
		ident, ok := left.(*ast.Identifier)
		if ident == nil {
			panic(fmt.Sprintf("top of stack not an expression: line %d col %d type %T", c.GetStart().GetLine(), c.GetStart().GetColumn(), left))
		}
		if !ok {
			panic(fmt.Sprintf("top of stack not an identifier: line %d col %d type %T", c.GetStart().GetLine(), c.GetStart().GetColumn(), left))
		}
		var temp []interface{}
		temp = append(temp, &ast.ConstantStatement{
			Token: token,
			Name:  ident,
			Value: val.(ast.Expression),
		})
		itemList = append(  
			temp, itemList...,
		)
	}
	for _, v := range itemList {
		l.push(v)
	}
}
func (l *FaultListener) EnterStructDecl(c *parser.StructDeclContext) {
	l.scope = c.GetChild(1).(antlr.TerminalNode).GetText()
}
func (l *FaultListener) ExitStructDecl(c *parser.StructDeclContext) {
	token := ast.Token{
		Type:    "ASSIGN",
		Literal: "=",
		Position: []int{c.GetStart().GetLine(),
			c.GetStart().GetColumn(),
			c.GetStop().GetLine(),
			c.GetStop().GetColumn(),
		},
	}
	right := l.pop()
	var val ast.Expression
	switch right.(type) {
	case *ast.StockLiteral, *ast.FlowLiteral:
		val = right.(ast.Expression)
	default:
		if right == nil {
			panic(fmt.Sprintf("top of stack not an expression: line %d col %d type %T", c.GetStart().GetLine(), c.GetStart().GetColumn(), right))
		}
		panic(fmt.Sprintf("def can only be used to define a valid stock or flow: line %d col %d", c.GetStart().GetLine(), c.GetStart().GetColumn()))
	}
	token2 := ast.Token{
		Type:    "IDENT",
		Literal: "IDENT",
		Position: []int{c.GetStart().GetLine(),
			c.GetStart().GetColumn(),
			c.GetStop().GetLine(),
			c.GetStop().GetColumn(),
		},
	}
	ident := &ast.Identifier{
		Token: token2,
		Value: c.IDENT().GetText(),
	}
	l.push(
		&ast.DefStatement{
			Token: token,
			Name:  ident,
			Value: val,
		})
	l.scope = ""
}
func (l *FaultListener) ExitStock(c *parser.StockContext) {
	pairs := c.AllStructProperties()
	token := ast.Token{
		Type:    "STOCK",
		Literal: "stock",
		Position: []int{c.GetStart().GetLine(),
			c.GetStart().GetColumn(),
			c.GetStop().GetLine(),
			c.GetStop().GetColumn(),
		},
	}
	l.push(
		&ast.StockLiteral{
			Token: token,
			Pairs: l.getPairs(len(pairs), []int{c.GetStart().GetLine(), c.GetStart().GetColumn()}),
		})
}
func (l *FaultListener) ExitFlow(c *parser.FlowContext) {
	pairs := c.AllStructProperties()
	token := ast.Token{
		Type:    "FLOW",
		Literal: "flow",
		Position: []int{c.GetStart().GetLine(),
			c.GetStart().GetColumn(),
			c.GetStop().GetLine(),
			c.GetStop().GetColumn(),
		},
	}
	l.push(
		&ast.FlowLiteral{
			Token: token,
			Pairs: l.getPairs(len(pairs), []int{c.GetStart().GetLine(), c.GetStart().GetColumn()}),
		},
	)
}
func (l *FaultListener) ExitPropInt(c *parser.PropIntContext) {
	val := l.pop()
	token2 := ast.Token{
		Type:    "IDENT",
		Literal: "IDENT",
		Position: []int{c.GetStart().GetLine(),
			c.GetStart().GetColumn(),
			c.GetStop().GetLine(),
			c.GetStop().GetColumn(),
		},
	}
	l.push(&ast.Identifier{
		Token: token2,
		Value: c.IDENT().GetText(),
	})
	l.push(val)
}
func (l *FaultListener) ExitPropString(c *parser.PropStringContext) {
	val := l.pop()
	token2 := ast.Token{
		Type:    "IDENT",
		Literal: "IDENT",
		Position: []int{c.GetStart().GetLine(),
			c.GetStart().GetColumn(),
			c.GetStop().GetLine(),
			c.GetStop().GetColumn(),
		},
	}
	l.push(&ast.Identifier{
		Token: token2,
		Value: c.IDENT().GetText(),
	},
	)
	l.push(val)
}
func (l *FaultListener) ExitPropVar(c *parser.PropVarContext) {
	f := l.pop()
	token2 := ast.Token{
		Type:    "IDENT",
		Literal: "IDENT",
		Position: []int{c.GetStart().GetLine(),
			c.GetStart().GetColumn(),
			c.GetStop().GetLine(),
			c.GetStop().GetColumn(),
		},
	}
	l.push(&ast.Identifier{
		Token: token2,
		Value: c.IDENT().GetText(),
	},
	)
	switch v := f.(type) {
	case *ast.Instance:
		v.Name = c.IDENT().GetText()
		l.push(v)
	case *ast.Identifier:
		l.push(v)
	default:
		panic(fmt.Sprintf("top of stack not an identifier: line %d col %d type %T", c.GetStart().GetLine(), c.GetStart().GetColumn(), f))
	}
}
func (l *FaultListener) EnterPropFunc(c *parser.PropFuncContext) {
	l.scope = fmt.Sprint(l.scope, ".", c.IDENT().GetText())
}
func (l *FaultListener) ExitPropFunc(c *parser.PropFuncContext) {
	val := l.pop()
	token1 := ast.Token{
		Type:    "IDENT",
		Literal: "IDENT",
		Position: []int{c.GetStart().GetLine(),
			c.GetStart().GetColumn(),
			c.GetStop().GetLine(),
			c.GetStop().GetColumn(),
		},
	}
	l.push(&ast.Identifier{
		Token: token1,
		Value: c.IDENT().GetText(),
	},
	)
	l.push(val)
}
func (l *FaultListener) ExitFunctionLit(c *parser.FunctionLitContext) {
	token := ast.Token{
		Type:    "FUNCTION",
		Literal: "FUNCTION",
		Position: []int{c.GetStart().GetLine(),
			c.GetStart().GetColumn(),
			c.GetStop().GetLine(),
			c.GetStop().GetColumn(),
		},
	}
	b := l.pop()
	f := &ast.FunctionLiteral{
		Token: token,
		Body:  b.(*ast.BlockStatement),
	}
	l.push(f)
}
func (l *FaultListener) ExitStatementList(c *parser.StatementListContext) {
	token := ast.Token{
		Type:    "FUNCTION",
		Literal: "FUNCTION",
		Position: []int{c.GetStart().GetLine(),
			c.GetStart().GetColumn(),
			c.GetStop().GetLine(),
			c.GetStop().GetColumn(),
		},
	}
	sl := &ast.BlockStatement{Token: token}
	for _, v := range c.GetChildren() {
		ex := l.pop()
		switch ex.(type) {
		case ast.Statement:
			sl.Statements = append([]ast.Statement{ex.(ast.Statement)}, sl.Statements...)
		case ast.Expression:
			token2 := ast.Token{
				Type:    "FUNCTION",
				Literal: "FUNCTION",
				Position: []int{v.(*parser.StatementContext).GetStart().GetLine(),
					v.(*parser.StatementContext).GetStart().GetColumn(),
					v.(*parser.StatementContext).GetStop().GetLine(),
					v.(*parser.StatementContext).GetStop().GetColumn(),
				},
			}
			s := &ast.ExpressionStatement{
				Token:      token2,
				Expression: ex.(ast.Expression),
			}
			sl.Statements = append([]ast.Statement{s}, sl.Statements...)
		default:
			panic(fmt.Sprintf("Neither statement nor expression got=%T", v))
		}
	}
	l.push(sl)
}
func (l *FaultListener) ExitFaultAssign(c *parser.FaultAssignContext) {
	operator := c.GetChild(1).(antlr.TerminalNode).GetText()
	token := ast.Token{
		Type:    "ASSIGN",
		Literal: operator,
		Position: []int{c.GetStart().GetLine(),
			c.GetStart().GetColumn(),
			c.GetStop().GetLine(),
			c.GetStop().GetColumn(),
		},
	}
	var receiver ast.Expression
	var sender ast.Expression
	right := l.pop()
	left := l.pop()
	if operator == "->" {
		switch right.(type) {
		case *ast.ParameterCall:  
			receiver = right.(ast.Expression)
		default:  
			sender = &ast.InfixExpression{
				Token:    l.generateToken(right.(ast.Expression).Position(), "MINUS", "-"),
				Left:     left.(ast.Expression),
				Operator: "-",
				Right:    right.(ast.Expression)}
		}
		switch left.(type) {
		case *ast.ParameterCall:  
			receiver = left.(ast.Expression)
		default:  
			sender = &ast.InfixExpression{
				Token:    l.generateToken(right.(ast.Expression).Position(), "MINUS", "-"),
				Left:     right.(ast.Expression),
				Operator: "-",
				Right:    left.(ast.Expression)}
		}
		if sender == nil || receiver == nil {
			panic(fmt.Sprintf("malformed flow assignment: line %d col %d type %T", c.GetStart().GetLine(), c.GetStart().GetColumn(), left))
		}
	} else if operator == "<-" {
		switch right.(type) {
		case *ast.ParameterCall:  
			receiver = right.(ast.Expression)
		default:  
			sender = &ast.InfixExpression{
				Token:    l.generateToken(right.(ast.Expression).Position(), "ADD", "+"),
				Left:     left.(ast.Expression),
				Operator: "+",
				Right:    right.(ast.Expression)}
		}
		switch left.(type) {
		case *ast.ParameterCall:  
			receiver = left.(ast.Expression)
		default:  
			sender = &ast.InfixExpression{
				Token:    l.generateToken(right.(ast.Expression).Position(), "ADD", "+"),
				Left:     right.(ast.Expression),
				Operator: "+",
				Right:    left.(ast.Expression)}
		}
		if sender == nil || receiver == nil {
			panic(fmt.Sprintf("malformed flow assignment: line %d col %d type %T", c.GetStart().GetLine(), c.GetStart().GetColumn(), left))
		}
	} else {
		panic(fmt.Sprintf("Invalid operator %s in expression", operator))
	}
	l.push(
		&ast.InfixExpression{
			Token:    token,
			Left:     receiver,
			Operator: "<-",  
			Right:    sender,
		})
}
func (l *FaultListener) ExitMiscAssign(c *parser.MiscAssignContext) {
	token := ast.Token{
		Type:    "ASSIGN",
		Literal: c.GetChild(1).(antlr.TerminalNode).GetText(),
		Position: []int{c.GetStart().GetLine(),
			c.GetStart().GetColumn(),
			c.GetStop().GetLine(),
			c.GetStop().GetColumn(),
		},
	}
	right := l.pop()
	if right == nil {
		panic(fmt.Sprintf("top of stack not an expression: line %d col %d type %T", c.GetStart().GetLine(), c.GetStart().GetColumn(), right))
	}
	var assign *ast.InfixExpression
	left := l.pop()
	switch ident := left.(type) {
	case *ast.Identifier:
		switch inst := right.(type) {
		case *ast.Instance:
			inst.Name = ident.Value
			right = inst
		}
		assign = &ast.InfixExpression{
			Token:    token,
			Left:     ident,
			Operator: c.GetChild(1).(antlr.TerminalNode).GetText(),
			Right:    right.(ast.Expression),
		}
	case *ast.ParameterCall:
		switch inst := right.(type) {
		case *ast.Instance:
			inst.Name = ident.Value[0]
			right = inst
		}
		assign = &ast.InfixExpression{
			Token:    token,
			Left:     ident,
			Operator: c.GetChild(1).(antlr.TerminalNode).GetText(),
			Right:    right.(ast.Expression),
		}
	default:
		panic(fmt.Sprintf("left side of expression should be an identifier: line %d col %d type %T", c.GetStart().GetLine(), c.GetStart().GetColumn(), left))
	}
	l.push(assign)
}
func (l *FaultListener) ExitLrExpr(c *parser.LrExprContext) {
	token := ast.Token{
		Type:    ast.OPS[c.GetChild(1).(antlr.TerminalNode).GetText()],
		Literal: c.GetChild(1).(antlr.TerminalNode).GetText(),
		Position: []int{c.GetStart().GetLine(),
			c.GetStart().GetColumn(),
			c.GetStop().GetLine(),
			c.GetStop().GetColumn(),
		},
	}
	rght := l.pop()
	lft := l.pop()
	e := &ast.InfixExpression{
		Token:    token,
		Left:     lft.(ast.Expression),
		Operator: c.GetChild(1).(antlr.TerminalNode).GetText(),
		Right:    rght.(ast.Expression),
	}
	l.push(e)
}
func (l *FaultListener) ExitParamCall(c *parser.ParamCallContext) {
	token := ast.Token{
		Type:    "IDENT",
		Literal: "IDENT",
		Position: []int{c.GetStart().GetLine(),
			c.GetStart().GetColumn(),
			c.GetStop().GetLine(),
			c.GetStop().GetColumn(),
		},
	}
	v := c.GetText()
	param := strings.Split(v, ".")
	l.push(&ast.ParameterCall{
		Token: token,
		Value: param,
	},
	)
}
func (l *FaultListener) ExitRunBlock(c *parser.RunBlockContext) {
	if !l.skipRun {
		token := ast.Token{
			Type:    "FUNCTION",
			Literal: "FUNCTION",
			Position: []int{c.GetStart().GetLine(),
				c.GetStart().GetColumn(),
				c.GetStop().GetLine(),
				c.GetStop().GetColumn(),
			},
		}
		sl := &ast.BlockStatement{
			Token: token,
		}
		steps := c.AllRunStep()
		for i := len(steps) - 1; i >= 0; i-- {
			v := steps[i]
			ex := l.pop()
			switch t := ex.(type) {
			case *ast.Instance:
				token2 := l.generateToken(
					[]int{v.(*parser.RunInitContext).GetStart().GetLine(),
						v.(*parser.RunInitContext).GetStart().GetColumn(),
						v.(*parser.RunInitContext).GetStop().GetLine(),
						v.(*parser.RunInitContext).GetStop().GetColumn(),
					}, "FUNCTION", "FUNCTION")
				s := &ast.ExpressionStatement{
					Token:      token2,
					Expression: t,
				}
				sl.Statements = append([]ast.Statement{s}, sl.Statements...)
			case ast.Statement:
				sl.Statements = append([]ast.Statement{t}, sl.Statements...)
			case ast.Expression:
				token2 := ast.Token{
					Type:    "FUNCTION",
					Literal: "FUNCTION",
					Position: []int{v.(*parser.RunStepExprContext).GetStart().GetLine(),
						v.(*parser.RunStepExprContext).GetStart().GetColumn(),
						v.(*parser.RunStepExprContext).GetStop().GetLine(),
						v.(*parser.RunStepExprContext).GetStop().GetColumn(),
					},
				}
				s := &ast.ExpressionStatement{
					Token:      token2,
					Expression: t,
				}
				sl.Statements = append([]ast.Statement{s}, sl.Statements...)
			default:
				panic(fmt.Sprintf("Neither statement nor expression got=%T", v))
			}
		}
		l.push(sl)
	} else {
		steps := c.AllRunStep()
		for i := len(steps) - 1; i >= 0; i-- {
			l.pop()
		}
	}
}
func (l *FaultListener) ExitRunInit(c *parser.RunInitContext) {
	if !l.skipRun {
		token := ast.Token{
			Type:    "ASSIGN",
			Literal: c.GetChild(1).(antlr.TerminalNode).GetText(),
			Position: []int{c.GetStart().GetLine(),
				c.GetStart().GetColumn(),
				c.GetStop().GetLine(),
				c.GetStop().GetColumn(),
			},
		}
		txt := c.AllIDENT()
		var right string
		ident := &ast.Identifier{Token: ast.Token{
			Type:    "IDENT",
			Literal: "IDENT",
			Position: []int{c.GetStart().GetLine(),
				c.GetStart().GetColumn(),
				c.GetStop().GetLine(),
				c.GetStop().GetColumn(),
			},
		},
		}
		switch len(txt) {
		case 2:
			ident.Spec = l.currSpec
			ident.Value = txt[0].GetText()
			right = txt[1].GetText()
		case 3:
			ident.Spec = txt[0].GetText()
			ident.Value = txt[1].GetText()
			right = txt[2].GetText()
		default:
			panic(fmt.Sprintf("%s is an invalid identifier line: %d col:%d", txt, c.GetStart().GetLine(), c.GetStart().GetColumn()))
		}
		l.push(
			&ast.Instance{
				Token: token,
				Value: ident,
				Name:  right,
			})
	}
}
func (l *FaultListener) ExitRunStepExpr(c *parser.RunStepExprContext) {
	if !l.skipRun {
		token := ast.Token{
			Type:    "Parallel",
			Literal: c.GetText(),
			Position: []int{c.GetStart().GetLine(),
				c.GetStart().GetColumn(),
				c.GetStop().GetLine(),
				c.GetStop().GetColumn(),
			},
		}
		var exp []ast.Expression
		for i := 0; i < len(c.AllParamCall()); i++ {
			idx := l.pop()
			exp = append([]ast.Expression{idx.(ast.Expression)}, exp...)
		}
		e := &ast.ParallelFunctions{
			Token:       token,
			Expressions: exp,
		}
		l.push(e)
	}
}
func (l *FaultListener) ExitPrefix(c *parser.PrefixContext) {
	token := ast.Token{
		Type:    ast.OPS[c.GetChild(0).(antlr.TerminalNode).GetText()],
		Literal: c.GetChild(0).(antlr.TerminalNode).GetText(),
		Position: []int{c.GetStart().GetLine(),
			c.GetStart().GetColumn(),
			c.GetStop().GetLine(),
			c.GetStop().GetColumn(),
		},
	}
	rght := l.pop()
	e := &ast.PrefixExpression{
		Token:    token,
		Operator: c.GetChild(0).(antlr.TerminalNode).GetText(),
		Right:    rght.(ast.Expression),
	}
	l.push(e)
}
func (l *FaultListener) ExitTyped(c *parser.TypedContext) {
	switch c.FaultType().GetText() {
	case "natural":
		token := ast.Token{
			Type:    "NATURAL",
			Literal: "NATURAL",
			Position: []int{c.GetStart().GetLine(),
				c.GetStart().GetColumn(),
				c.GetStop().GetLine(),
				c.GetStop().GetColumn(),
			},
		}
		value := l.pop()
		nat, ok := value.(*ast.IntegerLiteral)
		if !ok {
			panic(fmt.Sprintf("Invalid value cast to type natural. got=%T at line %d col %d", value, c.GetStart().GetLine(), c.GetStart().GetColumn()))
		}
		l.push(&ast.Natural{
			Token: token,
			Value: nat.Value,
		})
	case "uncertain":
		token := ast.Token{
			Type:    "UNCERTAIN",
			Literal: "UNCERTAIN",
			Position: []int{c.GetStart().GetLine(),
				c.GetStart().GetColumn(),
				c.GetStop().GetLine(),
				c.GetStop().GetColumn(),
			},
		}
		v1 := l.pop()
		sigma, err := l.intOrFloatOk(v1)
		if err != nil {
			panic(fmt.Sprintf("Invalid value for sigma of type uncertain. got=%T at: line %d col %d", v1, c.GetStart().GetLine(), c.GetStart().GetColumn()))
		}
		v2 := l.pop()
		mean, err := l.intOrFloatOk(v2)
		if err != nil {
			panic(fmt.Sprintf("Invalid value for mean of type uncertain. got=%T at: line %d col %d", v2, c.GetStart().GetLine(), c.GetStart().GetColumn()))
		}
		l.push(&ast.Uncertain{
			Token: token,
			Mean:  mean,
			Sigma: sigma,
		})
	}
}
func (l *FaultListener) ExitIncDecStmt(c *parser.IncDecStmtContext) {
	var tType ast.TokenType
	var tLit string
	if c.PLUS_PLUS() != nil {
		tType = "PLUS"
		tLit = "+"
	} else if c.MINUS_MINUS() != nil {
		tType = "MINUS"
		tLit = "-"
	} else {
		panic(fmt.Sprintf("Illegal operation: line %d col %d", c.GetStart().GetLine(), c.GetStart().GetColumn()))
	}
	token := ast.Token{
		Type:    tType,
		Literal: tLit,
		Position: []int{c.GetStart().GetLine(),
			c.GetStart().GetColumn(),
			c.GetStop().GetLine(),
			c.GetStop().GetColumn(),
		},
	}
	ident := l.pop()
	token2 := ast.Token{
		Type:    "INT",
		Literal: "INT",
		Position: []int{c.GetStart().GetLine(),
			c.GetStart().GetColumn(),
			c.GetStop().GetLine(),
			c.GetStop().GetColumn(),
		},
	}
	e := &ast.InfixExpression{
		Token:    token,
		Left:     ident.(ast.Expression),
		Operator: tLit,
		Right:    &ast.IntegerLiteral{Token: token2, Value: 1},
	}
	l.push(e)
}
func (l *FaultListener) ExitIfStmt(c *parser.IfStmtContext) {
	token := ast.Token{
		Type:    "IF",
		Literal: "IF",
		Position: []int{c.GetStart().GetLine(),
			c.GetStart().GetColumn(),
			c.GetStop().GetLine(),
			c.GetStop().GetColumn(),
		},
	}
	var a *ast.BlockStatement
	if len(c.GetChildren()) > 3 {
		ra := l.pop()
		a = ra.(*ast.BlockStatement)
	} else {
		a = &ast.BlockStatement{}
	}
	csq := l.pop()
	cond := l.pop()
	e := &ast.IfExpression{
		Token:       token,
		Condition:   cond.(ast.Expression),
		Consequence: csq.(*ast.BlockStatement),
		Alternative: a,
	}
	l.push(e)
}
func (l *FaultListener) ExitAccessHistory(c *parser.AccessHistoryContext) {
	token := ast.Token{
		Type:    "HISTORY",
		Literal: "HISTORY",
		Position: []int{c.GetStart().GetLine(),
			c.GetStart().GetColumn(),
			c.GetStop().GetLine(),
			c.GetStop().GetColumn(),
		},
	}
	var exp []ast.Expression
	for i := 0; i < len(c.AllExpression()); i++ {
		idx := l.pop()
		exp = append([]ast.Expression{idx.(ast.Expression)}, exp...)
	}
	for i := 0; i < len(exp); i++ {
		ident := l.pop()
		left := ident
		right := exp[i]
		l.push(&ast.IndexExpression{
			Token: token,
			Left:  left.(ast.Expression),
			Index: right,
		})
	}
}
func (l *FaultListener) ExitOpName(c *parser.OpNameContext) {
	token := ast.Token{
		Type:    "IDENT",
		Literal: "IDENT",
		Position: []int{c.GetStart().GetLine(),
			c.GetStart().GetColumn(),
			c.GetStop().GetLine(),
			c.GetStop().GetColumn(),
		},
	}
	l.push(&ast.Identifier{
		Token: token,
		Value: c.GetText(),
	},
	)
}