diff options
| author | Drahflow <drahflow@gmx.de> | 2012-12-14 12:15:40 +0100 |
|---|---|---|
| committer | Drahflow <drahflow@gmx.de> | 2012-12-14 12:15:40 +0100 |
| commit | f20e50a4e3ac3aeeac84358a68c253358f213667 (patch) | |
| tree | efed2b2c51fec59a0fae8f59845afa1b520e0204 /interpreter | |
| parent | 26c5b2be3918e7e27f9ae0616f3a3a629190b19c (diff) | |
Compiler Tokenizer working
Diffstat (limited to 'interpreter')
| -rw-r--r-- | interpreter/Elymas.pm | 17 | ||||
| -rw-r--r-- | interpreter/ElymasGlobal.pm | 63 | ||||
| -rw-r--r-- | interpreter/ElymasSys.pm | 15 |
3 files changed, 88 insertions, 7 deletions
diff --git a/interpreter/Elymas.pm b/interpreter/Elymas.pm index 22199b7..b58bffd 100644 --- a/interpreter/Elymas.pm +++ b/interpreter/Elymas.pm @@ -7,7 +7,7 @@ require Exporter; our @ISA = qw(Exporter); our @EXPORT = qw( popInt popString popArray enstruct arrayAccess $quoted @globalCallStack - interpretCode execute executeString executeFile resolve canCastTo + interpretCode execute executeString executeFile resolve canCastTo typeEqual ); use Data::Dumper; @@ -114,8 +114,21 @@ sub typeEqual { return 0 unless @{$a->[2]} == grep { typeEqual($a->[2]->[$_], $b->[2]->[$_]) } 0 .. $#{$a->[2]}; return 0 unless @{$a->[3]} == grep { typeEqual($a->[3]->[$_], $b->[3]->[$_]) } 0 .. $#{$a->[3]}; return 1; + } elsif($a->[0] eq 'struct') { + return 0 unless $b->[0] eq 'struct'; + + my @aKeys = sort keys %{$a->[1]}; + my @bKeys = sort keys %{$b->[1]}; + + return 0 unless @aKeys == @bKeys; + foreach my $i (0 .. $#aKeys) { + return 0 unless $aKeys[$i] eq $bKeys[$i]; + return 0 unless typeEqual($a->[1]->{$aKeys[$i]}->[0], $b->[1]->{$bKeys[$i]}->[0]); + } + + return 1; } else { - die "not yet implemented"; + die "not yet implemented" . Dumper($a); } } diff --git a/interpreter/ElymasGlobal.pm b/interpreter/ElymasGlobal.pm index f6b45c5..81da6f0 100644 --- a/interpreter/ElymasGlobal.pm +++ b/interpreter/ElymasGlobal.pm @@ -99,9 +99,8 @@ our $global = { last if($t->[1] eq 'tok' and $t->[0] eq '['); if($type) { - # FIXME: This is a hack until function types work if(ref($type) ne 'ARRAY' or $type->[0] ne 'func') { - die "mismatched types in array: " . Dumper($type) if($type ne $t->[1]); + die "mismatched types in array: " . Dumper($type) unless typeEqual($type, $t->[1]); } } else { $type = $t->[1]; @@ -244,6 +243,56 @@ our $global = { push @$data, ($p->[1] eq 'int' and $p->[0] == 0? $b: $a); }, ['func', '?'], 'active'], + 'include' => [sub { + my ($data, $scope) = @_; + + my $s = popString($data); + + executeFile($s, $data, $scope); + }, ['func', 'include'], 'active'], + 'regex' => [sub { + my ($data, $scope) = @_; + + my $rx = popString($data); + my $s = popString($data); + + my @result = $s =~ qr($rx)s; + if(not @result) { + push @$data, [0, 'int']; + } elsif(($result[0] & ~ $result[0]) eq "0") { + push @$data, [1, 'int']; + } else { + foreach my $m (reverse @result) { + push @$data, [$m, 'string']; + } + push @$data, [1, 'int']; + } + }, ['func', 'regex'], 'active'], + 'cat' => [sub { + my ($data, $scope) = @_; + + my $b = pop @$data or die "Stack underflow"; + my $a = pop @$data or die "Stack underflow"; + + if(ref($a->[1]) eq 'ARRAY' and $a->[1]->[0] eq 'array') { + if(ref($b->[1]) eq 'ARRAY' and $b->[1]->[0] eq 'array') { + die "Array types don't match in cat: " . Dumper($a->[1]->[3], $b->[1]->[3]) + unless typeEqual($a->[1]->[3], $b->[1]->[3]); + my @res = (@$a, @$b); + push @$data, [\@res, ['array', 'from cat', [['range', 0, $#res]], [$a->[1]->[3]]]]; + } else { + die "Mismatch between string and array in cat"; + } + } elsif($a->[1] eq 'string') { + if($b->[1] eq 'string') { + push @$data, [$a->[0] . $b->[0], 'string']; + } else { + die "Mismatch between string and array in cat"; + } + } else { + die "Neither string nor array: " . Dumper($a); + } + }, ['func', 'cat'], 'active'], # not really part of the spec, this is just for debugging 'dump' => [sub { @@ -274,9 +323,13 @@ our $global = { my ($data, $scope) = @_; my $a = pop @$data or die "Stack underflow"; - die "Not array: " . Dumper($a) unless ref($a->[1]) eq 'ARRAY' and $a->[1]->[0] eq 'array'; - - push @$data, [scalar @{$a->[0]}, 'int']; + if(ref($a->[1]) eq 'ARRAY' and $a->[1]->[0] eq 'array') { + push @$data, [scalar @{$a->[0]}, 'int']; + } elsif(ref($a->[1]) eq 'ARRAY' and $a->[1]->[0] eq 'string') { + push @$data, [length $a->[0], 'int']; + } else { + die "Neither string nor array: " . Dumper($a); + } }, ['func', 'len'], 'active'], '=[]' => [sub { my ($data, $scope) = @_; diff --git a/interpreter/ElymasSys.pm b/interpreter/ElymasSys.pm index 09e3f71..7e6d1b9 100644 --- a/interpreter/ElymasSys.pm +++ b/interpreter/ElymasSys.pm @@ -18,6 +18,7 @@ our $sys = { 'in' => [enstruct(createFile(0, &POSIX::O_RDONLY)), 'passive'], 'out' => [enstruct(createFile(1, &POSIX::O_WRONLY)), 'passive'], 'err' => [enstruct(createFile(2, &POSIX::O_WRONLY)), 'passive'], + 'argv' => [[map { [$_, 'string'] } @ARGV[1 .. $#ARGV]], ['array', 'sys .argv', ['range', 0, $#ARGV - 1], ['string']], 'passive'], }; sub createFile { @@ -91,6 +92,20 @@ sub createFile { push @$data, [$buf, ['array', '[]', [['range', 0, $#{$buf}]], ['int']]]; }, ['func', 'sys .file .read'], 'active'], + 'readstr' => [sub { + # FIXME: give the file an encoding and respect it here, buffering half-characters if needed + my ($data) = @_; + + die "file not open" if $$scope->{' fd'}->[0] == -1; + + my $count = popInt($data); + + my $buf; + my $ret = POSIX::read($$scope->{' fd'}->[0], $buf, $count); + die "read failed: $!" unless defined $ret; + + push @$data, [$buf, 'string']; + }, ['func', 'sys .file .writestr'], 'active'], 'write' => [sub { my ($data) = @_; |
