Permalink
Browse files

Update README.md

Adding CodeClimate badge

Updating Docs

Adding .gitignore

Update README.md

Adding YARD Docs badge

Adding SC::Spec

Adding SC::Spec::Parser

Adding SC::Spec::Parser tests

Adding Rake

Adding Travis Config

Create LICENSE

Updating gemspec

adding minitest as dep

Adding CC coverage report

Adding SC::Database tests

Mocking sample class for SC::Database tests

Improving SC::Databasetest coverage

SC tests
  • Loading branch information...
robertodecurnex committed Feb 27, 2015
1 parent 7bc5020 commit fdbae538224984060108c8bb9008765dbbb667d0
View
@@ -0,0 +1,4 @@
Gemfile.lock
coverage/*
sample/Gemfile.lock
.yardoc
View
@@ -0,0 +1,7 @@
language: ruby
rvm:
- ruby-head
- 2.2.1
addons:
code_climate:
repo_token: 41068f41a81afe631660b946d25f757ac81d7d65b6e9fd5bd196db1aaf7bd619
View
@@ -0,0 +1,3 @@
source 'https://rubygems.org'
gemspec
View
21 LICENSE
@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2015 Roberto Decurnex
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
View
@@ -3,6 +3,12 @@
Specs driven social meta-programming
[![Build Status](https://api.travis-ci.org/robertodecurnex/sc.png)](https://travis-ci.org/robertodecurnex/sc)
[![Code Climate](https://codeclimate.com/github/robertodecurnex/sc/badges/gpa.svg)](https://codeclimate.com/github/robertodecurnex/sc)
[![Coverage Status](https://coveralls.io/repos/robertodecurnex/sc/badge.svg?branch=master)](https://coveralls.io/r/robertodecurnex/sc?branch=master)
[![Test Coverage](https://codeclimate.com/github/robertodecurnex/sc/badges/coverage.svg)](https://codeclimate.com/github/robertodecurnex/sc)
[![YARD Docs](https://img.shields.io/badge/YARD-Docs-blue.svg)](http://www.rubydoc.info/github/robertodecurnex/sc/master)
## Prototype
```ruby
View
@@ -1,6 +1,7 @@
require 'yaml'
require_relative 'sc/database.rb'
require_relative 'sc/spec.rb'
# Specs driven social meta-programming
module SC
@@ -14,8 +15,7 @@ module ClassMethods
# Register the given method name supporting the given parameters.
#
# @param [Symbol|String] name the method name to register
# @param [<Symbol|String>] params that the method supports
# @param [{String, Symbol=><String, Symbol>}] interfaces hash of method names and required param names that the method supports
def implements interfaces
interfaces.each do |method_name, required_params|
λ = SC::Database.fetch(self, method_name, *required_params)
@@ -27,67 +27,3 @@ def implements interfaces
end
__END__
content, meta = File.read('sample.rb').split("__END__\n")
place_holders = content.scan /#sc \w+(?:\(\w+(?:, \w+)*\))?/
rules = meta.scan /sc \w+(?: \w+(?:, \w+)*)?: \w+\n(?: {2,4}[^\n]+(?:, [^\n]+)* -> [^\n]+\n)+/
protos = {}
facts = {}
rules.each do |rule|
split = rule.split("\n")
definition = split.shift.split(/(?::|,)? /)
protos[definition[1]] = definition[2..-1].map {|e| puts e; eval(e)}
facts[definition[1]] = split.inject([]) do |memo, fact|
memo << fact.strip.split(/(?:, )|(?: -> )/).map {|e| eval(e)}
memo
end
end
kb = {
[String, String] => [
%q{lambda {|string| string + 'lalala' }},
%q{lambda {|string| "Say Hello to #{string}" }}
],
[String, String, String] => [
%q{lambda {|s1, s2| "Nada q ver" }},
%q{lambda {|s1, s2| "#{s1} plus #{s1} == #{s2}" }},
%q{lambda {|s1, s2| "God help us" }}
]
}
resp = {}
protos.each do |name, signature|
throw "No tengo esa signature sorete!" if kb[signature].nil?
resp[name] = kb[signature].detect do |code|
facts[name].all? do |fact|
eval(code).call(*fact[0..-2]) == fact[-1]
end
end
end
puts resp.inspect
sc_class = "\nclass SC\n"
place_holders.each do |ph|
puts ph
a, proto_name, *var_names = ph.split(/[ (),]/)
var_names = var_names.reject {|v| v.empty?}
puts var_names.inspect
content.gsub!(ph, "#{ph}\nSC.#{ph.sub('#sc ','')}")
protos[proto_name]
sc_class << <<TAIL
def SC.#{proto_name}(#{var_names.join(', ')})
#{resp[proto_name]}.call(#{var_names.join(', ')})
end
TAIL
end
sc_class << "end\n"
content = sc_class + content
File.write('sample_out.rb', content)
View
@@ -5,10 +5,13 @@ module SC
# to fetch specific elements by different criterias.
class Database
attr_accessor :index
attr_accessor :cache, :index, :sc_path
def initialize
self.index = YAML.load_file('./.sc/index.yml')
def initialize sc_path='./.sc'
@@instance = self
self.cache = {}
self.sc_path = sc_path
self.index = YAML.load_file("#{self.sc_path}/index.yml")
end
# Instance delegator of SC::Database#fetch
@@ -37,7 +40,7 @@ def self.instance
# @return [Proc] the labda that would be implemented
def fetch klass, method_name, *required_params
λ_id = self.index["#{klass}"]["#{method_name}:#{required_params.count}"]
eval(File.read("./.sc/cache/#{λ_id}.rb"))
return self.cache[λ_id] ||= eval(File.read("#{self.sc_path}/cache/#{λ_id}.rb"))
end
end
View
@@ -0,0 +1,20 @@
require_relative 'spec/parser.rb'
require_relative 'spec/rule.rb'
require_relative 'spec/signature.rb'
module SC
class Spec
attr_accessor :rules, :signature
# @param [SC::Spec::Signature] signature spec signature
# @param [<SC::Spec::Rule>] rules collection of spec rules
def initialize signature, rules
self.rules = rules
self.signature = signature
end
end
end
View
@@ -0,0 +1,72 @@
module SC
class Spec
# Parser to get SC::Spec instances from the metadata on the program's files
class Parser
attr_accessor :file_path
# @param [String] file_path the path of the file to parse
def initialize file_path
self.file_path = file_path
end
# Look for specs on the given file and parse them as SC::Specs
#
# @return [<SC::Spec>] collection of specs found in the given file
def parse
/.*^__END__$(?<raw_specs>.*)\Z/m =~ File.read(self.file_path)
return raw_specs.split('spec_for')[1..-1].map do |raw_spec|
self.parse_spec raw_spec
end
end
# Parses a raw spec and returns an SC::Spec instance
#
# @param [String] raw_spec raw spec
# @return [SC::Spec] the SC::Spec instance
def parse_spec raw_spec
spec_raw_signature, *spec_raw_rules = raw_spec.split("\n")
spec_signature = self.parse_spec_signature(spec_raw_signature)
spec_rules = spec_raw_rules.map do |spec_raw_rule|
self.parse_spec_rule(spec_raw_rule)
end
return SC::Spec.new(spec_signature, spec_rules)
end
# Returns a SC::Spec::Rule instance from the raw spec rule
#
# @param [String] spec_raw_rule raw rule if the spec
# @return [SC::Spec::Rule]
def parse_spec_rule spec_raw_rule
# REGEX HERE PLEASE, F%#&!@* EASY
raw_params, raw_output = spec_raw_rule.split('->').map(&:strip)
output = eval(raw_output)
params = raw_params.split(/,\s+/).map do |raw_param|
eval(raw_param)
end
return SC::Spec::Rule.new(params, output)
end
# Returns a SC::Spec::Signature from the raw spec signature
#
# @param [String] spec_raw_signature raw signature of the spec
# @param [<SC::Spec::Signature]
def parse_spec_signature spec_raw_signature
# REGEX HERE PLEASE, F%#&!@* EASY
raw_name_and_params_types, output_type = spec_raw_signature.split('->').map(&:strip)
name, *params_types = raw_name_and_params_types.split(/,?\s+/).map(&:strip)
return SC::Spec::Signature.new(name, params_types, output_type)
end
end
end
end
View
@@ -0,0 +1,22 @@
module SC
class Spec
# Assert representation based on input params and an expected output.
# Meant to be used against an algorith to test its behavior.
class Rule
attr_accessor :output, :params
# @param [<Object>] parmas set of input params
# @param [<Object>] output expected result
def initialize params, output
self.output = output
self.params = params
end
end
end
end
View
@@ -0,0 +1,23 @@
module SC
class Spec
# Representation of the required input/output types
class Signature
attr_accessor :name, :output_type, :params_types
# @param [String] name local name of the algorith (not sure if needed)
# @param [<String>] param_types types of the expected input params
# @param [String] output_type type of the expected output
def initialize name, params_types, output_type
self.name = name
self.output_type = output_type
self.params_types = params_types
end
end
end
end
View
@@ -0,0 +1,5 @@
task default: %w[test]
task :test do
ruby "test/test.rb"
end
View

This file was deleted.

Oops, something went wrong.
View
@@ -9,7 +9,18 @@ Gem::Specification.new do |s|
s.version = '0.1'
s.files = [
'lib/sc.rb'
'README.md',
'lib/sc.rb',
'lib/sc/database.rb',
'lib/sc/spec.rb',
'lib/sc/spec/parser.rb',
'lib/sc/spec/rule.rb',
'lib/sc/spec/signature.rb'
]
s.add_development_dependency 'codeclimate-test-reporter'
s.add_development_dependency 'minitest'
s.add_development_dependency 'rake'
s.add_development_dependency 'yard'
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
@@ -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
View
@@ -0,0 +1,9 @@
# THIS FILE HAS BEEN AUTOGENERATED BY CS
# DO NOT MODIFY ITS CONTENT. IT WILL BE
# OVERWRITTEN.
Sample:
"hello:1": 7e46ad07603d4044a8d70c9004c48adf
"sum:2": aac019283279bcb5f59f9760865f7d77
"rule_of_three:3": 2e0dcba288b50596b4cdd8680fffbf2e
Oops, something went wrong.

0 comments on commit fdbae53

Please sign in to comment.