Is there an equivalent to C's __LINE__ macro in Pascal? - macros

Is there an equivalent to C's __LINE__ macro in Pascal? Maybe a function?
{ Prints the line number in source file. }
begin
write(__LINE__)
end.
Is supposed to print:
3

If you're using Free Pascal, you can use: {$I %LINE%}
I don't know how portable the construct is between existing compilers.

Related

How are arguments in C/C++ macros handled implicitly?

I'm trying to read and understand a file written in C (here) and not knowing much C (or if it's C++ to begin with), I'm wondering how the following:
#define BEGIN yy_start = 1 + 2 *
when called like this:
BEGIN(new_state)
is working. I know BEGIN is a macro/placeholder setting yy_start. However I can't find anything on how the argument passed in is handled and operands don't get me anywhere.
Question: How are arguments handled in a C/C++ macro if they are not handled explicitly?
How are arguments handled in a C/C++ macro if they are not handled explicitly?
If a macro is not declared with arguments then it does not take arguments at all. Indeed, C explicitly distinguishes between macros that accept arguments and those that don't. In your particular case, given a definition of BEGIN as an object-like macro:
#define BEGIN yy_start = 1 + 2 *
This invocation ...
BEGIN(new_state)
... expands to:
yy_start = 1 + 2 *(new_state)
. In particular, note that only the macro name is replaced. The parenthesized tokens following it are not part of the macro invocation, and are not affected by the macro expansion.
The macro BEGIN has no arguments so the resulting code will be
yy_start = 1 + 2 *(new_state)
It is done in preprocessing.

How do I write a perl6 macro to enquote text?

