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.
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