Skip to content

Commit

Permalink
Merge pull request #81 from GenieFramework/hh-push2
Browse files Browse the repository at this point in the history
refactoring of element-wise updates
  • Loading branch information
hhaensel committed Dec 21, 2021
2 parents d48dc14 + 96af7eb commit 9f7a11c
Showing 1 changed file with 53 additions and 59 deletions.
112 changes: 53 additions & 59 deletions src/Stipple.jl
Original file line number Diff line number Diff line change
Expand Up @@ -123,90 +123,74 @@ function Base.getindex(r::Reactive{T}, arg1, args...) where T
getindex(getfield(r, :o).val, arg1, args...)
end

function Base.setindex!(r::Reactive{T}, val, arg1, args...) where T
function Base.setindex!(r::Reactive{T}, val, arg1) where T
unnested = Pair[]
x = getfield(r, :o).val
jskeys = []
setindex!(x, val, arg1, args...)
key!(x, v, jskeys)
Observables.notify(r, v, jskeys)
setindex!(x, val, arg1)
key!(x, arg1; unnested)
notify(r, unnested)
end

Base.setindex!(r::Reactive, val, ::typeof(!)) = getfield(r, :o).val = val
Base.getindex(r::Reactive, ::typeof(!)) = getfield(r, :o).val

# support nested indexing

# function getindex_nested(x, keys...)
# foldl((x, key) -> Base.getindex(x, (isa(x, AbstractArray) ? key : [key])...), [keys...];
# init = x)
# end

import Base.notify
function Base.notify(observable::Observables.AbstractObservable, arg1, args...)
val = observable[]
for f in Observables.listeners(observable)
try
types = (typeof(val), typeof(arg1), typeof.(args)...)
if length(methods(f, types)) > 0
Base.invokelatest(f, val, arg1, args...)
catch
else
Base.invokelatest(f, val)
end
end
return
end

function linearindex(a::AbstractArray{T}, index::NTuple{N, Int}) where {T, N}
dims = size(a)
index0 = index .- first.(axes(a))
sum(cumprod([1, dims[1:end-1]...]) .* index0) + 1
end

function linearindex(a::AbstractArray{T, N}, index::Int) where {T, N}
if N == 1
index .- first(first(axes(a))) + 1
else
index
end
function key!(x::AbstractArray, @nospecialize(key); unnested::Union{Nothing, Vector{Pair}} = nothing)
newkey = LinearIndices(x)[key...]
isnothing(unnested) || push!(unnested, x => newkey)
newkey
end

function key!(x::AbstractArray, key, jskeys)
isnothing(jskeys) || push!(jskeys, linearindex(x, key) - 1)
function key!(@nospecialize(x), @nospecialize(key); unnested::Union{Nothing, Vector{Pair}} = nothing)
isnothing(unnested) || push!(unnested, x => key)
key
end

function key!(x, key, jskeys)
isnothing(jskeys) || push!(jskeys, key)
(key,)
end

