this repo has no description
at fixPythonPipStalling 342 lines 8.1 kB view raw
1#include "ResourceDefinitions.h" 2#include <ostream> 3#include <cassert> 4 5#include "ResourceCompiler.h" 6#include "Diagnostic.h" 7 8 9std::ostream &operator<<(std::ostream &out, TypeSpec ts) 10{ 11 out << ts.getType(); 12 if(ts.hasID()) 13 out << " (" << ts.getID() << ")"; 14 return out; 15} 16 17 18FieldList::~FieldList() 19{ 20 21} 22 23void FieldList::addField(FieldPtr field, yy::location loc) 24{ 25 field->location = loc; 26 fields.push_back(field); 27} 28 29void FieldList::addLabel(std::string name, yy::location loc) 30{ 31 addField(std::make_shared<LabelField>(name), loc); 32} 33 34void FieldList::compile(ExprPtr expr, ResourceCompiler *compiler, bool prePass) 35{ 36 CompoundExprPtr compound = std::dynamic_pointer_cast<CompoundExpr>(expr); 37 assert(compound); 38 39 int i = 0; 40 for(FieldPtr f : fields) 41 { 42 if(f->needsValue()) 43 { 44 if(i >= compound->size()) 45 compiler->problem(Diagnostic(Diagnostic::error,"not enough values specified", compound->location)); 46 else 47 f->compile(compound->getItem(i++), compiler, prePass); 48 } 49 else 50 f->compile(nullptr, compiler, prePass); 51 } 52 if(i < compound->size()) 53 { 54 compiler->problem(Diagnostic(Diagnostic::error,"extra value specified", 55 compound->getItem(i)->location)); 56 } 57} 58 59 60 61 62void SimpleField::addNamedValue(std::string n) 63{ 64 if(lastNamedValue) 65 addNamedValue(n, std::make_shared<BinaryExpr>( 66 BinaryOp::PLUS, lastNamedValue, std::make_shared<IntExpr>(1, yy::location()), yy::location())); 67 else 68 addNamedValue(n, std::make_shared<IntExpr>(0, yy::location())); 69} 70 71void SimpleField::addNamedValue(std::string n, ExprPtr val) 72{ 73 namedValues[n] = val; 74 lastNamedValue = val; 75} 76 77ExprPtr SimpleField::lookupNamedValue(std::string n) 78{ 79 auto p = namedValues.find(n); 80 if(p != namedValues.end()) 81 return p->second; 82 else 83 return nullptr; 84} 85 86bool SimpleField::needsValue() 87{ 88 return !value; 89} 90 91void SimpleField::compile(ExprPtr expr, ResourceCompiler *compiler, bool prePass) 92{ 93 switch(type) 94 { 95 case Type::bitstring: 96 case Type::boolean: 97 case Type::byte: 98 case Type::integer: 99 case Type::longint: 100 compileInt(expr, compiler, prePass); 101 break; 102 case Type::string: 103 case Type::wstring: 104 case Type::pstring: 105 case Type::char_: 106 compileString(expr, compiler, prePass); 107 break; 108 109 case Type::rect: 110 case Type::point: 111 compileCompound(expr, compiler, prePass); 112 break; 113 114 } 115} 116 117void SimpleField::compileString(ExprPtr expr, ResourceCompiler *compiler, bool prePass) 118{ 119 std::string str; 120 { 121 ResourceCompiler::FieldScope scope(compiler, this); 122 str = (value ? value : expr)->evaluateString(compiler); 123 } 124 125 if(arrayCount || type == Type::char_) 126 { 127 unsigned requestedSize = type == Type::char_ ? 1 : arrayCount->evaluateInt(compiler); 128 if(requestedSize < str.size()) 129 str.erase(str.begin() + requestedSize, str.end()); 130 else if(requestedSize > str.size()) 131 str.insert(str.end(),requestedSize - str.size(), '\0'); 132 } 133 134 int count = str.size(); 135 136 if(type == Type::pstring) 137 { 138 if(count > 255) 139 { 140 str.erase(str.begin() + 255, str.end()); 141 count = 255; 142 } 143 compiler->write(8, count); 144 } 145 else if(type == Type::wstring) 146 { 147 if(count > 65535) 148 { 149 str.erase(str.begin() + 65535, str.end()); 150 count = 65535; 151 } 152 compiler->write(16, count); 153 } 154 155 for(char c : str) 156 compiler->write(8, c); 157} 158 159void SimpleField::compileInt(ExprPtr expr, ResourceCompiler *compiler, bool prePass) 160{ 161 int bitSize = 0; 162 163 switch(type) 164 { 165 case Type::bitstring: 166 bitSize = arrayCount->evaluateInt(compiler); 167 break; 168 case Type::boolean: 169 bitSize = 1; 170 break; 171 case Type::byte: 172 bitSize = 8; 173 break; 174 case Type::integer: 175 bitSize = 16; 176 break; 177 case Type::longint: 178 bitSize = 32; 179 break; 180 default: 181 assert(false); 182 } 183 184 int actualValue = 0; 185 ResourceCompiler::FieldScope scope(compiler, this); 186 actualValue = (value ? value : expr)->evaluateInt(compiler); 187 188 compiler->write(bitSize, actualValue); 189} 190 191void SimpleField::compileCompound(ExprPtr expr, ResourceCompiler *compiler, bool prePass) 192{ 193 ExprPtr val = value ? value : expr; 194 if(IdentifierExprPtr id = std::dynamic_pointer_cast<IdentifierExpr>(val)) 195 { 196 ResourceCompiler::FieldScope scope(compiler, this); 197 val = id->lookup(compiler); 198 } 199 200 int count = 0; 201 switch(type) 202 { 203 case Type::rect: 204 count = 4; 205 break; 206 case Type::point: 207 count = 2; 208 break; 209 default: 210 assert(false); 211 } 212 213 CompoundExprPtr compound = std::dynamic_pointer_cast<CompoundExpr>(val); 214 if(!compound || compound->size() != count) 215 { 216 expr->error(compiler, std::string("expected ") + (type == Type::rect ? "rect {t,l,b,r}." : "point {v,h}.")); 217 return; 218 } 219 assert(compound); 220 assert(compound->size() == count); 221 222 for(int i = 0; i < count; i++) 223 { 224 int x = compound->getItem(i)->evaluateInt(compiler); 225 compiler->write(16, x); 226 } 227} 228 229 230ArrayField::ArrayField(std::string name, ExprPtr count) 231 : name(name), arrayCount(count) 232{ 233} 234 235void ArrayField::compile(ExprPtr expr, ResourceCompiler *compiler, bool prePass) 236{ 237 CompoundExprPtr compound = std::dynamic_pointer_cast<CompoundExpr>(expr); 238 assert(compound); 239 240 241 int i = 0; 242 int n = compound->size(); 243 244 int iterations = 0; 245 while(i < n) 246 { 247 ++iterations; 248 ResourceCompiler::ArrayScope scope(compiler, name, iterations); 249 for(FieldPtr f : fields) 250 { 251 if(f->needsValue()) 252 { 253 assert(i < n); 254 f->compile(compound->getItem(i++), compiler, prePass); 255 } 256 else 257 f->compile(nullptr, compiler, prePass); 258 } 259 } 260 261 if(!prePass && arrayCount) 262 { 263 int expected = arrayCount->evaluateInt(compiler); 264 assert(expected == iterations); 265 } 266} 267 268 269LabelField::LabelField(std::string name) 270 : name(name) 271{ 272} 273 274bool LabelField::needsValue() 275{ 276 return false; 277} 278 279void LabelField::compile(ExprPtr expr, ResourceCompiler *compiler, bool prePass) 280{ 281 compiler->defineLabel(name); 282} 283 284 285void SwitchField::addCase(const std::string name, FieldListPtr alternative) 286{ 287 cases[name] = alternative; 288} 289 290void SwitchField::compile(ExprPtr expr, ResourceCompiler *compiler, bool prePass) 291{ 292 CaseExprPtr caseExpr = std::dynamic_pointer_cast<CaseExpr>(expr); 293 assert(caseExpr); 294 295 FieldListPtr caseDefinition = cases[caseExpr->tag]; 296 assert(caseDefinition); 297 298 caseDefinition->compile(caseExpr->expr, compiler, prePass); 299} 300 301 302FillAlignField::FillAlignField(FillAlignField::Type type, bool isAlign, ExprPtr count) 303 : type(type), count(count), isAlign(isAlign) 304{ 305 306} 307 308bool FillAlignField::needsValue() 309{ 310 return false; 311} 312 313void FillAlignField::compile(ExprPtr expr, ResourceCompiler *compiler, bool prePass) 314{ 315 int bitSize; 316 switch(type) 317 { 318 case Type::bit: bitSize = 1; break; 319 case Type::nibble: bitSize = 4; break; 320 case Type::byte: bitSize = 8; break; 321 case Type::word: bitSize = 16; break; 322 case Type::long_: bitSize = 32; break; 323 } 324 325 int actualCount = 1; 326 if(count) 327 actualCount = count->evaluateInt(compiler); 328 329 for(int i = 0; i < actualCount; i++) 330 { 331 int n; 332 if(isAlign) 333 { 334 int mask = bitSize - 1; 335 int pos = compiler->tell(); 336 n = ((pos + mask) & ~mask) - pos; 337 } 338 else 339 n = bitSize; 340 compiler->write(n, 0); 341 } 342}