beginnings of a shell prototype
[scpubgit/DX.git] / lib / DX / Expander.pm
1 package DX::Expander;
2
3 use DX::Utils qw(:all);
4 use DX::Value::True;
5 use DX::Value::False;
6 use Tcl;
7 use DX::Class;
8
9 has tcl => (
10   is => 'lazy', builder => sub { Tcl->new },
11   handles => { _split_list => 'SplitList' },
12 );
13
14 sub expand_args {
15   my ($self, @args) = @_;
16   map { $self->expand_one($_) } @args;
17 }
18
19 sub expand_proposition {
20   my ($self, $prop) = @_;
21   my ($name, @args) = $self->_split_list($prop);
22   proposition($name, $self->expand_args(@args));
23 }
24
25 my @exp_t = map { [ qr/\A(\s*)${\$_->[1]}\s*\Z/, 'expand_'.$_->[0] ] } (
26   [ number => qr/([\d.]+)/ ],
27   [ string => qr/'(.*)'/s ],
28   [ bool => qr/(true|false)/ ],
29   [ symbol => qr/([a-zA-Z_][a-zA-Z0-9_]*)/ ],
30   [ dict => qr/{(.*)}/s ],
31   [ array => qr/\[(.*)\]/s ],
32 );
33
34 sub expand_one {
35   my ($self, $exp) = @_;
36   foreach my $try (@exp_t) {
37     my ($re, $meth) = @$try;
38     $exp =~ $re and return $self->$meth($2, $1);
39   }
40   die 'Uhhhh ... '.$exp;
41 }
42
43 sub expand_number { number($_[1]) }
44
45 sub expand_string {
46   my ($self, $exp, $ws) = @_;
47   return string($exp) unless $ws =~ s/.*\n//s;
48   my $wstrip = length($ws)+1;
49   $exp =~ s/^ {1,$wstrip}//mg;
50   return string($exp);
51 }
52
53 sub expand_symbol { $_[1] }
54
55 sub expand_dict {
56   my ($self, $val) = @_;
57   my @pairs = $self->_split_list($val);
58   die "Uneven dict" if @pairs % 2;
59   dict(map {
60     $pairs[2*$_] => $self->expand_one($pairs[(2*$_)+1])
61   } 0..int($#pairs/2))
62 }
63
64 sub expand_array { die;
65 }
66
67 sub expand_bool {
68   ('DX::Value::'.ucfirst($_[1]))->new
69 }
70
71 1;