Website Summary Files Commits Branches @commit @diff @stats
path: root / JSImpl / src
diff options
context:
space:
mode:
Commit12232668d931b0f3593807d2096a2c2f26844b0b (patch)
Author
 Martin Dobrev <martindobrev0@gmail.com>
2018-11-18 20:32:58 +0200
Committer
 GitHub <noreply@github.com>
2018-11-18 20:32:58 +0200
Fileseb05bfcde4de31a03ce033ed479db29c4b527bcc /JSImpl/src
IPL-12232668d931b0f3593807d2096a2c2f26844b0b.tar
IPL-12232668d931b0f3593807d2096a2c2f26844b0b.tar.gz
IPL-12232668d931b0f3593807d2096a2c2f26844b0b.zip
Parent5729bc0ea96fc0b944c243230910c537d692bcad (diff)
Code generation improvements (#56)
* Implement code generation for some unary expressions Implement debug code augmentation. Now part of expresions have source location. Extend Tokens with Column information. Refactor byte code generation. Add options for byte code generator. * Fix linux build * Little refactoring in byte code generation * Fix couple bugs in byte code generation and add some tests. * Fix some linux warnings.
7 files changed, 352 insertions, 105 deletions
-rw-r--r--JSImpl/src/ByteCodeGenerator.cpp327
-rw-r--r--JSImpl/src/ByteCodeGenerator.h12
-rw-r--r--JSImpl/src/Expression.h7
-rw-r--r--JSImpl/src/Lexer.cpp8
-rw-r--r--JSImpl/src/Lexer.h1
-rw-r--r--JSImpl/src/Parser.cpp54
-rw-r--r--JSImpl/src/main.cpp48
diff --git a/JSImpl/src/ByteCodeGenerator.cpp b/JSImpl/src/ByteCodeGenerator.cpp
index 09901e1..dc846f2 100644
--- a/JSImpl/src/ByteCodeGenerator.cpp
+++ b/JSImpl/src/ByteCodeGenerator.cpp
@@ -1,13 +1,15 @@
#include "ByteCodeGenerator.h"
#include "ExpressionVisitor.h"
#include <algorithm>
+#include <sstream>
+#include <iterator>
class ByteCodeGenerator : public ExpressionVisitor
{
public:
- ByteCodeGenerator() {};
- ~ByteCodeGenerator() {};
+ ByteCodeGenerator(const ByteCodeGeneratorOptions& o, const IPLVector<IPLString>& source) : m_Source(source), m_Options(o) {};
+ ~ByteCodeGenerator() {};
virtual void Visit(FunctionDeclaration* e) override;
virtual void Visit(BlockStatement* e) override;
@@ -20,16 +22,19 @@ public:
virtual void Visit(EmptyExpression* e) override { (void)e; }
virtual void Visit(IfStatement* e) override;
virtual void Visit(ForStatement* e) override;
+ virtual void Visit(UnaryExpression* e) override;
IPLString GetCode();
unsigned ResolveRegisterName(IPLString& name);
private:
+ void AddDebugInformation(Expression* e);
struct Instruction
{
enum Type : char
{
- ADD,
+ FIRST = 0,
+ ADD = FIRST,
SUB,
MUL,
DIV,
@@ -67,56 +72,119 @@ private:
CONST,
STRING,
HALT,
+ DEBUG,
+ LAST = DEBUG
};
Type Descriptor;
IPLString Args[3];
- double Number;
+ union
+ {
+ double Double[3];
+ long long Int[3];
+ unsigned long long Address[3];
+ } Values;
};
- size_t PushInstruction(Instruction::Type opcode, IPLString& arg1, IPLString& arg2, IPLString& arg3);
+ size_t PushInstruction(Instruction::Type opcode, const IPLString& arg1 = "", const IPLString& arg2 = "", const IPLString& arg3 = "");
size_t PushInstruction(Instruction::Type opcode, size_t Address);
- size_t PushInstruction(Instruction::Type opcode, IPLString& arg1, size_t Address);
+ size_t PushInstruction(Instruction::Type opcode, const IPLString& arg1, size_t Address);
+ size_t PushInstruction(Instruction::Type opcode, int Int);
+ size_t PushInstruction(Instruction::Type opcode, const IPLString& arg0, double value);
+ void PushConst(double c);
+ IPLString CreateRegister();
+ bool CheckOpCode(Instruction::Type opcode) { return opcode >= Instruction::Type::FIRST && opcode <= Instruction::Type::LAST; }
private:
IPLVector<IPLString> m_RegisterTable;
IPLVector<Instruction> m_Code;
+ IPLVector<IPLString> m_Source;
IPLStack<IPLString> m_RegisterStack;
- unsigned m_CurrentStackPointer;
IPLString m_OutputCode;
+ ByteCodeGeneratorOptions m_Options;
};
-size_t ByteCodeGenerator::PushInstruction(Instruction::Type opcode, IPLString& arg0, IPLString& arg1, IPLString& arg2)
+size_t ByteCodeGenerator::PushInstruction(Instruction::Type opcode, const IPLString& arg0, const IPLString& arg1, const IPLString& arg2)
{
+ assert(CheckOpCode(opcode));
Instruction ins;
ins.Descriptor = opcode;
ins.Args[0] = arg0;
ins.Args[1] = arg1;
ins.Args[2] = arg2;
- auto address = m_Code.size();
m_Code.push_back(ins);
- return address;
+ return m_Code.size() - 1;;
}
size_t ByteCodeGenerator::PushInstruction(Instruction::Type opcode, size_t Address)
{
+ assert(CheckOpCode(opcode));
Instruction ins;
ins.Descriptor = opcode;
- ins.Number = (double)Address;
- auto address = m_Code.size();
+ ins.Values.Address[0] = Address;
m_Code.push_back(ins);
- return address;
+ return m_Code.size() - 1;;
}
-size_t ByteCodeGenerator::PushInstruction(Instruction::Type opcode, IPLString& arg0, size_t Address)
+size_t ByteCodeGenerator::PushInstruction(Instruction::Type opcode, int Int)
{
+ assert(CheckOpCode(opcode));
+ Instruction ins;
+ ins.Descriptor = opcode;
+ ins.Values.Int[0] = Int;
+ m_Code.push_back(ins);
+ return m_Code.size() - 1;;
+}
+
+size_t ByteCodeGenerator::PushInstruction(Instruction::Type opcode, const IPLString& arg0, size_t Address)
+{
+ assert(CheckOpCode(opcode));
Instruction ins;
ins.Descriptor = opcode;
ins.Args[0] = arg0;
- ins.Number = (double)Address;
- auto address = m_Code.size();
+ ins.Values.Address[0] = Address;
+ m_Code.push_back(ins);
+ return m_Code.size() - 1;;
+}
+
+size_t ByteCodeGenerator::PushInstruction(Instruction::Type opcode, const IPLString& arg0, double value)
+{
+ assert(CheckOpCode(opcode));
+ Instruction ins;
+ ins.Descriptor = opcode;
+ ins.Args[0] = arg0;
+ ins.Values.Double[0] = value;
+ m_Code.push_back(ins);
+ return m_Code.size() - 1;;
+}
+
+void ByteCodeGenerator::PushConst(double c)
+{
+ IPLString regName = CreateRegister();
+ m_RegisterStack.push(regName);
+
+ PushInstruction(Instruction::Type::CONST, regName, c);
+}
+
+IPLString ByteCodeGenerator::CreateRegister()
+{
+ IPLString regName = IPLString("tmp");
+ regName += std::to_string(m_RegisterTable.size());
+ m_RegisterTable.push_back(regName);
+ return regName;
+}
+
+void ByteCodeGenerator::AddDebugInformation(Expression* e)
+{
+ if (!m_Options.AddDebugInformation || e->GetLine() == (unsigned)-1 || e->GetColumn() == (unsigned)-1)
+ {
+ return;
+ }
+ Instruction ins;
+ ins.Descriptor = Instruction::Type::DEBUG;
+ ins.Values.Int[0] = e->GetLine();
+ ins.Values.Int[1] = e->GetColumn();
m_Code.push_back(ins);
- return address;
}
void ByteCodeGenerator::Visit(FunctionDeclaration* e)
@@ -146,19 +214,14 @@ void ByteCodeGenerator::Visit(TopStatements* e)
{
auto& statements = e->GetValues();
- Instruction current;
- current.Descriptor = Instruction::Type::PUSH;
- auto index = m_Code.size();
- m_Code.push_back(current);
+ auto startAddress = PushInstruction(Instruction::Type::PUSH, (int)0);
for (auto& s : statements)
{
s->Accept(*this);
}
- m_Code[index].Number = (unsigned)m_RegisterTable.size();
+ m_Code[startAddress].Values.Int[0] = (int)m_RegisterTable.size();
- current.Descriptor = Instruction::Type::POP;
- current.Number = (unsigned)m_RegisterTable.size();
- m_Code.push_back(current);
+ PushInstruction(Instruction::Type::POP, (int)m_RegisterTable.size());
}
void ByteCodeGenerator::Visit(VariableDefinitionExpression* e)
@@ -166,6 +229,8 @@ void ByteCodeGenerator::Visit(VariableDefinitionExpression* e)
auto it = std::find_if(m_RegisterTable.begin(), m_RegisterTable.end(), [&](IPLString& current) {
return e->GetName() == current;
});
+
+
if (it != m_RegisterTable.end())
{
// TODO: error double definitions
@@ -176,64 +241,50 @@ void ByteCodeGenerator::Visit(VariableDefinitionExpression* e)
{
e->GetValue()->Accept(*this);
}
+ AddDebugInformation(e);
if (!m_RegisterStack.empty())
{
- Instruction current;
- current.Descriptor = Instruction::Type::MOV;
- current.Args[0] = e->GetName();
- current.Args[1] = m_RegisterStack.top();
+ PushInstruction(Instruction::Type::MOV, e->GetName(), m_RegisterStack.top(), "");
m_RegisterStack.pop();
- m_Code.push_back(current);
}
}
void ByteCodeGenerator::Visit(BinaryExpression* e)
{
- Instruction current;
-
- e->GetLeft()->Accept(*this);
- current.Args[1] = m_RegisterStack.top();
- m_RegisterStack.pop();
-
e->GetRight()->Accept(*this);
- current.Args[2] = m_RegisterStack.top();
- m_RegisterStack.pop();
+ auto r = m_RegisterStack.top();
+ e->GetLeft()->Accept(*this);
+ auto l = m_RegisterStack.top();
+ AddDebugInformation(e);
if (e->GetOperator() == TokenType::Equal)
{
- current.Descriptor = Instruction::Type::MOV;
- current.Args[0] = current.Args[1];
- current.Args[1] = current.Args[2];
- m_Code.push_back(current);
+ PushInstruction(Instruction::Type::MOV, l, r);
return;
}
-
- IPLString regName = IPLString ("tmp");
- regName += std::to_string(m_RegisterTable.size());
- m_RegisterTable.push_back(regName);
- m_RegisterStack.push(regName);
- current.Args[0] = regName;
+ IPLString o = CreateRegister();
+ m_RegisterStack.push(o);
switch (e->GetOperator()) {
case TokenType::Plus:
- current.Descriptor = Instruction::Type::ADD;
- break;
+ PushInstruction(Instruction::Type::ADD, o, l, r);
+ return;
case TokenType::Minus:
- current.Descriptor = Instruction::Type::SUB;
- break;
+ PushInstruction(Instruction::Type::SUB, o, l, r);
+ return;
case TokenType::Star:
- current.Descriptor = Instruction::Type::MUL;
- break;
+ PushInstruction(Instruction::Type::MUL, o, l, r);
+ return;
case TokenType::Division:
- current.Descriptor = Instruction::Type::DIV;
- break;
+ PushInstruction(Instruction::Type::DIV, o, l, r);
+ return;
case TokenType::Less:
- current.Descriptor = Instruction::Type::LESS;
- break;
+ PushInstruction(Instruction::Type::LESS, o, l, r);
+ return;
case TokenType::EqualEqual:
- current.Descriptor = Instruction::Type::EQ;
- break;
+ PushInstruction(Instruction::Type::EQ, o, l, r);
+ return;
case TokenType::BangEqual:
NOT_IMPLEMENTED;
break;
@@ -243,37 +294,28 @@ void ByteCodeGenerator::Visit(BinaryExpression* e)
default:
NOT_IMPLEMENTED;
}
- m_Code.push_back(current);
}
void ByteCodeGenerator::Visit(IfStatement* e)
{
- Instruction current;
e->GetCondition()->Accept(*this);
- current.Descriptor = Instruction::Type::JMPF;
- current.Args[0] = m_RegisterStack.top();
- current.Number = 0.0;
- m_RegisterStack.pop();
- auto ifIndex = m_Code.size();
- m_Code.push_back(current);
+ auto ifAddress = PushInstruction(Instruction::Type::JMPF, m_RegisterStack.top(), size_t(0));
e->GetIfStatement()->Accept(*this);
if (e->GetElseStatement())
{
- current.Descriptor = Instruction::Type::JMP;
- m_Code.push_back(current);
- auto afterTrueBlock = m_Code.size();
+ auto blockEndAddress = PushInstruction(Instruction::Type::JMP);
e->GetElseStatement()->Accept(*this);
// Patching
- m_Code[ifIndex].Number = (double)afterTrueBlock;
- m_Code[afterTrueBlock - 1].Number = (double)m_Code.size();
+ m_Code[ifAddress].Values.Address[0] = blockEndAddress + 1;
+ m_Code[blockEndAddress].Values.Address[0] = m_Code.size();
}
else
{
- m_Code[ifIndex].Number = (double)m_Code.size();
+ m_Code[ifAddress].Values.Address[0] = m_Code.size();
}
}
@@ -282,12 +324,12 @@ void ByteCodeGenerator::Visit(ForStatement* e)
e->GetInitialization()->Accept(*this);
auto compareAddress = m_Code.size();
e->GetCondition()->Accept(*this);
- auto endAddress = PushInstruction(Instruction::Type::JMPF, m_RegisterStack.top(), 0);
+ auto endAddress = PushInstruction(Instruction::Type::JMPF, m_RegisterStack.top(), (size_t)0);
m_RegisterStack.pop();
e->GetBody()->Accept(*this);
e->GetIteration()->Accept(*this);
PushInstruction(Instruction::Type::JMP, compareAddress);
- m_Code[endAddress].Number = (double)m_Code.size();
+ m_Code[endAddress].Values.Address[0] = m_Code.size();
}
void ByteCodeGenerator::Visit(IdentifierExpression* e)
@@ -297,12 +339,99 @@ void ByteCodeGenerator::Visit(IdentifierExpression* e)
void ByteCodeGenerator::Visit(LiteralNumber* e)
{
- IPLString regName = IPLString("const");
- regName += std::to_string(m_RegisterTable.size());
- m_RegisterTable.push_back(regName);
+ AddDebugInformation(e);
+ IPLString regName = CreateRegister();
m_RegisterStack.push(regName);
- PushInstruction(Instruction::Type::CONST, regName, (size_t)e->GetValue());
+ PushInstruction(Instruction::Type::CONST, regName, e->GetValue());
+}
+
+void ByteCodeGenerator::Visit(UnaryExpression* e)
+{
+ AddDebugInformation(e);
+ e->GetExpr()->Accept(*this);
+ auto reg = m_RegisterStack.top();
+ m_RegisterStack.pop();
+ if (e->GetSuffix())
+ {
+ switch (e->GetOperator())
+ {
+ case TokenType::PlusPlus:
+ PushConst(1);
+ {
+ auto one = m_RegisterStack.top();
+ m_RegisterStack.pop();
+ auto o = CreateRegister();
+ PushInstruction(Instruction::Type::MOV, o, reg);
+ m_RegisterStack.push(o);
+ PushInstruction(Instruction::Type::ADD, reg, reg, one);
+ }
+ return;
+ case TokenType::MinusMinus:
+ PushConst(1);
+ {
+ auto one = m_RegisterStack.top();
+ m_RegisterStack.pop();
+ auto o = CreateRegister();
+ PushInstruction(Instruction::Type::MOV, o, reg);
+ m_RegisterStack.push(o);
+ PushInstruction(Instruction::Type::SUB, reg, reg, one);
+ }
+ return;
+ default:
+ NOT_IMPLEMENTED;
+ break;
+ }
+ }
+ else
+ {
+ // prefix
+ switch (e->GetOperator())
+ {
+ case TokenType::Delete:
+ NOT_IMPLEMENTED;
+ return;
+ case TokenType::PlusPlus:
+ PushConst(1);
+ {
+ auto one = m_RegisterStack.top();
+ m_RegisterStack.pop();
+ m_RegisterStack.push(reg);
+ PushInstruction(Instruction::Type::ADD, reg, reg, one);
+ }
+ return;
+ case TokenType::MinusMinus:
+ PushConst(1);
+ {
+ auto one = m_RegisterStack.top();
+ m_RegisterStack.pop();
+ m_RegisterStack.push(reg);
+ PushInstruction(Instruction::Type::SUB, reg, reg, one);
+ }
+ return;
+ case TokenType::Void:
+ NOT_IMPLEMENTED;
+ return;
+ case TokenType::Typeof:
+ NOT_IMPLEMENTED;
+ return;
+ case TokenType::Plus:
+ NOT_IMPLEMENTED;
+ return;
+ case TokenType::Minus:
+ NOT_IMPLEMENTED;
+ return;
+ case TokenType::BitwiseNot:
+ NOT_IMPLEMENTED;
+ return;
+ case TokenType::Bang:
+ NOT_IMPLEMENTED;
+ return;
+ default:
+ NOT_IMPLEMENTED;
+ break;
+ }
+ }
}
unsigned ByteCodeGenerator::ResolveRegisterName(IPLString& name)
@@ -319,14 +448,16 @@ IPLString ByteCodeGenerator::GetCode()
auto programCounter = 0;
for (auto& i : m_Code)
{
- result += std::to_string(programCounter) + ": ";
+ if (i.Descriptor != ByteCodeGenerator::Instruction::DEBUG)
+ {
+ result += std::to_string(programCounter) + ": ";
+ }
switch (i.Descriptor)
{
case ByteCodeGenerator::Instruction::ADD:
result += "add 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::SUB:
result += "sub r" + std::to_string(ResolveRegisterName(i.Args[0]))
@@ -368,25 +499,25 @@ IPLString ByteCodeGenerator::GetCode()
NOT_IMPLEMENTED;
break;
case ByteCodeGenerator::Instruction::JMP:
- result += "jmp " + std::to_string((size_t)i.Number) + '\n';
+ result += "jmp " + std::to_string(i.Values.Address[0]) + '\n';
break;
case ByteCodeGenerator::Instruction::JMPT:
result += "jmpt r" + std::to_string(ResolveRegisterName(i.Args[0]))
- + " " + std::to_string((size_t)i.Number) + '\n';
+ + " " + std::to_string(i.Values.Address[0]) + '\n';
break;
case ByteCodeGenerator::Instruction::JMPF:
result += "jmpf r" + std::to_string(ResolveRegisterName(i.Args[0]))
- + " " + std::to_string((size_t)i.Number) + '\n';
+ + " " + std::to_string(i.Values.Address[0]) + '\n';
break;
case ByteCodeGenerator::Instruction::DUP:
result += "dup";
NOT_IMPLEMENTED;
break;
case ByteCodeGenerator::Instruction::PUSH:
- result += "push " + std::to_string((size_t)i.Number) + '\n';
+ result += "push " + std::to_string(i.Values.Int[0]) + '\n';
break;
case ByteCodeGenerator::Instruction::POP:
- result += "pop " + std::to_string((size_t)i.Number) + '\n';
+ result += "pop " + std::to_string(i.Values.Int[0]) + '\n';
break;
case ByteCodeGenerator::Instruction::SAVE:
result += "save";
@@ -471,7 +602,7 @@ IPLString ByteCodeGenerator::GetCode()
NOT_IMPLEMENTED;
break;
case ByteCodeGenerator::Instruction::CONST:
- result += "const r" + std::to_string(ResolveRegisterName(i.Args[0])) + " " + std::to_string(i.Number) + '\n';
+ 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";
@@ -480,6 +611,13 @@ IPLString ByteCodeGenerator::GetCode()
case ByteCodeGenerator::Instruction::HALT:
result += "halt\n";
break;
+ case ByteCodeGenerator::Instruction::DEBUG:
+ {
+ auto line = i.Values.Int[0];
+ auto column = i.Values.Int[1];
+ result += "D: " + m_Source[line].substr(0, column) + "@@=>" + m_Source[line].substr(column, m_Source[line].size()) + '\n';
+ }
+ break;
default:
NOT_IMPLEMENTED;
break;
@@ -492,9 +630,18 @@ IPLString ByteCodeGenerator::GetCode()
return result;
}
-IPLString GenerateByteCode(ExpressionPtr program)
+IPLString GenerateByteCode(ExpressionPtr program, const IPLString& source, const ByteCodeGeneratorOptions& options)
{
- ByteCodeGenerator generator;
+ std::istringstream sourceStream(source);
+
+ IPLVector<IPLString> sourceByLines;
+ while (sourceStream.good())
+ {
+ IPLString currentLine;
+ std::getline(sourceStream, currentLine);
+ sourceByLines.push_back(currentLine);
+ }
+ ByteCodeGenerator generator(options, sourceByLines);
program->Accept(generator);
return generator.GetCode();
diff --git a/JSImpl/src/ByteCodeGenerator.h b/JSImpl/src/ByteCodeGenerator.h
index a619603..4a1d521 100644
--- a/JSImpl/src/ByteCodeGenerator.h
+++ b/JSImpl/src/ByteCodeGenerator.h
@@ -2,5 +2,15 @@
#include "Expression.h"
+struct ByteCodeGeneratorOptions
+{
+ enum OptimizationsType
+ {
+ None
+ };
+ ByteCodeGeneratorOptions(OptimizationsType o = None, bool debug = false) : Optimisations(o), AddDebugInformation(debug) {}
+ OptimizationsType Optimisations;
+ bool AddDebugInformation;
+};
-IPLString GenerateByteCode(ExpressionPtr program);
+IPLString GenerateByteCode(ExpressionPtr program, const IPLString& source, const ByteCodeGeneratorOptions& options = ByteCodeGeneratorOptions());
diff --git a/JSImpl/src/Expression.h b/JSImpl/src/Expression.h
index 4d45cc3..3fa7b90 100644
--- a/JSImpl/src/Expression.h
+++ b/JSImpl/src/Expression.h
@@ -8,8 +8,15 @@
class Expression : public IPLEnableShared<Expression>
{
public:
+ Expression() : m_Line((unsigned)-1), m_Column((unsigned)-1) {}
virtual ~Expression() {}
virtual void Accept(ExpressionVisitor& v) = 0;
+ unsigned GetLine() { return m_Line; };
+ unsigned GetColumn() { return m_Column; };
+ void SetLocation(unsigned l, unsigned c) { m_Line = l; m_Column = c; };
+ private:
+ unsigned m_Line = 0;
+ unsigned m_Column = 0;
};
#define EXPAND_ARGUMENT(type, name, def)\
diff --git a/JSImpl/src/Lexer.cpp b/JSImpl/src/Lexer.cpp
index 8b3b909..dbbf92d 100644
--- a/JSImpl/src/Lexer.cpp
+++ b/JSImpl/src/Lexer.cpp
@@ -105,6 +105,7 @@ private:
unsigned m_Line;
unsigned m_Column;
unsigned m_Current;
+ unsigned m_LastTokenPozition;
const char* m_Code;
IPLError m_Error;
@@ -132,6 +133,7 @@ Tokenizer::Tokenizer(const char* code, const LexerSettings& settings)
: m_Line(0)
, m_Column(0)
, m_Current(0)
+ , m_LastTokenPozition(0)
, m_Code(code)
, m_Error()
, m_GenerationState(State::Success)
@@ -253,12 +255,14 @@ inline void Tokenizer::NextLine()
{
++m_Current;
++m_Line;
- m_Column = 0;
+ m_LastTokenPozition = m_Column = 0;
}
inline Token Tokenizer::ProduceToken(TokenType type, IPLString lexeme, double number = 0.0)
{
- return Token{ type, m_Line, lexeme, number };
+ auto token = Token{ type, m_Line, m_LastTokenPozition, lexeme, number };
+ m_LastTokenPozition = m_Column;
+ return token;
}
inline Token Tokenizer::ProduceSkipToken()
diff --git a/JSImpl/src/Lexer.h b/JSImpl/src/Lexer.h
index 5ea5064..3c0c785 100644
--- a/JSImpl/src/Lexer.h
+++ b/JSImpl/src/Lexer.h
@@ -110,6 +110,7 @@ struct Token
{
TokenType Type;
unsigned Line;
+ unsigned Column;
IPLString Lexeme;
double Number;
};
diff --git a/JSImpl/src/Parser.cpp b/JSImpl/src/Parser.cpp
index 8c387c8..7c3c039 100644
--- a/JSImpl/src/Parser.cpp
+++ b/JSImpl/src/Parser.cpp
@@ -63,6 +63,14 @@ private:
{
unsigned Current;
};
+
+ struct Location
+ {
+ unsigned Line;
+ unsigned Column;
+ };
+ Location GetLocation() const { return { m_Tokens[m_Current].Line , m_Tokens[m_Current].Column }; }
+
InternalState Snapshot();
void Restore(const InternalState& state);
@@ -649,6 +657,7 @@ ExpressionPtr Parser::ConditionalExpression()
ExpressionPtr Parser::AssignmentExpression()
{
+ auto location = GetLocation();
auto snapShot = m_Current;
auto left = LeftSideExpression();
if (MatchOneOf({ TokenType::Equal,
@@ -665,11 +674,21 @@ ExpressionPtr Parser::AssignmentExpression()
{
auto type = Prev().Type;
auto right = AssignmentExpression();
- return IPLMakeSharePtr<BinaryExpression>(left, right, type);
+ auto be = IPLMakeSharePtr<BinaryExpression>(left, right, type);
+ if (be)
+ {
+ be->SetLocation(location.Line, location.Column);
+ }
+ return be;
}
// revert state;
m_Current = snapShot;
- return ConditionalExpression();
+ auto ce = ConditionalExpression();
+ if (ce)
+ {
+ ce->SetLocation(location.Line, location.Column);
+ }
+ return ce;
}
ExpressionPtr Parser::Expression()
@@ -729,6 +748,7 @@ ExpressionPtr Parser::EmptyStatement()
ExpressionPtr Parser::VariableDefinition()
{
auto VariableDeclaration = [&]() -> ExpressionPtr {
+ auto location = GetLocation();
if (Match(TokenType::Identifier))
{
auto id = Prev().Lexeme;
@@ -737,7 +757,9 @@ ExpressionPtr Parser::VariableDefinition()
{
ae = AssignmentExpression();
}
- return IPLMakeSharePtr<VariableDefinitionExpression>(id, ae);
+ auto vd = IPLMakeSharePtr<VariableDefinitionExpression>(id, ae);
+ vd->SetLocation(location.Line, location.Column);
+ return vd;
}
return nullptr;
};
@@ -790,17 +812,21 @@ ExpressionPtr Parser::Block()
ExpressionPtr Parser::LabeledStatement()
{
+ auto location = GetLocation();
if (Match(TokenType::Identifier))
{
auto identifier = Prev().Lexeme;
auto stament = Statement();
- return IPLMakeSharePtr<::LabeledStatement>(identifier, stament);
+ auto ls = IPLMakeSharePtr<::LabeledStatement>(identifier, stament);
+ ls->SetLocation(location.Line, location.Column);
+ return ls;
}
return nullptr;
}
ExpressionPtr Parser::IfStatementfull()
{
+ auto location = GetLocation();
if (Match(TokenType::If))
{
auto cond = ParenthesizedExpression();
@@ -810,7 +836,9 @@ ExpressionPtr Parser::IfStatementfull()
{
elseBody = Statement();
}
- return IPLMakeSharePtr<::IfStatement>(cond, ifBody, elseBody);
+ auto is = IPLMakeSharePtr<::IfStatement>(cond, ifBody, elseBody);
+ is->SetLocation(location.Line, location.Column);
+ return is;
}
return nullptr;
}
@@ -868,18 +896,22 @@ ExpressionPtr Parser::DoStatement()
ExpressionPtr Parser::WhileStatement()
{
+ auto location = GetLocation();
if (Match(TokenType::While))
{
auto cond = ParenthesizedExpression();
auto body = Statement();
auto isDoWhile = false;
- return IPLMakeSharePtr<::WhileStatement>(cond, body, isDoWhile);
+ auto ws = IPLMakeSharePtr<::WhileStatement>(cond, body, isDoWhile);
+ ws->SetLocation(location.Line, location.Column);
+ return ws;
}
return nullptr;
}
ExpressionPtr Parser::ForStatement()
{
+ auto location = GetLocation();
if (Match(TokenType::For))
{
if (!Match(TokenType::LeftParen))
@@ -907,7 +939,9 @@ ExpressionPtr Parser::ForStatement()
assert(false);
}
auto body = Statement();
- return IPLMakeSharePtr<::ForStatement>(initializer, cond, iteration, body);
+ auto fs = IPLMakeSharePtr<::ForStatement>(initializer, cond, iteration, body);
+ fs->SetLocation(location.Line, location.Column);
+ return fs;
}
return nullptr;
}
@@ -1047,7 +1081,7 @@ ExpressionPtr Parser::FunctionDefinition()
}
return nullptr;
};
-
+ auto location = GetLocation();
if (Match(TokenType::Function))
{
if (Match(TokenType::Identifier))
@@ -1058,7 +1092,9 @@ ExpressionPtr Parser::FunctionDefinition()
{
if (auto body = Body())
{
- return IPLMakeSharePtr<FunctionDeclaration>(name, identifiers, body);
+ auto fd = IPLMakeSharePtr<FunctionDeclaration>(name, identifiers, body);
+ fd->SetLocation(location.Line, location.Column);
+ return fd;
}
else
{
diff --git a/JSImpl/src/main.cpp b/JSImpl/src/main.cpp
index c15458e..90f6023 100644
--- a/JSImpl/src/main.cpp
+++ b/JSImpl/src/main.cpp
@@ -6,6 +6,13 @@
#include <iostream>
#include <cstring>
+#include <sstream>
+#include <iterator>
+
+#if defined(_WIN32)
+#include <Windows.h>
+#endif
+
void RunParseCalc()
{
IPLVector<Token> tokens;
@@ -68,8 +75,43 @@ void Generate()
IPLVector<Token> tokens;
//Tokenize("var a = 0; var b = a + 123;a+b;", tokens);
/*Tokenize("var a; if(a < 4) { a = 8; if(a < 7) {var b = 4;}} else { a = 2} ", tokens);*/
- Tokenize("var i = 0; for (var j = 0; j < 10; j = j + 1) { i = i + j; }", tokens);
- std::cout << GenerateByteCode(Parse(tokens));
+ IPLString source = "var i = 0; \n"
+ "for (var j = 0; j < 10; j++)\n"
+ "{\n"
+ " i = i + j;\n"
+ "}";
+ Tokenize(source.c_str(), tokens);
+
+ auto asmb = GenerateByteCode(Parse(tokens), source,
+ ByteCodeGeneratorOptions(ByteCodeGeneratorOptions::OptimizationsType::None, true));
+
+ //sets the color to intense red on blue background
+#if defined(_WIN32)
+ HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
+ std::istringstream asmbStream(asmb);
+ while (asmbStream.good())
+ {
+ IPLString it;
+ std::getline(asmbStream, it);
+ if (it[0] == 'D')
+ {
+ SetConsoleTextAttribute(hStdout, FOREGROUND_GREEN| BACKGROUND_BLUE | FOREGROUND_INTENSITY);
+ auto dd = it.find("@@=>");
+ std::cout << it.substr(0, dd);
+ SetConsoleTextAttribute(hStdout, FOREGROUND_RED | BACKGROUND_BLUE | FOREGROUND_INTENSITY);
+ std::cout << it.substr(dd, 4);
+ SetConsoleTextAttribute(hStdout, FOREGROUND_GREEN | BACKGROUND_BLUE | FOREGROUND_INTENSITY);
+ std::cout << it.substr(dd + 4, it.size()) << std::endl;
+ }
+ else
+ {
+ std::cout << it << std::endl;
+ }
+ SetConsoleTextAttribute(hStdout, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
+ }
+#else
+ std::cout << asmb;
+#endif
}
int main()
@@ -78,7 +120,7 @@ int main()
//InteractiveInterpreter();
Generate();
#if defined(_WIN32)
- std::system("pause");
+ //std::system("pause");
#endif
return 0;
}