Skip to content

Commit

Permalink
Make asserts toggleable.
Browse files Browse the repository at this point in the history
  • Loading branch information
fredrikekre committed May 27, 2024
1 parent d688710 commit b10a7f9
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 5 deletions.
15 changes: 10 additions & 5 deletions src/Runic.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ module Runic
using JuliaSyntax:
JuliaSyntax, @K_str, @KSet_str

# compat for const fields
# Julia compat for const struct fields
@eval macro $(Symbol("const"))(field)
if VERSION >= v"1.8.0-DEV.1148"
Expr(:const, esc(field))
Expand All @@ -14,7 +14,8 @@ using JuliaSyntax:
end
end

include("chisel.jl")
# JuliaSyntax extensions and other utilities
include("chisels.jl")

# Return the result of expr if it doesn't evaluate to `nothing`
macro return_something(expr)
Expand All @@ -33,6 +34,7 @@ mutable struct Context
fmt_tree::Union{JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}, Nothing}
# User settings
verbose::Bool
assert::Bool
debug::Bool
# Current state
# node::Union{JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}, Nothing}
Expand All @@ -41,14 +43,17 @@ mutable struct Context
# parent::Union{JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}, Nothing}
end

function Context(src_str; debug::Bool = false, verbose::Bool = debug)
function Context(src_str; assert::Bool = true, debug::Bool = false, verbose::Bool = debug)
src_io = IOBuffer(src_str)
src_tree = JuliaSyntax.parseall(JuliaSyntax.GreenNode, src_str; ignore_warnings = true)
fmt_io = IOBuffer()
fmt_tree = nothing
# Debug mode enforces verbose and assert
verbose = debug ? true : verbose
assert = debug ? true : assert
return Context(
src_str, src_tree, src_io, fmt_io, fmt_tree, verbose, debug,
nothing, nothing,
src_str, src_tree, src_io, fmt_io, fmt_tree, verbose, assert, debug, nothing,
nothing,
)
end

Expand Down
44 changes: 44 additions & 0 deletions src/ToggleableAsserts.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# SPDX-License-Identifier: MIT

# The code in this file is derived from the ToggleableAsserts.jl package
# (https://github.com/MasonProtter/ToggleableAsserts.jl) licensed under the MIT license.
# (https://github.com/MasonProtter/ToggleableAsserts.jl/blob/master/LICENSE):

# MIT License
#
# Copyright (c) 2021 Mason Protter
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

assert_enabled() = true

macro assert(expr)
code = macroexpand_assert(expr)
:(assert_enabled() ? $(code) : nothing)
end

const toggle_lock = ReentrantLock()

function enable_assert(enable::Bool)
@lock toggle_lock begin
if assert_enabled() != enable
@eval Runic assert_enabled() = $enable
end
end
end
37 changes: 37 additions & 0 deletions src/chisel.jl → src/chisels.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,37 @@
# SPDX-License-Identifier: MIT

##############
# Debug info #
##############

# Code derived from ToggleableAsserts.jl kept in a separate file
include("ToggleableAsserts.jl")

abstract type RunicException <: Exception end

struct AssertionError <: RunicException
msg::String
end

function Base.showerror(io::IO, err::AssertionError)
print(
io,
"Runic.AssertionError: `", err.msg, "`. This is unexpected, " *
"please file an issue with a reproducible example at " *
"https://github.com/fredrikekre/Runic.jl/issues/new.",
)
end

function macroexpand_assert(expr)
msg = string(expr)
return :($(esc(expr)) || throw(AssertionError($msg)))
end


##########################
# JuliaSyntax extensions #
##########################

function is_leaf(node::JuliaSyntax.GreenNode)
return !JuliaSyntax.haschildren(node)
end
Expand All @@ -23,20 +55,25 @@ end
function is_assignment(node::JuliaSyntax.GreenNode)
return JuliaSyntax.is_prec_assignment(node)
end

# Just like `JuliaSyntax.is_infix_op_call`, but also check that the node is K"call"
function is_infix_op_call(node::JuliaSyntax.GreenNode)
return JuliaSyntax.kind(node) === K"call" &&
JuliaSyntax.is_infix_op_call(node)
end

function infix_op_call_op(node::JuliaSyntax.GreenNode)
@assert is_infix_op_call(node)
children = JuliaSyntax.children(node)::AbstractVector
first_operand_index = findfirst(!JuliaSyntax.is_whitespace, children)
op_index = findnext(JuliaSyntax.is_operator, children, first_operand_index + 1)
return children[op_index]
end

function is_comparison_leaf(node::JuliaSyntax.GreenNode)
return is_leaf(node) && JuliaSyntax.is_prec_comparison(node)
end

function is_operator_leaf(node::JuliaSyntax.GreenNode)
return is_leaf(node) && JuliaSyntax.is_operator(node)
end

0 comments on commit b10a7f9

Please sign in to comment.