context wrapper & t6 bug fixing
This commit is contained in:
parent
6980506e88
commit
9b7eb28b84
@ -185,6 +185,7 @@ void assembler::assemble_function(const function::ptr& func)
|
|||||||
{
|
{
|
||||||
func->index = script_->pos();
|
func->index = script_->pos();
|
||||||
func->size = 0;
|
func->size = 0;
|
||||||
|
labels_.clear();
|
||||||
|
|
||||||
for (const auto& inst : func->instructions)
|
for (const auto& inst : func->instructions)
|
||||||
{
|
{
|
||||||
@ -197,7 +198,7 @@ void assembler::assemble_function(const function::ptr& func)
|
|||||||
|
|
||||||
const auto& itr = func->labels.find(old_idx);
|
const auto& itr = func->labels.find(old_idx);
|
||||||
|
|
||||||
if (itr != labels_.end())
|
if (itr != func->labels.end())
|
||||||
{
|
{
|
||||||
labels_.insert({ inst->index, itr->second });
|
labels_.insert({ inst->index, itr->second });
|
||||||
}
|
}
|
||||||
@ -235,9 +236,7 @@ void assembler::assemble_instruction(const instruction::ptr& inst)
|
|||||||
case opcode::OP_GetAnim:
|
case opcode::OP_GetAnim:
|
||||||
case opcode::OP_GetGameRef:
|
case opcode::OP_GetGameRef:
|
||||||
case opcode::OP_CreateLocalVariable:
|
case opcode::OP_CreateLocalVariable:
|
||||||
case opcode::OP_RemoveLocalVariables:
|
|
||||||
case opcode::OP_EvalArray:
|
case opcode::OP_EvalArray:
|
||||||
case opcode::OP_EvalLocalArrayRefCached:
|
|
||||||
case opcode::OP_EvalArrayRef:
|
case opcode::OP_EvalArrayRef:
|
||||||
case opcode::OP_ClearArray:
|
case opcode::OP_ClearArray:
|
||||||
case opcode::OP_EmptyArray:
|
case opcode::OP_EmptyArray:
|
||||||
@ -364,7 +363,9 @@ void assembler::assemble_instruction(const instruction::ptr& inst)
|
|||||||
case opcode::OP_SafeCreateLocalVariables:
|
case opcode::OP_SafeCreateLocalVariables:
|
||||||
assemble_localvars(inst);
|
assemble_localvars(inst);
|
||||||
break;
|
break;
|
||||||
|
case opcode::OP_RemoveLocalVariables:
|
||||||
case opcode::OP_EvalLocalVariableCached:
|
case opcode::OP_EvalLocalVariableCached:
|
||||||
|
case opcode::OP_EvalLocalArrayRefCached:
|
||||||
case opcode::OP_SafeSetWaittillVariableFieldCached:
|
case opcode::OP_SafeSetWaittillVariableFieldCached:
|
||||||
case opcode::OP_EvalLocalVariableRefCached:
|
case opcode::OP_EvalLocalVariableRefCached:
|
||||||
script_->write<std::uint8_t>(static_cast<std::uint8_t>(inst->opcode));
|
script_->write<std::uint8_t>(static_cast<std::uint8_t>(inst->opcode));
|
||||||
@ -523,9 +524,7 @@ void assembler::align_instruction(const instruction::ptr& inst)
|
|||||||
case opcode::OP_GetAnim:
|
case opcode::OP_GetAnim:
|
||||||
case opcode::OP_GetGameRef:
|
case opcode::OP_GetGameRef:
|
||||||
case opcode::OP_CreateLocalVariable:
|
case opcode::OP_CreateLocalVariable:
|
||||||
case opcode::OP_RemoveLocalVariables:
|
|
||||||
case opcode::OP_EvalArray:
|
case opcode::OP_EvalArray:
|
||||||
case opcode::OP_EvalLocalArrayRefCached:
|
|
||||||
case opcode::OP_EvalArrayRef:
|
case opcode::OP_EvalArrayRef:
|
||||||
case opcode::OP_ClearArray:
|
case opcode::OP_ClearArray:
|
||||||
case opcode::OP_EmptyArray:
|
case opcode::OP_EmptyArray:
|
||||||
@ -649,7 +648,9 @@ void assembler::align_instruction(const instruction::ptr& inst)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case opcode::OP_RemoveLocalVariables:
|
||||||
case opcode::OP_EvalLocalVariableCached:
|
case opcode::OP_EvalLocalVariableCached:
|
||||||
|
case opcode::OP_EvalLocalArrayRefCached:
|
||||||
case opcode::OP_SafeSetWaittillVariableFieldCached:
|
case opcode::OP_SafeSetWaittillVariableFieldCached:
|
||||||
case opcode::OP_EvalLocalVariableRefCached:
|
case opcode::OP_EvalLocalVariableRefCached:
|
||||||
script_->seek(1);
|
script_->seek(1);
|
||||||
|
@ -40,23 +40,21 @@ void compiler::compile(const std::string& file, std::vector<std::uint8_t>& data)
|
|||||||
{
|
{
|
||||||
filename_ = file;
|
filename_ = file;
|
||||||
|
|
||||||
auto prog = parse_buffer(filename_, data);
|
auto prog = parse_buffer(filename_, reinterpret_cast<char*>(data.data()), data.size());
|
||||||
|
|
||||||
compile_program(prog);
|
compile_program(prog);
|
||||||
}
|
}
|
||||||
|
|
||||||
void compiler::read_callback(std::function<std::vector<std::uint8_t>(const std::string&)> func)
|
void compiler::mode(build mode)
|
||||||
{
|
{
|
||||||
read_callback_ = func;
|
mode_ = mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto compiler::parse_buffer(const std::string& file, std::vector<std::uint8_t>& data) -> ast::program::ptr
|
auto compiler::parse_buffer(const std::string& file, char* data, size_t size) -> ast::program::ptr
|
||||||
{
|
{
|
||||||
ast::program::ptr result(nullptr);
|
ast::program::ptr result(nullptr);
|
||||||
|
|
||||||
resolver::set_reader(read_callback_);
|
lexer lexer(mode_, file, data, size);
|
||||||
|
|
||||||
lexer lexer(mode_, file, reinterpret_cast<char*>(data.data()), data.size());
|
|
||||||
|
|
||||||
parser parser(lexer, result);
|
parser parser(lexer, result);
|
||||||
|
|
||||||
@ -70,8 +68,8 @@ auto compiler::parse_buffer(const std::string& file, std::vector<std::uint8_t>&
|
|||||||
|
|
||||||
auto compiler::parse_file(const std::string& file) -> ast::program::ptr
|
auto compiler::parse_file(const std::string& file) -> ast::program::ptr
|
||||||
{
|
{
|
||||||
auto buffer = read_callback_(file);
|
auto data = resolver::file_data(file);
|
||||||
auto result = parse_buffer(file, buffer);
|
auto result = parse_buffer(file, std::get<1>(data), std::get<2>(data));
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -113,7 +111,7 @@ void compiler::emit_include(const ast::include::ptr& include)
|
|||||||
{
|
{
|
||||||
if (entry == path)
|
if (entry == path)
|
||||||
{
|
{
|
||||||
throw comp_error(include->loc(), "error duplicated include file '" + path + "'.");
|
throw comp_error(include->loc(), "duplicated include file '" + path + "'.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -213,18 +211,20 @@ void compiler::emit_decl_thread(const ast::decl_thread::ptr& thread)
|
|||||||
can_break_ = false;
|
can_break_ = false;
|
||||||
can_continue_ = false;
|
can_continue_ = false;
|
||||||
local_stack_.clear();
|
local_stack_.clear();
|
||||||
break_loc_ = "";
|
blocks_.clear();
|
||||||
continue_loc_ = "";
|
|
||||||
abort_ = abort_t::abort_none;
|
|
||||||
|
|
||||||
process_thread(thread);
|
process_thread(thread);
|
||||||
|
|
||||||
|
blocks_.push_back(block());
|
||||||
|
|
||||||
emit_expr_parameters(thread->params);
|
emit_expr_parameters(thread->params);
|
||||||
emit_stmt_list(thread->stmt);
|
emit_stmt_list(thread->stmt);
|
||||||
|
|
||||||
if (abort_ == abort_t::abort_none)
|
if (blocks_.back().abort == abort_t::abort_none)
|
||||||
emit_opcode(opcode::OP_End);
|
emit_opcode(opcode::OP_End);
|
||||||
|
|
||||||
|
blocks_.pop_back();
|
||||||
|
|
||||||
function_->size = index_ - function_->index;
|
function_->size = index_ - function_->index;
|
||||||
assembly_->functions.push_back(std::move(function_));
|
assembly_->functions.push_back(std::move(function_));
|
||||||
}
|
}
|
||||||
@ -479,8 +479,13 @@ void compiler::emit_stmt_if(const ast::stmt_if::ptr& stmt)
|
|||||||
emit_opcode(opcode::OP_JumpOnFalse, end_loc);
|
emit_opcode(opcode::OP_JumpOnFalse, end_loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto& paren = blocks_.back();
|
||||||
|
blocks_.push_back(block(paren.loc_break, paren.loc_continue));
|
||||||
|
|
||||||
emit_stmt(stmt->stmt);
|
emit_stmt(stmt->stmt);
|
||||||
|
|
||||||
|
blocks_.pop_back();
|
||||||
|
|
||||||
insert_label(end_loc);
|
insert_label(end_loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -500,106 +505,102 @@ void compiler::emit_stmt_ifelse(const ast::stmt_ifelse::ptr& stmt)
|
|||||||
emit_opcode(opcode::OP_JumpOnFalse, else_loc);
|
emit_opcode(opcode::OP_JumpOnFalse, else_loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto& paren = blocks_.back();
|
||||||
|
blocks_.push_back(block(paren.loc_break, paren.loc_continue));
|
||||||
emit_stmt(stmt->stmt_if);
|
emit_stmt(stmt->stmt_if);
|
||||||
|
blocks_.pop_back();
|
||||||
|
|
||||||
emit_opcode(opcode::OP_Jump, end_loc);
|
emit_opcode(opcode::OP_Jump, end_loc);
|
||||||
|
|
||||||
insert_label(else_loc);
|
insert_label(else_loc);
|
||||||
|
|
||||||
|
auto& root = blocks_.back();
|
||||||
|
blocks_.push_back(block(root.loc_break, root.loc_continue));
|
||||||
emit_stmt(stmt->stmt_else);
|
emit_stmt(stmt->stmt_else);
|
||||||
|
blocks_.pop_back();
|
||||||
|
|
||||||
insert_label(end_loc);
|
insert_label(end_loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void compiler::emit_stmt_while(const ast::stmt_while::ptr& stmt)
|
void compiler::emit_stmt_while(const ast::stmt_while::ptr& stmt)
|
||||||
{
|
{
|
||||||
auto old_abort = abort_;
|
|
||||||
auto old_break_loc = break_loc_;
|
|
||||||
auto old_continue_loc = continue_loc_;
|
|
||||||
auto old_break = can_break_;
|
auto old_break = can_break_;
|
||||||
auto old_continue = can_continue_;
|
auto old_continue = can_continue_;
|
||||||
|
|
||||||
can_break_ = true;
|
can_break_ = true;
|
||||||
can_continue_ = true;
|
can_continue_ = true;
|
||||||
break_loc_ = create_label();
|
auto break_loc = create_label();
|
||||||
continue_loc_ = insert_label();
|
auto continue_loc = insert_label();
|
||||||
|
|
||||||
auto begin_loc = continue_loc_;
|
auto begin_loc = continue_loc;
|
||||||
|
|
||||||
if (stmt->test == ast::kind::expr_not)
|
if (stmt->test == ast::kind::expr_not)
|
||||||
{
|
{
|
||||||
emit_expr(stmt->test.as_not->rvalue);
|
emit_expr(stmt->test.as_not->rvalue);
|
||||||
emit_opcode(opcode::OP_JumpOnTrue, break_loc_);
|
emit_opcode(opcode::OP_JumpOnTrue, break_loc);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
emit_expr(stmt->test);
|
emit_expr(stmt->test);
|
||||||
emit_opcode(opcode::OP_JumpOnFalse, break_loc_);
|
emit_opcode(opcode::OP_JumpOnFalse, break_loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
blocks_.push_back(block(break_loc, continue_loc));
|
||||||
emit_stmt(stmt->stmt);
|
emit_stmt(stmt->stmt);
|
||||||
emit_opcode(opcode::OP_Jump, begin_loc);
|
blocks_.pop_back();
|
||||||
insert_label(break_loc_);
|
|
||||||
|
emit_opcode(opcode::OP_Jump, continue_loc);
|
||||||
|
insert_label(break_loc);
|
||||||
|
|
||||||
can_break_ = old_break;
|
can_break_ = old_break;
|
||||||
can_continue_ = old_continue;
|
can_continue_ = old_continue;
|
||||||
break_loc_ = old_break_loc;
|
|
||||||
continue_loc_ = old_continue_loc;
|
|
||||||
abort_ = old_abort;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void compiler::emit_stmt_dowhile(const ast::stmt_dowhile::ptr& stmt)
|
void compiler::emit_stmt_dowhile(const ast::stmt_dowhile::ptr& stmt)
|
||||||
{
|
{
|
||||||
auto old_abort = abort_;
|
|
||||||
auto old_break_loc = break_loc_;
|
|
||||||
auto old_continue_loc = continue_loc_;
|
|
||||||
auto old_break = can_break_;
|
auto old_break = can_break_;
|
||||||
auto old_continue = can_continue_;
|
auto old_continue = can_continue_;
|
||||||
|
|
||||||
can_break_ = true;
|
can_break_ = true;
|
||||||
can_continue_ = true;
|
can_continue_ = true;
|
||||||
break_loc_ = create_label();
|
auto break_loc = create_label();
|
||||||
continue_loc_ = create_label();
|
auto continue_loc = create_label();
|
||||||
|
|
||||||
auto begin_loc = insert_label();
|
auto begin_loc = insert_label();
|
||||||
|
|
||||||
|
blocks_.push_back(block(break_loc, continue_loc));
|
||||||
emit_stmt(stmt->stmt);
|
emit_stmt(stmt->stmt);
|
||||||
|
blocks_.pop_back();
|
||||||
|
|
||||||
insert_label(continue_loc_);
|
insert_label(continue_loc);
|
||||||
|
|
||||||
if (stmt->test == ast::kind::expr_not)
|
if (stmt->test == ast::kind::expr_not)
|
||||||
{
|
{
|
||||||
emit_expr(stmt->test.as_not->rvalue);
|
emit_expr(stmt->test.as_not->rvalue);
|
||||||
emit_opcode(opcode::OP_JumpOnTrue, break_loc_);
|
emit_opcode(opcode::OP_JumpOnTrue, break_loc);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
emit_expr(stmt->test);
|
emit_expr(stmt->test);
|
||||||
emit_opcode(opcode::OP_JumpOnFalse, break_loc_);
|
emit_opcode(opcode::OP_JumpOnFalse, break_loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
emit_opcode(opcode::OP_Jump, begin_loc);
|
emit_opcode(opcode::OP_Jump, begin_loc);
|
||||||
insert_label(break_loc_);
|
insert_label(break_loc);
|
||||||
|
|
||||||
can_break_ = old_break;
|
can_break_ = old_break;
|
||||||
can_continue_ = old_continue;
|
can_continue_ = old_continue;
|
||||||
break_loc_ = old_break_loc;
|
|
||||||
continue_loc_ = old_continue_loc;
|
|
||||||
abort_ = old_abort;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void compiler::emit_stmt_for(const ast::stmt_for::ptr& stmt)
|
void compiler::emit_stmt_for(const ast::stmt_for::ptr& stmt)
|
||||||
{
|
{
|
||||||
auto old_abort = abort_;
|
|
||||||
auto old_break_loc = break_loc_;
|
|
||||||
auto old_continue_loc = continue_loc_;
|
|
||||||
auto old_break = can_break_;
|
auto old_break = can_break_;
|
||||||
auto old_continue = can_continue_;
|
auto old_continue = can_continue_;
|
||||||
|
|
||||||
emit_stmt(stmt->init);
|
emit_stmt(stmt->init);
|
||||||
|
|
||||||
break_loc_ = create_label();
|
auto break_loc = create_label();
|
||||||
continue_loc_ = create_label();
|
auto continue_loc = create_label();
|
||||||
|
|
||||||
auto begin_loc = insert_label();
|
auto begin_loc = insert_label();
|
||||||
|
|
||||||
@ -608,34 +609,30 @@ void compiler::emit_stmt_for(const ast::stmt_for::ptr& stmt)
|
|||||||
if (!const_cond)
|
if (!const_cond)
|
||||||
{
|
{
|
||||||
emit_expr(stmt->test);
|
emit_expr(stmt->test);
|
||||||
emit_opcode(opcode::OP_JumpOnFalse, break_loc_);
|
emit_opcode(opcode::OP_JumpOnFalse, break_loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
can_break_ = true;
|
can_break_ = true;
|
||||||
can_continue_ = true;
|
can_continue_ = true;
|
||||||
|
|
||||||
|
blocks_.push_back(block(break_loc, continue_loc));
|
||||||
emit_stmt(stmt->stmt);
|
emit_stmt(stmt->stmt);
|
||||||
|
blocks_.pop_back();
|
||||||
|
|
||||||
can_break_ = false;
|
can_break_ = false;
|
||||||
can_continue_ = false;
|
can_continue_ = false;
|
||||||
|
|
||||||
insert_label(continue_loc_);
|
insert_label(continue_loc);
|
||||||
emit_stmt(stmt->iter);
|
emit_stmt(stmt->iter);
|
||||||
emit_opcode(opcode::OP_Jump, begin_loc);
|
emit_opcode(opcode::OP_Jump, begin_loc);
|
||||||
insert_label(break_loc_);
|
insert_label(break_loc);
|
||||||
|
|
||||||
can_break_ = old_break;
|
can_break_ = old_break;
|
||||||
can_continue_ = old_continue;
|
can_continue_ = old_continue;
|
||||||
break_loc_ = old_break_loc;
|
|
||||||
continue_loc_ = old_continue_loc;
|
|
||||||
abort_ = old_abort;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void compiler::emit_stmt_foreach(const ast::stmt_foreach::ptr& stmt)
|
void compiler::emit_stmt_foreach(const ast::stmt_foreach::ptr& stmt)
|
||||||
{
|
{
|
||||||
auto old_abort = abort_;
|
|
||||||
auto old_break_loc = break_loc_;
|
|
||||||
auto old_continue_loc = continue_loc_;
|
|
||||||
auto old_break = can_break_;
|
auto old_break = can_break_;
|
||||||
auto old_continue = can_continue_;
|
auto old_continue = can_continue_;
|
||||||
|
|
||||||
@ -645,14 +642,14 @@ void compiler::emit_stmt_foreach(const ast::stmt_foreach::ptr& stmt)
|
|||||||
emit_opcode(opcode::OP_FirstArrayKey);
|
emit_opcode(opcode::OP_FirstArrayKey);
|
||||||
emit_expr_variable_ref(stmt->key_expr, true);
|
emit_expr_variable_ref(stmt->key_expr, true);
|
||||||
|
|
||||||
break_loc_ = create_label();
|
auto break_loc = create_label();
|
||||||
continue_loc_ = create_label();
|
auto continue_loc = create_label();
|
||||||
|
|
||||||
auto begin_loc = insert_label();
|
auto begin_loc = insert_label();
|
||||||
|
|
||||||
emit_expr_variable(stmt->key_expr);
|
emit_expr_variable(stmt->key_expr);
|
||||||
emit_opcode(opcode::OP_IsDefined);
|
emit_opcode(opcode::OP_IsDefined);
|
||||||
emit_opcode(opcode::OP_JumpOnFalse, break_loc_);
|
emit_opcode(opcode::OP_JumpOnFalse, break_loc);
|
||||||
|
|
||||||
can_break_ = true;
|
can_break_ = true;
|
||||||
can_continue_ = true;
|
can_continue_ = true;
|
||||||
@ -661,44 +658,44 @@ void compiler::emit_stmt_foreach(const ast::stmt_foreach::ptr& stmt)
|
|||||||
emit_opcode(opcode::OP_EvalLocalVariableCached, variable_access(stmt->array.as_identifier));
|
emit_opcode(opcode::OP_EvalLocalVariableCached, variable_access(stmt->array.as_identifier));
|
||||||
emit_opcode(opcode::OP_EvalArray);
|
emit_opcode(opcode::OP_EvalArray);
|
||||||
emit_expr_variable_ref(stmt->value_expr, true);
|
emit_expr_variable_ref(stmt->value_expr, true);
|
||||||
|
|
||||||
|
blocks_.push_back(block(break_loc, continue_loc));
|
||||||
emit_stmt(stmt->stmt);
|
emit_stmt(stmt->stmt);
|
||||||
|
blocks_.pop_back();
|
||||||
|
|
||||||
can_break_ = false;
|
can_break_ = false;
|
||||||
can_continue_ = false;
|
can_continue_ = false;
|
||||||
|
|
||||||
insert_label(continue_loc_);
|
insert_label(continue_loc);
|
||||||
|
|
||||||
emit_expr_variable(stmt->key_expr);
|
emit_expr_variable(stmt->key_expr);
|
||||||
emit_expr_variable(stmt->array);
|
emit_expr_variable(stmt->array);
|
||||||
emit_opcode(opcode::OP_NextArrayKey);
|
emit_opcode(opcode::OP_NextArrayKey);
|
||||||
emit_expr_variable_ref(stmt->key_expr, true);
|
emit_expr_variable_ref(stmt->key_expr, true);
|
||||||
emit_opcode(opcode::OP_Jump, begin_loc);
|
emit_opcode(opcode::OP_Jump, begin_loc);
|
||||||
insert_label(break_loc_);
|
insert_label(break_loc);
|
||||||
|
|
||||||
can_break_ = old_break;
|
can_break_ = old_break;
|
||||||
can_continue_ = old_continue;
|
can_continue_ = old_continue;
|
||||||
break_loc_ = old_break_loc;
|
|
||||||
continue_loc_ = old_continue_loc;
|
|
||||||
abort_ = old_abort;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void compiler::emit_stmt_switch(const ast::stmt_switch::ptr& stmt)
|
void compiler::emit_stmt_switch(const ast::stmt_switch::ptr& stmt)
|
||||||
{
|
{
|
||||||
auto old_abort = abort_;
|
|
||||||
auto old_break_loc = break_loc_;
|
|
||||||
auto old_break = can_break_;
|
auto old_break = can_break_;
|
||||||
|
|
||||||
can_break_ = false;
|
can_break_ = false;
|
||||||
|
|
||||||
auto jmptable_loc = create_label();
|
auto jmptable_loc = create_label();
|
||||||
|
|
||||||
break_loc_ = create_label();
|
auto break_loc = create_label();
|
||||||
|
|
||||||
emit_expr(stmt->test);
|
emit_expr(stmt->test);
|
||||||
emit_opcode(opcode::OP_Switch, jmptable_loc);
|
emit_opcode(opcode::OP_Switch, jmptable_loc);
|
||||||
|
|
||||||
can_break_ = true;
|
can_break_ = true;
|
||||||
|
|
||||||
|
blocks_.push_back(block(break_loc, blocks_.back().loc_continue));
|
||||||
|
|
||||||
std::vector<std::string> data;
|
std::vector<std::string> data;
|
||||||
data.push_back(utils::string::va("%d", stmt->stmt->list.size()));
|
data.push_back(utils::string::va("%d", stmt->stmt->list.size()));
|
||||||
|
|
||||||
@ -735,7 +732,10 @@ void compiler::emit_stmt_switch(const ast::stmt_switch::ptr& stmt)
|
|||||||
throw comp_error(stmt->loc(), "case type must be int or string");
|
throw comp_error(stmt->loc(), "case type must be int or string");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto& paren = blocks_.back();
|
||||||
|
blocks_.push_back(block(paren.loc_break, paren.loc_continue));
|
||||||
emit_stmt_list(case_->stmt);
|
emit_stmt_list(case_->stmt);
|
||||||
|
blocks_.pop_back();
|
||||||
}
|
}
|
||||||
else if (entry == ast::kind::stmt_default)
|
else if (entry == ast::kind::stmt_default)
|
||||||
{
|
{
|
||||||
@ -743,7 +743,11 @@ void compiler::emit_stmt_switch(const ast::stmt_switch::ptr& stmt)
|
|||||||
data.push_back("default");
|
data.push_back("default");
|
||||||
data.push_back(loc);
|
data.push_back(loc);
|
||||||
has_default = true;
|
has_default = true;
|
||||||
|
|
||||||
|
auto& paren = blocks_.back();
|
||||||
|
blocks_.push_back(block(paren.loc_break, paren.loc_continue));
|
||||||
emit_stmt_list(entry.as_default->stmt);
|
emit_stmt_list(entry.as_default->stmt);
|
||||||
|
blocks_.pop_back();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -751,13 +755,13 @@ void compiler::emit_stmt_switch(const ast::stmt_switch::ptr& stmt)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
blocks_.pop_back();
|
||||||
|
|
||||||
insert_label(jmptable_loc);
|
insert_label(jmptable_loc);
|
||||||
emit_opcode(opcode::OP_EndSwitch, data);
|
emit_opcode(opcode::OP_EndSwitch, data);
|
||||||
insert_label(break_loc_);
|
insert_label(break_loc);
|
||||||
|
|
||||||
can_break_ = old_break;
|
can_break_ = old_break;
|
||||||
break_loc_ = old_break_loc;
|
|
||||||
abort_ = old_abort;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void compiler::emit_stmt_case(const ast::stmt_case::ptr& stmt)
|
void compiler::emit_stmt_case(const ast::stmt_case::ptr& stmt)
|
||||||
@ -772,26 +776,26 @@ void compiler::emit_stmt_default(const ast::stmt_default::ptr& stmt)
|
|||||||
|
|
||||||
void compiler::emit_stmt_break(const ast::stmt_break::ptr& stmt)
|
void compiler::emit_stmt_break(const ast::stmt_break::ptr& stmt)
|
||||||
{
|
{
|
||||||
if (!can_break_ || abort_ != abort_t::abort_none || break_loc_ == "")
|
if (!can_break_ || blocks_.back().abort != abort_t::abort_none || blocks_.back().loc_break == "")
|
||||||
throw comp_error(stmt->loc(), "illegal break statement");
|
throw comp_error(stmt->loc(), "illegal break statement");
|
||||||
|
|
||||||
abort_ = abort_t::abort_break;
|
blocks_.back().abort = abort_t::abort_break;
|
||||||
emit_opcode(opcode::OP_Jump, break_loc_);
|
emit_opcode(opcode::OP_Jump, blocks_.back().loc_break);
|
||||||
}
|
}
|
||||||
|
|
||||||
void compiler::emit_stmt_continue(const ast::stmt_continue::ptr& stmt)
|
void compiler::emit_stmt_continue(const ast::stmt_continue::ptr& stmt)
|
||||||
{
|
{
|
||||||
if (!can_continue_ || abort_ != abort_t::abort_none || continue_loc_ == "")
|
if (!can_continue_ || blocks_.back().abort != abort_t::abort_none || blocks_.back().loc_continue == "")
|
||||||
throw comp_error(stmt->loc(), "illegal continue statement");
|
throw comp_error(stmt->loc(), "illegal continue statement");
|
||||||
|
|
||||||
abort_ = abort_t::abort_continue;
|
blocks_.back().abort = abort_t::abort_continue;
|
||||||
emit_opcode(opcode::OP_Jump, continue_loc_);
|
emit_opcode(opcode::OP_Jump, blocks_.back().loc_continue);
|
||||||
}
|
}
|
||||||
|
|
||||||
void compiler::emit_stmt_return(const ast::stmt_return::ptr& stmt)
|
void compiler::emit_stmt_return(const ast::stmt_return::ptr& stmt)
|
||||||
{
|
{
|
||||||
if (abort_ == abort_t::abort_none)
|
if (blocks_.back().abort == abort_t::abort_none)
|
||||||
abort_ = abort_t::abort_return;
|
blocks_.back().abort = abort_t::abort_return;
|
||||||
|
|
||||||
if (stmt->expr != ast::kind::null)
|
if (stmt->expr != ast::kind::null)
|
||||||
{
|
{
|
||||||
@ -1222,6 +1226,7 @@ void compiler::emit_expr_call(const ast::expr_call::ptr& expr)
|
|||||||
|
|
||||||
void compiler::emit_expr_call_pointer(const ast::expr_pointer::ptr& expr)
|
void compiler::emit_expr_call_pointer(const ast::expr_pointer::ptr& expr)
|
||||||
{
|
{
|
||||||
|
emit_opcode(opcode::OP_PreScriptCall);
|
||||||
emit_expr_arguments(expr->args);
|
emit_expr_arguments(expr->args);
|
||||||
emit_expr(expr->func);
|
emit_expr(expr->func);
|
||||||
|
|
||||||
@ -1296,6 +1301,7 @@ void compiler::emit_expr_method(const ast::expr_method::ptr& expr)
|
|||||||
|
|
||||||
void compiler::emit_expr_method_pointer(const ast::expr_pointer::ptr& expr, const ast::expr& obj)
|
void compiler::emit_expr_method_pointer(const ast::expr_pointer::ptr& expr, const ast::expr& obj)
|
||||||
{
|
{
|
||||||
|
emit_opcode(opcode::OP_PreScriptCall);
|
||||||
emit_expr_arguments(expr->args);
|
emit_expr_arguments(expr->args);
|
||||||
emit_expr(obj);
|
emit_expr(obj);
|
||||||
emit_expr(expr->func);
|
emit_expr(expr->func);
|
||||||
@ -1571,14 +1577,11 @@ void compiler::emit_expr_array_ref(const ast::expr_array::ptr& expr, bool set)
|
|||||||
break;
|
break;
|
||||||
case ast::kind::expr_array:
|
case ast::kind::expr_array:
|
||||||
case ast::kind::expr_field:
|
case ast::kind::expr_field:
|
||||||
|
case ast::kind::expr_identifier:
|
||||||
emit_expr_variable_ref(expr->obj, false);
|
emit_expr_variable_ref(expr->obj, false);
|
||||||
emit_opcode(opcode::OP_EvalArrayRef);
|
emit_opcode(opcode::OP_EvalArrayRef);
|
||||||
if (set) emit_opcode(opcode::OP_SetVariableField);
|
if (set) emit_opcode(opcode::OP_SetVariableField);
|
||||||
break;
|
break;
|
||||||
case ast::kind::expr_identifier:
|
|
||||||
emit_opcode(opcode::OP_EvalLocalArrayRefCached, variable_access(expr->obj.as_identifier));
|
|
||||||
if (set) emit_opcode(opcode::OP_SetVariableField);
|
|
||||||
break;
|
|
||||||
case ast::kind::expr_call:
|
case ast::kind::expr_call:
|
||||||
case ast::kind::expr_method:
|
case ast::kind::expr_method:
|
||||||
default:
|
default:
|
||||||
|
@ -12,7 +12,6 @@ enum class opcode : std::uint8_t;
|
|||||||
|
|
||||||
class compiler : public arc::compiler
|
class compiler : public arc::compiler
|
||||||
{
|
{
|
||||||
build mode_;
|
|
||||||
std::string filename_;
|
std::string filename_;
|
||||||
assembly::ptr assembly_;
|
assembly::ptr assembly_;
|
||||||
function::ptr function_;
|
function::ptr function_;
|
||||||
@ -24,23 +23,20 @@ class compiler : public arc::compiler
|
|||||||
std::vector<include_t> includes_;
|
std::vector<include_t> includes_;
|
||||||
std::vector<animtree_t> animtrees_;
|
std::vector<animtree_t> animtrees_;
|
||||||
std::unordered_map<std::string, ast::expr> constants_;
|
std::unordered_map<std::string, ast::expr> constants_;
|
||||||
std::function<std::vector<std::uint8_t>(const std::string&)> read_callback_;
|
std::vector<block> blocks_;
|
||||||
abort_t abort_;
|
|
||||||
std::string break_loc_;
|
|
||||||
std::string continue_loc_;
|
|
||||||
bool can_break_;
|
bool can_break_;
|
||||||
bool can_continue_;
|
bool can_continue_;
|
||||||
bool developer_thread_;
|
bool developer_thread_;
|
||||||
|
build mode_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
compiler(build mode) : mode_(mode) {}
|
|
||||||
auto output() -> assembly::ptr;
|
auto output() -> assembly::ptr;
|
||||||
auto output_data() -> std::vector<std::uint8_t>;
|
auto output_data() -> std::vector<std::uint8_t>;
|
||||||
void compile(const std::string& file, std::vector<std::uint8_t>& data);
|
void compile(const std::string& file, std::vector<std::uint8_t>& data);
|
||||||
void read_callback(std::function<std::vector<std::uint8_t>(const std::string&)> func);
|
void mode(build mode);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
auto parse_buffer(const std::string& file, std::vector<std::uint8_t>& data) -> ast::program::ptr;
|
auto parse_buffer(const std::string& file, char* data, size_t size) -> ast::program::ptr;
|
||||||
auto parse_file(const std::string& file) -> ast::program::ptr;
|
auto parse_file(const std::string& file) -> ast::program::ptr;
|
||||||
void compile_program(const ast::program::ptr& program);
|
void compile_program(const ast::program::ptr& program);
|
||||||
void emit_include(const ast::include::ptr& include);
|
void emit_include(const ast::include::ptr& include);
|
||||||
@ -163,7 +159,6 @@ private:
|
|||||||
|
|
||||||
auto map_known_includes(const std::string& include) -> bool;
|
auto map_known_includes(const std::string& include) -> bool;
|
||||||
|
|
||||||
|
|
||||||
utils::byte_buffer::ptr output_;
|
utils::byte_buffer::ptr output_;
|
||||||
void print_function(const function::ptr& func);
|
void print_function(const function::ptr& func);
|
||||||
void print_instruction(const instruction::ptr& inst);
|
void print_instruction(const instruction::ptr& inst);
|
||||||
|
23
src/t6/xsk/context.cpp
Normal file
23
src/t6/xsk/context.cpp
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
// Copyright 2022 xensik. All rights reserved.
|
||||||
|
//
|
||||||
|
// Use of this source code is governed by a GNU GPLv3 license
|
||||||
|
// that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
#include "stdafx.hpp"
|
||||||
|
#include "t6.hpp"
|
||||||
|
|
||||||
|
namespace xsk::arc::t6
|
||||||
|
{
|
||||||
|
|
||||||
|
void context::init(build mode, read_cb_type callback)
|
||||||
|
{
|
||||||
|
compiler_.mode(mode);
|
||||||
|
resolver::init(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
void context::cleanup()
|
||||||
|
{
|
||||||
|
resolver::cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace xsk::arc::t6
|
28
src/t6/xsk/context.hpp
Normal file
28
src/t6/xsk/context.hpp
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
// Copyright 2022 xensik. All rights reserved.
|
||||||
|
//
|
||||||
|
// Use of this source code is governed by a GNU GPLv3 license
|
||||||
|
// that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace xsk::arc::t6
|
||||||
|
{
|
||||||
|
|
||||||
|
class context : public arc::context
|
||||||
|
{
|
||||||
|
t6::assembler assembler_;
|
||||||
|
t6::disassembler disassembler_;
|
||||||
|
t6::compiler compiler_;
|
||||||
|
t6::decompiler decompiler_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
void init(build mode, read_cb_type callback);
|
||||||
|
void cleanup();
|
||||||
|
|
||||||
|
auto assembler() -> arc::assembler& { return assembler_; }
|
||||||
|
auto disassembler() -> arc::disassembler& { return disassembler_; }
|
||||||
|
auto compiler() -> arc::compiler& { return compiler_; }
|
||||||
|
auto decompiler() -> arc::decompiler& { return decompiler_; }
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace xsk::arc::t6
|
@ -248,6 +248,8 @@ void disassembler::disassemble_function(const function::ptr& func)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void disassembler::disassemble_instruction(const instruction::ptr& inst)
|
void disassembler::disassemble_instruction(const instruction::ptr& inst)
|
||||||
{
|
{
|
||||||
switch (opcode(inst->opcode))
|
switch (opcode(inst->opcode))
|
||||||
@ -264,9 +266,7 @@ void disassembler::disassemble_instruction(const instruction::ptr& inst)
|
|||||||
case opcode::OP_GetAnim:
|
case opcode::OP_GetAnim:
|
||||||
case opcode::OP_GetGameRef:
|
case opcode::OP_GetGameRef:
|
||||||
case opcode::OP_CreateLocalVariable:
|
case opcode::OP_CreateLocalVariable:
|
||||||
case opcode::OP_RemoveLocalVariables:
|
|
||||||
case opcode::OP_EvalArray:
|
case opcode::OP_EvalArray:
|
||||||
case opcode::OP_EvalLocalArrayRefCached:
|
|
||||||
case opcode::OP_EvalArrayRef:
|
case opcode::OP_EvalArrayRef:
|
||||||
case opcode::OP_ClearArray:
|
case opcode::OP_ClearArray:
|
||||||
case opcode::OP_EmptyArray:
|
case opcode::OP_EmptyArray:
|
||||||
@ -351,17 +351,14 @@ void disassembler::disassemble_instruction(const instruction::ptr& inst)
|
|||||||
inst->data.push_back(utils::string::va("%i", script_->read<std::int32_t>()));
|
inst->data.push_back(utils::string::va("%i", script_->read<std::int32_t>()));
|
||||||
break;
|
break;
|
||||||
case opcode::OP_GetFloat:
|
case opcode::OP_GetFloat:
|
||||||
{
|
|
||||||
inst->size += script_->align(4);
|
inst->size += script_->align(4);
|
||||||
auto val = script_->read<float>();
|
inst->data.push_back(utils::string::float_string(script_->read<float>()));
|
||||||
inst->data.push_back(utils::string::va("%g%s", val, val == int(val) ? ".0" : ""));
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case opcode::OP_GetVector:
|
case opcode::OP_GetVector:
|
||||||
inst->size += script_->align(4);
|
inst->size += script_->align(4);
|
||||||
inst->data.push_back(utils::string::va("%g", script_->read<float>()));
|
inst->data.push_back(utils::string::float_string(script_->read<float>()));
|
||||||
inst->data.push_back(utils::string::va("%g", script_->read<float>()));
|
inst->data.push_back(utils::string::float_string(script_->read<float>()));
|
||||||
inst->data.push_back(utils::string::va("%g", script_->read<float>()));
|
inst->data.push_back(utils::string::float_string(script_->read<float>()));
|
||||||
break;
|
break;
|
||||||
case opcode::OP_GetString:
|
case opcode::OP_GetString:
|
||||||
case opcode::OP_GetIString:
|
case opcode::OP_GetIString:
|
||||||
@ -383,7 +380,9 @@ void disassembler::disassemble_instruction(const instruction::ptr& inst)
|
|||||||
case opcode::OP_SafeCreateLocalVariables:
|
case opcode::OP_SafeCreateLocalVariables:
|
||||||
disassemble_localvars(inst);
|
disassemble_localvars(inst);
|
||||||
break;
|
break;
|
||||||
|
case opcode::OP_RemoveLocalVariables:
|
||||||
case opcode::OP_EvalLocalVariableCached:
|
case opcode::OP_EvalLocalVariableCached:
|
||||||
|
case opcode::OP_EvalLocalArrayRefCached:
|
||||||
case opcode::OP_SafeSetWaittillVariableFieldCached:
|
case opcode::OP_SafeSetWaittillVariableFieldCached:
|
||||||
case opcode::OP_EvalLocalVariableRefCached:
|
case opcode::OP_EvalLocalVariableRefCached:
|
||||||
inst->data.push_back(utils::string::va("%i", script_->read<std::uint8_t>()));
|
inst->data.push_back(utils::string::va("%i", script_->read<std::uint8_t>()));
|
||||||
|
@ -12,6 +12,18 @@ namespace xsk::arc::t6
|
|||||||
std::unordered_map<std::uint8_t, std::string_view> opcode_map;
|
std::unordered_map<std::uint8_t, std::string_view> opcode_map;
|
||||||
std::unordered_map<std::string_view, std::uint8_t> opcode_map_rev;
|
std::unordered_map<std::string_view, std::uint8_t> opcode_map_rev;
|
||||||
std::unordered_map<std::uint32_t, std::string_view> dvar_map;
|
std::unordered_map<std::uint32_t, std::string_view> dvar_map;
|
||||||
|
std::unordered_map<std::string, std::vector<std::uint8_t>> files;
|
||||||
|
std::function<std::vector<std::uint8_t>(const std::string&)> read_callback = nullptr;
|
||||||
|
|
||||||
|
void resolver::init(read_cb_type callback)
|
||||||
|
{
|
||||||
|
read_callback = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
void resolver::cleanup()
|
||||||
|
{
|
||||||
|
files.clear();
|
||||||
|
}
|
||||||
|
|
||||||
auto resolver::opcode_id(const std::string& name) -> std::uint8_t
|
auto resolver::opcode_id(const std::string& name) -> std::uint8_t
|
||||||
{
|
{
|
||||||
@ -22,7 +34,7 @@ auto resolver::opcode_id(const std::string& name) -> std::uint8_t
|
|||||||
return itr->second;
|
return itr->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw gsc::error(utils::string::va("Couldn't resolve opcode id for name '%s'!", name.data()));
|
throw error(utils::string::va("Couldn't resolve opcode id for name '%s'!", name.data()));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto resolver::opcode_name(std::uint8_t id) -> std::string
|
auto resolver::opcode_name(std::uint8_t id) -> std::string
|
||||||
@ -34,7 +46,7 @@ auto resolver::opcode_name(std::uint8_t id) -> std::string
|
|||||||
return std::string(itr->second);
|
return std::string(itr->second);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw gsc::error(utils::string::va("Couldn't resolve opcode name for id '0x%hhX'!", id));
|
throw error(utils::string::va("Couldn't resolve opcode name for id '0x%hhX'!", id));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto resolver::dvar_name(std::uint32_t id) -> std::string
|
auto resolver::dvar_name(std::uint32_t id) -> std::string
|
||||||
@ -67,9 +79,6 @@ auto resolver::make_token(std::string_view str) -> std::string
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::function<std::vector<std::uint8_t>(const std::string&)> read_callback = nullptr;
|
|
||||||
std::unordered_map<std::string, std::vector<std::uint8_t>> files;
|
|
||||||
|
|
||||||
auto resolver::file_data(const std::string& name) -> std::tuple<const std::string*, char*, size_t>
|
auto resolver::file_data(const std::string& name) -> std::tuple<const std::string*, char*, size_t>
|
||||||
{
|
{
|
||||||
const auto& itr = files.find(name);
|
const auto& itr = files.find(name);
|
||||||
@ -91,11 +100,6 @@ auto resolver::file_data(const std::string& name) -> std::tuple<const std::strin
|
|||||||
throw error("couldn't open gsc file '" + name + "'");
|
throw error("couldn't open gsc file '" + name + "'");
|
||||||
}
|
}
|
||||||
|
|
||||||
void resolver::set_reader(std::function<std::vector<std::uint8_t>(const std::string&)> callback)
|
|
||||||
{
|
|
||||||
read_callback = callback;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::set<std::string> paths
|
std::set<std::string> paths
|
||||||
{
|
{
|
||||||
"aitype",
|
"aitype",
|
||||||
|
@ -11,6 +11,8 @@ namespace xsk::arc::t6
|
|||||||
class resolver
|
class resolver
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
static void init(read_cb_type callback);
|
||||||
|
static void cleanup();
|
||||||
static auto opcode_id(const std::string& name) -> std::uint8_t;
|
static auto opcode_id(const std::string& name) -> std::uint8_t;
|
||||||
static auto opcode_name(std::uint8_t id) -> std::string;
|
static auto opcode_name(std::uint8_t id) -> std::string;
|
||||||
static auto dvar_name(std::uint32_t id) -> std::string;
|
static auto dvar_name(std::uint32_t id) -> std::string;
|
||||||
|
@ -25,9 +25,7 @@ auto opcode_size(std::uint8_t id) -> std::uint32_t
|
|||||||
case opcode::OP_GetAnim:
|
case opcode::OP_GetAnim:
|
||||||
case opcode::OP_GetGameRef:
|
case opcode::OP_GetGameRef:
|
||||||
case opcode::OP_CreateLocalVariable:
|
case opcode::OP_CreateLocalVariable:
|
||||||
case opcode::OP_RemoveLocalVariables:
|
|
||||||
case opcode::OP_EvalArray:
|
case opcode::OP_EvalArray:
|
||||||
case opcode::OP_EvalLocalArrayRefCached:
|
|
||||||
case opcode::OP_EvalArrayRef:
|
case opcode::OP_EvalArrayRef:
|
||||||
case opcode::OP_ClearArray:
|
case opcode::OP_ClearArray:
|
||||||
case opcode::OP_EmptyArray:
|
case opcode::OP_EmptyArray:
|
||||||
@ -102,7 +100,9 @@ auto opcode_size(std::uint8_t id) -> std::uint32_t
|
|||||||
case opcode::OP_GetByte:
|
case opcode::OP_GetByte:
|
||||||
case opcode::OP_GetNegByte:
|
case opcode::OP_GetNegByte:
|
||||||
case opcode::OP_SafeCreateLocalVariables:
|
case opcode::OP_SafeCreateLocalVariables:
|
||||||
|
case opcode::OP_RemoveLocalVariables:
|
||||||
case opcode::OP_EvalLocalVariableCached:
|
case opcode::OP_EvalLocalVariableCached:
|
||||||
|
case opcode::OP_EvalLocalArrayRefCached:
|
||||||
case opcode::OP_SafeSetWaittillVariableFieldCached:
|
case opcode::OP_SafeSetWaittillVariableFieldCached:
|
||||||
case opcode::OP_EvalLocalVariableRefCached:
|
case opcode::OP_EvalLocalVariableRefCached:
|
||||||
case opcode::OP_ScriptFunctionCallPointer:
|
case opcode::OP_ScriptFunctionCallPointer:
|
||||||
|
@ -9,9 +9,10 @@
|
|||||||
|
|
||||||
#include "assembler.hpp"
|
#include "assembler.hpp"
|
||||||
#include "disassembler.hpp"
|
#include "disassembler.hpp"
|
||||||
#include "decompiler.hpp"
|
|
||||||
#include "compiler.hpp"
|
#include "compiler.hpp"
|
||||||
|
#include "decompiler.hpp"
|
||||||
#include "resolver.hpp"
|
#include "resolver.hpp"
|
||||||
|
#include "context.hpp"
|
||||||
|
|
||||||
namespace xsk::arc::t6
|
namespace xsk::arc::t6
|
||||||
{
|
{
|
||||||
|
@ -452,25 +452,22 @@ void init()
|
|||||||
namespace arc
|
namespace arc
|
||||||
{
|
{
|
||||||
|
|
||||||
std::map<game, assembler::ptr> assemblers;
|
std::map<game, context::ptr> contexts;
|
||||||
std::map<game, disassembler::ptr> disassemblers;
|
|
||||||
std::map<game, compiler::ptr> compilers;
|
|
||||||
std::map<game, decompiler::ptr> decompilers;
|
|
||||||
std::map<mode, std::function<void(game game, const std::filesystem::path& file)>> funcs;
|
std::map<mode, std::function<void(game game, const std::filesystem::path& file)>> funcs;
|
||||||
|
|
||||||
void assemble_file(game game, const std::filesystem::path& file)
|
void assemble_file(game game, const std::filesystem::path& file)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
const auto& assembler = assemblers[game];
|
auto& assembler = contexts[game]->assembler();
|
||||||
|
|
||||||
auto data = utils::file::read(file.string());
|
auto data = utils::file::read(file.string());
|
||||||
auto path = t6::resolver::fs_to_game_path(file);
|
auto path = t6::resolver::fs_to_game_path(file);
|
||||||
auto next = path.extension() == ".gscasm" ? path.replace_extension(".gsc") : path.replace_extension(".csc");
|
auto next = path.extension() == ".gscasm" ? path.replace_extension(".gsc") : path.replace_extension(".csc");
|
||||||
|
|
||||||
assembler->assemble(next.string(), data);
|
assembler.assemble(next.string(), data);
|
||||||
|
|
||||||
utils::file::save((std::filesystem::path("assembled/t6") / next).string(), assembler->output());
|
utils::file::save((std::filesystem::path("assembled/t6") / next).string(), assembler.output());
|
||||||
std::cout << "assembled " << path.replace_extension() << "\n";
|
std::cout << "assembled " << path.replace_extension() << "\n";
|
||||||
}
|
}
|
||||||
catch (const std::exception& e)
|
catch (const std::exception& e)
|
||||||
@ -483,15 +480,15 @@ void disassemble_file(game game, const std::filesystem::path& file)
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
const auto& disassembler = disassemblers[game];
|
auto& disassembler = contexts[game]->disassembler();
|
||||||
|
|
||||||
auto data = utils::file::read(file.string());
|
auto data = utils::file::read(file.string());
|
||||||
auto path = t6::resolver::fs_to_game_path(file);
|
auto path = t6::resolver::fs_to_game_path(file);
|
||||||
auto next = path.extension() == ".gsc" ? path.replace_extension(".gscasm") : path.replace_extension(".cscasm");
|
auto next = path.extension() == ".gsc" ? path.replace_extension(".gscasm") : path.replace_extension(".cscasm");
|
||||||
|
|
||||||
disassembler->disassemble(file.string(), data);
|
disassembler.disassemble(file.string(), data);
|
||||||
|
|
||||||
utils::file::save((std::filesystem::path("disassembled/t6") / next).string(), disassembler->output_data());
|
utils::file::save((std::filesystem::path("disassembled/t6") / next).string(), disassembler.output_data());
|
||||||
std::cout << "disassembled " << path.replace_extension() << "\n";
|
std::cout << "disassembled " << path.replace_extension() << "\n";
|
||||||
}
|
}
|
||||||
catch (const std::exception& e)
|
catch (const std::exception& e)
|
||||||
@ -504,20 +501,19 @@ void compile_file(game game, const std::filesystem::path& file)
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
const auto& assembler = assemblers[game];
|
auto& assembler = contexts[game]->assembler();
|
||||||
const auto& compiler = compilers[game];
|
auto& compiler = contexts[game]->compiler();
|
||||||
|
|
||||||
auto data = utils::file::read(file.string());
|
auto data = utils::file::read(file.string());
|
||||||
auto path = t6::resolver::fs_to_game_path(file);
|
auto path = t6::resolver::fs_to_game_path(file);
|
||||||
|
|
||||||
compiler->read_callback(utils::file::read);
|
compiler.compile(file.string(), data);
|
||||||
compiler->compile(file.string(), data);
|
|
||||||
|
|
||||||
auto assembly = compiler->output();
|
auto assembly = compiler.output();
|
||||||
|
|
||||||
assembler->assemble(path.string(), assembly);
|
assembler.assemble(path.string(), assembly);
|
||||||
|
|
||||||
utils::file::save((std::filesystem::path("compiled/t6") / path).string(), assembler->output());
|
utils::file::save((std::filesystem::path("compiled/t6") / path).string(), assembler.output());
|
||||||
std::cout << "compiled " << path.replace_extension() << "\n";
|
std::cout << "compiled " << path.replace_extension() << "\n";
|
||||||
}
|
}
|
||||||
catch (const std::exception& e)
|
catch (const std::exception& e)
|
||||||
@ -530,19 +526,19 @@ void decompile_file(game game, const std::filesystem::path& file)
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
const auto& disassembler = disassemblers[game];
|
auto& disassembler = contexts[game]->disassembler();
|
||||||
const auto& decompiler = decompilers[game];
|
auto& decompiler = contexts[game]->decompiler();
|
||||||
|
|
||||||
auto data = utils::file::read(file.string());
|
auto data = utils::file::read(file.string());
|
||||||
auto path = t6::resolver::fs_to_game_path(file);
|
auto path = t6::resolver::fs_to_game_path(file);
|
||||||
|
|
||||||
disassembler->disassemble(file.string(), data);
|
disassembler.disassemble(file.string(), data);
|
||||||
|
|
||||||
auto output = disassembler->output();
|
auto output = disassembler.output();
|
||||||
|
|
||||||
decompiler->decompile(file.string(), output);
|
decompiler.decompile(file.string(), output);
|
||||||
|
|
||||||
utils::file::save((std::filesystem::path("decompiled/t6") / path).string(), decompiler->output());
|
utils::file::save((std::filesystem::path("decompiled/t6") / path).string(), decompiler.output());
|
||||||
std::cout << "decompiled " << path.replace_extension() << "\n";
|
std::cout << "decompiled " << path.replace_extension() << "\n";
|
||||||
}
|
}
|
||||||
catch (const std::exception& e)
|
catch (const std::exception& e)
|
||||||
@ -553,10 +549,9 @@ void decompile_file(game game, const std::filesystem::path& file)
|
|||||||
|
|
||||||
void init()
|
void init()
|
||||||
{
|
{
|
||||||
assemblers[game::T6] = std::make_unique<t6::assembler>();
|
contexts[game::T6] = std::make_unique<t6::context>();
|
||||||
disassemblers[game::T6] = std::make_unique<t6::disassembler>();
|
contexts[game::T6]->init(build::prod, utils::file::read);
|
||||||
compilers[game::T6] = std::make_unique<t6::compiler>(build::prod);
|
|
||||||
decompilers[game::T6] = std::make_unique<t6::decompiler>();
|
|
||||||
funcs[mode::ASM] = assemble_file;
|
funcs[mode::ASM] = assemble_file;
|
||||||
funcs[mode::DISASM] = disassemble_file;
|
funcs[mode::DISASM] = disassemble_file;
|
||||||
funcs[mode::COMP] = compile_file;
|
funcs[mode::COMP] = compile_file;
|
||||||
|
@ -19,6 +19,8 @@ struct block
|
|||||||
bool is_dev;
|
bool is_dev;
|
||||||
|
|
||||||
block() : is_dev(false), abort(abort_t::abort_none) {}
|
block() : is_dev(false), abort(abort_t::abort_none) {}
|
||||||
|
block(const std::string& lbreak, const std::string& lcont)
|
||||||
|
: is_dev(false), abort(abort_t::abort_none), loc_break(lbreak), loc_continue(lcont) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace xsk::arc
|
} // namespace xsk::arc
|
||||||
|
@ -17,7 +17,6 @@ public:
|
|||||||
virtual auto output() -> assembly::ptr = 0;
|
virtual auto output() -> assembly::ptr = 0;
|
||||||
virtual auto output_data() -> std::vector<std::uint8_t> = 0;
|
virtual auto output_data() -> std::vector<std::uint8_t> = 0;
|
||||||
virtual void compile(const std::string& file, std::vector<std::uint8_t>& data) = 0;
|
virtual void compile(const std::string& file, std::vector<std::uint8_t>& data) = 0;
|
||||||
virtual void read_callback(std::function<std::vector<std::uint8_t>(const std::string&)> func) = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace xsk::arc
|
} // namespace xsk::arc
|
||||||
|
26
src/utils/xsk/arc/interfaces/context.hpp
Normal file
26
src/utils/xsk/arc/interfaces/context.hpp
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
// Copyright 2022 xensik. All rights reserved.
|
||||||
|
//
|
||||||
|
// Use of this source code is governed by a GNU GPLv3 license
|
||||||
|
// that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace xsk::arc
|
||||||
|
{
|
||||||
|
|
||||||
|
class context
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using ptr = std::unique_ptr<context>;
|
||||||
|
|
||||||
|
virtual ~context() = default;
|
||||||
|
virtual void init(build mode, read_cb_type callback) = 0;
|
||||||
|
virtual void cleanup() = 0;
|
||||||
|
|
||||||
|
virtual auto assembler() -> assembler& = 0;
|
||||||
|
virtual auto disassembler() -> disassembler& = 0;
|
||||||
|
virtual auto compiler() -> compiler& = 0;
|
||||||
|
virtual auto decompiler() -> decompiler& = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace xsk::arc
|
@ -8,10 +8,12 @@
|
|||||||
namespace xsk::arc
|
namespace xsk::arc
|
||||||
{
|
{
|
||||||
|
|
||||||
|
using read_cb_type = std::function<std::vector<std::uint8_t>(const std::string&)>;
|
||||||
|
|
||||||
enum class build
|
enum class build
|
||||||
{
|
{
|
||||||
dev,
|
|
||||||
prod,
|
prod,
|
||||||
|
dev,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class abort_t
|
enum class abort_t
|
||||||
|
@ -37,3 +37,4 @@
|
|||||||
#include "arc/interfaces/disassembler.hpp"
|
#include "arc/interfaces/disassembler.hpp"
|
||||||
#include "arc/interfaces/compiler.hpp"
|
#include "arc/interfaces/compiler.hpp"
|
||||||
#include "arc/interfaces/decompiler.hpp"
|
#include "arc/interfaces/decompiler.hpp"
|
||||||
|
#include "arc/interfaces/context.hpp"
|
||||||
|
@ -227,4 +227,86 @@ auto string::parse_code(std::string& line) -> std::vector<std::string>
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto string::float_string(float value) -> std::string
|
||||||
|
{
|
||||||
|
enum flags_t : std::uint8_t { none = 0, negative = 1, integer = 2, has_exp = 4, exp_neg = 8 };
|
||||||
|
|
||||||
|
auto str = utils::string::va("%g", value);
|
||||||
|
|
||||||
|
auto flags = integer | (str[0] == '-' ? negative : none);
|
||||||
|
|
||||||
|
for (auto i = 1; i < str.size(); i++)
|
||||||
|
{
|
||||||
|
if (str[i] == '-') flags |= exp_neg;
|
||||||
|
else if (str[i] == 'e') flags |= has_exp;
|
||||||
|
else if ( str[i] == '.') flags &= ~integer;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(flags & has_exp))
|
||||||
|
return str += (flags & integer) ? ".0" : "";
|
||||||
|
|
||||||
|
std::string p_int;
|
||||||
|
std::string p_dec;
|
||||||
|
std::string p_exp;
|
||||||
|
|
||||||
|
if(flags & integer)
|
||||||
|
{
|
||||||
|
auto i = (flags & negative) ? 1 : 0;
|
||||||
|
|
||||||
|
while (str[i] != 'e')
|
||||||
|
p_int.push_back(str[i++]);
|
||||||
|
|
||||||
|
i += 2;
|
||||||
|
|
||||||
|
while (i < str.size())
|
||||||
|
p_exp.push_back(str[i++]);
|
||||||
|
|
||||||
|
auto offset = std::stoi(p_exp);
|
||||||
|
|
||||||
|
if ((flags & exp_neg))
|
||||||
|
offset -= p_int.size();
|
||||||
|
|
||||||
|
while (offset--)
|
||||||
|
{
|
||||||
|
if((flags & exp_neg))
|
||||||
|
p_int.insert(p_int.begin(), '0');
|
||||||
|
else
|
||||||
|
p_int.push_back('0');
|
||||||
|
}
|
||||||
|
|
||||||
|
return ((flags & negative) ? "-" : "") + ((flags & exp_neg) ? "0." + p_int : p_int + ".0");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto i = (flags & negative) ? 1 : 0;
|
||||||
|
|
||||||
|
while (str[i] != '.')
|
||||||
|
p_int.push_back(str[i++]);
|
||||||
|
|
||||||
|
i++;
|
||||||
|
|
||||||
|
while (str[i] != 'e')
|
||||||
|
p_dec.push_back(str[i++]);
|
||||||
|
|
||||||
|
i += 2;
|
||||||
|
|
||||||
|
while (i < str.size())
|
||||||
|
p_exp.push_back(str[i++]);
|
||||||
|
|
||||||
|
auto offset = std::stoi(p_exp);
|
||||||
|
|
||||||
|
offset -= (flags & exp_neg) ? p_int.size() : p_dec.size();
|
||||||
|
|
||||||
|
while (offset--)
|
||||||
|
{
|
||||||
|
if(flags & exp_neg)
|
||||||
|
p_int.insert(p_int.begin(), '0');
|
||||||
|
else
|
||||||
|
p_dec.push_back('0');
|
||||||
|
}
|
||||||
|
|
||||||
|
return ((flags & negative) ? "-" : "") + ((flags & exp_neg) ? "0." + p_int + p_dec : p_int + p_dec + ".0");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace xsk::utils
|
} // namespace xsk::utils
|
||||||
|
@ -37,6 +37,7 @@ public:
|
|||||||
static auto split(std::string& str, char delimiter) -> std::vector<std::string>;
|
static auto split(std::string& str, char delimiter) -> std::vector<std::string>;
|
||||||
static auto clean_buffer_lines(std::vector<std::uint8_t>& buffer) -> std::vector<std::string>;
|
static auto clean_buffer_lines(std::vector<std::uint8_t>& buffer) -> std::vector<std::string>;
|
||||||
static auto parse_code(std::string& line) -> std::vector<std::string>;
|
static auto parse_code(std::string& line) -> std::vector<std::string>;
|
||||||
|
static auto float_string(float value) -> std::string;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace xsk::utils
|
} // namespace xsk::utils
|
||||||
|
Loading…
x
Reference in New Issue
Block a user