Skip to content
Permalink
Browse files

SC::Compiler - Detect and dump missing specs into .sc/undefined.yml

  • Loading branch information...
robertodecurnex committed Mar 11, 2015
1 parent b77ee6d commit 4e663807119c6d41dbbeae07fc9f8207c4c996b4
@@ -1,4 +1,6 @@
require 'digest'
require 'yaml'
require 'yaml/store'

require_relative 'sc/compiler.rb'
require_relative 'sc/database.rb'
@@ -5,11 +5,8 @@ module SC
# implementations (specs without an associated lambda)
class Compiler

attr_accessor :sc_path

def initialize sc_path='.sc'
def initialize
@@instance = self
self.sc_path = sc_path
end

# Returns the singleton instance of SC::Compiler
@@ -25,20 +22,42 @@ def self.instance
#
# @return [SC::Compiler] self
def compile
files_specs = self.targets.inject({}) do |memo, path|
memo[path] = SC::Spec::Parser.parse(path)
undefined_yaml = YAML::Store.new(".sc/undefined.yml")
undefined_yaml.transaction do
targets().map do |path|
missing_specs = missing_specs_from_file(path)

next if missing_specs.empty?

undefined_yaml[path] = missing_specs
end
end
#TODO: Reject specs already registered on index.yml
# and dump the rest of them into the undefined.yml

return self
end

private

# Parse the specs on the given file path and return those specs
# that have not been fulfilled or need to be updated.
#
# @param [String] path target file path
# @return [<SC::Spec>] collection of specs not fulfilled or out of date
def missing_specs_from_file(path)
SC::Spec::Parser.parse(path).select do |spec|
index_spec = SC::Database.index[path] && SC::Database.index[path][spec.signature.name]
index_spec.nil? || index_spec['spec_md5'] != spec.md5
end
end

# Filter project's rb files returning an Array of files
# containinig specs to be parsed.
#
# @return [<String>] array of files to be parsed
def targets
return %x[ grep -Pzrl --include="*.rb" "^__END__.*\\n.*spec_for" . ].split("\n")
return %x[ grep -Pzrl --include="*.rb" "^__END__.*\\n.*spec_for" . ].split("\n").collect do |path|
path[2..-1]
end
end

end
@@ -5,13 +5,15 @@ module SC
# to fetch specific elements by different criterias.
class Database

attr_accessor :cache, :index, :sc_path
attr_accessor :cache

def initialize sc_path='.sc'
def initialize
@@instance = self
self.cache = {}
self.sc_path = sc_path
self.index = YAML.load_file("#{self.sc_path}/index.yml")
end

def index
@index ||= YAML.load_file('./.sc/index.yml')
end

# Instance delegator of SC::Database#fetch
@@ -24,6 +26,13 @@ def self.fetch klass, method_name, *required_params
self.instance.fetch(klass, method_name, *required_params)
end

# Instane delegator of SC::Database#index
#
# @return [Hash] the parsed index as Hash
def self.index
self.instance.index
end

# Returns the singleton instance of SC::Database
#
# @return [SC::Database] Current/new instance of the SC::Database
@@ -39,8 +48,8 @@ def self.instance
# @param [<Symbol>] required_params parameters that would be required by the lambda
# @return [Proc] the labda that would be implemented
def fetch file_path, method_name, *required_params
λ_id = self.index["#{file_path}"]["#{method_name}:#{required_params.count}"]
return self.cache[λ_id] ||= eval(File.read("#{self.sc_path}/cache/#{λ_id}.rb"))
λ_id = self.index["#{file_path}"]["#{method_name}"]['lambda_id']
return self.cache[λ_id] ||= eval(File.read(".sc/cache/#{λ_id}.rb"))
end

end
@@ -6,11 +6,13 @@ module SC

class Spec

attr_accessor :rules, :signature

attr_accessor :md5, :rules, :signature

# @param [String] spec md5
# @param [SC::Spec::Signature] signature spec signature
# @param [<SC::Spec::Rule>] rules collection of spec rules
def initialize signature, rules
def initialize md5, signature, rules
self.md5 = md5
self.rules = rules
self.signature = signature
end
@@ -45,7 +45,9 @@ def parse_spec raw_spec
self.parse_spec_rule(spec_raw_rule)
end

