private bool TryLookupType(string typeName, out TypeInfo typeInfo) { if (BuiltInPrimitives.TryGetValue(typeName, out typeInfo)) { return(true); } return(userDefinedTypes.TryGetValue(typeName, out typeInfo)); }
private string EvaluateOperator(Operator op, string varName) { bool isSpecialVar = SpecialVariables.AllSpecialVariables.Contains(varName); bool isLocalVar = TryLookupLocal(varName, out double localVarVal); // Handle special variables if (isSpecialVar) { if (op != Operator.ValueOf) { Log(LogLevel.Warning, "Operator {0} cannot be used on special variable '{1}'.", op, varName); return(""); } switch (varName) { case SpecialVariables.Filesize: return(file.Length + ""); case SpecialVariables.GlobalOffset: return(GlobalOffset + ""); case SpecialVariables.Offset: return(CurrentCodeBlock.Offset + ""); } } // Handle local variables if (isLocalVar) { if (op != Operator.ValueOf) { Log(LogLevel.Warning, "Operator {0} cannot be used on local variable '{1}'.", op, varName); return(""); } return(localVarVal + ""); } bool isVar = CurrentCodeBlock.Symbol.TryLookup(varName, out SymbolTable sym); bool isUserDefinedType = userDefinedTypes.TryGetValue(varName, out TypeInfo usrType); bool isBuiltinType = BuiltInPrimitives.TryGetValue(varName, out TypeInfo builtinType); if (!(isVar || isUserDefinedType || isBuiltinType)) { // TODO: get statement. Perhaps throw a different exception and have Caller of ResolveVariables catch and handle it string msg = "Unknown variable or typename '{0}'"; throw LayoutScriptException.Create <LayoutScriptException>(layout, null, msg, varName); } string val = ""; switch (op) { case Operator.GlobalOffsetOf: if (CurrentCodeBlock.IsProcessingTypedef) { string msg = "GlobalOffsetOf operator not valid within type definitions."; throw LayoutScriptException.Create <LayoutScriptException>(layout, null, msg, varName); } if (isVar) { val = sym.GlobalDataAddress.ToString(); } else { string msg = "GlobalOffsetOf operator not valid for types."; throw LayoutScriptException.Create <LayoutScriptException>(layout, null, msg, varName); } break; case Operator.OffsetOf: if (CurrentCodeBlock.IsProcessingTypedef) { string msg = "OffsetOf operator not valid within type definitions."; throw LayoutScriptException.Create <LayoutScriptException>(layout, null, msg, varName); } if (isVar) { val = sym.LocalDataAddress.ToString(); } else { string msg = "OffsetOf operator not valid for types."; throw LayoutScriptException.Create <LayoutScriptException>(layout, null, msg, varName); } break; case Operator.SizeOf: if (isVar) { val = sym.DataLength.ToString(); } else if (isBuiltinType) { val = builtinType.Size.ToString(); } else if (isUserDefinedType) { val = usrType.Size.ToString(); } break; case Operator.ValueOf: if (CurrentCodeBlock.IsProcessingTypedef) { string msg = "ValueOf operator not valid within type definitions."; throw LayoutScriptException.Create <LayoutScriptException>(layout, null, msg, varName); } if (isVar) { val = StringValueOf(sym); } else { string msg = "ValueOf operator not valid for types."; throw LayoutScriptException.Create <LayoutScriptException>(layout, null, msg, varName); } break; } return(val); }