diff --git a/src/t6/xsk/assembler.cpp b/src/t6/xsk/assembler.cpp index 0f623c97..069cb39a 100644 --- a/src/t6/xsk/assembler.cpp +++ b/src/t6/xsk/assembler.cpp @@ -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(static_cast(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); diff --git a/src/t6/xsk/compiler.cpp b/src/t6/xsk/compiler.cpp index 97c086de..933ac98f 100644 --- a/src/t6/xsk/compiler.cpp +++ b/src/t6/xsk/compiler.cpp @@ -40,23 +40,21 @@ void compiler::compile(const std::string& file, std::vector& data) { filename_ = file; - auto prog = parse_buffer(filename_, data); + auto prog = parse_buffer(filename_, reinterpret_cast(data.data()), data.size()); compile_program(prog); } -void compiler::read_callback(std::function(const std::string&)> func) +void compiler::mode(build mode) { - read_callback_ = func; + mode_ = mode; } -auto compiler::parse_buffer(const std::string& file, std::vector& 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(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& 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 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: diff --git a/src/t6/xsk/compiler.hpp b/src/t6/xsk/compiler.hpp index c159b84f..0ef3c97f 100644 --- a/src/t6/xsk/compiler.hpp +++ b/src/t6/xsk/compiler.hpp @@ -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 includes_; std::vector animtrees_; std::unordered_map constants_; - std::function(const std::string&)> read_callback_; - abort_t abort_; - std::string break_loc_; - std::string continue_loc_; + std::vector 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; void compile(const std::string& file, std::vector& data); - void read_callback(std::function(const std::string&)> func); + void mode(build mode); private: - auto parse_buffer(const std::string& file, std::vector& 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); diff --git a/src/t6/xsk/context.cpp b/src/t6/xsk/context.cpp new file mode 100644 index 00000000..ec35fc2c --- /dev/null +++ b/src/t6/xsk/context.cpp @@ -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 diff --git a/src/t6/xsk/context.hpp b/src/t6/xsk/context.hpp new file mode 100644 index 00000000..e951c758 --- /dev/null +++ b/src/t6/xsk/context.hpp @@ -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 diff --git a/src/t6/xsk/disassembler.cpp b/src/t6/xsk/disassembler.cpp index dcf7b259..f2d761f5 100644 --- a/src/t6/xsk/disassembler.cpp +++ b/src/t6/xsk/disassembler.cpp @@ -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())); break; case opcode::OP_GetFloat: - { inst->size += script_->align(4); - auto val = script_->read(); - inst->data.push_back(utils::string::va("%g%s", val, val == int(val) ? ".0" : "")); - } + inst->data.push_back(utils::string::float_string(script_->read())); break; case opcode::OP_GetVector: inst->size += script_->align(4); - inst->data.push_back(utils::string::va("%g", script_->read())); - inst->data.push_back(utils::string::va("%g", script_->read())); - inst->data.push_back(utils::string::va("%g", script_->read())); + inst->data.push_back(utils::string::float_string(script_->read())); + inst->data.push_back(utils::string::float_string(script_->read())); + inst->data.push_back(utils::string::float_string(script_->read())); 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())); diff --git a/src/t6/xsk/resolver.cpp b/src/t6/xsk/resolver.cpp index aa231aa9..f95ee798 100644 --- a/src/t6/xsk/resolver.cpp +++ b/src/t6/xsk/resolver.cpp @@ -12,6 +12,18 @@ namespace xsk::arc::t6 std::unordered_map opcode_map; std::unordered_map opcode_map_rev; std::unordered_map dvar_map; +std::unordered_map> files; +std::function(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(const std::string&)> read_callback = nullptr; -std::unordered_map> files; - auto resolver::file_data(const std::string& name) -> std::tuple { const auto& itr = files.find(name); @@ -81,7 +90,7 @@ auto resolver::file_data(const std::string& name) -> std::tuple std::tuple(const std::string&)> callback) -{ - read_callback = callback; -} - std::set paths { "aitype", diff --git a/src/t6/xsk/resolver.hpp b/src/t6/xsk/resolver.hpp index c08756e1..8cdffd5e 100644 --- a/src/t6/xsk/resolver.hpp +++ b/src/t6/xsk/resolver.hpp @@ -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; diff --git a/src/t6/xsk/t6.cpp b/src/t6/xsk/t6.cpp index 9ff8d9b5..8b67f166 100644 --- a/src/t6/xsk/t6.cpp +++ b/src/t6/xsk/t6.cpp @@ -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: diff --git a/src/t6/xsk/t6.hpp b/src/t6/xsk/t6.hpp index 8285861c..c396fa07 100644 --- a/src/t6/xsk/t6.hpp +++ b/src/t6/xsk/t6.hpp @@ -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 { diff --git a/src/tool/xsk/main.cpp b/src/tool/xsk/main.cpp index ce40a1a4..6395250b 100644 --- a/src/tool/xsk/main.cpp +++ b/src/tool/xsk/main.cpp @@ -452,25 +452,22 @@ void init() namespace arc { -std::map assemblers; -std::map disassemblers; -std::map compilers; -std::map decompilers; +std::map contexts; std::map> 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(); - disassemblers[game::T6] = std::make_unique(); - compilers[game::T6] = std::make_unique(build::prod); - decompilers[game::T6] = std::make_unique(); + contexts[game::T6] = std::make_unique(); + contexts[game::T6]->init(build::prod, utils::file::read); + funcs[mode::ASM] = assemble_file; funcs[mode::DISASM] = disassemble_file; funcs[mode::COMP] = compile_file; diff --git a/src/utils/xsk/arc/block.hpp b/src/utils/xsk/arc/block.hpp index 6127554e..7c042d2d 100644 --- a/src/utils/xsk/arc/block.hpp +++ b/src/utils/xsk/arc/block.hpp @@ -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 diff --git a/src/utils/xsk/arc/interfaces/compiler.hpp b/src/utils/xsk/arc/interfaces/compiler.hpp index 29f90ade..95ae6975 100644 --- a/src/utils/xsk/arc/interfaces/compiler.hpp +++ b/src/utils/xsk/arc/interfaces/compiler.hpp @@ -17,7 +17,6 @@ public: virtual auto output() -> assembly::ptr = 0; virtual auto output_data() -> std::vector = 0; virtual void compile(const std::string& file, std::vector& data) = 0; - virtual void read_callback(std::function(const std::string&)> func) = 0; }; } // namespace xsk::arc diff --git a/src/utils/xsk/arc/interfaces/context.hpp b/src/utils/xsk/arc/interfaces/context.hpp new file mode 100644 index 00000000..4abb3ea5 --- /dev/null +++ b/src/utils/xsk/arc/interfaces/context.hpp @@ -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; + + 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 diff --git a/src/utils/xsk/arc/types.hpp b/src/utils/xsk/arc/types.hpp index d9b736d1..53e19fac 100644 --- a/src/utils/xsk/arc/types.hpp +++ b/src/utils/xsk/arc/types.hpp @@ -8,10 +8,12 @@ namespace xsk::arc { +using read_cb_type = std::function(const std::string&)>; + enum class build { - dev, prod, + dev, }; enum class abort_t diff --git a/src/utils/xsk/utils.hpp b/src/utils/xsk/utils.hpp index 17edd946..2aa2b284 100644 --- a/src/utils/xsk/utils.hpp +++ b/src/utils/xsk/utils.hpp @@ -37,3 +37,4 @@ #include "arc/interfaces/disassembler.hpp" #include "arc/interfaces/compiler.hpp" #include "arc/interfaces/decompiler.hpp" +#include "arc/interfaces/context.hpp" diff --git a/src/utils/xsk/utils/string.cpp b/src/utils/xsk/utils/string.cpp index e64a40f2..e909a5cb 100644 --- a/src/utils/xsk/utils/string.cpp +++ b/src/utils/xsk/utils/string.cpp @@ -227,4 +227,86 @@ auto string::parse_code(std::string& line) -> std::vector 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 diff --git a/src/utils/xsk/utils/string.hpp b/src/utils/xsk/utils/string.hpp index 160e6198..8ef6cedc 100644 --- a/src/utils/xsk/utils/string.hpp +++ b/src/utils/xsk/utils/string.hpp @@ -37,6 +37,7 @@ public: static auto split(std::string& str, char delimiter) -> std::vector; static auto clean_buffer_lines(std::vector& buffer) -> std::vector; static auto parse_code(std::string& line) -> std::vector; + static auto float_string(float value) -> std::string; }; } // namespace xsk::utils