module lqtools; import std.array; import std.string; import environment; import formals; import lqtypes; import stringtools; LqPair as_pair(LqType expr) { assert(expr.type_indicator == "pair"); return cast(LqPair)expr; } LqList as_list(LqType expr) { assert(expr.is_list()); return cast(LqList)expr; } /* convert a list of Lq objects to a list of strings. */ string[] list_of_symbols(LqType[] items) { string[] list = []; foreach(LqType q; items) { //assert(q.type_indicator() == "symbol"); list ~= q.lq_repr(); } return list; } /* convert an LqPair containing LqSymbols to a list of strings. */ string[] list_of_symbols(LqType list) { assert(list.is_list()); LqType[] items = (cast(LqList)list).to_list(); return list_of_symbols(items); } /* Wrap a series of expressions in a (begin ..) clause. If there's only one expression in the list, return that expression instead. */ LqType wrap_in_begin(LqType[] exprs) { if (exprs.length == 1) return exprs[0]; LqType[] elems = [new LqSymbol("begin")]; elems ~= exprs; return LqPair.from_list(elems); } void check_arg(LqType x, int argno, string name, string fname) { if (x.type_indicator() != name) { throw new Exception(format("%s: argument %d must be %s, got %s instead", fname, argno, name, x.type_indicator())); } } /* variant that accepts multiple types */ void check_arg(LqType x, int argno, string[] types, string fname) { if (!string_in_list(x.type_indicator(), types)) { string typelist = "(" ~ std.string.join(types, ", ") ~ ")"; throw new Exception(format("%s: argument %d must be one of %s, got %s instead", fname, argno, typelist, x.type_indicator())); } } /* Check the length of argument list against a minimum and a maximum. If the maximum is -1, there is no upper limit. */ void check_arglength(LqType[] args, int minlength, int maxlength, string fname) { if (args.length < minlength) throw new Exception(format("%s: not enough arguments", fname)); if (maxlength > -1 && args.length > maxlength) throw new Exception(format("%s: too many arguments", fname)); } Environment env_from_context(LqType x) { if (x.type_indicator() == "userdef-function") { auto lambda = cast(LqUserDefinedFunction)(x); return lambda.env(); } else if (x.type_indicator() == "environment") { auto lenv = cast(LqEnvironment)(x); return lenv.env; } throw new Exception("could not extract environment"); } LqType get_keyword(kwdict kwargs, string name) { LqType result; try { result = kwargs[name]; } catch (ArrayBoundsError e) { return LQ_FALSE(); } return result; }