From 68b0ccc460781f9618a6a92d4de772e2d68ebb09 Mon Sep 17 00:00:00 2001 From: Tim Morgan Date: Wed, 25 Dec 2024 09:00:20 -0600 Subject: [PATCH] Add actual File object type This keeps us from having to cast an IoObject to a FileObject, which is a subclass, which is undefined behavior. --- include/natalie/file_object.hpp | 5 ++++- include/natalie/io_object.hpp | 3 +++ include/natalie/object.hpp | 3 ++- include/natalie/object_type.hpp | 1 + src/natalie.cpp | 2 +- src/object.cpp | 6 +++++- 6 files changed, 16 insertions(+), 4 deletions(-) diff --git a/include/natalie/file_object.hpp b/include/natalie/file_object.hpp index ce939f1403..a8fed04a00 100644 --- a/include/natalie/file_object.hpp +++ b/include/natalie/file_object.hpp @@ -17,7 +17,10 @@ namespace Natalie { class FileObject : public IoObject { public: FileObject() - : IoObject { GlobalEnv::the()->Object()->const_fetch("File"_s)->as_class() } { } + : FileObject { GlobalEnv::the()->Object()->const_fetch("File"_s)->as_class() } { } + + FileObject(ClassObject *klass) + : IoObject { Object::Type::File, klass } { } Value initialize(Env *, Args &&, Block *); diff --git a/include/natalie/io_object.hpp b/include/natalie/io_object.hpp index a68951869e..cc8a2d3c3b 100644 --- a/include/natalie/io_object.hpp +++ b/include/natalie/io_object.hpp @@ -23,6 +23,9 @@ class IoObject : public Object { IoObject(ClassObject *klass) : Object { Object::Type::Io, klass } { } + IoObject(Type type, ClassObject *klass) + : Object { type, klass } { } + IoObject(int fileno) : Object { Object::Type::Io, GlobalEnv::the()->Object()->const_fetch("IO"_s)->as_class() } , m_sync { fileno == STDERR_FILENO } { diff --git a/include/natalie/object.hpp b/include/natalie/object.hpp index d5f7413193..1f13387bd0 100644 --- a/include/natalie/object.hpp +++ b/include/natalie/object.hpp @@ -130,7 +130,8 @@ class Object : public Cell { bool is_float() const { return m_type == Type::Float; } bool is_hash() const { return m_type == Type::Hash; } bool is_integer() const { return m_type == Type::Integer; } - bool is_io() const { return m_type == Type::Io; } + bool is_io() const { return m_type == Type::Io || m_type == Type::File; } + bool is_file() const { return m_type == Type::File; } bool is_file_stat() const { return m_type == Type::FileStat; } bool is_match_data() const { return m_type == Type::MatchData; } bool is_proc() const { return m_type == Type::Proc; } diff --git a/include/natalie/object_type.hpp b/include/natalie/object_type.hpp index 04cf7258c0..3db2d038af 100644 --- a/include/natalie/object_type.hpp +++ b/include/natalie/object_type.hpp @@ -16,6 +16,7 @@ enum class ObjectType { Exception, False, Fiber, + File, FileStat, Float, Hash, diff --git a/src/natalie.cpp b/src/natalie.cpp index 844ad19bf8..2906053d3b 100644 --- a/src/natalie.cpp +++ b/src/natalie.cpp @@ -163,7 +163,7 @@ Env *build_top_env() { IO->include_once(env, Enumerable); IoObject::build_constants(env, IO); - ClassObject *File = IO->subclass(env, "File"); + ClassObject *File = IO->subclass(env, "File", Object::Type::File); Object->const_set("File"_s, File); File->include_once(env, Enumerable); diff --git a/src/object.cpp b/src/object.cpp index bd877aba04..86d17defb2 100644 --- a/src/object.cpp +++ b/src/object.cpp @@ -62,6 +62,10 @@ Value Object::create(Env *env, ClassObject *klass) { obj = new IoObject { klass }; break; + case Object::Type::File: + obj = new FileObject { klass }; + break; + case Object::Type::MatchData: obj = new MatchDataObject { klass }; break; @@ -355,7 +359,7 @@ const IoObject *Object::as_io() const { } FileObject *Object::as_file() { - assert(is_io()); + assert(is_file()); return static_cast(this); }