diff --git a/common/type_system/Type.cpp b/common/type_system/Type.cpp index 0a215e748c..2da77b23be 100644 --- a/common/type_system/Type.cpp +++ b/common/type_system/Type.cpp @@ -630,6 +630,23 @@ int BasicType::get_inline_array_start_alignment() const { } } +bool BasicType::operator==(const Type& other) const { + if (typeid(*this) != typeid(other)) { + return false; + } + + auto* p_other = dynamic_cast(&other); + // clang-format off + return other.is_equal(*this) && + m_fields == p_other->m_fields && + m_dynamic == p_other->m_dynamic && + m_size_in_mem == p_other->m_size_in_mem && + m_pack == p_other->m_pack && + m_allow_misalign == p_other->m_allow_misalign && + m_final == p_other->m_final; + // clang-format on +} + ///////////////// // Bitfield ///////////////// diff --git a/common/type_system/Type.h b/common/type_system/Type.h index 2a747d1664..f8e4accae2 100644 --- a/common/type_system/Type.h +++ b/common/type_system/Type.h @@ -107,7 +107,6 @@ class Type { bool m_allow_in_runtime = true; std::string m_runtime_name; bool m_is_boxed = false; // does this have runtime type information? - int m_heap_base = 0; }; @@ -286,7 +285,13 @@ class BasicType : public StructureType { int get_offset() const override; int get_inline_array_start_alignment() const override; std::string print() const override; + bool final() const { return m_final; } + void set_final() { m_final = true; } ~BasicType() = default; + bool operator==(const Type& other) const override; + + protected: + bool m_final = false; }; class BitField { diff --git a/common/type_system/TypeSystem.cpp b/common/type_system/TypeSystem.cpp index 44ffcdf8aa..842d1bc1ff 100644 --- a/common/type_system/TypeSystem.cpp +++ b/common/type_system/TypeSystem.cpp @@ -724,6 +724,7 @@ void TypeSystem::add_builtin_types() { auto symbol_type = add_builtin_basic("basic", "symbol"); auto type_type = add_builtin_basic("basic", "type"); auto string_type = add_builtin_basic("basic", "string"); + string_type->set_final(); // no virtual calls used on string. auto function_type = add_builtin_basic("basic", "function"); auto vu_function_type = add_builtin_structure("structure", "vu-function"); auto link_block_type = add_builtin_basic("basic", "link-block"); @@ -1539,3 +1540,16 @@ std::string TypeSystem::generate_deftype(const Type* type) const { ";; cannot generate deftype for {}, it is not a structure, basic, or bitfield (parent {})\n", type->get_name(), type->get_parent()); } + +bool TypeSystem::should_use_virtual_methods(const Type* type) const { + auto as_basic = dynamic_cast(type); + if (as_basic && !as_basic->final()) { + return true; + } else { + return false; + } +} + +bool TypeSystem::should_use_virtual_methods(const TypeSpec& type) const { + return should_use_virtual_methods(lookup_type(type)); +} \ No newline at end of file diff --git a/common/type_system/TypeSystem.h b/common/type_system/TypeSystem.h index f88df24f92..7f155b5a96 100644 --- a/common/type_system/TypeSystem.h +++ b/common/type_system/TypeSystem.h @@ -174,6 +174,9 @@ class TypeSystem { int offset, int field_size); + bool should_use_virtual_methods(const Type* type) const; + bool should_use_virtual_methods(const TypeSpec& type) const; + /*! * Get a type by name and cast to a child class of Type*. Must succeed. */ diff --git a/common/type_system/deftype.cpp b/common/type_system/deftype.cpp index 21a04cd54d..3bc5a16b68 100644 --- a/common/type_system/deftype.cpp +++ b/common/type_system/deftype.cpp @@ -208,6 +208,7 @@ struct StructureDefResult { bool generate_runtime_type = true; bool pack_me = false; bool allow_misaligned = false; + bool final = false; }; StructureDefResult parse_structure_def(StructureType* type, @@ -271,6 +272,8 @@ StructureDefResult parse_structure_def(StructureType* type, flags.heap_base = hb; } else if (opt_name == ":allow-misaligned") { result.allow_misaligned = true; + } else if (opt_name == ":final") { + result.final = true; } else { throw std::runtime_error("Invalid option in field specification: " + opt_name); } @@ -436,6 +439,11 @@ DeftypeResult parse_deftype(const goos::Object& deftype, TypeSystem* ts) { auto new_type = std::make_unique(parent_type_name, name, false, 0); auto pto = dynamic_cast(ts->lookup_type(parent_type)); assert(pto); + if (pto->final()) { + throw std::runtime_error( + fmt::format("[TypeSystem] Cannot make a child type {} of final basic type {}", name, + parent_type_name)); + } new_type->inherit(pto); ts->forward_declare_type_as_basic(name); auto sr = parse_structure_def(new_type.get(), ts, field_list_obj, options_obj); @@ -452,6 +460,9 @@ DeftypeResult parse_deftype(const goos::Object& deftype, TypeSystem* ts) { throw std::runtime_error("invalid pack option on basic"); } new_type->set_heap_base(result.flags.heap_base); + if (sr.final) { + new_type->set_final(); + } ts->add_type(name, std::move(new_type)); } else if (is_type("structure", parent_type, ts)) { auto new_type = std::make_unique(parent_type_name, name, false, false, false, 0); @@ -468,6 +479,10 @@ DeftypeResult parse_deftype(const goos::Object& deftype, TypeSystem* ts) { if (sr.allow_misaligned) { new_type->set_allow_misalign(true); } + if (sr.final) { + throw std::runtime_error( + fmt::format("[TypeSystem] :final option cannot be used on structure type {}", name)); + } new_type->set_heap_base(result.flags.heap_base); ts->add_type(name, std::move(new_type)); } else if (is_type("integer", parent_type, ts)) { diff --git a/decompiler/IR2/AtomicOpTypeAnalysis.cpp b/decompiler/IR2/AtomicOpTypeAnalysis.cpp index 7cb51b3963..fd5b2c6d69 100644 --- a/decompiler/IR2/AtomicOpTypeAnalysis.cpp +++ b/decompiler/IR2/AtomicOpTypeAnalysis.cpp @@ -726,9 +726,9 @@ TP_Type LoadVarOp::get_src_type(const TypeState& input, if (method_id == GOAL_NEW_METHOD) { return TP_Type::make_from_ts(method_type); } else if (input_type.kind == TP_Type::Kind::TYPE_OF_TYPE_NO_VIRTUAL) { - return TP_Type::make_non_virtual_method(method_type); + return TP_Type::make_non_virtual_method(method_type, TypeSpec(type_name)); } else { - return TP_Type::make_virtual_method(method_type); + return TP_Type::make_virtual_method(method_type, TypeSpec(type_name)); } } @@ -740,7 +740,7 @@ TP_Type LoadVarOp::get_src_type(const TypeState& input, if (method_id != GOAL_NEW_METHOD && method_id != GOAL_RELOC_METHOD) { // this can get us the wrong thing for `new` methods. And maybe relocate? return TP_Type::make_non_virtual_method( - method_info.type.substitute_for_method_call("object")); + method_info.type.substitute_for_method_call("object"), TypeSpec("object")); } } diff --git a/decompiler/IR2/Form.h b/decompiler/IR2/Form.h index f275490bdc..c47d2947ca 100644 --- a/decompiler/IR2/Form.h +++ b/decompiler/IR2/Form.h @@ -1329,6 +1329,7 @@ class StackVarDefElement : public FormElement { FormStack& stack, std::vector* result, bool allow_side_effects) override; + const TypeSpec& type() const { return m_entry.ref_type; } private: StackVarEntry m_entry; diff --git a/decompiler/IR2/FormExpressionAnalysis.cpp b/decompiler/IR2/FormExpressionAnalysis.cpp index 075ccb3a9c..1701239fa8 100644 --- a/decompiler/IR2/FormExpressionAnalysis.cpp +++ b/decompiler/IR2/FormExpressionAnalysis.cpp @@ -1796,12 +1796,23 @@ void FunctionCallElement::update_from_stack(const Env& env, } std::vector arg_forms; + bool has_good_types = env.has_type_analysis() && function_type.arg_count() == nargs + 1; + TypeSpec first_arg_type; for (size_t arg_id = 0; arg_id < nargs; arg_id++) { auto val = unstacked.at(arg_id + 1); // first is the function itself. auto& var = all_pop_vars.at(arg_id + 1); - if (env.has_type_analysis() && function_type.arg_count() == nargs + 1) { + if (has_good_types) { auto actual_arg_type = env.get_types_before_op(var.idx()).get(var.reg()).typespec(); + auto val_atom = form_as_atom(val); + if (val_atom && val_atom->is_var()) { + actual_arg_type = env.get_variable_type(val_atom->var(), true); + } + + if (arg_id == 0) { + first_arg_type = actual_arg_type; + } + auto desired_arg_type = function_type.get_arg(arg_id); if (!env.dts->ts.tc(desired_arg_type, actual_arg_type)) { arg_forms.push_back(cast_form(val, desired_arg_type, pool, env)); @@ -1826,6 +1837,17 @@ void FunctionCallElement::update_from_stack(const Env& env, auto vtable_var_name = env.get_variable_name(*vtable_reg); auto arg0_mr = match(Matcher::any_reg(0), unstacked.at(1)); if (arg0_mr.matched && env.get_variable_name(*arg0_mr.maps.regs.at(0)) == vtable_var_name) { + if (tp_type.kind != TP_Type::Kind::VIRTUAL_METHOD) { + throw std::runtime_error( + "Method internal mismatch. METHOD_OF_OBJECT operator didn't get a VIRTUAL_METHOD " + "type."); + } + + if (!env.dts->ts.should_use_virtual_methods(tp_type.method_from_type())) { + throw std::runtime_error( + fmt::format("Method call on {} used a virtual call unexpectedly.", + tp_type.method_from_type().print())); + } // fmt::print("STACK\n{}\n\n", stack.print(env)); auto pop = pop_to_forms({*arg0_mr.maps.regs.at(0)}, env, pool, stack, allow_side_effects, {}, {2}) @@ -1944,7 +1966,7 @@ void FunctionCallElement::update_from_stack(const Env& env, { // detect method calls: - // ex: ((method-of-type x new) (quote global) pair gp-0 a3-0) + // ex: ((method-of-type x blah) arg...) constexpr int method_name = 0; constexpr int type_source = 1; @@ -1957,7 +1979,73 @@ void FunctionCallElement::update_from_stack(const Env& env, auto match_result = match(matcher, temp_form); if (match_result.matched) { auto name = match_result.maps.strings.at(method_name); + if (name != "new") { + // only do these checks on non-new methods. New methods are treated as functions because + // they are never virtual and are never called like a method. + if (tp_type.kind != TP_Type::Kind::NON_VIRTUAL_METHOD) { + throw std::runtime_error(fmt::format( + "Method internal mismatch. METHOD_OF_TYPE operator didn't get a NON_VIRTUAL_METHOD " + "type. Got {} instead.", + tp_type.print())); + } + + if (env.dts->ts.should_use_virtual_methods(tp_type.method_from_type())) { + throw std::runtime_error( + fmt::format("Expected type {} to use virtual methods, but it didn't. Set option " + ":final in the deftype to disable virtual method calls", + tp_type.method_from_type().print())); + } + } + auto type_source_form = match_result.maps.forms.at(type_source); + + // if the type is the exact type of the argument, we want to build it into a method call + if (type_source_form->to_string(env) == first_arg_type.base_type() && name != "new") { + auto method_op = pool.alloc_single_element_form(nullptr, name); + auto gop = GenericOperator::make_function(method_op); + + result->push_back(pool.alloc_element(gop, arg_forms)); + return; + } + + if (name == "new" && arg_forms.size() >= 2) { + bool got_stack_new = true; + // method + // (the-as symbol (new 'stack-no-clear 'draw-context)) + // draw-context + auto first_cast = arg_forms.at(0)->try_as_element(); + if (!first_cast || first_cast->type() != TypeSpec("symbol")) { + got_stack_new = false; + } + + if (got_stack_new) { + auto new_op = first_cast->source()->try_as_element(); + if (!new_op || new_op->type().base_type() != type_source_form->to_string(env)) { + got_stack_new = false; + } + } + + if (got_stack_new) { + if (arg_forms.at(1)->to_string(env) != type_source_form->to_string(env)) { + got_stack_new = false; + } + } + + if (got_stack_new) { + std::vector stack_new_args; + stack_new_args.push_back( + pool.alloc_single_element_form(nullptr, "'stack")); + stack_new_args.push_back(pool.alloc_single_element_form( + nullptr, fmt::format("'{}", type_source_form->to_string(env)))); + for (size_t i = 2; i < arg_forms.size(); i++) { + stack_new_args.push_back(arg_forms.at(i)); + } + result->push_back(pool.alloc_element( + GenericOperator::make_fixed(FixedOperatorKind::NEW), stack_new_args)); + return; + } + } + auto method_op = pool.alloc_single_element_form(nullptr, type_source_form, name, false); auto gop = GenericOperator::make_function(method_op); diff --git a/decompiler/util/TP_Type.h b/decompiler/util/TP_Type.h index 5306a2b132..883cd24721 100644 --- a/decompiler/util/TP_Type.h +++ b/decompiler/util/TP_Type.h @@ -111,16 +111,18 @@ class TP_Type { static TP_Type make_from_ts(const std::string& ts) { return make_from_ts(TypeSpec(ts)); } - static TP_Type make_virtual_method(const TypeSpec& method_type) { + static TP_Type make_virtual_method(const TypeSpec& method_type, const TypeSpec& obj_type) { TP_Type result; result.kind = Kind::VIRTUAL_METHOD; result.m_ts = method_type; + result.m_method_from_type = obj_type; return result; } - static TP_Type make_non_virtual_method(const TypeSpec& method_type) { + static TP_Type make_non_virtual_method(const TypeSpec& method_type, const TypeSpec& obj_type) { TP_Type result; result.kind = Kind::NON_VIRTUAL_METHOD; + result.m_method_from_type = obj_type; result.m_ts = method_type; return result; } @@ -288,8 +290,14 @@ class TP_Type { return false; } + const TypeSpec& method_from_type() const { + assert(kind == Kind::VIRTUAL_METHOD || kind == Kind::NON_VIRTUAL_METHOD); + return m_method_from_type; + } + private: TypeSpec m_ts; + TypeSpec m_method_from_type; std::string m_str; int64_t m_int = 0; bool m_pcpyud = false; // have we extracted the top doubleword of a bitfield? diff --git a/goalc/compiler/compilation/Type.cpp b/goalc/compiler/compilation/Type.cpp index 3c2a793efb..d59d91f522 100644 --- a/goalc/compiler/compilation/Type.cpp +++ b/goalc/compiler/compilation/Type.cpp @@ -72,7 +72,7 @@ RegVal* Compiler::compile_get_method_of_object(const goos::Object& form, auto fe = get_parent_env_of_type(env); RegVal* runtime_type = nullptr; - if (is_basic(compile_time_type)) { + if (m_ts.should_use_virtual_methods(compile_time_type)) { runtime_type = fe->make_gpr(m_ts.make_typespec("type")); MemLoadInfo info; info.size = 4; diff --git a/test/decompiler/reference/engine/camera/math-camera_REF.gc b/test/decompiler/reference/engine/camera/math-camera_REF.gc index 11cc5f07a1..a5e865e074 100644 --- a/test/decompiler/reference/engine/camera/math-camera_REF.gc +++ b/test/decompiler/reference/engine/camera/math-camera_REF.gc @@ -666,24 +666,11 @@ (set! (-> s5-0 vector 1 quad) (the-as uint128 0)) (set! (-> s5-0 vector 2 quad) (the-as uint128 0)) (set! (-> s5-0 vector 3 quad) (the-as uint128 0)) - (let - ((s4-0 - ((method-of-type vector4s-3 new) - (the-as symbol (new 'stack-no-clear 'vector4s-3)) - vector4s-3 - ) - ) - (s3-0 (new 'stack-no-clear 'vector)) - ) + (let ((s4-0 (new 'stack 'vector4s-3)) + (s3-0 (new 'stack-no-clear 'vector)) + ) (set! (-> s3-0 quad) (the-as uint128 0)) - (let - ((s2-0 - ((method-of-type vector4s-3 new) - (the-as symbol (new 'stack-no-clear 'vector4s-3)) - vector4s-3 - ) - ) - ) + (let ((s2-0 (new 'stack 'vector4s-3))) (matrix*! s5-0 arg0 (-> *math-camera* camera-temp)) (matrix-3x3-inverse-transpose! gp-0 arg0) (let ((v1-3 s3-0)) @@ -757,7 +744,3 @@ (none) ) ) - - - - diff --git a/test/decompiler/reference/engine/engine/connect_REF.gc b/test/decompiler/reference/engine/engine/connect_REF.gc index 7da75a44bf..fbc5169075 100644 --- a/test/decompiler/reference/engine/engine/connect_REF.gc +++ b/test/decompiler/reference/engine/engine/connect_REF.gc @@ -95,7 +95,7 @@ ;; definition for method 12 of type connection (defmethod belongs-to-process? connection ((obj connection) (arg0 process)) - (= arg0 ((method-of-type connection get-process) obj)) + (= arg0 (get-process obj)) ) ;; definition for method 2 of type connection @@ -253,25 +253,25 @@ (format #t "~Talive-list:~%") (let ((s5-0 *print-column*)) (set! *print-column* (+ *print-column* (the-as uint 64))) - ((method-of-type connectable inspect) (-> obj alive-list)) + (inspect (-> obj alive-list)) (set! *print-column* s5-0) ) (format #t "~Talive-list-end:~%") (let ((s5-1 *print-column*)) (set! *print-column* (+ *print-column* (the-as uint 64))) - ((method-of-type connectable inspect) (-> obj alive-list-end)) + (inspect (-> obj alive-list-end)) (set! *print-column* s5-1) ) (format #t "~Tdead-list:~%") (let ((s5-2 *print-column*)) (set! *print-column* (+ *print-column* (the-as uint 64))) - ((method-of-type connectable inspect) (-> obj dead-list)) + (inspect (-> obj dead-list)) (set! *print-column* s5-2) ) (format #t "~Tdead-list-end:~%") (let ((s5-3 *print-column*)) (set! *print-column* (+ *print-column* (the-as uint 64))) - ((method-of-type connectable inspect) (-> obj dead-list-end)) + (inspect (-> obj dead-list-end)) (set! *print-column* s5-3) ) (format #t "~Tdata[~D]: @ #x~X~%" (-> obj allocated-length) (-> obj data)) @@ -427,7 +427,7 @@ ;; definition for method 13 of type connection (defmethod move-to-dead connection ((obj connection)) - (let ((v1-1 ((method-of-type connection get-engine) obj))) + (let ((v1-1 (get-engine obj))) (set! (-> obj prev0 next0) (-> obj next0)) (set! (-> obj next0 prev0) (-> obj prev0)) (set! (-> obj prev1 next1) (-> obj next1)) diff --git a/test/decompiler/reference/engine/gfx/hw/display_REF.gc b/test/decompiler/reference/engine/gfx/hw/display_REF.gc index d23a3c04bc..9ead0dfa02 100644 --- a/test/decompiler/reference/engine/gfx/hw/display_REF.gc +++ b/test/decompiler/reference/engine/gfx/hw/display_REF.gc @@ -506,32 +506,21 @@ (defun draw-sprite2d-xy ((buf dma-buffer) (x int) (y int) (w int) (h int) (color rgba)) - (let* - ((context - ((method-of-type draw-context new) - (the-as symbol (new 'stack-no-clear 'draw-context)) - draw-context - x - y - w - h - color - ) - ) - (draw-x (max 1792 (min 2304 (+ (-> context orgx) 1792)))) - (draw-y - (max - (min - (+ (-> context orgy) (-> *video-parms* screen-miny)) - (-> *video-parms* screen-maxy) - ) - (-> *video-parms* screen-miny) - ) - ) - (draw-w (-> context width)) - (draw-h (-> context height)) - (end-dma (the-as dma-packet (-> buf base))) - ) + (let* ((context (new 'stack 'draw-context x y w h color)) + (draw-x (max 1792 (min 2304 (+ (-> context orgx) 1792)))) + (draw-y + (max + (min + (+ (-> context orgy) (-> *video-parms* screen-miny)) + (-> *video-parms* screen-maxy) + ) + (-> *video-parms* screen-miny) + ) + ) + (draw-w (-> context width)) + (draw-h (-> context height)) + (end-dma (the-as dma-packet (-> buf base))) + ) (let* ((a2-2 buf) (dma (the-as dma-packet (-> a2-2 base))) ) @@ -742,19 +731,7 @@ (defun screen-gradient ((arg0 dma-buffer) (arg1 rgba) (arg2 rgba) (arg3 rgba) (arg4 rgba)) - (let - ((a1-2 - ((method-of-type draw-context new) - (the-as symbol (new 'stack-no-clear 'draw-context)) - draw-context - 0 - 0 - 512 - 224 - (new 'static 'rgba) - ) - ) - ) + (let ((a1-2 (new 'stack 'draw-context 0 0 512 224 (new 'static 'rgba)))) (set! (-> a1-2 color 0) arg1) (set! (-> a1-2 color 1) arg2) (set! (-> a1-2 color 2) arg3) diff --git a/test/decompiler/reference/engine/physics/trajectory_REF.gc b/test/decompiler/reference/engine/physics/trajectory_REF.gc index 2c0f820146..d085ba8b62 100644 --- a/test/decompiler/reference/engine/physics/trajectory_REF.gc +++ b/test/decompiler/reference/engine/physics/trajectory_REF.gc @@ -76,7 +76,7 @@ trajectory ((obj trajectory) (arg0 vector) (arg1 vector) (arg2 float) (arg3 float)) (let ((f0-1 (/ (vector-vector-xz-distance arg1 arg0) arg2))) - ((method-of-type trajectory TODO-RENAME-11) obj arg0 arg1 f0-1 arg3) + (TODO-RENAME-11 obj arg0 arg1 f0-1 arg3) ) (let ((v0-1 0)) ) @@ -98,7 +98,7 @@ (set! f0-3 (fmax (/ (- (- arg2) f0-4) arg3) (/ (+ (- arg2) f0-4) arg3))) ) ) - ((method-of-type trajectory TODO-RENAME-11) obj arg0 arg1 f0-3 arg3) + (TODO-RENAME-11 obj arg0 arg1 f0-3 arg3) ) (let ((v0-1 0)) ) @@ -118,7 +118,7 @@ (if (< 0.0 f1-5) (set! f0-3 (sqrtf f1-5)) ) - ((method-of-type trajectory TODO-RENAME-13) obj arg0 arg1 f0-3 arg3) + (TODO-RENAME-13 obj arg0 arg1 f0-3 arg3) ) (let ((v0-1 0)) ) @@ -142,7 +142,7 @@ ) (let ((f0-1 (* (-> obj time) (/ (+ 1.0 (the float s2-0)) (the float s3-0))))) - ((method-of-type trajectory TODO-RENAME-9) obj f0-1 s4-0) + (TODO-RENAME-9 obj f0-1 s4-0) ) (add-debug-line #t 68 s5-0 s4-0 (new 'static 'rgba :r #xff :a #x80) #f -1) ) @@ -151,7 +151,3 @@ ) (none) ) - - - - diff --git a/test/decompiler/reference/engine/util/smush-control-h_REF.gc b/test/decompiler/reference/engine/util/smush-control-h_REF.gc index 20673c4b66..ca7372119c 100644 --- a/test/decompiler/reference/engine/util/smush-control-h_REF.gc +++ b/test/decompiler/reference/engine/util/smush-control-h_REF.gc @@ -69,11 +69,11 @@ (set! (-> obj period) (* (-> obj period) (-> obj damp-period))) (set! (-> obj ticks) f30-0) (if (< (-> obj damp-period) 0.0) - ((method-of-type smush-control set-zero!) obj) + (set-zero! obj) ) ) (if (>= f30-0 (-> obj duration)) - ((method-of-type smush-control set-zero!) obj) + (set-zero! obj) ) (* (sin (/ (* 65536.0 f28-0) (-> obj period))) @@ -130,11 +130,7 @@ (arg4 float) (arg5 float) ) - (when - (>= - (fabs (* 0.2 (-> obj amp))) - (fabs ((method-of-type smush-control get-no-update) obj)) - ) + (when (>= (fabs (* 0.2 (-> obj amp))) (fabs (get-no-update obj))) (set! (-> obj amp) arg0) (set! (-> obj period) (the float arg1)) (set! (-> obj duration) (the float arg2)) @@ -145,7 +141,3 @@ ) obj ) - - - - diff --git a/test/decompiler/reference/engine/util/sync-info_REF.gc b/test/decompiler/reference/engine/util/sync-info_REF.gc index 3eebc0286e..0a692dd167 100644 --- a/test/decompiler/reference/engine/util/sync-info_REF.gc +++ b/test/decompiler/reference/engine/util/sync-info_REF.gc @@ -196,7 +196,7 @@ ;; definition for method 9 of type sync-info-paused (defmethod dummy-9 sync-info-paused ((obj sync-info-paused) (arg0 float)) - (* ((method-of-type sync-info-paused dummy-11) obj) arg0) + (* (dummy-11 obj) arg0) ) ;; definition for method 13 of type sync-info @@ -337,12 +337,12 @@ ;; definition for method 12 of type sync-info-eased (defmethod dummy-12 sync-info-eased ((obj sync-info-eased) (arg0 float)) - (* ((method-of-type sync-info-eased dummy-13) obj) arg0) + (* (dummy-13 obj) arg0) ) ;; definition for method 12 of type sync-info-paused (defmethod dummy-12 sync-info-paused ((obj sync-info-paused) (arg0 float)) - (* ((method-of-type sync-info-paused dummy-13) obj) arg0) + (* (dummy-13 obj) arg0) ) ;; definition for method 9 of type delayed-rand-float @@ -427,7 +427,7 @@ (arg5 float) (arg6 float) ) - ((method-of-type oscillating-float dummy-9) (-> obj osc) arg0 arg4 arg5 arg6) + (dummy-9 (-> obj osc) arg0 arg4 arg5 arg6) (set! (-> obj max-value) arg1) (set! (-> obj min-value) arg2) (set! (-> obj elasticity) arg3) @@ -437,7 +437,7 @@ ;; definition for method 10 of type bouncing-float (defmethod dummy-10 bouncing-float ((obj bouncing-float) (arg0 float)) - ((method-of-type oscillating-float dummy-10) (-> obj osc) arg0) + (dummy-10 (-> obj osc) arg0) (set! (-> obj state) 0) (when (>= (-> obj osc value) (-> obj max-value)) (set! (-> obj osc value) (-> obj max-value)) @@ -510,7 +510,7 @@ (the-as int (- (-> *display* base-frame-counter) (-> obj start-time))) (-> obj timer) ) - ((method-of-type delayed-rand-vector dummy-10) obj) + (dummy-10 obj) ) (-> obj value) ) @@ -524,7 +524,7 @@ (the-as int (- (-> *display* base-frame-counter) (-> obj start-time))) (-> obj timer) ) - ((method-of-type delayed-rand-vector dummy-10) obj) + (dummy-10 obj) (.svf (&-> (-> obj value) quad) vf0) ) (-> obj value) diff --git a/test/decompiler/reference/kernel/gstring_REF.gc b/test/decompiler/reference/kernel/gstring_REF.gc index 81db96a730..05bed6c444 100644 --- a/test/decompiler/reference/kernel/gstring_REF.gc +++ b/test/decompiler/reference/kernel/gstring_REF.gc @@ -41,7 +41,7 @@ ((allocation symbol) (type-to-make type) (arg0 int) (arg1 string)) (cond (arg1 - (let* ((s2-1 (max ((method-of-type string length) arg1) arg0)) + (let* ((s2-1 (max (length arg1) arg0)) (a0-4 (object-new allocation @@ -277,11 +277,7 @@ ;; definition for function string a data i) (-> b data i)) @@ -298,11 +294,7 @@ ;; definition for function string>? (defun string>? ((a string) (b string)) - (let - ((len - (min ((method-of-type string length) a) ((method-of-type string length) b)) - ) - ) + (let ((len (min (length a) (length b)))) (dotimes (i len) (cond ((< (-> a data i) (-> b data i)) @@ -319,11 +311,7 @@ ;; definition for function string<=? (defun string<=? ((a string) (b string)) - (let - ((len - (min ((method-of-type string length) a) ((method-of-type string length) b)) - ) - ) + (let ((len (min (length a) (length b)))) (dotimes (i len) (cond ((< (-> a data i) (-> b data i)) @@ -340,11 +328,7 @@ ;; definition for function string>=? (defun string>=? ((a string) (b string)) - (let - ((len - (min ((method-of-type string length) a) ((method-of-type string length) b)) - ) - ) + (let ((len (min (length a) (length b)))) (dotimes (i len) (cond ((< (-> a data i) (-> b data i)) @@ -437,8 +421,8 @@ ;; definition for function string-strip-trailing-whitespace! (defun string-strip-trailing-whitespace! ((str string)) - (when (nonzero? ((method-of-type string length) str)) - (let ((ptr (&+ (-> str data) (+ ((method-of-type string length) str) -1)))) + (when (nonzero? (length str)) + (let ((ptr (&+ (-> str data) (+ (length str) -1)))) (while (and (>= (the-as int ptr) (the-as int (-> str data))) diff --git a/test/decompiler/test_FormExpressionBuild.cpp b/test/decompiler/test_FormExpressionBuild.cpp index d0387e8c6e..70226549cb 100644 --- a/test/decompiler/test_FormExpressionBuild.cpp +++ b/test/decompiler/test_FormExpressionBuild.cpp @@ -2467,19 +2467,15 @@ TEST_F(FormRegressionTest, StringLt) { std::string type = "(function string string symbol)"; std::string expected = "(begin\n" - " (let\n" - " ((s4-1\n" - " (min\n" - " ((method-of-type string length) arg0)\n" - " ((method-of-type string length) arg1)\n" - " )\n" - " )\n" - " )\n" - " (dotimes\n" - " (v1-4 s4-1)\n" + " (let ((s4-1 (min (length arg0) (length arg1))))\n" + " (dotimes (v1-4 s4-1)\n" " (cond\n" - " ((< (-> arg0 data v1-4) (-> arg1 data v1-4)) (return #t))\n" - " ((< (-> arg1 data v1-4) (-> arg0 data v1-4)) (return #f))\n" + " ((< (-> arg0 data v1-4) (-> arg1 data v1-4))\n" + " (return #t)\n" + " )\n" + " ((< (-> arg1 data v1-4) (-> arg0 data v1-4))\n" + " (return #f)\n" + " )\n" " )\n" " )\n" " )\n" @@ -2714,9 +2710,8 @@ TEST_F(FormRegressionTest, StripStripTrailingWhitespace) { std::string type = "(function string symbol)"; std::string expected = "(begin\n" - " (when (nonzero? ((method-of-type string length) arg0))\n" - " (let\n" - " ((v1-6 (&+ (-> arg0 data) (+ ((method-of-type string length) arg0) -1))))\n" + " (when (nonzero? (length arg0))\n" + " (let ((v1-6 (&+ (-> arg0 data) (+ (length arg0) -1))))\n" " (while\n" " (and\n" " (>= (the-as int v1-6) (the-as int (-> arg0 data)))\n"