Skip to content

Commit

Permalink
Merge branch 'ox/nostorevars'
Browse files Browse the repository at this point in the history
  • Loading branch information
oxinabox committed May 11, 2019
2 parents da1fef1 + 244e0e7 commit 077943b
Show file tree
Hide file tree
Showing 16 changed files with 329 additions and 341 deletions.
2 changes: 1 addition & 1 deletion .appveyor.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Documentation: https://github.com/JuliaCI/Appveyor.jl
environment:
matrix:
- julia_version: 1.0
- julia_version: 1.1
- julia_version: nightly
platform:
- x86
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@
*.jl.*.cov
*.jl.mem
/dev

statprof/
4 changes: 2 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ os:
- linux
- osx
julia:
- 1.0
- 1.1
- nightly
matrix:
allow_failures:
Expand All @@ -17,7 +17,7 @@ after_success:
jobs:
include:
- stage: Documentation
julia: 1.0
julia: 1.1
script: julia --project=docs -e '
using Pkg;
Pkg.develop(PackageSpec(path=pwd()));
Expand Down
7 changes: 4 additions & 3 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "MagneticReadHead"
uuid = "63dd013e-5414-5e51-b21a-a24e12ed54cf"
authors = ["Lyndon White <[email protected]>"]
version = "0.2.2"
version = "0.3.0-dev"

[deps]
Cassette = "7057c7e9-c182-5462-911a-8362d720325c"
Expand All @@ -13,9 +13,10 @@ Revise = "295af30f-e4ad-537b-8983-00126c2a3abe"

[compat]
Cassette = "0.2.2"
CodeTracking = "0.4, 0.5"
CodeTracking = "0.5.0"
OrderedCollections = "1.1"
Revise = "2"
Revise = "2.1.3"
julia = "1.1"

[extras]
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
Expand Down
5 changes: 3 additions & 2 deletions src/MagneticReadHead.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,20 @@ module MagneticReadHead
using Base: invokelatest
using Cassette
using MacroTools
using OrderedCollections
using InteractiveUtils
using CodeTracking
# We don't use Revise, but if it isn't loaded CodeTracking has issues
using Revise: Revise
using OrderedCollections

export @iron_debug


include("utils.jl")
include("method_utils.jl")

include("breakpoint_rules.jl")

include("core_control.jl")
@nospecialize
include("pass.jl")
Expand All @@ -40,7 +42,6 @@ macro iron_debug(body)
# Disable any stepping left-over
ctx.metadata.stepping_mode = StepContinue
end

end
end

Expand Down
50 changes: 27 additions & 23 deletions src/break_action.jl
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@ end
function breadcrumbs(io, file::AbstractString, line_num; nbefore=2, nafter=2)
@assert(nbefore >= 0)
@assert(nafter >= 0)

all_lines = loc_for_file(file)
first_line_num = max(1, line_num - nbefore)
last_line_num = min(length(all_lines), line_num + nafter)

for ln in first_line_num:last_line_num
line = all_lines[ln]
if ln == line_num
Expand All @@ -52,36 +52,40 @@ end


# this function exists only for mocking so we can test it.
breakpoint_hit(meth, statement_ind) = nothing
breakpoint_hit(meth, statement_ind, variables) = nothing

function iron_repl(metadata::HandEvalMeta, meth, statement_ind)
breakpoint_hit(meth, statement_ind)
function iron_repl(metadata::HandEvalMeta, meth, statement_ind, variables)
breadcrumbs(meth, statement_ind)

printstyled("Vars: "; color=:light_yellow)
println(join(keys(metadata.variables), ", "))
println(join(keys(variables), ", "))
print_commands()

run_repl(metadata.variables, metadata.eval_module)

run_repl(variables, metadata.eval_module)
end

"""
should_break
Determines if we should actualy break at a potential breakpoint
"""
function should_break(ctx, meth, statement_ind)
return ctx.metadata.stepping_mode === StepNext ||
should_breakon(ctx.metadata.breakpoint_rules, meth, statement_ind)
end


"""
break_action(metadata, meth, statement_ind)
break_action
This determines what we should do when we hit a potential point to break at.
We check if we should actually break here,
and if so open up a REPL.
if not, then we continue.
What to do when a breakpoint is hit
"""
function break_action(metadata, meth, statement_ind)
if !(metadata.stepping_mode === StepNext
|| should_breakon(metadata.breakpoint_rules, meth, statement_ind)
)
# Only break on StepNext and actual breakpoints
return
end

code_word = iron_repl(metadata, meth, statement_ind)
function break_action(ctx, meth, statement_ind, slotnames, slotvals)
metadata = ctx.metadata

variables = LittleDict(slotnames, slotvals)
pop!(variables, Symbol("#self#"))
breakpoint_hit(meth, statement_ind, variables)

code_word = iron_repl(metadata, meth, statement_ind, variables)
actions[code_word].act(metadata)
end
14 changes: 8 additions & 6 deletions src/breakpoint_rules.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,27 @@ struct Rule{V}
statement_ind::Int
end
# No matter if a Function or a Method, default to break at start
Rule(v) = Rule(v, 0)
Rule(v) = Rule(v, 1)

##############################################################################
# instrumenting rules
match(rule::Rule, ::Any) = false