return SC::Spec.new(spec_signature, spec_rules)
spec_md5 = Digest::MD5.hexdigest(raw_spec)

return SC::Spec.new(spec_md5, spec_signature, spec_rules)
end

# Returns a SC::Spec::Rule instance from the raw spec rule
@@ -1,5 +1,5 @@
task default: %w[test]

task :test do
ruby "test/test.rb"
ruby "test/test.rb --verbose"
end
@@ -0,0 +1,7 @@
# THIS FILE HAS BEEN AUTOGENERATED BY CS
# DO NOT MODIFY ITS CONTENT. IT WILL BE
# OVERWRITTEN.

lambda do |i1, i2|
return i1 + i2
end
@@ -0,0 +1,7 @@
# THIS FILE HAS BEEN AUTOGENERATED BY CS
# DO NOT MODIFY ITS CONTENT. IT WILL BE
# OVERWRITTEN.

lambda do |f1, f2, f3|
return f3 * f2 / f1
end
@@ -0,0 +1,7 @@
# THIS FILE HAS BEEN AUTOGENERATED BY CS
# DO NOT MODIFY ITS CONTENT. IT WILL BE
# OVERWRITTEN.

lambda do |s1|
return "Say Hello to #{s1}"
end
@@ -3,7 +3,13 @@
# OVERWRITTEN.

sample.rb:
"hello:1": 7e46ad07603d4044a8d70c9004c48adf
"sum:2": aac019283279bcb5f59f9760865f7d77
"rule_of_three:3": 2e0dcba288b50596b4cdd8680fffbf2e
"hello":
lambda_id: bfc794ba0e2f5aca9a2e4550ad8632e7
spec_md5: 1aa2c69a47b054824a21b295f089ca3d
"sum":
lambda_id: 1db993c17e61ad1fa3a064b34892ff11
spec_md5: 0f53328066424f07d2a5bd8bebbdd534
"rule_of_three":
lambda_id: 8832fa985fc6ed6453428472a05f50c0
spec_md5: 2690a33a08fc2ccf651fb79dbeda10f8

@@ -1,10 +1,14 @@
# THIS FILE HAS BEEN AUTOGENERATED BY CS
# DO NOT MODIFY ITS CONTENT. IT WILL BE
# OVERWRITTEN.

---
sample.rb:
- 'unknown_lambda:1':
signature: 'FalseClass -> TrueClass'
rules:
- 'false -> true'

- !ruby/object:SC::Spec
md5: 94dd639208a00598a7248336398ad769
rules:
- !ruby/object:SC::Spec::Rule
output: true
params:
- false
signature: !ruby/object:SC::Spec::Signature
name: unknown_lambda
output_type: TrueClass
params_types:
- FalseClass
@@ -15,6 +15,8 @@ def double n1

end



__END__
spec_for hello String -> String
"Minion" -> "Say Hello to Minion"
@@ -0,0 +1,7 @@
# THIS FILE HAS BEEN AUTOGENERATED BY CS
# DO NOT MODIFY ITS CONTENT. IT WILL BE
# OVERWRITTEN.

lambda do |i1, i2|
return i1 + i2
end
@@ -0,0 +1,7 @@
# THIS FILE HAS BEEN AUTOGENERATED BY CS
# DO NOT MODIFY ITS CONTENT. IT WILL BE
# OVERWRITTEN.

lambda do |f1, f2, f3|
return f3 * f2 / f1
end
@@ -0,0 +1,7 @@
# THIS FILE HAS BEEN AUTOGENERATED BY CS
# DO NOT MODIFY ITS CONTENT. IT WILL BE
# OVERWRITTEN.

lambda do |s1|
return "Say Hello to #{s1}"
end
@@ -2,8 +2,14 @@
# DO NOT MODIFY ITS CONTENT. IT WILL BE
# OVERWRITTEN.

test/files/sample.rb:
"hello:1": 7e46ad07603d4044a8d70c9004c48adf
"sum:2": aac019283279bcb5f59f9760865f7d77
"rule_of_three:3": 2e0dcba288b50596b4cdd8680fffbf2e
sample.rb:
"hello":
lambda_id: bfc794ba0e2f5aca9a2e4550ad8632e7
spec_md5: 1aa2c69a47b054824a21b295f089ca3d
"sum":
lambda_id: 1db993c17e61ad1fa3a064b34892ff11
spec_md5: 0f53328066424f07d2a5bd8bebbdd534
"rule_of_three":
lambda_id: 8832fa985fc6ed6453428472a05f50c0
spec_md5: 2690a33a08fc2ccf651fb79dbeda10f8

