Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/dev' into add-typechecking-for-i…
Browse files Browse the repository at this point in the history
…nsert!
  • Loading branch information
nicolaefilat committed May 24, 2024
2 parents 0bd802c + aca61f9 commit 3e1a45d
Show file tree
Hide file tree
Showing 11 changed files with 101 additions and 72 deletions.
8 changes: 8 additions & 0 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ jobs:
matrix:
version:
- '1.8'
- '1'
- 'nightly'
os:
- ubuntu-latest
Expand All @@ -33,3 +34,10 @@ jobs:
- uses: julia-actions/cache@v1
- uses: julia-actions/julia-buildpkg@v1
- uses: julia-actions/julia-runtest@v1
- uses: julia-actions/julia-processcoverage@v1
- uses: codecov/codecov-action@v4
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: lcov.info
fail_ci_if_error: false

2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "HerbGrammar"
uuid = "4ef9e186-2fe5-4b24-8de7-9f7291f24af7"
authors = ["Sebastijan Dumancic <[email protected]>", "Jaap de Jong <[email protected]>", "Nicolae Filat <[email protected]>", "Piotr Cichoń <[email protected]>"]
version = "0.2.2"
version = "0.3.0"

[deps]
AbstractTrees = "1520ce14-60c1-5f80-bbc7-55ef81b5835c"
Expand Down
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
# HerbGrammar.jl

[![codecov](https://codecov.io/github/Herb-AI/HerbGrammar.jl/graph/badge.svg?token=IKDBJC5IBK)](https://codecov.io/github/Herb-AI/HerbGrammar.jl)
[![Build Status](https://github.com/Herb-AI/HerbGrammar.jl/actions/workflows/CI.yml/badge.svg?branch=master)](https://github.com/Herb-AI/HerbGrammar.jl/actions/workflows/CI.yml?query=branch%3Amaster)
[![Dev-Docs](https://img.shields.io/badge/docs-latest-blue.svg)](https://Herb-AI.github.io/Herb.jl/dev)

# HerbGrammar.jl

This package contains functionality for declaring grammars for the Herb Program Synthesis framework.

For full documentation please see the [`Herb.jl` documentation](https://herb-ai.github.io/Herb.jl/dev/).
Expand Down
1 change: 0 additions & 1 deletion src/HerbGrammar.jl
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@ export
mindepth,
containedin,
subsequenceof,
has_children,
store_csg,
read_csg,
read_pcsg,
Expand Down
34 changes: 13 additions & 21 deletions src/csg/csg.jl
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ ContextSensitiveGrammar(
log_probabilities::Union{Vector{<:Real}, Nothing}
) = ContextSensitiveGrammar(rules, types, isterminal, iseval, bytype, domains, childtypes, bychildtypes, log_probabilities, AbstractConstraint[])

ContextSensitiveGrammar() = ContextSensitiveGrammar([], [], BitVector[], BitVector[], Dict{Symbol, Vector{Int}}(), Dict{Symbol, BitVector}(), Vector{Vector{Symbol}}(), Vector{BitVector}(), nothing, AbstractConstraint[])

"""
expr2csgrammar(ex::Expr)::ContextSensitiveGrammar
Expand All @@ -68,31 +70,15 @@ grammar = expr2csgrammar(
```
"""
function expr2csgrammar(ex::Expr)::ContextSensitiveGrammar
rules = Any[]
types = Symbol[]
bytype = Dict{Symbol,Vector{Int}}()
grammar = ContextSensitiveGrammar()

for e ex.args
if isa(e, Expr)
if e.head == :(=)
s = e.args[1] # name of return type
rule = e.args[2] # expression?
rvec = Any[]
parse_rule!(rvec, rule)
for r rvec
push!(rules, r)
push!(types, s)
bytype[s] = push!(get(bytype, s, Int[]), length(rules))
end
end
add_rule!(grammar, e)
end
end
alltypes = collect(keys(bytype))
is_terminal::Vector{Bool} = [isterminal(rule, alltypes) for rule rules]
is_eval::Vector{Bool} = [iseval(rule) for rule rules]
childtypes::Vector{Vector{Symbol}} = [get_childtypes(rule, alltypes) for rule rules]
domains = Dict(type => BitArray(r bytype[type] for r 1:length(rules)) for type alltypes)
bychildtypes = [BitVector([childtypes[i1] == childtypes[i2] for i2 1:length(rules)]) for i1 1:length(rules)]
return ContextSensitiveGrammar(rules, types, is_terminal, is_eval, bytype, domains, childtypes, bychildtypes, nothing)

return grammar
end


Expand Down Expand Up @@ -133,6 +119,12 @@ macro csgrammar(ex)
return expr2csgrammar(ex)
end


"""
@cfgrammar
This macro is deprecated and will be removed in future versions. Use [`@csgrammar`](@ref) instead.
"""
macro cfgrammar(ex)
return expr2csgrammar(ex)
end
Expand Down
2 changes: 1 addition & 1 deletion src/grammar_base.jl
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ function add_rule!(g::AbstractGrammar, e::Expr)
# Only add a rule if it does not exist yet. Check for existance
# with strict equality so that true and 1 are not considered
# equal. that means we can't use `in` or `∈` for equality checking.
if !any(r === rule for rule g.rules)
if !any(r === rule || typeof(r)==Expr && r == rule for rule g.rules)
push!(g.rules, r)
push!(g.iseval, iseval(rule))
push!(g.types, s)
Expand Down
48 changes: 12 additions & 36 deletions src/rulenode_operators.jl
Original file line number Diff line number Diff line change
Expand Up @@ -152,28 +152,6 @@ end
rulesonleft(::Hole, ::Vector{Int}) = Set{Int}()


#TODO: it seems like this function is exactly redefining what is already in HerbCore/rulenode.jl. It can be safely deleted
# """
# get_node_at_location(root::RuleNode, location::Vector{Int})

# Retrieves a [`RuleNode`](@ref) at the given location by reference.
# """
# function get_node_at_location(root::AbstractRuleNode, location::Vector{Int})
# if location == []
# return root
# else
# return get_node_at_location(root.children[location[1]], location[2:end])
# end
# end

# function get_node_at_location(root::VariableShapedHole, location::Vector{Int})
# if location == []
# return root
# end
# return nothing
# end


"""
rulenode2expr(rulenode::AbstractRuleNode, grammar::AbstractGrammar)
Expand All @@ -191,10 +169,9 @@ function rulenode2expr(rulenode::AbstractRuleNode, grammar::AbstractGrammar)
return root
end

function _get_hole_type(hole::Hole, grammar::AbstractGrammar)
#TODO: convert the children of UniformHoles to subexpressions
function _get_hole_type(hole::AbstractHole, grammar::AbstractGrammar)
@assert !isfilled(hole) "Hole $(hole) is convertable to an expression. There is no need to represent it using a symbol."
index = findfirst(rulenode.domain)
index = findfirst(hole.domain)
return isnothing(index) ? :Nothing : grammar.types[index]
end

Expand All @@ -205,27 +182,26 @@ function _rulenode2expr(expr::Expr, rulenode::AbstractRuleNode, grammar::Abstrac
expr.args[k],j = _rulenode2expr(arg, rulenode, grammar, j)
elseif haskey(grammar.bytype, arg)
child = rulenode.children[j+=1]
if !isfilled(rulenode)
return _get_hole_type(rulenode, grammar)
end
expr.args[k] = hasdynamicvalue(rulenode) ? child._val : deepcopy(grammar.rules[get_rule(child)])
if !isterminal(grammar, child)
expr.args[k],_ = _rulenode2expr(expr.args[k], child, grammar, 0)
if isfilled(child)
expr.args[k] = hasdynamicvalue(child) ? child._val : deepcopy(grammar.rules[get_rule(child)])
if !isterminal(grammar, child)
expr.args[k],_ = _rulenode2expr(expr.args[k], child, grammar, 0)
end
else
expr.args[k] = _get_hole_type(child, grammar)
end
end
end
return expr, j
end
return expr, j
end


function _rulenode2expr(typ::Symbol, rulenode::RuleNode, grammar::AbstractGrammar, j=0)
function _rulenode2expr(typ::Symbol, rulenode::AbstractRuleNode, grammar::AbstractGrammar, j=0)
@assert isfilled(rulenode) "grammar contains a duplicate rule"
retval = typ
if haskey(grammar.bytype, typ)
child = rulenode.children[1]
if isa(child, Hole)
return retval, j
end
retval = hasdynamicvalue(rulenode) ? child._val : deepcopy(grammar.rules[get_rule(child)])
if !grammar.isterminal[get_rule(child)]
retval,_ = _rulenode2expr(retval, child, grammar, 0)
Expand Down
10 changes: 0 additions & 10 deletions src/utils.jl
Original file line number Diff line number Diff line change
Expand Up @@ -150,13 +150,3 @@ function subsequenceof(vec1::Vector{Int}, vec2::Vector{Int})
return get(vec1, vec1_index, nothing) === nothing

end


"""
has_children(node::RuleNode)
Returns true if `node` has children
"""
has_children(node::RuleNode) = !isempty(node.children)
has_children(::Hole) = false

2 changes: 2 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
using HerbCore
using HerbGrammar
using Test

@testset "HerbGrammar.jl" verbose=true begin
include("test_csg.jl")
include("test_rulenode_operators.jl")
include("test_rulenode2expr.jl")
end
11 changes: 11 additions & 0 deletions test/test_csg.jl
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@
Real = 1 | 2 | 3
end
@test g₃.rules == [1,2,3]

g₄ = @cfgrammar begin
Real = 1 | 1
end
@test g₄.rules == [1]
end


Expand All @@ -38,6 +43,12 @@
# Basic adding
add_rule!(g₁, :(Real = 3))
@test g₁.rules == [1, 2, 3]
@test g₁.bytype[:Real] == [1, 2, 3]
@test g₁.types == [:Real, :Real, :Real]
@test g₁.isterminal == [true, true, true]
@test g₁.iseval == [false, false, false]
@test g₁.childtypes == [[], [], []]
@test g₁.bychildtypes == [BitVector((1, 1, 1)) for _ in 1:3]

# Adding multiple rules in one line
add_rule!(g₁, :(Real = 4 | 5))
Expand Down
50 changes: 50 additions & 0 deletions test/test_rulenode2expr.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
@testset verbose=true "rulenode2expr" begin
grammar = @csgrammar begin
S = 1
S = x
S = S + S
S = S * S
end

@testset "RuleNode" begin
node = RuleNode(3, [
RuleNode(3,[
RuleNode(1),
RuleNode(1)
]),
RuleNode(3,[
RuleNode(2),
RuleNode(1)
]),
])
@test string(rulenode2expr(node, grammar)) == "(1 + 1) + (x + 1)"
end

@testset "Hole" begin
node = RuleNode(3, [
RuleNode(3,[
RuleNode(1),
RuleNode(1)
]),
RuleNode(3,[
RuleNode(2),
Hole(get_domain(grammar, :S))
]),
])
@test string(rulenode2expr(node, grammar)) == "(1 + 1) + (x + S)"
end

@testset "UniformHole" begin
node = RuleNode(3, [
RuleNode(3,[
RuleNode(1),
RuleNode(1)
]),
UniformHole(BitVector((0, 0, 1, 1)),[
RuleNode(2),
RuleNode(1)
]),
])
@test string(rulenode2expr(node, grammar)) == "(1 + 1) + S"
end
end

0 comments on commit 3e1a45d

Please sign in to comment.