Cab Dafny use an imported ADT in a match command - module

Hi I am running into time out problems and am trying to decompose my file into different modules on the hope that a verified module will not have to be reverified, in VS code, when working on a module that imports it.
If any one knows if this is a reasonable way to avoid time out problems I would like to hear.
But the more basic problem I found is that once I import an ADT I can make use of in in if statements but not in match statements. See code below for an example. Any ideas on what I am doing wrong?
module inner {
datatype Twee = Node(value : int, left : Twee, right : Twee) | Leaf
function rot(t:Twee) :Twee
{
match t
case Leaf => t
case Node(v,l,r) => Node(v,r,l)
}
}
module outer {
import TL = inner
function workingIf(t:TL.Twee) :TL.Twee
{ if (t == TL.Leaf) then TL.Leaf else t }
function failingMatch(t:TL.Twee) :TL.Twee
{
match t
case TL.Leaf => t // error "darrow expected"
case TL.Node(v,l,r) => TL.Node(v,r,l)
}
}

Sorry for asking the question - the following worked.
function failingMatch(t:TL.Twee) :TL.Twee
{
match t
case Leaf => t
case Node(v,l,r) => TL.Node(v,r,l)
}
Well that worked but the following failed
function rotateLeft(t:TL.Twee) :TL.Twee
{
match t
case Leaf => t
case Node(v,Leaf,r) => TL.Node(v,TL.Leaf,r)
case Node(v,Node(vl,ll,rl),r) => TL.Node(vl,ll,TL.Node(v,rl,r))
}

The answer to the first question was given by James Wilcox and can be found in What are the relationships among imports, includes, and verification in Dafny?
but for convienience I repeat below:
"import has no direct influence on whether the imported module is verified or not. Modules in other files will not be verified unless their file is listed on the command line. Modules in the current file are always verified (whether or not they are imported by anyone)."
The main question I have raised in https://github.com/dafny-lang/dafny/issues/870
Many thanks to everyone - teaching how to use Dafny with out stack overflow would be so much harder.

Somewhat oddly, the constructor names that follow each case keyword are expected to be unqualified. They are looked up in the type of the expression that follows the match. It's quirky that qualified names are not allowed, and this is likely something that will be corrected in the future (I thought there was a Dafny issue on github about this, but I can't find it).

Related

Replace PHPUnit method `withConsecutive`

