Skip to content

Commit

Permalink
major refactoring to fable inputs and user methods
Browse files Browse the repository at this point in the history
  • Loading branch information
leios committed Jul 17, 2024
1 parent 79d75b4 commit 6a99383
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 151 deletions.
56 changes: 28 additions & 28 deletions src/Fable.jl
Original file line number Diff line number Diff line change
Expand Up @@ -33,43 +33,43 @@ include("utils/histogram.jl")
include("structs/generators.jl")
include("structs/fable_input.jl")
include("structs/fable_user_methods.jl")
include("fums/shaders.jl")
include("structs/fable_operators.jl")
include("structs/fable_executable/fable_executable.jl")
include("structs/fable_executable/hutchinson.jl")
include("structs/fable_executable/shader.jl")
#include("fums/shaders.jl")
#include("structs/fable_operators.jl")
#include("structs/fable_executable/fable_executable.jl")
#include("structs/fable_executable/hutchinson.jl")
#include("structs/fable_executable/shader.jl")

# Operations
include("utils/simple_rng.jl")
include("fums/flames.jl")
include("fums/smears.jl")
#include("utils/simple_rng.jl")
#include("fums/flames.jl")
#include("fums/smears.jl")

# Shapes
include("objects/rectangle.jl")
include("objects/circle.jl")
include("objects/triangle.jl")
include("objects/barnsley.jl")
#include("objects/rectangle.jl")
#include("objects/circle.jl")
#include("objects/triangle.jl")
#include("objects/barnsley.jl")

# IO
include("structs/layers/layers.jl")
include("io/postprocess/postprocess.jl")
include("structs/layers/fractal_layer.jl")
include("structs/layers/color_layer.jl")
include("structs/layers/image_layer.jl")
include("structs/layers/shader_layer.jl")
include("structs/video_params.jl")
include("io/io_tools.jl")
#include("structs/layers/layers.jl")
#include("io/postprocess/postprocess.jl")
#include("structs/layers/fractal_layer.jl")
#include("structs/layers/color_layer.jl")
#include("structs/layers/image_layer.jl")
#include("structs/layers/shader_layer.jl")
#include("structs/video_params.jl")
#include("io/io_tools.jl")

# PostProcessing
include("io/postprocess/clip.jl")
include("io/postprocess/filter.jl")
include("io/postprocess/sobel.jl")
include("io/postprocess/outline.jl")
#include("io/postprocess/clip.jl")
#include("io/postprocess/filter.jl")
#include("io/postprocess/sobel.jl")
#include("io/postprocess/outline.jl")

# Main file
include("run/run.jl")
include("run/fractal_flame.jl")
include("run/shader.jl")
include("run/color.jl")
#include("run/run.jl")
#include("run/fractal_flame.jl")
#include("run/shader.jl")
#include("run/color.jl")

end # module
70 changes: 23 additions & 47 deletions src/structs/fable_input.jl
Original file line number Diff line number Diff line change
@@ -1,53 +1,29 @@
export FableInput, fi, @fi, set!, combine, to_args, find_fi_index, value

struct FableInput
s::Union{Symbol, String}
x::Ref{Union{Number, Tuple, Vector}}
#-------------fable_input------------------------------------------------------#
#
# Purpose: This file is meant to create fable inputs for Fable
# Fable Inputs are any values meant to be modified by the user
# within a Fable executable to avoid recompilation.
#
# Notes: Maybe save as pointers to expressions for usability?
#
#------------------------------------------------------------------------------#
export FableInput, @fi

struct FableInput{E}
expr::E
end

fi(args...) = FableInput(args...)

function set!(fi::FableInput, val)
fi.x.x = val
end
"""
x = @fi 7
function combine(nt::Tuple, fis::Tuple)
return Tuple(combine(nt[i], fis[i]) for i = 1:length(fis))
end
or
combine(fis::Vector{FableInput}, nt::NamedTuple) = combine(nt, fis)
x = @fi 7*y+5
function combine(nt::NamedTuple, fis::Vector{FableInput})
if length(fis) == 0
return nt
end

fi_vals = (remove_vectors(fis[i].x.x) for i = 1:length(fis))
fi_keys = (Symbol(fis[i].s) for i = 1:length(fis))

return NamedTuple{(keys(nt)..., fi_keys...)}((values(nt)..., fi_vals...))
Marks the variable `x` as a FableInput -- a dynamic variable passed in to the
final executable at runtime.
This avoids recompilation of code for variables that are dynamically changing.
"""
macro fi(ex)
esc(FableInput(ex))
end

function to_args(nt::Tuple, fis::Tuple)
return Tuple(combine(fis[i], nt[i]) for i = 1:length(fis))
end

function to_args(nt::NamedTuple, fis::Vector{FableInput})
if length(fis) == 0
return values(nt)
end
fi_vals = (remove_vectors(fis[i].x.x) for i = 1:length(fis))
return (values(nt)..., fi_vals...)
end

function find_fi_index(s, fis::FT) where FT <: Union{Vector{FableInput},
Tuple}
for i = 1:length(fis)
if Symbol(fis[i].s) == Symbol(s)
return i
end
end
end

value(fi::FableInput) = fi.x.x
value(a) = a
141 changes: 67 additions & 74 deletions src/structs/fable_user_methods.jl
Original file line number Diff line number Diff line change
@@ -1,102 +1,94 @@
#-------------fable-user_methods-----------------------------------------------#
#
# Purpose: This file is meant to define how users interact with fable user
# methods.
# fums are essentially function fragments that will be compiled at
# a later stage of the Fable pipeline
#
# Notes: I think the best way to carry fis with the user methods is
# to define a constructor function that reads in the expr block and
# kwargs, and then parses out the fis from that list. Then at the
# end of the @fum macro, I can call into that constructor.
# We could get fanc with our own @generated macro, but...
#
#------------------------------------------------------------------------------#
export FableUserMethod, @fum

struct FableUserMethod{NT <: NamedTuple,
V <: Vector{FableInput},
F <: Function}
kwargs::NT
fis::V
fx::F
struct FableUserMethod{E, F}
body::E
fis::F
end


args(a,n) = a.args[n]

function __set_args(args, config)
if config == :fractal
correct_args = [:y, :x, :frame]
elseif config == :shader
correct_args = [:y, :x, :color, :frame]
function __warn_args(args, config)
correct_args = (:y, :x, :frame, :color)
max_arg_idx = 3
if config == :color
max_arg_idx = 4
end
if !issubset(args, correct_args)
if !issubset(args, correct_args[1:max_arg_idx])
error("Function arguments must be one of the following:\n"*
string(correct_args)*"\n"*
string(correct_args[1:max_arg_idx])*"\n"*
"Please use key-word arguments for any additional arguments!")
end
return correct_args
end

# this function can create a NamedTuple from kwargs in a macro, ie:
# kwargs = __to_NamedTuple(def[:kwargs])
# It is not currently used, but took a while to find out, so I'm leaving it
# here for debugging purposes
#function __to_NamedTuple(kwargs)
# NamedTuple{Tuple(args.(kwargs[:],1))}(Tuple(args.(kwargs[:],2)))
#end

function __create_fum_stuff(expr, config, mod, force_inbounds)
def = MacroTools.splitdef(expr)
def[:name] = name = Symbol(def[:name], :_fum)
used_args = def[:args]
args = __set_args(used_args, config)
def[:args] = args
if force_inbounds
body_qt = quote
@inbounds $(def[:body])
end
def[:body] = body_qt
end
kwargs = NamedTuple()
fum_fx = combinedef(def)
return kwargs, Core.eval(mod, fum_fx)
end
"""
f = @fum f(x) = x+1
Defines a Fable User Method (f) that can be used along with other fums to
build a Fable Executable.
Note that these are not compiled until the Fable Executable is built!
This means you will not have error checking until later in the process!
You may use `:color` to specify that the fum is meant for coloring.
"""
macro fum(exprs...)

# Note: this operator currently works like this:
# f = @fum function config f(x) x+1 end
# There should be a way to define f in this macro, so we don't need to
# say `f = @fum function ...`, but instead just `@fum function ...`
macro fum(ex...)

config = :fractal
force_inbounds = false

if length(ex) == 1
else
for i = 1:length(ex)-1
if ex[i] == :color || ex[i] == :shader ||
ex[i] == :(:shader) || ex[i] == :(:color)
config = :shader
elseif ex[i] isa Expr && ex[i].head == :(=) &&
ex[i].args[1] == :inbounds && ex[i].args[2] isa Bool
force_inbounds = ex[i].args[2]
config = :default

if length(exprs) != 1
for i = 1:length(exprs)-1
if exprs[i] == :color || exprs[i] == :shader ||
exprs[i] == :(:shader) || exprs[i] == :(:color)
config = :color
else
error("Incorrect config argument ", ex[i], "!")
end
end
end

expr = ex[end]
kwargs = nothing
ex = exprs[end]

if isa(expr, Symbol)
error("Cannot convert Symbol to Fable User Method!")
elseif expr.head == :(=)
# inline function definitions
if isa(expr.args[1], Expr)
kwargs, fum_fx = __create_fum_stuff(expr, config, __module__,
force_inbounds)
else
error("Cannot create FableUserMethod.\n"*
"Input is not a valid function definition!")
if !isa(ex, Expr)
error("Cannot convert single inputs to Fable User Method!")
elseif ex.head == :(=) && !(isa(ex.args[1], Expr))
error("Invalid function definition!")
end

def = MacroTools.splitdef(ex)
__warn_args(def[:args], config)
kwargs = def[:kwargs]
fis = Tuple(FableInput[])
for i = 1:length(kwargs)
if !isa(kwargs[i], Expr)
error("fum key word arguments must be an expression, like "*
"`q = 5`")
end
kwargs[i].head = :(=)
if isa(kwargs[i].args[2], FableInput)
fis = (fis..., kwargs[i].args[2])
end
elseif expr.head == :function
kwargs, fum_fx = __create_fum_stuff(expr, config, __module__,
force_inbounds)
else
error("Cannot convert expr to Fable User Method!")
end

return FableUserMethod(kwargs, FableInput[], fum_fx)
final_ex = Expr(:block, kwargs..., def[:body])
return esc(FableUserMethod(Expr(:block, def[:kwargs]..., def[:body]),
fis))
end

#=
function (a::FableUserMethod)(args...; kwargs...)
Expand Down Expand Up @@ -151,3 +143,4 @@ function (a::FableUserMethod)(args...; kwargs...)
final_kwargs = NamedTuple{ks}(vals)
return FableUserMethod(final_kwargs, fis, a.fx)
end
=#
4 changes: 2 additions & 2 deletions src/structs/generators.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ export AbstractGenerator, ChaosGenerator, StandardGenerator

abstract type AbstractGenerator end;

struct ChaosGenerator{A, I, P, F} where {I <: Integer, P <: Tuple, F <: Tuple}
struct ChaosGenerator{A, I, P, F} <: AbstractGenerator
args::A
iterations::I
prob_set::P
fnums::F
end

struct StandardGenerator{A, ND}
struct StandardGenerator{A, ND} <: AbstractGenerator
args::A
ndrange::ND
end

0 comments on commit 6a99383

Please sign in to comment.