context wrapper & t6 bug fixing

This commit is contained in:
xensik 2022-02-21 16:08:55 +01:00
parent 6980506e88
commit 9b7eb28b84
18 changed files with 309 additions and 145 deletions

View File

@ -185,6 +185,7 @@ void assembler::assemble_function(const function::ptr& func)
{
func->index = script_->pos();
func->size = 0;
labels_.clear();
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);
if (itr != labels_.end())
if (itr != func->labels.end())
{
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_GetGameRef:
case opcode::OP_CreateLocalVariable:
case opcode::OP_RemoveLocalVariables:
case opcode::OP_EvalArray:
case opcode::OP_EvalLocalArrayRefCached:
case opcode::OP_EvalArrayRef:
case opcode::OP_ClearArray:
case opcode::OP_EmptyArray:
@ -364,7 +363,9 @@ void assembler::assemble_instruction(const instruction::ptr& inst)
case opcode::OP_SafeCreateLocalVariables:
assemble_localvars(inst);
break;
case opcode::OP_RemoveLocalVariables:
case opcode::OP_EvalLocalVariableCached:
case opcode::OP_EvalLocalArrayRefCached:
case opcode::OP_SafeSetWaittillVariableFieldCached:
case opcode::OP_EvalLocalVariableRefCached:
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_GetGameRef:
case opcode::OP_CreateLocalVariable:
case opcode::OP_RemoveLocalVariables:
case opcode::OP_EvalArray:
case opcode::OP_EvalLocalArrayRefCached:
case opcode::OP_EvalArrayRef:
case opcode::OP_ClearArray:
case opcode::OP_EmptyArray:
@ -649,7 +648,9 @@ void assembler::align_instruction(const instruction::ptr& inst)
}
}
break;
case opcode::OP_RemoveLocalVariables:
case opcode::OP_EvalLocalVariableCached:
case opcode::OP_EvalLocalArrayRefCached:
case opcode::OP_SafeSetWaittillVariableFieldCached:
case opcode::OP_EvalLocalVariableRefCached:
script_->seek(1);

View File