match(rule::Rule{Method}, method::Method) = method == rule.v
match(rule::Rule{Method}, f::F) where F = functiontypeof(rule.v) <: F

match(rule::Rule{Module}, method::Method) = moduleof(method) == rule.v
match(rule::Rule{Module}, ::F) where F = F.name.module == rule.v

# function
match(rule::Rule{F}, ::G) where {F,G} = false
match(rule::Rule{F}, ::F) where F = true
function match(rule::Rule{F}, method::Method) where F
return functiontypeof(method) <: F
end

# For breakpoints
function match(rule::Rule, method, statement_ind)
return match(rule, method) && rule.statement_ind == statement_ind
return rule.statement_ind === statement_ind && match(rule, method)
end


Expand All @@ -35,7 +36,7 @@ to allow the descision of which methods to instrument with potential breakpoints
and to decide which potential breakpoints in instrumented code to actually break on.
(When not already in stepping mode)
"""
mutable struct BreakpointRules
struct BreakpointRules
no_instrument_rules::Vector{Rule}
breakon_rules::Vector{Rule}
end
Expand Down Expand Up @@ -74,7 +75,8 @@ should be broken on.
I.e. if this point in the code has a breakpoint set.
"""
function should_breakon(rules::BreakpointRules, method, statement_ind)
return any(rules.breakon_rules) do rule
match(rule, method, statement_ind)
for rule in rules.breakon_rules
match(rule, method, statement_ind) && return true
end
return false
end
47 changes: 23 additions & 24 deletions src/core_control.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,17 @@ Cassette.@context HandEvalCtx

@enum SteppingMode StepIn StepNext StepContinue StepOut


# On the way in
@inline function child_stepping_mode!(ctx::HandEvalCtx)
cur_mode = ctx.metadata.stepping_mode
ctx.metadata.stepping_mode = cur_mode === StepIn ? StepNext : StepContinue
end

# On the way out
@inline function parent_stepping_mode!(ctx::HandEvalCtx)
cur_mode = ctx.metadata.stepping_mode
ctx.metadata.stepping_mode = cur_mode === StepContinue ? StepContinue : StepNext
end


mutable struct HandEvalMeta
variables::LittleDict{Symbol, Any}
eval_module::Module
stepping_mode::SteppingMode
breakpoint_rules::BreakpointRules
end

# TODO: Workout how we are actually going to do this in a nonglobal way
# TODO: Workout how and if we are actually going to do this in a nonglobal way
const GLOBAL_BREAKPOINT_RULES = BreakpointRules()

function HandEvalMeta(eval_module, stepping_mode)
return HandEvalMeta(
LittleDict{Symbol,Any}(),
eval_module,
stepping_mode,
GLOBAL_BREAKPOINT_RULES
Expand All @@ -49,23 +33,38 @@ function Cassette.overdub(ctx::HandEvalCtx, f, args...)
# This is basically the epicenter of all the logic
# We control the flow of stepping modes
# and which methods are instrumented or not.
cur_mode = ctx.metadata.stepping_mode

should_recurse =
ctx.metadata.stepping_mode === StepIn ||
cur_mode === StepIn ||
should_instrument(ctx.metadata.breakpoint_rules, f)

if should_recurse
if Cassette.canrecurse(ctx, f, args...)
child_stepping_mode!(ctx)
cur_variables = ctx.metadata.variables # store these for after the call
ctx.metadata.variables = LittleDict{Symbol, Any}()
# Both StepOut and StepContinue means child should StepContinue
ctx.metadata.stepping_mode = cur_mode === StepIn ? StepNext : StepContinue
# Determine stepping mode for child
try
return Cassette.recurse(ctx, f, args...)
finally
parent_stepping_mode!(ctx)
ctx.metadata.variables = cur_variables # restore them
# Determine stepping mode for parent
child_instruction = ctx.metadata.stepping_mode
ctx.metadata.stepping_mode =
child_instruction !== StepContinue ? StepNext :
cur_mode === StepIn ? StepContinue : cur_mode

# if child said StepOut or StepNext or StepIn, then we shold break on next (StepNext)
# if the child said StepContinue,
# if we were saying to StepIn can now StepContinue
# as we have completed what ever work we were doing
# if we were saying to StepContinue, then still want to continue
# (unless we hit a breakpoint where the child gave new instructions)
# But if we were StepOut then we still need to stepout til we return
# (and it gets turnd into a StepNext)
# and if we were StepNext then we made our child StepContinue,
# but we want to go StepNext ourself so have to restore that
end
else
#@assert f isa Core.Builtin
#@warn "Not able to enter into method" f args
return Cassette.fallback(ctx, f, args...)
end
Expand Down
4 changes: 3 additions & 1 deletion src/locate.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ if no matching path is found then an empty list is returned
function source_paths(mod, file)
mdata = pkgfiles(mod)
if mdata === nothing
Revise.track(mod) # maybe it is untracked (e.g. stdlib)
is_stdlib = CodeTracking.PkgId(mod).uuid === nothing
is_stdlib && Revise.track(mod) # need to track stdlibs explictly

Revise.revise() # Or maybe a Revise was pending
mdata = pkgfiles(mod)
if mdata === nothing
Expand Down
Loading

0 comments on commit 077943b

Please sign in to comment.