짠, 저번에 파싱을 통해서 추상언어트리를 만드는걸 했구요, 이제는 가상머신을 구현해볼 차례입니다. 말이 거창하게 가상머신인데, 알고보면 간단한 놈이에요. 명령어를 받아들여서, 해석하고, 그에 따라 적당한 행동을 하면 됩니다. (CPU의 작동원리랑 거의 비슷해요!)
다만 실제로 구현할때 까다로운 부분은 메모리를 관리하는 겁니다. 가비지 컬렉션을 구현해야하니까요. 근데 그런거 없고 그냥 닥치고 shared_ptr로도 어느정도 메모리 관리를 할 수 있어요.
PGLight가 채택한 명령어 체계는 스택기반의 0주소 명령어에요. 스택기반의 명령어 체계는 트리를 후위순회(post order)하면 쉽게 얻어질 수 있고 피연산자의 주소를 계산하는 일이 없어서 코드 생성작업이 간단하기 때문이죠.
일단 스택에 보관될 자료타입에 대해서 정의하는 일이 필요합니다. 동적타이핑 언어답게 자료타입은 자유롭게 변경이 가능합니다. 그렇기에 변수 하나는 반드시 스택 1칸을 차지하므로 명령어를 단순하고 일관적으로 만들수 있습니다.
먼저 PGLight가 지원하는 자료타입이에요.
단순 타입
void : (값이 음슴ㅋ)
정수
실수 : (32비트 부동소수점 float. 64비트는 걍 지원안했음. 쓸일이 없어서...)
문자열 : (UTF-8 포맷이 원칙입니다)
부울
시간
쓰레드
복합 타입
배열
사전 : (키는 단순 타입만 사용할수 있도록 제한했습니다)
호출가능한 타입
함수 : (PGLight 언어의 함수)
C언어 함수 : (외부 C언어 함수)
클로져 : (변수가 캡쳐된 함수)
언어 내부적으로 사용되는 타입
레퍼런스 : (클로져에서 캡쳐된 변수들의 데이터를 공유하기 위해 사용됩니다)
배열 반복자 : (for문에서 배열을 순회하기 위해 사용됩니다)
사전 반복자 : (for문에서 사전을 순회하기 위해 사용됩니다)
정리해보니깐 타입이 은근 많네요. 우리는 이런 타입들을 모두 표현할 추상 클래스를 만들어야합니다ㅋ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
class PGLCompoundData { public : enum Type { None, Integer, Real, String, Boolean, Array, Dictionary, Function, CFunction, Closure, Ref, CVectorIter, CMapIter, Thread, Time, }; enum Cmp { EQ, // == NEQ, // != GT, // > GTE, // >= LS, // < LSE, // <= }; virtual Type GetType() const = 0; //현재 객체의 타입을 반환합니다. virtual ~PGLCompoundData() {} virtual bool Compare( const PGLCompoundData* o) const = 0; // 현재 객체와 o를 비교(< 연산)합니다. 정렬하는데 사용됨 virtual string DebugInfo() const = 0; // 디버깅에 필요한 정보를 문자열로 반환합니다. virtual shared_ptr<PGLCompoundData> OperateAdd( const shared_ptr<PGLCompoundData>& right) const { return nullptr ;} virtual shared_ptr<PGLCompoundData> OperateSub( const shared_ptr<PGLCompoundData>& right) const { return nullptr ;} virtual shared_ptr<PGLCompoundData> OperateMul( const shared_ptr<PGLCompoundData>& right) const { return nullptr ;} virtual shared_ptr<PGLCompoundData> OperateDiv( const shared_ptr<PGLCompoundData>& right) const { return nullptr ;} virtual shared_ptr<PGLCompoundData> OperateMod( const shared_ptr<PGLCompoundData>& right) const { return nullptr ;} virtual shared_ptr<PGLCompoundData> OperatePow( const shared_ptr<PGLCompoundData>& right) const { return nullptr ;} virtual shared_ptr<PGLCompoundData> OperateAnd( const shared_ptr<PGLCompoundData>& right) const { return nullptr ;} virtual shared_ptr<PGLCompoundData> OperateOr( const shared_ptr<PGLCompoundData>& right) const { return nullptr ;} virtual shared_ptr<PGLCompoundData> OperateDot( const string& right) const { return nullptr ;} virtual shared_ptr<PGLCompoundData> OperateSign() const { return nullptr ;} virtual shared_ptr<PGLCompoundData> OperateNot() const { return nullptr ;} virtual shared_ptr<PGLCompoundData> OperateCmp(Cmp cmp, const shared_ptr<PGLCompoundData>& right) const { return nullptr ;} // 여기까진 연산작업입니다. 연산이 불가능할 경우에는 nullptr를 호출해요. virtual void Next() {} virtual bool IsNotEnd() const { return false ;} virtual shared_ptr<PGLCompoundData> GetKey() const { return nullptr ;} virtual shared_ptr<PGLCompoundData> GetValue() const { return nullptr ;} // 반복자를 위한 함수들이에요 virtual shared_ptr<PGLCompoundData> Copy() const { return nullptr ;} // 깊은 복사를 수행하는 함수입니다 }; |
자, 이를 바탕으로 이제 각각의 데이터 타입을 선언해 봅시다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 |
// 단순 타입을 표현하는 클래스. 별건 없어요.. class PGLFirstData : public PGLCompoundData { public : virtual Type GetType() const = 0; virtual ~PGLFirstData() {} }; // void타입을 표현합니다 class PGLVoidData : public PGLFirstData { public : Type GetType() const override { return None;} virtual bool Compare( const PGLCompoundData* o) const ; string DebugInfo() const { return "null" ;} virtual shared_ptr<PGLCompoundData> Copy() const { return make_shared<PGLVoidData>();} }; // 정수 타입 class PGLIntData : public PGLFirstData { public : int data; PGLIntData( int _d = 0) : data(_d) {} Type GetType() const override { return Integer;} virtual bool Compare( const PGLCompoundData* o) const ; virtual shared_ptr<PGLCompoundData> OperateAdd( const shared_ptr<PGLCompoundData>& right) const ; virtual shared_ptr<PGLCompoundData> OperateSub( const shared_ptr<PGLCompoundData>& right) const ; virtual shared_ptr<PGLCompoundData> OperateMul( const shared_ptr<PGLCompoundData>& right) const ; virtual shared_ptr<PGLCompoundData> OperateDiv( const shared_ptr<PGLCompoundData>& right) const ; virtual shared_ptr<PGLCompoundData> OperateMod( const shared_ptr<PGLCompoundData>& right) const ; virtual shared_ptr<PGLCompoundData> OperatePow( const shared_ptr<PGLCompoundData>& right) const ; virtual shared_ptr<PGLCompoundData> OperateSign() const ; virtual shared_ptr<PGLCompoundData> OperateCmp(Cmp cmp, const shared_ptr<PGLCompoundData>& right) const ; // 각각의 연산들은 이따가 구현하는걸로 string DebugInfo() const { char buf[32]; sprintf_s(buf, 32, "%d" , data); return buf;} virtual shared_ptr<PGLCompoundData> Copy() const { return make_shared<PGLIntData>(data);} }; // 실수 타입 class PGLRealData : public PGLFirstData { public : float data; PGLRealData( float _d = 0) : data(_d) {} Type GetType() const override { return Real;} virtual bool Compare( const PGLCompoundData* o) const ; virtual shared_ptr<PGLCompoundData> OperateAdd( const shared_ptr<PGLCompoundData>& right) const ; virtual shared_ptr<PGLCompoundData> OperateSub( const shared_ptr<PGLCompoundData>& right) const ; virtual shared_ptr<PGLCompoundData> OperateMul( const shared_ptr<PGLCompoundData>& right) const ; virtual shared_ptr<PGLCompoundData> OperateDiv( const shared_ptr<PGLCompoundData>& right) const ; virtual shared_ptr<PGLCompoundData> OperateMod( const shared_ptr<PGLCompoundData>& right) const ; virtual shared_ptr<PGLCompoundData> OperatePow( const shared_ptr<PGLCompoundData>& right) const ; virtual shared_ptr<PGLCompoundData> OperateSign() const ; virtual shared_ptr<PGLCompoundData> OperateCmp(Cmp cmp, const shared_ptr<PGLCompoundData>& right) const ; // 각각 연산들은 이따 구현하는걸로 string DebugInfo() const { char buf[32]; sprintf_s(buf, 32, "%f" , data); return buf;} virtual shared_ptr<PGLCompoundData> Copy() const { return make_shared<PGLRealData>(data);} }; // 문자열 타입 class PGLStringData : public PGLFirstData { public : string data; PGLStringData(string _d = string()) : data(_d) {} Type GetType() const override { return String;} virtual bool Compare( const PGLCompoundData* o) const ; virtual shared_ptr<PGLCompoundData> OperateAdd( const shared_ptr<PGLCompoundData>& right) const ; virtual shared_ptr<PGLCompoundData> OperateCmp(Cmp cmp, const shared_ptr<PGLCompoundData>& right) const ; // 역시나 연산은 이따 구현하는걸로 string DebugInfo() const { return "\"" data "\"" ;} virtual shared_ptr<PGLCompoundData> Copy() const { return make_shared<PGLStringData>(data);} }; // 부울 타입 class PGLBooleanData : public PGLFirstData { public : bool data; PGLBooleanData( bool _d = false ) : data(_d) {} Type GetType() const override { return Boolean;} virtual bool Compare( const PGLCompoundData* o) const ; virtual shared_ptr<PGLCompoundData> OperateAnd( const shared_ptr<PGLCompoundData>& right) const ; virtual shared_ptr<PGLCompoundData> OperateOr( const shared_ptr<PGLCompoundData>& right) const ; virtual shared_ptr<PGLCompoundData> OperateNot() const ; virtual shared_ptr<PGLCompoundData> OperateCmp(Cmp cmp, const shared_ptr<PGLCompoundData>& right) const ; string DebugInfo() const { return data ? "true" : "false" ;} virtual shared_ptr<PGLCompoundData> Copy() const { return make_shared<PGLBooleanData>(data);} }; // 함수 타입 class PGLFunctionData : public PGLFirstData { protected : public : int data; // 함수의 주소에요 bool memberFunc; PGLFunctionData( int _d = false ) : data(_d), memberFunc( false ) {} Type GetType() const override { return Function;} virtual bool Compare( const PGLCompoundData* o) const ; string DebugInfo() const { char buf[32]; sprintf_s(buf, 32, "%x" , data); return buf;} virtual shared_ptr<PGLCompoundData> Copy() const { return make_shared<PGLFunctionData>(data);} }; // C함수 타입 class PGLCFunctionData : public PGLFirstData { protected : public : void * data; PGLCFunctionData( void * _d = false ) : data(_d) {} Type GetType() const override { return CFunction;} virtual bool Compare( const PGLCompoundData* o) const ; string DebugInfo() const { char buf[32]; sprintf_s(buf, 32, "%x" , data); return buf;} virtual shared_ptr<PGLCompoundData> Copy() const { return make_shared<PGLCFunctionData>(data);} }; // 시간 타입 class PGLTimeData : public PGLFirstData { public : time_t data; PGLTimeData( time_t _d = 0) : data(_d) {} Type GetType() const override { return Time;} virtual bool Compare( const PGLCompoundData* o) const ; virtual shared_ptr<PGLCompoundData> OperateAdd( const shared_ptr<PGLCompoundData>& right) const ; virtual shared_ptr<PGLCompoundData> OperateSub( const shared_ptr<PGLCompoundData>& right) const ; virtual shared_ptr<PGLCompoundData> OperateMul( const shared_ptr<PGLCompoundData>& right) const ; virtual shared_ptr<PGLCompoundData> OperateDiv( const shared_ptr<PGLCompoundData>& right) const ; virtual shared_ptr<PGLCompoundData> OperateCmp(Cmp cmp, const shared_ptr<PGLCompoundData>& right) const ; virtual shared_ptr<PGLCompoundData> OperateDot( const string& right) const ; string DebugInfo() const { char buf[64]; ctime_s(buf, 64, &data); return buf;} virtual shared_ptr<PGLCompoundData> Copy() const { return make_shared<PGLTimeData>(data);} }; |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 |
// 반복되는 비교 코드를 아예 템플릿화했어요ㅋ template < typename Ty1, typename Ty2> bool compare(Ty1 a, Ty2 b, PGLCompoundData::Cmp cmp) { switch (cmp) { case PGLCompoundData::EQ: return a == b; case PGLCompoundData::NEQ: return a != b; case PGLCompoundData::GT: return a > b; case PGLCompoundData::GTE: return a >= b; case PGLCompoundData::LS: return a < b; case PGLCompoundData::LSE: return a <= b; } return false ; } // 정수의 더하기 연산 shared_ptr<PGLCompoundData> PGLIntData::OperateAdd( const shared_ptr<PGLCompoundData>& right) const { switch (right->GetType()) { //우항이 정수 타입일 경우 case Integer: return make_shared<PGLIntData> (data ((PGLIntData*)right.get())->data); //우항이 실수 타입일 경우 case Real: return make_shared<PGLRealData> (data ((PGLRealData*)right.get())->data); //우항이 문자열 타입일 경우 문자열로 변환해서 합칩니다 case String: { char buf[16]; _itoa_s(data, buf, 16, 10); return make_shared<PGLStringData> (buf ((PGLStringData*)right.get())->data); } //나머지는 연산 실패 default : return nullptr ; } } // 정수의 빼기 연산 shared_ptr<PGLCompoundData> PGLIntData::OperateSub( const shared_ptr<PGLCompoundData>& right) const { switch (right->GetType()) { case Integer: return make_shared<PGLIntData> (data - ((PGLIntData*)right.get())->data); case Real: return make_shared<PGLRealData> (data - ((PGLRealData*)right.get())->data); default : return nullptr ; } } // 정수의 곱하기 연산 shared_ptr<PGLCompoundData> PGLIntData::OperateMul( const shared_ptr<PGLCompoundData>& right) const { switch (right->GetType()) { case Integer: return make_shared<PGLIntData> (data * ((PGLIntData*)right.get())->data); case Real: return make_shared<PGLRealData> (data * ((PGLRealData*)right.get())->data); default : return nullptr ; } } // 정수의 나누기 연산 shared_ptr<PGLCompoundData> PGLIntData::OperateDiv( const shared_ptr<PGLCompoundData>& right) const { switch (right->GetType()) { case Integer: return make_shared<PGLIntData>(data / ((PGLIntData*)right.get())->data); case Real: return make_shared<PGLRealData>(data / ((PGLRealData*)right.get())->data); default : return nullptr ; } } // 정수의 나머지 연산 shared_ptr<PGLCompoundData> PGLIntData::OperateMod( const shared_ptr<PGLCompoundData>& right) const { switch (right->GetType()) { case Integer: return make_shared<PGLIntData>(data % ((PGLIntData*)right.get())->data); //우항이 실수 타입이면 fmod를 사용합니다 case Real: return make_shared<PGLRealData>(fmodf(data, ((PGLRealData*)right.get())->data)); default : return nullptr ; } } // 정수의 거듭제곱 연산 shared_ptr<PGLCompoundData> PGLIntData::OperatePow( const shared_ptr<PGLCompoundData>& right) const { switch (right->GetType()) { case Integer: return make_shared<PGLIntData>(( int ) pow (data, ((PGLIntData*)right.get())->data)); case Real: return make_shared<PGLRealData>(powf(data, ((PGLRealData*)right.get())->data)); default : return nullptr ; } } // 정수의 -부호 연산. 간단하죠 shared_ptr<PGLCompoundData> PGLIntData::OperateSign() const { return make_shared<PGLIntData>(-data); } // 정수의 비교연산 shared_ptr<PGLCompoundData> PGLIntData::OperateCmp(Cmp cmp, const shared_ptr<PGLCompoundData>& right) const { switch (right->GetType()) { case Integer: return make_shared<PGLBooleanData>(compare(data, ((PGLIntData*)right.get())->data, cmp)); case Real: return make_shared<PGLBooleanData>(compare(data, ((PGLIntData*)right.get())->data, cmp)); default : return nullptr ; } } // 실수의 덧셈연산 shared_ptr<PGLCompoundData> PGLRealData::OperateAdd( const shared_ptr<PGLCompoundData>& right) const { switch (right->GetType()) { case Integer: return make_shared<PGLRealData>(data ((PGLIntData*)right.get())->data); case Real: return make_shared<PGLRealData>(data ((PGLRealData*)right.get())->data); case String: { char buf[16]; sprintf_s(buf, 16, "%.3f" , data); return make_shared<PGLStringData>(buf ((PGLStringData*)right.get())->data); } default : return nullptr ; } } // 실수의 뺄셈 연산 shared_ptr<PGLCompoundData> PGLRealData::OperateSub( const shared_ptr<PGLCompoundData>& right) const { switch (right->GetType()) { case Integer: return make_shared<PGLRealData>(data - ((PGLIntData*)right.get())->data); case Real: return make_shared<PGLRealData>(data - ((PGLRealData*)right.get())->data); default : return nullptr ; } } // 실수의 곱셈 연산 shared_ptr<PGLCompoundData> PGLRealData::OperateMul( const shared_ptr<PGLCompoundData>& right) const { switch (right->GetType()) { case Integer: return make_shared<PGLRealData>(data * ((PGLIntData*)right.get())->data); case Real: return make_shared<PGLRealData>(data * ((PGLRealData*)right.get())->data); default : return nullptr ; } } // 실수의 나눗셈 연산 shared_ptr<PGLCompoundData> PGLRealData::OperateDiv( const shared_ptr<PGLCompoundData>& right) const { switch (right->GetType()) { case Integer: return make_shared<PGLRealData>(data / ((PGLIntData*)right.get())->data); case Real: return make_shared<PGLRealData>(data / ((PGLRealData*)right.get())->data); default : return nullptr ; } } // 실수의 나머지 연산 shared_ptr<PGLCompoundData> PGLRealData::OperateMod( const shared_ptr<PGLCompoundData>& right) const { switch (right->GetType()) { case Integer: return make_shared<PGLRealData>(fmodf(data, ((PGLRealData*)right.get())->data)); case Real: return make_shared<PGLRealData>(fmodf(data, ((PGLRealData*)right.get())->data)); default : return nullptr ; } } // 실수의 거듭제곱 연산 shared_ptr<PGLCompoundData> PGLRealData::OperatePow( const shared_ptr<PGLCompoundData>& right) const { switch (right->GetType()) { case Integer: return make_shared<PGLRealData>( pow (data, ((PGLIntData*)right.get())->data)); case Real: return make_shared<PGLRealData>(powf(data, ((PGLRealData*)right.get())->data)); default : return nullptr ; } } // 실수의 -부호 연산 shared_ptr<PGLCompoundData> PGLRealData::OperateSign() const { return make_shared<PGLRealData>(-data); } // 실수의 비교 연산 shared_ptr<PGLCompoundData> PGLRealData::OperateCmp(Cmp cmp, const shared_ptr<PGLCompoundData>& right) const { switch (right->GetType()) { case Integer: return make_shared<PGLBooleanData>(compare(data, ((PGLIntData*)right.get())->data, cmp)); case Real: return make_shared<PGLBooleanData>(compare(data, ((PGLIntData*)right.get())->data, cmp)); default : return nullptr ; } } // 문자열 더하기 연산 shared_ptr<PGLCompoundData> PGLStringData::OperateAdd( const shared_ptr<PGLCompoundData>& right) const { switch (right->GetType()) { case String: return make_shared<PGLStringData>(data ((PGLStringData*)right.get())->data); case Integer: { char buf[16]; _itoa_s(((PGLIntData*)right.get())->data, buf, 16, 10); return make_shared<PGLStringData>(data buf); } case Real: { char buf[16]; sprintf_s(buf, 16, "%.3f" , ((PGLRealData*)right.get())->data); return make_shared<PGLStringData>(data buf); } default : return nullptr ; } } // 문자열 비교 연산 shared_ptr<PGLCompoundData> PGLStringData::OperateCmp(Cmp cmp, const shared_ptr<PGLCompoundData>& right) const { switch (right->GetType()) { case String: return make_shared<PGLBooleanData>(compare(data, ((PGLStringData*)right.get())->data, cmp)); default : return nullptr ; } } // 부울의 and 연산 shared_ptr<PGLCompoundData> PGLBooleanData::OperateAnd( const shared_ptr<PGLCompoundData>& right) const { switch (right->GetType()) { case Boolean: return make_shared<PGLBooleanData>(data && ((PGLBooleanData*)right.get())->data); default : return nullptr ; } } // 부울의 or 연산 shared_ptr<PGLCompoundData> PGLBooleanData::OperateOr( const shared_ptr<PGLCompoundData>& right) const { switch (right->GetType()) { case Boolean: return make_shared<PGLBooleanData>(data || ((PGLBooleanData*)right.get())->data); default : return nullptr ; } } // 부울의 not 연산 shared_ptr<PGLCompoundData> PGLBooleanData::OperateNot() const { return make_shared<PGLBooleanData>(!data); } // 부울의 비교 연산 shared_ptr<PGLCompoundData> PGLBooleanData::OperateCmp(Cmp cmp, const shared_ptr<PGLCompoundData>& right) const { switch (right->GetType()) { case Boolean: return make_shared<PGLBooleanData>(compare(data, ((PGLBooleanData*)right.get())->data, cmp)); default : return nullptr ; } } // 시간의 덧셈 연산 shared_ptr<PGLCompoundData> PGLTimeData::OperateAdd( const shared_ptr<PGLCompoundData>& right) const { switch (right->GetType()) { // 시간은 시간끼리만 더하고 뺄수 있어요 case Time: return make_shared<PGLTimeData> (data static_pointer_cast<PGLTimeData>(right)->data); default : return nullptr ; } } // 시간의 뺄셈연산 shared_ptr<PGLCompoundData> PGLTimeData::OperateSub( const shared_ptr<PGLCompoundData>& right) const { switch (right->GetType()) { case Time: return make_shared<PGLTimeData> (data - static_pointer_cast<PGLTimeData>(right)->data); default : return nullptr ; } } // 시간의 곱셈연산 shared_ptr<PGLCompoundData> PGLTimeData::OperateMul( const shared_ptr<PGLCompoundData>& right) const { switch (right->GetType()) { // 시간은 정수/실수하고만 곱하고 나눌수 있어요 case Integer: return make_shared<PGLTimeData> (data * static_pointer_cast<PGLIntData>(right)->data); case Real: return make_shared<PGLTimeData> (( time_t )(data * static_pointer_cast<PGLRealData>(right)->data)); default : return nullptr ; } } shared_ptr<PGLCompoundData> PGLTimeData::OperateDiv( const shared_ptr<PGLCompoundData>& right) const { switch (right->GetType()) { case Integer: return make_shared<PGLTimeData> (data / static_pointer_cast<PGLIntData>(right)->data); case Real: return make_shared<PGLTimeData> (( time_t )(data / static_pointer_cast<PGLRealData>(right)->data)); default : return nullptr ; } } bool PGLTimeData::Compare( const PGLCompoundData* o) const { if (GetType() < o->GetType()) return true ; if (GetType() > o->GetType()) return false ; return data < (( const PGLTimeData*)o)->data; } shared_ptr<PGLCompoundData> PGLTimeData::OperateCmp(Cmp cmp, const shared_ptr<PGLCompoundData>& right) const { switch (right->GetType()) { case Time: return ConvertToPGLType(compare(data, static_pointer_cast<PGLTimeData>(right)->data, cmp)); default : return nullptr ; } } // dot연산은 내적이 아니라 type.abs ~~에서마냥 마침표를 찍어서 참조하는 연산을 가리킵니다. // 이름을 잘못지은거같네요 shared_ptr<PGLCompoundData> PGLTimeData::OperateDot( const string& right) const { // 우항을 따라 알맞은 메소드를 반환해줍니다. // PGLTimeLibrary는 말그대로 시간 관련 연산을 모아둔 라이브러리입니다. // ConvertToPGLType 템플릿을 이용해 C언어함수를 PGLCFunctionType으로 만들어줍니다 if (right == "@second" ) { return ConvertToPGLType< void *>(PGLTimeLibrary::second); } if (right == "@minute" ) { return ConvertToPGLType< void *>(PGLTimeLibrary::minute); } if (right == "@hour" ) { return ConvertToPGLType< void *>(PGLTimeLibrary::hour); } if (right == "@day" ) { return ConvertToPGLType< void *>(PGLTimeLibrary::day); } if (right == "@date" ) { return ConvertToPGLType< void *>(PGLTimeLibrary::date); } if (right == "@gmdate" ) { return ConvertToPGLType< void *>(PGLTimeLibrary::gmdate); } return nullptr ; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
enum class PGLOpcode : short { NOP, // 아무 것도 하지 않음 PUSH, // 리터럴/전역변수[오퍼랜드1]을 스택에 넣는다 STORE, // 스택에서 자료를 빼서 전역변수[오퍼랜드1]로 설정한다 COPY, // 베이스스택 오퍼랜드1 위치에 있는 자료를 스택에 넣는다 WRITE, // 스택에서 자료 하나를 빼서 베이스스택 오퍼랜드1 위치에 덮어쓴다 POP, // 스택에서 오퍼랜드1개의 자료를 빼낸다 CALL, // 스택에서 주소를 꺼내고, 오퍼랜드1개의 인자를 사용하여 함수 호출 THISCALL, // 스택에서 주소를 꺼내고 this와 오퍼랜드1개의 인자를 사용하여 함수 호출 RETURN, // 반환값을 오퍼랜드1개로 설정하고, 이전 주소로 복귀 YIELD, // 반환값을 오퍼랜드1개로 설정하고, 현 스레드 실행을 중지하고, 부모 스레드에게 권한을 넘긴다 ADD, // 스택에서 2개를 뽑아 더한 결과를 스택에 넣는다 SUB, // 스택에서 2개를 뽑아 뺀 결과를 스택에 넣는다 MUL, // 스택에서 2개를 뽑아 곱한 결과를 스택에 넣는다 DIV, // 스택에서 2개를 뽑아 나눈 결과를 스택에 넣는다 MOD, // 스택에서 2개를 뽑아 나머지 구한 결과를 스택에 넣는다 POW, // 스택에서 2개를 뽑아 n승한 결과를 스택에 넣는다 SIGN, // 스택에서 1개를 뽑아 부호를 반전하여 스택에 넣는다 EQ, // 스택에서 2개를 뽑아 == 연산 결과를 스택에 넣는다 NEQ, // 스택에서 2개를 뽑아 != 연산 결과를 스택에 넣는다 GT, // > GTE, // >= LS, // < LSE, // <= AND, // 스택에서 2개를 뽑아 and 연산한 결과를 스택에 넣는다 OR, // or NOT, // not JMP, // 현재 주소에서 오퍼랜드1변위로 점프한다 UNLESSJMP, // 스택에서 1개를 뽑아, 그 값이 거짓이면, 현재 주소에서 오퍼랜드1변위로 점프한다 PUSHNULL, // 스택에 null을 넣는다 ASSEMBLE, // 스택에서 오퍼랜드1개를 뽑아 배열로 만들어 스택에 넣는다 NEWDICT, // 스택에서 2* 오퍼랜드1개를 뽑아, 차례로 키, 값으로 하는 사전을 만들어 스택에 넣는다 AT, // 스택에서 배열 혹은 사전과 키를 뽑아, 키에 해당하는 값을 스택에 넣는다 LEN, // 스택에서 배열 혹은 사전을 뽑고 그 크기를 구하여 스택에 넣는다 ATD, // 스택에서 배열을 뽑고, 오퍼랜드1번째 원소를 스택에 넣는다 MAKECLOSURE, // 스택에서 함수 주소와 배열을 꺼내 클로져로 묶고, 결과를 스택에 넣는다 SET, // 스택에서 자료와 배열 혹은 사전과 키를 뽑아, 키에 해당하는 값을 자료로 설정한다 SETD, // 스택에서 자료와 배열을 뽑아, 그 배열의 오퍼랜드1번째 원소로 설정한다 REF, // 스택에서 자료를 뽑아, 레퍼런스하여 스택에 넣는다 DEREF, // 스택에서 자료를 뽑아, 디레퍼런스하여 스택에 넣는다 COPYDEREF, // COPY DEREF SETDDEREF, // 스택에서 자료와 배열을 뽑아, 그 배열의 오퍼랜드1번째 원소가 가리키는 값을 그것으로 설정한다 WRITEDEREF, // 스택에서 자료 하나를 빼서 베이스스택 오퍼랜드1위치가 가리키는 값을 그것으로 설정한다 PUSHBEGIN, // 스택 꼭대기에 위치한 배열 혹은 사전에서 순회 첫 지점의 정보를 담는 자료를 스택에 넣는다 ISNOTEND, // 스택 꼭대기에 위치한 순회 지점이 끝에 다다랐으면 거짓, 아니면 참을 스택에 넣는다 NEXT, // 스택 꼭대기에 위치한 순회 지점을 다음으로 설정한다 PUSHKEYVAL, // 스택 꼭대기에 위치한 순회 지점에서 키와 값을 뽑아 스택에 넣는다 FIND, // 스택에서 배열 혹은 사전과 키를 뽑에 키에 해당하는 값을 스택에 넣는다. 값이 없을 경우 런타임 에러 FINDP, // 스택에서 배열 혹은 사전과 키를 뽑에 키에 해당하는 값을 스택에 넣고 배열 혹은 사전을 다시 넣는다. 값이 없을 경우 런타임 에러. }; |
으갸갸. 명령어가 많죠? (생각보다 많은 편은 아닙니다.) 요 명령어들만 있으면 모든 연산이 가능하다는게 놀라울 정도네요.
간단히 훑어보자면
스택에 자료를 넣거나 스택에 있는 자료를 외부로 저장하는 명령어들이 있어요
PUSH, POP, STORE, COPY, WRITE, PUSHNULL
PUSH 같은 경우는 스택에 자료를 넣는놈인데, 뒤에 오는 피연산자는 넣을 자료의 주소를 설정합니다. PGLight어 타입이 다양하고 길어서 코드 안에 직접 자료를 넣을순 없구요, 그 대신에 전역변수와 리터럴들이 모여있는 글로벌 데이터 존을 만들었어요. 거기에서 값을 찾아와서 스택에 넣어주는 역할을 합니다.
POP은 그냥 스택에서 자료를 빼는 녀석이구요
STORE 같은 경우는 글로벌 데이터 존에 자료를 입력하는 역할을 합니다. 값을 읽어오는 PUSH의 반대지요.
COPY는 스택에 있는 자료를 복사해서 마지막에 추가하는 역할을 합니다. 지역변수는 스택에 차곡차곡 저장되거든요. 지역변수 값을 불러올때 사용합니다. 그래서 이놈의 피연산자는 베이스 스택으로부터의 위치를 지정합니다.
WRITE는 스택에 있는 값을 덮어쓰는데 사용됩니다. 지역변수의 값을 설정할때 사용하는거죠. 그래서 이놈 역시 피연산자가 베이스 스택으로부터의 위치를 지정합니다.
PUSHNULL은 널 값을 넣어주는 명령어입니다.
호출과 관련된 명령어들이 있어요
CALL, THISCALL, RETURN, YIELD
CALL은 함수 호출입니다. 피연산자로 함수의 인수 갯수가 들어갑니다. 인수에 앞서 먼저 호출할 함수가 스택에 들어있어야하겠죠. 이 함수가 일반 함수인지, C함수인지, 클로져인지 구분하여 적절하게 다른 일을 하는게 포인트입니다. 당연히 베이스 스택과 호출 스택을 쌓는 역할도 하죠
THISCALL은 클래스 메소드를 위한 함수 호출입니다. 이걸로 함수를 호출할 경우에는 첫번째 인자로 this가 넘어가게 됩니다.
RETURN 은 반환이죠. 함수 수행을 중지하고 호출했던 곳으로 돌아갑니다. 당연히 베이스 스택과 호출 스택을 정리하는 역할도 합니다. 만약 돌아갈 곳이 없는 상태에서 RETURN이 호출되면 실행을 정지합니다.
YIELD는 return과 비슷하지만, 쓰레드의 수행을 일시 정지하고, 자신을 생성시킨 부모 쓰레드에게로 돌아가는 일을 합니다.
연산과 관련된 명령어들이 있어요
산술 ADD, SUB, MUL, DIV, MOD, POW, SIGN
비교 EQ, NEQ, GT, GTE, LS, LSE
논리 AND, OR, NOT
흐름제어와 관련된 명령어들이 있어요
JMP, UNLESSJMP
JMP는 무조건 분기입니다. 분기되는 위치는 상대주소(현재 실행되는 주소를 중심으로하는 변위)로 피연산자에 지정됩니다.
UNLESSJUMP는 조건문과 반복문을 위한 조건분기입니다. 스택에서 가져온 값이 거짓일때 분기를 해요. (왜 거짓일때 분기하도록 했느냐하면, if문과 while문 작동방식이 그렇거든요.) 역시나 피연산자로 상대주소를 지정합니다.
배열, 사전과 관련된 명령어
ASSEMBLE, NEWDICT, AT, ATD, LEN, SET, SETD
ASSEMBLE은 새 배열을 만들어요
NEWDICT는 새 사전을 만들구요
AT은 배열, 사전을 참조합니다.
ATD는 배열을 참조하는데, 참조하는 위치를 스택에서 가져오는것이 아니라 피연산자로 지정합니다. 클로저 구현에 중요하게 사용됩니다.
LEN은 배열, 사전의 크기를 얻어와요
SET은 배열, 사전의 값을 설정해요
SETD는 배열의 값을 설정하는데, 참조하는 위치를 스택에서 가져오는게 아니라 피연산자로 지정합니다.
클로저와 관련된 명령어
MAKECLOSURE, REF, DEREF, COPYDEREF, SETDDEREF, WRITEDEREF
MAKECLOSURE는 함수 주소와 캡쳐 변수 배열을 이용해 클로저 타입을 만듭니다. 이때 캡쳐되는 변수들은 레퍼런스화 되어있어야해요
REF는 스택에 있는 자료를 레퍼런스화하는데 사용합니다. 그 결과 그 값을 여러곳에서 공유하는게 가능해집니다 (c언어의 포인터 & 연산)
DEREF는 스택에 있는 레퍼런스화된 자료를 참조해서 그 값을 가져오는데 사용합니다. (c언어의 포인터 * 연산)
COPYDEREF 는 COPY DEREF를 합친거에요
SETDDEREF 는 SETD DEREF
WRITEDEREF는 WRITE DEREF
순회와 관련된 명령어
PUSHBEGIN, ISNOTEND, NEXT, PUSHKEYVAL
PUSHBEGIN은 배열, 사전의 순회를 시작하기 위해 첫 반복자를 얻는데 사용됩니다
ISNOTEND는 스택에 있는 반복자가 끝에 다다르지 않았으면 참을 스택에 넣습니다
NEXT는 스택에 있는 반복자를 다음으로 넘기구요
PUSHKEYVAL은 스택에 있는 반복자에서 키와 값을 얻어옵니다
명령어를 짰으니, 명령어를 실행하는 머신을 만들어야겠죠?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
//모든 스레드가 공유하는 자원들을 관리하고 //스레드를 생성하는 역할을 합니다 class PGLVM { friend class PGLVMThread; protected : vector< short > m_codes; // 코드 vector<PGLVMDebugInfo> m_debugInfo; // 코드에 대한 디버그 정보 vector<shared_ptr<PGLCompoundData>> m_literal; // 리터럴/전역 변수 공간입니다 vector<string> m_globDebugInfo; // 리터럴/전역 변수 공간에 대한 디버그 정보 public : PGLVM( const FinalData& fd); ~PGLVM(); shared_ptr<PGLVMThread> NewThread(); string _GetDisassembly( const short * codes, size_t size); string GetDisassembly( const char * funcName = nullptr ); }; //실제로 코드를 실행하는 역할을 담당합니다. class PGLVMThread { protected : int m_pc; // 프로그램 카운터. 현재 실행되고 있는 코드의 주소입니다 vector<shared_ptr<PGLCompoundData>> m_stack; // 스택입니다 vector< int > m_stackBase; // 베이스주소 스택입니다 vector< int > m_callstack; // 호출주소 스택입니다 PGLVM* m_mainVM; string m_err; // 에러를 저장하는 놈 size_t m_retCnt; // 반환인수 개수 int m_state; // 현재 상태. 실행중인지 정지인지 public : int ProcNOP(); int ProcPUSH(); int ProcSTORE(); int ProcCOPY(); int ProcWRITE(); int ProcPOP(); int ProcCALL(); int ProcTHISCALL(); int ProcRETURN(); int ProcYIELD(); int ProcADD(); int ProcSUB(); int ProcMUL(); int ProcDIV(); int ProcMOD(); int ProcPOW(); int ProcSIGN(); int ProcEQ(); int ProcNEQ(); int ProcGT(); int ProcGTE(); int ProcLS(); int ProcLSE(); int ProcAND(); int ProcOR(); int ProcNOT(); int ProcJMP(); int ProcUNLESSJMP(); int ProcPUSHNULL(); int ProcASSEMBLE(); int ProcNEWDICT(); int ProcAT(); int ProcLEN(); int ProcATD(); int ProcMAKECLOSURE(); int ProcSET(); int ProcSETD(); int ProcREF(); int ProcDEREF(); int ProcCOPYDEREF(); int ProcSETDDEREF(); int ProcWRITEDEREF(); int ProcPUSHBEGIN(); int ProcISNOTEND(); int ProcNEXT(); int ProcPUSHKEYVAL(); int ProcFIND(); int ProcFINDP(); PGLVMThread(PGLVM* vm); ~PGLVMThread() {} PGLVM* GetVM() const { return m_mainVM;} int Entry( int paramCnt); // 스택에서 paramCnt만큼의 인수를 가져오고, 함수객체를 가져와 함수를 호출합니다. // 처음에 특정함수를 호출하며 쓰레드를 시작하기 위해 사용합니다. int Resume(); // 정지된 쓰레드 재개 int Receive( const shared_ptr<PGLVMThread>& from, int cnt); // 다른 쓰레드로부터 cnt개만큼의 자료를 받아옵니다 int GetState() const { return m_state;} void PushError(PGLVMError e, int addr); shared_ptr<PGLCompoundData> GetParameter( int i); size_t GetParameterCnt() const ; void SetReturnCnt( size_t i); size_t GetReturnCnt() const { return m_retCnt;} void PushNull(); void Push( const shared_ptr<PGLCompoundData>& data); string GetErrMsg() const { return m_err;} }; |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 |
/* 각각의 명령어들은 단순해서 구현하는게 어렵지 않습니다. 오퍼랜드를 가져와서, 그에 맞는 행동을 하는게 전부 */ int PGLVMThread::ProcNOP() { return -1; } int PGLVMThread::ProcPUSH() { short operand = m_mainVM->m_codes[m_pc++]; m_stack.push_back(m_mainVM->m_literal[operand]); return -1; } int PGLVMThread::ProcSTORE() { short operand = m_mainVM->m_codes[m_pc++]; if (m_stack.empty()) { PushError(PGLVMError::stack_underflow, m_pc - 2); return PGL_RUNERR; } m_mainVM->m_literal[operand] = m_stack.back(); m_stack.pop_back(); return -1; } int PGLVMThread::ProcCOPY() { short operand = m_mainVM->m_codes[m_pc++]; if (m_stackBase.empty()) { PushError(PGLVMError::no_stackbase, m_pc - 2); return PGL_RUNERR; } auto v = m_stack[m_stackBase.back() operand]; m_stack.push_back(v); return -1; } int PGLVMThread::ProcWRITE() { short operand = m_mainVM->m_codes[m_pc++]; if (m_stackBase.empty()) { PushError(PGLVMError::no_stackbase, m_pc - 2); return PGL_RUNERR; } m_stack[m_stackBase.back() operand] = m_stack.back(); m_stack.pop_back(); return -1; } int PGLVMThread::ProcPOP() { short operand = m_mainVM->m_codes[m_pc++]; for ( int i = 0; i < operand; i) m_stack.pop_back(); return -1; } int PGLVMThread::ProcCALL() { short operand = m_mainVM->m_codes[m_pc++]; auto call = *(m_stack.end() - operand - 1); m_stackBase.push_back(m_stack.size() - operand); m_callstack.push_back(m_pc); switch (call->GetType()) { case PGLFirstData::Function: m_pc = ((PGLFunctionData*)call.get())->data; break ; case PGLFirstData::CFunction: { int ret = ((PGL_CFunc)(((PGLCFunctionData*)call.get())->data))( this ); m_pc = m_callstack.back(); m_callstack.pop_back(); // 스택 정리, return 될 값들만 남기고 모두 지운다 m_stack.erase(m_stack.begin() + m_stackBase.back() - 1, m_stack.end() - m_retCnt); m_stackBase.pop_back(); if (ret != PGL_OK) return ret; } break ; case PGLFirstData::Closure: m_stack.insert(m_stack.end() - operand, ((PGLClosureData*)call.get())->context); m_pc = ((PGLClosureData*)call.get())->func->data; break ; default : PushError(PGLVMError::not_callable, m_pc - 2); return PGL_RUNERR; } return -1; } int PGLVMThread::ProcTHISCALL() { short operand = m_mainVM->m_codes[m_pc++]; auto call = *(m_stack.end() - operand - 2); m_stackBase.push_back(m_stack.size() - operand - 1); m_callstack.push_back(m_pc); shared_ptr<PGLFunctionData> func; switch (call->GetType()) { case PGLFirstData::Function: func = static_pointer_cast<PGLFunctionData>(call); break ; case PGLFirstData::Closure: func = static_pointer_cast<PGLClosureData>(call)->func; break ; case PGLFirstData::CFunction: { int ret = ((PGL_CFunc)(((PGLCFunctionData*)call.get())->data))( this ); m_pc = m_callstack.back(); m_callstack.pop_back(); // 스택 정리, return 될 값들만 남기고 모두 지운다 m_stack.erase(m_stack.begin() + m_stackBase.back() - 1, m_stack.end() - m_retCnt); m_stackBase.pop_back(); if (ret != PGL_OK) return ret; } return -1; default : PushError(PGLVMError::not_callable, m_pc - 2); return PGL_RUNERR; } if (call->GetType() == PGLFirstData::Closure) { m_stack.insert(m_stack.end() - operand - 1, ((PGLClosureData*)call.get())->context); } m_pc = func->data; // this 인자가 필요없는 경우 제거한다 if (!func->memberFunc) { m_stack.erase(m_stack.end() - operand - 1); } return -1; } int PGLVMThread::ProcRETURN() { short operand = m_mainVM->m_codes[m_pc++]; //되돌아갈 곳이 없으면 정상 종료 if (m_callstack.empty()) return PGL_OK; m_pc = m_callstack.back(); m_callstack.pop_back(); // 스택 정리, return 될 값들만 남기고 모두 지운다 m_stack.erase(m_stack.begin() m_stackBase.back() - 1, m_stack.end() - operand); m_stackBase.pop_back(); return -1; } int PGLVMThread::ProcYIELD() { short operand = m_mainVM->m_codes[m_pc++]; m_retCnt = operand; return PGL_YIELD; } int PGLVMThread::ProcADD() { if (m_stack.size() < 2) { PushError(PGLVMError::stack_underflow, m_pc - 1); return PGL_RUNERR; } auto & a = *(m_stack.end()-2); a = a->OperateAdd(m_stack.back()); m_stack.pop_back(); if (!a) { PushError(PGLVMError::unable_add, m_pc - 1); return PGL_RUNERR; } return -1; } int PGLVMThread::ProcSUB() { if (m_stack.size() < 2) { PushError(PGLVMError::stack_underflow, m_pc - 1); return PGL_RUNERR; } auto & a = *(m_stack.end()-2); a = a->OperateSub(m_stack.back()); m_stack.pop_back(); if (!a) { PushError(PGLVMError::unable_sub, m_pc - 1); return PGL_RUNERR; } return -1; } int PGLVMThread::ProcMUL() { if (m_stack.size() < 2) { PushError(PGLVMError::stack_underflow, m_pc - 1); return PGL_RUNERR; } auto & a = *(m_stack.end()-2); a = a->OperateMul(m_stack.back()); m_stack.pop_back(); if (!a) { PushError(PGLVMError::unable_mul, m_pc - 1); return PGL_RUNERR; } return -1; } int PGLVMThread::ProcDIV() { if (m_stack.size() < 2) { PushError(PGLVMError::stack_underflow, m_pc - 1); return PGL_RUNERR; } auto & a = *(m_stack.end()-2); a = a->OperateDiv(m_stack.back()); m_stack.pop_back(); if (!a) { PushError(PGLVMError::unable_div, m_pc - 1); return PGL_RUNERR; } return -1; } int PGLVMThread::ProcMOD() { if (m_stack.size() < 2) { PushError(PGLVMError::stack_underflow, m_pc - 1); return PGL_RUNERR; } auto & a = *(m_stack.end()-2); a = a->OperateMod(m_stack.back()); m_stack.pop_back(); if (!a) { PushError(PGLVMError::unable_mod, m_pc - 1); return PGL_RUNERR; } return -1; } int PGLVMThread::ProcPOW() { if (m_stack.size() < 2) { PushError(PGLVMError::stack_underflow, m_pc - 1); return PGL_RUNERR; } auto & a = *(m_stack.end()-2); a = a->OperatePow(m_stack.back()); m_stack.pop_back(); if (!a) { PushError(PGLVMError::unable_pow, m_pc - 1); return PGL_RUNERR; } return -1; } int PGLVMThread::ProcAND() { if (m_stack.size() < 2) { PushError(PGLVMError::stack_underflow, m_pc - 1); return PGL_RUNERR; } auto & a = *(m_stack.end()-2); a = a->OperateAnd(m_stack.back()); m_stack.pop_back(); if (!a) { PushError(PGLVMError::unable_and, m_pc - 1); return PGL_RUNERR; } return -1; } int PGLVMThread::ProcOR() { if (m_stack.size() < 2) { PushError(PGLVMError::stack_underflow, m_pc - 1); return PGL_RUNERR; } auto & a = *(m_stack.end()-2); a = a->OperateOr(m_stack.back()); m_stack.pop_back(); if (!a) { PushError(PGLVMError::unable_or, m_pc - 1); return PGL_RUNERR; } return -1; } int PGLVMThread::ProcEQ() { if (m_stack.size() < 2) { PushError(PGLVMError::stack_underflow, m_pc - 1); return PGL_RUNERR; } auto & a = *(m_stack.end()-2); a = a->OperateCmp(PGLCompoundData::EQ, m_stack.back()); m_stack.pop_back(); if (!a) { PushError(PGLVMError::unable_cmp, m_pc - 1); return PGL_RUNERR; } return -1; } int PGLVMThread::ProcNEQ() { if (m_stack.size() < 2) { PushError(PGLVMError::stack_underflow, m_pc - 1); return PGL_RUNERR; } auto & a = *(m_stack.end()-2); a = a->OperateCmp(PGLCompoundData::NEQ, m_stack.back()); m_stack.pop_back(); if (!a) { PushError(PGLVMError::unable_cmp, m_pc - 1); return PGL_RUNERR; } return -1; } int PGLVMThread::ProcGT() { if (m_stack.size() < 2) { PushError(PGLVMError::stack_underflow, m_pc - 1); return PGL_RUNERR; } auto & a = *(m_stack.end()-2); a = a->OperateCmp(PGLCompoundData::GT, m_stack.back()); m_stack.pop_back(); if (!a) { PushError(PGLVMError::unable_cmp, m_pc - 1); return PGL_RUNERR; } return -1; } int PGLVMThread::ProcGTE() { if (m_stack.size() < 2) { PushError(PGLVMError::stack_underflow, m_pc - 1); return PGL_RUNERR; } auto & a = *(m_stack.end()-2); a = a->OperateCmp(PGLCompoundData::GTE, m_stack.back()); m_stack.pop_back(); if (!a) { PushError(PGLVMError::unable_cmp, m_pc - 1); return PGL_RUNERR; } return -1; } int PGLVMThread::ProcLS() { if (m_stack.size() < 2) { PushError(PGLVMError::stack_underflow, m_pc - 1); return PGL_RUNERR; } auto & a = *(m_stack.end()-2); a = a->OperateCmp(PGLCompoundData::LS, m_stack.back()); m_stack.pop_back(); if (!a) { PushError(PGLVMError::unable_cmp, m_pc - 1); return PGL_RUNERR; } return -1; } int PGLVMThread::ProcLSE() { if (m_stack.size() < 2) { PushError(PGLVMError::stack_underflow, m_pc - 1); return PGL_RUNERR; } auto & a = *(m_stack.end()-2); a = a->OperateCmp(PGLCompoundData::LSE, m_stack.back()); m_stack.pop_back(); if (!a) { PushError(PGLVMError::unable_cmp, m_pc - 1); return PGL_RUNERR; } return -1; } int PGLVMThread::ProcSIGN() { if (m_stack.size() < 1) { PushError(PGLVMError::stack_underflow, m_pc - 1); return PGL_RUNERR; } m_stack.back() = m_stack.back()->OperateSign(); if (!m_stack.back()) { PushError(PGLVMError::unable_sign, m_pc - 1); return PGL_RUNERR; } return -1; } int PGLVMThread::ProcNOT() { if (m_stack.size() < 1) { PushError(PGLVMError::stack_underflow, m_pc - 1); return PGL_RUNERR; } m_stack.back() = m_stack.back()->OperateNot(); if (!m_stack.back()) { PushError(PGLVMError::unable_not, m_pc - 1); return PGL_RUNERR; } return -1; } int PGLVMThread::ProcJMP() { short operand = m_mainVM->m_codes[m_pc ]; m_pc = operand; return -1; } int PGLVMThread::ProcUNLESSJMP() { short operand = m_mainVM->m_codes[m_pc ]; auto value = m_stack.back(); m_stack.pop_back(); if (value->GetType() == PGLFirstData::Boolean) { if (static_pointer_cast<PGLBooleanData>(value)->data == false ) { m_pc = operand; } } else { PushError(PGLVMError::expect_bool, m_pc - 2); return PGL_RUNERR; } return -1; } int PGLVMThread::ProcPUSHNULL() { m_stack.push_back(shared_ptr<PGLFirstData>( new PGLVoidData)); return -1; } int PGLVMThread::ProcASSEMBLE() { short operand = m_mainVM->m_codes[m_pc ]; if (m_stack.size() < operand) { PushError(PGLVMError::stack_underflow, m_pc - 2); return PGL_RUNERR; } auto arr = shared_ptr<PGLArrayData>( new PGLArrayData); move(m_stack.end() - operand, m_stack.end(), back_inserter(arr->data)); m_stack.erase(m_stack.end() - operand, m_stack.end()); m_stack.push_back(arr); return -1; } int PGLVMThread::ProcNEWDICT() { short operand = m_mainVM->m_codes[m_pc ]; if (m_stack.size() < 2*operand) { PushError(PGLVMError::stack_underflow, m_pc - 2); return PGL_RUNERR; } auto dict = shared_ptr<PGLDictionaryData>( new PGLDictionaryData); for ( int i = 0; i < operand; i) { auto val = m_stack.back(); m_stack.pop_back(); auto key = m_stack.back(); m_stack.pop_back(); switch (key->GetType()) { case PGLCompoundData::Array: case PGLCompoundData::Dictionary: case PGLCompoundData::Closure: PushError(PGLVMError::compound_key, m_pc - 2); return PGL_RUNERR; } dict->data[static_pointer_cast<PGLFirstData>(key)] = val; } m_stack.push_back(dict); return -1; } int PGLVMThread::ProcAT() { if (m_stack.size() < 2) { PushError(PGLVMError::stack_underflow, m_pc - 1); return PGL_RUNERR; } auto key = m_stack.back(); m_stack.pop_back(); auto cont = m_stack.back(); m_stack.pop_back(); switch (key->GetType()) { case PGLCompoundData::Array: case PGLCompoundData::Dictionary: case PGLCompoundData::Closure: PushError(PGLVMError::compound_key, m_pc - 1); return PGL_RUNERR; } switch (cont->GetType()) { case PGLCompoundData::Array: if (key->GetType() != PGLCompoundData::Integer) { PushError(PGLVMError::compound_key, m_pc - 1); return PGL_RUNERR; } m_stack.push_back( ((PGLArrayData*)(cont.get()))->data[((PGLIntData*)(key.get()))->data]); break ; case PGLCompoundData::Dictionary: { auto p = ((PGLDictionaryData*)(cont.get()))->data[static_pointer_cast<PGLFirstData>(key)]; if (!p) p = shared_ptr<PGLFirstData>( new PGLVoidData); m_stack.push_back(p); } break ; default : if (key->GetType() == PGLCompoundData::String) { auto p = cont->OperateDot(static_pointer_cast<PGLStringData>(key)->data); if (!p) { PushError(PGLVMError::unable_dereference, m_pc - 1); return PGL_RUNERR; } m_stack.push_back(p); } else { PushError(PGLVMError::unable_dereference, m_pc - 1); return PGL_RUNERR; } } return -1; } int PGLVMThread::ProcLEN() { if (m_stack.empty()) { PushError(PGLVMError::stack_underflow, m_pc - 1); return PGL_RUNERR; } auto cont = m_stack.back(); m_stack.pop_back(); switch (cont->GetType()) { case PGLCompoundData::Array: m_stack.push_back(make_shared<PGLIntData>( ((PGLArrayData*)(cont.get()))->data.size())); break ; case PGLCompoundData::Dictionary: m_stack.push_back(make_shared<PGLIntData>( ((PGLDictionaryData*)(cont.get()))->data.size())); break ; default : PushError(PGLVMError::unable_dereference, m_pc - 1); return PGL_RUNERR; } return -1; } int PGLVMThread::ProcATD() { short operand = m_mainVM->m_codes[m_pc ]; if (m_stack.empty()) { PushError(PGLVMError::stack_underflow, m_pc - 2); return PGL_RUNERR; } auto cont = m_stack.back(); m_stack.pop_back(); switch (cont->GetType()) { case PGLCompoundData::Array: m_stack.push_back( ((PGLArrayData*)(cont.get()))->data[operand]); break ; default : PushError(PGLVMError::unable_dereference, m_pc - 2); return PGL_RUNERR; } return -1; } int PGLVMThread::ProcMAKECLOSURE() { if (m_stack.size() < 2) { PushError(PGLVMError::stack_underflow, m_pc - 1); return PGL_RUNERR; } auto caps = m_stack.back(); m_stack.pop_back(); auto func = m_stack.back(); m_stack.pop_back(); if (caps->GetType() != PGLCompoundData::Array) { PushError(PGLVMError::unable_dereference, m_pc - 1); return PGL_RUNERR; } if (func->GetType() != PGLCompoundData::Function) { PushError(PGLVMError::not_callable, m_pc - 1); return PGL_RUNERR; } auto cls = make_shared<PGLClosureData>(); cls->func = static_pointer_cast<PGLFunctionData>(func); cls->context = static_pointer_cast<PGLArrayData>(caps); m_stack.push_back(cls); return -1; } int PGLVMThread::ProcSET() { if (m_stack.size() < 3) { PushError(PGLVMError::stack_underflow, m_pc - 1); return PGL_RUNERR; } auto key = m_stack.back(); m_stack.pop_back(); auto cont = m_stack.back(); m_stack.pop_back(); auto value = m_stack.back(); m_stack.pop_back(); switch (key->GetType()) { case PGLCompoundData::Array: case PGLCompoundData::Dictionary: case PGLCompoundData::Closure: PushError(PGLVMError::compound_key, m_pc - 1); return PGL_RUNERR; } switch (cont->GetType()) { case PGLCompoundData::Array: if (key->GetType() != PGLCompoundData::Integer) { PushError(PGLVMError::compound_key, m_pc - 1); return PGL_RUNERR; } ((PGLArrayData*)(cont.get()))->data[((PGLIntData*)(key.get()))->data] = value; break ; case PGLCompoundData::Dictionary: { ((PGLDictionaryData*)(cont.get()))->data[static_pointer_cast<PGLFirstData>(key)] = value; } break ; default : PushError(PGLVMError::unable_dereference, m_pc - 1); return PGL_RUNERR; } return -1; } int PGLVMThread::ProcSETD() { short operand = m_mainVM->m_codes[m_pc ]; if (m_stack.empty()) { PushError(PGLVMError::stack_underflow, m_pc - 2); return PGL_RUNERR; } auto cont = m_stack.back(); m_stack.pop_back(); auto value = m_stack.back(); m_stack.pop_back(); switch (cont->GetType()) { case PGLCompoundData::Array: { auto & v = ((PGLArrayData*)(cont.get()))->data[operand]; v = value; } break ; default : PushError(PGLVMError::unable_dereference, m_pc - 2); return PGL_RUNERR; } return -1; } int PGLVMThread::ProcREF() { if (m_stack.empty()) { PushError(PGLVMError::stack_underflow, m_pc - 1); return PGL_RUNERR; } auto value = m_stack.back(); m_stack.pop_back(); m_stack.push_back(make_shared<PGLRefData>(value)); return -1; } int PGLVMThread::ProcDEREF() { if (m_stack.empty()) { PushError(PGLVMError::stack_underflow, m_pc - 1); return PGL_RUNERR; } auto value = m_stack.back(); m_stack.pop_back(); if (value->GetType() != PGLCompoundData::Ref) { PushError(PGLVMError::unable_dereference, m_pc - 1); return PGL_RUNERR; } m_stack.push_back(static_pointer_cast<PGLRefData>(value)->data); return -1; } int PGLVMThread::ProcCOPYDEREF() { short operand = m_mainVM->m_codes[m_pc ]; if (m_stackBase.empty()) { PushError(PGLVMError::no_stackbase, m_pc - 2); return PGL_RUNERR; } auto v = m_stack[m_stackBase.back() operand]; if (v->GetType() == PGLCompoundData::Ref) { m_stack.push_back(static_pointer_cast<PGLRefData>(v)->data); } else { PushError(PGLVMError::unable_dereference, m_pc - 1); return PGL_RUNERR; } return -1; } int PGLVMThread::ProcSETDDEREF() { short operand = m_mainVM->m_codes[m_pc ]; if (m_stack.empty()) { PushError(PGLVMError::stack_underflow, m_pc - 2); return PGL_RUNERR; } auto cont = m_stack.back(); m_stack.pop_back(); auto value = m_stack.back(); m_stack.pop_back(); switch (cont->GetType()) { case PGLCompoundData::Array: { auto & v = ((PGLArrayData*)(cont.get()))->data[operand]; if (v->GetType() == PGLCompoundData::Ref) { static_pointer_cast<PGLRefData>(v)->data = value; break ; } } default : PushError(PGLVMError::unable_dereference, m_pc - 2); return PGL_RUNERR; } return -1; } int PGLVMThread::ProcWRITEDEREF() { short operand = m_mainVM->m_codes[m_pc ]; if (m_stackBase.empty()) { PushError(PGLVMError::no_stackbase, m_pc - 2); return PGL_RUNERR; } auto value = m_stack.back(); m_stack.pop_back(); auto & v = m_stack[m_stackBase.back() operand]; if (v->GetType() == PGLCompoundData::Ref) { static_pointer_cast<PGLRefData>(v)->data = value; } else { PushError(PGLVMError::unable_dereference, m_pc - 2); return PGL_RUNERR; } return -1; } int PGLVMThread::ProcPUSHBEGIN() { if (m_stack.empty()) { PushError(PGLVMError::stack_underflow, m_pc - 1); return PGL_RUNERR; } auto value = m_stack.back(); switch (value->GetType()) { case PGLCompoundData::Array: m_stack.push_back(make_shared<PGLCVectorIterData>(*static_pointer_cast<PGLArrayData>(value))); break ; case PGLCompoundData::Dictionary: m_stack.push_back(make_shared<PGLCMapIterData>(*static_pointer_cast<PGLDictionaryData>(value))); break ; default : PushError(PGLVMError::unable_dereference, m_pc - 1); return PGL_RUNERR; } return -1; } int PGLVMThread::ProcISNOTEND() { if (m_stack.empty()) { PushError(PGLVMError::stack_underflow, m_pc - 1); return PGL_RUNERR; } auto value = m_stack.back(); m_stack.pop_back(); switch (value->GetType()) { case PGLCompoundData::CVectorIter: case PGLCompoundData::CMapIter: m_stack.push_back(make_shared<PGLBooleanData>(value->IsNotEnd())); break ; default : PushError(PGLVMError::unable_dereference, m_pc - 1); return PGL_RUNERR; } return -1; } int PGLVMThread::ProcNEXT() { if (m_stack.empty()) { PushError(PGLVMError::stack_underflow, m_pc - 1); return PGL_RUNERR; } auto & value = m_stack.back(); switch (value->GetType()) { case PGLCompoundData::CVectorIter: case PGLCompoundData::CMapIter: value->Next(); break ; default : PushError(PGLVMError::unable_dereference, m_pc - 1); return PGL_RUNERR; } return -1; } int PGLVMThread::ProcPUSHKEYVAL() { if (m_stack.empty()) { PushError(PGLVMError::stack_underflow, m_pc - 1); return PGL_RUNERR; } auto value = m_stack.back(); switch (value->GetType()) { case PGLCompoundData::CVectorIter: case PGLCompoundData::CMapIter: m_stack.push_back(value->GetKey()); m_stack.push_back(value->GetValue()); break ; default : PushError(PGLVMError::unable_dereference, m_pc - 1); return PGL_RUNERR; } return -1; } int PGLVMThread::ProcFIND() { if (m_stack.size() < 2) { PushError(PGLVMError::stack_underflow, m_pc - 1); return PGL_RUNERR; } auto key = m_stack.back(); m_stack.pop_back(); auto cont = m_stack.back(); m_stack.pop_back(); switch (key->GetType()) { case PGLCompoundData::Array: case PGLCompoundData::Dictionary: case PGLCompoundData::Closure: PushError(PGLVMError::compound_key, m_pc - 1); return PGL_RUNERR; } switch (cont->GetType()) { case PGLCompoundData::Array: if (key->GetType() != PGLCompoundData::Integer) { PushError(PGLVMError::compound_key, m_pc - 1); return PGL_RUNERR; } else { int i = static_pointer_cast<PGLIntData>(key)->data; if (i >= static_pointer_cast<PGLArrayData>(cont)->data.size()) { PushError(PGLVMError::not_found, m_pc - 1); return PGL_RUNERR; } m_stack.push_back(static_pointer_cast<PGLArrayData>(cont)->data[i]); } break ; case PGLCompoundData::Dictionary: { auto k = static_pointer_cast<PGLFirstData>(key); auto it = static_pointer_cast<PGLDictionaryData>(cont)->data.find(k); if (it == static_pointer_cast<PGLDictionaryData>(cont)->data.end()) { PushError(PGLVMError::not_found, m_pc - 1); return PGL_RUNERR; } m_stack.push_back(it->second); } break ; default : if (key->GetType() == PGLCompoundData::String) { auto p = cont->OperateDot(static_pointer_cast<PGLStringData>(key)->data); if (!p) { PushError(PGLVMError::unable_dereference, m_pc - 1); return PGL_RUNERR; } m_stack.push_back(p); } else { PushError(PGLVMError::unable_dereference, m_pc - 1); return PGL_RUNERR; } } return -1; } int PGLVMThread::ProcFINDP() { if (m_stack.size() < 2) { PushError(PGLVMError::stack_underflow, m_pc - 1); return PGL_RUNERR; } auto key = m_stack.back(); m_stack.pop_back(); auto cont = m_stack.back(); m_stack.pop_back(); switch (key->GetType()) { case PGLCompoundData::Array: case PGLCompoundData::Dictionary: case PGLCompoundData::Closure: PushError(PGLVMError::compound_key, m_pc - 1); return PGL_RUNERR; } switch (cont->GetType()) { case PGLCompoundData::Array: if (key->GetType() != PGLCompoundData::Integer) { PushError(PGLVMError::compound_key, m_pc - 1); return PGL_RUNERR; } else { int i = static_pointer_cast<PGLIntData>(key)->data; if (i >= static_pointer_cast<PGLArrayData>(cont)->data.size()) { PushError(PGLVMError::not_found, m_pc - 1); return PGL_RUNERR; } m_stack.push_back(static_pointer_cast<PGLArrayData>(cont)->data[i]); } break ; case PGLCompoundData::Dictionary: { auto k = static_pointer_cast<PGLFirstData>(key); auto it = static_pointer_cast<PGLDictionaryData>(cont)->data.find(k); if (it == static_pointer_cast<PGLDictionaryData>(cont)->data.end()) { PushError(PGLVMError::not_found, m_pc - 1); return PGL_RUNERR; } m_stack.push_back(it->second); } break ; default : if (key->GetType() == PGLCompoundData::String) { auto p = cont->OperateDot(static_pointer_cast<PGLStringData>(key)->data); if (!p) { PushError(PGLVMError::unable_dereference, m_pc - 1); return PGL_RUNERR; } m_stack.push_back(p); } else { PushError(PGLVMError::unable_dereference, m_pc - 1); return PGL_RUNERR; } } m_stack.push_back(cont); return -1; } int PGLVMThread::Entry( int paramCnt) { short operand = paramCnt; auto call = *(m_stack.end() - operand - 1); m_stackBase.push_back(m_stack.size() - operand); switch (call->GetType()) { case PGLFirstData::Function: m_pc = ((PGLFunctionData*)call.get())->data; break ; case PGLFirstData::CFunction: { int ret = ((PGL_CFunc)(((PGLCFunctionData*)call.get())->data))( this ); if (ret != PGL_OK) return ret; m_pc = m_callstack.back(); m_callstack.pop_back(); // 스택 정리, return 될 값들만 남기고 모두 지운다 m_stack.erase(m_stack.begin() m_stackBase.back() - 1, m_stack.end() - m_retCnt); m_stackBase.pop_back(); } break ; case PGLFirstData::Closure: m_stack.insert(m_stack.end() - operand, ((PGLClosureData*)call.get())->context); m_pc = ((PGLClosureData*)call.get())->func->data; break ; default : PushError(PGLVMError::not_callable, m_pc - 2); return PGL_RUNERR; } m_state = PGL_ENTRY; return PGL_OK; } int PGLVMThread::Resume() { m_state = PGL_RUNNING; #define PROC(p) case PGLOpcode::p: ret = Proc##p(); if(ret >= 0) return m_state = ret; break; int ret; while (m_pc < m_mainVM->m_codes.size()) { switch (m_mainVM->m_codes[m_pc ]) { PROC(NOP) PROC(PUSH) PROC(STORE) PROC(COPY) PROC(WRITE) PROC(POP) PROC(THISCALL) PROC(CALL) PROC(RETURN) PROC(YIELD) PROC(ADD) PROC(SUB) PROC(MUL) PROC(DIV) PROC(MOD) PROC(POW) PROC(SIGN) PROC(EQ) PROC(NEQ) PROC(GT) PROC(GTE) PROC(LS) PROC(LSE) PROC(AND) PROC(OR) PROC(NOT) PROC(JMP) PROC(UNLESSJMP) PROC(PUSHNULL) PROC(ASSEMBLE) PROC(NEWDICT) PROC(AT) PROC(LEN) PROC(ATD) PROC(MAKECLOSURE) PROC(SET) PROC(SETD) PROC(REF) PROC(DEREF) PROC(COPYDEREF) PROC(SETDDEREF) PROC(WRITEDEREF) PROC(PUSHBEGIN) PROC(ISNOTEND) PROC(NEXT) PROC(PUSHKEYVAL) PROC(FIND) PROC(FINDP) } } m_state = PGL_OK; return PGL_OK; } |
길기는 무지막지하게 긴데, 실제로는 별 내용없는 코드입니다. 에뮬레이터 구현하는게 이런 뻘뻘한 느낌이겠죠 아마...?
실제로 이런 명령어들을 통해 어떻게 함수가 호출되고, 클로저가 구현되며, YIELDING이 가능한지는 다음으로 넘겨야할거 같네요. 글이 너무 길어져서...
PGLight 배포파일 (2) | 2013.10.11 |
---|---|
두둥! (PGLight 실행기) PGLRun (3) | 2013.07.13 |
5일만에 뚝딱 스크립트 언어 만들기 PGLight (5/5) (6) | 2013.07.06 |
5일만에 뚝딱 스크립트 언어 만들기 PGLight (3/5) (2) | 2013.06.17 |
5일만에 뚝딱 스크립트 언어 만들기 PGLight (2/5) (5) | 2013.06.15 |
5일만에 뚝딱 스크립트 언어 만들기 PGLight (1/5) (3) | 2013.06.14 |
댓글 영역