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

Adapt nyan to new specification #84

Closed
wants to merge 71 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
71 commits
Select commit Hold shift + click to select a range
ef6cf3b
lexer: Add '!' (bang) as symbol.
heinezen Oct 5, 2020
ec687e0
lexer: Enforce 'version' as first argument in file.
heinezen Oct 6, 2020
e017655
lexer: Fix dates and include dict type.
heinezen Oct 12, 2020
05f74f6
parser: Read arbitrary member type arguments.
heinezen Oct 16, 2020
1083219
nyan: Allow floats for int operations.
heinezen Oct 17, 2020
d075d25
nyan: Define values for float/int positive and negative infinty.
heinezen Oct 17, 2020
c9a9daa
nyan: Calculus rules for infinity.
heinezen Oct 18, 2020
d2a9005
lexer: Parse inf/-inf tokens.
heinezen Oct 19, 2020
e29f7d4
nyan: Fix handling infinity pointer.
heinezen Oct 19, 2020
8e902ec
nyan: Change bool's True/False to pythonic notation.
heinezen Oct 19, 2020
0b873cf
nyan: ValueToken for more complex values.
heinezen Oct 24, 2020
096317c
nyan: Use ValueToken while creating AST and Value instances.
heinezen Oct 25, 2020
c1b62b5
parser: Parse dict items.
heinezen Oct 25, 2020
32df34b
nyan: Dict data type.
heinezen Oct 27, 2020
6b19fab
nyan: Make 'element_type' of Type a vector.
heinezen Nov 22, 2020
6902201
dict: Create dicts from nyan file.
heinezen Nov 22, 2020
4b005dd
dict: Intersection operation.
heinezen Nov 23, 2020
80ea0e9
dict: Iterator logic.
heinezen Nov 25, 2020
f4000a4
refactor: Rename container types to composite types. Include type mod…
heinezen Nov 26, 2020
5995d04
parser: Allow limiting the number of read elements in comma_list().
heinezen Nov 28, 2020
4497163
parser: Allow nested types.
heinezen Nov 28, 2020
5090faf
init: New function for extracting value from ValueToken.
heinezen Dec 11, 2020
28465f5
nyan: Check for "None" value.
heinezen Dec 11, 2020
436071b
nyan: None value.
heinezen Dec 12, 2020
2eee390
nyan: Check modifiers.
heinezen Dec 12, 2020
6d02965
refactor: Add comments to ast.h.
heinezen Dec 12, 2020
1af9713
refactor: Add comments to api_error.h.
heinezen Dec 16, 2020
f1a190e
refactor: Add comments to basic_type.h.
heinezen Dec 16, 2020
fee9488
refactor: Add comments to c3.h.
heinezen Dec 16, 2020
78cd996
refactor: Add comments to change_tracker.h.
heinezen Dec 16, 2020
aeeaa1b
refactor: Add comments to curve.h.
heinezen Dec 16, 2020
d1c52d9
refactor: Add comments to database.h.
heinezen Dec 16, 2020
9c2a7fe
refactor: Add comments to error.h.
heinezen Dec 16, 2020
06212ba
refactor: Add comments to file.h.
heinezen Dec 16, 2020
ecbb66f
refactor: Add comments to id_token.h.
heinezen Dec 16, 2020
ef2bf3a
refactor: Add comments to inheritance_change.h.
heinezen Dec 16, 2020
458bb5e
refactor: Add comments to lang_error.h.
heinezen Dec 16, 2020
9a4c8ab
refactor: Add comments to location.h.
heinezen Dec 16, 2020
6358d0e
refactor: Add comments to member_info.h.
heinezen Dec 19, 2020
36af270
refactor: Add comments to member.h.
heinezen Dec 19, 2020
312914b
refactor: Add comments to meta_info.h.
heinezen Dec 19, 2020
6756dc1
refactor: Add comments to namespace_finder.h.
heinezen Dec 20, 2020
d139bab
refactor: Add comments to namespace.h.
heinezen Dec 20, 2020
a54937e
refactor: Add comments to object_history.h.
heinezen Dec 20, 2020
bf5db02
refactor: Add comments to object_info.h.
heinezen Dec 20, 2020
4025fff
refactor: Add comments to object_notifier.h.
heinezen Dec 20, 2020
5ed8e63
refactor: Add comments to object_state.h.
heinezen Dec 20, 2020
d48c873
refactor: Add comments to object.h.
heinezen Dec 20, 2020
a345388
refactor: Add comments to ops.h.
heinezen Dec 20, 2020
492d730
refactor: Add comments to parser.h.
heinezen Dec 20, 2020
c6e080a
refactor: Add comments to patch_info.h.
heinezen Dec 20, 2020
0f79321
refactor: Add comments to state_history.h.
heinezen Dec 20, 2020
9122237
refactor: Add comments to state.h.
heinezen Dec 20, 2020
543478d
refactor: Add comments to token_stream.h.
heinezen Dec 20, 2020
8ba7e7a
refactor: Add comments to token.h.
heinezen Dec 20, 2020
549855c
refactor: Add comments to transaction.h.
heinezen Dec 21, 2020
ba2cdfc
refactor: Add comments to type.h.
heinezen Dec 21, 2020
7d5dfaa
refactor: Add comments to util.h.
heinezen Dec 21, 2020
22b1725
refactor: Add comments to value_token.h.
heinezen Dec 21, 2020
8fd9b9e
refactor: Add comments to value.h.
heinezen Dec 21, 2020
ccae9c0
refactor: Add comments to value_holder.h.
heinezen Dec 21, 2020
bb3dfd4
refactor: Convert tabs to spaces in files.
heinezen Dec 21, 2020
1a092e3
fix copyright dates.
heinezen Dec 21, 2020
90097df
nyan: Assign None directly on Member::apply().
heinezen Dec 23, 2020
3cb82d7
parser: Use switch statement for differentiating composite types.
heinezen Jan 15, 2021
590c268
dict: Comment fixes.
heinezen Jan 15, 2021
2831c7e
ast: Use size_t for comma list boundary.
heinezen Jan 15, 2021
a83907e
nyan: Cody styling for is_none() function.
heinezen Jan 15, 2021
8e537c9
nyan: Remove unused parameters from lambda functions.
heinezen Jan 15, 2021
b8952bf
nyan: Better description for None.
heinezen Jan 15, 2021
72f5e03
parser: Replace ifs in handle_modifiers() with switch statement.
heinezen Jan 15, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 12 additions & 3 deletions nyan/value/boolean.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,16 +96,25 @@ bool Boolean::equals(const Value &other) const {


const std::unordered_set<nyan_op> &Boolean::allowed_operations(const Type &with_type) const {

const static std::unordered_set<nyan_op> none_ops{
nyan_op::ASSIGN,
};

const static std::unordered_set<nyan_op> ops{
nyan_op::ASSIGN,
nyan_op::UNION_ASSIGN,
nyan_op::INTERSECT_ASSIGN,
};

if (with_type.get_primitive_type() == primitive_t::BOOLEAN) {
switch (with_type.get_primitive_type()) {
case primitive_t::BOOLEAN:
return ops;
}
else {

case primitive_t::NONE:
return none_ops;

default:
return no_nyan_ops;
}
}
Expand Down
14 changes: 11 additions & 3 deletions nyan/value/dict.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -229,9 +229,9 @@ void Dict::apply_value(const Value &value, nyan_op operation) {

const std::unordered_set<nyan_op> &Dict::allowed_operations(const Type &with_type) const {

if (not with_type.is_container()) {
return no_nyan_ops;
}
const static std::unordered_set<nyan_op> none_ops{
nyan_op::ASSIGN,
};

const static std::unordered_set<nyan_op> set_ops{
nyan_op::SUBTRACT_ASSIGN,
Expand All @@ -245,6 +245,14 @@ const std::unordered_set<nyan_op> &Dict::allowed_operations(const Type &with_typ
nyan_op::INTERSECT_ASSIGN,
};

if (with_type.get_primitive_type() == primitive_t::NONE) {
return none_ops;
Copy link
Member

Choose a reason for hiding this comment

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

why can we assign = None to a dict? that shouldn't work.

Copy link
Member Author

Choose a reason for hiding this comment

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

None is assigned directly to the member, it's not applied like the other values. However, we still need to list it here because assigning None is an allowed operation.

}

if (not with_type.is_container()) {
return no_nyan_ops;
}

switch (with_type.get_composite_type()) {
case composite_t::SET:
case composite_t::ORDEREDSET:
Expand Down
8 changes: 5 additions & 3 deletions nyan/value/file.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,12 @@ const std::unordered_set<nyan_op> &Filename::allowed_operations(const Type &with
nyan_op::ASSIGN,
};

if (with_type.get_primitive_type() == primitive_t::FILENAME) {
switch (with_type.get_primitive_type()) {
case primitive_t::FILENAME:
case primitive_t::NONE:
Copy link
Member

Choose a reason for hiding this comment

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

why can we assign = None to a filename?

Copy link
Member Author

Choose a reason for hiding this comment

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

return ops;
}
else {

default:
return no_nyan_ops;
}
}
Expand Down
8 changes: 8 additions & 0 deletions nyan/value/number.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,10 @@ template <typename T>
const std::unordered_set<nyan_op> &
Number<T>::allowed_operations(const Type &with_type) const {

const static std::unordered_set<nyan_op> none_ops{
nyan_op::ASSIGN,
};

const static std::unordered_set<nyan_op> ops{
nyan_op::ASSIGN,
nyan_op::ADD_ASSIGN,
Expand All @@ -403,6 +407,10 @@ Number<T>::allowed_operations(const Type &with_type) const {
case primitive_t::FLOAT:
case primitive_t::INT:
return ops;

case primitive_t::NONE:
return none_ops;
Copy link
Member

Choose a reason for hiding this comment

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

why can we assign = None to a number?

Copy link
Member Author

Choose a reason for hiding this comment

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


default:
return no_nyan_ops;
}
Expand Down
8 changes: 5 additions & 3 deletions nyan/value/object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,12 @@ const std::unordered_set<nyan_op> &ObjectValue::allowed_operations(const Type &w
nyan_op::ASSIGN,
};

if (with_type.get_primitive_type() == primitive_t::OBJECT) {
switch (with_type.get_primitive_type()) {
case primitive_t::OBJECT:
case primitive_t::NONE:
return ops;
Copy link
Member

Choose a reason for hiding this comment

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

why can we assign = None to an object?

Copy link
Member Author

Choose a reason for hiding this comment

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

}
else {

default:
return no_nyan_ops;
}
}
Expand Down
13 changes: 10 additions & 3 deletions nyan/value/orderedset.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,9 @@ std::string OrderedSet::repr() const {

const std::unordered_set<nyan_op> &OrderedSet::allowed_operations(const Type &with_type) const {

if (not with_type.is_container()) {
return no_nyan_ops;
}
const static std::unordered_set<nyan_op> none_ops{
nyan_op::ASSIGN,
};

const static std::unordered_set<nyan_op> orderedset_ops{
nyan_op::ASSIGN,
Expand All @@ -88,6 +88,13 @@ const std::unordered_set<nyan_op> &OrderedSet::allowed_operations(const Type &wi
nyan_op::INTERSECT_ASSIGN,
};

if (with_type.get_primitive_type() == primitive_t::NONE) {
return none_ops;
Copy link
Member

Choose a reason for hiding this comment

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

why can we assign = None to an orderedset?

Copy link
Member Author

Choose a reason for hiding this comment

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

}

if (not with_type.is_container()) {
return no_nyan_ops;
}

switch (with_type.get_composite_type()) {
case composite_t::ORDEREDSET:
Expand Down
14 changes: 11 additions & 3 deletions nyan/value/set.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,9 @@ std::string Set::repr() const {

const std::unordered_set<nyan_op> &Set::allowed_operations(const Type &with_type) const {

if (not with_type.is_container()) {
return no_nyan_ops;
}
const static std::unordered_set<nyan_op> none_ops{
nyan_op::ASSIGN,
};

const static std::unordered_set<nyan_op> set_ops{
nyan_op::ASSIGN,
Expand All @@ -90,6 +90,14 @@ const std::unordered_set<nyan_op> &Set::allowed_operations(const Type &with_type
nyan_op::INTERSECT_ASSIGN,
};

if (with_type.get_primitive_type() == primitive_t::NONE) {
return none_ops;
Copy link
Member

Choose a reason for hiding this comment

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

why can we assign = None to a set?

Copy link
Member Author

Choose a reason for hiding this comment

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

}

if (not with_type.is_container()) {
return no_nyan_ops;
}

switch (with_type.get_composite_type()) {
case composite_t::SET:
return set_ops;
Expand Down
14 changes: 11 additions & 3 deletions nyan/value/text.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,18 @@ const std::unordered_set<nyan_op> &Text::allowed_operations(const Type &with_typ
nyan_op::ADD_ASSIGN,
};

if (with_type.get_primitive_type() == primitive_t::TEXT) {
const static std::unordered_set<nyan_op> none_ops{
nyan_op::ASSIGN,
};

switch (with_type.get_primitive_type()) {
case primitive_t::TEXT:
return ops;
}
else {

case primitive_t::NONE:
return none_ops;
Copy link
Member

Choose a reason for hiding this comment

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

why can we assign = None to a text?

Copy link
Member Author

Choose a reason for hiding this comment

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


default:
return no_nyan_ops;
}
}
Expand Down
73 changes: 58 additions & 15 deletions nyan/value/value.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,18 @@ static void handle_modifiers(const std::vector<Type> &modifiers,
const ValueHolder &value_holder,
std::vector<std::pair<fqon_t, Location>> *objs_in_values) {
bool contains_optional = false;
for (auto &mod: modifiers) {
auto modifier_type = mod.get_composite_type();

if (modifier_type == composite_t::OPTIONAL) {
TheJJ marked this conversation as resolved.
Show resolved Hide resolved
contains_optional = true;
}
Copy link
Member

@TheJJ TheJJ Jan 11, 2021

Choose a reason for hiding this comment

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

interesting corner case, which optional do we assign to in optional(optional(int)) = None (it won't matter in practice since the returnvalue is None in either way). or optional(bool) = None where it will matter in practice.

Copy link
Member Author

Choose a reason for hiding this comment

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

It is just assigned to the member because optional does not have its own Value instance. In the current implementation optional(optional(int)) is treated the same as optional(int).

Copy link
Member

Choose a reason for hiding this comment

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

ok that resolves that, but what about optional(bool) = None? we have do decide on a behavior there, i'd say we try to assign it from the inside to the outside until the operator = is accepted. then we also don't need all the none-assignments in all the types

}

if (typeid(*value_holder.get_value()) == typeid(None&) and not contains_optional) {
throw InternalError{"NoneValue is content, but no optional modifier was found"};
}

for (auto &mod: modifiers) {
auto modifier_type = mod.get_composite_type();

Expand All @@ -133,7 +145,9 @@ static void handle_modifiers(const std::vector<Type> &modifiers,

if (modifier_type == composite_t::CHILDREN) {
if (unlikely(typeid(*value_holder.get_value()) != typeid(ObjectValue&))) {
throw InternalError{"children type requires ObjectValue as content"};
if (not contains_optional) {
throw InternalError{"children type requires ObjectValue as content"};
}
}

// Check if object fqon is a child (i.e. not the same fqon as the member type)
Expand All @@ -147,19 +161,16 @@ static void handle_modifiers(const std::vector<Type> &modifiers,

if (modifier_type == composite_t::ABSTRACT) {
if (unlikely(typeid(*value_holder.get_value()) != typeid(ObjectValue&))) {
throw InternalError{"abstract type requires ObjectValue as content"};
if (not contains_optional) {
throw InternalError{"abstract type requires ObjectValue as content"};
}
}

// Remove last element here, so the object is not checked
// for non-abstractness later
objs_in_values->pop_back();
Copy link
Member

Choose a reason for hiding this comment

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

that's bad, since there's also other checks with all the objects used as values. better would be that within that check which validates if objects used as values can be used as such, the checker is aware of the modifiers and validate None, abstractness and children there. These modifiers update the hierarchy validity, and Database::check_hierarchy verifies exactly that.

Copy link
Member Author

Choose a reason for hiding this comment

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

This is a list and not a set, so it's technically fine. It removes only the reference that was added right after the value was created. Although having a set overall would definitely better for not wasting memory on the value.

Copy link
Member

Choose a reason for hiding this comment

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

no, it's not about lists or sets, rather removing this object from the to-be-checked bunch of names :)

}
}

if (typeid(*value_holder.get_value()) == typeid(None&) and not contains_optional) {
throw InternalError{"NoneValue is content, but no optional modifier was found"};
}

}
ValueHolder Value::from_ast(const Type &target_type,
const ASTMemberValue &astmembervalue,
Expand Down Expand Up @@ -205,7 +216,7 @@ ValueHolder Value::from_ast(const Type &target_type,
return value;
}

composite_t composite_type = astmembervalue.get_composite_type();
composite_t composite_type = current_type.get_composite_type();

// For sets/orderedsets (with primitive values)
std::vector<ValueHolder> values;
Expand All @@ -218,17 +229,30 @@ ValueHolder Value::from_ast(const Type &target_type,
values.reserve(astmembervalue.get_values().size());

// convert all tokens to values
const std::vector<Type> *element_type = target_type.get_element_type();
const std::vector<Type> *element_type = current_type.get_element_type();
if (unlikely(element_type == nullptr)) {
throw InternalError{"container element type is nonexisting"};
}

Type cur_elem_type = element_type->at(0);
std::vector<Type> elem_modifiers;
while (cur_elem_type.is_modifier()) {
elem_modifiers.insert(elem_modifiers.begin(), cur_elem_type);
cur_elem_type = cur_elem_type.get_element_type()->at(0);
}

std::vector<Type> target_types{cur_elem_type};
for (auto &value_token : astmembervalue.get_values()) {
values.push_back(
value_from_value_token(*element_type,
value_token,
get_fqon)[0]
);
ValueHolder value = value_from_value_token(
target_types,
value_token,
get_fqon
)[0];

handle_modifiers(elem_modifiers, value, objs_in_values);

values.push_back(value);

}

switch (composite_type) {
Expand All @@ -252,13 +276,32 @@ ValueHolder Value::from_ast(const Type &target_type,
throw InternalError{"container element type is nonexisting"};
}

Type cur_elem_type_key = element_type->at(0);
std::vector<Type> elem_modifiers_key;
while (cur_elem_type_key.is_modifier()) {
elem_modifiers_key.insert(elem_modifiers_key.begin(), cur_elem_type_key);
cur_elem_type_key = cur_elem_type_key.get_element_type()->at(0);
}

Type cur_elem_type_value = element_type->at(1);
std::vector<Type> elem_modifiers_value;
while (cur_elem_type_value.is_modifier()) {
elem_modifiers_value.insert(elem_modifiers_value.begin(), cur_elem_type_value);
cur_elem_type_value = cur_elem_type_value.get_element_type()->at(0);
}

std::vector<Type> target_types{cur_elem_type_key, cur_elem_type_value};

for (auto &value_token : astmembervalue.get_values()) {
std::vector<ValueHolder> keyval = value_from_value_token(
*element_type,
target_types,
value_token,
get_fqon
);

handle_modifiers(elem_modifiers_key, keyval[0], objs_in_values);
handle_modifiers(elem_modifiers_value, keyval[1], objs_in_values);

items.insert(std::make_pair(keyval[0], keyval[1]));
}

Expand Down
2 changes: 1 addition & 1 deletion test/test.nyan
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ First():
wat : abstract(First) = Second
wat2 : abstract(children(First)) = Second
wat3 : optional(First) = Second
# wat4 : set(children(First)) = None
wat4 : set(children(First)) = {Second}
member : int = 15
test : text = "rofl lol"
bla : file = "wtf.h4x"
Expand Down