Parametrized new() expects "identifier" - record

I found the following code in an old document (1977!) and need to run it. However I get the following error message from FreePascal (2.6.4, Win64) at the first 'new':
(14, 9) Fatal: Syntax error, "identifier" expected but "TRUE" found
According to this('new') and this('record'), it should work, but it doesn't. Any suggestions?
program prog(input, output);
type ptr = ^node;
node = record position: 1 .. 512; fathers: array [0.. 4] of ptr;
case (* internal: *) boolean of
true: (ub: (minus, undef, plus);
left, right: 0..5;
rank: 0.. 4);
false: (present: boolean; pred, succ: ptr);
end;
procedure initialize(level: integer);
var v: ptr;
begin if level > 0 then
new(v,true)
else
new(v,false);
end

In your code you're calling the New procedure passing boolean values into its second parameter which for Free Pascal compiler signals to choose this overload:
procedure New(var P: Pointer; Cons: TProcedure);
which is used for allocating objects, where the second Cons parameter is used for passing the object's constructor method. So in this case the compiler was expecting a method, not a boolean value.
Since you are not allocating objects but records, you can call the New procedure just this way:
New(v);

The code you are using is probably ISO Pascal. FPC 2.6.4 cannot handle this construct. FPC from svn trunk aka FPC 2.7.1 can when you compile using the command line switch -Miso. The boolean values passed to new gets a meaning as soon as you un-comment the symbol internal. When this so-called tag-field is present, it is initialized with the value passed to new.

Related

unable to use Sigilless variables with WHERE clause in CLASS?