As method withConsecutive will be deleted in PHPUnit 10 (in 9.6 it's deprecated) I need to replace all of occurrences of this method to new code.
Try to find some solutions and didn't find any of reasonable solution.
For example, I have a code
$this->personServiceMock->expects($this->exactly(2))
->method('prepare')
->withConsecutive(
[$personFirst, $employeeFirst],
[$personSecond, $employeeSecond],
)
->willReturnOnConsecutiveCalls($personDTO, $personSecondDTO);
To which code should I replace withConsecutive ?
P.S. Documentation on official site still shows how use withConsecutive
I've just upgraded to PHPUnit 10 and faced the same issue. Here's the solution I came to:
$this->personServiceMock
->method('prepare')
->willReturnCallback(fn($person, $employee) =>
match([$person, $employee]) {
[$personFirst, $employeeFirst] => $personDTO,
[$personSecond, $employeeSecond] => $personSecondDTO
}
);
If the mocked method is passed something other than what's expected in the match block, PHP will throw a UnhandledMatchError.
Looks like there are not exists solution from the box.
So, what I found - several solutions
Use your own trait which implements method withConsecutive
Use prophecy or mockery for mocking.

Trouble importing LESS files among different domains

Warning: The explanation may be a bit long. In case you are in a hurry, just skip directly to the end of the question, where I summarise what I'm looking for based in my problem.
Here is the problem: I have to load a LESS file (from domain A) from another LESS file (from domain B), and build them on real time with LESS.js. Until then, no harm; the instructions in the start of the official website work out of the box.
<link rel="stylesheet/less" type="text/css" href="styles.less" />
<script src="//cdnjs.cloudflare.com/ajax/libs/less.js/3.9.0/less.min.js" ></script>
However, there are other LESS files inside B (let's say module1/less, module2/less, and so on), and A should contain the #imports to those files. Also, there are multiple other domains similar to B (C, D, E...). That's where the problem starts. I couldn't find a proper way to do that, considering that I can't update C, D and E (other people need to do it, and for bureaucracy reasons they will only be able to do it after me), only A and B, so A needs to be compatible with the older version of C, D and E (in case they need any change).
When doing an #import inside an imported LESS file, its relative path is according to that same LESS file path, but since that LESS file may be loaded from B, C, D or E, I can't provide an absolute path out of the box.
What I tried (1): I surely need to find a way to provide the domain name from B to A. Firstly, I tried by adding something like that before the less.min.js line in the B domain HTML file:
<script>
less = {plugins: [{
install: function(less, pluginManager, functions) {
functions.add('getRootLessFolder', function() {
var getDomain = function() {
return window.location.protocol + "//" + window.location.host + "/";
}
return getDomain() + "less/";
});
}
}]}
</script>
And then adding that to the start of B's main LESS file:
#root-less-folder: getRootLessFolder();
So I could update the #imports in A to be like that:
#import "#{root-less-folder}module1/less";
That approach worked... until I tried using it with the older version of B, before making the changes mentioned above. In that way, LESS claims that #root-less-folder is undefined, even if I add (optional) to the #import.
What I tried (2): I also tried to use the paths property in server B, like that:
var getDomain = function() {
return window.location.protocol + "//" + window.location.host + "/";
}
var lessFolder = getDomain() + "less/";
less = {paths:[lessFolder]};
Because according to the documentation:
lessc --include-path=PATH1;PATH2 { paths: ['PATH1', 'PATH2'] }
If the file in an #import rule does not exist at that exact location, Less will look for it at the location(s) passed to this option. You might use this for instance to specify a path to a library which you want to be referenced simply and relatively in the Less files.
So I figured I could use it to make less find the LESS files automatically by just using the line below in A:
#import (optional) "module1/less";
So it wouldn't find module1/less in server A, but would find it in server B because of the paths property. Although, it doesn't seem to try to find module1/less in B. Instead, the Chrome Console spills the 404 error from server A, and the contents of module1/less from B are not present in the produced CSS style (no Console error either), like if it don't even tried.
What I need: I need a way to make method 1 or 2 work under those conditions, or even a method 3.
Being able to populate a LESS variable (if it is not populated only) would solve method 1;
Figuring out how LESS's paths is supposed to work may help using method 2;
Although, maybe you have another suggestion to that problem, which could work out as well.
I've managed to solve my problem. In case anyone else is having this trouble, I will describe what I did: apparently, while you can't reference variables that weren't defined, you can reference plugins that were not defined (in those cases, they are identified as strings).
So I added that before the less.min.js line in the B domain HTML file:
<script>
less = {plugins: [{
install: function(less, pluginManager, functions) {
functions.add('getRootLessFolder', function() {
var getDomain = function() {
return window.location.protocol + "//" + window.location.host + "/";
}
return getDomain() + "less/";
});
}
}]}
</script>
And updated the #imports in A to be like that:
#root-less-folder: getRootLessFolder();
#import (optional) "#{root-less-folder}module1/less";
So when getRootLessFolder is defined, the path is based in its returned value, and when it isn't, the path is "getRootLessFolder()module1/less", which will return a 404, but since it's an optional #import, that won't be a problem.
So if server B is updated, the change in server A is going to work. In case server B is not updated, the change is server A won't break it either.

Check if an existing value is in a database

I was wondering how I would go about checking to see if a table contains a value in a certain column.
I need to check if the column 'e-mail' contains an e-mail someone is trying to register with, and if something exists, do nothing, however, if nothing exists, insert the data into the database.
All I need to do is check if the e-mail column contains the value the user is registering with.
I'm using the RedBeanPHP ORM, I can do this without using it but I need to use that for program guidelines.
I've tried finding them but if they don't exist it returns an error within the redbean PHP file. Here's the error:Fatal error: Call to a member function find() on a non-object in /home/aeterna/www/user/rb.php on line 2433
Here's the code that I'm using when trying this:
function searchDatabase($email) {
return R::findOne('users', 'email LIKE "' . $email . '"');
}
My approach on the function would be
function searchDatabase($email) {
$data = array('email' => $email);
$user = R::findOne('users', 'email LIKE :email, $data);
if (!empty($user)) {
// do stuff here
} // end if
} // end function
It's a bit more clean and in your function
Seems like you are not connected to a database.
Have you done R::setup() before R::find()?
RedBeanPHP raises this error if it can't find the R::$redbean instance, the facade static functions just route calls to the $redbean object (to hide all object oriented fuzzyness for people who dont like that sort of thing).
However you need to bootstrap the facade using R::setup(). Normally you can start using RB with just two lines:
require('rb.php'); //cant make this any simpler :(
R::setup(); //this could be done in rb.php but people would not like that ;)
//and then go...
R::find( ... );
I recommend to check whether the $redbean object is available or whether for some reason the code flow has skipped the R::setup() boostrap method.
Edited to account for your updated question:
According to the error message, the error is happening inside the function find() in rb.php on line 2433. I'm guessing that rb.php is the RedBean package.
Make sure you've included rb.php in your script and set up your database, according to the instructions in the RedBean Manual.
As a starting point, look at what it's trying to do on line 2433 in rb.php. It appears to be calling a method on an invalid object. Figure out where that object is being created and why it's invalid. Maybe the find function was supplied with bad parameters.
Feel free to update your question by pasting the entirety of the find() function in rb.php and please indicate which line is 2433. If the function is too lengthy, you can paste it on a site like pastebin.com and link to it from here.
Your error sounds like you haven't done R::setup() yet.
My approach to performing the check you want would be something like this:
$count = count(R::find('users', 'email LIKE :email', array(':email' => $email)));
if($count === 0)
{
$user = R::dispense('users');
$user->name = $name;
$user->email = $email;
$user->dob = $dob;
R::store($user);
}
I don't know if it is this basic or not, but with SQL (using PHP for variables), a query could look like
$lookup = 'customerID';
$result = mysql_fetch_array(mysql_query("SELECT columnName IN tableName WHERE id='".$lookup."' LIMIT 1"));
$exists = is_null($result['columnName'])?false:true;
If you're just trying to find a single value in a database, you should always limit your result to 1, that way, if it is found in the first record, your query will stop.
Hope this helps

Why does this Rails named scope return empty (uninitialized?) objects?

In a Rails app, I have a model, Machine, that contains the following named scope:
named_scope :needs_updates, lambda {
{ :select => self.column_names.collect{|c| "\"machines\".\"#{c}\""}.join(','),
:group => self.column_names.collect{|c| "\"machines\".\"#{c}\""}.join(','),
:joins => 'LEFT JOIN "machine_updates" ON "machine_updates"."machine_id" = "machines"."id"',
:having => ['"machines"."manual_updates" = ? AND "machines"."in_use" = ? AND (MAX("machine_updates"."date") IS NULL OR MAX("machine_updates"."date") < ?)', true, true, UPDATE_THRESHOLD.days.ago]
}
}
This named scope works fine in development mode. In production mode, however, it returns the 2 models as expected, but the models are empty or uninitialized; that is, actual objects are returned (not nil), but all the fields are nil. For example, when inspecting the return value of the named scope in the console, the following is returned:
[#<Machine >, #<Machine >]
But, as you can see, all the fields of the objects returned are set to nil.
The production and development environments are essentially the same. Both are using a SQLite database. Here is the SQL statement that is generated for the query:
SELECT
"machines"."id",
"machines"."machine_name",
"machines"."hostname",
"machines"."mac_address",
"machines"."ip_address",
"machines"."hard_drive",
"machines"."ram",
"machines"."machine_type",
"machines"."use",
"machines"."comments",
"machines"."in_use",
"machines"."model",
"machines"."vendor_id",
"machines"."operating_system_id",
"machines"."location",
"machines"."acquisition_date",
"machines"."rpi_tag",
"machines"."processor",
"machines"."processor_speed",
"machines"."manual_updates",
"machines"."serial_number",
"machines"."owner"
FROM
"machines"
LEFT JOIN
"machine_updates" ON "machine_updates"."machine_id" = "machines"."id"
GROUP BY
"machines"."id",
"machines"."machine_name",
"machines"."hostname",
"machines"."mac_address",
"machines"."ip_address",
"machines"."hard_drive",
"machines"."ram",
"machines"."machine_type",
"machines"."use",
"machines"."comments",
"machines"."in_use",
"machines"."model",
"machines"."vendor_id",
"machines"."operating_system_id",
"machines"."location",
"machines"."acquisition_date",
"machines"."rpi_tag",
"machines"."processor",
"machines"."processor_speed",
"machines"."manual_updates",
"machines"."serial_number",
"machines"."owner"
HAVING
"machines"."manual_updates" = 't'
AND "machines"."in_use" = 't'
AND (MAX("machine_updates"."date") IS NULL
OR MAX("machine_updates"."date") < '2010-03-26 13:46:28')
Any ideas what's going wrong?
This might not be related to what is happening to you, but it sounds similar enough, so here it goes: are you using the rails cache for anything?
I got nearly the same results as you when I tried to cache the results of a query (as explained on railscast #115).
I tracked down the issue to a still open rails bug that makes cached ActiveRecords unusable - you have to choose between not using cached AR or applying a patch and getting memory leaks.
The cache works ok with non-AR objects, so I ended up "translating" the stuff I needed to integers and arrays, and cached that.
Hope this helps!
Seems like the grouping may be causing the problem. Is the data also identical in both dev & production?
Um, I'm not sure you're having the problem you think you're having.
[#<Machine >, #<Machine >]
implies that you have called "inspect" on the array... but not on each of the individual machine-objects inside it. This may be a silly question, but have you actually tried calling inspect on the individual Machine objects returned to really see if they have nil in the columns?
Machine.needs_updates.each do |m|
p m.inspect
end
?
If that does in fact result in nil-column data. My next suggestion is that you copy the generated SQL and go into the standard mysql interface and see what you get when you run that SQL... and then paste it into your question above so we can see.

Can I pretty-print the DBIC_TRACE output in DBIx::Class?

Setting the DBIC_TRACE environment variable to true:
BEGIN { $ENV{DBIC_TRACE} = 1 }
generates very helpful output, especially showing the SQL query that is being executed, but the SQL query is all on one line.
Is there a way to push it through some kinda "sql tidy" routine to format it better, perhaps breaking it up over multiple lines? Failing that, could anyone give me a nudge into where in the code I'd need to hack to add such a hook? And what the best tool is to accept a badly formatted SQL query and push out a nicely formatted one?
"nice formatting" in this context simply means better than "all on one line". I'm not particularly fussed about specific styles of formatting queries
Thanks!
As of DBIx::Class 0.08124 it's built in.
Just set $ENV{DBIC_TRACE_PROFILE} to console or console_monochrome.
From the documentation of DBIx::Class::Storage
If DBIC_TRACE is set then trace information is produced (as when the
debug method is set). ...
debug Causes trace information to be emitted on the debugobj
object. (or STDERR if debugobj has not specifically been set).
debugobj Sets or retrieves the object used for metric collection.
Defaults to an instance of DBIx::Class::Storage::Statistics that is
compatible with the original method of using a coderef as a callback.
See the aforementioned Statistics class for more information.
In other words, you should set debugobj in that class to an object that subclasses DBIx::Class::Storage::Statistics. In your subclass, you can reformat the query the way you want it to be.
First, thanks for the pointers! Partial answer follows ....
What I've got so far ... first some scaffolding:
# Connect to our db through DBIx::Class
my $schema = My::Schema->connect('dbi:SQLite:/home/me/accounts.db');
# See also BEGIN { $ENV{DBIC_TRACE} = 1 }
$schema->storage->debug(1);
# Create an instance of our subclassed (see below)
# DBIx::Class::Storage::Statistics class
my $stats = My::DBIx::Class::Storage::Statistics->new();
# Set the debugobj object on our schema's storage
$schema->storage->debugobj($stats);
And the definition of My::DBIx::Class::Storage::Statistics being:
package My::DBIx::Class::Storage::Statistics;
use base qw<DBIx::Class::Storage::Statistics>;
use Data::Dumper qw<Dumper>;
use SQL::Statement;
use SQL::Parser;
sub query_start {
my ($self, $sql_query, #params) = #_;
print "The original sql query is\n$sql_query\n\n";
my $parser = SQL::Parser->new();
my $stmt = SQL::Statement->new($sql_query, $parser);
#printf "%s\n", $stmt->command;
print "The parameters for this query are:";
print Dumper \#params;
}
Which solves the problem about how to hook in to get the SQL query for me to "pretty-ify".
Then I run a query:
my $rs = $schema->resultset('SomeTable')->search(
{
'email' => $email,
'others.some_col' => 1,
},
{ join => 'others' }
);
$rs->count;
However SQL::Parser barfs on the SQL generated by DBIx::Class:
The original sql query is
SELECT COUNT( * ) FROM some_table me LEFT JOIN others other_table ON ( others.some_col_id = me.id ) WHERE ( others.some_col_id = ? AND email = ? )
SQL ERROR: Bad table or column name '(others' has chars not alphanumeric or underscore!
SQL ERROR: No equijoin condition in WHERE or ON clause
So ... is there a better parser than SQL::Parser for the job?