@@ -1,10 +1,14 @@
# THIS FILE HAS BEEN AUTOGENERATED BY CS
# DO NOT MODIFY ITS CONTENT. IT WILL BE
# OVERWRITTEN.

---
sample.rb:
"unknown:0":
signature: "FalseClass -> TrueClass"
rules:
- "False -> True"

- !ruby/object:SC::Spec
md5: 94dd639208a00598a7248336398ad769
rules:
- !ruby/object:SC::Spec::Rule
output: true
params:
- false
signature: !ruby/object:SC::Spec::Signature
name: unknown_lambda
output_type: TrueClass
params_types:
- FalseClass
@@ -8,7 +8,7 @@ def setup
end

def test_equal
skip
skip "Assert that two different instances of SC::Spec::Rule are == if their instance variables are =="
end

end
@@ -8,7 +8,7 @@ def setup
end

def test_equal
skip
skip "Assert that two different instances of SC::Spec::Signature are == if their instance variables are =="
end

end
@@ -6,30 +6,41 @@ def setup
if File.exists?('test/files/.sc/undefined.yml')
FileUtils.remove_file('test/files/.sc/undefined.yml')
end
@compiler = SC::Compiler.new('test/files/.sc')
@compiler = SC::Compiler.new
end

def test_instance
assert_equal @compiler, SC::Compiler.instance
end

def test_targets
assert_equal ['./sample/sample.rb', './test/files/sample.rb'], @compiler.targets.sort
Dir.chdir('test/files') do
assert_equal ['sample.rb'], @compiler.send(:targets).sort
end
end

def test_compile
skip
@compiler.compile
expected_undefined = {
'test/files/sample.rb' => {
'unknown_lambda:1' => {
'signature' => 'FalseClass -> TrueClass',
'rules' => ['false -> true']
}
}
}
Dir.chdir('test/files') do
@compiler.compile
end
expected_yaml = <<YAML
---
"sample.rb":
- !ruby/object:SC::Spec
md5: 94dd639208a00598a7248336398ad769
rules:
- !ruby/object:SC::Spec::Rule
output: true
params:
- false
signature: !ruby/object:SC::Spec::Signature
name: unknown_lambda
output_type: TrueClass
params_types:
- FalseClass
YAML
assert File.exists?('test/files/.sc/undefined.yml'), 'SC::Compiler#compile was expected to create an undefined.yml file but it did not.'
assert_equal expected_undefined, YAML.load_file('test/files/.sc/undefined.yml')
assert_equal YAML.load(expected_yaml), YAML.load_file('test/files/.sc/undefined.yml')
end

end
@@ -3,19 +3,24 @@ class TestSC < Minitest::Test
class TestDatabase < Minitest::Test

def setup
@database = SC::Database.new('./test/files/.sc')
@database = SC::Database.new
end

def test_instance
assert_equal @database, SC::Database.instance
end

def test_class_fetch
assert_equal @database.fetch('test/files/sample.rb', 'hello', [:name]), SC::Database.fetch('test/files/sample.rb', 'hello', [:name])
Dir.chdir('test/files') do
assert_equal @database.fetch('sample.rb', 'hello', [:name]), SC::Database.fetch('sample.rb', 'hello', [:name])
end
end

def test_fetch
λ = @database.fetch('test/files/sample.rb', 'hello', [:name])
λ = nil
Dir.chdir('test/files') do
λ = @database.fetch('sample.rb', 'hello', [:name])
end
assert_instance_of Proc, λ
assert λ.lambda?, 'SC::Database#fetch was expected to return a lambda type of Proc but it did not.'
assert_equal 'Say Hello to Test', λ.call('Test')
@@ -10,7 +10,7 @@ def setup
end

def test_equal
skip
skip "Assert that two different instances of SC::Spec are == if their instance variables are =="
end

end

0 comments on commit 4e66380

Please sign in to comment.
You can’t perform that action at this time.