1
1
mirror of https://github.com/kanaka/mal.git synced 2024-11-09 18:06:35 +03:00
mal/impls/pike/Types.pmod
Joel Martin 8a19f60386 Move implementations into impls/ dir
- Reorder README to have implementation list after "learning tool"
  bullet.

- This also moves tests/ and libs/ into impls. It would be preferrable
  to have these directories at the top level.  However, this causes
  difficulties with the wasm implementations which need pre-open
  directories and have trouble with paths starting with "../../". So
  in lieu of that, symlink those directories to the top-level.

- Move the run_argv_test.sh script into the tests directory for
  general hygiene.
2020-02-10 23:50:16 -06:00

461 lines
6.9 KiB
Plaintext

enum MalType {
MALTYPE_UNDEFINED,
MALTYPE_NIL,
MALTYPE_TRUE,
MALTYPE_FALSE,
MALTYPE_NUMBER,
MALTYPE_SYMBOL,
MALTYPE_STRING,
MALTYPE_KEYWORD,
MALTYPE_LIST,
MALTYPE_VECTOR,
MALTYPE_MAP,
MALTYPE_FN,
MALTYPE_BUILTINFN,
MALTYPE_ATOM,
};
class Val
{
constant mal_type = MALTYPE_UNDEFINED;
Val meta;
string to_string(bool print_readably);
Val clone();
bool `==(mixed other)
{
return objectp(other) && other.mal_type == mal_type;
}
}
class Nil
{
inherit Val;
constant mal_type = MALTYPE_NIL;
string to_string(bool print_readably)
{
return "nil";
}
int count()
{
return 0;
}
Val first()
{
return MAL_NIL;
}
Val rest()
{
return List(({ }));
}
Val clone()
{
return this_object();
}
Val seq()
{
return MAL_NIL;
}
}
Nil MAL_NIL = Nil();
class True
{
inherit Val;
constant mal_type = MALTYPE_TRUE;
string to_string(bool print_readably)
{
return "true";
}
Val clone()
{
return this_object();
}
}
True MAL_TRUE = True();
class False
{
inherit Val;
constant mal_type = MALTYPE_FALSE;
string to_string(bool print_readably)
{
return "false";
}
Val clone()
{
return this_object();
}
}
False MAL_FALSE = False();
Val to_bool(bool b)
{
if(b) return MAL_TRUE;
return MAL_FALSE;
}
class Number(int value)
{
constant mal_type = MALTYPE_NUMBER;
inherit Val;
string to_string(bool print_readably)
{
return (string)value;
}
bool `==(mixed other)
{
return ::`==(other) && other.value == value;
}
Val clone()
{
return this_object();
}
}
class Symbol(string value)
{
constant mal_type = MALTYPE_SYMBOL;
inherit Val;
string to_string(bool print_readably)
{
return value;
}
bool `==(mixed other)
{
return ::`==(other) && other.value == value;
}
int __hash()
{
return hash((string)mal_type) ^ hash(value);
}
Val clone()
{
return Symbol(value);
}
}
class String(string value)
{
constant mal_type = MALTYPE_STRING;
inherit Val;
string to_string(bool print_readably)
{
if(print_readably) {
string s = replace(value, "\\", "\\\\");
s = replace(s, "\"", "\\\"");
s = replace(s, "\n", "\\n");
return "\"" + s + "\"";
}
return value;
}
bool `==(mixed other)
{
return ::`==(other) && other.value == value;
}
int __hash()
{
return hash((string)mal_type) ^ hash(value);
}
Val clone()
{
return String(value);
}
Val seq()
{
if(sizeof(value) == 0) return MAL_NIL;
array(Val) parts = ({ });
for(int i = 0; i < sizeof(value); i++)
{
parts += ({ String(value[i..i]) });
}
return List(parts);
}
}
class Keyword(string value)
{
constant mal_type = MALTYPE_KEYWORD;
inherit Val;
string to_string(bool print_readably)
{
return ":" + value;
}
bool `==(mixed other)
{
return ::`==(other) && other.value == value;
}
int __hash()
{
return hash((string)mal_type) ^ hash(value);
}
Val clone()
{
return Keyword(value);
}
}
class Sequence(array(Val) data)
{
inherit Val;
constant is_sequence = true;
string to_string(bool print_readably)
{
return map(data, lambda(Val e) { return e.to_string(print_readably); }) * " ";
}
bool emptyp()
{
return sizeof(data) == 0;
}
int count()
{
return sizeof(data);
}
Val nth(int index)
{
if(index >= count()) throw("nth: index out of range");
return data[index];
}
Val first()
{
if(emptyp()) return MAL_NIL;
return data[0];
}
Val rest()
{
return List(data[1..]);
}
bool `==(mixed other)
{
if(!objectp(other)) return 0;
if(!other.is_sequence) return 0;
if(other.count() != count()) return 0;
for(int i = 0; i < count(); i++)
{
if(other.data[i] != data[i]) return 0;
}
return 1;
}
Val seq()
{
if(emptyp()) return MAL_NIL;
return List(data);
}
}
class List
{
inherit Sequence;
constant mal_type = MALTYPE_LIST;
string to_string(bool print_readably)
{
return "(" + ::to_string(print_readably) + ")";
}
Val clone()
{
return List(data);
}
Val conj(array(Val) other)
{
return List(reverse(other) + data);
}
}
class Vector
{
inherit Sequence;
constant mal_type = MALTYPE_VECTOR;
string to_string(bool print_readably)
{
return "[" + ::to_string(print_readably) + "]";
}
Val clone()
{
return Vector(data);
}
Val conj(array(Val) other)
{
return Vector(data + other);
}
}
class Map
{
inherit Val;
constant mal_type = MALTYPE_MAP;
mapping(Val:Val) data;
void create(array(Val) list)
{
array(Val) keys = Array.everynth(list, 2, 0);
array(Val) vals = Array.everynth(list, 2, 1);
data = mkmapping(keys, vals);
}
string to_string(bool print_readably)
{
array(string) strs = ({ });
foreach(data; Val k; Val v)
{
strs += ({ k.to_string(print_readably), v.to_string(print_readably) });
}
return "{" + (strs * " ") + "}";
}
int count()
{
return sizeof(data);
}
bool `==(mixed other)
{
if(!::`==(other)) return 0;
if(other.count() != count()) return 0;
foreach(data; Val k; Val v)
{
if(other.data[k] != v) return 0;
}
return 1;
}
Val assoc(array(Val) list)
{
array(Val) keys = Array.everynth(list, 2, 0);
array(Val) vals = Array.everynth(list, 2, 1);
Map result = Map(({ }));
result.data = copy_value(data);
for(int i = 0; i < sizeof(keys); i++)
{
result.data[keys[i]] = vals[i];
}
return result;
}
Val dissoc(array(Val) list)
{
Map result = Map(({ }));
result.data = copy_value(data);
foreach(list, Val key) m_delete(result.data, key);
return result;
}
Val clone()
{
Map m = Map(({ }));
m.data = data;
return m;
}
}
class Fn(Val ast, Val params, .Env.Env env, function func, void|bool macro)
{
inherit Val;
constant mal_type = MALTYPE_FN;
constant is_fn = true;
void set_macro()
{
macro = true;
}
string to_string(bool print_readably)
{
string tag = macro ? "Macro" : "Fn";
return "#<" + tag + " params=" + params.to_string(true) + ">";
}
mixed `()(mixed ... args)
{
return func(@args);
}
Val clone()
{
return Fn(ast, params, env, func);
}
Val clone_as_macro()
{
return Fn(ast, params, env, func, true);
}
}
class BuiltinFn(string name, function func)
{
inherit Val;
constant mal_type = MALTYPE_BUILTINFN;
constant is_fn = true;
string to_string(bool print_readably)
{
return "#<BuiltinFn " + name + ">";
}
mixed `()(mixed ... args)
{
return func(@args);
}
Val clone()
{
return BuiltinFn(name, func);
}
}
class Atom(Val data)
{
inherit Val;
constant mal_type = MALTYPE_ATOM;
string to_string(bool print_readably)
{
return "(atom " + data.to_string(print_readably) + ")";
}
Val clone()
{
return Atom(data);
}
}