@ -40,23 +40,21 @@ void compiler::compile(const std::string& file, std::vector<std::uint8_t>& data)
{
filename_ = file;
auto prog = parse_buffer(filename_, data);
auto prog = parse_buffer(filename_, reinterpret_cast<char*>(data.data()), data.size());
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);
resolver::set_reader(read_callback_);
lexer lexer(mode_, file, reinterpret_cast<char*>(data.data()), data.size());
lexer lexer(mode_, file, data, size);
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 buffer = read_callback_(file);
auto result = parse_buffer(file, buffer);
auto data = resolver::file_data(file);
auto result = parse_buffer(file, std::get<1>(data), std::get<2>(data));
return result;
}
@ -113,7 +111,7 @@ void compiler::emit_include(const ast::include::ptr& include)
{
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_continue_ = false;
local_stack_.clear();
break_loc_ = "";
continue_loc_ = "";
abort_ = abort_t::abort_none;
blocks_.clear();
process_thread(thread);
blocks_.push_back(block());
emit_expr_parameters(thread->params);
emit_stmt_list(thread->stmt);
if (abort_ == abort_t::abort_none)
if (blocks_.back().abort == abort_t::abort_none)
emit_opcode(opcode::OP_End);
blocks_.pop_back();
function_->size = index_ - function_->index;
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);
}
auto& paren = blocks_.back();
blocks_.push_back(block(paren.loc_break, paren.loc_continue));
emit_stmt(stmt->stmt);
blocks_.pop_back();
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);
}
auto& paren = blocks_.back();
blocks_.push_back(block(paren.loc_break, paren.loc_continue));
emit_stmt(stmt->stmt_if);
blocks_.pop_back();
emit_opcode(opcode::OP_Jump, end_loc);
insert_label(else_loc);
auto& root = blocks_.back();
blocks_.push_back(block(root.loc_break, root.loc_continue));
emit_stmt(stmt->stmt_else);
blocks_.pop_back();
insert_label(end_loc);
}
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_continue = can_continue_;
can_break_ = true;
can_continue_ = true;
break_loc_ = create_label();
continue_loc_ = insert_label();
auto break_loc = create_label();
auto continue_loc = insert_label();
auto begin_loc = continue_loc_;
auto begin_loc = continue_loc;
if (stmt->test == ast::kind::expr_not)
{
emit_expr(stmt->test.as_not->rvalue);
emit_opcode(opcode::OP_JumpOnTrue, break_loc_);
emit_opcode(opcode::OP_JumpOnTrue, break_loc);
}
else
{
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_opcode(opcode::OP_Jump, begin_loc);
insert_label(break_loc_);
blocks_.pop_back();
emit_opcode(opcode::OP_Jump, continue_loc);
insert_label(break_loc);
can_break_ = old_break;
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)
{
auto old_abort = abort_;
auto old_break_loc = break_loc_;
auto old_continue_loc = continue_loc_;
auto old_break = can_break_;
auto old_continue = can_continue_;
can_break_ = true;
can_continue_ = true;
break_loc_ = create_label();
continue_loc_ = create_label();
auto break_loc = create_label();
auto continue_loc = create_label();
auto begin_loc = insert_label();
blocks_.push_back(block(break_loc, continue_loc));
emit_stmt(stmt->stmt);
blocks_.pop_back();
insert_label(continue_loc_);
insert_label(continue_loc);
if (stmt->test == ast::kind::expr_not)
{
emit_expr(stmt->test.as_not->rvalue);
emit_opcode(opcode::OP_JumpOnTrue, break_loc_);
emit_opcode(opcode::OP_JumpOnTrue, break_loc);
}
else
{
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);
insert_label(break_loc_);
insert_label(break_loc);
can_break_ = old_break;
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)
{
auto old_abort = abort_;
auto old_break_loc = break_loc_;
auto old_continue_loc = continue_loc_;
auto old_break = can_break_;
auto old_continue = can_continue_;
emit_stmt(stmt->init);
break_loc_ = create_label();
continue_loc_ = create_label();
auto break_loc = create_label();
auto continue_loc = create_label();
auto begin_loc = insert_label();
@ -608,34 +609,30 @@ void compiler::emit_stmt_for(const ast::stmt_for::ptr& stmt)
if (!const_cond)
{
emit_expr(stmt->test);
emit_opcode(opcode::OP_JumpOnFalse, break_loc_);
emit_opcode(opcode::OP_JumpOnFalse, break_loc);
}
can_break_ = true;
can_continue_ = true;
blocks_.push_back(block(break_loc, continue_loc));
emit_stmt(stmt->stmt);
blocks_.pop_back();
can_break_ = false;
can_continue_ = false;
insert_label(continue_loc_);
insert_label(continue_loc);
emit_stmt(stmt->iter);
emit_opcode(opcode::OP_Jump, begin_loc);
insert_label(break_loc_);
insert_label(break_loc);
can_break_ = old_break;
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)
{
auto old_abort = abort_;
auto old_break_loc = break_loc_;
auto old_continue_loc = continue_loc_;
auto old_break = can_break_;
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_expr_variable_ref(stmt->key_expr, true);
break_loc_ = create_label();
continue_loc_ = create_label();
auto break_loc = create_label();
auto continue_loc = create_label();
auto begin_loc = insert_label();
emit_expr_variable(stmt->key_expr);
emit_opcode(opcode::OP_IsDefined);
emit_opcode(opcode::OP_JumpOnFalse, break_loc_);
emit_opcode(opcode::OP_JumpOnFalse, break_loc);
can_break_ = 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_EvalArray);
emit_expr_variable_ref(stmt->value_expr, true);
blocks_.push_back(block(break_loc, continue_loc));
emit_stmt(stmt->stmt);
blocks_.pop_back();
can_break_ = false;
can_continue_ = false;
insert_label(continue_loc_);
insert_label(continue_loc);
emit_expr_variable(stmt->key_expr);
emit_expr_variable(stmt->array);
emit_opcode(opcode::OP_NextArrayKey);
emit_expr_variable_ref(stmt->key_expr, true);
emit_opcode(opcode::OP_Jump, begin_loc);
insert_label(break_loc_);
insert_label(break_loc);
can_break_ = old_break;
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)
{
auto old_abort = abort_;
auto old_break_loc = break_loc_;
auto old_break = can_break_;
can_break_ = false;
auto jmptable_loc = create_label();
break_loc_ = create_label();
auto break_loc = create_label();
emit_expr(stmt->test);
emit_opcode(opcode::OP_Switch, jmptable_loc);
can_break_ = true;
blocks_.push_back(block(break_loc, blocks_.back().loc_continue));
std::vector<std::string> data;
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");
}
auto& paren = blocks_.back();
blocks_.push_back(block(paren.loc_break, paren.loc_continue));
emit_stmt_list(case_->stmt);
blocks_.pop_back();
}
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(loc);
has_default = true;
auto& paren = blocks_.back();
blocks_.push_back(block(paren.loc_break, paren.loc_continue));
emit_stmt_list(entry.as_default->stmt);
blocks_.pop_back();
}
else
{
@ -751,13 +755,13 @@ void compiler::emit_stmt_switch(const ast::stmt_switch::ptr& stmt)
}
}
blocks_.pop_back();
insert_label(jmptable_loc);
emit_opcode(opcode::OP_EndSwitch, data);
insert_label(break_loc_);
insert_label(break_loc);
can_break_ = old_break;
break_loc_ = old_break_loc;
abort_ = old_abort;
}
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)
{
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");
abort_ = abort_t::abort_break;
emit_opcode(opcode::OP_Jump, break_loc_);
blocks_.back().abort = abort_t::abort_break;
emit_opcode(opcode::OP_Jump, blocks_.back().loc_break);
}
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");
abort_ = abort_t::abort_continue;
emit_opcode(opcode::OP_Jump, continue_loc_);
blocks_.back().abort = abort_t::abort_continue;
emit_opcode(opcode::OP_Jump, blocks_.back().loc_continue);
}
void compiler::emit_stmt_return(const ast::stmt_return::ptr& stmt)
{
if (abort_ == abort_t::abort_none)
abort_ = abort_t::abort_return;
if (blocks_.back().abort == abort_t::abort_none)
blocks_.back().abort = abort_t::abort_return;
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)
{
emit_opcode(opcode::OP_PreScriptCall);
emit_expr_arguments(expr->args);
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)
{
emit_opcode(opcode::OP_PreScriptCall);
emit_expr_arguments(expr->args);
emit_expr(obj);
emit_expr(expr->func);
@ -1571,14 +1577,11 @@ void compiler::emit_expr_array_ref(const ast::expr_array::ptr& expr, bool set)
break;
case ast::kind::expr_array:
case ast::kind::expr_field:
case ast::kind::expr_identifier:
emit_expr_variable_ref(expr->obj, false);
emit_opcode(opcode::OP_EvalArrayRef);
if (set) emit_opcode(opcode::OP_SetVariableField);
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_method:
default:

View File

@ -12,7 +12,6 @@ enum class opcode : std::uint8_t;
class compiler : public arc::compiler
{
build mode_;
std::string filename_;
assembly::ptr assembly_;
function::ptr function_;
@ -24,23 +23,20 @@ class compiler : public arc::compiler
std::vector<include_t> includes_;
std::vector<animtree_t> animtrees_;
std::unordered_map<std::string, ast::expr> constants_;
std::function<std::vector<std::uint8_t>(const std::string&)> read_callback_;
abort_t abort_;
std::string break_loc_;
std::string continue_loc_;
std::vector<block> blocks_;
bool can_break_;
bool can_continue_;
bool developer_thread_;
build mode_;
public:
compiler(build mode) : mode_(mode) {}
auto output() -> assembly::ptr;
auto output_data() -> std::vector<std::uint8_t>;
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:
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;
void compile_program(const ast::program::ptr& program);
void emit_include(const ast::include::ptr& include);
@ -163,7 +159,6 @@ private:
auto map_known_includes(const std::string& include) -> bool;
utils::byte_buffer::ptr output_;
void print_function(const function::ptr& func);
void print_instruction(const instruction::ptr& inst);

23
src/t6/xsk/context.cpp Normal file
View 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
View 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

View File

@ -248,6 +248,8 @@ void disassembler::disassemble_function(const function::ptr& func)
}
}
void disassembler::disassemble_instruction(const instruction::ptr& inst)
{
switch (opcode(inst->opcode))
@ -264,9 +266,7 @@ void disassembler::disassemble_instruction(const instruction::ptr& inst)
case opcode::OP_GetAnim:
case opcode::OP_GetGameRef:
case opcode::OP_CreateLocalVariable:
case opcode::OP_RemoveLocalVariables:
case opcode::OP_EvalArray:
case opcode::OP_EvalLocalArrayRefCached:
case opcode::OP_EvalArrayRef:
case opcode::OP_ClearArray:
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>()));
break;
case opcode::OP_GetFloat:
{
inst->size += script_->align(4);
auto val = script_->read<float>();
inst->data.push_back(utils::string::va("%g%s", val, val == int(val) ? ".0" : ""));
}
inst->data.push_back(utils::string::float_string(script_->read<float>()));
break;
case opcode::OP_GetVector:
inst->size += script_->align(4);
inst->data.push_back(utils::string::va("%g", script_->read<float>()));
inst->data.push_back(utils::string::va("%g", 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::float_string(script_->read<float>()));
inst->data.push_back(utils::string::float_string(script_->read<float>()));
break;
case opcode::OP_GetString:
case opcode::OP_GetIString:
@ -383,7 +380,9 @@ void disassembler::disassemble_instruction(const instruction::ptr& inst)
case opcode::OP_SafeCreateLocalVariables:
disassemble_localvars(inst);
break;
case opcode::OP_RemoveLocalVariables:
case opcode::OP_EvalLocalVariableCached:
case opcode::OP_EvalLocalArrayRefCached:
case opcode::OP_SafeSetWaittillVariableFieldCached:
case opcode::OP_EvalLocalVariableRefCached:
inst->data.push_back(utils::string::va("%i", script_->read<std::uint8_t>()));

View File

@ -12,6 +12,18 @@ namespace xsk::arc::t6
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::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
{
@ -22,7 +34,7 @@ auto resolver::opcode_id(const std::string& name) -> std::uint8_t
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
@ -34,7 +46,7 @@ auto resolver::opcode_name(std::uint8_t id) -> std::string
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
@ -67,9 +79,6 @@ auto resolver::make_token(std::string_view str) -> std::string
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>
{
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 + "'");
}
void resolver::set_reader(std::function<std::vector<std::uint8_t>(const std::string&)> callback)
{
read_callback = callback;
}
std::set<std::string> paths
{
"aitype",

View File

@ -11,6 +11,8 @@ namespace xsk::arc::t6
class resolver
{
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_name(std::uint8_t id) -> std::string;
static auto dvar_name(std::uint32_t id) -> std::string;

View File

@ -25,9 +25,7 @@ auto opcode_size(std::uint8_t id) -> std::uint32_t
case opcode::OP_GetAnim:
case opcode::OP_GetGameRef:
case opcode::OP_CreateLocalVariable:
case opcode::OP_RemoveLocalVariables:
case opcode::OP_EvalArray:
case opcode::OP_EvalLocalArrayRefCached:
case opcode::OP_EvalArrayRef:
case opcode::OP_ClearArray:
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_GetNegByte:
case opcode::OP_SafeCreateLocalVariables:
case opcode::OP_RemoveLocalVariables:
case opcode::OP_EvalLocalVariableCached:
case opcode::OP_EvalLocalArrayRefCached:
case opcode::OP_SafeSetWaittillVariableFieldCached:
case opcode::OP_EvalLocalVariableRefCached:
case opcode::OP_ScriptFunctionCallPointer:

View File

@ -9,9 +9,10 @@
#include "assembler.hpp"
#include "disassembler.hpp"
#include "decompiler.hpp"
#include "compiler.hpp"
#include "decompiler.hpp"
#include "resolver.hpp"
#include "context.hpp"
namespace xsk::arc::t6
{

View File

@ -452,25 +452,22 @@ void init()
namespace arc
{
std::map<game, assembler::ptr> assemblers;
std::map<game, disassembler::ptr> disassemblers;
std::map<game, compiler::ptr> compilers;
std::map<game, decompiler::ptr> decompilers;
std::map<game, context::ptr> contexts;
std::map<mode, std::function<void(game game, const std::filesystem::path& file)>> funcs;
void assemble_file(game game, const std::filesystem::path& file)
{
try
{
const auto& assembler = assemblers[game];
auto& assembler = contexts[game]->assembler();
auto data = utils::file::read(file.string());
auto path = t6::resolver::fs_to_game_path(file);
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";
}
catch (const std::exception& e)
@ -483,15 +480,15 @@ void disassemble_file(game game, const std::filesystem::path& file)
{
try
{
const auto& disassembler = disassemblers[game];
auto& disassembler = contexts[game]->disassembler();
auto data = utils::file::read(file.string());
auto path = t6::resolver::fs_to_game_path(file);
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";
}
catch (const std::exception& e)
@ -504,20 +501,19 @@ void compile_file(game game, const std::filesystem::path& file)
{
try
{
const auto& assembler = assemblers[game];
const auto& compiler = compilers[game];
auto& assembler = contexts[game]->assembler();
auto& compiler = contexts[game]->compiler();
auto data = utils::file::read(file.string());
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";
}
catch (const std::exception& e)
@ -530,19 +526,19 @@ void decompile_file(game game, const std::filesystem::path& file)
{
try
{
const auto& disassembler = disassemblers[game];
const auto& decompiler = decompilers[game];
auto& disassembler = contexts[game]->disassembler();
auto& decompiler = contexts[game]->decompiler();
auto data = utils::file::read(file.string());
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";
}
catch (const std::exception& e)
@ -553,10 +549,9 @@ void decompile_file(game game, const std::filesystem::path& file)
void init()
{
assemblers[game::T6] = std::make_unique<t6::assembler>();
disassemblers[game::T6] = std::make_unique<t6::disassembler>();
compilers[game::T6] = std::make_unique<t6::compiler>(build::prod);
decompilers[game::T6] = std::make_unique<t6::decompiler>();
contexts[game::T6] = std::make_unique<t6::context>();
contexts[game::T6]->init(build::prod, utils::file::read);
funcs[mode::ASM] = assemble_file;
funcs[mode::DISASM] = disassemble_file;
funcs[mode::COMP] = compile_file;

View File

@ -19,6 +19,8 @@ struct block
bool is_dev;
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

View File

@ -17,7 +17,6 @@ public:
virtual auto output() -> assembly::ptr = 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 read_callback(std::function<std::vector<std::uint8_t>(const std::string&)> func) = 0;
};
} // namespace xsk::arc

View 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

View File

@ -8,10 +8,12 @@
namespace xsk::arc
{
using read_cb_type = std::function<std::vector<std::uint8_t>(const std::string&)>;
enum class build
{
dev,
prod,
dev,
};
enum class abort_t

View File

@ -37,3 +37,4 @@
#include "arc/interfaces/disassembler.hpp"
#include "arc/interfaces/compiler.hpp"
#include "arc/interfaces/decompiler.hpp"
#include "arc/interfaces/context.hpp"

View File

@ -227,4 +227,86 @@ auto string::parse_code(std::string& line) -> std::vector<std::string>
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

View File

@ -37,6 +37,7 @@ public:
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 parse_code(std::string& line) -> std::vector<std::string>;
static auto float_string(float value) -> std::string;
};
} // namespace xsk::utils