Skip to content

Commit

Permalink
updates and fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
odow committed Dec 10, 2023
1 parent 25e1848 commit e98d59c
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 23 deletions.
10 changes: 10 additions & 0 deletions src/macros.jl
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,16 @@ function _add_kw_args(call, kw_args; exclude = Symbol[])
return
end

function _add_keyword_args(call::Expr, kwargs::Dict; exclude = Symbol[])
for (key, value) in kwargs
if key in exclude
continue
end
push!(call.args, esc(Expr(:kw, key, value)))
end
return
end

"""
_add_positional_args(call, args)::Nothing
Expand Down
34 changes: 21 additions & 13 deletions src/macros/@constraint.jl
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ user syntax: `@constraint(model, ref[...], expr, my_arg, kwargs...)`.
"""
macro constraint(input_args...)
error_fn(str...) = _macro_error(:constraint, input_args, __source__, str...)
args, kwargs, container = Containers._extract_kw_args(input_args)
args, kwargs = Containers.parse_macro_arguments(error_fn, input_args)
if length(args) < 2 && !isempty(kwargs)
error_fn(
"No constraint expression detected. If you are trying to " *
Expand All @@ -102,13 +102,12 @@ macro constraint(input_args...)
# [1:2] | Expr | :vect
# [i = 1:2, j = 1:2; i + j >= 3] | Expr | :vcat
# a constraint expression | Expr | :call or :comparison
c, x = if y isa Symbol || Meta.isexpr(y, (:vect, :vcat, :ref, :typed_vcat))
c, x = nothing, y
if y isa Symbol || Meta.isexpr(y, (:vect, :vcat, :ref, :typed_vcat))
if length(extra) == 0
error_fn("No constraint expression was given.")
end
y, popfirst!(extra)
else
nothing, y
c, x = y, popfirst!(extra)
end
if length(extra) > 1
error_fn("Cannot specify more than 1 additional positional argument.")
Expand All @@ -122,18 +121,27 @@ macro constraint(input_args...)
end
is_vectorized, parse_code, build_call = parse_constraint(error_fn, x)
_add_positional_args(build_call, extra)
_add_kw_args(build_call, kwargs; exclude = [:base_name, :set_string_name])
base_name = _get_kwarg_value(
_add_keyword_args(
build_call,
kwargs;
exclude = [:base_name, :container, :set_string_name],
)
# Handle keyword arguments
# ; base_name
base_name = get(
kwargs,
:base_name;
default = string(something(Containers._get_name(c), "")),
:base_name,
string(something(Containers._get_name(c), "")),
)
set_name_flag = _get_kwarg_value(
# ; set_string_name
set_string_name = get(
kwargs,
:set_string_name;
default = :(set_string_names_on_creation($model)),
:set_string_name,
:(set_string_names_on_creation($model)),
)
name_expr = :($set_name_flag ? $(_name_call(base_name, index_vars)) : "")
# ; container
container = get(kwargs, :container, :Auto)
name_expr = :($set_string_name ? $(_name_call(base_name, index_vars)) : "")
code = if is_vectorized
quote
$parse_code
Expand Down
10 changes: 5 additions & 5 deletions src/macros/@expression.jl
Original file line number Diff line number Diff line change
Expand Up @@ -54,17 +54,17 @@ julia> expr = @expression(model, [i in 1:3], i * sum(x[j] for j in 1:3))
"""
macro expression(input_args...)
error_fn(str...) = _macro_error(:expression, input_args, __source__, str...)
args, kw_args = Containers.parse_macro_arguments(error_fn, input_args)
args, kwargs = Containers.parse_macro_arguments(error_fn, input_args)
if !(2 <= length(args) <= 3)
error_fn("expected 2 or 3 positional arguments, got $(length(args)).")
elseif Meta.isexpr(args[2], :block)
error_fn("Invalid syntax. Did you mean to use `@expressions`?")
elseif !isempty(kw_args)
for key in keys(kw_args)
elseif !isempty(kwargs)
for key in keys(kwargs)
if key == :container
continue
end
error_fn("unrecognized keyword argument $key")
error_fn("unsupported keyword argument `$key`.")
end
end
name_expr = length(args) == 3 ? args[2] : nothing
Expand All @@ -83,7 +83,7 @@ macro expression(input_args...)
# other structure that returns `_MA.Zero()`.
_replace_zero($model, $expr)
end
container = get(kw_args, :container, :Auto)
container = get(kwargs, :container, :Auto)
return _finalize_macro(
model,
Containers.container_code(index_vars, indices, code, container),
Expand Down
8 changes: 4 additions & 4 deletions src/macros/@objective.jl
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,12 @@ x² - 2 x + 1
"""
macro objective(input_args...)
error_fn(str...) = _macro_error(:objective, input_args, __source__, str...)
args, kw_args = Containers.parse_macro_arguments(error_fn, input_args)
args, kwargs = Containers.parse_macro_arguments(error_fn, input_args)
if length(args) != 3
error_fn("expected 3 positional arguments, got $(length(args)).")
elseif !isempty(kw_args)
for key in keys(kw_args)
error_fn("unrecognized keyword argument $key")
elseif !isempty(kwargs)
for key in keys(kwargs)
error_fn("unsupported keyword argument `$key`.")
end
end
esc_model = esc(args[1])
Expand Down
14 changes: 13 additions & 1 deletion test/test_macros.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1716,13 +1716,25 @@ function test_expression_keyword_arguments()
@variable(model, x)
@test_macro_throws(
ErrorException(
"In `@expression(model, x, foo = 1)`: unrecognized keyword argument",
"In `@expression(model, x, foo = 1)`: unsupported keyword argument `foo`.",
),
@expression(model, x, foo = 1),
)
return
end

function test_objective_keyword_arguments()
model = Model()
@variable(model, x)
@test_macro_throws(
ErrorException(
"In `@objective(model, Min, x, foo = 1)`: unsupported keyword argument `foo`.",
),
@objective(model, Min, x, foo = 1),
)
return
end

function test_build_constraint_invalid()
model = Model()
@variable(model, x)
Expand Down

0 comments on commit e98d59c

Please sign in to comment.