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");
|
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.parameters.push_back(std::string(std::move(param).token.source));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lambda.context = env;
|
||||||
lambda.body = std::move(ast.arguments.back());
|
lambda.body = std::move(ast.arguments.back());
|
||||||
return Value::lambda(std::move(lambda));
|
return Value::lambda(std::move(lambda));
|
||||||
}
|
}
|
||||||
|
@ -427,8 +427,9 @@ struct Number
|
|||||||
|
|
||||||
std::ostream& operator<<(std::ostream& os, Number const& num);
|
std::ostream& operator<<(std::ostream& os, Number const& num);
|
||||||
|
|
||||||
struct Value;
|
struct Env;
|
||||||
struct Interpreter;
|
struct Interpreter;
|
||||||
|
struct Value;
|
||||||
|
|
||||||
using Function = std::function<Result<Value>(Interpreter &i, std::vector<Value>)>;
|
using Function = std::function<Result<Value>(Interpreter &i, std::vector<Value>)>;
|
||||||
|
|
||||||
@ -437,6 +438,7 @@ struct Lambda
|
|||||||
Location location;
|
Location location;
|
||||||
std::vector<std::string> parameters;
|
std::vector<std::string> parameters;
|
||||||
Ast body;
|
Ast body;
|
||||||
|
std::shared_ptr<Env> context;
|
||||||
|
|
||||||
Result<Value> operator()(Interpreter &i, std::vector<Value> params);
|
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)
|
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();
|
i.enter_scope();
|
||||||
|
|
||||||
assert(parameters.size() == arguments.size(), "wrong number of arguments");
|
assert(parameters.size() == arguments.size(), "wrong number of arguments");
|
||||||
|
|
||||||
for (usize j = 0; j < parameters.size(); ++j) {
|
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;
|
Ast body_copy = body;
|
||||||
auto result = i.eval(std::move(body_copy));
|
auto result = i.eval(std::move(body_copy));
|
||||||
|
|
||||||
i.leave_scope();
|
i.env = old_scope;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user