algebrick 0.2.2 → 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (5) hide show
  1. checksums.yaml +4 -4
  2. data/README_FULL.md +0 -6
  3. data/VERSION +1 -1
  4. data/lib/algebrick.rb +106 -42
  5. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 13d3ecc1ea957d30796a0a4a66c670707c52d12c
4
- data.tar.gz: 90fdd38aaee376f2b48c7c8885e979cc5e3b634d
3
+ metadata.gz: 89c05ba82f9bb193d0cf67ba85d5fc8138d2a3a3
4
+ data.tar.gz: 2dd790e7a2b66e0ae466c2422a053f7acd280e2d
5
5
  SHA512:
6
- metadata.gz: a0a8bdc76d1fd32d8c3e9f214a03eb9d9802def07fdc5dd0e407b72edb5b53d2c87030bddb01f243afb4a086baff074b058a190f7737bf1d4104248853802517
7
- data.tar.gz: 435a6f291c7c9c4d7cad122a0c412627c95182b3a06e54c32d79d49d3d0cc30b965eb6f8d79e22b9234797fc3802f289d7eeb3ed4c69602146c647958202aba7
6
+ metadata.gz: db7d3e5b6f804119b92dd522cf1860fe6c26bf16b14be44c352f82b74728fc563a4665ed698f2fb7f63d8c70d84585abf14a4088cce580da735e6073237073d7
7
+ data.tar.gz: ca7af9d723d0c8b57397be9b9cd259a274cd98970af2852257e0d52d786eea9b2e3f822a15abb6bf916b70d7cbda8c64a6ada87f34f9670673474f3f038e77e2
data/README_FULL.md CHANGED
@@ -93,9 +93,3 @@ Just small snippet from a gem I am still working on.
93
93
  end
94
94
  end
95
95
  end
96
-
97
- ### TODO
98
-
99
- - Menu model, TypedArray
100
- - update actor pattern when gem is done
101
- - example with birth-number Valid|Invalid
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.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, :field_names, :field_indexes, :variants
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 @field_names
358
- raise ArgumentError, "no field name #{field}" unless @field_names.include? field
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 @field_names.map(&:to_s).include? name.to_s
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
- class TypeDefinitionScope
546
- attr_reader :new_type
562
+ module DSL
563
+ module Shortcuts
564
+ def type(&block)
565
+ Algebrick.type &block
566
+ end
547
567
 
548
- def initialize(&block)
549
- @new_type = ProductVariant.new nil
550
- instance_exec @new_type, &block
551
- @new_type.kind
568
+ def atom
569
+ Algebrick.atom
570
+ end
552
571
  end
553
572
 
554
- def fields(*fields)
555
- @new_type.set_fields fields
556
- self
557
- end
573
+ class TypeDefinitionScope
574
+ include Shortcuts
558
575
 
559
- def variants(*variants)
560
- @new_type.set_variants variants
561
- self
562
- end
576
+ attr_reader :new_type
563
577
 
564
- def type(&block)
565
- Algebrick.type &block
566
- end
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
- def field_readers(*names)
569
- @new_type.add_field_method_readers *names
570
- self
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
- alias_method :readers, :field_readers
609
+ class OuterShellImpl
610
+ include Shortcuts
574
611
 
575
- def all_field_readers
576
- @new_type.add_all_field_method_readers
577
- self
612
+ def run(&block)
613
+ instance_eval &block
614
+ end
578
615
  end
579
616
 
580
- alias_method :all_readers, :all_field_readers
617
+ OuterShell = OuterShellImpl.new
581
618
  end
582
619
 
583
620
  def self.type(&block)
584
621
  if block.nil?
585
- Atom.new nil
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 += ::Array.new(algebraic_type.fields.size) { Algebrick.any } if field_matchers.empty?
912
- @field_matchers = field_matchers
913
- raise ArgumentError unless algebraic_type.fields.size == field_matchers.size
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.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-17 00:00:00.000000000 Z
11
+ date: 2013-09-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest