Skip to content

Commit

Permalink
initial work on extracting callable methods on remote drivers
Browse files Browse the repository at this point in the history
This will allow for compile time warnings when code won't work
  • Loading branch information
stakach committed Jan 30, 2019
1 parent 0972a44 commit 0e0965f
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 4 deletions.
7 changes: 7 additions & 0 deletions spec/test_build.cr
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ class Helper
end
end

module IncludedAble
def you_had_me_at_hello
"hello"
end
end

# A basic engine driver for testing
class TestDriver < HelperBase
generic_name :Driver
Expand All @@ -24,6 +30,7 @@ class Helper
},
})

accessor thing : Thing, implementing: IncludedAble
accessor main_lcd : Display_1, implementing: Powerable
accessor switcher : Switcher
accessor camera : Array(Camera), implementing: [Powerable, Moveable]
Expand Down
33 changes: 29 additions & 4 deletions src/engine-driver/utilities/discovery.cr
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,11 @@ abstract class EngineDriver

# Creates helper methods for accessing proxy objects
macro accessor(name, implementing = nil)
# ntype is the type of the name attribute. i.e. Display
{% ntype = name.type %}
{% optional = false %}
{% collection = false %}
{% methods = [] of Crystal::Macros::TypeNode %}

{% if ntype.is_a?(Union) %}
# Anything with a ? goes here: Array(Int32)? + Int32?
Expand Down Expand Up @@ -84,19 +86,42 @@ abstract class EngineDriver
# Ensure implementing is an Array
{% if implementing %}
{% if !implementing.is_a?(ArrayLiteral) %}
{% implementing = [implementing.id.stringify] %}
{% implementing = [implementing] %}
{% end %}

# Attempt to inspect the modules so we can have compile time checking
{% compiler_enforced = true %}
{% for type in implementing %}
{% klass = type.resolve? %}
{% if klass %}
{% methods = methods + klass.methods %}
{% klasses = klass.ancestors.reject { |a| IGNORE_KLASSES.includes?(a.stringify) } %}
{% klasses.map { |a| methods = methods + a.methods } %}
{% else %}
{% compiler_enforced = false %}
{% end %}
{% end %}

{% if compiler_enforced %}
{% methods = methods.reject { |method| RESERVED_METHODS[method.name.stringify] } %}
{% methods = methods.reject { |method| method.visibility != :public } %}
{% methods = methods.reject { |method| method.accepts_block? } %}
{% else %}
{% implementing = implementing.map(&.id.stringify) %}
{% methods = [] of Crystal::Macros::TypeNode %}
{% end %}

# {{methods.map &.name.stringify}} <- How does this look?

{% implements = implementing.map(&.id.stringify) %}
{% else %}
{% implementing = "[] of String".id %}
{% implements = "[] of String".id %}
{% end %}

# non optional requirements to be recorded
{% if !optional %}
%requirements = Utilities::Discovery.requirements
%existing = %requirements[{{ntype}}]? || [] of String
%existing += {{implementing}}
%existing += {{implements}}
%existing.uniq!
%requirements[{{ntype}}] = %existing
{% end %}
Expand Down

0 comments on commit 0e0965f

Please sign in to comment.