Skip to content

Commit

Permalink
Add typecheck for insert! for #66
Browse files Browse the repository at this point in the history
Add grammar to arguments to enable the check to be made.
  • Loading branch information
nicolaefilat committed Apr 22, 2024
1 parent ec7aa9b commit 0bd802c
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 12 deletions.
4 changes: 3 additions & 1 deletion src/HerbGrammar.jl
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ export
read_pcsg,
add_rule!,
remove_rule!,
cleanup_removed_rules!
cleanup_removed_rules!,

RuleNodeTypeCheckError

end # module HerbGrammar
35 changes: 25 additions & 10 deletions src/nodelocation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,34 @@ function Base.get(root::AbstractRuleNode, loc::NodeLoc)
end
end

struct RuleNodeTypeCheckError <: Exception
message::String
end

Base.showerror(io::IO, e::RuleNodeTypeCheckError) = print(io, e.message)

Check warning on line 35 in src/nodelocation.jl

View check run for this annotation

Codecov / codecov/patch

src/nodelocation.jl#L35

Added line #L35 was not covered by tests

"""
insert!(loc::NodeLoc, rulenode::RuleNode)
Replaces the subtree pointed to by loc with the given rulenode.
"""
function Base.insert!(root::RuleNode, loc::NodeLoc, rulenode::RuleNode)
parent, i = loc.parent, loc.i
if loc.i > 0
parent.children[i] = rulenode
else
root.ind = rulenode.ind
root._val = rulenode._val
root.children = rulenode.children
end
return root
function Base.insert!(root::RuleNode, loc::NodeLoc, rulenode::RuleNode, grammar::AbstractGrammar)
subtree = get(root, loc)
return_type_subtree = return_type(grammar, subtree.ind)
return_type_replacement = return_type(grammar, rulenode.ind)
# if the types do not match throw an error
if return_type_replacement !== return_type_subtree
throw(RuleNodeTypeCheckError("The provided replacement node does have the correct type to be replaced in the tree.
The subtree of the current tree expects a rule with type $return_type_subtree , but
the provided replacement has type $return_type_replacement"))
end

parent, i = loc.parent, loc.i
if loc.i > 0
parent.children[i] = rulenode
else
root.ind = rulenode.ind
root._val = rulenode._val
root.children = rulenode.children

Check warning on line 58 in src/nodelocation.jl

View check run for this annotation

Codecov / codecov/patch

src/nodelocation.jl#L56-L58

Added lines #L56 - L58 were not covered by tests
end
return root
end
28 changes: 27 additions & 1 deletion test/test_rulenode_operators.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
module SomeDefinitions
a_variable_that_is_defined = 7
a_variable_that_is_defined = 7
end

@testset verbose = true "RuleNode Operators" begin
Expand All @@ -15,4 +15,30 @@ end
@test !isvariable(g₁, RuleNode(7, g₁), SomeDefinitions)
@test isvariable(g₁, RuleNode(7, g₁))
end
@testset "Check typecheck for insert!" begin
g = @cfgrammar begin
Start = Int + Int
Int = 1
Int = 2
B = "notgood"
end

root = RuleNode(1, [RuleNode(2), RuleNode(2)]) # 1 + 1
replacement = RuleNode(4) # notgood
@test rulenode2expr(replacement, g) == :("notgood")
location = NodeLoc(root, 1) # first child

# attempting to replace type Int by type B should not work
@test_throws HerbGrammar.RuleNodeTypeCheckError insert!(root, location, replacement, g)

root = RuleNode(1, [RuleNode(2), RuleNode(2)]) # 1 + 1
replacement = RuleNode(3) # number 2
@test rulenode2expr(replacement, g) == :2
location = NodeLoc(root, 1) # first child

# replacing from (1 + 1) -> (2 + 1) should work
insert!(root, location, replacement, g)

@test rulenode2expr(root, g) == :(2 + 1)
end
end

0 comments on commit 0bd802c

Please sign in to comment.