OR-1 dataflow CPU sketch
1#include "./language.h"
2#include "tree_sitter/api.h"
3
4#include <napi.h>
5#include <string>
6
7using namespace Napi;
8
9namespace node_tree_sitter::language_methods {
10
11/*
12 tstag() {
13 b2sum -l64 <(printf tree-sitter) <(printf "$1") | \
14 awk '{printf "0x" toupper($1) (NR == 1 ? ", " : "\n")}'
15 }
16 tstag language # => 0x8AF2E5212AD58ABF, 0xD5006CAD83ABBA16
17*/
18const napi_type_tag LANGUAGE_TYPE_TAG = {
19 0x8AF2E5212AD58ABF, 0xD5006CAD83ABBA16
20};
21
22const TSLanguage *UnwrapLanguage(Napi::Value value) {
23 Napi::Env env = value.Env();
24
25 if (value.IsObject()) {
26 value = value.As<Object>()["language"];
27 }
28
29 auto arg = value.As<External<const TSLanguage>>();
30 if (arg.IsExternal() && arg.CheckTypeTag(&LANGUAGE_TYPE_TAG)) {
31 const TSLanguage *language = arg.Data();
32 if (language != nullptr) {
33 uint16_t version = ts_language_version(language);
34 if (
35 version < TREE_SITTER_MIN_COMPATIBLE_LANGUAGE_VERSION ||
36 version > TREE_SITTER_LANGUAGE_VERSION
37 ) {
38 std::string message =
39 "Incompatible language version. Compatible range: " +
40 std::to_string(TREE_SITTER_MIN_COMPATIBLE_LANGUAGE_VERSION) + " - " +
41 std::to_string(TREE_SITTER_LANGUAGE_VERSION) + ". Got: " +
42 std::to_string(ts_language_version(language));
43 RangeError::New(env, message.c_str());
44 return nullptr;
45 }
46 return language;
47 }
48 }
49 throw TypeError::New(env, "Invalid language object");
50}
51
52namespace {
53
54Napi::Value GetNodeTypeNamesById(const Napi::CallbackInfo &info) {
55 Env env = info.Env();
56
57 const TSLanguage *language = UnwrapLanguage(info[0]);
58 if (language == nullptr) {
59 return env.Undefined();
60 }
61
62 auto result = Array::New(env);
63 uint32_t length = ts_language_symbol_count(language);
64 for (uint32_t i = 0; i < length; i++) {
65 const char *name = ts_language_symbol_name(language, i);
66 TSSymbolType type = ts_language_symbol_type(language, i);
67 if (type == TSSymbolTypeRegular) {
68 result[i] = String::New(env, name);
69 } else {
70 result[i] = env.Null();
71 }
72 }
73
74 return result;
75}
76
77Napi::Value GetNodeFieldNamesById(const Napi::CallbackInfo &info) {
78 Env env = info.Env();
79
80 const TSLanguage *language = UnwrapLanguage(info[0]);
81 if (language == nullptr) {
82 return env.Undefined();
83 }
84
85 auto result = Array::New(env);
86 uint32_t length = ts_language_field_count(language);
87 for (uint32_t i = 0; i < length + 1; i++) {
88 const char *name = ts_language_field_name_for_id(language, i);
89 if (name != nullptr) {
90 result[i] = String::New(env, name);
91 } else {
92 result[i] = env.Null();
93 }
94 }
95
96 return result;
97}
98
99} // namespace
100
101void Init(Napi::Env env, Napi::Object exports) {
102 exports["getNodeTypeNamesById"] = Function::New(env, GetNodeTypeNamesById);
103 exports["getNodeFieldNamesById"] = Function::New(env, GetNodeFieldNamesById);
104}
105
106} // namespace node_tree_sitter::language_methods