Using the Embedded Сompiler
This section covers how to integrate the built-in compiler and use the API.
JavaScript
Install the NPM Package
- Note
- I haven’t published the package to npmjs. Instead, it’s hosted in a public GitHub repository. You’ll need to:
- Add the GitHub repository to your
.npmrc
under the NAMESPACE
vladimirshaleev
(GitHub repo setup).
- Authenticate with GitHub to access GitHub repositories (GitHub auth).
- Create an empty project (e.g., in a folder like
test-js
). Inside it, generate a package.json by running npm init
.
- Then, add the idlc npm package as a dependency:
@bash
npm install @vladimirshaleev/idlc
After this, your package.json
might look like this:
@json
{
"name": "test-js",
"main": "index.js",
"type": "module",
"description": "",
"dependencies": {
"@vladimirshaleev/idlc": "^1.5.12"
}
}
Using the Embedded Compiler
Now, in index.js
, you can add the following code:
@javascript
import idlcInit from '@vladimirshaleev/idlc';
const idlc = await idlcInit();
const compiledCodes = {};
const options = new idlc.Options;
options.warningsAsErrors = false;
options.writer = function (source) {
compiledCodes[source.name] = source.data;
};
const source = {
name: "myfile",
data: `
@ API Sample
api Sample
@ Sum of all values.
@ Return sum. [return]
func Sum {Float32}
arg Values {Float32} [const,array(Count)] @ Array of values.
arg Count {Uint32} @ Count of {Values}.
`
};
const compiler = new idlc.Compiler;
const result = compiler.compile(idlc.Generator.C, undefined, [source], options);
result.messages.forEach(message => {
const prefx = `${message.isError ? "error" : "warning"}`;
const code = `${message.status.value < 2000 ? "W" : "E"}${message.status.value}`;
const place = `${message.filename}:${message.line}:${message.column}`;
console.log(`${prefx} [${code}]: ${message.message} at ${place}`)
});
result.delete();
compiler.delete();
options.delete();
console.log(`total files ${Object.keys(compiledCodes).length}`);
for (const [filename, code] of Object.entries(compiledCodes)) {
console.log(`file: ${filename}`);
console.log(`code:\n${code}`);
}
As we can see, the JavaScript API created by IDLC can work with lambda expressions, closures, properties, and JavaScript arrays.
C
Install the Vcpkg Port
The port is located in a custom registry. To add the custom registry, include the following registry with the idlc port in your vcpkg-configuration.json
(in the same directory as your vcpkg.json
):
@json
{
"$schema": "https://raw.githubusercontent.com/microsoft/vcpkg-tool/main/docs/vcpkg-configuration.schema.json",
"default-registry": {
"kind": "git",
"baseline": "0cf34c184ce990471435b5b9c92edcf7424930b1",
"repository": "https://github.com/microsoft/vcpkg"
},
"registries": [
{
"kind": "git",
"baseline": "124f27dfa5e457147722d976eeecba8332937f2f",
"reference": "vcpkg-registry",
"repository": "https://github.com/VladimirShaleev/idlc",
"packages": [
"idlc"
]
}
]
}
After that, you can add the dependency to your vcpkg.json
:
@json
{
"$schema": "https://raw.githubusercontent.com/microsoft/vcpkg-tool/main/docs/vcpkg.schema.json",
"name": "test-c",
"dependencies": [
"idlc"
]
}
- Note
- For information on using vcpkg, refer to the official website
Add the following configuration to your CMakeLists.txt
:
@cmake
cmake_minimum_required(VERSION 3.16)
project(test-c CXX)
find_package(idlc CONFIG REQUIRED)
add_executable(test-c main.cpp)
target_link_libraries(test-c PRIVATE idlc::idl)
target_compile_features(test-c PRIVATE cxx_std_17)
Using the Embedded Compiler
Now you can add the following code to main.cpp
, which is functionally similar to the code above for JavaScript:
@cpp
#include <iostream>
#include <vector>
#include <map>
{
{
}
};
int main()
{
int exitCode{};
std::map<std::string, std::string> compiledCodes{};
try
{
{
auto &compiledCodes = *static_cast<std::map<std::string, std::string>*>(data);
compiledCodes[source->
name] = std::string(source->
data, source->
size);
}, &compiledCodes);
constexpr char sourceCode[] = R"(
@ API Sample
api Sample
@ Sum of all values.
@ Return sum. [return]
func Sum {Float32}
arg Values {Float32} [const,array(Count)] @ Array of values.
arg Count {Uint32} @ Count of {Values}.
)";
source.
data = sourceCode;
std::vector<idl_message_t> messages;
messages.resize(size_t(messageCount));
for (const auto &message : messages)
{
auto& stream = message.is_error ? std::cerr : std::cout;
stream << (message.is_error ? "error" : "warning") << " [";
stream << ((int)message.status >=
IDL_STATUS_E2001 ?
'E' :
'W') << (
int)message.status <<
"]: ";
stream << message.message << " at ";
stream << message.filename << ':' << message.line << ':' << message.column << std::endl;
}
}
catch (const std::exception &exc)
{
std::cerr << exc.what() << std::endl;
exitCode = 1;
}
std::cout << "total files " << compiledCodes.size() << std::endl;
for (const auto &[filename, code] : compiledCodes)
{
std::cout << "file: " << filename << std::endl;
std::cout << "code:" << std::endl << code << std::endl;
}
return exitCode;
}
idl_result_t
Result codes.
Definition idl-results.h:23
@ IDL_GENERATOR_C
C generator.
Definition idl.h:50
@ IDL_RESULT_SUCCESS
Indicates success (this is not an error).
Definition idl-results.h:24
@ IDL_STATUS_E2001
Unexpected character.
Definition idl-results.h:43
void idl_compiler_destroy(idl_compiler_t compiler)
Releases compiler instance.
void idl_options_destroy(idl_options_t options)
Releases options instance.
idl_bool_t idl_compilation_result_has_errors(idl_compilation_result_t compilation_result)
Checking if there were errors.
void idl_options_set_writer(idl_options_t options, idl_write_callback_t callback, idl_data_t data)
Set write callback.
void idl_compilation_result_destroy(idl_compilation_result_t compilation_result)
Releases compilation result instance.
void idl_options_set_warnings_as_errors(idl_options_t options, idl_bool_t enable)
Set warning handling setting.
void idl_compilation_result_get_messages(idl_compilation_result_t compilation_result, idl_uint32_t *message_count, idl_message_t *messages)
Returns messages with warnings and errors.
idl_result_t idl_compiler_create(idl_compiler_t *compiler)
Creates new compiler instance.
idl_result_t idl_compiler_compile(idl_compiler_t compiler, idl_generator_t generator, idl_utf8_t file, idl_uint32_t source_count, const idl_source_t *sources, idl_options_t options, idl_compilation_result_t *result)
Compile IDL.
idl_utf8_t idl_result_to_string(idl_result_t result)
Converts error code to descriptive string.
idl_result_t idl_options_create(idl_options_t *options)
Creates new options instance.
void * idl_data_t
pointer to data.
Definition idl-platform.h:125
struct _idl_compilation_result * idl_compilation_result_t
Compilation result.
Definition idl-types.h:32
struct _idl_options * idl_options_t
Compilation options.
Definition idl-types.h:33
uint32_t idl_uint32_t
32 bit unsigned integer.
Definition idl-platform.h:119
struct _idl_compiler * idl_compiler_t
Compiler interface.
Definition idl-types.h:34
Source code.
Definition idl-options.h:22
idl_uint32_t size
Size of idl_source_t::data in bytes.
Definition idl-options.h:25
idl_utf8_t name
Source name (used to resolve imports).
Definition idl-options.h:23
const idl_char_t * data
Source code.
Definition idl-options.h:24
Next Steps
To explore all the compiler's capabilities, check out the documentation at the link below.