Context aware clojures
Moved from dynamic scoping to static scoping.
This commit is contained in:
parent
8ac9fc5929
commit
6bc2a1cd38
38
examples/church.mq
Normal file
38
examples/church.mq
Normal file
@ -0,0 +1,38 @@
|
||||
-- PAIR definition
|
||||
var pair = [x y | [z | z x y]];
|
||||
var car = [p | p [x y | x]];
|
||||
var cdr = [p | p [x y | y]];
|
||||
|
||||
var x = pair 100 200;
|
||||
say (car x);
|
||||
say (cdr x);
|
||||
|
||||
-- This two values should be builtin, but currently is not
|
||||
var true = (1 == 1);
|
||||
var false = (1 != 1);
|
||||
|
||||
-- LIST definition
|
||||
var null = pair true true;
|
||||
var is_empty = car;
|
||||
var head = [list | car (cdr list)];
|
||||
var tail = [list | cdr (cdr list)];
|
||||
var cons = [head tail | pair false (pair head tail)];
|
||||
|
||||
var for_each = [list iterator |
|
||||
if (is_empty list) [| nil ] [|
|
||||
iterator (head list);
|
||||
for_each (tail list) iterator ]];
|
||||
|
||||
var map = [list iterator |
|
||||
if (is_empty list) [| null ] [|
|
||||
cons (iterator (head list)) (map (tail list) iterator) ]];
|
||||
|
||||
var foldr = [list init folder |
|
||||
if (is_empty list)
|
||||
[| init ]
|
||||
[| foldr (tail list) (folder (head list) init) folder ]];
|
||||
|
||||
var range = [start stop | if (start >= stop) [|cons start null] [|cons start (range (start+1) stop)]];
|
||||
|
||||
var xs = range 1 5;
|
||||
say (foldr xs 1 [x y|x*y]);
|
@ -151,6 +151,8 @@ Result<Value> Interpreter::eval(Ast &&ast)
|
||||
assert(param.type == Ast::Type::Literal && param.token.type == Token::Type::Symbol, "Not a name in parameter section of Ast::lambda");
|
||||
lambda.parameters.push_back(std::string(std::move(param).token.source));
|
||||
}
|
||||
|
||||
lambda.context = env;
|
||||
lambda.body = std::move(ast.arguments.back());
|
||||
return Value::lambda(std::move(lambda));
|
||||
}
|
||||
|
@ -427,8 +427,9 @@ struct Number
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, Number const& num);
|
||||
|
||||
struct Value;
|
||||
struct Env;
|
||||
struct Interpreter;
|
||||
struct Value;
|
||||
|
||||
using Function = std::function<Result<Value>(Interpreter &i, std::vector<Value>)>;
|
||||
|
||||
@ -437,6 +438,7 @@ struct Lambda
|
||||
Location location;
|
||||
std::vector<std::string> parameters;
|
||||
Ast body;
|
||||
std::shared_ptr<Env> context;
|
||||
|
||||
Result<Value> operator()(Interpreter &i, std::vector<Value> params);
|
||||
};
|
||||
|
@ -129,8 +129,9 @@ std::string_view type_name(Value::Type t)
|
||||
|
||||
Result<Value> Lambda::operator()(Interpreter &i, std::vector<Value> arguments)
|
||||
{
|
||||
// TODO Add some kind of scope guard
|
||||
auto old_scope = std::exchange(i.env, context);
|
||||
i.enter_scope();
|
||||
|
||||
assert(parameters.size() == arguments.size(), "wrong number of arguments");
|
||||
|
||||
for (usize j = 0; j < parameters.size(); ++j) {
|
||||
@ -140,6 +141,6 @@ Result<Value> Lambda::operator()(Interpreter &i, std::vector<Value> arguments)
|
||||
Ast body_copy = body;
|
||||
auto result = i.eval(std::move(body_copy));
|
||||
|
||||
i.leave_scope();
|
||||
i.env = old_scope;
|
||||
return result;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user