$search
00001 /* 00002 Aseba - an event-based framework for distributed robot control 00003 Copyright (C) 2007--2012: 00004 Stephane Magnenat <stephane at magnenat dot net> 00005 (http://stephane.magnenat.net) 00006 and other contributors, see authors.txt for details 00007 00008 This program is free software: you can redistribute it and/or modify 00009 it under the terms of the GNU Lesser General Public License as published 00010 by the Free Software Foundation, version 3 of the License. 00011 00012 This program is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 GNU Lesser General Public License for more details. 00016 00017 You should have received a copy of the GNU Lesser General Public License 00018 along with this program. If not, see <http://www.gnu.org/licenses/>. 00019 */ 00020 00021 #include "compiler.h" 00022 #include "../common/consts.h" 00023 #include "tree.h" 00024 #include "../utils/FormatableString.h" 00025 #include <cassert> 00026 #include <cstdlib> 00027 #include <sstream> 00028 #include <iostream> 00029 #include <fstream> 00030 #include <iomanip> 00031 #include <memory> 00032 #include <limits> 00033 #ifndef __APPLE__ 00034 #include <malloc.h> 00035 #endif 00036 00037 namespace Aseba 00038 { 00045 00047 std::wstring SourcePos::toWString() const 00048 { 00049 if (valid) 00050 { 00051 std::wostringstream oss; 00052 oss << row + 1 << ':' << column; 00053 return oss.str(); 00054 } 00055 else 00056 return L""; 00057 } 00058 00060 bool NamedValuesVector::contains(const std::wstring& s, size_t* position) const 00061 { 00062 for (size_t i = 0; i < size(); i++) 00063 { 00064 if ((*this)[i].name == s) 00065 { 00066 if (position) 00067 *position = i; 00068 return true; 00069 } 00070 } 00071 return false; 00072 } 00073 00075 template <class T> unsigned int editDistance(const T& s1, const T& s2, const unsigned maxDist) 00076 { 00077 const size_t len1 = s1.size() + 1, len2 = s2.size() + 1; 00078 const size_t matSize(len1*len2); 00079 unsigned *d(reinterpret_cast<unsigned*>(alloca(matSize*sizeof(unsigned)))); 00080 00081 d[0] = 0; 00082 for(unsigned i = 1; i < len1; ++i) 00083 d[i*len2+0] = i; 00084 for(unsigned i = 1; i < len2; ++i) 00085 d[i] = i; 00086 00087 for(unsigned i = 1; i < len1; ++i) 00088 { 00089 bool wasBelowMax(false); 00090 for(unsigned j = 1; j < len2; ++j) 00091 { 00092 const unsigned cost = std::min(std::min( 00093 d[(i - 1)*len2+j] + 1, 00094 d[i*len2+(j - 1)] + 1), 00095 d[(i - 1)*len2+(j - 1)] + (s1[i - 1] == s2[j - 1] ? 0 : 1) 00096 ); 00097 if (cost < maxDist) 00098 wasBelowMax = true; 00099 d[i*len2+j] = cost; 00100 } 00101 if (!wasBelowMax) 00102 return maxDist; 00103 } 00104 return d[matSize-1]; 00105 } 00106 00108 template <typename MapType> 00109 typename MapType::const_iterator findInTable(const MapType& map, const std::wstring& name, const SourcePos& pos, const ErrorCode notFoundError, const ErrorCode misspelledError) 00110 { 00111 typename MapType::const_iterator it(map.find(name)); 00112 if (it == map.end()) 00113 { 00114 const unsigned maxDist(3); 00115 std::wstring bestName; 00116 unsigned bestDist(std::numeric_limits<unsigned>::max()); 00117 for (typename MapType::const_iterator jt(map.begin()); jt != map.end(); ++jt) 00118 { 00119 const std::wstring thatName(jt->first); 00120 const unsigned d(editDistance<std::wstring>(name, thatName, maxDist)); 00121 if (d < bestDist && d < maxDist) 00122 { 00123 bestDist = d; 00124 bestName = thatName; 00125 } 00126 } 00127 if (bestDist < maxDist) 00128 throw TranslatableError(pos, misspelledError).arg(name).arg(bestName); 00129 else 00130 throw TranslatableError(pos, notFoundError).arg(name); 00131 } 00132 return it; 00133 } 00134 00136 Compiler::VariablesMap::const_iterator Compiler::findVariable(const std::wstring& varName, const SourcePos& varPos) const 00137 { 00138 return findInTable<VariablesMap>(variablesMap, varName, varPos, ERROR_VARIABLE_NOT_DEFINED, ERROR_VARIABLE_NOT_DEFINED_GUESS); 00139 } 00140 00142 Compiler::FunctionsMap::const_iterator Compiler::findFunction(const std::wstring& funcName, const SourcePos& funcPos) const 00143 { 00144 return findInTable<FunctionsMap>(functionsMap, funcName, funcPos, ERROR_FUNCTION_NOT_DEFINED, ERROR_FUNCTION_NOT_DEFINED_GUESS); 00145 } 00146 00148 Compiler::ConstantsMap::const_iterator Compiler::findConstant(const std::wstring& name, const SourcePos& pos) const 00149 { 00150 return findInTable<ConstantsMap>(constantsMap, name, pos, ERROR_CONSTANT_NOT_DEFINED, ERROR_CONSTANT_NOT_DEFINED_GUESS); 00151 } 00152 00154 bool Compiler::constantExists(const std::wstring& name) const 00155 { 00156 return constantsMap.find(name) != constantsMap.end(); 00157 } 00158 00160 Compiler::EventsMap::const_iterator Compiler::findGlobalEvent(const std::wstring& name, const SourcePos& pos) const 00161 { 00162 try 00163 { 00164 return findInTable<EventsMap>(globalEventsMap, name, pos, ERROR_EVENT_NOT_DEFINED, ERROR_EVENT_NOT_DEFINED_GUESS); 00165 } 00166 catch (TranslatableError e) 00167 { 00168 if (allEventsMap.find(name) != allEventsMap.end()) 00169 throw TranslatableError(pos, ERROR_EMIT_LOCAL_EVENT).arg(name); 00170 else 00171 throw e; 00172 } 00173 } 00174 00175 Compiler::EventsMap::const_iterator Compiler::findAnyEvent(const std::wstring& name, const SourcePos& pos) const 00176 { 00177 return findInTable<EventsMap>(allEventsMap, name, pos, ERROR_EVENT_NOT_DEFINED, ERROR_EVENT_NOT_DEFINED_GUESS); 00178 } 00179 00181 Compiler::SubroutineReverseTable::const_iterator Compiler::findSubroutine(const std::wstring& name, const SourcePos& pos) const 00182 { 00183 return findInTable<SubroutineReverseTable>(subroutineReverseTable, name, pos, ERROR_SUBROUTINE_NOT_DEFINED, ERROR_SUBROUTINE_NOT_DEFINED_GUESS); 00184 } 00185 00187 void Compiler::buildMaps() 00188 { 00189 assert(targetDescription); 00190 freeVariableIndex = 0; 00191 00192 // erase tables 00193 implementedEvents.clear(); 00194 subroutineTable.clear(); 00195 subroutineReverseTable.clear(); 00196 00197 // fill variables map 00198 variablesMap.clear(); 00199 for (unsigned i = 0; i < targetDescription->namedVariables.size(); i++) 00200 { 00201 variablesMap[targetDescription->namedVariables[i].name] = 00202 std::make_pair(freeVariableIndex, targetDescription->namedVariables[i].size); 00203 freeVariableIndex += targetDescription->namedVariables[i].size; 00204 } 00205 00206 // fill functions map 00207 functionsMap.clear(); 00208 for (unsigned i = 0; i < targetDescription->nativeFunctions.size(); i++) 00209 { 00210 functionsMap[targetDescription->nativeFunctions[i].name] = i; 00211 } 00212 00213 // fill contants maps 00214 constantsMap.clear(); 00215 for (unsigned i = 0; i < commonDefinitions->constants.size(); i++) 00216 { 00217 const NamedValue &constant(commonDefinitions->constants[i]); 00218 constantsMap[constant.name] = constant.value; 00219 } 00220 00221 // fill global events map 00222 globalEventsMap.clear(); 00223 for (unsigned i = 0; i < commonDefinitions->events.size(); i++) 00224 { 00225 globalEventsMap[commonDefinitions->events[i].name] = i; 00226 } 00227 00228 // fill global all events map 00229 allEventsMap = globalEventsMap; 00230 for (unsigned i = 0; i < targetDescription->localEvents.size(); ++i) 00231 { 00232 allEventsMap[targetDescription->localEvents[i].name] = ASEBA_EVENT_LOCAL_EVENTS_START - i; 00233 } 00234 } 00235 00238 } // Aseba