public void CheckEvt(IScope currScope, LSLAst id)
        {
            EventSymbol evt = (EventSymbol)currScope.Resolve(id.Text + "()");

            Debug.Assert(evt != null);

            //try to find this event in our table
            if (!_supportedEvents.HasEventByName(id.Text))
            {
                _listener.Error("line " + id.Token.Line + ":" +
                                id.Token.CharPositionInLine + " No event evailable with name '" + id.Text + "'");

                return;
            }

            //also try to resolve the arguments
            List <VarType> passedEvtArgs = evt.ExtractArgumentTypes();

            if (!_supportedEvents.HasEventBySig(id.Text, VarType.Void, passedEvtArgs))
            {
                string paramList = this.FormatParamTypeList(_supportedEvents.GetArguments(id.Text));
                _listener.Error("line " + id.Token.Line + ":" +
                                id.Token.CharPositionInLine + " Incorrect parameters for event " + id.Text +
                                paramList);
            }
        }
        public bool IsAssignable(LSLAst lhs)
        {
            //lhs will either be an id direct or an EXPR with an ID child
            if (lhs.Type == LSLParser.ID)
            {
                return(true);
            }

            if (lhs.Type == LSLParser.EXPR &&
                lhs.ChildCount == 1 &&
                lhs.Children[0].Type == LSLParser.ID)
            {
                return(true);
            }

            if (lhs.Type == LSLParser.SUBSCRIPT)
            {
                return(true);
            }


            _listener.Error(
                "line " + lhs.Line + ":" + lhs.CharPositionInLine + " '" +
                lhs.Text + "' is not assignable"
                );

            return(false);
        }
        public ISymbolType PreDec(LSLAst a)
        {
            if (a.evalType == null)
            {
                _listener.Error(
                    "line " + a.Token.Line + ":" + a.Token.CharPositionInLine +
                    " (--) Unknown type in expression " + a.Text
                    );

                return(VOID);
            }

            if (!IsAssignable(a))
            {
                return(VOID);
            }

            if (!TypeIsIn(a.evalType, new ISymbolType[] { INT, FLOAT }))
            {
                _listener.Error(
                    "line " + a.Token.Line + ":" + a.Token.CharPositionInLine +
                    " -- not valid for type " + a.evalType.Name
                    );

                return(VOID);
            }

            return(a.evalType);
        }
        public ISymbolType Bop(LSLAst bop, LSLAst lhs, LSLAst rhs)
        {
            ISymbolType[,] symTable;
            string op = bop.Token.Text;

            symTable = FindOperationTable(lhs, op);
            if (symTable == null)
            {
                return(VOID);
            }

            if (HasUnknownTypes(lhs, rhs))
            {
                return(VOID);
            }

            ISymbolType symType = symTable[lhs.evalType.TypeIndex, rhs.evalType.TypeIndex];

            if (symType == VOID)
            {
                _listener.Error("line " + lhs.Token.Line + ":" +
                                lhs.Token.CharPositionInLine + " '" + op + "' is not a valid operation between " +
                                lhs.evalType.Name + " and " + rhs.evalType.Name);
                return(VOID);
            }

            return(symType);
        }
        public bool CheckRotationLiteral(LSLAst e1, LSLAst e2, LSLAst e3, LSLAst e4)
        {
            if (!AllTypesAreResolved(new LSLAst[] { e1, e2, e3, e4 }))
            {
                _listener.Error(
                    "line " + e1.Token.Line + ":" + e1.Token.CharPositionInLine +
                    " Rotation contains expression(s) of unknown type"
                    );

                return(false);
            }

            //try type promotion first
            e1.promoteToType = promoteFromTo[e1.evalType.TypeIndex, FLOAT.TypeIndex];
            e2.promoteToType = promoteFromTo[e2.evalType.TypeIndex, FLOAT.TypeIndex];
            e3.promoteToType = promoteFromTo[e3.evalType.TypeIndex, FLOAT.TypeIndex];
            e4.promoteToType = promoteFromTo[e4.evalType.TypeIndex, FLOAT.TypeIndex];

            if (CanAssignTo(e1.evalType, FLOAT, e1.promoteToType) &&
                CanAssignTo(e2.evalType, FLOAT, e2.promoteToType) &&
                CanAssignTo(e3.evalType, FLOAT, e3.promoteToType) &&
                CanAssignTo(e4.evalType, FLOAT, e4.promoteToType))
            {
                return(true);
            }

            _listener.Error(
                "line " + e1.Token.Line + ":" + e1.Token.CharPositionInLine +
                " Rotation components must be float or implicitly convertable to float "
                );

            return(false);
        }
        public ISymbolType RelOp(LSLAst lhs, LSLAst rhs)
        {
            if (HasUnknownTypes(lhs, rhs))
            {
                return(VOID);
            }

            //relational operations must be between the same types
            int tlhs = lhs.evalType.TypeIndex; // promote right to left type?
            int trhs = rhs.evalType.TypeIndex;

            rhs.promoteToType = promoteFromTo[trhs, tlhs];
            lhs.promoteToType = promoteFromTo[tlhs, trhs];

            if (!HaveSameTypes(lhs, rhs))
            {
                _listener.Error("line " + lhs.Token.Line + ":" +
                                lhs.Token.CharPositionInLine + " Type mismatch, relational operators require arguments of the same type");
            }

            //strings can not be LT/GT compared in LSL
            if (lhs.evalType == STRING || rhs.evalType == STRING)
            {
                _listener.Error("line " + lhs.Token.Line + ":" +
                                lhs.Token.CharPositionInLine + " Type mismatch, strings can not be compared with < or >");
            }

            return(INT);
        }
 public void CheckLogicalExpr(LSLAst expr)
 {
     if (expr.evalType != INT)
     {
         _listener.Error("line " + expr.Token.Line + ":" +
                         expr.Token.CharPositionInLine + " Logical expressions require integer type");
     }
 }
        public string text(LSLAst t)
        {
            string ts = "";

            //if (t.evalType != null) ts = ":<" + t.evalType + ">";
            return(_tokens.ToString(t.TokenStartIndex,
                                    t.TokenStopIndex) + ts);
        }
        public ISymbolType SubScript(LSLAst id, LSLAst subScript)
        {
            //the lhs must be an ID and it must be of vector type or rotation type
            //and it must be the letters x, y, z, or s for rotation
            if (id.Type != LSLParser.ID)
            {
                _listener.Error(
                    "line " + id.Token.Line + ":" + id.Token.CharPositionInLine +
                    " Use of subscript ." + subScript.Text + " requires a vector or rotation variable "
                    );

                return(VOID);
            }

            if (!TypeIsIn(id.evalType, new ISymbolType[] { VECTOR, ROTATION }))
            {
                _listener.Error(
                    "line " + id.Token.Line + ":" + id.Token.CharPositionInLine +
                    " Use of subscript ." + subScript.Text + " requires a vector or rotation variable"
                    );

                return(VOID);
            }

            if (id.evalType == VECTOR)
            {
                if (subScript.Text != "x" &&
                    subScript.Text != "y" &&
                    subScript.Text != "z")
                {
                    _listener.Error(
                        "line " + id.Token.Line + ":" + id.Token.CharPositionInLine +
                        " Invalid subscript ." + subScript.Text
                        );

                    return(VOID);
                }
            }

            if (id.evalType == ROTATION)
            {
                if (subScript.Text != "x" &&
                    subScript.Text != "y" &&
                    subScript.Text != "z" &&
                    subScript.Text != "s")
                {
                    _listener.Error(
                        "line " + id.Token.Line + ":" + id.Token.CharPositionInLine +
                        " Invalid subscript ." + subScript.Text
                        );

                    return(VOID);
                }
            }

            return(FLOAT);
        }
        public ISymbolType LogBop(LSLAst lhs, LSLAst rhs)
        {
            if (lhs.evalType != INT || rhs.evalType != INT)
            {
                _listener.Error("line " + lhs.Token.Line + ":" +
                                lhs.Token.CharPositionInLine + " Type mismatch, logical operators || and && require integer arguments");
            }

            return(INT);
        }
        public bool HasUnknownType(LSLAst lhs)
        {
            if (lhs.evalType == null)
            {
                _listener.Error("line " + lhs.Token.Line + ":" +
                                lhs.Token.CharPositionInLine + " Invalid operation. At least one type is unknown");
                return(true);
            }

            return(false);
        }
        public ISymbolType CheckListLiteral(LSLAst start, IList <LSLAst> args)
        {
            foreach (LSLAst node in args)
            {
                if (node.evalType == LIST)
                {
                    _listener.Error("line " + start.Token.Line + ":" +
                                    start.Token.CharPositionInLine + " A list can not contain another list");
                }
            }

            return(LIST);
        }
        public void CheckStateChange(LSLAst chgNode, LSLAst destID)
        {
            string      stateName = destID != null ? destID.Text + "(*)" : "default(*)";
            StateSymbol state     = _globals.Resolve(stateName) as StateSymbol;

            if (state == null)
            {
                _listener.Error(
                    "line " + chgNode.Token.Line + ":" + chgNode.Token.CharPositionInLine +
                    " Undefined state " + stateName
                    );
            }
        }
        public void CheckJump(LSLAst jumpStmt, LSLAst id)
        {
            LabelSymbol label = jumpStmt.scope.Resolve("@" + id.Text) as LabelSymbol;

            if (label == null)
            {
                _listener.Error("line " + id.Token.Line + ":" +
                                id.Token.CharPositionInLine + " Undefined label " + id.Text);
            }
            else
            {
                id.symbol = label;
            }
        }
        public ISymbolType BitOp(LSLAst lhs, LSLAst rhs)
        {
            if (HasUnknownTypes(lhs, rhs))
            {
                return(INT);
            }

            if (lhs.evalType != INT || rhs.evalType != INT)
            {
                _listener.Error("line " + lhs.Token.Line + ":" +
                                lhs.Token.CharPositionInLine + " Type mismatch, bitwise operators require arguments of integral type");
            }

            return(INT);
        }
        private ISymbolType StdAssign(LSLAst lhs, LSLAst rhs, int tlhs, int trhs)
        {
            rhs.promoteToType = promoteFromTo[trhs, tlhs];
            if (!CanAssignTo(rhs.evalType, lhs.evalType, rhs.promoteToType))
            {
                _listener.Error(
                    "line " + lhs.Line + ":" + lhs.CharPositionInLine + " " + text(lhs) + " and " +
                    text(rhs) + " have incompatible types in " +
                    text((LSLAst)lhs.Parent)
                    );

                return(VOID);
            }

            return(lhs.evalType);
        }
        private ISymbolType[,] FindOperationTable(LSLAst lhs, string op)
        {
            ISymbolType[,] symTable;
            switch (op)
            {
            case "+":
            case "+=":
                symTable = additionResultType;
                break;

            case "-":
            case "-=":
                symTable = subtractionResultType;
                break;

            case "*":
            case "*=":
                symTable = multiplicationResultType;
                break;

            case "/":
            case "/=":
                symTable = divisionResultType;
                break;

            case "%":
            case "%=":
                symTable = modResultType;
                break;

            case "<<":
            case ">>":
            case ">>=":
            case "<<=":
                symTable = shiftResultType;
                break;

            default:
                _listener.Error("line " + lhs.Token.Line + ":" +
                                lhs.Token.CharPositionInLine + " Internal error. No such operation '" + op + "'");
                symTable = null;
                break;
            }

            return(symTable);
        }
        public void DeclInit(LSLAst varName, LSLAst initExpr)
        {
            int tlhs = varName.symbol.Type.TypeIndex; // promote right to left type?

            varName.evalType = varName.symbol.Type;
            int trhs = initExpr.evalType.TypeIndex;

            initExpr.promoteToType = promoteFromTo[trhs, tlhs];
            if (!CanAssignTo(initExpr.evalType, varName.evalType, initExpr.promoteToType))
            {
                _listener.Error(
                    "line " + varName.Line + ":" + varName.CharPositionInLine + " " + text(varName) + " and " +
                    text(initExpr) + " have incompatible types in " +
                    text((LSLAst)initExpr.Parent)
                    );
            }
        }
        public ISymbolType Assign(string type, LSLAst lhs, LSLAst rhs)
        {
            if (HasUnknownTypes(lhs, rhs))
            {
                return(VOID);
            }

            //the left hand side needs to be assignable
            if (!IsAssignable(lhs))
            {
                return(VOID);
            }

            int tlhs = lhs.evalType.TypeIndex; // promote right to left type?
            int trhs = rhs.evalType.TypeIndex;

            if (type == "=")
            {
                return(StdAssign(lhs, rhs, tlhs, trhs));
            }

            ISymbolType[,] opTable = FindOperationTable(lhs, type);
            if (opTable == null)
            {
                return(VOID);
            }

            ISymbolType symType = opTable[lhs.evalType.TypeIndex, rhs.evalType.TypeIndex];

            if (symType == VOID)
            {
                if (lhs.Type == LSLParser.EXPR)
                {
                    lhs = (LSLAst)lhs.Children[0];
                }

                _listener.Error("line " + lhs.Token.Line + ":" +
                                lhs.Token.CharPositionInLine + " '" + type + "' is not a valid operation between " +
                                lhs.evalType.Name + " and " + rhs.evalType.Name);
                return(VOID);
            }

            return(symType);
        }
        public bool HaveSameTypes(LSLAst lhs, LSLAst rhs)
        {
            if (lhs.evalType == null || rhs.evalType == null)
            {
                _listener.Error("line " + lhs.Token.Line + ":" +
                                lhs.Token.CharPositionInLine + "Can not compare types, at least one type is unknown " + lhs.Text + ", " + rhs.Text);

                return(false);
            }

            if (lhs.evalType == rhs.evalType ||
                (lhs.promoteToType == rhs.promoteToType && lhs.promoteToType != null && rhs.promoteToType != null) ||
                lhs.evalType == rhs.promoteToType ||
                rhs.evalType == lhs.promoteToType)
            {
                return(true);
            }

            return(false);
        }
        private bool IsChildNodeOf(LSLAst sym, LSLAst node)
        {
            if (sym == null || sym.Children == null)
            {
                return(false);
            }

            foreach (Antlr.Runtime.Tree.ITree childNode in sym.Children)
            {
                if (childNode == node)
                {
                    return(true);
                }

                if (IsChildNodeOf((LSLAst)childNode, node))
                {
                    return(true);
                }
            }

            return(false);
        }
        public ISymbolType EqOp(LSLAst lhs, LSLAst rhs)
        {
            if (HasUnknownTypes(lhs, rhs))
            {
                return(VOID);
            }

            //equality operations must be between the same types
            int tlhs = lhs.evalType.TypeIndex; // promote right to left type?
            int trhs = rhs.evalType.TypeIndex;

            rhs.promoteToType = promoteFromTo[trhs, tlhs];
            lhs.promoteToType = promoteFromTo[tlhs, trhs];

            if (!HaveSameTypes(lhs, rhs))
            {
                _listener.Error("line " + lhs.Token.Line + ":" +
                                lhs.Token.CharPositionInLine + " Type mismatch, equality operators == and != require arguments of the same type");
            }

            return(INT);
        }
        public ISymbolType TypeCast(LSLAst expr, LSLAst type)
        {
            if (HasUnknownType(expr))
            {
                return(VOID);
            }

            int texpr = expr.evalType.TypeIndex;

            //type must be a builtin type
            ISymbolType toType = (ISymbolType)_globals.Resolve(type.Text);
            int         ttype  = toType.TypeIndex;

            if (!CanCast(texpr, ttype))
            {
                _listener.Error(
                    "line " + type.Line + ":" + type.CharPositionInLine + " Can not cast from "
                    + expr.evalType.Name + " to " + type.Text
                    );
            }

            return(toType);
        }
        public ISymbolType Uminus(LSLAst a)
        {
            if (a.evalType == null)
            {
                _listener.Error(
                    "line " + a.Token.Line + ":" + a.Token.CharPositionInLine +
                    " Unknown type in expression -" + a.Text
                    );

                return(VOID);
            }

            //only integer, float, vector and rotations can be negated
            if (!TypeIsIn(a.evalType, new ISymbolType[] { INT, FLOAT, VECTOR, ROTATION }))
            {
                _listener.Error(
                    "line " + a.Token.Line + ":" + a.Token.CharPositionInLine +
                    " Unary minus (-N) not valid for type " + a.evalType.Name
                    );
            }

            return(a.evalType);
        }
        public ISymbolType UBitNot(LSLAst a)
        {
            if (a.evalType == null)
            {
                _listener.Error(
                    "line " + a.Token.Line + ":" + a.Token.CharPositionInLine +
                    " Unknown type in expression !" + a.Text
                    );

                return(VOID);
            }

            if (a.evalType != INT)
            {
                _listener.Error(
                    "line " + a.Token.Line + ":" + a.Token.CharPositionInLine +
                    " Bitwise not (~) not valid for type " + a.evalType.Name
                    );

                return(VOID);
            }

            return(INT);
        }
        public void CheckReturn(LSLAst retStmt, LSLAst retExpr)
        {
            //return must match function type
            if (retExpr == null)
            {
                if (retStmt.symbol.Type == VOID)
                {
                    //void return type with void result
                    return;
                }
                else
                {
                    _listener.Error(
                        "line " + retStmt.Token.Line + ":" + retStmt.Token.CharPositionInLine +
                        " Function must return a value"
                        );

                    return;
                }
            }

            if (HasUnknownType(retExpr))
            {
                return;
            }

            //check promotions and return
            retExpr.promoteToType = promoteFromTo[retExpr.evalType.TypeIndex, retStmt.symbol.Type.TypeIndex];
            if (!CanAssignTo(retExpr.evalType, retStmt.symbol.Type, retExpr.promoteToType))
            {
                _listener.Error(
                    "line " + retStmt.Token.Line + ":" + retStmt.Token.CharPositionInLine +
                    " Invalid return type " + retExpr.evalType.Name + ", expecting " + retStmt.symbol.Type.Name
                    );
            }
        }
        public ISymbolType MethodCall(LSLAst id, IList <LSLAst> args)
        {
            Symbol s = id.scope.Resolve(id.Text + "()");

            if (s == null)
            {
                _listener.Error(
                    "line " + id.Token.Line + ":" + id.Token.CharPositionInLine +
                    " Call to undefined function " + id.Text + "()"
                    );

                return(VOID);
            }

            MethodSymbol ms = (MethodSymbol)s;

            id.symbol = ms;

            //check the call parameters
            if (!AllTypesAreResolved(args))
            {
                _listener.Error(
                    "line " + id.Token.Line + ":" + id.Token.CharPositionInLine +
                    " Method call contains expression(s) of unknown type"
                    );

                return(ms.Type);
            }

            //check param count and type
            if (args.Count != ms.Members.Count)
            {
                _listener.Error(
                    "line " + id.Token.Line + ":" + id.Token.CharPositionInLine +
                    " Function " + id.Text + "() takes " + Convert.ToString(ms.Members.Count) +
                    " parameters, " + args.Count + " given"
                    );

                return(ms.Type);
            }


            List <ParmAndExpected> erroredParms = new List <ParmAndExpected>();
            IEnumerator <Symbol>   correctParms = ms.Members.GetEnumerator();

            foreach (LSLAst parm in args)
            {
                correctParms.MoveNext();

                //promote if necessary
                parm.promoteToType = promoteFromTo[parm.evalType.TypeIndex, correctParms.Current.Type.TypeIndex];

                if (!CanAssignTo(parm.evalType, correctParms.Current.Type, parm.promoteToType))
                {
                    erroredParms.Add(new ParmAndExpected {
                        Parm = parm, Expected = correctParms.Current
                    });
                }
            }

            //one of the parameter types is incompatible
            if (erroredParms.Count > 0)
            {
                _listener.Error("line " + id.Token.Line + ":" + id.Token.CharPositionInLine +
                                " In call of function " + id.Text + "(): ");

                foreach (ParmAndExpected error in erroredParms)
                {
                    _listener.Error(
                        "line " + error.Parm.Token.Line + ":" + error.Parm.Token.CharPositionInLine +
                        " Parameter " + error.Expected.Name + ", expected " + error.Expected.Type.Name +
                        " got " + error.Parm.evalType.Name
                        );
                }
            }

            return(ms.Type);
        }
 public ISymbolType Unot(LSLAst a)
 {
     return(INT);
 }
 public ISymbolType PostDec(LSLAst a)
 {
     return(PreDec(a));
 }
 public ISymbolType PostInc(LSLAst a)
 {
     return(PreInc(a));
 }