Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add relation and equality operators #17

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

matedabis
Copy link
Contributor

@matedabis matedabis commented Feb 8, 2019

This generator tests ES v5.1 11.8. - 11.9. (except 11.8.7. and 11.8.6.), relation and equality operators (> >= <= < == === != !==).
The new validate function:

function validate_boolean(test_value, expected_result, false_result) {
    assert(test_value === expected_result);
    assert(test_value.toString() === expected_result.toString());
    assert(test_value !== false_result);
    assert(test_value.toString() !== false_result.toString());
}

A test case looks like this:

t1 = false;
t2 = null;
t3 = null;
t4 = false;
t5 = -2933530887918864;
t6 = false;
t7 = NaN;
t8 = '5871211041646662';
t9 = null;
t10 = NaN;
t11 = 5820634256891770;
f = true;
e = false;
validate_boolean(((((((((((t1 != t2) > t3) <= t4) <= t5) !== t6) !== t7) !== t8) >= t9) === t10) > t11)
, e, f);

declaration_string += "%s = '%s';\n" % (str(key), str(value))
else:
declaration_string += "%s = %d;\n" % (str(key), value)
declaration_string += "%s = %s;\n" % (str(key), str(value))
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This utility function is changes over and over the PRs. This should be finalized somehow.


class _InnerValues():
generated_filename = '''relation-equality-ops-{NUMBER}.js''' # The file name prefix of the generated
relational_and_equality_operators = ["equ", "nequ", "sequ", "snequ", "less", "moreorequ", "more", "lessorequ"]
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd suggest the: eq, neq, less, less_eq, greater, greater_eq namings.

elif (decider == 3):
self.operands[i] = "false"
elif (decider == 4):
self.operands[i] = "NaN"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about this?

if decider <= 4:
  self.operands[i] = special_values[i]

converted = "true"
else:
converted = "false"
return converted
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd suggest: return "true" if value else "false";

converted = "false"
return converted

# Add comas to the value if it is meant to be a string in the test case
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo: comas

(left_value == "undefined" and right_value == "null") or
(left_value == "null" and right_value == "undefined") or
(left_value == "true" and right_value == "true") or
(left_value == "false" and right_value == "false")):
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Create a mapping or something for these special cases. This look like a but ugly.

@matedabis matedabis force-pushed the add_binary_features branch 2 times, most recently from 6683c57 to 5ca07d7 Compare February 8, 2019 09:57
@matedabis
Copy link
Contributor Author

Updated the patch.


class _InnerValues():
generated_filename = '''relation-equality-ops-{NUMBER}.js''' # The file name prefix of the generated
relational_and_equality_operators = ["eq", "neq", "seq", "sneq", "less", "less_eq", "greater", "greater_eq"]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The assembly-like form would be much better. Please use the followings or the lowercase version of them instead!
EQ = equal
NE = not equal
GT = greater
LT = lesser
GE = greater and equal
LE = lesser and equal
SE (or STRICT_EQ) = strict equal
SN (or STRICT_NQ) = not strict equal

"seq": self.seq,
"neq": self.neq,
"sneq": self.sneq,
} # Functions for the operators
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about to generate getattr(self, relational_and_equality_operators[i]) for each elements of relational_and_equality_operators ?

} # Functions for the operators

# Generating the expression with operands and operators
def expression_maker(self):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expression_maker? The expression_generator sounds better.


# If it does not match the cases above and values are not undefined or null
elif (left_value != "undefined" and left_value != "null" and right_value != "null"
and right_value != "undefined"):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

elif left_value not in ["undefined", "null"] and right_value not in ["undefined", "null"]: ?

result = left_converted < right_converted
else:
result = int(left_converted) < int(right_converted)
result = self.convert_true_false_to_lowercase_string(result)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please combine these expressions!

# Greater than operator
def greater(self, left_value, right_value):
if (left_value == "NaN" or right_value == "NaN" or
left_value == "undefined" or right_value == "undefined"):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

?
if left_value in ["NaN", "undefined"] or right_value in ["NaN", "undefined"]:

# Less than or equal operator
def less_eq(self, left_value, right_value):
if (left_value == "NaN" or right_value == "NaN" or
left_value == "undefined" or right_value == "undefined"):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

?
if left_value in ["NaN", "undefined"] or right_value in ["NaN", "undefined"]:

# Greater than or equal operator
def greater_eq(self, left_value, right_value):
if (left_value == "NaN" or right_value == "NaN" or
left_value == "undefined" or right_value == "undefined"):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

?
if left_value in ["NaN", "undefined"] or right_value in ["NaN", "undefined"]:

write_file(gen_settings, self.file_output)
self.debug(Messages.done, self.options)

def main():
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you create separate main function? Do you want to call this why you are importing this class?
If you do not want that the main will be callable, please move its body under if __name__ == '__main__': block!

@matedabis
Copy link
Contributor Author

Updated the patch according to the review, and also found and fixed some bugs. I corrected almost everything mentioned, I have to reply to some questions.

expression_maker? The expression_generator sounds better.

I already have a function with that name so its not possible.

?
left_converted = {"true": 1, "false": 0}.get(left_value, int(left_value))

I had to check for true or false before, because it would try to convert the default value to int, and it throws error, this way it is still shorter and simpler than before.

if left_value in ["true", "false"]:
    left_converted = {"true": 1, "false": 0}.get(left_value)
else:
    left_converted = int(left_value)

Why do you create separate main function? Do you want to call this why you are importing this class?
If you do not want that the main will be callable, please move its body under if __name__ == '__main__': block!

I did not want it to make it callable, but this review gave me and idea so I left it as it was, but if you do not agree I will change it. When we reach the end of this project, and we will have more generators, we could create a script which calls all the generators and they each generate the same number of test cases which number is given by argparser, and we could add a command line option to run the generated tests with the test runner script after the generators finished generating, and maybe an another one, which deletes the .js files which did not fail (This would not be useful in all the cases, but as an option). And if this project seems to be useful, we could insert it to jerryscript's run-tests.py with a command line option. What do you think?

@loki04
Copy link
Contributor

loki04 commented Feb 13, 2019

Updated the patch according to the review, and also found and fixed some bugs. I corrected almost everything mentioned, I have to reply to some questions.

expression_maker? The expression_generator sounds better.

I already have a function with that name so its not possible.

It sounds weird. Please, try to find a different function name.

?
left_converted = {"true": 1, "false": 0}.get(left_value, int(left_value))

I had to check for true or false before, because it would try to convert the default value to int, and it throws error, this way it is still shorter and simpler than before.

Well, probably I wrote the int() at wrong position. Consider this instead:

for v in [0, 1, 42, -33, "123", "true", "false"]:
  out = int({"true": 1, "false": 0}.get(v, v))
  print(out, type(out))

0 <class 'int'>
1 <class 'int'>
42 <class 'int'>
-33 <class 'int'>
123 <class 'int'>
1 <class 'int'>
0 <class 'int'>

Why do you create separate main function? Do you want to call this why you are importing this class?
If you do not want that the main will be callable, please move its body under if __name__ == '__main__': block!

I did not want it to make it callable, but this review gave me and idea so I left it as it was, but if you do not agree I will change it. When we reach the end of this project, and we will have more generators, we could create a script which calls all the generators and they each generate the same number of test cases which number is given by argparser, and we could add a command line option to run the generated tests with the test runner script after the generators finished generating, and maybe an another one, which deletes the .js files which did not fail (This would not be useful in all the cases, but as an option). And if this project seems to be useful, we could insert it to jerryscript's run-tests.py with a command line option. What do you think?

This can be done and could be a good option, but I still can't see the need of a separate main. In your case we can import classes and use them as you described above.

def eq_helper_special_cases(self, values):
special_cases = [["undefined", "undefined"], ["null", "null"], ["undefined", "null"],
["null", "undefined"], ["true", "true"], ["false", "false"]]
return True if values in special_cases else False

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return values in special_cases is enough

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants