Website Summary Files Commits Branches @commit @diff @stats
path: root / JSImpl
diff options
context:
space:
mode:
Commit4e883334a14ff22f12765204d6bf223d07c0298f (patch)
Author
 Martin Dobrev <martindobrev0@gmail.com>
2020-11-21 14:47:49 +0200
Committer
 Martin Dobrev <martindobrev0@gmail.com>
2020-11-21 14:47:49 +0200
Files1e4c153947023080f0256cb4a9cc531458d5e14a /JSImpl
IPL-4e883334a14ff22f12765204d6bf223d07c0298f.tar
IPL-4e883334a14ff22f12765204d6bf223d07c0298f.tar.gz
IPL-4e883334a14ff22f12765204d6bf223d07c0298f.zip
Parent64a545c0c9988755a1b022bffd5f4303d0070af2 (diff)
Implement byte code generation for object literals.
2 files changed, 117 insertions, 11 deletions
-rw-r--r--JSImpl/src/ByteCodeGenerator.cpp62
-rw-r--r--JSImpl/test/CodeGenerationTests.cpp66
diff --git a/JSImpl/src/ByteCodeGenerator.cpp b/JSImpl/src/ByteCodeGenerator.cpp
index 49e734b..31a80bd 100644
--- a/JSImpl/src/ByteCodeGenerator.cpp
+++ b/JSImpl/src/ByteCodeGenerator.cpp
@@ -23,6 +23,9 @@ public:
virtual void Visit(IfStatement* e) override;
virtual void Visit(ForStatement* e) override;
virtual void Visit(UnaryExpression* e) override;
+ virtual void Visit(LiteralField* e) override;
+ virtual void Visit(LiteralObject* e) override;
+ virtual void Visit(LiteralString* e) override;
IPLString GetCode();
unsigned ResolveRegisterName(IPLString& name);
@@ -447,6 +450,41 @@ void ByteCodeGenerator::Visit(UnaryExpression* e)
}
}
+void ByteCodeGenerator::Visit(LiteralField* e)
+{
+ e->GetValue()->Accept(*this);
+ e->GetIdentifier()->Accept(*this);
+}
+
+void ByteCodeGenerator::Visit(LiteralObject* e)
+{
+ auto initialSize = m_RegisterStack.size();
+ auto objReg = CreateRegister();
+
+ for (const auto& field : e->GetValues())
+ {
+ field->Accept(*this);
+ auto fieldName = m_RegisterStack.top();
+ m_RegisterStack.pop();
+
+ auto fieldNameReg = CreateRegister();
+ PushInstruction(Instruction::Type::STRING, fieldNameReg, fieldName);
+
+ auto valueReg = m_RegisterStack.top();
+ m_RegisterStack.pop();
+ PushInstruction(Instruction::Type::SET, objReg, fieldNameReg, valueReg);
+ }
+ assert(m_RegisterStack.size() == initialSize);
+ m_RegisterStack.push(objReg);
+}
+
+void ByteCodeGenerator::Visit(LiteralString* e)
+{
+ auto stringReg = CreateRegister();
+ PushInstruction(Instruction::Type::STRING, stringReg, e->GetValue());
+ m_RegisterStack.push(stringReg);
+}
+
unsigned ByteCodeGenerator::ResolveRegisterName(IPLString& name)
{
auto it = std::find_if(m_RegisterTable.begin(), m_RegisterTable.end(), [&](IPLString& current) {
@@ -592,20 +630,22 @@ IPLString ByteCodeGenerator::GetCode()
NOT_IMPLEMENTED;
break;
case ByteCodeGenerator::Instruction::GET:
- result += "get";
- NOT_IMPLEMENTED;
+ result += "get r" + std::to_string(ResolveRegisterName(i.Args[0]))
+ + " r" + std::to_string(ResolveRegisterName(i.Args[1]))
+ + " r" + std::to_string(ResolveRegisterName(i.Args[2])) + '\n';
break;
case ByteCodeGenerator::Instruction::SET:
- result += "set";
- NOT_IMPLEMENTED;
+ result += "set r" + std::to_string(ResolveRegisterName(i.Args[0]))
+ + " r" + std::to_string(ResolveRegisterName(i.Args[1]))
+ + " r" + std::to_string(ResolveRegisterName(i.Args[2])) + '\n';
break;
case ByteCodeGenerator::Instruction::INC:
- result += "inc";
- NOT_IMPLEMENTED;
+ result += "inc r" + std::to_string(ResolveRegisterName(i.Args[0]))
+ + " r" + std::to_string(i.Values.Int[0]) + '\n';
break;
case ByteCodeGenerator::Instruction::DEC:
- result += "dec";
- NOT_IMPLEMENTED;
+ result += "dec r" + std::to_string(ResolveRegisterName(i.Args[0]))
+ + " r" + std::to_string(i.Values.Int[0]) + '\n';
break;
case ByteCodeGenerator::Instruction::AND:
result += "and r" + std::to_string(ResolveRegisterName(i.Args[0]))
@@ -623,7 +663,8 @@ IPLString ByteCodeGenerator::GetCode()
+ " r" + std::to_string(ResolveRegisterName(i.Args[2])) + '\n';
break;
case ByteCodeGenerator::Instruction::NOT:
- result += "not";
+ result += "not r" + std::to_string(ResolveRegisterName(i.Args[0]))
+ + " r" + std::to_string(ResolveRegisterName(i.Args[1])) + '\n';
NOT_IMPLEMENTED;
break;
case ByteCodeGenerator::Instruction::THROW:
@@ -638,8 +679,7 @@ IPLString ByteCodeGenerator::GetCode()
result += "const r" + std::to_string(ResolveRegisterName(i.Args[0])) + " " + std::to_string(i.Values.Double[0]) + '\n';
break;
case ByteCodeGenerator::Instruction::STRING:
- result += "string";
- NOT_IMPLEMENTED;
+ result += "string r" + std::to_string(ResolveRegisterName(i.Args[0])) + " " + i.Args[1] + '\n';
break;
case ByteCodeGenerator::Instruction::HALT:
result += "halt\n";
diff --git a/JSImpl/test/CodeGenerationTests.cpp b/JSImpl/test/CodeGenerationTests.cpp
index a6ebc6e..4a8ebbe 100644
--- a/JSImpl/test/CodeGenerationTests.cpp
+++ b/JSImpl/test/CodeGenerationTests.cpp
@@ -169,4 +169,70 @@ TEST(CodeGen, SimpleFor)
"15: halt\n";
ASSERT_TRUE(asmb == expected);
+}
+
+TEST(CodeGen, EmptyObject)
+{
+ IPLString source = "var a = {}";
+ IPLVector<Token> tokens = Tokenize(source.c_str()).tokens;
+ auto ast = Parse(tokens);
+ auto asmb = GenerateByteCode(ast, source,
+ ByteCodeGeneratorOptions(ByteCodeGeneratorOptions::OptimizationsType::None, false));
+ IPLString expected = "0: push 2\n"
+ "1: mov r0 r1\n"
+ "2: pop 2\n"
+ "3: halt\n";
+
+ ASSERT_TRUE(asmb == expected);
+}
+
+
+TEST(CodeGen, ObjectWithFlatProps)
+{
+ IPLString source = "var a = {a: 5, n: \"pesho\"}";
+ IPLVector<Token> tokens = Tokenize(source.c_str()).tokens;
+ auto ast = Parse(tokens);
+ auto asmb = GenerateByteCode(ast, source,
+ ByteCodeGeneratorOptions(ByteCodeGeneratorOptions::OptimizationsType::None, false));
+ IPLString expected = "0: push 6\n"
+ "1: const r2 5.000000\n"
+ "2: string r3 a\n"
+ "3: set r1 r3 r2\n"
+ "4: string r4 pesho\n"
+ "5: string r5 n\n"
+ "6: set r1 r5 r4\n"
+ "7: mov r0 r1\n"
+ "8: pop 6\n"
+ "9: halt\n";
+
+ ASSERT_TRUE(asmb == expected);
+}
+
+TEST(CodeGen, NestedObjects)
+{
+ IPLString source = "var a = {a: 5, n: \"pesho\", obj1: {a: 4, b: 5}}\n";
+ IPLVector<Token> tokens = Tokenize(source.c_str()).tokens;
+ auto ast = Parse(tokens);
+ auto asmb = GenerateByteCode(ast, source,
+ ByteCodeGeneratorOptions(ByteCodeGeneratorOptions::OptimizationsType::None, false));
+ IPLString expected = "0: push 12\n"
+ "1: const r2 5.000000\n"
+ "2: string r3 a\n"
+ "3: set r1 r3 r2\n"
+ "4: string r4 pesho\n"
+ "5: string r5 n\n"
+ "6: set r1 r5 r4\n"
+ "7: const r7 4.000000\n"
+ "8: string r8 a\n"
+ "9: set r6 r8 r7\n"
+ "10: const r9 5.000000\n"
+ "11: string r10 b\n"
+ "12: set r6 r10 r9\n"
+ "13: string r11 obj1\n"
+ "14: set r1 r11 r6\n"
+ "15: mov r0 r1\n"
+ "16: pop 12\n"
+ "17: halt\n";
+
+ ASSERT_TRUE(asmb == expected);
} \ No newline at end of file