Module A has a member variable name c, with a WHERE clause:
unit class A;
my \MAXVALUE = 1000_000;
has $.c where 0 < * < MAXVALUE;
method gist() {
"$!c";
}
set RAKULIB environment variable:
set RAKULIB="d:\scripts\Raku\A\lib" # Windows
export RAKULIB="/opt/scripts/Raku/A/lib" # Linux
use Module A like this:
use A;
my $a = A.new(c => 1);
say $a;
but got type check error:
Type check failed in binding to parameter '<anon>'; expected Any but got Mu (Mu)
in whatevercode at D:\scripts\Raku\Raku\A\lib\.precomp\C6EB86CB837D3BCAAA3D85B66CE337C820700C08\6D\6DCD4CE23D88E2EE9568BA546C007C63D9131C1B line 1
in block <unit> at basic.rakutest line 3
Is this a bug?
raku version:
raku -v
This is Rakudo version 2020.05.1 built on MoarVM version 2020.05
implementing Raku 6.d.
Golfed to: BEGIN say 1 < Mu displays essentially the same error message.
In your code, MAXVALUE is initialized with the value Mu at compile time. You must alter your code so evaluation of ... < MAXVALUE comes after MAXVALUE has been initialized to have a value other than Mu.
In the rest of this answer:
What are the simplest compile time solutions?
What if you want to use a run-time value?
What's going on behind the scenes?
Is the error message LTA?
What are the simplest compile time solutions?
You yourself provide a good compile time solution in your comment below this answer in response to my first version of it.
That said, if you wish to keep the symbol purely lexically scoped, you should start with a my:
my constant MAXVALUE = 1000_000;
Problem solved.
What if you want to use a run-time value?
The variables/symbols/expressions in a where clause will be evaluated at compile-time if they're in a WhateverCode expression.
But that might not be the case if you use a lambda (with { ... } syntax) instead. If the line in your code:
has $.c where 0 < * < MAXVALUE;
was changed to:
has $.c where { 0 < $_ < MAXVALUE }
then your code would work.
BUT...
If you add an explicit initial value to the has line...
has $.c where { 0 < $_ < MAXVALUE } = 10;
^^^^ Explicit initialization
...then the error would return because now the where clause is invoked during compile time due to a chain reaction:
The compiler decides to check that the initialization value passes the where check.
To do that the compiler evaluates the where clause at compile-time;
That in turn causes MAXVALUE to be evaluated -- and it contains Mu at compile-time, causing the error to return.
What's going on behind the scenes?
There are both compile-time and run-time phases in initializing has variables:
During compile-time, when a class is being composed, the default value that instances will have for each has variable is determined. Three common scenarios are:
has statement
default value
has $foo;
Any
has $foo where some-condition;
<anon>
has $foo = 42;
42
During run-time, when an instance of a class is being built, the values of the has variables of that particular instance are set, possibly initializing them to values other than the class's default values.
The following code is intended to demonstrate the process:
BEGIN say 'code compile-time, start, outside class';
say 'code run-time, start, outside class';
sub init (*%_) { say "initializing {|%_}" }
class foo {
has $.bar;
has $.baz where init(baz => $_);
has $.buz where init(buz => $_) = 42;
say 'run-time, at end of class';
BEGIN say 'compile-time, at end of class';
}
BEGIN say 'compile-time, outside class again';
say 'run-time, outside class again';
say foo.new(buz => 99);
displays:
code compile-time, start, outside class
compile-time, at end of class
initializing buz 42
compile-time, outside class again
code run-time, start, outside class
run-time, at end of class
run-time, outside class again
initializing buz 99
foo.new(bar => Any, baz => <anon>, buz => 99)
Note the completed initializations of the three has variables in the fully built instance:
bar => Any.
This is the usual default initialization of a variable.
baz => <anon>.
cf say my Int $var; which displays (Int), because the default value of a variable with a type constraint but no explicit initializing value is the type object corresponding to the type constraint, and say my $var where 1; which displays (<anon>), reflecting the anonymous nature of a where constraint (as contrasted with a subset). So has $.baz where init(baz => $_); results in a default value of (<anon>).
buz => 99.
This is the only has variable for which an initializing ... line was displayed -- and, importantly, there are two lines, not one:
The first line is displayed immediately after compile-time, at end of class, i.e. when the compiler reaches the closing curly of the class declaration. This is when Raku does class composition, and buz gets the default value 42.
Then, during evaluation of foo.new(buz => 99);, which builds an instance of the class at run-time, comes initializing 99.
Is the error message LTA?
In my first version of this answer I wrote:
I'm not myself able to provide a coherent explanation ... whether it's considered a bug. I do currently consider the error message LTA.
Now it's time for me to carefully discuss the error message:
Type check failed in binding to parameter '<anon>'; expected Any but got Mu (Mu)
in whatevercode at ... A\lib ... line 1
in block <unit> at ... line 3
Type check failed ...
The where check failed. It is referred to as a "type check". Given normal Raku use of the word "type", I'm going to count this as fine.
... in binding to parameter '<anon>';
I'm not sure what "parameter" refers to, nor '<anon>'. Imhh (in my humble hypothesizing) "parameter" refers to a parameter of the infix:«<» function and '<anon>' to the value stored in $.c at compile-time before the anonymous where constraint is attempted at run-time.
LTA? Perhaps something like <where clause> instead of <anon> would be viable and appropriate?
expected Any but got Mu (Mu)
By default, has variables expect Mu, not Any. So this bit of the message seems not to refer to the $.c. So, as with my hypothesis about "parameter", I think this is about a parameter of the infix:«<» function.
This is really useful info. Any time you see but got Mu (Mu) you can be pretty sure a failure to initialize some value is part of the problem, as was indeed the case here.
in whatevercode
The blow up is happening in a WhateverCode, so this part is useful for someone who knows what a WhateverCode is.
LTA? If someone does not know what a WhateverCode is, this part is cryptic. I think in WhateverCode instead of in whatevercode would be a worthwhile improvement. Perhaps in WhateverCode (eg '* < 42'), where the '* < 42' is fixed as literally that rather than being the actual source whatevercode, because I don't think that's doable, would be better?
at ... A\lib ...
The paths parts I've elided (...) are both helpful (full) and awful (long non-human friendly strings).
LTA? Perhaps moving the paths to the end would help:
Type check failed ... got Mu (Mu)
in whatevercode at A\lib line 1
(Full path to A\lib: D:\scripts\Raku\Raku\A\lib\.precomp\
C6EB86CB837D3BCAAA3D85B66CE337C820700C08\
6D\6DCD4CE23D88E2EE9568BA546C007C63D9131C1B)
... line 1
"line 1" presumably refers to either line 1 in the whatevercode or line 1 in the A\lib. Either way, it's not especially helpful.
LTA? Perhaps it's viable and appropriate to make it clearer what the line 1 refers to, and, if it refers to A\lib, then make it accurately point to the whatevercode.
in block <unit> at line 3
That's useful.

How overloaded horzcat() works?

