I'm writing some macro and this is the sample code
macro public static function test(object:Expr,name:Expr):Expr{
#if debug
return macro if ($object.get($name) == true) {$object.scan();$object.submit();return;};
#else
return macro trace("debug mode only");
#end
}
As my macro getting longer & complex, I'm thinking there must be another way to write multi-line macro other than joining statement with semicolon.
any suggestion on writing multi-line (approx. 50-100 generated line) macro ?
From this example, I found out that you can return a block of expression, not just one line. Simply add the statement inside a curly bracket and return it. You can also return a class using macro.
macro public static function test(object:Expr, name:Expr):Expr {
#if debug
return macro
if ($object.get($name) == true) {
$object.scan();
$object.submit();
return;
}
#else
return macro {
trace("not working!")
trace("compile with -Ddebug");
}
#end
}
Related
I have code that looks like this, that I'm trying to format
Original code:
public int doThing(int a) // -incredibly useful comment here
{
int ab = a+1;
return ab;
}
I want it to look like this
public int doThing() { // -incredibly useful comment here
int ab = a+1;
return ab;
}
If I try to turn on the Brace position -> Method Declaration -> Same line option and run the formatter, any code with a comment in the position "breaks" the formatter, and I get an output for my example that looks the same as the original code, but methods without a comment have the correct formatting (meaning the results are inconsistent).
Is it possible with the eclipse formatter to get the style I want? I'm trying to run it against a large amount of code, and would prefer not to have to fix these all manually to get a consistent brace position.
The problem here is that is not formatting but rewriting. Using File Search + regular expression + Replace could do that in bulk.
Try this regex
^(\s*(?:public|private|protected)\s+[^(]+\([^)]*\))(\s*\/\/[^/]+)\R\s*\{
On File Search ( Ctrl + H)
Hit Replace and use $1 { $2\n as replacement
Code should compile after the refactoring.
UPDATE:
Fixed regex part that represents function arguments
\([^)]*\)
Full Regex matches these cases
public int doSmthg() // coment here
{
return 1;
}
private String doSmthgElse(String arg) // coment here
{
return arg;
}
All I need to do with my code is if it passes the if statement, it simply passes the class and moves on to the rest of the code, but in my research, I can't exactly figure out what the command may be. Is there a way to implement Python's pass keyword in dart?
There is no direct equivalent to the pass statement in Dart language. In Python, there are language restrictions that do not allow leaving empty loops, if statements and so on. However, in Dart it's completely OK to do that, you can just leave empty braces. For instance:
void main() {
for (int i = 0; i < 5; i++) {
// Ignored
}
try {
// Some logic
} on Exception {
// Ignored
}
if (true) {
// Ignored
}
}
There are even some lint rules that check for you not to leave empty logic (you can still add a comment and not leave them empty, though): empty_statements, empty_catches and so on.
Just add empty curly braces {}. For example:
const num = 5;
if (num == 5) {
}
you don't have to provide code within the curly braces, it can be left empty.
Using a macro that breaks out of a loop works, but I want to pass in a label to be able to define which outer loop to break out of.
Passing the argument in as an expression gave a syntax error, the only way I managed to get this to work was to pass in a block however this isn't very elegant, e.g.:
my_macro({ break 'outer; });
Is there a way to pass:
my_macro('outer);
... that can be written in the macro as break $my_label; that expands into break 'outer; ?
Passing it as the versatile tt (token tree) works:
macro_rules! my_break {
($label:tt) => { break $label; }
}
fn main() {
'outer: loop {
println!("Start of outer");
loop {
println!("Start of inner");
my_break!('outer);
println!("Not reachable");
}
println!("End of outer");
}
println!("End of main");
}
Playground
To future readers, there's an accepted RFC adding a lifetime specifier for macro parameters.
OK, what I'm trying to do is fairy complicated, but I'll try to explain.
Let's say we want (at compile-time) all derivedMembers of class someClass. Then we'd simply do :
const string[] methods = [__traits(derivedMembers,someClass)];
Now, how could we get someClass from "someClass"? (yep, its string representation).
Let me explain a bit more what I'm trying to do :
I want to create an "intermediate" function which takes a function name as an argument (along with a params array) and calls the appropriate function from a list of available static methods in a specific (predefined) set of classes. Like execute("someFunc",["one","two","three"]);.
Here's the full (test) code :
class Math {
static string noArgs(string[] s) { writeln(s); return ""; }
static string withOneArg(string[] s) { writeln(s); return ""; }
static string withTwoArgs(string[] s) { writeln(s); return ""; }
}
string cases()
{
string ret = "";
const string[] methods = [__traits(derivedMembers,Math)];
foreach (string s; methods)
{
ret ~= "case \"" ~ s ~ "\": return Math."~s~"(params);";
}
return ret;
}
string execute(string what, string[] params)
{
switch (what)
{
mixin(cases());
default: break;
}
return "";
}
The trouble with the above code is that it only looks for methods in Math. How could I change it, in an elegant D-friendly way, so that it'll go through an array of classes like [Math,String,SomethingElse] -- it doesn't have to be variable (we need it at compile-time anyway)?
UPDATE:
Tried something along the lines of :
const string[] methods = [__traits(derivedMembers,mixin("Math")];
but it complains that Cannot interpret Math at compile time.
UPDATE 2:
Also, tried using Object.factory("Math") but it's still not working. (Perhaps I'm just creating an instance of the Math class?)
Let me rewrite this to show you some cool tricks:
import std.stdio;
class Math {
static string noArgs(string[] s) { writeln(s); return ""; }
static string withOneArg(string[] s) { writeln(s); return ""; }
static string withTwoArgs(string[] s) { writeln(s); return ""; }
}
class String {
static string oneArg(string[] s) { return null; }
}
string execute(string what, string[] params) {
import std.string;
auto parts = what.split(".");
auto className = parts[0];
auto methodName = parts[1];
import std.typetuple;
switch(className) {
default: assert(0, "unknown class");
foreach(possibleClass; TypeTuple!(Math, String)) {
case possibleClass.stringof:
switch(methodName) {
default: assert(0, "unknown method");
foreach(memberName; __traits(derivedMembers, possibleClass)) {
case memberName:
return __traits(getMember, possibleClass, memberName)(params);
break;
}
}
break;
}
}
assert(0);
}
void main() {
execute("Math.withOneArg", ["cool"]);
execute("String.oneArg", ["cool"]);
}
Notice that there are no mixin expressions used at all. Instead of getting an instance of the class from a string, I just made a TypeTuple of all the classes I wanted to use. This is preferable to mixin because then it is less likely to find name classes when used in different scopes; if possibleClasses were a compile-time parameter to execute from a different module, the list of classes would still work, whereas the list of strings would see undefined identifier errors because the library module doesn't import your user module.
Another mixin I removed was the one to generate the cases. This looks insane, but is allowed in D: if you have a compile-time foreach (that is, a foreach over a built-in tuple of some sort, e.g. TypeTuple, template argument lists, the results of __traits...) you can actually put case statements inside them!
So, all you have to do is write a regular switch statement on the run time variable you want to compare against, put the foreach inside it looping over the compile-time stuff you're searching for, case that_loop_var: and boom, you're in business.
Similarly, I used __traits(getMember) rather than a mixin string to call the method. This solution will help avoid name clashes and IMO is cleaner code. It can also potentially handle overloads, if wanted (with __traits(getOverloads) instead of __traits(getMember), you can loop over each one then and match the parameter types).
Finally, nesting switches inside other case statements is allowed. If you need to break out of an outer loop or switch and don't want ambiguity, you can label loops and switches and use break label_name_here; to specify which one you want to break from. Ditto for continue with nested loops.
BTW you could also automatically generate the wrapper functions that convert string[] to other types of arguments if you dove into the std.traits stuff. I wish my book was out already, I wrote about this at some length in there and don't feel like writing it all right now but if you look at std.traits.ParameterTypeTuple and ReturnType in the same module that will get you started if you wanna try it.
I have the following macro:
#define IF_TRACE_ENABLED(level) if (IsTraceEnabled(level))
The user code should look following:
IF_TRACE_ENABLED(LEVEL1)
{
... some very smart code
}
The emphasis here on curly brackets - I want to prevent "if" from macro to "eat" other code:
if (...)
IF_TRACE_ENABLED(LEVEL1)
printf(....);
else
bla bla bla
In this example IF_TRACE_ENABLED "eats" else block.
Is there way to enforce user code not compile without curly brakes or there are other to define the macro to achieve the safety?
This doesn't force the user of the macro to use braces, but it will prevent an else clause from being unintentionally eaten:
#define IF_TRACE_ENABLED(level) if (!IsTraceEnabled(level)) {} else
A side note: braces around the printf() in the second example of the question wouldn't have fixed the problem - the else associated with bla bla bla would still be bound to the if statement in the macro.
You could try this:
#define IF_TRACE_ENABLED(level) do { if(IsTraceEnabled(level)) {
#define END_TRACE_ENABLED } } while(0);
I don't think there's any way to "enforce" good syntax from only the opening line of the macro. You will need to use two.
EDIT
I've added an extra pair of braces inside the macro to avoid all ambiguity.
In response to the comment, this macro is meant to be used like this:
IF_TRACE_ENABLED(LEVEL1)
printf("Trace\n");
END_TRACE_ENABLED
Not as a statement. For the record, I think this is an abuse of the preprocessor and nobody should do this at all. What's wrong with just writing it out, bracketed with #ifdef DEBUG if necessary.
This should work, but you'll have the pass the contents of the if block as an argument to the macro as well:
#define IF_TRACE_ENABLED(level,content) { if (IsTraceEnabled(level)) {content} }