#ifdef _WIN32
#ifndef NOMINMAX
#define NOMINMAX
#endif // NOMINMAX
#include
#endif
#include
#include
#include
#include
#include
#include
#include
#ifndef _WIN32
#include
#endif
#ifdef _WIN32
#define stat _stat
#if !defined S_ISDIR
#define S_ISDIR(m) (((m) & _S_IFDIR) == _S_IFDIR)
#endif
#endif
namespace LCompilers::LPython {
void get_executable_path(std::string &executable_path, int &dirname_length)
{
#ifdef HAVE_WHEREAMI
int length;
length = wai_getExecutablePath(NULL, 0, &dirname_length);
if (length > 0) {
std::string path(length+1, '\0');
wai_getExecutablePath(&path[0], length, &dirname_length);
executable_path = path;
if (executable_path[executable_path.size()-1] == '\0') {
executable_path = executable_path.substr(0,executable_path.size()-1);
}
} else {
throw LCompilersException("Cannot determine executable path.");
}
#else
executable_path = "src/bin/lpython.js";
dirname_length = 7;
#endif
}
std::string get_runtime_library_dir()
{
#ifdef HAVE_BUILD_TO_WASM
return "asset_dir";
#endif
char *env_p = std::getenv("LFORTRAN_RUNTIME_LIBRARY_DIR");
if (env_p) return env_p;
std::string path;
int dirname_length;
get_executable_path(path, dirname_length);
std::string dirname = path.substr(0,dirname_length);
if ( endswith(dirname, "src/bin")
|| endswith(dirname, "src\\bin")
|| endswith(dirname, "SRC\\BIN")) {
// Development version
return dirname + "/../runtime";
} else if (endswith(dirname, "src/lpython/tests") ||
endswith(to_lower(dirname), "src\\lpython\\tests")) {
// CTest Tests
return dirname + "/../../runtime";
} else {
// Installed version
return dirname + "/../share/lpython/lib";
}
}
std::string get_runtime_library_header_dir()
{
char *env_p = std::getenv("LFORTRAN_RUNTIME_LIBRARY_HEADER_DIR");
if (env_p) return env_p;
// The header file is in src/libasr/runtime for development, but in impure
// in installed version
std::string path;
int dirname_length;
get_executable_path(path, dirname_length);
std::string dirname = path.substr(0,dirname_length);
if ( endswith(dirname, "src/bin")
|| endswith(dirname, "src\\bin")
|| endswith(dirname, "SRC\\BIN")) {
// Development version
return dirname + "/../libasr/runtime";
} else if (endswith(dirname, "src/lpython/tests") ||
endswith(to_lower(dirname), "src\\lpython\\tests")) {
// CTest Tests
return dirname + "/../../libasr/runtime";
} else {
// Installed version
return dirname + "/../share/lpython/lib/impure";
}
return path;
}
bool is_directory(std::string path) {
struct stat buffer;
if (stat(path.c_str(), &buffer) == 0) {
if (S_ISDIR(buffer.st_mode)) {
return true;
} else {
return false;
}
}
return false;
}
bool path_exists(std::string path) {
struct stat buffer;
if (stat(path.c_str(), &buffer) == 0) {
return true;
} else {
return false;
}
}
// Decodes the exit status code of the process (in Unix)
// See `WEXITSTATUS` for more information.
// https://stackoverflow.com/a/27117435/15913193
// https://linux.die.net/man/3/system
int32_t get_exit_status(int32_t err) {
return (((err) >> 8) & 0x000000ff);
}
std::string generate_visualize_html(std::string &astr_data_json) {
std::hash<:string> hasher;
std::ofstream out;
std::string file_name = "visualize" + std::to_string(hasher(astr_data_json)) + ".html";
out.open(file_name);
out << R"(
LCompilers AST/R Visualization
\n";
out << R"(
;
return (
{node.node}
{
node.literals.map((val, idx) =>
{val[0]}: {val[1]}
)
}
);
}
const getLayoutedElements = (nodes, edges, direction = 'TB') => {
const nodeWidth = 180;
const isHorizontal = direction === 'LR';
const dagreGraph = new dagre.graphlib.Graph();
dagreGraph.setDefaultEdgeLabel(() => ({}));
dagreGraph.setGraph({ rankdir: direction });
nodes.forEach(node => dagreGraph.setNode(node.id, { width: nodeWidth, height: node.nodeHeight }));
edges.forEach(edge => dagreGraph.setEdge(edge.source, edge.target));
dagre.layout(dagreGraph);
nodes.forEach((node) => {
const nodeWithPosition = dagreGraph.node(node.id);
node.targetPosition = isHorizontal ? 'left' : 'top';
node.sourcePosition = isHorizontal ? 'right' : 'bottom';
// Shifting the dagre node position (anchor=center center) to the top left
// so it matches the React Flow node anchor point (top left).
node.position = {
x: nodeWithPosition.x - nodeWidth / 2,
y: nodeWithPosition.y - node.nodeHeight / 2,
};
return node;
});
return [nodes, edges];
};
class Graph {
constructor() {
this.nodes = [];
this.edges = [];
this.idx = 1;
return this;
}
createNode(cur_node) {
cur_node.idx = this.idx++;
cur_node.literals = [];
let obj = cur_node.fields;
for (let prop in obj) {
let neigh = obj[prop];
if (typeof neigh === 'object') {
if (neigh.hasOwnProperty("node")) {
this.createEdge(cur_node.idx, neigh, prop);
} else {
if (neigh.length > 0) {
for (let i in neigh) {
let arrayElement = neigh[i];
if (typeof arrayElement === 'object') {
if (arrayElement.hasOwnProperty("node")) {
this.createEdge(cur_node.idx, arrayElement, `${prop}[${i}]`);
} else {
console.log("ERROR: Unexpected 2D Array found");
}
} else {
cur_node.literals.push([`${prop}[${i}]`, `${arrayElement}`]);
}
}
} else {
// 0 length array, show as literal
cur_node.literals.push([prop, "[]"]);
}
}
} else {
cur_node.literals.push([prop, `${neigh}`]);
}
}
this.nodes.push({ id: `${cur_node.idx}`, data: { label: }, nodeHeight: 70 + 20 * (cur_node.literals.length) });
}
createEdge(parent_idx, cur_node, edge_label) {
this.edges.push({
id: `${parent_idx}-${this.idx}`,
source: `${parent_idx}`,
target: `${this.idx}`,
label: edge_label,
labelStyle: { fontWeight: 700 },
labelBgPadding: [8, 4],
labelBgStyle: { fill: '#FBBD23' },
});
this.createNode(cur_node);
}
}
function Flow({ nodes, edges }) {
return (
);
}
function MyApp() {
var g = new Graph();
g.createNode(astr_data);
var [layoutedNodes, layoutedEdges] = getLayoutedElements(g.nodes, g.edges);
return ();
}
ReactDOM.render(, document.body);
)";
return file_name;
}
}