From 88bd24726dbf845aa645c375750df9f21b019052 Mon Sep 17 00:00:00 2001 From: Philipp Gabler Date: Sat, 21 Aug 2021 19:08:33 +0200 Subject: [PATCH 01/10] First try, not working --- src/compiler.jl | 91 ++++++++++++++++++++++++------------------------- 1 file changed, 45 insertions(+), 46 deletions(-) diff --git a/src/compiler.jl b/src/compiler.jl index 4e32b7d5a..49cce4535 100644 --- a/src/compiler.jl +++ b/src/compiler.jl @@ -1,6 +1,10 @@ const INTERNALNAMES = (:__model__, :__sampler__, :__context__, :__varinfo__, :__rng__) const DEPRECATED_INTERNALNAMES = (:_model, :_sampler, :_context, :_varinfo, :_rng) +for name in INTERNALNAMES + @eval $(Symbol(uppercase(string(name)))) = $(Meta.quot((name))) +end + """ isassumption(expr) @@ -16,11 +20,9 @@ Let `expr` be `:(x[1])`. It is an assumption in the following cases: When `expr` is not an expression or symbol (i.e., a literal), this expands to `false`. """ function isassumption(expr::Union{Symbol,Expr}) - vn = gensym(:vn) - return quote - let $vn = $(varname(expr)) - if $(DynamicPPL.contextual_isassumption)(__context__, $vn) + let vn = $(varname(expr)) + if $(DynamicPPL.contextual_isassumption)($__CONTEXT__, vn) # Considered an assumption by `__context__` which means either: # 1. We hit the default implementation, e.g. using `DefaultContext`, # which in turn means that we haven't considered if it's one of @@ -34,8 +36,8 @@ function isassumption(expr::Union{Symbol,Expr}) # TODO: Support by adding context to model, and use `model.args` # as the default conditioning. Then we no longer need to check `inargnames` # since it will all be handled by `contextual_isassumption`. - if !($(DynamicPPL.inargnames)($vn, __model__)) || - $(DynamicPPL.inmissings)($vn, __model__) + if !($(DynamicPPL.inargnames)(vn, $__MODEL__)) || + $(DynamicPPL.inmissings)(vn, $__MODEL__) true else $(maybe_view(expr)) === missing @@ -201,7 +203,7 @@ To generate a `Model`, call `model(xvalue)` or `model(xvalue, yvalue)`. macro model(expr, warn=false) # include `LineNumberNode` with information about the call site in the # generated function for easier debugging and interpretation of error messages - return esc(model(__module__, __source__, expr, warn)) + return model(__module__, __source__, expr, warn) end function model(mod, linenumbernode, expr, warn) @@ -325,7 +327,7 @@ function generate_mainbody!(mod, found, sym::Symbol, warn) end function generate_mainbody!(mod, found, expr::Expr, warn) # Do not touch interpolated expressions - expr.head === :$ && return expr.args[1] + Meta.isexpr(expr, :$) && return esc(expr.args[1]) # If it's a macro, we expand it if Meta.isexpr(expr, :macrocall) @@ -370,40 +372,39 @@ function generate_tilde(left, right) if isliteral(left) return quote $(DynamicPPL.tilde_observe!)( - __context__, $(DynamicPPL.check_tilde_rhs)($right), $left, __varinfo__ + $__CONTEXT__, $(DynamicPPL.check_tilde_rhs)($right), $left, $__VARINFO__ ) end end # Otherwise it is determined by the model or its value, # if the LHS represents an observation - @gensym vn inds isassumption return quote - $vn = $(varname(left)) - $inds = $(vinds(left)) - $isassumption = $(DynamicPPL.isassumption(left)) - if $isassumption + vn = $(varname(left)) + inds = $(vinds(left)) + isassumption = $(DynamicPPL.isassumption(left)) + if isassumption $left = $(DynamicPPL.tilde_assume!)( - __context__, + $__CONTEXT__, $(DynamicPPL.unwrap_right_vn)( - $(DynamicPPL.check_tilde_rhs)($right), $vn + $(DynamicPPL.check_tilde_rhs)($right), vn )..., - $inds, - __varinfo__, + inds, + $__VARINFO__, ) else # If `vn` is not in `argnames`, we need to make sure that the variable is defined. - if !$(DynamicPPL.inargnames)($vn, __model__) - $left = $(DynamicPPL.getvalue_nested)(__context__, $vn) + if !$(DynamicPPL.inargnames)(vn, $__MODEL__) + $left = $(DynamicPPL.getvalue_nested)($__CONTEXT__, vn) end $(DynamicPPL.tilde_observe!)( - __context__, + $__CONTEXT__, $(DynamicPPL.check_tilde_rhs)($right), $(maybe_view(left)), - $vn, - $inds, - __varinfo__, + vn, + inds, + $__VARINFO__, ) end end @@ -419,40 +420,39 @@ function generate_dot_tilde(left, right) if isliteral(left) return quote $(DynamicPPL.dot_tilde_observe!)( - __context__, $(DynamicPPL.check_tilde_rhs)($right), $left, __varinfo__ + $__CONTEXT__, $(DynamicPPL.check_tilde_rhs)($right), $left, $__VARINFO__ ) end end # Otherwise it is determined by the model or its value, # if the LHS represents an observation - @gensym vn inds isassumption return quote - $vn = $(varname(left)) - $inds = $(vinds(left)) - $isassumption = $(DynamicPPL.isassumption(left)) - if $isassumption + vn = $(varname(left)) + inds = $(vinds(left)) + isassumption = $(DynamicPPL.isassumption(left)) + if isassumption $left .= $(DynamicPPL.dot_tilde_assume!)( - __context__, + $__CONTEXT__, $(DynamicPPL.unwrap_right_left_vns)( - $(DynamicPPL.check_tilde_rhs)($right), $(maybe_view(left)), $vn + $(DynamicPPL.check_tilde_rhs)($right), $(maybe_view(left)), vn )..., - $inds, - __varinfo__, + inds, + $__VARINFO__, ) else # If `vn` is not in `argnames`, we need to make sure that the variable is defined. - if !$(DynamicPPL.inargnames)($vn, __model__) - $left .= $(DynamicPPL.getvalue_nested)(__context__, $vn) + if !$(DynamicPPL.inargnames)(vn, $__MODEL__) + $left .= $(DynamicPPL.getvalue_nested)($__CONTEXT__, vn) end $(DynamicPPL.dot_tilde_observe!)( - __context__, + $__CONTEXT__, $(DynamicPPL.check_tilde_rhs)($right), $(maybe_view(left)), - $vn, - $inds, - __varinfo__, + vn, + inds, + $__VARINFO__, ) end end @@ -478,9 +478,9 @@ function build_output(modelinfo, linenumbernode) # Add the internal arguments to the user-specified arguments (positional + keywords). evaluatordef[:args] = vcat( [ - :(__model__::$(DynamicPPL.Model)), - :(__varinfo__::$(DynamicPPL.AbstractVarInfo)), - :(__context__::$(DynamicPPL.AbstractContext)), + :($__MODEL__::$(DynamicPPL.Model)), + :($__VARINFO__::$(DynamicPPL.AbstractVarInfo)), + :($__CONTEXT__::$(DynamicPPL.AbstractContext)), ], modelinfo[:allargs_exprs], ) @@ -500,16 +500,15 @@ function build_output(modelinfo, linenumbernode) # Update the function body of the user-specified model. # We use a name for the anonymous evaluator that does not conflict with other variables. modeldef = modelinfo[:modeldef] - @gensym evaluator # We use `MacroTools.@q begin ... end` instead of regular `quote ... end` to ensure # that no new `LineNumberNode`s are added apart from the reference `linenumbernode` # to the call site modeldef[:body] = MacroTools.@q begin $(linenumbernode) - $evaluator = $(MacroTools.combinedef(evaluatordef)) + evaluator = $(MacroTools.combinedef(evaluatordef)) return $(DynamicPPL.Model)( $(QuoteNode(modeldef[:name])), - $evaluator, + evaluator, $allargs_namedtuple, $defaults_namedtuple, ) From f1d30e97fc166dfb0983ee637b2f9bad1acd4719 Mon Sep 17 00:00:00 2001 From: Philipp Gabler Date: Mon, 23 Aug 2021 15:27:31 +0200 Subject: [PATCH 02/10] Reintroduce gensyms --- src/compiler.jl | 99 +++++++++++++++++++++++++++---------------------- 1 file changed, 55 insertions(+), 44 deletions(-) diff --git a/src/compiler.jl b/src/compiler.jl index 49cce4535..548029350 100644 --- a/src/compiler.jl +++ b/src/compiler.jl @@ -5,6 +5,15 @@ for name in INTERNALNAMES @eval $(Symbol(uppercase(string(name)))) = $(Meta.quot((name))) end + +# macro _id(expr) +# return expr +# end + +# macro hygienize(expr) +# return Meta.quot(macroexpand(__module__, :(@_id $expr))) +# end + """ isassumption(expr) @@ -19,32 +28,30 @@ Let `expr` be `:(x[1])`. It is an assumption in the following cases: When `expr` is not an expression or symbol (i.e., a literal), this expands to `false`. """ -function isassumption(expr::Union{Symbol,Expr}) +function isassumption(expr::Union{Symbol,Expr}, vn) return quote - let vn = $(varname(expr)) - if $(DynamicPPL.contextual_isassumption)($__CONTEXT__, vn) - # Considered an assumption by `__context__` which means either: - # 1. We hit the default implementation, e.g. using `DefaultContext`, - # which in turn means that we haven't considered if it's one of - # the model arguments, hence we need to check this. - # 2. We are working with a `ConditionContext` _and_ it's NOT in the model arguments, - # i.e. we're trying to condition one of the latent variables. - # In this case, the below will return `true` since the first branch - # will be hit. - # 3. We are working with a `ConditionContext` _and_ it's in the model arguments, - # i.e. we're trying to override the value. This is currently NOT supported. - # TODO: Support by adding context to model, and use `model.args` - # as the default conditioning. Then we no longer need to check `inargnames` - # since it will all be handled by `contextual_isassumption`. - if !($(DynamicPPL.inargnames)(vn, $__MODEL__)) || - $(DynamicPPL.inmissings)(vn, $__MODEL__) - true - else - $(maybe_view(expr)) === missing - end + if $(DynamicPPL.contextual_isassumption)($__CONTEXT__, $vn) + # Considered an assumption by `__context__` which means either: + # 1. We hit the default implementation, e.g. using `DefaultContext`, + # which in turn means that we haven't considered if it's one of + # the model arguments, hence we need to check this. + # 2. We are working with a `ConditionContext` _and_ it's NOT in the model arguments, + # i.e. we're trying to condition one of the latent variables. + # In this case, the below will return `true` since the first branch + # will be hit. + # 3. We are working with a `ConditionContext` _and_ it's in the model arguments, + # i.e. we're trying to override the value. This is currently NOT supported. + # TODO: Support by adding context to model, and use `model.args` + # as the default conditioning. Then we no longer need to check `inargnames` + # since it will all be handled by `contextual_isassumption`. + if !($(DynamicPPL.inargnames)($vn, $__MODEL__)) || + $(DynamicPPL.inmissings)($vn, $__MODEL__) + true else - false + $(maybe_view(expr)) === missing end + else + false end end end @@ -379,31 +386,32 @@ function generate_tilde(left, right) # Otherwise it is determined by the model or its value, # if the LHS represents an observation + @gensym vn inds isassumption return quote - vn = $(varname(left)) - inds = $(vinds(left)) - isassumption = $(DynamicPPL.isassumption(left)) - if isassumption + $vn = $(varname(left)) + $inds = $(vinds(left)) + $isassumption = $(DynamicPPL.isassumption(left, vn)) + if $isassumption $left = $(DynamicPPL.tilde_assume!)( $__CONTEXT__, $(DynamicPPL.unwrap_right_vn)( - $(DynamicPPL.check_tilde_rhs)($right), vn + $(DynamicPPL.check_tilde_rhs)($right), $vn )..., - inds, + $inds, $__VARINFO__, ) else # If `vn` is not in `argnames`, we need to make sure that the variable is defined. - if !$(DynamicPPL.inargnames)(vn, $__MODEL__) - $left = $(DynamicPPL.getvalue_nested)($__CONTEXT__, vn) + if !$(DynamicPPL.inargnames)($vn, $__MODEL__) + $left = $(DynamicPPL.getvalue_nested)($__CONTEXT__, $vn) end $(DynamicPPL.tilde_observe!)( $__CONTEXT__, $(DynamicPPL.check_tilde_rhs)($right), $(maybe_view(left)), - vn, - inds, + $vn, + $inds, $__VARINFO__, ) end @@ -427,31 +435,32 @@ function generate_dot_tilde(left, right) # Otherwise it is determined by the model or its value, # if the LHS represents an observation + @gensym vn inds isassumption return quote - vn = $(varname(left)) - inds = $(vinds(left)) - isassumption = $(DynamicPPL.isassumption(left)) - if isassumption + $vn = $(varname(left)) + $inds = $(vinds(left)) + $isassumption = $(DynamicPPL.isassumption(left, vn)) + if $isassumption $left .= $(DynamicPPL.dot_tilde_assume!)( $__CONTEXT__, $(DynamicPPL.unwrap_right_left_vns)( - $(DynamicPPL.check_tilde_rhs)($right), $(maybe_view(left)), vn + $(DynamicPPL.check_tilde_rhs)($right), $(maybe_view(left)), $vn )..., - inds, + $inds, $__VARINFO__, ) else # If `vn` is not in `argnames`, we need to make sure that the variable is defined. if !$(DynamicPPL.inargnames)(vn, $__MODEL__) - $left .= $(DynamicPPL.getvalue_nested)($__CONTEXT__, vn) + $left .= $(DynamicPPL.getvalue_nested)($__CONTEXT__, $vn) end $(DynamicPPL.dot_tilde_observe!)( $__CONTEXT__, $(DynamicPPL.check_tilde_rhs)($right), $(maybe_view(left)), - vn, - inds, + $vn, + $inds, $__VARINFO__, ) end @@ -500,15 +509,17 @@ function build_output(modelinfo, linenumbernode) # Update the function body of the user-specified model. # We use a name for the anonymous evaluator that does not conflict with other variables. modeldef = modelinfo[:modeldef] + modeldef[:name] = esc(modeldef[:name]) + @gensym evaluator # We use `MacroTools.@q begin ... end` instead of regular `quote ... end` to ensure # that no new `LineNumberNode`s are added apart from the reference `linenumbernode` # to the call site modeldef[:body] = MacroTools.@q begin $(linenumbernode) - evaluator = $(MacroTools.combinedef(evaluatordef)) + $evaluator = $(MacroTools.combinedef(evaluatordef)) return $(DynamicPPL.Model)( $(QuoteNode(modeldef[:name])), - evaluator, + $evaluator, $allargs_namedtuple, $defaults_namedtuple, ) From 4e231cd8e9884055314e71f60ac116c1cf1ed555 Mon Sep 17 00:00:00 2001 From: Philipp Gabler Date: Mon, 23 Aug 2021 16:36:02 +0200 Subject: [PATCH 03/10] Clean up some things --- src/compiler.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/compiler.jl b/src/compiler.jl index 548029350..0b439d93f 100644 --- a/src/compiler.jl +++ b/src/compiler.jl @@ -2,7 +2,7 @@ const INTERNALNAMES = (:__model__, :__sampler__, :__context__, :__varinfo__, :__ const DEPRECATED_INTERNALNAMES = (:_model, :_sampler, :_context, :_varinfo, :_rng) for name in INTERNALNAMES - @eval $(Symbol(uppercase(string(name)))) = $(Meta.quot((name))) + @eval $(Symbol(uppercase(string(name)))) = $(Meta.quot(name)) end @@ -90,7 +90,7 @@ function contextual_isassumption(context::PrefixContext, vn) end # failsafe: a literal is never an assumption -isassumption(expr) = :(false) +isassumption(expr, vn) = :(false) # If we're working with, say, a `Symbol`, then we're not going to `view`. maybe_view(x) = x @@ -524,7 +524,7 @@ function build_output(modelinfo, linenumbernode) $defaults_namedtuple, ) end - + return :($(Base).@__doc__ $(MacroTools.combinedef(modeldef))) end From 9d6f8f7c88c55738f4a3ce11bcba8b91504b5cd9 Mon Sep 17 00:00:00 2001 From: Philipp Gabler Date: Mon, 30 Aug 2021 10:48:28 +0200 Subject: [PATCH 04/10] Forgot to add changes... --- src/compiler.jl | 58 ++++++++++++++++++++++++------------------------- 1 file changed, 28 insertions(+), 30 deletions(-) diff --git a/src/compiler.jl b/src/compiler.jl index 8e8e4cac4..8a5b76537 100644 --- a/src/compiler.jl +++ b/src/compiler.jl @@ -5,7 +5,6 @@ for name in INTERNALNAMES @eval $(Symbol(uppercase(string(name)))) = $(Meta.quot(name)) end - # macro _id(expr) # return expr # end @@ -15,7 +14,7 @@ end # end """ - isassumption(expr) + isassumption(expr, vn) Return an expression that can be evaluated to check if `expr` is an assumption in the model. @@ -30,34 +29,35 @@ When `expr` is not an expression or symbol (i.e., a literal), this expands to `f """ function isassumption(expr::Union{Symbol,Expr}, vn) return quote - let $vn = $(varname(expr)) - if $(DynamicPPL.contextual_isassumption)(__context__, $vn) - # Considered an assumption by `__context__` which means either: - # 1. We hit the default implementation, e.g. using `DefaultContext`, - # which in turn means that we haven't considered if it's one of - # the model arguments, hence we need to check this. - # 2. We are working with a `ConditionContext` _and_ it's NOT in the model arguments, - # i.e. we're trying to condition one of the latent variables. - # In this case, the below will return `true` since the first branch - # will be hit. - # 3. We are working with a `ConditionContext` _and_ it's in the model arguments, - # i.e. we're trying to override the value. This is currently NOT supported. - # TODO: Support by adding context to model, and use `model.args` - # as the default conditioning. Then we no longer need to check `inargnames` - # since it will all be handled by `contextual_isassumption`. - if !($(DynamicPPL.inargnames)($vn, __model__)) || - $(DynamicPPL.inmissings)($vn, __model__) - true - else - $(maybe_view(expr)) === missing - end + if $(DynamicPPL.contextual_isassumption)(__context__, $vn) + # Considered an assumption by `__context__` which means either: + # 1. We hit the default implementation, e.g. using `DefaultContext`, + # which in turn means that we haven't considered if it's one of + # the model arguments, hence we need to check this. + # 2. We are working with a `ConditionContext` _and_ it's NOT in the model arguments, + # i.e. we're trying to condition one of the latent variables. + # In this case, the below will return `true` since the first branch + # will be hit. + # 3. We are working with a `ConditionContext` _and_ it's in the model arguments, + # i.e. we're trying to override the value. This is currently NOT supported. + # TODO: Support by adding context to model, and use `model.args` + # as the default conditioning. Then we no longer need to check `inargnames` + # since it will all be handled by `contextual_isassumption`. + if !($(DynamicPPL.inargnames)($vn, __model__)) || + $(DynamicPPL.inmissings)($vn, __model__) + true else - false + $(maybe_view(expr)) === missing end + else + false end end end +# failsafe: a literal is never an assumption +isassumption(expr, vn) = :(false) + """ contextual_isassumption(context, vn) @@ -91,9 +91,6 @@ function contextual_isassumption(context::PrefixContext, vn) return contextual_isassumption(childcontext(context), prefix(context, vn)) end -# failsafe: a literal is never an assumption -isassumption(expr, vn) = :(false) - # If we're working with, say, a `Symbol`, then we're not going to `view`. maybe_view(x) = x maybe_view(x::Expr) = :(@views($x)) @@ -392,7 +389,7 @@ function generate_tilde(left, right) return quote $vn = $(varname(left)) $inds = $(vinds(left)) - $isassumption = $(DynamicPPL.isassumption(left)) + $isassumption = $(DynamicPPL.isassumption(left, vn)) if $isassumption $left = $(DynamicPPL.tilde_assume!)( __context__, @@ -441,7 +438,7 @@ function generate_dot_tilde(left, right) return quote $vn = $(varname(left)) $inds = $(vinds(left)) - $isassumption = $(DynamicPPL.isassumption(left)) + $isassumption = $(DynamicPPL.isassumption(left, vn)) if $isassumption $left .= $(DynamicPPL.dot_tilde_assume!)( __context__, @@ -495,6 +492,7 @@ function build_output(modelinfo, linenumbernode) # Delete the keyword arguments. evaluatordef[:kwargs] = [] + evaluatordef[:name] = esc(evaluatordef[:name]) # Replace the user-provided function body with the version created by DynamicPPL. # We use `MacroTools.@q begin ... end` instead of regular `quote ... end` to ensure @@ -506,7 +504,6 @@ function build_output(modelinfo, linenumbernode) end ## Build the model function. - # Extract the named tuple expression of all arguments and the default values. allargs_namedtuple = modelinfo[:allargs_namedtuple] defaults_namedtuple = modelinfo[:defaults_namedtuple] @@ -516,6 +513,7 @@ function build_output(modelinfo, linenumbernode) # that no new `LineNumberNode`s are added apart from the reference `linenumbernode` # to the call site modeldef = modelinfo[:modeldef] + modeldef[:name] = esc(modeldef[:name]) modeldef[:body] = MacroTools.@q begin $(linenumbernode) return $(DynamicPPL.Model)( From e59c67ef150363ef772746b947c7da5314cd54e4 Mon Sep 17 00:00:00 2001 From: Philipp Gabler Date: Mon, 30 Aug 2021 11:33:03 +0200 Subject: [PATCH 05/10] Remove accidentially re-introduced deprecated names --- src/compiler.jl | 1 - 1 file changed, 1 deletion(-) diff --git a/src/compiler.jl b/src/compiler.jl index 8a5b76537..3c323d175 100644 --- a/src/compiler.jl +++ b/src/compiler.jl @@ -1,5 +1,4 @@ const INTERNALNAMES = (:__model__, :__context__, :__varinfo__) -const DEPRECATED_INTERNALNAMES = (:_model, :_context, :_varinfo) for name in INTERNALNAMES @eval $(Symbol(uppercase(string(name)))) = $(Meta.quot(name)) From cd9640ee711d21312d12ed5fdfe2bdc8fe8fbbbc Mon Sep 17 00:00:00 2001 From: Philipp Gabler Date: Mon, 30 Aug 2021 11:36:48 +0200 Subject: [PATCH 06/10] ...and their usages --- src/compiler.jl | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/compiler.jl b/src/compiler.jl index 3c323d175..112ae6041 100644 --- a/src/compiler.jl +++ b/src/compiler.jl @@ -314,15 +314,6 @@ generate_mainbody(mod, expr, warn) = generate_mainbody!(mod, Symbol[], expr, war generate_mainbody!(mod, found, x, warn) = x function generate_mainbody!(mod, found, sym::Symbol, warn) - if sym in DEPRECATED_INTERNALNAMES - newsym = Symbol(:_, sym, :__) - Base.depwarn( - "internal variable `$sym` is deprecated, use `$newsym` instead.", - :generate_mainbody!, - ) - return generate_mainbody!(mod, found, newsym, warn) - end - if warn && sym in INTERNALNAMES && sym ∉ found @warn "you are using the internal variable `$sym`" push!(found, sym) From 4d8aa1e7f7fd08cc53bb3e2b62ac8c5b8fe338ab Mon Sep 17 00:00:00 2001 From: Philipp Gabler Date: Mon, 30 Aug 2021 12:15:25 +0200 Subject: [PATCH 07/10] Fix things broken by merging, and whatever remained otherwise --- src/compiler.jl | 45 +++++++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/src/compiler.jl b/src/compiler.jl index 112ae6041..96646747d 100644 --- a/src/compiler.jl +++ b/src/compiler.jl @@ -1,7 +1,7 @@ const INTERNALNAMES = (:__model__, :__context__, :__varinfo__) for name in INTERNALNAMES - @eval $(Symbol(uppercase(string(name)))) = $(Meta.quot(name)) + @eval const $(Symbol(uppercase(string(name)))) = $(Meta.quot(name)) end # macro _id(expr) @@ -28,7 +28,7 @@ When `expr` is not an expression or symbol (i.e., a literal), this expands to `f """ function isassumption(expr::Union{Symbol,Expr}, vn) return quote - if $(DynamicPPL.contextual_isassumption)(__context__, $vn) + if $(DynamicPPL.contextual_isassumption)($__CONTEXT__, $vn) # Considered an assumption by `__context__` which means either: # 1. We hit the default implementation, e.g. using `DefaultContext`, # which in turn means that we haven't considered if it's one of @@ -42,8 +42,8 @@ function isassumption(expr::Union{Symbol,Expr}, vn) # TODO: Support by adding context to model, and use `model.args` # as the default conditioning. Then we no longer need to check `inargnames` # since it will all be handled by `contextual_isassumption`. - if !($(DynamicPPL.inargnames)($vn, __model__)) || - $(DynamicPPL.inmissings)($vn, __model__) + if !($(DynamicPPL.inargnames)($vn, $__MODEL__)) || + $(DynamicPPL.inmissings)($vn, $__MODEL__) true else $(maybe_view(expr)) === missing @@ -208,7 +208,7 @@ To generate a `Model`, call `model(xvalue)` or `model(xvalue, yvalue)`. macro model(expr, warn=false) # include `LineNumberNode` with information about the call site in the # generated function for easier debugging and interpretation of error messages - return esc(model(__module__, __source__, expr, warn)) + return model(__module__, __source__, expr, warn) end function model(mod, linenumbernode, expr, warn) @@ -323,7 +323,7 @@ function generate_mainbody!(mod, found, sym::Symbol, warn) end function generate_mainbody!(mod, found, expr::Expr, warn) # Do not touch interpolated expressions - expr.head === :$ && return expr.args[1] + Meta.isexpr(expr, :$) && return esc(expr.args[1]) # If it's a macro, we expand it if Meta.isexpr(expr, :macrocall) @@ -368,7 +368,7 @@ function generate_tilde(left, right) if isliteral(left) return quote $(DynamicPPL.tilde_observe!)( - __context__, $(DynamicPPL.check_tilde_rhs)($right), $left, __varinfo__ + $__CONTEXT__, $(DynamicPPL.check_tilde_rhs)($right), $left, $__VARINFO__ ) end end @@ -382,26 +382,26 @@ function generate_tilde(left, right) $isassumption = $(DynamicPPL.isassumption(left, vn)) if $isassumption $left = $(DynamicPPL.tilde_assume!)( - __context__, + $__CONTEXT__, $(DynamicPPL.unwrap_right_vn)( $(DynamicPPL.check_tilde_rhs)($right), $vn )..., $inds, - __varinfo__, + $__VARINFO__, ) else # If `vn` is not in `argnames`, we need to make sure that the variable is defined. - if !$(DynamicPPL.inargnames)($vn, __model__) - $left = $(DynamicPPL.getvalue_nested)(__context__, $vn) + if !$(DynamicPPL.inargnames)($vn, $__MODEL__) + $left = $(DynamicPPL.getvalue_nested)($__CONTEXT__, $vn) end $(DynamicPPL.tilde_observe!)( - __context__, + $__CONTEXT__, $(DynamicPPL.check_tilde_rhs)($right), $(maybe_view(left)), $vn, $inds, - __varinfo__, + $__VARINFO__, ) end end @@ -417,7 +417,7 @@ function generate_dot_tilde(left, right) if isliteral(left) return quote $(DynamicPPL.dot_tilde_observe!)( - __context__, $(DynamicPPL.check_tilde_rhs)($right), $left, __varinfo__ + $__CONTEXT__, $(DynamicPPL.check_tilde_rhs)($right), $left, $__VARINFO__ ) end end @@ -431,26 +431,26 @@ function generate_dot_tilde(left, right) $isassumption = $(DynamicPPL.isassumption(left, vn)) if $isassumption $left .= $(DynamicPPL.dot_tilde_assume!)( - __context__, + $__CONTEXT__, $(DynamicPPL.unwrap_right_left_vns)( $(DynamicPPL.check_tilde_rhs)($right), $(maybe_view(left)), $vn )..., $inds, - __varinfo__, + $__VARINFO__, ) else # If `vn` is not in `argnames`, we need to make sure that the variable is defined. - if !$(DynamicPPL.inargnames)($vn, __model__) - $left .= $(DynamicPPL.getvalue_nested)(__context__, $vn) + if !$(DynamicPPL.inargnames)($vn, $__MODEL__) + $left .= $(DynamicPPL.getvalue_nested)($__CONTEXT__, $vn) end $(DynamicPPL.dot_tilde_observe!)( - __context__, + $__CONTEXT__, $(DynamicPPL.check_tilde_rhs)($right), $(maybe_view(left)), $vn, $inds, - __varinfo__, + $__VARINFO__, ) end end @@ -469,6 +469,7 @@ Builds the output expression. function build_output(modelinfo, linenumbernode) ## Build the anonymous evaluator from the user-provided model definition. evaluatordef = deepcopy(modelinfo[:modeldef]) + evaluatordef[:name] = esc(evaluatordef[:name]) # Add the internal arguments to the user-specified arguments (positional + keywords). evaluatordef[:args] = vcat( @@ -482,7 +483,6 @@ function build_output(modelinfo, linenumbernode) # Delete the keyword arguments. evaluatordef[:kwargs] = [] - evaluatordef[:name] = esc(evaluatordef[:name]) # Replace the user-provided function body with the version created by DynamicPPL. # We use `MacroTools.@q begin ... end` instead of regular `quote ... end` to ensure @@ -503,11 +503,12 @@ function build_output(modelinfo, linenumbernode) # that no new `LineNumberNode`s are added apart from the reference `linenumbernode` # to the call site modeldef = modelinfo[:modeldef] + modelname_symbol = Meta.quot(modeldef[:name]) modeldef[:name] = esc(modeldef[:name]) modeldef[:body] = MacroTools.@q begin $(linenumbernode) return $(DynamicPPL.Model)( - $(QuoteNode(modeldef[:name])), + $modelname_symbol, $(modeldef[:name]), $allargs_namedtuple, $defaults_namedtuple, From fe9798f4c2ffcbc9e10b00acbda31f22debf611e Mon Sep 17 00:00:00 2001 From: Philipp Gabler Date: Sun, 12 Sep 2021 11:45:39 +0200 Subject: [PATCH 08/10] Minor refactoring --- src/compiler.jl | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/compiler.jl b/src/compiler.jl index 96646747d..489b0bc30 100644 --- a/src/compiler.jl +++ b/src/compiler.jl @@ -469,16 +469,15 @@ Builds the output expression. function build_output(modelinfo, linenumbernode) ## Build the anonymous evaluator from the user-provided model definition. evaluatordef = deepcopy(modelinfo[:modeldef]) + original_arguments = modelinfo[:allargs_exprs] evaluatordef[:name] = esc(evaluatordef[:name]) # Add the internal arguments to the user-specified arguments (positional + keywords). evaluatordef[:args] = vcat( - [ - :($__MODEL__::$(DynamicPPL.Model)), - :($__VARINFO__::$(DynamicPPL.AbstractVarInfo)), - :($__CONTEXT__::$(DynamicPPL.AbstractContext)), - ], - modelinfo[:allargs_exprs], + :($__MODEL__::$(DynamicPPL.Model)), + :($__VARINFO__::$(DynamicPPL.AbstractVarInfo)), + :($__CONTEXT__::$(DynamicPPL.AbstractContext)), + original_arguments, ) # Delete the keyword arguments. From 0c08cc0faf8026fede6ec7ddb394df67d0d7a9da Mon Sep 17 00:00:00 2001 From: Philipp Gabler Date: Mon, 13 Sep 2021 16:04:40 +0200 Subject: [PATCH 09/10] Cleanup and undo some impossible things --- src/compiler.jl | 34 +++++++++++----------------------- 1 file changed, 11 insertions(+), 23 deletions(-) diff --git a/src/compiler.jl b/src/compiler.jl index 21c5e8512..e83d51f9e 100644 --- a/src/compiler.jl +++ b/src/compiler.jl @@ -4,13 +4,6 @@ for name in INTERNALNAMES @eval const $(Symbol(uppercase(string(name)))) = $(Meta.quot(name)) end -# macro _id(expr) -# return expr -# end - -# macro hygienize(expr) -# return Meta.quot(macroexpand(__module__, :(@_id $expr))) -# end """ isassumption(expr, vn) @@ -322,15 +315,13 @@ function generate_mainbody!(mod, found, sym::Symbol, warn) return sym end function generate_mainbody!(mod, found, expr::Expr, warn) - # Do not touch interpolated expressions - Meta.isexpr(expr, :$) && return esc(expr.args[1]) - - # Do we don't want escaped expressions because we unfortunately - # escape the entire body afterwards. - Meta.isexpr(expr, :escape) && return generate_mainbody(mod, found, expr.args[1], warn) - - # If it's a macro, we expand it - if Meta.isexpr(expr, :macrocall) + if Meta.isexpr(expr, :$) + # Do not touch interpolated expressions + return expr.args[1] + elseif Meta.isexpr(expr, :escape) + return generate_mainbody(mod, found, expr.args[1], warn) + elseif Meta.isexpr(expr, :macrocall) + # If it's a macro, we expand it (recursively) return generate_mainbody!(mod, found, macroexpand(mod, expr; recursive=true), warn) end @@ -383,9 +374,6 @@ function generate_tilde(left, right) # if the LHS represents an observation @gensym vn isassumption - # HACK: Usage of `drop_escape` is unfortunate. It's a consequence of the fact - # that in DynamicPPL we the entire function body. Instead we should be - # more selective with our escape. Until that's the case, we remove them all. return quote $vn = $(AbstractPPL.drop_escape(varname(left))) $isassumption = $(DynamicPPL.isassumption(left, vn)) @@ -417,8 +405,8 @@ function generate_tilde_assume(left, right, vn) ) ) - return if left isa Expr - AbstractPPL.drop_escape( + if left isa Expr + return AbstractPPL.drop_escape( Setfield.setmacro(BangBang.prefermutation, expr; overwrite=true) ) else @@ -488,7 +476,7 @@ function build_output(modelinfo, linenumbernode) ## Build the anonymous evaluator from the user-provided model definition. evaluatordef = deepcopy(modelinfo[:modeldef]) original_arguments = modelinfo[:allargs_exprs] - evaluatordef[:name] = esc(evaluatordef[:name]) + # evaluatordef[:name] = esc(evaluatordef[:name]) # Add the internal arguments to the user-specified arguments (positional + keywords). evaluatordef[:args] = vcat( @@ -522,7 +510,7 @@ function build_output(modelinfo, linenumbernode) # to the call site modeldef = modelinfo[:modeldef] modelname_symbol = Meta.quot(modeldef[:name]) - modeldef[:name] = esc(modeldef[:name]) + # modeldef[:name] = esc(modeldef[:name]) modeldef[:body] = MacroTools.@q begin $(linenumbernode) return $(DynamicPPL.Model)( From 6813731c97a3822d4cccfbc6930f39468278d739 Mon Sep 17 00:00:00 2001 From: Philipp Gabler Date: Mon, 13 Sep 2021 16:14:07 +0200 Subject: [PATCH 10/10] Delete unnecessary commented code --- src/compiler.jl | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/compiler.jl b/src/compiler.jl index e83d51f9e..79ea63c9a 100644 --- a/src/compiler.jl +++ b/src/compiler.jl @@ -476,7 +476,6 @@ function build_output(modelinfo, linenumbernode) ## Build the anonymous evaluator from the user-provided model definition. evaluatordef = deepcopy(modelinfo[:modeldef]) original_arguments = modelinfo[:allargs_exprs] - # evaluatordef[:name] = esc(evaluatordef[:name]) # Add the internal arguments to the user-specified arguments (positional + keywords). evaluatordef[:args] = vcat( @@ -510,7 +509,6 @@ function build_output(modelinfo, linenumbernode) # to the call site modeldef = modelinfo[:modeldef] modelname_symbol = Meta.quot(modeldef[:name]) - # modeldef[:name] = esc(modeldef[:name]) modeldef[:body] = MacroTools.@q begin $(linenumbernode) return $(DynamicPPL.Model)(