I'm writing a Matlab class that implements custom concatenation in order to present a clean, expressive interface to the user. Unlike the built-in's, the result of the overloaded horzcat() --- for example --- should be a scalar object set according to class' semantics. However, I'm not sure anymore about which rules apply to overloaded functions...
A class to illustrate the issue would be:
classdef A < handle
properties
k;
end;
methods
function obj = A(varargin)
if nargin == 0
obj.k = 0;
else
obj.k = varargin{1};
end;
end;
function obj = horzcat(obj1, varargin)
fprintf('1st arg is %s.\n', class(obj1));
if nargin > 1
fprintf('2nd arg is %s.\n', class(varargin{1}));
end;
obj = obj1; % Not important
end;
end;
end
Now, when testing this class with a small script:
% Please don't run this is you have valuable
% data in your base workspace.
clear classes;
clc;
a = A('dummy');
b = [-1, a]; % Should fail
the output is:
1st arg is double.
2nd arg is A.
This is surprising, because first argument is a double, i.e. the built-in horzcat() should have been called, subsequently throwing an exception about type mismatch or something. To my understanding, the type of the first argument decides which of the overloaded functions will be called (OK, we restrict ourselves to non-static methods). The code was tested on R2011b/Linux and R2012a/Windows, with the same results.
So, this is my question: what are the actual rules of calling overloaded methods? The Matlab documentation does not explain the above result, and I'd like to avoid developing code based on my illusions about how the language works.
Thank you in advance for your input.
I think MATLAB's documentation is pretty clear about it:
From here:
MATLAB uses the dominant argument to determine which version of a
function to call. If the dominant argument is an object, then MATLAB
calls the method defined by the object's class, if there is one.
And from here more about dominant argument:
The dominant argument in a method's argument list determines which
version of the method or function that the MATLAB runtime calls.
Dominance is determined by the relative precedences of the classes of
the arguments. In general, user-defined classes take precedence over
built-in MATLAB classes. Therefore, the left most argument determines
which method to call. However, user-defined classes can specify the
relative dominance of specific classes.

Statement goto can not cross variable definition?

