Universal Lambda Machine: Difference between revisions

m
Move Haskell before JavaScript
m (Move Haskell before JavaScript)
 
(One intermediate revision by the same user not shown)
Line 180:
}
</syntaxhighlight>
 
=={{header|Haskell}}==
A bit-wise only ULM:
<syntaxhighlight lang="haskell">
import System.IO
import Data.List
import Text.Parsec
import Control.Applicative hiding ((<|>), many)
 
data WHNF = SYM !Char | FUN (WHNF -> WHNF)
 
fun :: WHNF -> WHNF -> WHNF
fun (SYM c) _ = error $ "Cannot apply symbol " ++ [c]
fun (FUN f) w = f w
 
expr :: Monad m => ParsecT String u m ([WHNF] -> WHNF)
expr = char '0' *> (buildLambda <$ char '0' <*> expr
<|> buildApply <$ char '1' <*> expr <*> expr)
<|> buildVar <$> pred.length <$> many (char '1') <* char '0' where
buildLambda e env = FUN $ \arg -> e (arg:env)
buildApply e1 e2 env = e1 env `fun` e2 env
buildVar n env = env !! n
 
buildIO prog = whnfToString . (prog [] `fun` ) . stringToWhnf where
stringToWhnf :: [Char] -> WHNF
stringToWhnf = foldr (whnfCons . bitToWhnf . fromEnum) whnfFalse where
bitToWhnf :: Integral a => a -> WHNF
bitToWhnf n = if even n then whnfTrue else whnfFalse
 
whnfCons :: WHNF -> WHNF -> WHNF
whnfCons fw gw = FUN $ \hw -> hw `fun` fw `fun` gw
 
whnfToString = map whnfToChar . whnfToList where
cons2sym :: WHNF
cons2sym = whnfConst . whnfConst $ SYM ':'
 
whnfToList :: WHNF -> [WHNF]
whnfToList l = case (l `fun` cons2sym) of
SYM ':' -> l `fun` whnfTrue : whnfToList (l `fun` whnfFalse)
FUN _ -> []
 
whnfToChar :: WHNF -> Char
whnfToChar iw = c where (SYM c) = iw `fun` SYM '0' `fun` SYM '1'
 
whnfConst :: WHNF -> WHNF
whnfConst = FUN . const
 
whnfTrue :: WHNF
whnfTrue = FUN whnfConst
 
whnfFalse :: WHNF
whnfFalse = whnfConst $ FUN id
 
main = do
hSetBuffering stdout NoBuffering
interact $ either (error . show) id . parse (buildIO <$> expr <*> getInput) ""
</syntaxhighlight>
Feel free to replace this by a solution for both bit-wise and byte-wise.
 
=={{header|JavaScript}}==
Line 254 ⟶ 312:
});</syntaxhighlight>
 
=={{header|HaskellPerl}}==
A bit-wise only ULM:
<syntaxhighlight lang="haskell">
import System.IO
import Data.List
import Text.Parsec
import Control.Applicative hiding ((<|>), many)
 
<syntaxhighlight lang="perl">#!/usr/bin/perl
data WHNF = SYM !Char | FUN (WHNF -> WHNF)
sub bit2lam {
 
my $bit = pop;
fun :: WHNF -> WHNF -> WHNF
sub { my $x0 = pop; sub { my $x1 = pop; $bit ? $x1 : $x0 } }
fun (SYM c) _ = error $ "Cannot apply symbol " ++ [c]
}
fun (FUN f) w = f w
sub byte2lam {
 
my ($bits,$n) = @_;
expr :: Monad m => ParsecT String u m ([WHNF] -> WHNF)
$n == 0 ? sub { sub { pop } } # nil
expr = char '0' *> (buildLambda <$ char '0' <*> expr
: sub { pop->(bit2lam(vec$bits,$n-1,1))->(byte2lam($bits,$n-1)) }
<|> buildApply <$ char '1' <*> expr <*> expr)
}
<|> buildVar <$> pred.length <$> many (char '1') <* char '0' where
sub input {
buildLambda e env = FUN $ \arg -> e (arg:env)
my $n = pop; # input from n'th character onward
buildApply e1 e2 env = e1 env `fun` e2 env
if buildVar ($n env >= env@B) !! n{
my $c = getc;
 
push @B, !defined($c) ? sub {sub { pop } } # nil
buildIO prog = whnfToString . (prog [] `fun` ) . stringToWhnf where
: sub { pop->($bytemode ? byte2lam($c,8) : bit2lam($c))->(input($n+1)) }
stringToWhnf :: [Char] -> WHNF
}
stringToWhnf = foldr (whnfCons . bitToWhnf . fromEnum) whnfFalse where
$B[$n];
bitToWhnf :: Integral a => a -> WHNF
}
bitToWhnf n = if even n then whnfTrue else whnfFalse
sub lam2bit {
 
pop->(sub{0})->(sub{1})->() # force suspension
whnfCons :: WHNF -> WHNF -> WHNF
}
whnfCons fw gw = FUN $ \hw -> hw `fun` fw `fun` gw
sub lam2byte {
 
my ($lambits, $x) = @_; # 2nd argument is partial byte
whnfToString = map whnfToChar . whnfToList where
$lambits->(sub { my $lambit = pop; sub { my $tail = pop; sub { lam2byte($tail, 2*$x + lam2bit($lambit)) }
cons2sym :: WHNF
}})->(chr $x) # end of byte
cons2sym = whnfConst . whnfConst $ SYM ':'
}
 
sub output {
whnfToList :: WHNF -> [WHNF]
pop->(sub { my $c = pop; print($bytemode ? lam2byte($c,0) : lam2bit($c));
whnfToList l = case (l `fun` cons2sym) of
sub { my $tail = SYMpop; ':'sub { output($tail) } } })->(0) l `fun` whnfTrue :# whnfToListend (lof `fun` whnfFalse)output
}
FUN _ -> []
sub getbit {
 
$n ||= ($c = getc, $bytemode ? 8 : 1);
whnfToChar :: WHNF -> Char
vec $c,--$n,1;
whnfToChar iw = c where (SYM c) = iw `fun` SYM '0' `fun` SYM '1'
}
 
sub program {
whnfConst :: WHNF -> WHNF
if (getbit()) { # variable
whnfConst = FUN . const
my $i;
 
whnfTrue$i++ ::while WHNFgetbit();
sub { $_[$i] }
whnfTrue = FUN whnfConst
} elsif (getbit()) { # application
 
my $p=program();
whnfFalse :: WHNF
my $q=program();
whnfFalse = whnfConst $ FUN id
sub { my @env = @_; $p->(@env)->(sub { $q->(@env)->(pop) }) } # suspend argument
 
} else {
main = do
my $p = program();
hSetBuffering stdout NoBuffering
sub { my @env = @_; sub { $p->(pop,@env) } } # extend environment with one more argument
interact $ either (error . show) id . parse (buildIO <$> expr <*> getInput) ""
}
</syntaxhighlight>
}
Feel free to replace this by a solution for both bit-wise and byte-wise.
$bytemode = !pop; # any argument sets bitmode instead
$| = 1; # non zero value sets autoflush
$prog = program()->();
output $prog->(input(0)) # run program with empty env on input</syntaxhighlight>
 
=={{header|Phix}}==
Line 620 ⟶ 676:
Hello, world!
</pre>
 
=={{header|Perl}}==
 
<syntaxhighlight lang="perl">#!/usr/bin/perl
sub bit2lam {
my $bit = pop;
sub { my $x0 = pop; sub { my $x1 = pop; $bit ? $x1 : $x0 } }
}
sub byte2lam {
my ($bits,$n) = @_;
$n == 0 ? sub { sub { pop } } # nil
: sub { pop->(bit2lam(vec$bits,$n-1,1))->(byte2lam($bits,$n-1)) }
}
sub input {
my $n = pop; # input from n'th character onward
if ($n >= @B) {
my $c = getc;
push @B, !defined($c) ? sub {sub { pop } } # nil
: sub { pop->($bytemode ? byte2lam($c,8) : bit2lam($c))->(input($n+1)) }
}
$B[$n];
}
sub lam2bit {
pop->(sub{0})->(sub{1})->() # force suspension
}
sub lam2byte {
my ($lambits, $x) = @_; # 2nd argument is partial byte
$lambits->(sub { my $lambit = pop; sub { my $tail = pop; sub { lam2byte($tail, 2*$x + lam2bit($lambit)) }
}})->(chr $x) # end of byte
}
sub output {
pop->(sub { my $c = pop; print($bytemode ? lam2byte($c,0) : lam2bit($c));
sub { my $tail = pop; sub { output($tail) } } })->(0) # end of output
}
sub getbit {
$n ||= ($c = getc, $bytemode ? 8 : 1);
vec $c,--$n,1;
}
sub program {
if (getbit()) { # variable
my $i;
$i++ while getbit();
sub { $_[$i] }
} elsif (getbit()) { # application
my $p=program();
my $q=program();
sub { my @env = @_; $p->(@env)->(sub { $q->(@env)->(pop) }) } # suspend argument
} else {
my $p = program();
sub { my @env = @_; sub { $p->(pop,@env) } } # extend environment with one more argument
}
}
$bytemode = !pop; # any argument sets bitmode instead
$| = 1; # non zero value sets autoflush
$prog = program()->();
output $prog->(input(0)) # run program with empty env on input</syntaxhighlight>
 
=={{header|Python}}==
7,813

edits