Created
January 13, 2019 21:35
-
-
Save shintakezou/e059abce3817ae86205178ec9616b773 to your computer and use it in GitHub Desktop.
tests of "dynamic overloading" (or alike) in several languages
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- 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") | |
--} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-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. | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
% 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. | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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 | |
} | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-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}. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-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}. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-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