algebrick 0.2.2 → 0.2.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|