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 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 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 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 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 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); }
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) ); } }
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 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 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 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 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 Symbol EnsureResolve(LSLAst node, IScope scope, string symName) { Symbol sym = scope.Resolve(symName); if (sym == null) { _listener.Error("line " + node.Token.Line + ":" + node.Token.CharPositionInLine + " Undefined symbol '" + symName + "'"); return null; } //globals are always ok to ref, so skip the rest of the checks if this is a global if (sym.Scope == Globals) { return sym; } //consts are always ok to ref if (sym is ConstantSymbol) { return sym; } if (sym.Def == null) { _listener.Error(String.Format("INTERNAL COMPILER ERROR: Symbol definition not set: {0}", sym)); return sym; } //if the symbol is local, it cant be used before it's defined if (sym.Def.TokenStartIndex > node.TokenStartIndex) { //if we are in a local scope, check if there is a version of this symbol in the function (parameter) scope //then check if there is a version of this symbol on the global scope Symbol methodSymbol = FindSymbolInMethodScope(sym, scope); Symbol globalSymbol = Globals.Resolve(symName); if (methodSymbol == null && globalSymbol == null) { //there is no global by this name, it's only defined locally and it's defined after //its use _listener.Error("line " + node.Token.Line + ":" + node.Token.CharPositionInLine + " Symbol '" + symName + "' can not be used before it is defined"); } if (methodSymbol != null) sym = methodSymbol; else sym = globalSymbol; } //also if this symbol is local, it can not be defined in the root of the expression from which it is being used else if (IsChildNodeOf((LSLAst)sym.Def.GetAncestor(LSLParser.VAR_DECL), node)) { //the symbol we found is a parent of the declaration and is therefore not valid for use //check parent scopes for a valid symbol Symbol methodSymbol = FindSymbolInMethodScope(sym, scope); Symbol globalSymbol = Globals.Resolve(symName); if (methodSymbol == null && globalSymbol == null) { //there is no global by this name, it's only defined locally and it's defined after //its use _listener.Error("line " + node.Token.Line + ":" + node.Token.CharPositionInLine + " Symbol '" + symName + "' can not be used before it is defined"); } if (methodSymbol != null) sym = methodSymbol; else sym = globalSymbol; } return sym; }
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 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 CheckLogicalExpr(LSLAst expr) { if (expr.evalType != INT) { _listener.Error("line " + expr.Token.Line + ":" + expr.Token.CharPositionInLine + " Logical expressions require integer type"); } }
public ISymbolType Unot(LSLAst a) { 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 PostDec(LSLAst a) { return(PreDec(a)); }
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; }
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; }
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 Unot(LSLAst a) { return INT; }
public ISymbolType PostDec(LSLAst a) { return PreDec(a); }
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 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 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; }
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 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 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; }
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 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 string text(LSLAst t) { string ts = ""; //if (t.evalType != null) ts = ":<" + t.evalType + ">"; return _tokens.ToString(t.TokenStartIndex, t.TokenStopIndex) + ts; }
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 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 PostInc(LSLAst a) { return PreInc(a); }
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 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 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 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 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 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); } }
private void methodDef() { EnterRule_methodDef(); EnterRule("methodDef", 10); TraceIn("methodDef", 10); LSLAst ID1 = default(LSLAst); LSLAst TYPE2 = default(LSLAst); try { DebugEnterRule(GrammarFileName, "methodDef"); DebugLocation(122, 1); try { // Analyze.g:123:2: ( ^( METHOD_DEF ( TYPE )? ID ( . )* ) ) DebugEnterAlt(1); // Analyze.g:123:4: ^( METHOD_DEF ( TYPE )? ID ( . )* ) { DebugLocation(123, 4); DebugLocation(123, 6); Match(input, METHOD_DEF, Follow._METHOD_DEF_in_methodDef264); if (state.failed) { return; } Match(input, TokenTypes.Down, null); if (state.failed) { return; } DebugLocation(123, 17); // Analyze.g:123:17: ( TYPE )? int alt3 = 2; try { DebugEnterSubRule(3); try { DebugEnterDecision(3, false); int LA3_0 = input.LA(1); if ((LA3_0 == TYPE)) { alt3 = 1; } } finally { DebugExitDecision(3); } switch (alt3) { case 1: DebugEnterAlt(1); // Analyze.g:123:17: TYPE { DebugLocation(123, 17); TYPE2 = (LSLAst)Match(input, TYPE, Follow._TYPE_in_methodDef266); if (state.failed) { return; } } break; } } finally { DebugExitSubRule(3); } DebugLocation(123, 23); ID1 = (LSLAst)Match(input, ID, Follow._ID_in_methodDef269); if (state.failed) { return; } DebugLocation(123, 26); // Analyze.g:123:26: ( . )* try { DebugEnterSubRule(4); while (true) { int alt4 = 2; try { DebugEnterDecision(4, false); int LA4_0 = input.LA(1); if (((LA4_0 >= ASSIGN_EQ && LA4_0 <= 95))) { alt4 = 1; } else if ((LA4_0 == UP)) { alt4 = 2; } } finally { DebugExitDecision(4); } switch (alt4) { case 1: DebugEnterAlt(1); // Analyze.g:123:26: . { DebugLocation(123, 26); MatchAny(input); if (state.failed) { return; } } break; default: goto loop4; } } loop4: ; } finally { DebugExitSubRule(4); } Match(input, TokenTypes.Up, null); if (state.failed) { return; } DebugLocation(124, 3); if (state.backtracking == 1) { currentBranch = new FunctionBranch(ID1, (TYPE2 != null?TYPE2.Text:null)); } } } catch (RecognitionException re) { ReportError(re); Recover(input, re); } finally { TraceOut("methodDef", 10); LeaveRule("methodDef", 10); LeaveRule_methodDef(); } DebugLocation(127, 1); } finally { DebugExitRule(GrammarFileName, "methodDef"); } return; }
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 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) ); } }