algebrick 0.2.2 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README_FULL.md +0 -6
- data/VERSION +1 -1
- data/lib/algebrick.rb +106 -42
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 89c05ba82f9bb193d0cf67ba85d5fc8138d2a3a3
|
4
|
+
data.tar.gz: 2dd790e7a2b66e0ae466c2422a053f7acd280e2d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: db7d3e5b6f804119b92dd522cf1860fe6c26bf16b14be44c352f82b74728fc563a4665ed698f2fb7f63d8c70d84585abf14a4088cce580da735e6073237073d7
|
7
|
+
data.tar.gz: ca7af9d723d0c8b57397be9b9cd259a274cd98970af2852257e0d52d786eea9b2e3f822a15abb6bf916b70d7cbda8c64a6ada87f34f9670673474f3f038e77e2
|
data/README_FULL.md
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.2.
|
1
|
+
0.2.3
|
data/lib/algebrick.rb
CHANGED
@@ -15,6 +15,11 @@
|
|
15
15
|
|
16
16
|
# TODO method definition in variant type defines methods on variants based on match, better performance?
|
17
17
|
# TODO type variables/constructor maybe(a) === none | a
|
18
|
+
# TODO add matcher/s for Hash
|
19
|
+
# TODO add method matcher (:size, matcher)
|
20
|
+
# TODO Menu modeling example, add TypedArray
|
21
|
+
# TODO update actor pattern example when gem is done
|
22
|
+
# TODO example with birth-number Valid|Invalid
|
18
23
|
|
19
24
|
require 'set'
|
20
25
|
|
@@ -283,7 +288,7 @@ module Algebrick
|
|
283
288
|
|
284
289
|
def to_s
|
285
290
|
"#{self.class.type.name}[" +
|
286
|
-
if type.field_names
|
291
|
+
if type.field_names?
|
287
292
|
type.field_names.map { |name| "#{name}: #{self[name].to_s}" }.join(', ')
|
288
293
|
else
|
289
294
|
fields.map(&:to_s).join(',')
|
@@ -300,7 +305,7 @@ module Algebrick
|
|
300
305
|
|
301
306
|
def to_hash
|
302
307
|
{ TYPE_KEY => self.class.type.name }.
|
303
|
-
update(if type.field_names
|
308
|
+
update(if type.field_names?
|
304
309
|
type.field_names.inject({}) { |h, name| h.update name => hashize(self[name]) }
|
305
310
|
else
|
306
311
|
{ FIELDS_KEY => fields.map { |v| hashize v } }
|
@@ -334,7 +339,7 @@ module Algebrick
|
|
334
339
|
end
|
335
340
|
|
336
341
|
class ProductVariant < Type
|
337
|
-
attr_reader :fields, :
|
342
|
+
attr_reader :fields, :variants
|
338
343
|
|
339
344
|
def set_fields(fields_or_hash)
|
340
345
|
raise TypeError, 'can be set only once' if @fields
|
@@ -346,16 +351,28 @@ module Algebrick
|
|
346
351
|
|
347
352
|
set_field_names keys if keys
|
348
353
|
|
349
|
-
fields.all? { |f| is_kind_of! f, Type, Class }
|
354
|
+
fields.all? { |f| is_kind_of! f, Type, Class, Module }
|
350
355
|
raise TypeError, 'there is no product with zero fields' unless fields.size > 0
|
351
356
|
define_method(:value) { @fields.first } if fields.size == 1
|
352
357
|
@fields = fields
|
353
358
|
@constructor = Class.new(ProductConstructor).tap { |c| c.type = self }
|
354
359
|
end
|
355
360
|
|
361
|
+
def field_names
|
362
|
+
@field_names or raise TypeError, "field names not defined on #{self}"
|
363
|
+
end
|
364
|
+
|
365
|
+
def field_names?
|
366
|
+
!!@field_names
|
367
|
+
end
|
368
|
+
|
369
|
+
def field_indexes
|
370
|
+
@field_indexes or raise TypeError, "field names not defined on #{self}"
|
371
|
+
end
|
372
|
+
|
356
373
|
def add_field_method_reader(field)
|
357
|
-
raise TypeError, 'no field names' unless
|
358
|
-
raise ArgumentError, "no field name #{field}" unless
|
374
|
+
raise TypeError, 'no field names' unless field_names?
|
375
|
+
raise ArgumentError, "no field name #{field}" unless field_names.include? field
|
359
376
|
raise ArgumentError, "method #{field} already defined" if instance_methods.include? field
|
360
377
|
define_method(field) { self[field] }
|
361
378
|
self
|
@@ -486,7 +503,7 @@ module Algebrick
|
|
486
503
|
private
|
487
504
|
|
488
505
|
def product_to_s
|
489
|
-
fields_str = if field_names
|
506
|
+
fields_str = if field_names?
|
490
507
|
field_names.zip(fields).map { |name, field| "#{name}: #{field.name}" }
|
491
508
|
else
|
492
509
|
fields.map(&:name)
|
@@ -517,7 +534,7 @@ module Algebrick
|
|
517
534
|
self[*fields.map { |value| field_from_hash value }]
|
518
535
|
when Hash
|
519
536
|
self[fields.inject({}) do |h, (name, value)|
|
520
|
-
raise ArgumentError unless
|
537
|
+
raise ArgumentError unless field_names.map(&:to_s).include? name.to_s
|
521
538
|
h.update name.to_sym => field_from_hash(value)
|
522
539
|
end]
|
523
540
|
end
|
@@ -542,52 +559,80 @@ module Algebrick
|
|
542
559
|
end
|
543
560
|
end
|
544
561
|
|
545
|
-
|
546
|
-
|
562
|
+
module DSL
|
563
|
+
module Shortcuts
|
564
|
+
def type(&block)
|
565
|
+
Algebrick.type &block
|
566
|
+
end
|
547
567
|
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
@new_type.kind
|
568
|
+
def atom
|
569
|
+
Algebrick.atom
|
570
|
+
end
|
552
571
|
end
|
553
572
|
|
554
|
-
|
555
|
-
|
556
|
-
self
|
557
|
-
end
|
573
|
+
class TypeDefinitionScope
|
574
|
+
include Shortcuts
|
558
575
|
|
559
|
-
|
560
|
-
@new_type.set_variants variants
|
561
|
-
self
|
562
|
-
end
|
576
|
+
attr_reader :new_type
|
563
577
|
|
564
|
-
|
565
|
-
|
566
|
-
|
578
|
+
def initialize(&block)
|
579
|
+
@new_type = ProductVariant.new nil
|
580
|
+
instance_exec @new_type, &block
|
581
|
+
@new_type.kind
|
582
|
+
end
|
567
583
|
|
568
|
-
|
569
|
-
|
570
|
-
|
584
|
+
def fields(*fields)
|
585
|
+
@new_type.set_fields fields
|
586
|
+
self
|
587
|
+
end
|
588
|
+
|
589
|
+
def variants(*variants)
|
590
|
+
@new_type.set_variants variants
|
591
|
+
self
|
592
|
+
end
|
593
|
+
|
594
|
+
def field_readers(*names)
|
595
|
+
@new_type.add_field_method_readers *names
|
596
|
+
self
|
597
|
+
end
|
598
|
+
|
599
|
+
alias_method :readers, :field_readers
|
600
|
+
|
601
|
+
def all_field_readers
|
602
|
+
@new_type.add_all_field_method_readers
|
603
|
+
self
|
604
|
+
end
|
605
|
+
|
606
|
+
alias_method :all_readers, :all_field_readers
|
571
607
|
end
|
572
608
|
|
573
|
-
|
609
|
+
class OuterShellImpl
|
610
|
+
include Shortcuts
|
574
611
|
|
575
|
-
|
576
|
-
|
577
|
-
|
612
|
+
def run(&block)
|
613
|
+
instance_eval &block
|
614
|
+
end
|
578
615
|
end
|
579
616
|
|
580
|
-
|
617
|
+
OuterShell = OuterShellImpl.new
|
581
618
|
end
|
582
619
|
|
583
620
|
def self.type(&block)
|
584
621
|
if block.nil?
|
585
|
-
|
622
|
+
atom
|
586
623
|
else
|
587
|
-
TypeDefinitionScope.new(&block).new_type
|
624
|
+
DSL::TypeDefinitionScope.new(&block).new_type
|
588
625
|
end
|
589
626
|
end
|
590
627
|
|
628
|
+
def self.atom
|
629
|
+
Atom.new nil
|
630
|
+
end
|
631
|
+
|
632
|
+
def self.types(&block)
|
633
|
+
DSL::OuterShell.run &block
|
634
|
+
end
|
635
|
+
|
591
636
|
module Matchers
|
592
637
|
|
593
638
|
class Abstract
|
@@ -897,20 +942,39 @@ module Algebrick
|
|
897
942
|
end
|
898
943
|
end
|
899
944
|
|
900
|
-
# TODO Hash matcher
|
901
|
-
# TODO Method matcher (:size, matcher)
|
902
|
-
|
903
945
|
class Product < Abstract
|
904
|
-
# TODO allow to match by field_name e.g. Address.(:street)
|
905
946
|
attr_reader :algebraic_type, :field_matchers
|
906
947
|
|
907
948
|
def initialize(algebraic_type, *field_matchers)
|
908
949
|
super()
|
909
950
|
@algebraic_type = is_kind_of! algebraic_type, Algebrick::ProductVariant
|
910
951
|
raise ArgumentError unless algebraic_type.fields
|
911
|
-
field_matchers
|
912
|
-
|
913
|
-
|
952
|
+
@field_matchers = case
|
953
|
+
when field_matchers.empty?
|
954
|
+
::Array.new(algebraic_type.fields.size) { Algebrick.any }
|
955
|
+
|
956
|
+
when field_matchers.size == 1 && field_matchers.first.is_a?(Hash)
|
957
|
+
field_matchers = field_matchers.first
|
958
|
+
unless (dif = field_matchers.keys - algebraic_type.field_names).empty?
|
959
|
+
raise ArgumentError, "no #{dif} fields in #{algebraic_type}"
|
960
|
+
end
|
961
|
+
algebraic_type.field_names.map do |field|
|
962
|
+
field_matchers[field] || Algebrick.any
|
963
|
+
end
|
964
|
+
when field_matchers.is_a?(::Array) && field_matchers.all? { |v| v.is_a? Symbol }
|
965
|
+
unless (dif = field_matchers - algebraic_type.field_names).empty?
|
966
|
+
raise ArgumentError, "no #{dif} fields in #{algebraic_type}"
|
967
|
+
end
|
968
|
+
algebraic_type.field_names.map do |field|
|
969
|
+
field_matchers.include?(field) ? ~Algebrick.any : Algebrick.any
|
970
|
+
end
|
971
|
+
|
972
|
+
else
|
973
|
+
field_matchers
|
974
|
+
end
|
975
|
+
unless algebraic_type.fields.size == @field_matchers.size
|
976
|
+
raise ArgumentError
|
977
|
+
end
|
914
978
|
end
|
915
979
|
|
916
980
|
def children
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: algebrick
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Petr Chalupa
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-09-
|
11
|
+
date: 2013-09-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: minitest
|