nk 1.0.0
C++ Numerical Computing Runtime
Loading...
Searching...
No Matches
value/include/nk/value/object.hpp
1// include/nk/value/object.hpp
2//
3// Engine object model — see object_model.md. A class instance is a
4// ValueType::OBJECT heap value carrying a class name + shared
5// ObjectState. The class itself (methods, property hooks, attributes)
6// is registered once with the Engine as a BuiltinClass.
7#pragma once
8
9#include <nk/value/span.hpp>
10#include <nk/value/value.hpp>
11
12#include <functional>
13#include <map>
14#include <memory>
15#include <memory_resource>
16#include <string>
17#include <unordered_map>
18#include <vector>
19
20namespace nk {
21
22struct CallContext; // defined in types.hpp; used only by-reference here
23struct UserFunction; // defined in types.hpp; held by shared_ptr in BuiltinClass
24
25// ============================================================
26// NativePayload — opaque C++ instance state for builtin classes
27// (a hash for containers.Map, columns for table, …). Subclassed per
28// class. `clone()` is used only for VALUE classes (deep copy on COW);
29// handle classes share the payload and never clone it.
30// ============================================================
32{
33 virtual ~NativePayload() = default;
34 virtual std::shared_ptr<NativePayload> clone() const = 0;
35};
36
37// ============================================================
38// ObjectState — instance state, shared via shared_ptr. The handle/value
39// pivot lives in HeapObject::clone(): a handle object shares this state
40// across copies; a value object deep-copies it. See object_model.md §1.
41// ============================================================
42struct ObjectState
43{
44 std::pmr::map<std::string, Value> props; // MATLAB-visible properties
45 std::shared_ptr<NativePayload> native; // optional opaque payload
46 std::string enumName; // enumeration member name ("" if not an enum)
47
48 explicit ObjectState(std::pmr::memory_resource *mr) : props(mr) {}
49
50 // Deep copy for value-class COW. props copied by value; native via
51 // its own clone().
52 std::shared_ptr<ObjectState> deepCopy(std::pmr::memory_resource *mr) const
53 {
54 auto s = std::make_shared<ObjectState>(mr);
55 for (const auto &[k, v] : props)
56 s->props.emplace(k, v);
57 s->native = native ? native->clone() : nullptr;
58 s->enumName = enumName;
59 return s;
60 }
61};
62
63// A class method / constructor body. `self` is the receiver (the object
64// the method dispatches on); constructors take no self and return the
65// new object via the BuiltinClass::construct functor instead.
66using ObjectMethod = std::function<void(Value &self, Span<const Value> args,
67 size_t nargout, Span<Value> outs,
68 CallContext &ctx)>;
69
70// Per-member reflection metadata, mirrored from the classdef into the runtime
71// class so introspection (metaclass/meta.property/meta.method) can report it
72// without reaching back into the compiler-side ClassDefDesc.
74{
75 std::string name;
76 std::string getAccess = "public"; // public | private | protected
77 std::string setAccess = "public"; // (+ immutable on the set side)
78 bool isConstant = false;
79 bool isDependent = false;
80};
82{
83 std::string name;
84 bool isStatic = false;
85 std::string access = "public";
86 bool isAbstract = false;
87};
88
89// ============================================================
90// BuiltinClass — one registry entry. Instances reference it by name.
91// ============================================================
93{
94 std::string name; // registry key, e.g. "containers.Map"
95 bool isHandle = false;
96 bool isSealed = false; // classdef (Sealed) — reflection
97 bool isAbstract = false; // has an unimplemented Abstract member
98 std::vector<std::string> superclasses; // for isa()
99
100 // Constructor: ClassName(args) -> object Value.
101 std::function<Value(Span<const Value> args, CallContext &ctx)> construct;
102
103 // Methods: obj.m(args) / m(obj, args).
104 std::unordered_map<std::string, ObjectMethod> methods;
105
106 // Property names (for properties(), disp). Access goes through the
107 // hooks below — v1 ships hooks only (no default ObjectState.props
108 // backing until a class needs it; see object_model.md §2).
109 std::vector<std::string> propNames;
110 std::function<bool(const Value &self, const std::string &name,
111 Value &out, CallContext &ctx)> propGet;
112 std::function<bool(Value &self, const std::string &name,
113 const Value &val, CallContext &ctx)> propSet;
114
115 // Optional overloads (empty = default / error).
116 // subsref: obj(i…) read — args = the subscripts; result in out[0].
117 // subsasgn: obj(i…) = v — args = [subscripts…, value] (value last);
118 // mutates `self` in place via objectStateMut() (so the
119 // value/handle COW rule applies); out is unused.
120 ObjectMethod subsref;
121 ObjectMethod subsasgn;
122 std::function<std::string(const Value &self)> dispText; // disp/display
123 std::unordered_map<std::string, ObjectMethod> ops; // "plus","eq",…
124 // Members declared `Hidden` — still usable, but omitted from
125 // properties() / methods() introspection listings.
126 std::vector<std::string> hidden;
127 // Reflection metadata for metaclass()/meta.property/meta.method. Populated
128 // for classdef-defined classes; left empty for native builtin classes
129 // (containers.Map, …), whose introspection falls back to propNames/methods.
130 std::vector<PropMeta> propMeta;
131 std::vector<MethodMeta> methodMeta;
132 // classdef instance methods as UserFunctions (name → uf), so the VM can
133 // compile + run their bodies as native frames instead of the C++ hook.
134 // Absent for native builtin-class methods (containers.Map, …), which keep
135 // the hook. `uf->name` is the declaring-class-qualified "Class>method".
136 std::unordered_map<std::string, std::shared_ptr<const UserFunction>> methodFns;
137};
138
139} // namespace nk
Core MATLAB-compatible multidimensional array and scalar value type.
Definition value.hpp:61