Skip to content

Commit e12c78d

Browse files
committed
feat: JavaScript api
1 parent 5ccf929 commit e12c78d

File tree

2 files changed

+807
-0
lines changed

2 files changed

+807
-0
lines changed

include/mrdox/Support/JavaScript.hpp

+348
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,348 @@
1+
//
2+
// Licensed under the Apache License v2.0 with LLVM Exceptions.
3+
// See https://llvm.org/LICENSE.txt for license information.
4+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5+
//
6+
// Copyright (c) 2023 Vinnie Falco (vinnie.falco@gmail.com)
7+
//
8+
// Official repository: https://github.com/cppalliance/mrdox
9+
//
10+
11+
#ifndef MRDOX_SUPPORT_JAVASCRIPT_HPP
12+
#define MRDOX_SUPPORT_JAVASCRIPT_HPP
13+
14+
#include <mrdox/Platform.hpp>
15+
#include <mrdox/Support/Error.hpp>
16+
#include <mrdox/Support/Expected.hpp>
17+
#include <cstdlib>
18+
#include <string_view>
19+
20+
namespace clang {
21+
namespace mrdox {
22+
namespace js {
23+
24+
struct Access;
25+
class Context;
26+
class Scope;
27+
28+
class Array;
29+
class Boolean;
30+
class Object;
31+
class String;
32+
class Value;
33+
34+
//------------------------------------------------
35+
36+
class Prop
37+
{
38+
unsigned int index_;
39+
std::string_view name_;
40+
41+
public:
42+
constexpr Prop(std::string_view name) noexcept
43+
: index_(0)
44+
, name_(name)
45+
{
46+
}
47+
48+
constexpr Prop(unsigned int index) noexcept
49+
: index_(index)
50+
{
51+
}
52+
53+
constexpr bool isIndex() const noexcept
54+
{
55+
return name_.empty();
56+
}
57+
};
58+
59+
//------------------------------------------------
60+
61+
/** A reference to an instance of a JavaScript interpreter.
62+
*/
63+
class Context
64+
{
65+
struct Impl;
66+
67+
Impl* impl_;
68+
69+
friend struct Access;
70+
71+
public:
72+
/** Copy assignment.
73+
*/
74+
Context& operator=(Context const&) = delete;
75+
76+
/** Destructor.
77+
*/
78+
MRDOX_DECL ~Context();
79+
80+
/** Constructor.
81+
*/
82+
MRDOX_DECL Context();
83+
84+
/** Constructor.
85+
*/
86+
MRDOX_DECL Context(Context const&) noexcept;
87+
};
88+
89+
//------------------------------------------------
90+
91+
struct Arg
92+
{
93+
void (*push)(Arg const&, Scope&);
94+
95+
int number = 0;
96+
char const* data = nullptr;
97+
std::size_t size = 0;
98+
unsigned int index = 0; // of object
99+
100+
Arg() = default;
101+
102+
Arg(std::string_view s) noexcept
103+
: push(&push_lstring)
104+
, data(s.data())
105+
, size(s.size())
106+
{
107+
}
108+
109+
MRDOX_DECL Arg(Value const& value) noexcept;
110+
111+
MRDOX_DECL static void push_Value(Arg const&, Scope&);
112+
MRDOX_DECL static void push_lstring(Arg const&, Scope&);
113+
};
114+
115+
//------------------------------------------------
116+
117+
class Scope
118+
{
119+
Context ctx_;
120+
std::size_t refs_;
121+
int top_;
122+
123+
friend struct Access;
124+
125+
void reset();
126+
127+
public:
128+
MRDOX_DECL
129+
Scope(Context const& ctx) noexcept;
130+
131+
MRDOX_DECL
132+
~Scope();
133+
134+
/** Run a script.
135+
*/
136+
MRDOX_DECL Error script(std::string_view jsCode);
137+
138+
/** Return a global object if it exists.
139+
*/
140+
MRDOX_DECL
141+
Expected<Object>
142+
tryGetGlobal(std::string_view name);
143+
144+
/** Return a global object if it exists.
145+
*/
146+
MRDOX_DECL
147+
Object
148+
getGlobal(std::string_view name);
149+
150+
Expected<Value> call();
151+
};
152+
153+
//------------------------------------------------
154+
155+
/** Types of values.
156+
*/
157+
enum class Type
158+
{
159+
undefined = 1,
160+
null,
161+
boolean,
162+
number,
163+
string,
164+
object
165+
};
166+
167+
/** An ECMAScript value.
168+
*/
169+
class Value
170+
{
171+
protected:
172+
Scope* scope_;
173+
int idx_;
174+
175+
friend struct Access;
176+
177+
Value(int, Scope&) noexcept;
178+
179+
public:
180+
MRDOX_DECL ~Value();
181+
MRDOX_DECL Value() noexcept;
182+
MRDOX_DECL Value(Value const&);
183+
MRDOX_DECL Value(Value&&) noexcept;
184+
MRDOX_DECL Value& operator=(Value const&);
185+
MRDOX_DECL Value& operator=(Value&&) noexcept;
186+
187+
MRDOX_DECL Type type() const noexcept;
188+
189+
bool isUndefined() const noexcept
190+
{
191+
return type() == Type::undefined;
192+
}
193+
194+
bool isNull() const noexcept
195+
{
196+
return type() == Type::null;
197+
}
198+
199+
bool isBoolean() const noexcept
200+
{
201+
return type() == Type::boolean;
202+
}
203+
204+
bool isNumber() const noexcept
205+
{
206+
return type() == Type::number;
207+
}
208+
209+
bool isString() const noexcept
210+
{
211+
return type() == Type::string;
212+
}
213+
214+
bool isObject() const noexcept
215+
{
216+
return type() == Type::object;
217+
}
218+
219+
/** Call a function.
220+
*/
221+
template<class... Args>
222+
friend
223+
Expected<Value>
224+
tryCall(
225+
Value const& fn,
226+
Args&&... args);
227+
228+
/** Call a function.
229+
*/
230+
template<class... Args>
231+
friend
232+
Value
233+
call(
234+
Value const& fn,
235+
Args&&... args);
236+
237+
private:
238+
MRDOX_DECL
239+
Expected<Value>
240+
callImpl(
241+
Arg const* data,
242+
std::size_t size) const;
243+
};
244+
245+
template<class... Args>
246+
Expected<Value>
247+
tryCall(
248+
Value const& fn,
249+
Args&&... args)
250+
{
251+
std::array<Arg, sizeof...(args)> va{ Arg(args)... };
252+
return fn.callImpl(va.data(), va.size());
253+
}
254+
255+
/** Call a function.
256+
*/
257+
template<class... Args>
258+
Value
259+
call(
260+
Value const& fn,
261+
Args&&... args)
262+
{
263+
auto result = tryCall(fn,
264+
std::forward<Args>(args)...);
265+
if(result)
266+
throw result;
267+
}
268+
269+
//------------------------------------------------
270+
271+
/** An ECMAScript Object.
272+
*/
273+
class String : public Value
274+
{
275+
friend struct Access;
276+
277+
String(int idx, Scope&) noexcept;
278+
279+
public:
280+
MRDOX_DECL String(Value value);
281+
MRDOX_DECL String& operator=(Value value);
282+
MRDOX_DECL explicit String(std::string_view s);
283+
284+
MRDOX_DECL std::string_view get() const noexcept;
285+
286+
std::string_view operator*() const noexcept
287+
{
288+
return get();
289+
}
290+
291+
operator std::string_view() const noexcept
292+
{
293+
return get();
294+
}
295+
};
296+
297+
//------------------------------------------------
298+
299+
/** An ECMAScript Object.
300+
*/
301+
class Object : public Value
302+
{
303+
friend struct Access;
304+
305+
Object(int idx, Scope&) noexcept;
306+
307+
Expected<Value> callImpl(
308+
std::string_view name,
309+
Arg const* data,
310+
std::size_t size) const;
311+
312+
public:
313+
MRDOX_DECL Object(Value value);
314+
MRDOX_DECL Object& operator=(Value value);
315+
MRDOX_DECL explicit Object(Scope& scope);
316+
317+
/** Call a member or function.
318+
*/
319+
template<class... Args>
320+
Expected<Value>
321+
tryCall(
322+
std::string_view name,
323+
Args&&... args) const
324+
{
325+
std::array<Arg, sizeof...(args)> va{ Arg(args)... };
326+
return callImpl(name, va.data(), va.size());
327+
}
328+
329+
/** Call a member or function.
330+
*/
331+
template<class... Args>
332+
Value
333+
call(
334+
std::string_view name,
335+
Args&&... args) const
336+
{
337+
auto result = tryCall(name, std::forward<Args>(args)...);
338+
if(! result)
339+
throw result;
340+
return *result;
341+
}
342+
};
343+
344+
} // js
345+
} // mrdox
346+
} // clang
347+
348+
#endif

0 commit comments

Comments
 (0)