I'm looking to create a macro in P6 which converts its argument to a string.
Here's my macro:
macro tfilter($expr) {
quasi {
my $str = Q ({{{$expr}}});
filter-sub $str;
};
}
And here is how I call it:
my #some = tfilter(age < 50);
However, when I run the program, I obtain the error:
Unable to parse expression in quote words; couldn't find final '>'
How do I fix this?
Your use case, converting some code to a string via a macro, is very reasonable. There isn't an established API for this yet (even in my head), although I have come across and thought about the same use case. It would be nice in cases such as:
assert a ** 2 + b ** 2 == c ** 2;
This assert statement macro could evaluate its expression, and if it fails, it could print it out. Printing it out requires stringifying it. (In fact, in this case, having file-and-line information would be a nice touch also.)
(Edit: 007 is a language laboratory to flesh out macros in Perl 6.)
Right now in 007 if you stringify a Q object (an AST), you get a condensed object representation of the AST itself, not the code it represents:
$ bin/007 -e='say(~quasi { 2 + 2 })'
Q::Infix::Addition {
identifier: Q::Identifier "infix:+",
lhs: Q::Literal::Int 2,
rhs: Q::Literal::Int 2
}
This is potentially more meaningful and immediate than outputting source code. Consider also the fact that it's possible to build ASTs that were never source code in the first place. (And people are expected to do this. And to mix such "synthetic Qtrees" with natural ones from programs.)
So maybe what we're looking at is a property on Q nodes called .source or something. Then we'd be able to do this:
$ bin/007 -e='say((quasi { 2 + 2 }).source)'
2 + 2
(Note: doesn't work yet.)
It's an interesting question what .source ought to output for synthetic Qtrees. Should it throw an exception? Or just output <black box source>? Or do a best-effort attempt to turn itself into stringified source?
Coming back to your original code, this line fascinates me:
my $str = Q ({{{$expr}}});
It's actually a really cogent attempt to express what you want to do (turn an AST into its string representation). But I doubt it'll ever work as-is. In the end, it's still kind of based on a source-code-as-strings kind of thinking à la C. The fundamental issue with it is that the place where you put your {{{$expr}}} (inside of a string quote environment) is not a place where an expression AST is able to go. From an AST node type perspective, it doesn't typecheck because expressions are not a subtype of quote environments.
Hope that helps!
(PS: Taking a step back, I think you're doing yourself a disservice by making filter-sub accept a string argument. What will you do with the string inside of this function? Parse it for information? In that case you'd be better off analyzing the AST, not the string.)
(PPS: Moritz++ on #perl6 points out that there's an unrelated syntax error in age < 50 that needs to be addressed. Perl 6 is picky about things being defined before they are used; macros do not change this equation much. Therefore, the Perl 6 parser is going to assume that age is a function you haven't declared yet. Then it's going to consider the < an opening quote character. Eventually it'll be disappointed that there's no >. Again, macros don't rescue you from needing to declare your variables up-front. (Though see #159 for further discussion.))

How do I translate this `for` loop for the fish shell?

I'm translating a script from Z shell to Fish, and I've got this one part I can't figure out how to translate:
for (( i=0; i < $COLUMNS; i++ )); do
printf $1
done
The only documentation for for loops I can find in Fish is for this kind. How would I do this in Fish?
It appears that the Fish shell does not have that kind of for loop, but instead requires you to take a different approach. (The philosophy is apparently to rely on as few syntactic structures and operators as possible, and do as much with commands as possible.)
Here's how I did it, although I assume there are better ways:
for CHAR in (seq $COLUMNS)
printf $argv[1]
end
This appears inside a function, hence the $argv[1].
I believe the answer from #iconoclast is the correct answer here.
I am here just to give an (not better) alternative.
a brief search in fish shell seems suggest it provides a while-loop in a form of :
while true
echo "Loop forever"
end
As in C/C++ 101, we learned that for loop can be (mostly) translated to a while loop by:
for (A; B; C) {
D;
}
translates to
A;
while (B) {
D;
C;
}
That's what you can consider if the condition and "incrementation" is not a straight-forward one.

Fortran substitute subroutine name using macro

I am writing a module that allows users to log information. I want to provide an interface that logs a string message, which can be called as
call m_log(msg)
So in file m_logger.f90, I will have
module m_logger
..
subroutine m_log(msg)
..
end module
In file main.f90, a user will have
program main
use m_logger
call m_log(msg)
end program
Now how can I substitute call m_log(msg) with call m_log(msg, __FILE__, __LINE__) ?
Because of this substitution, a different subroutine subroutine m_log(msg, filename, linenum) in the logger module will be called instead.
If I use a macro like #define m_log(msg) m_log(msg,__FILE__,__LINE__) , it will have to be added to every user file that uses the logger.
Also, I do not want to enforce the user to pass __FILE__ and __LINE__ explicitly.
Is there a way I can do this? Or are there any other alternatives altogether?
Thanks in advance
Edit:
I had a discussion on comp.lang.fortran. Adding a link for reference.
here
In this case you would have to use the same approach C uses. Define the macro you proposed
#define log(msg) m_log(msg,__FILE__,__LINE__)
in a separate file (possibly with other useful macros) and include it using #include "file.inc" (standard Fortran include won't suffice).
If the macro has a different name, than the subroutine it actually calls, you can ensure that the user has to use the include and cannot forget it.
If you don't want to force __file__ and __line__ explicitly, then you can use the optional flag, such that your subroutine looks like:
subroutine m_log(msg, filename, linenum)
character(len=*) :: msg
character(len=*), optional :: filename
integer, optional :: linenum
if(present(filename)) then
<something with filename>
endif
if(present(linenum)) then
<something with linenume>
endif
<normal stuff with msg>
end subroutine
The intrinsic function present returns a true value if filename or linenum have any values attached to it, returning false otherwise.
Since you want them to be passed as compiler macros by the user, you would first have to choose different names for your macros. __FILE__ and __LINE__ are both predefined macros. These two macros are defined by preprocessor, not passed by the user. I think that might have cause some confusion.
If you would like to allow users to optionally supply the macros through compiler options, it is probably best to include #ifdef directive in your subroutine:
subroutine m_log(msg)
implicit none
character(len=*) :: msg
character(len=something) :: file
integer ::line
!Initialize file and line to some default value
file=...
line=...
#ifdef __KVM_FILE__
file=__KVM_FILE__
#endif
#ifdef __KVM_LINE__
line=__KVM_LINE__
#endif
...
This way the user will always call the subroutine with the same syntax call m_log(something), but the effect will change according to your compilation macros. Of course, that would also require the user to recompile your code every time they change this macro. If this is too costly to do, you can set up a subroutine with optional argument (as in Kyle's answer), then enclose #define macro in #ifdef blocks, and put them into an .h file, and have your user always include that file. (similar to Vladimir's answer)

Why can't parameter names start with a number?

Variable names can be numeric-alpha, why can't parameter names behave this way as well?
Because the first-parameter-char of the command-parameter syntax as specified in the Powershell Language Specification does not allow for it.
2.3.4 Parameters
Syntax:
command-parameter:
dash first-parameter-char parameter-chars colonopt
first-parameter-char:
A Unicode character of classes Lu, Ll, Lt, Lm, or Lo
_ (The underscore character U+005F)
?
You can find a list of unicode character classes here.
It's definitely convention, and is not a purely technical limitation.
function f($1) {
$1
}
# Works positionally
f 1
# Works with splatting
$h = #{"1" = 2}
f #H
# Doesn't work by name
f -1 2
It's worth noting that the Language Specification was written after the language itself, so there are probably a few points where it's a little more specific and PowerShell itself is.