diff options
| Commit | 72d9bbcc3154142af79fb686d9dc7e4d1fa1badb (patch) | |
|---|---|---|
| Author | 2018-11-29 09:13:12 +0200 | |
| Committer | 2018-11-29 09:13:12 +0200 | |
| Files | 3cea4377cba9370f3f2248557f82831d617d89d1 /spasm/src | |
| IPL-72d9bbcc3154142af79fb686d9dc7e4d1fa1badb.tar IPL-72d9bbcc3154142af79fb686d9dc7e4d1fa1badb.tar.gz IPL-72d9bbcc3154142af79fb686d9dc7e4d1fa1badb.zip | ||
| Parent | cdfd42d72030a031e5c5d810fcd53441902b5cff (diff) | |
Feature/strings (#75)
* The assembler supports string opcode
* disabled the string test until implmented
* strings can be printed
11 files changed, 757 insertions, 466 deletions
| -rw-r--r-- | spasm/src/asm/assembler.cpp | 23 | ||||
| -rw-r--r-- | spasm/src/asm/bytecode.cpp | 6 | ||||
| -rw-r--r-- | spasm/src/asm/bytecode.hpp | 2 | ||||
| -rw-r--r-- | spasm/src/asm/lexer.cpp | 879 | ||||
| -rw-r--r-- | spasm/src/asm/lexer.re | 20 | ||||
| -rw-r--r-- | spasm/src/asm/token.cpp | 1 | ||||
| -rw-r--r-- | spasm/src/asm/token.hpp | 2 | ||||
| -rw-r--r-- | spasm/src/spasm.cpp | 49 | ||||
| -rw-r--r-- | spasm/src/spasm_impl.hpp | 37 | ||||
| -rw-r--r-- | spasm/src/string.hpp | 43 | ||||
| -rw-r--r-- | spasm/src/value.hpp | 161 |
diff --git a/spasm/src/asm/assembler.cpp b/spasm/src/asm/assembler.cpp index fadd747..1f69b1a 100644 --- a/spasm/src/asm/assembler.cpp +++ b/spasm/src/asm/assembler.cpp @@ -55,6 +55,23 @@ int get_arg_size(const Lexer::Token args[]) size = std::max(size, 3); break; } + case Lexer::Token::StringValue: + { + const auto length = args[i].value_str().size(); + if (length > 0xffffffff) + { + size = std::max(size, 3); + } + else if (length > 0xffff) + { + size = std::max(size, 2); + } + else if (length > 0xff) + { + size = std::max(size, 1); + } + break; + } default: break; } @@ -125,6 +142,12 @@ void Assembler::assemble() assert(args[1].type() == Lexer::Token::Ident); assemble_identifier(args[1]); } + else if (type == Lexer::Token::String) + { + assert(args[1].type() == Lexer::Token::StringValue); + const auto& s = args[1].value_str(); + _bytecode->push_string(s.data(), s.size(), arg_size); + } else { if (args[1].type() == Lexer::Token::Integer) diff --git a/spasm/src/asm/bytecode.cpp b/spasm/src/asm/bytecode.cpp index cc250ba..70e16c9 100644 --- a/spasm/src/asm/bytecode.cpp +++ b/spasm/src/asm/bytecode.cpp @@ -100,6 +100,12 @@ void Bytecode_Memory::push_location(size_t location) } } +void Bytecode_Memory::push_string(const char* s, size_t length, int size) +{ + push_integer(int64_t(length), size); + _bytecode.insert(_bytecode.end(), s, s + length); +} + const Bytecode_Memory::Bytecode& Bytecode_Memory::bytecode() const { return _bytecode; diff --git a/spasm/src/asm/bytecode.hpp b/spasm/src/asm/bytecode.hpp index fb80122..7d0d838 100644 --- a/spasm/src/asm/bytecode.hpp +++ b/spasm/src/asm/bytecode.hpp @@ -21,6 +21,7 @@ class Bytecode_Stream virtual void push_integer(int64_t, int size) = 0; virtual void push_double(double) = 0; virtual void push_location(size_t) = 0; + virtual void push_string(const char* s, size_t length, int size) = 0; virtual void set_location(size_t, size_t) = 0; virtual size_t size() const = 0; }; // class Bytecode_Stream @@ -51,6 +52,7 @@ class Bytecode_Memory : public Bytecode_Stream virtual void push_double(double) override; virtual void push_location(size_t); virtual void set_location(size_t, size_t); + virtual void push_string(const char* s, size_t length, int size) override; virtual size_t size() const; typedef std::vector<Bytecode_Stream::byte> Bytecode; diff --git a/spasm/src/asm/lexer.cpp b/spasm/src/asm/lexer.cpp index 5be7836..996762c 100644 --- a/spasm/src/asm/lexer.cpp +++ b/spasm/src/asm/lexer.cpp @@ -1,4 +1,4 @@ -/* Generated by re2c 1.1.1 on Thu Nov 22 14:23:32 2018 */ +/* Generated by re2c 1.1.1 on Wed Nov 28 21:13:09 2018 */ #line 1 "lexer.re" #include <iostream> @@ -34,7 +34,7 @@ bool Lexer::tokenize(TokenStream& ts) #line 41 "lexer.cpp" { char yych; - if ((limit - cursor) < 6) + if ((limit - cursor) < 7) return true; yych = *cursor; switch (yych) @@ -45,12 +45,16 @@ bool Lexer::tokenize(TokenStream& ts) goto yy6; case ' ': goto yy8; - case '#': + case '"': goto yy11; - case '-': + case '#': goto yy13; + case '\'': + goto yy15; + case '-': + goto yy17; case '0': - goto yy14; + goto yy18; case '1': case '2': case '3': @@ -60,9 +64,9 @@ bool Lexer::tokenize(TokenStream& ts) case '7': case '8': case '9': - goto yy16; + goto yy20; case ':': - goto yy18; + goto yy22; case 'A': case 'B': case 'C': @@ -107,55 +111,55 @@ bool Lexer::tokenize(TokenStream& ts) case 'x': case 'y': case 'z': - goto yy20; + goto yy24; case 'a': - goto yy23; + goto yy27; case 'c': - goto yy24; + goto yy28; case 'd': - goto yy25; + goto yy29; case 'j': - goto yy26; + goto yy30; case 'l': - goto yy27; + goto yy31; case 'm': - goto yy28; + goto yy32; case 'p': - goto yy29; + goto yy33; case 'r': - goto yy30; + goto yy34; case 's': - goto yy31; + goto yy35; default: goto yy4; } yy2: ++cursor; -#line 274 "lexer.re" +#line 290 "lexer.re" { ts.push_token(Token(Token::EndInput, lineno)); break; } -#line 126 "lexer.cpp" +#line 128 "lexer.cpp" yy4: ++cursor; yy5: -#line 280 "lexer.re" +#line 296 "lexer.re" { return false; } -#line 134 "lexer.cpp" +#line 136 "lexer.cpp" yy6: ++cursor; -#line 267 "lexer.re" +#line 283 "lexer.re" { ++lineno; token_start = cursor; continue; } -#line 144 "lexer.cpp" +#line 146 "lexer.cpp" yy8: ++cursor; if (limit <= cursor) @@ -169,13 +173,13 @@ bool Lexer::tokenize(TokenStream& ts) goto yy10; } yy10: -#line 251 "lexer.re" +#line 267 "lexer.re" { token_start = cursor; continue; } -#line 160 "lexer.cpp" +#line 162 "lexer.cpp" yy11: ++cursor; if (limit <= cursor) @@ -183,21 +187,49 @@ bool Lexer::tokenize(TokenStream& ts) yych = *cursor; switch (yych) { - case '\n': - goto yy32; + case '"': + goto yy36; + case '\\': + goto yy38; default: goto yy11; } yy13: + ++cursor; + if (limit <= cursor) + return true; + yych = *cursor; + switch (yych) + { + case '\n': + goto yy40; + default: + goto yy13; + } + yy15: + ++cursor; + if (limit <= cursor) + return true; + yych = *cursor; + switch (yych) + { + case '\'': + goto yy36; + case '\\': + goto yy42; + default: + goto yy15; + } + yy17: yych = *++cursor; switch (yych) { case '0': - goto yy34; + goto yy44; default: goto yy5; } - yy14: + yy18: yych = *(marker = ++cursor); switch (yych) { @@ -212,23 +244,23 @@ bool Lexer::tokenize(TokenStream& ts) case '8': case '9': case ':': - goto yy36; + goto yy46; case 'X': case 'x': - goto yy38; + goto yy48; default: - goto yy15; + goto yy19; } - yy15: -#line 60 "lexer.re" + yy19: +#line 62 "lexer.re" { ts.push_token(Token(Token::Integer, lineno, token_start, cursor)); token_start = cursor; continue; } -#line 202 "lexer.cpp" - yy16: +#line 222 "lexer.cpp" + yy20: marker = ++cursor; if ((limit - cursor) < 2) return true; @@ -236,7 +268,7 @@ bool Lexer::tokenize(TokenStream& ts) switch (yych) { case '.': - goto yy39; + goto yy49; case '0': case '1': case '2': @@ -247,27 +279,27 @@ bool Lexer::tokenize(TokenStream& ts) case '7': case '8': case '9': - goto yy16; + goto yy20; case ':': - goto yy18; + goto yy22; default: - goto yy15; + goto yy19; } - yy18: + yy22: ++cursor; -#line 256 "lexer.re" +#line 272 "lexer.re" { token_start = cursor; continue; } -#line 230 "lexer.cpp" - yy20: +#line 250 "lexer.cpp" + yy24: ++cursor; if (limit <= cursor) return true; yych = *cursor; - yy21: + yy25: switch (yych) { case '0': @@ -333,25 +365,25 @@ bool Lexer::tokenize(TokenStream& ts) case 'x': case 'y': case 'z': - goto yy20; + goto yy24; default: - goto yy22; + goto yy26; } - yy22: -#line 243 "lexer.re" + yy26: +#line 252 "lexer.re" { ts.push_token(Token(Token::Ident, lineno, token_start, cursor)); token_start = cursor; continue; } -#line 311 "lexer.cpp" - yy23: +#line 331 "lexer.cpp" + yy27: yych = *++cursor; switch (yych) { case '0': - goto yy40; + goto yy50; case '1': case '2': case '3': @@ -361,84 +393,84 @@ bool Lexer::tokenize(TokenStream& ts) case '7': case '8': case '9': - goto yy42; + goto yy52; case 'd': - goto yy44; + goto yy54; default: - goto yy21; + goto yy25; } - yy24: + yy28: yych = *++cursor; switch (yych) { case 'a': - goto yy45; + goto yy55; case 'o': - goto yy46; + goto yy56; default: - goto yy21; + goto yy25; } - yy25: + yy29: yych = *++cursor; switch (yych) { case 'i': - goto yy47; + goto yy57; case 'u': - goto yy48; + goto yy58; default: - goto yy21; + goto yy25; } - yy26: + yy30: yych = *++cursor; switch (yych) { case 'm': - goto yy49; + goto yy59; default: - goto yy21; + goto yy25; } - yy27: + yy31: yych = *++cursor; switch (yych) { case 'a': - goto yy50; + goto yy60; case 'e': - goto yy51; + goto yy61; default: - goto yy21; + goto yy25; } - yy28: + yy32: yych = *++cursor; switch (yych) { case 'o': - goto yy52; + goto yy62; case 'u': - goto yy53; + goto yy63; default: - goto yy21; + goto yy25; } - yy29: + yy33: yych = *++cursor; switch (yych) { case 'o': - goto yy54; + goto yy64; case 'r': - goto yy55; + goto yy65; case 'u': - goto yy56; + goto yy66; default: - goto yy21; + goto yy25; } - yy30: + yy34: yych = *++cursor; switch (yych) { case '0': - goto yy57; + goto yy67; case '1': case '2': case '3': @@ -448,40 +480,77 @@ bool Lexer::tokenize(TokenStream& ts) case '7': case '8': case '9': - goto yy59; + goto yy69; case 'e': - goto yy61; + goto yy71; default: - goto yy21; + goto yy25; } - yy31: + yy35: yych = *++cursor; switch (yych) { + case 't': + goto yy72; case 'u': - goto yy62; + goto yy73; default: - goto yy21; + goto yy25; } - yy32: + yy36: + ++cursor; +#line 259 "lexer.re" + { + ts.push_token(Token(Token::StringValue, lineno, token_start + 1, + cursor - 1)); + token_start = cursor; + + continue; + } +#line 423 "lexer.cpp" + yy38: + ++cursor; + if (limit <= cursor) + return true; + yych = *cursor; + switch (yych) + { + case '\\': + goto yy38; + default: + goto yy11; + } + yy40: ++cursor; -#line 261 "lexer.re" +#line 277 "lexer.re" { ++lineno; token_start = cursor; continue; } -#line 401 "lexer.cpp" - yy34: +#line 441 "lexer.cpp" + yy42: ++cursor; - goto yy15; - yy35: + if (limit <= cursor) + return true; + yych = *cursor; + switch (yych) + { + case '\\': + goto yy42; + default: + goto yy15; + } + yy44: + ++cursor; + goto yy19; + yy45: ++cursor; if (limit <= cursor) return true; yych = *cursor; - yy36: + yy46: switch (yych) { case '0': @@ -494,16 +563,16 @@ bool Lexer::tokenize(TokenStream& ts) case '7': case '8': case '9': - goto yy35; + goto yy45; case ':': - goto yy18; + goto yy22; default: - goto yy37; + goto yy47; } - yy37: + yy47: cursor = marker; - goto yy15; - yy38: + goto yy19; + yy48: yych = *++cursor; switch (yych) { @@ -529,16 +598,16 @@ bool Lexer::tokenize(TokenStream& ts) case 'd': case 'e': case 'f': - goto yy63; + goto yy74; default: - goto yy37; + goto yy47; } - yy39: + yy49: yych = *++cursor; switch (yych) { case '0': - goto yy66; + goto yy77; case '1': case '2': case '3': @@ -548,11 +617,11 @@ bool Lexer::tokenize(TokenStream& ts) case '7': case '8': case '9': - goto yy68; + goto yy79; default: - goto yy37; + goto yy47; } - yy40: + yy50: yych = *++cursor; switch (yych) { @@ -619,12 +688,12 @@ bool Lexer::tokenize(TokenStream& ts) case 'x': case 'y': case 'z': - goto yy20; + goto yy24; default: - goto yy41; + goto yy51; } - yy41: -#line 84 "lexer.re" + yy51: +#line 86 "lexer.re" { Token t(Token::Integer, lineno, token_start + 1, cursor); t.set_int(-t.value_int()); @@ -632,8 +701,8 @@ bool Lexer::tokenize(TokenStream& ts) token_start = cursor; continue; } -#line 547 "lexer.cpp" - yy42: +#line 595 "lexer.cpp" + yy52: ++cursor; if (limit <= cursor) return true; @@ -650,7 +719,7 @@ bool Lexer::tokenize(TokenStream& ts) case '7': case '8': case '9': - goto yy42; + goto yy52; case 'A': case 'B': case 'C': @@ -704,130 +773,130 @@ bool Lexer::tokenize(TokenStream& ts) case 'x': case 'y': case 'z': - goto yy20; + goto yy24; default: - goto yy41; + goto yy51; } - yy44: + yy54: yych = *++cursor; switch (yych) { case 'd': - goto yy70; + goto yy81; default: - goto yy21; + goto yy25; } - yy45: + yy55: yych = *++cursor; switch (yych) { case 'l': - goto yy72; + goto yy83; default: - goto yy21; + goto yy25; } - yy46: + yy56: yych = *++cursor; switch (yych) { case 'n': - goto yy73; + goto yy84; default: - goto yy21; + goto yy25; } - yy47: + yy57: yych = *++cursor; switch (yych) { case 'v': - goto yy74; + goto yy85; default: - goto yy21; + goto yy25; } - yy48: + yy58: yych = *++cursor; switch (yych) { case 'p': - goto yy76; + goto yy87; default: - goto yy21; + goto yy25; } - yy49: + yy59: yych = *++cursor; switch (yych) { case 'p': - goto yy78; + goto yy89; default: - goto yy21; + goto yy25; } - yy50: + yy60: yych = *++cursor; switch (yych) { case 'b': - goto yy80; + goto yy91; default: - goto yy21; + goto yy25; } - yy51: + yy61: yych = *++cursor; switch (yych) { case 'q': - goto yy81; + goto yy92; case 's': - goto yy83; + goto yy94; default: - goto yy21; + goto yy25; } - yy52: + yy62: yych = *++cursor; switch (yych) { case 'd': - goto yy84; + goto yy95; default: - goto yy21; + goto yy25; } - yy53: + yy63: yych = *++cursor; switch (yych) { case 'l': - goto yy86; + goto yy97; default: - goto yy21; + goto yy25; } - yy54: + yy64: yych = *++cursor; switch (yych) { case 'p': - goto yy88; + goto yy99; default: - goto yy21; + goto yy25; } - yy55: + yy65: yych = *++cursor; switch (yych) { case 'i': - goto yy90; + goto yy101; default: - goto yy21; + goto yy25; } - yy56: + yy66: yych = *++cursor; switch (yych) { case 's': - goto yy91; + goto yy102; default: - goto yy21; + goto yy25; } - yy57: + yy67: yych = *++cursor; switch (yych) { @@ -894,12 +963,12 @@ bool Lexer::tokenize(TokenStream& ts) case 'x': case 'y': case 'z': - goto yy20; + goto yy24; default: - goto yy58; + goto yy68; } - yy58: -#line 77 "lexer.re" + yy68: +#line 79 "lexer.re" { ts.push_token( Token(Token::Integer, lineno, token_start + 1, cursor)); @@ -907,8 +976,8 @@ bool Lexer::tokenize(TokenStream& ts) continue; } -#line 774 "lexer.cpp" - yy59: +#line 822 "lexer.cpp" + yy69: ++cursor; if (limit <= cursor) return true; @@ -925,7 +994,7 @@ bool Lexer::tokenize(TokenStream& ts) case '7': case '8': case '9': - goto yy59; + goto yy69; case 'A': case 'B': case 'C': @@ -979,31 +1048,40 @@ bool Lexer::tokenize(TokenStream& ts) case 'x': case 'y': case 'z': - goto yy20; + goto yy24; default: - goto yy58; + goto yy68; } - yy61: + yy71: yych = *++cursor; switch (yych) { case 'a': - goto yy92; + goto yy103; case 't': - goto yy93; + goto yy104; default: - goto yy21; + goto yy25; } - yy62: + yy72: + yych = *++cursor; + switch (yych) + { + case 'r': + goto yy106; + default: + goto yy25; + } + yy73: yych = *++cursor; switch (yych) { case 'b': - goto yy95; + goto yy107; default: - goto yy21; + goto yy25; } - yy63: + yy74: ++cursor; if (limit <= cursor) return true; @@ -1032,23 +1110,23 @@ bool Lexer::tokenize(TokenStream& ts) case 'd': case 'e': case 'f': - goto yy63; + goto yy74; default: - goto yy65; + goto yy76; } - yy65: -#line 93 "lexer.re" + yy76: +#line 95 "lexer.re" { ts.push_token(Token(Token::XInteger, lineno, token_start, cursor)); token_start = cursor; continue; } -#line 896 "lexer.cpp" - yy66: +#line 950 "lexer.cpp" + yy77: ++cursor; - yy67: -#line 68 "lexer.re" + yy78: +#line 70 "lexer.re" { ts.push_token( Token(Token::FloatingPoint, lineno, token_start, cursor)); @@ -1056,8 +1134,8 @@ bool Lexer::tokenize(TokenStream& ts) continue; } -#line 909 "lexer.cpp" - yy68: +#line 963 "lexer.cpp" + yy79: ++cursor; if (limit <= cursor) return true; @@ -1074,11 +1152,11 @@ bool Lexer::tokenize(TokenStream& ts) case '7': case '8': case '9': - goto yy68; + goto yy79; default: - goto yy67; + goto yy78; } - yy70: + yy81: yych = *++cursor; switch (yych) { @@ -1145,38 +1223,38 @@ bool Lexer::tokenize(TokenStream& ts) case 'x': case 'y': case 'z': - goto yy20; + goto yy24; default: - goto yy71; + goto yy82; } - yy71: -#line 147 "lexer.re" + yy82: +#line 149 "lexer.re" { ts.push_token(Token(Token::Add, lineno)); token_start = cursor; continue; } -#line 1003 "lexer.cpp" - yy72: +#line 1057 "lexer.cpp" + yy83: yych = *++cursor; switch (yych) { case 'l': - goto yy97; + goto yy109; default: - goto yy21; + goto yy25; } - yy73: + yy84: yych = *++cursor; switch (yych) { case 's': - goto yy99; + goto yy111; default: - goto yy21; + goto yy25; } - yy74: + yy85: yych = *++cursor; switch (yych) { @@ -1243,20 +1321,20 @@ bool Lexer::tokenize(TokenStream& ts) case 'x': case 'y': case 'z': - goto yy20; + goto yy24; default: - goto yy75; + goto yy86; } - yy75: -#line 168 "lexer.re" + yy86: +#line 170 "lexer.re" { ts.push_token(Token(Token::Div, lineno)); token_start = cursor; continue; } -#line 1092 "lexer.cpp" - yy76: +#line 1146 "lexer.cpp" + yy87: yych = *++cursor; switch (yych) { @@ -1323,20 +1401,20 @@ bool Lexer::tokenize(TokenStream& ts) case 'x': case 'y': case 'z': - goto yy20; + goto yy24; default: - goto yy77; + goto yy88; } - yy77: -#line 126 "lexer.re" + yy88: +#line 128 "lexer.re" { ts.push_token(Token(Token::Dup, lineno)); token_start = cursor; continue; } -#line 1169 "lexer.cpp" - yy78: +#line 1223 "lexer.cpp" + yy89: yych = *++cursor; switch (yych) { @@ -1401,33 +1479,33 @@ bool Lexer::tokenize(TokenStream& ts) case 'x': case 'y': case 'z': - goto yy20; + goto yy24; case 'f': - goto yy100; + goto yy112; case 't': - goto yy102; + goto yy114; default: - goto yy79; + goto yy90; } - yy79: -#line 196 "lexer.re" + yy90: +#line 198 "lexer.re" { ts.push_token(Token(Token::Jump, lineno)); token_start = cursor; continue; } -#line 1246 "lexer.cpp" - yy80: +#line 1300 "lexer.cpp" + yy91: yych = *++cursor; switch (yych) { case 'e': - goto yy104; + goto yy116; default: - goto yy21; + goto yy25; } - yy81: + yy92: yych = *++cursor; switch (yych) { @@ -1494,29 +1572,29 @@ bool Lexer::tokenize(TokenStream& ts) case 'x': case 'y': case 'z': - goto yy20; + goto yy24; default: - goto yy82; + goto yy93; } - yy82: -#line 223 "lexer.re" + yy93: +#line 232 "lexer.re" { ts.push_token(Token(Token::LessEq, lineno)); token_start = cursor; continue; } -#line 1329 "lexer.cpp" - yy83: +#line 1383 "lexer.cpp" + yy94: yych = *++cursor; switch (yych) { case 's': - goto yy105; + goto yy117; default: - goto yy21; + goto yy25; } - yy84: + yy95: yych = *++cursor; switch (yych) { @@ -1583,20 +1661,20 @@ bool Lexer::tokenize(TokenStream& ts) case 'x': case 'y': case 'z': - goto yy20; + goto yy24; default: - goto yy85; + goto yy96; } - yy85: -#line 175 "lexer.re" + yy96: +#line 177 "lexer.re" { ts.push_token(Token(Token::Mod, lineno)); token_start = cursor; continue; } -#line 1412 "lexer.cpp" - yy86: +#line 1466 "lexer.cpp" + yy97: yych = *++cursor; switch (yych) { @@ -1663,20 +1741,20 @@ bool Lexer::tokenize(TokenStream& ts) case 'x': case 'y': case 'z': - goto yy20; + goto yy24; default: - goto yy87; + goto yy98; } - yy87: -#line 161 "lexer.re" + yy98: +#line 163 "lexer.re" { ts.push_token(Token(Token::Mul, lineno)); token_start = cursor; continue; } -#line 1489 "lexer.cpp" - yy88: +#line 1543 "lexer.cpp" + yy99: yych = *++cursor; switch (yych) { @@ -1742,49 +1820,49 @@ bool Lexer::tokenize(TokenStream& ts) case 'x': case 'y': case 'z': - goto yy20; + goto yy24; case 'r': - goto yy107; + goto yy119; default: - goto yy89; + goto yy100; } - yy89: -#line 113 "lexer.re" + yy100: +#line 115 "lexer.re" { ts.push_token(Token(Token::Pop, lineno)); token_start = cursor; continue; } -#line 1566 "lexer.cpp" - yy90: +#line 1620 "lexer.cpp" + yy101: yych = *++cursor; switch (yych) { case 'n': - goto yy109; + goto yy121; default: - goto yy21; + goto yy25; } - yy91: + yy102: yych = *++cursor; switch (yych) { case 'h': - goto yy110; + goto yy122; default: - goto yy21; + goto yy25; } - yy92: + yy103: yych = *++cursor; switch (yych) { case 'd': - goto yy112; + goto yy124; default: - goto yy21; + goto yy25; } - yy93: + yy104: yych = *++cursor; switch (yych) { @@ -1851,20 +1929,29 @@ bool Lexer::tokenize(TokenStream& ts) case 'x': case 'y': case 'z': - goto yy20; + goto yy24; default: - goto yy94; + goto yy105; } - yy94: -#line 216 "lexer.re" + yy105: +#line 225 "lexer.re" { ts.push_token(Token(Token::Ret, lineno)); token_start = cursor; continue; } -#line 1661 "lexer.cpp" - yy95: +#line 1715 "lexer.cpp" + yy106: + yych = *++cursor; + switch (yych) + { + case 'i': + goto yy126; + default: + goto yy25; + } + yy107: yych = *++cursor; switch (yych) { @@ -1931,20 +2018,20 @@ bool Lexer::tokenize(TokenStream& ts) case 'x': case 'y': case 'z': - goto yy20; + goto yy24; default: - goto yy96; + goto yy108; } - yy96: -#line 154 "lexer.re" + yy108: +#line 156 "lexer.re" { ts.push_token(Token(Token::Sub, lineno)); token_start = cursor; continue; } -#line 1738 "lexer.cpp" - yy97: +#line 1798 "lexer.cpp" + yy109: yych = *++cursor; switch (yych) { @@ -2011,29 +2098,29 @@ bool Lexer::tokenize(TokenStream& ts) case 'x': case 'y': case 'z': - goto yy20; + goto yy24; default: - goto yy98; + goto yy110; } - yy98: -#line 209 "lexer.re" + yy110: +#line 218 "lexer.re" { ts.push_token(Token(Token::Call, lineno)); token_start = cursor; continue; } -#line 1815 "lexer.cpp" - yy99: +#line 1875 "lexer.cpp" + yy111: yych = *++cursor; switch (yych) { case 't': - goto yy114; + goto yy127; default: - goto yy21; + goto yy25; } - yy100: + yy112: yych = *++cursor; switch (yych) { @@ -2100,20 +2187,20 @@ bool Lexer::tokenize(TokenStream& ts) case 'x': case 'y': case 'z': - goto yy20; + goto yy24; default: - goto yy101; + goto yy113; } - yy101: -#line 189 "lexer.re" + yy113: +#line 191 "lexer.re" { ts.push_token(Token(Token::JumpF, lineno)); token_start = cursor; continue; } -#line 1898 "lexer.cpp" - yy102: +#line 1958 "lexer.cpp" + yy114: yych = *++cursor; switch (yych) { @@ -2180,29 +2267,29 @@ bool Lexer::tokenize(TokenStream& ts) case 'x': case 'y': case 'z': - goto yy20; + goto yy24; default: - goto yy103; + goto yy115; } - yy103: -#line 182 "lexer.re" + yy115: +#line 184 "lexer.re" { ts.push_token(Token(Token::JumpT, lineno)); token_start = cursor; continue; } -#line 1975 "lexer.cpp" - yy104: +#line 2035 "lexer.cpp" + yy116: yych = *++cursor; switch (yych) { case 'l': - goto yy116; + goto yy129; default: - goto yy21; + goto yy25; } - yy105: + yy117: yych = *++cursor; switch (yych) { @@ -2269,20 +2356,20 @@ bool Lexer::tokenize(TokenStream& ts) case 'x': case 'y': case 'z': - goto yy20; + goto yy24; default: - goto yy106; + goto yy118; } - yy106: -#line 229 "lexer.re" + yy118: +#line 238 "lexer.re" { ts.push_token(Token(Token::Less, lineno)); token_start = cursor; continue; } -#line 2058 "lexer.cpp" - yy107: +#line 2118 "lexer.cpp" + yy119: yych = *++cursor; switch (yych) { @@ -2349,29 +2436,29 @@ bool Lexer::tokenize(TokenStream& ts) case 'x': case 'y': case 'z': - goto yy20; + goto yy24; default: - goto yy108; + goto yy120; } - yy108: -#line 119 "lexer.re" + yy120: +#line 121 "lexer.re" { ts.push_token(Token(Token::PopTo, lineno)); token_start = cursor; continue; } -#line 2135 "lexer.cpp" - yy109: +#line 2195 "lexer.cpp" + yy121: yych = *++cursor; switch (yych) { case 't': - goto yy118; + goto yy131; default: - goto yy21; + goto yy25; } - yy110: + yy122: yych = *++cursor; switch (yych) { @@ -2437,22 +2524,22 @@ bool Lexer::tokenize(TokenStream& ts) case 'x': case 'y': case 'z': - goto yy20; + goto yy24; case 'r': - goto yy120; + goto yy133; default: - goto yy111; + goto yy123; } - yy111: -#line 107 "lexer.re" + yy123: +#line 109 "lexer.re" { ts.push_token(Token(Token::Push, lineno)); token_start = cursor; continue; } -#line 2218 "lexer.cpp" - yy112: +#line 2278 "lexer.cpp" + yy124: yych = *++cursor; switch (yych) { @@ -2519,20 +2606,29 @@ bool Lexer::tokenize(TokenStream& ts) case 'x': case 'y': case 'z': - goto yy20; + goto yy24; default: - goto yy113; + goto yy125; } - yy113: -#line 133 "lexer.re" + yy125: +#line 135 "lexer.re" { ts.push_token(Token(Token::Read, lineno)); token_start = cursor; continue; } -#line 2295 "lexer.cpp" - yy114: +#line 2355 "lexer.cpp" + yy126: + yych = *++cursor; + switch (yych) + { + case 'n': + goto yy135; + default: + goto yy25; + } + yy127: yych = *++cursor; switch (yych) { @@ -2599,20 +2695,20 @@ bool Lexer::tokenize(TokenStream& ts) case 'x': case 'y': case 'z': - goto yy20; + goto yy24; default: - goto yy115; + goto yy128; } - yy115: -#line 202 "lexer.re" + yy128: +#line 204 "lexer.re" { ts.push_token(Token(Token::Const, lineno)); token_start = cursor; continue; } -#line 2372 "lexer.cpp" - yy116: +#line 2438 "lexer.cpp" + yy129: yych = *++cursor; switch (yych) { @@ -2679,20 +2775,20 @@ bool Lexer::tokenize(TokenStream& ts) case 'x': case 'y': case 'z': - goto yy20; + goto yy24; default: - goto yy117; + goto yy130; } - yy117: -#line 236 "lexer.re" + yy130: +#line 245 "lexer.re" { ts.push_token(Token(Token::Label, lineno)); token_start = cursor; continue; } -#line 2449 "lexer.cpp" - yy118: +#line 2515 "lexer.cpp" + yy131: yych = *++cursor; switch (yych) { @@ -2759,20 +2855,20 @@ bool Lexer::tokenize(TokenStream& ts) case 'x': case 'y': case 'z': - goto yy20; + goto yy24; default: - goto yy119; + goto yy132; } - yy119: -#line 140 "lexer.re" + yy132: +#line 142 "lexer.re" { ts.push_token(Token(Token::Print, lineno)); token_start = cursor; continue; } -#line 2526 "lexer.cpp" - yy120: +#line 2592 "lexer.cpp" + yy133: yych = *++cursor; switch (yych) { @@ -2839,21 +2935,110 @@ bool Lexer::tokenize(TokenStream& ts) case 'x': case 'y': case 'z': - goto yy20; + goto yy24; default: - goto yy121; + goto yy134; } - yy121: -#line 101 "lexer.re" + yy134: +#line 103 "lexer.re" { ts.push_token(Token(Token::PushFrom, lineno)); token_start = cursor; continue; } -#line 2603 "lexer.cpp" +#line 2669 "lexer.cpp" + yy135: + yych = *++cursor; + switch (yych) + { + case 'g': + goto yy136; + default: + goto yy25; + } + yy136: + yych = *++cursor; + switch (yych) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + case 'G': + case 'H': + case 'I': + case 'J': + case 'K': + case 'L': + case 'M': + case 'N': + case 'O': + case 'P': + case 'Q': + case 'R': + case 'S': + case 'T': + case 'U': + case 'V': + case 'W': + case 'X': + case 'Y': + case 'Z': + case '_': + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + case 'g': + case 'h': + case 'i': + case 'j': + case 'k': + case 'l': + case 'm': + case 'n': + case 'o': + case 'p': + case 'q': + case 'r': + case 's': + case 't': + case 'u': + case 'v': + case 'w': + case 'x': + case 'y': + case 'z': + goto yy24; + default: + goto yy137; + } + yy137: +#line 211 "lexer.re" + { + ts.push_token(Token(Token::String, lineno)); + token_start = cursor; + + continue; + } +#line 2752 "lexer.cpp" } -#line 284 "lexer.re" +#line 300 "lexer.re" } return true; } diff --git a/spasm/src/asm/lexer.re b/spasm/src/asm/lexer.re index fabeaf7..bdf792d 100644 --- a/spasm/src/asm/lexer.re +++ b/spasm/src/asm/lexer.re @@ -56,6 +56,8 @@ NONNEGATIVE = "0" | ([1-9] DIGIT*) ; XINTEGER = "0" [xX] XDIGIT+ ; FLOATING = "-"? "0" | ([1-9] DIGIT*) "." NONNEGATIVE ; IDENTIFIER = [a-zA-Z_] [0-9a-zA-Z_]* ; +SSTRING = "'" ([^']|"\\'")* "'" ; +DSTRING = "\"" ([^"]|"\\\"")* "\"" ; INTEGER { ts.push_token (Token (Token::Integer, lineno, @@ -198,13 +200,20 @@ XINTEGER { token_start = cursor; continue; - } + } "const" { ts.push_token (Token (Token::Const, lineno)); token_start = cursor; continue; - } + } + +"string" { + ts.push_token (Token (Token::String, lineno)); + token_start = cursor; + + continue; + } "call" { ts.push_token (Token (Token::Call, lineno)); @@ -247,6 +256,13 @@ IDENTIFIER { continue; } +SSTRING | DSTRING { + ts.push_token (Token (Token::StringValue, lineno, token_start + 1, + cursor - 1)); + token_start = cursor; + + continue; + } [ ]+ { token_start = cursor; diff --git a/spasm/src/asm/token.cpp b/spasm/src/asm/token.cpp index fa612e3..7582892 100644 --- a/spasm/src/asm/token.cpp +++ b/spasm/src/asm/token.cpp @@ -36,6 +36,7 @@ Token::Token(Token::Token_type type, break; } case Ident: + case StringValue: { if (end) { diff --git a/spasm/src/asm/token.hpp b/spasm/src/asm/token.hpp index 8f18768..2e69108 100644 --- a/spasm/src/asm/token.hpp +++ b/spasm/src/asm/token.hpp @@ -31,6 +31,7 @@ class Token JumpT = _TwoArgBegin, JumpF, Const, + String, _ThreeArgBegin, Add = _ThreeArgBegin, Sub, @@ -46,6 +47,7 @@ class Token Integer, XInteger, FloatingPoint, + StringValue, EndInput, NotUsed }; diff --git a/spasm/src/spasm.cpp b/spasm/src/spasm.cpp index 63e09a0..6a62c90 100644 --- a/spasm/src/spasm.cpp +++ b/spasm/src/spasm.cpp @@ -131,6 +131,13 @@ Spasm::RunResult Spasm::run() set_local(reg, value); break; } + case OpCodes::String: + { + const auto reg = read_reg(size); + const auto value = read_string(size); + set_local(reg, value); + break; + } case OpCodes::Add: { const auto arg0 = read_reg(size); @@ -461,6 +468,16 @@ void Spasm::push_data(data_t data) reg_t Spasm::read_reg(size_t size) { + return read_integer(size); +} + +data_t Spasm::read_number(size_t size) +{ + return data_t(double(read_integer(size))); +} + +int64_t Spasm::read_integer(size_t size) +{ switch (size) { case 0: @@ -488,33 +505,13 @@ reg_t Spasm::read_reg(size_t size) return 0; } -data_t Spasm::read_number(size_t size) +data_t Spasm::read_string(size_t size) { - switch (size) - { - case 0: - return data_t(double(m_ByteCode[m_PC++])); - case 1: - { - auto result = *reinterpret_cast<int16_t*>(&m_ByteCode[0] + m_PC); - m_PC += 2; - return data_t(double(result)); - } - case 2: - { - auto result = *reinterpret_cast<int32_t*>(&m_ByteCode[0] + m_PC); - m_PC += 4; - return data_t(double(result)); - } - case 3: - { - auto result = *reinterpret_cast<double*>(&m_ByteCode[0] + m_PC); - m_PC += 8; - return data_t(double(result)); - } - } - assert(false && "not reached"); - return data_t{}; + const auto length = read_integer(size); + const auto s = reinterpret_cast<const char*>(&m_ByteCode[m_PC]); + m_PC += length; + const auto value = m_Strings.Get(s, length); + return data_t(::Spasm::ValueType::String, (void*)value); } } // namespace SpasmImpl diff --git a/spasm/src/spasm_impl.hpp b/spasm/src/spasm_impl.hpp index 2548828..04e809a 100644 --- a/spasm/src/spasm_impl.hpp +++ b/spasm/src/spasm_impl.hpp @@ -3,6 +3,7 @@ #include <iostream> +#include <unordered_set> #include "types.hpp" namespace SpasmImpl @@ -23,6 +24,7 @@ enum OpCodes : char JumpT, JumpF, Const, + String, Add, Sub, Mul, @@ -30,14 +32,29 @@ enum OpCodes : char Mod, Less, LessEq, - Greater, - GreaterEq, - Equal, - NotEqual, + Greater, + GreaterEq, + Equal, + NotEqual, LastIndex = NotEqual, }; static_assert(LastIndex < 0x3f, "Too many opcodes"); +class StringTable +{ + public: + const SPStringValue* Get(const char* s, size_t length) + { + SPString v(s, length); + auto pos = m_Strings.insert(SPStringValue(v)); + return &(*pos.first); + } + + private: + typedef std::unordered_set<SPStringValue> StringMap; + StringMap m_Strings; +}; + //! The Abstract Stack Machine /*! ** The machine contains a data stack for operations and control flow and @@ -93,6 +110,8 @@ class Spasm //! Stack for function frames FrameStack m_Frames; + StringTable m_Strings; + //! Input stream for read () operation std::istream* istr; @@ -125,11 +144,11 @@ class Spasm void less(reg_t a0, reg_t a1, reg_t a2); void lesseq(reg_t a0, reg_t a1, reg_t a2); - void greater(reg_t a0, reg_t a1, reg_t a2); - void greatereq(reg_t a0, reg_t a1, reg_t a2); + void greater(reg_t a0, reg_t a1, reg_t a2); + void greatereq(reg_t a0, reg_t a1, reg_t a2); - void equal(reg_t a0, reg_t a1, reg_t a2); - void not_equal(reg_t a0, reg_t a1, reg_t a2); + void equal(reg_t a0, reg_t a1, reg_t a2); + void not_equal(reg_t a0, reg_t a1, reg_t a2); data_t get_local(reg_t reg); void set_local(reg_t reg, data_t data); @@ -137,6 +156,8 @@ class Spasm void push_data(data_t); reg_t read_reg(size_t size); data_t read_number(size_t size); + int64_t read_integer(size_t size); + data_t read_string(size_t size); }; } // namespace SpasmImpl diff --git a/spasm/src/string.hpp b/spasm/src/string.hpp new file mode 100644 index 0000000..8ffb214 --- /dev/null +++ b/spasm/src/string.hpp @@ -0,0 +1,43 @@ +#pragma once + +#include <string> + +namespace SpasmImpl +{ +typedef std::string SPString; + +class SPStringValue +{ + public: + explicit SPStringValue(SPString s) : m_Value(std::move(s)) {} + + SPStringValue(const SPStringValue&) = delete; + SPStringValue(SPStringValue&&) = default; + SPStringValue& operator=(const SPStringValue&) = delete; + SPStringValue& operator=(SPStringValue&&) = default; + + const SPString& GetValue() const { return m_Value; } + + bool operator==(const SPStringValue& rhs) const + { + return m_Value == rhs.m_Value; + } + + bool operator==(const SPString& rhs) const { return m_Value == rhs; } + + private: + SPString m_Value; +}; +} // namespace SpasmImpl + +namespace std +{ +template <> +struct hash<SpasmImpl::SPStringValue> +{ + size_t operator()(const SpasmImpl::SPStringValue& v) const + { + return std::hash<SpasmImpl::SPString>{}(v.GetValue()); + } +}; +} // namespace std
\ No newline at end of file diff --git a/spasm/src/value.hpp b/spasm/src/value.hpp index 6569721..d86c0ef 100644 --- a/spasm/src/value.hpp +++ b/spasm/src/value.hpp @@ -1,81 +1,66 @@ #pragma once #include <cassert> +#include "string.hpp" namespace Spasm { - enum class ValueType - { - Number, - Null, - Undefined, - Boolean, - String, - Array, - Object, - Function, - }; +enum class ValueType +{ + Number, + Null, + Undefined, + Boolean, + String, + Array, + Object, + Function, +}; - static_assert(int(ValueType::Function) < 8, "Too many types"); +static_assert(int(ValueType::Function) < 8, "Too many types"); struct Value { - Value() - { - m_value.as_double = 0.0; - } - - explicit Value(double v) - { - m_value.as_double = v; - } + Value() { m_value.as_double = 0.0; } - explicit Value(bool v) - : Value(ValueType::Boolean, (size_t)v) + explicit Value(double v) { m_value.as_double = v; } - { - } + explicit Value(bool v) : Value(ValueType::Boolean, (size_t)v) {} - Value(ValueType tag, size_t payload) - { - assert(tag != ValueType::Number && "Zero tag is plain double"); - assert(!(payload >> 48) && "Use only pointers to the heap."); - m_value.as_pointer.pointer = payload; - m_value.as_pointer.tag = size_t(tag); - m_value.as_pointer.nan = 0x1fff; - } - - Value(ValueType tag, void* pointer) - : Value(tag, (size_t)pointer) + Value(ValueType tag, size_t payload) { + assert(tag != ValueType::Number && "Zero tag is plain double"); + assert(!(payload >> 48) && "Use only pointers to the heap."); + m_value.as_pointer.pointer = payload; + m_value.as_pointer.tag = size_t(tag); + m_value.as_pointer.nan = 0x1fff; } + Value(ValueType tag, void* pointer) : Value(tag, (size_t)pointer) {} + struct NanPointer { - size_t pointer:48; - size_t tag:3; - size_t nan:13; + size_t pointer : 48; + size_t tag : 3; + size_t nan : 13; }; struct CheckType { - size_t payload: 48; - size_t check:16; + size_t payload : 48; + size_t check : 16; }; union { double as_double; NanPointer as_pointer; CheckType to_check; - size_t as_int64; + size_t as_int64; } m_value; static_assert(sizeof(size_t) == 8, "unsupported arch"); static_assert(sizeof(double) == 8, "unsupported arch"); - bool is_double() const - { - return m_value.to_check.check <= 0xFFF8; - } + bool is_double() const { return m_value.to_check.check <= 0xFFF8; } double get_double() const { @@ -83,99 +68,109 @@ struct Value return m_value.as_double; } - ValueType get_type() const { - return is_double()? ValueType::Number : ValueType(m_value.as_pointer.tag); + ValueType get_type() const + { + return is_double() ? ValueType::Number + : ValueType(m_value.as_pointer.tag); } - void* get_pointer() const { - return (void*)(size_t) m_value.as_pointer.pointer; + void* get_pointer() const + { + return (void*)(size_t)m_value.as_pointer.pointer; } - bool get_boolean() const { - assert(get_type() == ValueType::Boolean); - return m_value.as_pointer.pointer != 0; - } - - explicit operator bool() const { - // NaN will be true. Assume that is ok. - return (get_type() != ValueType::Boolean && m_value.as_int64 != 0) || get_boolean(); - } + bool get_boolean() const + { + assert(get_type() == ValueType::Boolean); + return m_value.as_pointer.pointer != 0; + } + explicit operator bool() const + { + // NaN will be true. Assume that is ok. + return (get_type() != ValueType::Boolean && m_value.as_int64 != 0) || + get_boolean(); + } }; inline std::istream& operator>>(std::istream& input, Value& value) { - return input >> value.m_value.as_double; + return input >> value.m_value.as_double; } inline std::ostream& operator<<(std::ostream& output, const Value& value) { - switch (value.get_type())
- {
- case ValueType::Number:
- return output << value.m_value.as_double; - case ValueType::Boolean:
- return output << bool(value); - default: - break;
- } - return output; + switch (value.get_type()) + { + case ValueType::Number: + return output << value.m_value.as_double; + case ValueType::Boolean: + return output << bool(value); + case ValueType::String: + { + const auto s = static_cast<const SpasmImpl::SPStringValue*>( + value.get_pointer()); + return output << s->GetValue(); + } + default: + break; + } + return output; } inline Value operator+(const Value& lhs, const Value& rhs) { - return Value(lhs.get_double() + rhs.get_double()); + return Value(lhs.get_double() + rhs.get_double()); } inline Value operator-(const Value& lhs, const Value& rhs) { - return Value(lhs.get_double() - rhs.get_double()); + return Value(lhs.get_double() - rhs.get_double()); } inline Value operator*(const Value& lhs, const Value& rhs) { - return Value(lhs.get_double() * rhs.get_double()); + return Value(lhs.get_double() * rhs.get_double()); } inline Value operator/(const Value& lhs, const Value& rhs) { - return Value(lhs.get_double() / rhs.get_double()); + return Value(lhs.get_double() / rhs.get_double()); } inline Value operator%(const Value& lhs, const Value& rhs) { - return Value(double(int64_t(lhs.get_double()) % int64_t(rhs.get_double()))); + return Value(double(int64_t(lhs.get_double()) % int64_t(rhs.get_double()))); } - inline Value operator<(const Value& lhs, const Value& rhs) { - return Value(lhs.get_double() < rhs.get_double()); + return Value(lhs.get_double() < rhs.get_double()); } inline Value operator>(const Value& lhs, const Value& rhs) { - return Value(lhs.get_double() > rhs.get_double()); + return Value(lhs.get_double() > rhs.get_double()); } inline Value operator<=(const Value& lhs, const Value& rhs) { - return Value(lhs.get_double() <= rhs.get_double()); + return Value(lhs.get_double() <= rhs.get_double()); } inline Value operator>=(const Value& lhs, const Value& rhs) { - return Value(lhs.get_double() >= rhs.get_double()); + return Value(lhs.get_double() >= rhs.get_double()); } inline Value operator==(const Value& lhs, const Value& rhs) { - return Value(lhs.get_double() == rhs.get_double()); + return Value(lhs.get_double() == rhs.get_double()); } inline Value operator!=(const Value& lhs, const Value& rhs) { - return Value(lhs.get_double() != rhs.get_double()); + return Value(lhs.get_double() != rhs.get_double()); } -}
\ No newline at end of file +} // namespace Spasm
\ No newline at end of file |