function getindex_nested!(x, keys...; jskeys::Union{Nothing, Vector} = nothing)
val = foldl((x, key) -> Base.getindex(x, key!(x, key, jskeys)...), [keys...];
function getindex_nested!(@nospecialize(x), keys...; unnested::Union{Nothing, Vector{Pair}} = nothing)
val = foldl((x, key) -> Base.getindex(x, key!(x, key, unnested)), [keys...];
init = x)
val
end

function setindex_nested!(x, v, k1, keys...; jskeys::Union{Nothing, Vector} = nothing)
function setindex_nested!(@nospecialize(x), @nospecialize(v), @nospecialize(k1), keys...; unnested::Union{Nothing, Vector{Pair}} = nothing)
kk = [k1, keys...]
x = getindex_nested!(x, kk[1:end-1]...; jskeys)
setindex!(x, v, key!(x, kk[end], jskeys)...)
x = getindex_nested!(x, kk[1:end-1]...; unnested)
setindex!(x, v, key!(x, kk[end], unnested))
end

function setindex_nested!(r::Reactive{<:AbstractDict}, v, arg1, arg2, args...) where T
jskeys = []
setindex_nested!(getfield(r, :o).val, v, arg1, arg2, args...; jskeys)
notify(r, v, jskeys)
function setindex_nested!(r::Reactive{<:AbstractDict}, @nospecialize(v), @nospecialize(arg1), args...) where T
unnested = Pair[]
x = getfield(r, :o).val
setindex_nested!(x, v, arg1, args...; unnested)
notify(r, unnested)
v
end

function setindex_nested!(r::Reactive{<:AbstractArray{T, N}}, v, arg1, args...) where {T, N}
jskeys = []
function setindex_nested!(r::Reactive{<:AbstractArray{T, N}}, @nospecialize(v), @nospecialize(arg1), args...) where {T, N}
unnested = Pair[]
x = getfield(r, :o).val
if length(args) + 1 > N
setindex_nested!(getfield(r, :o).val, v, arg1, args...; jskeys)
notify(r, v, jskeys)
setindex_nested!(x, v, arg1, args...; unnested)
else
x = getfield(r, :o).val
setindex!(x, v, arg1, args...)
key!(x, (arg1, args...), jskeys)
notify(r, v, jskeys)
key!(x, (arg1, args...), unnested)
end
notify(r, unnested)
v
end

Expand All @@ -225,13 +209,14 @@ function Base.getindex(r::Reactive{<:AbstractArray{T, N}}, arg1, arg2, args...)
end
end

function Base.setindex!(r::Reactive{<:AbstractArray{T, N}}, v, arg1, arg2, args...) where {T, N}
# function Base.setindex!(r::Reactive{<:AbstractArray{T, N}}, v, arg1, arg2, args...) where {T, N}
function Base.setindex!(r::Reactive, v, arg1, arg2, args...) where {T, N}
setindex_nested!(r, v, arg1, arg2, args...)
end

function Base.setindex!(r::Reactive{<:AbstractDict}, v, arg1, arg2, args...) where {T, N}
setindex_nested!(r, v, arg1, arg2, args...)
end
# function Base.setindex!(r::Reactive{<:AbstractDict}, v, arg1, arg2, args...) where {T, N}
# setindex_nested!(r, v, arg1, arg2, args...)
# end

function Base.getproperty(r::Reactive{T}, field::Symbol) where T
if field in (:o, :r_mode, :no_backend_watcher, :no_frontend_watcher) # fieldnames(Reactive)
Expand Down Expand Up @@ -653,7 +638,8 @@ function setindex_withoutwatchers!(field::Reactive{T}, val, keys::Int...; notify
end

function Base.setindex!(r::Reactive{T}, val, args::Vector{Int}; notify=(x)->true) where T
setindex_withoutwatchers!(r, val, args...)
@warn "setindex!(r, val, skip::Vector{Int}) has been replaced by setindex_withoutwatchers!(r, val, args...)"
setindex_withoutwatchers!(r, val, args...; notify)
end

"""
Expand Down Expand Up @@ -759,12 +745,12 @@ function stipple_parse(::Type{T}, value::Dict) where {Tval, T <: AbstractDict{Sy
T(zip(Symbol.(string.(keys(value))), values(value)))
end

function stipple_parse(::Type{T1}, value::T2) where {T1 <: Number, T2 <: Number}
  convert(T1, value)
function stipple_parse(::Type{T1}, value::T2) where {T1 <: Number, T2 <: Number}
convert(T1, value)
end

function stipple_parse(::Type{T1}, value::T2) where {T1 <: Integer, T2 <: Number}
round(T1, value)
function stipple_parse(::Type{T1}, value::T2) where {T1 <: Integer, T2 <: Number}
round(T1, value)
end

function stipple_parse(::Type{T1}, value::T2) where {T1 <: AbstractArray, T2 <: AbstractArray}
Expand Down Expand Up @@ -844,7 +830,7 @@ function init(m::Type{M};

newval = convertvalue(val, payload["newval"])
oldval = try
convertvalue(val, payload["oldval"])
convertvalue(val, payload["oldval"])
catch ex
val[]
end
Expand Down Expand Up @@ -911,11 +897,19 @@ function setup(model::M, channel = Genie.config.webchannels_default_route)::M wh
end
f.r_mode == PRIVATE || f.no_backend_watcher && continue

on(f) do val, options...
on(f) do _, options...
if isempty(options)
@info "standard"
push!(model, field => f, channel = channel)
else
push!(model, field => options[1], channel = channel, options = opts(mode = "dict", keys = options[2]))
unnested = options[1]
x, key = unnested[end]
v = x[key]
jskeys = (p -> isa(p[1], AbstractArray) ? p[2] - first(first(axes(p[1][:]))) : p[2]).(unnested)
@info "keys: $(getindex.(unnested, 2))"
@info "jskeys: $jskeys"
@info "v: $v"
push!(model, field => v, channel = channel, options = opts(mode = "dict", keys = jskeys))
end
end
end
Expand Down

0 comments on commit 9f7a11c

Please sign in to comment.