Skip to content

Instantly share code, notes, and snippets.

@shintakezou
Created January 13, 2019 21:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shintakezou/e059abce3817ae86205178ec9616b773 to your computer and use it in GitHub Desktop.
Save shintakezou/e059abce3817ae86205178ec9616b773 to your computer and use it in GitHub Desktop.
tests of "dynamic overloading" (or alike) in several languages
-- interpreter of + and .
data StackEl = Onum Integer | Ostr String
instance Show StackEl where
show (Onum a) = show a
show (Ostr s) = "\"" ++ s ++ "\""
plus (Onum a) (Onum b) = Onum $ a+b
plus (Onum a) (Ostr b) = Ostr $ (show a) ++ b
plus (Ostr a) (Onum b) = Ostr $ a ++ (show b)
plus (Ostr a) (Ostr b) = Ostr $ a ++ b
inter :: String -> [StackEl] -> IO ()
inter [] _ = do
return ()
inter ('+':cs) (o2:o1:ops) = do
inter cs $ [plus o1 o2] ++ ops
inter ('.':cs) (r:ops) = do
putStrLn $ show r
inter cs ops
main = do
let stack = [Onum 3, Onum 2, Onum 1,
Ostr "bc", Ostr "a",
Onum 12, Ostr "13",
Ostr "x", Onum 5,
Onum 11, Onum 10]
inter "++.+.+.+.+." stack
{--
main = do
putStrLn $ show $ plus (Onum 10) (Ostr "x")
putStrLn $ show $ plus (Ostr "y") (Onum 11)
putStrLn $ show $ plus (Onum 10) (Onum 11)
putStrLn $ show $ plus (Ostr "a") (Ostr "bc")
--}
-module(dynerlang).
% likely dyn-erlang is a misnomer: here we use pattern
% matching capabilities to run the intended plus fun.
-export([run/0]).
run() ->
inter("++.+.+.+.+.",
stack:new([onumber:new(3),
onumber:new(2),
onumber:new(1),
ostring:new("bc"),
ostring:new("a"),
onumber:new(12),
ostring:new("13"),
ostring:new("x"),
onumber:new(5),
onumber:new(11),
onumber:new(10)])).
inter([], _) ->
ok;
inter([$+|Rest], S) ->
{X2, S1} = stack:pop(S),
{X1, S2} = stack:pop(S1),
S3 = stack:push(S2, plus(X1, X2)),
inter(Rest, S3);
inter([$.|Rest], S) ->
{X, S1} = stack:pop(S),
case emit(X) of
error -> error;
_ -> inter(Rest, S1)
end.
plus({string, A}, {string, B}) -> ostring:new(A ++ B);
plus({string, A}, {number, B}) -> ostring:new(A ++ integer_to_list(B));
plus({number, A}, {number, B}) -> onumber:new(A + B);
plus({number, A}, {string, B}) -> ostring:new(integer_to_list(A) ++ B);
plus(_, _) -> error.
% these should call ostring:str and onumber:str...
emit({string, A}) -> io:format("\"~s\"~n", [A]);
emit({number, A}) -> io:format("~.10B~n", [A]);
emit(_) -> error.
% using guards instead of "annotated" objects on stack
-module(dynerlangguard).
% likely dyn-erlang* is a misnomer: here we use pattern
% matching capabilities to run the intended plus fun.
-export([run/0]).
% for testing purposes
%-export([plus/2, inter/2, emit/1]).
run() ->
inter("++.+.+.+.+.",
stack:new([3, 2, 1,
"bc", "a",
12, "13",
"x", 5,
11, 10])).
inter([], _) ->
ok;
inter([$+|Rest], S) ->
{X2, S1} = stack:pop(S),
{X1, S2} = stack:pop(S1),
S3 = stack:push(S2, plus(X1, X2)),
inter(Rest, S3);
inter([$.|Rest], S) ->
{X, S1} = stack:pop(S),
case emit(X) of
error -> error;
_ -> inter(Rest, S1)
end.
plus(A, B) when is_list(A) and is_list(B) -> A ++ B;
plus(A, B) when is_list(A) and is_number(B) -> A ++ integer_to_list(B);
plus(A, B) when is_number(A) and is_number(B) -> A + B;
plus(A, B) when is_number(A) and is_list(B) -> integer_to_list(A) ++ B;
plus(_, _) -> error.
% these should call ostring:str and onumber:str...
emit(A) when is_list(A) -> io:format("\"~s\"~n", [A]);
emit(A) when is_number(A) -> io:format("~.10B~n", [A]);
emit(_) -> error.
# Perl6
use v6.c;
multi plus(Numeric $a, Numeric $b --> Numeric) { $a + $b }
multi plus(Str $a, Numeric $b --> Str) { $a ~ Str($b) }
multi plus(Numeric $a, Str $b --> Str) { Str($a) ~ $b }
multi plus(Str $a, Str $b --> Str) { $a ~ $b }
class ONum {
has Numeric $.value;
method new(Numeric $n) {
self.bless(value => $n)
}
#multi method Str(--> Str) { self.gist }
method gist(--> Str) { Str($!value) }
}
class OStr {
has Str $.value;
method new(Str $s) {
self.bless(value => $s)
}
#multi method Str(--> Str) { $!value }
method gist(--> Str) { "\"" ~ $!value.subst(/\"/, '\"') ~ "\"" }
}
multi wplus(ONum $a, ONum $b --> ONum) { ONum.new($a.value + $b.value) }
multi wplus(OStr $a, ONum $b --> OStr) { OStr.new($a.value ~ Str($b.value)) }
multi wplus(ONum $a, OStr $b --> OStr) { OStr.new(Str($a.value) ~ $b.value) }
multi wplus(OStr $a, OStr $b --> OStr) { OStr.new($a.value ~ $b.value) }
my @wstack = [];
@wstack.push: ONum.new(10);
@wstack.push: ONum.new(11);
@wstack.push: ONum.new(5);
@wstack.push: OStr.new("x");
@wstack.push: OStr.new("13");
@wstack.push: ONum.new(12);
@wstack.push: OStr.new("a");
@wstack.push: OStr.new("bc");
@wstack.push: ONum.new(1);
@wstack.push: ONum.new(2);
@wstack.push: ONum.new(3);
my @stack = map *.value, @wstack;
# no special representation for strings
for "++.+.+.+.+.".comb {
when "+" {
my $o2 = @stack.pop;
my $o1 = @stack.pop;
@stack.push: plus($o1, $o2);
# wrapped
$o2 = @wstack.pop;
$o1 = @wstack.pop;
@wstack.push: wplus($o1, $o2);
}
when "." {
say @stack.pop;
# wrapped
say @wstack.pop
}
}
from typing import *
class Number:
def __init__(self, n:int):
self.n = int(n)
def value(self):
return self.n
def __str__(self):
return str(self.n)
class String:
def __init__(self, s:str):
self.s = str(s)
def value(self):
return self.s
def __str__(self):
return '"' + str(self.s) + '"'
def op_sum(a, b):
if type(a) == Number and type(b) == Number:
return Number(int(a.value()) + int(b.value()))
elif type(a) == Number and type(b) == String:
return String(str(a.value()) + b.value())
elif type(a) == String and type(b) == Number:
return String(a.value() + str(b.value()))
elif type(a) == String and type(b) == String:
return String(str(a.value()) + str(b.value()))
else:
raise Exception("...")
def typed_sum(a:Number, b:Number) -> Number:
#return Number(a.value() + b.value())
return Number(-1)
#def typed_sum(a:String, b:String) -> String:
# return String(a.value() + b.value)
stack = [Number(10), Number(11),
Number(5), String("x"),
String("13"), Number(12),
String("a"), String("bc"),
Number(1), Number(2), Number(3),
Number(5), Number(6),
String("typed"), String("sum")]
for e in "p.p.++.+.+.+.+.":
if e == "+" or e == "p":
o2 = stack.pop()
o1 = stack.pop()
if e == "+":
stack.append(op_sum(o1, o2))
else:
stack.append(typed_sum(o1, o2))
elif e == ".":
r = stack.pop()
print(r)
def stronghold(t: int) -> str:
return str(t) + " old"
print(stronghold("hello"))
p = 10 # type: int
print(p)
class ONumber
attr_reader :value
def initialize(n)
@value = n
end
def to_s
@value.to_s
end
end
class OString
attr_reader :value
def initialize(s)
@value = s
end
def to_s
"\"" + @value + "\""
end
end
def op_sum(a, b)
if a.is_a?(ONumber) and b.is_a?(ONumber)
ONumber.new(a.value + b.value)
elsif a.is_a?(ONumber) and b.is_a?(OString)
OString.new(a.to_s + b.value)
elsif a.is_a?(OString) and b.is_a?(ONumber)
OString.new(a.value + b.to_s)
elsif a.is_a?(OString) and b.is_a?(OString)
OString.new(a.value + b.value)
else
raise RuntimeError
end
end
stack = [ONumber.new(10), ONumber.new(11),
ONumber.new(5), OString.new("x"),
OString.new("13"), ONumber.new(12),
OString.new("a"), OString.new("bc"),
ONumber.new(1), ONumber.new(2), ONumber.new(3),
ONumber.new(5), ONumber.new(6),
OString.new("typed"), OString.new("sum")]
"+.+.++.+.+.+.+.".split(//).each do |c|
case c
when "+"
o2 = stack.pop
o1 = stack.pop
stack << op_sum(o1, o2)
when "."
r = stack.pop
puts r
end
end
-module(onumber).
-export([new/1]).
% I don't define a new type at all, because after all
% I don't need it for real...
%-spec new(number()) -> {atom(), number()}.
% and let's the when do its job...
new(N) when is_integer(N) or is_float(N) ->
{number, N}.
-module(ostring).
-export([new/1]).
%-spec new(string()) -> {atom(), string()}.
% let's the when do its job...
% not all lists are printable string, but for the example sake, we
% disregard this detail
new(S) when is_list(S) ->
{string, S}.
-module(stack).
-export([new/1, new/0, pop/1, push/2]).
new() ->
{empty, []}.
new([H|T]) ->
{stack, H, T};
new([]) ->
new().
pop({stack, R, []}) ->
{R, {empty, []}};
pop({stack, R, [R1|T]}) ->
{R, {stack, R1, T}};
pop({empty, _}) -> error.
push({empty, []}, V) ->
{stack, V, []};
push({stack, H, L}, V) ->
{stack, V, [H|L]}.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment