Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 19 additions & 19 deletions docs/literate/parse-program/parse_julia_tutorial.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# ## Parse Julia Programs
# # Parse Julia Programs
# The purpose of this documentation is to provide a tutorial on the functionality of the ParseJuliaPrograms file.
# This tutorial will provide a brief overview on each of the functions and how a wiring diagram is parsed from
# a Julia function expression.
Expand All @@ -23,7 +23,7 @@ end
# This macro is the definition for the macro @program where it takes in the presentation and the list of ast expressions as parameters
# Expr creates an expression where :call indicates the expression is a function call and
# GlobalRef creates a reference to the function being called,
# with ParseJuliaPrograms being the module and parse_wiring_diagram the function called.
# with ParseJuliaPrograms being the module and `parse_wiring_diagram` the function called.
# Esc allows the presentation to be evaluated in the context of the caller rather than the macro's scope.
# QuoteNode takes each expression from the list of ast expressions passed in to create a quoted expression.

Expand All @@ -41,15 +41,15 @@ function parse_wiring_diagram(pres::Presentation, expr::Expr)::WiringDiagram
end


# Function expression match Expr(:function, call, body) => parse_wiring_diagram(pres, call, body)
# Function expression match Expr(:function, call, body) => `parse_wiring_diagram(pres, call, body)`

# Lambda expression match Expr(:->, call, body) => parse_wiring_diagram(pres, call, body)
# Lambda expression match Expr(:->, call, body) => `parse_wiring_diagram(pres, call, body)`

# This function parses a wiring diagram from a Julia function expression where it takes in the presentation and a given expression as parameters.
# and uses the @match macro to determine whether the expression is a function or lambda expression and calls a following parse_wiring_diagram function with the call and body
# and uses the @match macro to determine whether the expression is a function or lambda expression and calls a following `parse_wiring_diagram` function with the call and body
# of the expression if true.

# The following parse_wiring_diagram function takes in the presentation, call and body of the expression passed in from the previous parse_wiring_diagram as parameters
# The following `parse_wiring_diagram` function takes in the presentation, call and body of the expression passed in from the previous `parse_wiring_diagram` as parameters
# and uses pattern matching to determine the arguments of the function call.
function parse_wiring_diagram(pres::Presentation, call::Expr0, body::Expr)::WiringDiagram
syntax_module = pres.syntax
Expand Down Expand Up @@ -98,26 +98,26 @@ end
# The function first matches call expressions to output the arguments of a function call and matches the output into name type pairs,
# validating that arguments have a name and type using eval_type_expr.

# Case for standard function declarations ex: f(x::T, y::U)
# Case for standard function declarations ex: `f(x::T, y::U)`
"""
Expr(:call, name, args...) => args
"""
# Case for when the function call is a tuple ex: (x::T, y::U)
# Case for when the function call is a tuple ex: `(x::T, y::U)`
"""
Expr(:tuple, args...) => args
"""
# Case for a single argument ex: :(x::T)
# Case for a single argument ex: `:(x::T)`
"""
Expr(:(::), _...) => [call]
"""
# Case for a single symbol ex: :x
# Case for a single symbol ex: `:x`
"""
_::Symbol => [call])
"""



# Eval_type_expr is used by parse_wiring_diagram to evaluate the expression (ex: X or otimes{X, Y}) and passes in its symbol to the generator before returning the type expression.
# `Eval_type_expr` is used by `parse_wiring_diagram` to evaluate the expression (ex: `X` or `otimes{X, Y}`) and passes in its symbol to the generator before returning the type expression.
function eval_type_expr(pres::Presentation, syntax_module::Module, expr::Expr0)
function _eval_type_expr(expr)
@match expr begin
Expand All @@ -140,7 +140,7 @@ func_expr = compile_recording_expr(body, args, kwargs = sort!(collect(keys(kwarg
func = mk_function(parentmodule(syntax_module), func_expr)
"""

# The make_lookup_table function is called to create a lookup table dictionary to store and assign names to generators or term constructors.
# The `make_lookup_table` function is called to create a lookup table dictionary to store and assign names to generators or term constructors.
function make_lookup_table(pres::Presentation, syntax_module::Module, names)
theory = syntax_module.Meta.theory
terms = Set(nameof.(keys(theory.resolvers)))
Expand All @@ -156,7 +156,7 @@ function make_lookup_table(pres::Presentation, syntax_module::Module, names)
table
end

# The compile_recording_expr function is called to generate a Julia function expression that records function calls
# The `compile_recording_expr` function is called to generate a Julia function expression that records function calls
# The function takes in args input and calls a rewrite function that uses the @match macro to determine the type of expression passed in.
function compile_recording_expr(body::Expr, args::Vector{Symbol};
kwargs::Vector{Symbol}=Symbol[],
Expand All @@ -178,8 +178,8 @@ function compile_recording_expr(body::Expr, args::Vector{Symbol};
rewrite(body))
end

# After compile_recording_expr rewrites the function body where curly functions are mapped to a function call (ex: f(x,y) becomes f(x,y))
# or ordinary functions calls are mapped to recorded calls (ex: f(x,y) becomes recorder(f, x, y)),
# After `compile_recording_expr` rewrites the function body where curly functions are mapped to a function call (ex: `f(x,y)` becomes `f(x,y)`)
# or ordinary functions calls are mapped to recorded calls (ex: `f(x,y)` becomes `recorder(f, x, y)`),
# the function defintion is rewritten and returned as an AST.

# For example should the body input be:
Expand All @@ -198,14 +198,14 @@ function (var"##recorder", x; f = nothing, g = nothing)
end
"""

# Afterwards parse_wiring_diagram then creates a diagram to record function calls
# Afterwards `parse_wiring_diagram` then creates a diagram to record function calls
# and sets up the input and output ports for the wiring diagram.
"""
recorder = f -> (args...) -> record_call!(diagram, f, args...)
value = func(recorder, arg_ports...; kwargs...)
"""

# Record_call! is the function called that records the function calls in the wiring diagram
# `Record_call!` is the function called that records the function calls in the wiring diagram
# and adds wires and output ports to the box recorded in the diagram.
function record_call!(diagram::WiringDiagram, f::HomExpr, args...)
subdiagram = to_wiring_diagram(f)
Expand All @@ -224,7 +224,7 @@ function record_call!(diagram::WiringDiagram, f::HomExpr, args...)
make_return_value(return_ports)
end

# Finally, parse_wiring_diagram adds outgoing wires for the return values by normalizing the arguments given as tuples or vectors
# Finally, `parse_wiring_diagram` adds outgoing wires for the return values by normalizing the arguments given as tuples or vectors
# and adding output ports to the diagram.
"""
out_ports = normalize_arguments((value,))
Expand All @@ -237,7 +237,7 @@ add_wires!(diagram, [
])
"""

# Normalize_arguments function takes in the arguments passed in and normalizes them into a tuple of vectors
# `Normalize_arguments` function takes in the arguments passed in and normalizes them into a tuple of vectors
# where it flattens the vector of arguments and maps the arguments to a tuple of vectors.
function normalize_arguments(xs::Tuple)
mapreduce(normalize_arguments, (xs,ys) -> (xs..., ys...), xs; init=())
Expand Down