Website Summary Files Commits Branches @commit @diff @stats
diff options
context:
space:
mode:
Commit72d9bbcc3154142af79fb686d9dc7e4d1fa1badb (patch)
Author
 dtrendafilov <trendafilov.dn@gmail.com>
2018-11-29 09:13:12 +0200
Committer
 GitHub <noreply@github.com>
2018-11-29 09:13:12 +0200
Files3cea4377cba9370f3f2248557f82831d617d89d1
IPL-72d9bbcc3154142af79fb686d9dc7e4d1fa1badb.tar
IPL-72d9bbcc3154142af79fb686d9dc7e4d1fa1badb.tar.gz
IPL-72d9bbcc3154142af79fb686d9dc7e4d1fa1badb.zip
Parentcdfd42d72030a031e5c5d810fcd53441902b5cff (diff)
Feature/strings (#75)
* The assembler supports string opcode * disabled the string test until implmented * strings can be printed
12 files changed, 801 insertions, 466 deletions
-rw-r--r--JSImpl/test/sprtTests.cpp44
-rw-r--r--spasm/src/asm/assembler.cpp23
-rw-r--r--spasm/src/asm/bytecode.cpp6
-rw-r--r--spasm/src/asm/bytecode.hpp2
-rw-r--r--spasm/src/asm/lexer.cpp879
-rw-r--r--spasm/src/asm/lexer.re20
-rw-r--r--spasm/src/asm/token.cpp1
-rw-r--r--spasm/src/asm/token.hpp2
-rw-r--r--spasm/src/spasm.cpp49
-rw-r--r--spasm/src/spasm_impl.hpp37
-rw-r--r--spasm/src/string.hpp43
-rw-r--r--spasm/src/value.hpp161
diff --git a/JSImpl/test/sprtTests.cpp b/JSImpl/test/sprtTests.cpp
index a7b9e3b..25b7665 100644
--- a/JSImpl/test/sprtTests.cpp
+++ b/JSImpl/test/sprtTests.cpp
@@ -379,3 +379,47 @@ TEST_F(SPASMTest, GCD)
CompileAndRun(program);
ASSERT_EQ(Output.str(), "3");
}
+
+TEST_F(SPASMTest, StringS)
+{
+ const char* program =
+ "push 1" "\n"
+ "string 1 'the answer is 42'" "\n"
+ "print 1" "\n"
+ ;
+ CompileAndRun(program);
+ ASSERT_EQ(Output.str(), "the answer is 42");
+}
+
+TEST_F(SPASMTest, StringD)
+{
+ const char* program =
+ "push 1" "\n"
+ "string 1 'the answer is 42'" "\n"
+ "print 1" "\n"
+ ;
+ CompileAndRun(program);
+ ASSERT_EQ(Output.str(), "the answer is 42");
+}
+
+TEST_F(SPASMTest, StringEscapeS)
+{
+ const char* program =
+ "push 1" "\n"
+ "string 1 'the answer\\' is 42'" "\n"
+ "print 1" "\n"
+ ;
+ CompileAndRun(program);
+ ASSERT_EQ(Output.str(), "the answer\\' is 42");
+}
+
+TEST_F(SPASMTest, StringEscapeD)
+{
+ const char* program =
+ "push 1" "\n"
+ "string 1 \"the answer\\\" is 42\"" "\n"
+ "print 1" "\n"
+ ;
+ CompileAndRun(program);
+ ASSERT_EQ(Output.str(), "the answer\\\" is 42");
+}
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