AdeptLanguage / Adept

The Adept Programming Language
GNU General Public License v3.0
120 stars 8 forks source link

Use Adept code outside of Adept #293

Closed ghost closed 6 months ago

ghost commented 7 months ago

For example, I want to take Adept's JSON.adept and turn it into a shared library that could be called from C. I know that I could do this, but what I don't know is if it will work or not, given the complex scoping rule of the current ownership-based memory management used by JSON.adept.

IsaacShelton commented 6 months ago

There are some basic examples at https://github.com/IsaacShelton/AdeptWorkingWithC (although the syntax is a little outdated in style)

To take something like JSON.adept and turn it a dynamically linked C library, would be difficult because it wasn't designed to interop with C code.

There are implicit management function calls when JSON values are passed, assigned, and when they go out of scope (also they are expected to be zero-initialized), so mimicking them in C would be pretty tedious. Also the functions/method rely on function overloading so each would have to have a uniquely named wrapper or external function name.

You would have to do something like:

pragma project_name my_json
pragma options '--shared "" ""'

external func JSON_new_undefined() JSON {
    return JSON\undefined()
}

external func JSON_new_null() JSON {
    return JSON\null()
}

external func JSON_new_bool(value bool) JSON {
    return JSON(value)
}

external func JSON_new_number(value double) JSON {
    return JSON(value)
}

external func JSON_new_string_owned(owned_content *ubyte) JSON {
    length usize = strlen(owned_content)
    return JSON(String(owned_content, length, length + 1, ::GIVEN))
}

external func JSON_new_string_view(reference_content *ubyte) JSON {
    return JSON(StringView(reference_content))
}

external func JSON_new_array(values *JSON, count usize) JSON {
    return JSON(__initializer_list__(values, count))
}

alias JSONField = <String, JSON> AsymmetricPair

external func JSON_new_object(keys_references *ubyte, values *JSON, count usize) JSON {
    result POD JSON = JSON\object()
    repeat static count {
        result.add(StringView(keys_references[idx]), values[idx])
    }
    return result.commit()
}

external func JSON_assign(dest *JSON, src POD JSON) {
    dest.__assign__(src)
}

external func JSON_destroy(json *JSON) {
    json.__defer__()
}

external func JSON_pass(json POD JSON) JSON {
    return __pass__(json)
}

external func JSON_serialize(json POD JSON) *ubyte {
    return JSON\serialize(json)
}

external func JSON_deserialize(content *ubyte) JSON {
    return JSON\deserialize(StringView(content))
}

external func JSON_to_string(json POD JSON) *ubyte {
    return toString(json).cstr()
}

external func JSON_from_string(content *ubyte) JSON {
    return JSONFromString(StringView(content))
}
#ifndef MY_JSON_H_INCLUDED
#define MY_JSON_H_INCLUDED

#include <stdint.h>
#include <stdbool.h>

typedef struct {
    void *internal_data;
} json_t;

json_t JSON_new_undefined();
json_t JSON_new_null();
json_t JSON_new_bool(bool value);
json_t JSON_new_number(double value);
json_t JSON_new_string_owned(char *owned_content);
json_t JSON_new_string_view(const char *reference_content);
json_t JSON_new_array(json_t *values, uint64_t count);
json_t JSON_new_object(const char *const *reference_keys, json_t *values, size_t count);
void JSON_assign(json_t *dest, json_t src);
void JSON_destroy(json_t *json);
json_t JSON_pass(json_t json);
char *JSON_serialize(json_t *json);
json_t JSON_deserialize(const char *content);
char *JSON_to_string(json_t *json);
json_t JSON_from_string(const char *content);

#endif // MY_JSON_H_INCLUDED
adept my_json.adept
gcc main.c "my_json.dll" -o main

Also this doesn't include the methods for accessing the items since they return adept data structures, so they would have to be further wrapped and unwrapped in order to interface with C.

Using it correctly would be pretty hard though still, you'd have to do something like:

#include "my_json.h"

int main(){
    json_t settings;
    memset(&settings, 0, sizeof settings);
    JSON_assign(&settings, JSON_from_string("{\"url\":\"example.com\"}"));

    // TODO: Use the loaded settings

    JSON_destroy(&settings);
}