Skip to content

Commit

Permalink
Improved ascent/descent loops
Browse files Browse the repository at this point in the history
  • Loading branch information
Natashi committed Aug 10, 2020
1 parent c9e415c commit 4593899
Show file tree
Hide file tree
Showing 3 changed files with 138 additions and 134 deletions.
177 changes: 111 additions & 66 deletions source/GcLib/gstd/Script/Parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,70 @@
//Natashi's TODO: Implement a parse tree

namespace gstd {
script_block::script_block(int the_level, block_kind the_kind) {
level = the_level;
arguments = 0;
func = nullptr;
kind = the_kind;
}

#pragma push_macro("new")
#undef new
code::code() {
}
code::code(int the_line, command_kind the_command) {
line = the_line;
command = the_command;
}
code::code(int the_line, command_kind the_command, int the_level, size_t the_variable, const std::string& the_name)
: code(the_line, the_command) {
level = the_level;
variable = the_variable;
#ifdef _DEBUG
var_name = the_name;
#endif
}
code::code(int the_line, command_kind the_command, script_block* the_sub, int the_arguments) : code(the_line, the_command) {
sub = the_sub;
arguments = the_arguments;
}
code::code(int the_line, command_kind the_command, size_t the_ip) : code(the_line, the_command) {
ip = the_ip;
}
code::code(int the_line, command_kind the_command, const value& the_data) : code(the_line, the_command) {
new (&data) value(the_data);
}
code::code(const code& src) {
*this = src;
}
code::~code() {
switch (command) {
case command_kind::pc_push_value:
data.~value();
break;
}
}

code& code::operator=(const code& src) {
if (this == std::addressof(src)) return *this;
this->~code();

switch (src.command) {
case command_kind::pc_push_value:
new (&data) value(src.data);
break;
default:
sub = src.sub;
arguments = src.arguments;
break;
}
command = src.command;
line = src.line;

return *this;
}
#pragma pop_macro("new")

const function base_operations[] = {
//{ "true", true_, 0 },
//{ "false", false_, 0 },
Expand Down Expand Up @@ -92,8 +156,8 @@ namespace gstd {
parser_state_t stateParser(lexer_main);

int countVar = scan_current_scope(&stateParser, 1, nullptr, false);
if (countVar > 0)
stateParser.AddCode(engine->main_block, code(command_kind::pc_var_alloc, countVar));
stateParser.AddCode(engine->main_block, code(command_kind::pc_var_alloc, countVar));

parse_statements(engine->main_block, &stateParser, token_kind::tk_end, token_kind::tk_semicolon);

parser_assert(stateParser.next() == token_kind::tk_end,
Expand Down Expand Up @@ -1290,87 +1354,69 @@ namespace gstd {

size_t ip_ascdsc_begin = state->ip;

script_block* containerBlock = engine->new_block(block->level + 1, block_kind::bk_normal);
state->AddCode(block, code(command_kind::pc_call, containerBlock, 0));
//Parse the first expression
parse_expression(block, state);

parser_state_t containerState(state->lex);
parser_assert(state, state->next() == token_kind::tk_range, "\"..\" is required.\r\n");
state->advance();

frame.push_back(scope_t(containerBlock->kind));
{
auto InsertSymbol = [&](size_t var, const std::string& name, bool isInternal) {
symbol s;
s.level = containerBlock->level;
s.sub = nullptr;
s.variable = var;
s.can_overload = false;
s.can_modify = !isInternal;
frame.back().singular_insert(name, s);
};
//Parse the second expression
parse_expression(block, state);

InsertSymbol(0, "!0", true); //An internal value, inaccessible to scripters (value copied to s_2 in each loop)
InsertSymbol(1, "!1", true); //An internal value, inaccessible to scripters
InsertSymbol(2, counterName, false); //The actual counter
parser_assert(state, state->next() == token_kind::tk_close_par, "\")\" is required.\r\n");
state->advance();

containerState.AddCode(containerBlock, code(command_kind::pc_var_alloc, 3));
if (state->next() == token_kind::tk_LOOP)
state->advance();

parse_expression(containerBlock, &containerState); //First value, to s_0 if ascent
containerState.AddCode(containerBlock, code(command_kind::pc_assign,
containerBlock->level, (int)(!isAscent), "!0"));
state->AddCode(block, code(command_kind::pc_dup_n_unique, 2)); //s1 s2 -> s1 s2 s1
state->AddCode(block, code(command_kind::pc_dup_n_unique, 2)); //s1 s2 s1 -> s1 s2 s1 s2

parser_assert(&containerState, containerState.next() == token_kind::tk_range, "\"..\" is required.\r\n");
containerState.advance();
if (isAscent)
state->AddCode(block, code(command_kind::pc_swap));

parse_expression(containerBlock, &containerState); //Second value, to s_0 if descent
containerState.AddCode(containerBlock, code(command_kind::pc_assign,
containerBlock->level, (int)(isAscent), "!1"));
size_t ip = state->ip;

state->AddCode(block, code(isAscent ? command_kind::pc_compare_and_loop_ascent :
command_kind::pc_compare_and_loop_descent));

parser_assert(&containerState, containerState.next() == token_kind::tk_close_par, "\")\" is required.\r\n");
containerState.advance();
if (!isAscent) {
state->AddCode(block, code(command_kind::pc_dup_n, 1));
state->AddCode(block, code(command_kind::pc_inline_dec, -1, 0, "!0"));
}

if (containerState.next() == token_kind::tk_LOOP) {
containerState.advance();
}
state->AddCode(block, code(command_kind::pc_dup_n, 1));

size_t ip = containerBlock->codes.size();
script_block* b = engine->new_block(block->level + 1, block_kind::bk_loop);
{
parser_state_t newState(state->lex);

containerState.AddCode(containerBlock, code(command_kind::pc_push_variable,
containerBlock->level, 0, "!0"));
containerState.AddCode(containerBlock, code(command_kind::pc_push_variable,
containerBlock->level, 1, "!1"));
containerState.AddCode(containerBlock, code(isAscent ? command_kind::pc_compare_and_loop_ascent :
command_kind::pc_compare_and_loop_descent));
std::vector<std::string> counter;
counter.push_back(counterName);

if (!isAscent) {
containerState.AddCode(containerBlock, code(command_kind::pc_inline_dec,
containerBlock->level, 0, "!0"));
}
parse_block(b, &newState, &counter, false, true);
}

//Copy s_0 to s_2
containerState.AddCode(containerBlock, code(command_kind::pc_push_variable,
containerBlock->level, 0, "!0"));
containerState.AddCode(containerBlock, code(command_kind::pc_assign,
containerBlock->level, 2, counterName));
state->AddCode(block, code(command_kind::pc_call, b, 1));

//Parse the code contained inside the loop
size_t codeBlockSize = parse_inline_block(nullptr, containerBlock, &containerState, block_kind::bk_loop, true);
state->AddCode(block, code(command_kind::pc_continue_marker));

containerState.AddCode(containerBlock, code(command_kind::pc_continue_marker));
if (isAscent) {
state->AddCode(block, code(command_kind::pc_dup_n, 1));
state->AddCode(block, code(command_kind::pc_inline_inc, -1, 0, "!0"));
}

if (isAscent) {
containerState.AddCode(containerBlock, code(command_kind::pc_inline_inc,
containerBlock->level, 0, "!0"));
}
state->AddCode(block, code(command_kind::pc_jump, ip));
state->AddCode(block, code(command_kind::pc_loop_back));

containerState.AddCode(containerBlock, code(command_kind::pc_jump, ip));
containerState.AddCode(containerBlock, code(command_kind::pc_loop_back));
//Pop twice for two statements * 2
state->AddCode(block, code(command_kind::pc_pop, 2 * 2));

if (codeBlockSize == 0U) {
engine->blocks.pop_back(); //containerBlock
while (state->ip > ip_ascdsc_begin)
state->PopCode(block);
}
if (b->codes.size() == 1U) { //1 for pc_assign
engine->blocks.pop_back();
while (state->ip > ip_ascdsc_begin)
state->PopCode(block);
}
frame.pop_back();

need_terminator = false;
break;
Expand Down Expand Up @@ -1660,8 +1706,7 @@ namespace gstd {

if (!single_line) {
int countVar = scan_current_scope(state, block->level, args, adding_result);
if (countVar > 0)
state->AddCode(block, code(command_kind::pc_var_alloc, countVar));
state->AddCode(block, code(command_kind::pc_var_alloc, countVar));
}
if (args) {
scope_t* ptrBackFrame = &frame.back();
Expand Down
80 changes: 14 additions & 66 deletions source/GcLib/gstd/Script/Parser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,14 @@
#include "ScriptLexer.hpp"
#include "ScriptFunction.hpp"

#pragma push_macro("new")
#undef new

#pragma warning (disable : 4786) //STL Warning抑止
#pragma warning (disable : 4018) //signed と unsigned の数値を比較
#pragma warning (disable : 4244) //double' から 'float' に変換

namespace gstd {
enum class command_kind : uint8_t {
pc_var_alloc, pc_assign, pc_assign_writable, pc_break_loop, pc_break_routine,
pc_var_alloc,
pc_assign, pc_assign_writable, pc_break_loop, pc_break_routine,
pc_call, pc_call_and_push_result,

pc_jump_target,
Expand All @@ -27,7 +25,7 @@ namespace gstd {
pc_compare_e, pc_compare_g, pc_compare_ge, pc_compare_l,
pc_compare_le, pc_compare_ne,

pc_dup_n,
pc_dup_n, pc_dup_n_unique,

pc_for, pc_for_each_and_push_first,
pc_compare_and_loop_ascent, pc_compare_and_loop_descent,
Expand Down Expand Up @@ -62,12 +60,7 @@ namespace gstd {
std::vector<code> codes;
block_kind kind;

script_block(int the_level, block_kind the_kind) {
level = the_level;
arguments = 0;
func = nullptr;
kind = the_kind;
}
script_block(int the_level, block_kind the_kind);
};
struct code {
command_kind command = command_kind::pc_null;
Expand All @@ -93,30 +86,12 @@ namespace gstd {
};
};

code() {}
code(int the_line, command_kind the_command) {
line = the_line;
command = the_command;
}
code(int the_line, command_kind the_command, int the_level, size_t the_variable, const std::string& the_name)
: code(the_line, the_command)
{
level = the_level;
variable = the_variable;
#ifdef _DEBUG
var_name = the_name;
#endif
}
code(int the_line, command_kind the_command, script_block* the_sub, int the_arguments) : code(the_line, the_command) {
sub = the_sub;
arguments = the_arguments;
}
code(int the_line, command_kind the_command, size_t the_ip) : code(the_line, the_command) {
ip = the_ip;
}
code(int the_line, command_kind the_command, const value& the_data) : code(the_line, the_command) {
new (&data) value(the_data);
}
code();
code(int the_line, command_kind the_command);
code(int the_line, command_kind the_command, int the_level, size_t the_variable, const std::string& the_name);
code(int the_line, command_kind the_command, script_block* the_sub, int the_arguments);
code(int the_line, command_kind the_command, size_t the_ip);
code(int the_line, command_kind the_command, const value& the_data);

code(command_kind the_command) : code(0, the_command) {}
code(command_kind the_command, int the_level, size_t the_variable, const std::string& the_name)
Expand All @@ -126,36 +101,11 @@ namespace gstd {
code(command_kind the_command, size_t the_ip) : code(0, the_command, the_ip) {}
code(command_kind the_command, const value& the_data) : code(0, the_command, the_data) {}

code(const code& src) {
*this = src;
}

~code() {
switch (command) {
case command_kind::pc_push_value:
data.~value();
break;
}
}
code(const code& src);

code& operator=(const code& src) {
if (this == std::addressof(src)) return *this;
this->~code();

switch (src.command) {
case command_kind::pc_push_value:
new (&data) value(src.data);
break;
default:
sub = src.sub;
arguments = src.arguments;
break;
}
command = src.command;
line = src.line;
~code();

return *this;
}
code& operator=(const code& src);
};

class parser {
Expand Down Expand Up @@ -302,6 +252,4 @@ namespace gstd {
}
return command_kind::pc_jump_target;
}
}

#pragma pop_macro("new")
}
15 changes: 13 additions & 2 deletions source/GcLib/gstd/Script/Script.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,7 @@ void script_machine::run_code() {
break;
}
case command_kind::pc_dup_n:
case command_kind::pc_dup_n_unique:
{
stack_t& stack = current->stack;
value* val = &stack.back() - c->ip + 1;
Expand All @@ -491,6 +492,8 @@ void script_machine::run_code() {
value valCopy = *val;
stack.push_back(valCopy);
}
if (c->command == command_kind::pc_dup_n_unique)
stack.back().unique();
break;
}
case command_kind::pc_swap:
Expand All @@ -508,15 +511,23 @@ void script_machine::run_code() {
value* cmp_arg = (value*)(&stack.back() - 1);
value cmp_res = BaseFunction::compare(this, 2, cmp_arg);

/*
{
std::wstring str = c->command == command_kind::pc_compare_and_loop_ascent ? L"Asc: " : L"Dsc: ";
str += cmp_arg->as_string() + L" " + (cmp_arg + 1)->as_string();
Logger::WriteTop(str);
}
*/

bool is_skip = c->command == command_kind::pc_compare_and_loop_ascent ?
(cmp_res.as_int() >= 0) : (cmp_res.as_int() <= 0);
(cmp_res.as_int() <= 0) : (cmp_res.as_int() >= 0);
if (is_skip) {
do
++(current->ip);
while (current->sub->codes[current->ip - 1].command != command_kind::pc_loop_back);
}

current->stack.pop_back(2U);
//current->stack.pop_back(2U);
break;
}
case command_kind::pc_loop_count:
Expand Down

0 comments on commit 4593899

Please sign in to comment.