Suppose these code compiled in g++:
#include <stdlib.h>
int main() {
int a =0;
goto exit;
int *b = NULL;
exit:
return 0;
}
g++ will throw errors:
goto_test.c:10:1: error: jump to label ‘exit’ [-fpermissive]
goto_test.c:6:10: error: from here [-fpermissive]
goto_test.c:8:10: error: crosses initialization of ‘int* b’
It seems like that the goto can not cross pointer definition, but gcc compiles them ok, nothing complained.
After fixed the error, we must declare all the pointers before any of the goto statement, that is to say you must declare these pointers even though you do not need them at the present (and violation with some principles).
What the origin design consideration that g++ forbidden the useful tail-goto statement?
Update:
goto can cross variable (any type of variable, not limited to pointer) declaration, but except those that got a initialize value. If we remove the NULL assignment above, g++ keep silent now. So if you want to declare variables that between goto-cross-area, do not initialize them (and still violate some principles).
Goto can't skip over initializations of variables, because the respective objects would not exist after the jump, since lifetime of object with non-trivial initialization starts when that initialization is executed:
C++11 §3.8/1:
[…] The lifetime of an object of type T begins when:
storage with the proper alignment and size for type T is obtained, and
if the object has non-trivial initialization, its initialization is complete.
C++11 §6.7/3:
It is possible to transfer into a block, but not in a way that bypasses declarations with initialization. A
program that jumps from a point where a variable with automatic storage duration is not in scope to a
point where it is in scope is ill-formed unless the variable has scalar type, class type with a trivial default
constructor and a trivial destructor, a cv-qualified version of one of these types, or an array of one of the
preceding types and is declared without an initializer (8.5).
Since the error mentions [-fpermissive], you can turn it to warning by specifying that compiler flag. This indicates two things. That it used to be allowed (the variable would exist, but be uninitialized after the jump) and that gcc developers believe the specification forbids it.
The compiler only checks whether the variable should be initialized, not whether it's used, otherwise the results would be rather inconsistent. But if you don't need the variable anymore, you can end it's lifetime yourself, making the "tail-goto" viable:
int main() {
int a =0;
goto exit;
{
int *b = NULL;
}
exit:
return 0;
}
is perfectly valid.
On a side-note, the file has extension .c, which suggests it is C and not C++. If you compile it with gcc instead of g++, the original version should compile, because C does not have that restriction (it only has the restriction for variable-length arrays—which don't exist in C++ at all).
There is an easy work-around for those primitive types like int:
// --- original form, subject to cross initialization error. ---
// int foo = 0;
// --- work-around form: no more cross initialization error. ---
int foo; foo = 0;

no new variables on left side of :=

What's happening here?
package main
import "fmt"
func main() {
myArray :=[...]int{12,14,26} ;
fmt.Println(myArray)
myArray :=[...]int{11,12,14} //error pointing on this line
fmt.Println(myArray) ;
}
It throws an error that says
no new variables on left side of :=
What I was doing was re-assigning values to an already declared variable.
Remove the colon : from the second statement as you are assigning a new value to existing variable.
myArray = [...]int{11,12,14}
colon : is used when you perform the short declaration and assignment for the first time as you are doing in your first statement i.e. myArray :=[...]int{12,14,26}.
There are two types of assignment operators in go := and =. They are semantically equivalent (with respect to assignment) but the first one is also a "short variable declaration" ( http://golang.org/ref/spec#Short_variable_declarations ) which means that in the left we need to have at least a new variable declaration for it to be correct.
You can change the second to a simple assignment statement := -> = or you can use a new variable if that's ok with your algorithm.
As a side note, redeclaration can only appear in a multi-variable short declaration
Quoting from the Language specification:
Unlike regular variable declarations, a short variable declaration may
redeclare variables provided they were originally declared earlier in
the same block with the same type, and at least one of the non-blank
variables is new. As a consequence, redeclaration can only appear in a
multi-variable short declaration. Redeclaration does not introduce a
new variable; it just assigns a new value to the original.
package main
import "fmt"
func main() {
a, b := 1, 2
c, b := 3, 4
fmt.Println(a, b, c)
}
Here is a very good example about redeclaration of variables in golang:
https://stackoverflow.com/a/27919847/4418897
myArray :=[...]int{12,14,26}
As stated by the previous commenters, := is a type of short-hand and/or the short-form of variable declaration.
So in the statment above you are doing two things.
You are declaring your variable to be myArray.
You are assigning an array of integers to the myArray variable.
The second part of your code fails, because what you are doing here:
myArray :=[...]int{11,12,14} //error pointing on this line
Is RE-declaring the existing variable myArray, which already contains integer values.
This works:
myArray = [...]int{11,12,14} // NO error will be produced by this line
Because, it is assigning the integer array to the existing ( pre-declared / initialized ) variable.

Ignore Ada Function Return Values

Is there a way to ignore return values in Ada functions?
I have a function which imports from an Intrinsic.
subtype int32 is Interfaces.Interger_32;
function Intrinsic_Sync_Add_And_Fetch
(P : access int32; I : int32) return int32;
pragma Import(
Intrinsic,
Intrinsic_Sync_Add_And_Fetch,
"__sync_add_and_fetch_4");
If I want to use this in a procedure, I need to accept the return value or I will get a compiler error:
cannot use function Intrinsic_Sync_Add_And_Fetch in procedure call.
But, if I create a variable that simply takes the return value of the function and is never used then I get compiler warnings. Obviously, I'd rather avoid those.
I can't very well assign the value back to the value I'm adding to; this would undermine the point of the add operation being atomic.
There is the option of taking the value and doing something with it, like:
val := Intrinsic_Sync_Add_And_Fetch(...);
if val := 0 then null; end if;
It forces the code to compile without errors or warnings, but it seems stupid to me. How can I "get around" this language feature and safely ignore the return value?
Edit: What is __sync_add_and_fetch_4?
This is a built-in atomic operation available on Intel CPUs. As such, part of my Autoconf/Automake process would be deciding if the operation is available, and use a fallback implementation, which involves a critical section, if it's not.
You can read about this and similar operations in GCC's section on atomic builtins.
The __sync_add_and_fetch_4 does pretty much exactly what it says. In C, it would look something like this:
int32_t __sync_add_and_fetch_4(int32_t *ptr, int32_t value) {
*ptr += value;
return *ptr;
}
So it's an atomic addition operation, which returns the result of the addition. Basically, it's an atomic += operator. The _4 means that it takes a 4-byte integer.
Edit: I understand that I could probably just switch off that particular compiler warning, but that always feels dirty to me. If there's a solution available that allows me to continue using -Wall -Werror then I'd love to see it.
declare
dummy : constant return_type := my_function;
pragma Unreferenced (dummy);
begin null; end;
or write a wrapper procedure.
If you never want to reference the return value, why not declare the subprogram as a procedure? The value is going to be returned in a register, so throwing it away won’t cause a lot of grief. (I stand to be corrected on this one!)
subtype int32 is Interfaces.Integer_32;
procedure Intrinsic_Sync_Add_And_Fetch
(P : access int32; I : int32);
pragma Import(
Intrinsic,
Intrinsic_Sync_Add_And_Fetch,
"__sync_add_and_fetch_4");
You said you're only targeting the GNAT compiler. The GNAT User's Guide says:
Note that a special exemption applies to variables which contain any of the substrings DISCARD, DUMMY, IGNORE, JUNK, UNUSED, in any casing. Such variables are considered likely to be intentionally used in a situation where otherwise a warning would be given, so warnings of this kind are always suppressed for such variables.
So the simplest solution to your problem is :
unused := Intrinsic_Sync_Add_And_Fetch(...);
Though you might want to wrap that in a procedure if you are going to use it more than a couple of times :
procedure Intrinsic_Sync_Add_And_Fetch(P : access int32; I : int32) is
unused : int32;
begin
unused := Intrinsic_Sync_Add_And_Fetch(P : access int32; I : int32);
end Intrinsic_Sync_Add_And_Fetch;
i don't know of any way to ignore the return value of a function in Ada: the language has been especially designed to force you to store those return values.
personally, i would store the return value and ignore any warning regarding the use of the variable. anyway, the said warning is quite strange since the variable is indeed used to store the return value.