Skip to content

Commit

Permalink
Added a new match type
Browse files Browse the repository at this point in the history
  • Loading branch information
JKRT committed Feb 29, 2024
1 parent 6f7f39e commit dbde540
Show file tree
Hide file tree
Showing 4 changed files with 144 additions and 72 deletions.
2 changes: 1 addition & 1 deletion src/MetaModelica.jl
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ include("metaRuntime.jl")
include("shouldFail.jl")
include("utilityMacros.jl")

export @match, @matchcontinue, MatchFailure, ModelicaReal, ModelicaInteger
export @match, @matchcontinue, @unsafematch, MatchFailure, ModelicaReal, ModelicaInteger
export @Uniontype, @Record, @UniontypeDecl, @ExtendedFunction, @ExtendedAnonFunction
export List, list, Nil, nil, Cons, cons, =>, Option, SOME, NONE, SourceInfo, SOURCEINFO
export @do_threaded_for, <|, @shouldFail, sourceInfo, _cons, @importDBG
Expand Down
77 changes: 72 additions & 5 deletions src/matchcontinue.jl
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ function handle_destruct(value::Symbol, pattern, bound::Set{Symbol}, asserts::Ve
push!(asserts,
quote
a = typeof($(esc(T)))
#= NONE is a function. However, we treat it a bit special=#
#= NONE is a function. However, we treat it as a special case =#
if $(esc(T)) !== NONE && typeof($(esc(T))) <: Function
func = $(esc(T))
file = @__FILE__
Expand Down Expand Up @@ -360,10 +360,62 @@ end


"""
Top level function for all match macros except
the match equation macro.
Top level function for all match macros except for the match equation macro.
"""
function handle_match_cases(value, match::Expr; mathcontinue::Bool=false)
tail = nothing
if match.head != :block
error("Unrecognized match syntax: Expected begin block $match")
end
line = nothing
local neverFails = false
cases = Expr[]
asserts = Expr[]
for arg in match.args
if isa(arg, LineNumberNode)
line = arg
continue
elseif isa(arg, Expr)
push!(cases, arg)
end
end
for case in reverse(cases)
tail = handle_match_case(:value, case, tail, asserts, mathcontinue)
if line !== nothing
replaceLineNum(tail, @__FILE__, line)
end
#= If one case contains a _ we know this match never fails. =#
pat = case.args[2]
if pat === :_
neverFails = true
end
end
if neverFails == false || mathcontinue
quote
$(asserts...)
local value = $(esc(value))
local __omc_match_done::Bool = false
local res
$tail
if !__omc_match_done
throw(MatchFailure("unfinished", value))
end
res
end
else
quote
$(asserts...)
local value = $(esc(value))
local __omc_match_done::Bool = false
local res
$tail
res
end
end
end


function unsafe_handle_match_cases(value, match::Expr; mathcontinue::Bool=false)
tail = nothing
if match.head != :block
error("Unrecognized match syntax: Expected begin block $match")
Expand Down Expand Up @@ -392,9 +444,10 @@ function handle_match_cases(value, match::Expr; mathcontinue::Bool=false)
local res
$tail
if !__omc_match_done
throw(MatchFailure("unfinished", value))
value
else
res
end
res
end
end

Expand Down Expand Up @@ -438,6 +491,20 @@ macro match(value, cases)
res
end

"""
@unsafematch value begin
pattern1 => result1
pattern2 => result2
...
end
Return `result` for the first matching `pattern`. If there are no matches, returns `value`.
"""
macro unsafematch(value, cases)
res = unsafe_handle_match_cases(value, cases; mathcontinue=false)
replaceLineNum(res, @__FILE__, __source__)
res
end

"""
Patterns:
Expand Down
Loading

0 comments on commit dbde540

Please sign in to comment.