Skip to content

Commit 95757fe

Browse files
committed
bender-slang(ffi): Refactor interface (once again)
1 parent b6ef2fc commit 95757fe

4 files changed

Lines changed: 102 additions & 172 deletions

File tree

crates/bender-slang/cpp/slang_bridge.cpp

Lines changed: 33 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
using namespace slang;
1111
using namespace slang::driver;
1212
using namespace slang::syntax;
13+
using namespace slang::parsing;
1314

1415
using std::memcpy;
1516
using std::shared_ptr;
@@ -20,58 +21,40 @@ using std::vector;
2021
// Create a new SlangContext instance
2122
std::unique_ptr<SlangContext> new_slang_context() { return std::make_unique<SlangContext>(); }
2223

23-
// Constructor: initialize driver with standard args
24-
SlangContext::SlangContext() { driver.addStandardArgs(); }
24+
SlangContext::SlangContext() {}
2525

26-
// Add a source file path to the context
27-
void SlangContext::add_source(rust::Str path) { sources.emplace_back(std::string(path)); }
28-
29-
// Add an include path to the context
30-
void SlangContext::add_include(rust::Str path) { includes.emplace_back(std::string(path)); }
31-
32-
// Add a define to the context
33-
void SlangContext::add_define(rust::Str def) { defines.emplace_back(std::string(def)); }
34-
35-
bool SlangContext::parse() {
36-
vector<string> arg_strings;
37-
arg_strings.push_back("slang_tool");
38-
39-
for (const auto& s : sources)
40-
arg_strings.push_back(s);
41-
for (const auto& i : includes) {
42-
arg_strings.push_back("-I");
43-
arg_strings.push_back(i);
26+
// Set the include paths for the preprocessor
27+
void SlangContext::set_includes(const rust::Vec<rust::String>& incs) {
28+
ppOptions.additionalIncludePaths.clear();
29+
for (const auto& inc : incs) {
30+
ppOptions.additionalIncludePaths.emplace_back(std::string(inc));
4431
}
45-
for (const auto& d : defines) {
46-
arg_strings.push_back("-D");
47-
arg_strings.push_back(d);
32+
}
33+
34+
// Sets the preprocessor defines
35+
void SlangContext::set_defines(const rust::Vec<rust::String>& defs) {
36+
ppOptions.predefines.clear();
37+
for (const auto& def : defs) {
38+
ppOptions.predefines.emplace_back(std::string(def));
4839
}
40+
}
4941

50-
vector<const char*> c_args;
51-
for (const auto& s : arg_strings)
52-
c_args.push_back(s.c_str());
42+
// Parses the given file and returns a syntax tree, if successful
43+
std::shared_ptr<SyntaxTree> SlangContext::parse_file(rust::Str path) {
44+
Bag options;
45+
options.set(ppOptions);
5346

54-
if (!driver.parseCommandLine(c_args.size(), c_args.data())) {
55-
throw std::runtime_error("Failed to parse command line args");
56-
}
47+
auto result = SyntaxTree::fromFile(string_view(path.data(), path.size()), sourceManager, options);
5748

58-
if (!driver.processOptions()) {
59-
throw std::runtime_error("Failed to process options");
49+
if (!result) {
50+
auto& err = result.error();
51+
std::string msg = "System Error loading '" + std::string(err.second) + "': " + err.first.message();
52+
throw std::runtime_error(msg);
6053
}
6154

62-
bool ok = driver.parseAllSources();
63-
// reportDiagnostics returns true if issues found, so we invert logic or check strictness
64-
bool hasErrors = driver.reportDiagnostics(false);
65-
66-
return ok && !hasErrors;
55+
return *result;
6756
}
6857

69-
// Get the number of syntax trees parsed by the driver
70-
size_t SlangContext::get_tree_count() const { return driver.syntaxTrees.size(); }
71-
72-
// Get the syntax tree at the specified index
73-
shared_ptr<SyntaxTree> SlangContext::get_tree(size_t index) const { return driver.syntaxTrees[index]; }
74-
7558
// Rewriter that adds prefix/suffix to module and instantiated hierarchy names
7659
class SuffixPrefixRewriter : public SyntaxRewriter<SuffixPrefixRewriter> {
7760
public:
@@ -134,24 +117,21 @@ class SuffixPrefixRewriter : public SyntaxRewriter<SuffixPrefixRewriter> {
134117
string_view suffix;
135118
};
136119

137-
// Rename modules and instantiated hierarchy names in the given syntax tree
138-
shared_ptr<SyntaxTree> SlangContext::rename_tree(const shared_ptr<SyntaxTree> tree, rust::Str prefix,
139-
rust::Str suffix) const {
140-
141-
// Convert rust::Str to string_view and instantiate rewriter
142-
string_view prefix_str(prefix.data(), prefix.size());
143-
string_view suffix_str(suffix.data(), suffix.size());
144-
SuffixPrefixRewriter rewriter(prefix_str, suffix_str);
120+
// Transform the given syntax tree by renaming modules and instantiated hierarchy names with the specified prefix/suffix
121+
std::shared_ptr<SyntaxTree> rename(std::shared_ptr<SyntaxTree> tree, rust::Str prefix, rust::Str suffix) {
122+
std::string_view p(prefix.data(), prefix.size());
123+
std::string_view s(suffix.data(), suffix.size());
145124

146-
// Apply the rewriter to the tree and return the transformed tree
125+
// SuffixPrefixRewriter is defined in the .cpp file as before
126+
SuffixPrefixRewriter rewriter(p, s);
147127
return rewriter.transform(tree);
148128
}
149129

150130
// Print the given syntax tree with specified options
151-
rust::String SlangContext::print_tree(const shared_ptr<SyntaxTree> tree, SlangPrintOpts options) const {
131+
rust::String print_tree(const shared_ptr<SyntaxTree> tree, SlangPrintOpts options) {
152132

153133
// Set up the printer with options
154-
SyntaxPrinter printer(driver.sourceManager);
134+
SyntaxPrinter printer(tree->sourceManager());
155135

156136
printer.setIncludeDirectives(options.include_directives);
157137
printer.setExpandIncludes(options.expand_includes);

crates/bender-slang/cpp/slang_bridge.h

Lines changed: 11 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -12,36 +12,27 @@
1212
#include <string>
1313
#include <vector>
1414

15-
struct SlangPrintOpts; // Forward decl
15+
struct SlangPrintOpts;
1616

17-
// The wrapper class exposed as "SlangContext" to Rust
1817
class SlangContext {
1918
public:
2019
SlangContext();
2120

22-
void add_source(rust::Str path);
23-
void add_include(rust::Str path);
24-
void add_define(rust::Str def);
21+
void set_includes(const rust::Vec<rust::String>& includes);
22+
void set_defines(const rust::Vec<rust::String>& defines);
2523

26-
bool parse();
27-
28-
size_t get_tree_count() const;
29-
std::shared_ptr<slang::syntax::SyntaxTree> get_tree(size_t index) const;
30-
31-
std::shared_ptr<slang::syntax::SyntaxTree> rename_tree(const std::shared_ptr<slang::syntax::SyntaxTree>,
32-
rust::Str prefix, rust::Str suffix) const;
33-
34-
rust::String print_tree(const std::shared_ptr<slang::syntax::SyntaxTree>, SlangPrintOpts options) const;
24+
std::shared_ptr<slang::syntax::SyntaxTree> parse_file(rust::Str path);
3525

3626
private:
37-
slang::driver::Driver driver;
38-
39-
// We buffer args to pass to driver.parseCommandLine later
40-
std::vector<std::string> sources;
41-
std::vector<std::string> includes;
42-
std::vector<std::string> defines;
27+
slang::SourceManager sourceManager;
28+
slang::parsing::PreprocessorOptions ppOptions;
4329
};
4430

4531
std::unique_ptr<SlangContext> new_slang_context();
4632

33+
std::shared_ptr<slang::syntax::SyntaxTree> rename(std::shared_ptr<slang::syntax::SyntaxTree> tree, rust::Str prefix,
34+
rust::Str suffix);
35+
36+
rust::String print_tree(std::shared_ptr<slang::syntax::SyntaxTree> tree, SlangPrintOpts options);
37+
4738
#endif // BENDER_SLANG_BRIDGE_H

crates/bender-slang/src/lib.rs

Lines changed: 47 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -29,37 +29,48 @@ mod ffi {
2929
#[namespace = "slang::syntax"]
3030
type SyntaxTree;
3131

32-
/// Create a new persistent context (owns the Driver)
32+
/// Create a new persistent context
3333
fn new_slang_context() -> UniquePtr<SlangContext>;
3434

35-
// Methods on SlangContext
36-
fn add_source(self: Pin<&mut SlangContext>, path: &str);
37-
fn add_include(self: Pin<&mut SlangContext>, path: &str);
38-
fn add_define(self: Pin<&mut SlangContext>, def: &str);
35+
/// Set the include directories
36+
fn set_includes(self: Pin<&mut SlangContext>, includes: &Vec<String>);
37+
/// Set the preprocessor defines
38+
fn set_defines(self: Pin<&mut SlangContext>, defines: &Vec<String>);
3939

4040
/// Parse all added sources. Returns true on success.
41-
fn parse(self: Pin<&mut SlangContext>) -> Result<bool>;
41+
fn parse_file(self: Pin<&mut SlangContext>, path: &str) -> Result<SharedPtr<SyntaxTree>>;
4242

43-
/// Retrieves the number of parsed syntax trees
44-
fn get_tree_count(self: &SlangContext) -> usize;
43+
/// Rename names in the syntax tree with a given prefix and suffix
44+
fn rename(tree: SharedPtr<SyntaxTree>, prefix: &str, suffix: &str)
45+
-> SharedPtr<SyntaxTree>;
46+
47+
/// Print a specific tree
48+
fn print_tree(tree: SharedPtr<SyntaxTree>, options: SlangPrintOpts) -> String;
49+
}
50+
}
4551

46-
/// Retrieves a shared pointer to a specific syntax tree by index
47-
fn get_tree(self: &SlangContext, index: usize) -> SharedPtr<SyntaxTree>;
52+
/// A wrapper around a Slang syntax tree
53+
pub struct SyntaxTree {
54+
ptr: SharedPtr<ffi::SyntaxTree>,
55+
}
4856

49-
/// Rename names in the syntax tree with a given prefix and suffix
50-
fn rename_tree(
51-
self: &SlangContext,
52-
tree: SharedPtr<SyntaxTree>,
53-
prefix: &str,
54-
suffix: &str,
55-
) -> SharedPtr<SyntaxTree>;
56-
57-
/// Print a specific tree using the context's SourceManager
58-
fn print_tree(
59-
self: &SlangContext,
60-
tree: SharedPtr<SyntaxTree>,
61-
options: SlangPrintOpts,
62-
) -> String;
57+
impl SyntaxTree {
58+
/// Renames all names in the syntax tree with the given prefix and suffix
59+
pub fn rename(&self, prefix: Option<&str>, suffix: Option<&str>) -> Self {
60+
let p = prefix.unwrap_or("");
61+
let s = suffix.unwrap_or("");
62+
63+
let ptr = if p.is_empty() && s.is_empty() {
64+
self.ptr.clone()
65+
} else {
66+
ffi::rename(self.ptr.clone(), p, s)
67+
};
68+
69+
SyntaxTree { ptr: ptr }
70+
}
71+
72+
pub fn display(&self, options: SlangPrintOpts) -> String {
73+
ffi::print_tree(self.ptr.clone(), options)
6374
}
6475
}
6576

@@ -76,62 +87,21 @@ impl SlangSession {
7687
}
7788
}
7889

79-
/// Adds a source file to be parsed
80-
pub fn add_source(&mut self, path: &str) {
81-
self.ctx.pin_mut().add_source(path);
82-
}
83-
84-
/// Adds an include directory
85-
pub fn add_include(&mut self, path: &str) {
86-
self.ctx.pin_mut().add_include(path);
87-
}
88-
89-
/// Adds a preprocessor define
90-
pub fn add_define(&mut self, define: &str) {
91-
self.ctx.pin_mut().add_define(define);
92-
}
93-
94-
/// Parses all added source files into syntax trees
95-
pub fn parse(&mut self) -> Result<bool, Box<dyn std::error::Error>> {
96-
Ok(self.ctx.pin_mut().parse()?)
97-
}
98-
99-
/// Returns the parsed syntax trees as a Rust vector
100-
pub fn get_trees(&self) -> Vec<SharedPtr<ffi::SyntaxTree>> {
101-
let count = self.ctx.get_tree_count();
102-
let mut trees = Vec::with_capacity(count);
103-
for i in 0..count {
104-
trees.push(self.ctx.get_tree(i));
105-
}
106-
trees
107-
}
108-
109-
/// Returns an iterator over the parsed syntax trees
110-
pub fn trees_iter(&self) -> impl Iterator<Item = SharedPtr<ffi::SyntaxTree>> + '_ {
111-
(0..self.ctx.get_tree_count()).map(|i| self.ctx.get_tree(i))
90+
/// Sets the include directories
91+
pub fn set_includes(mut self, includes: &[String]) -> Self {
92+
self.ctx.pin_mut().set_includes(&includes.to_vec());
93+
self
11294
}
11395

114-
/// Renames names in the syntax tree with a given prefix and suffix
115-
pub fn rename_tree(
116-
&self,
117-
tree: SharedPtr<ffi::SyntaxTree>,
118-
prefix: Option<&str>,
119-
suffix: Option<&str>,
120-
) -> SharedPtr<ffi::SyntaxTree> {
121-
if prefix.is_none() && suffix.is_none() {
122-
return tree;
123-
}
124-
let prefix = prefix.unwrap_or("");
125-
let suffix = suffix.unwrap_or("");
126-
self.ctx.rename_tree(tree, prefix, suffix)
96+
/// Sets the preprocessor defines
97+
pub fn set_defines(mut self, defines: &[String]) -> Self {
98+
self.ctx.pin_mut().set_defines(&defines.to_vec());
99+
self
127100
}
128101

129-
/// Prints a syntax tree with given printing options
130-
pub fn print_tree(
131-
&self,
132-
tree: SharedPtr<ffi::SyntaxTree>,
133-
opts: ffi::SlangPrintOpts,
134-
) -> String {
135-
self.ctx.print_tree(tree, opts)
102+
/// Parses a source file and returns the syntax tree
103+
pub fn parse(&mut self, path: &str) -> Result<SyntaxTree, Box<dyn std::error::Error>> {
104+
let ptr = self.ctx.pin_mut().parse_file(path)?;
105+
Ok(SyntaxTree { ptr })
136106
}
137107
}

src/cmd/pickle.rs

Lines changed: 11 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -62,24 +62,6 @@ pub struct PickleArgs {
6262

6363
/// Execute the `pickle` subcommand.
6464
pub fn run(args: PickleArgs) -> Result<()> {
65-
let mut slang = SlangSession::new();
66-
67-
for file in args.files.iter() {
68-
slang.add_source(file);
69-
}
70-
71-
for include in args.include_dirs.iter() {
72-
slang.add_include(include);
73-
}
74-
75-
for define in args.defines.iter() {
76-
slang.add_define(define);
77-
}
78-
79-
slang
80-
.parse()
81-
.map_err(|cause| Error::new(format!("Cannot parse files: {}", cause)))?;
82-
8365
let print_opts = SlangPrintOpts {
8466
include_directives: args.include_directives,
8567
expand_includes: args.expand_includes,
@@ -88,10 +70,17 @@ pub fn run(args: PickleArgs) -> Result<()> {
8870
squash_newlines: args.strip_newlines,
8971
};
9072

91-
for tree in slang.trees_iter() {
92-
let renamed_tree = slang.rename_tree(tree, args.prefix.as_deref(), args.suffix.as_deref());
93-
let pickled = slang.print_tree(renamed_tree, print_opts);
94-
println!("{}", pickled);
73+
let mut slang = SlangSession::new()
74+
.set_includes(&args.include_dirs)
75+
.set_defines(&args.defines);
76+
77+
for source in &args.files {
78+
let tree = slang
79+
.parse(source)
80+
.map_err(|cause| Error::new(format!("Cannot parse file {}: {}", source, cause)))?;
81+
let renamed_tree = tree.rename(args.prefix.as_deref(), args.suffix.as_deref());
82+
println!("{}", renamed_tree.display(print_opts));
9583
}
84+
9685
Ok(())
9786
}

0 commit comments

Comments
 (0)