Block indexing and len builtin
This commit is contained in:
parent
23b9d901ac
commit
f28cb10669
11
examples/arrays.mq
Normal file
11
examples/arrays.mq
Normal file
@ -0,0 +1,11 @@
|
||||
var numbers = [1;2;3;4;5];
|
||||
|
||||
var for = [array iteration |
|
||||
var iter = [i | if (i < (len array)) [
|
||||
iteration (numbers.i);
|
||||
iter (i+1)
|
||||
]];
|
||||
iter 0
|
||||
];
|
||||
|
||||
for numbers say;
|
@ -95,6 +95,16 @@ Interpreter::Interpreter(std::ostream& out)
|
||||
return {};
|
||||
});
|
||||
|
||||
global.force_define("len", +[](Interpreter &, std::vector<Value> args) -> Result<Value> {
|
||||
assert(args.size() == 1, "len only accepts one argument");
|
||||
assert(args.front().type == Value::Type::Block, "Only blocks can be measure");
|
||||
if (args.front().blk.body.type != Ast::Type::Sequence) {
|
||||
return Value::number(Number(1));
|
||||
} else {
|
||||
return Value::number(Number(args.front().blk.body.arguments.size()));
|
||||
}
|
||||
});
|
||||
|
||||
operators["+"] = binary_operator<std::plus<>>();
|
||||
operators["-"] = binary_operator<std::minus<>>();
|
||||
operators["*"] = binary_operator<std::multiplies<>>();
|
||||
@ -107,6 +117,13 @@ Interpreter::Interpreter(std::ostream& out)
|
||||
|
||||
operators["=="] = equality_operator<std::equal_to<>>();
|
||||
operators["!="] = equality_operator<std::not_equal_to<>>();
|
||||
|
||||
operators["."] = +[](Interpreter &i, std::vector<Value> args) -> Result<Value> {
|
||||
assert(args.size() == 2, "Operator . requires two arguments"); // TODO(assert)
|
||||
assert(args.front().type == Value::Type::Block, "Only blocks can be indexed"); // TODO(assert)
|
||||
assert(args.back().type == Value::Type::Number, "Only numbers can be used for indexing"); // TODO(assert)
|
||||
return std::move(args.front()).blk.index(i, std::move(args.back()).n.as_int());
|
||||
};
|
||||
}
|
||||
|
||||
Result<Value> Interpreter::eval(Ast &&ast)
|
||||
|
@ -7,6 +7,7 @@ constexpr std::string_view Valid_Operator_Chars =
|
||||
"+-*/:%" // arithmetic
|
||||
"|&^" // logic & bit operations
|
||||
"<>=!" // comparisons
|
||||
"." // indexing
|
||||
;
|
||||
|
||||
constexpr auto Keywords = std::array {
|
||||
@ -84,14 +85,6 @@ auto Lexer::next_token() -> Result<Token>
|
||||
return { Token::Type::Parameter_Separator, finish(), token_location };
|
||||
}
|
||||
|
||||
// Number literals like .75
|
||||
if (peek() == '.') {
|
||||
consume();
|
||||
while (consume_if(unicode::is_digit)) {}
|
||||
if (token_length != 1)
|
||||
return { Token::Type::Numeric, finish(), token_location };
|
||||
}
|
||||
|
||||
if (consume_if(unicode::is_digit)) {
|
||||
while (consume_if(unicode::is_digit)) {}
|
||||
if (peek() == '.') {
|
||||
|
@ -444,6 +444,7 @@ struct Block
|
||||
std::shared_ptr<Env> context;
|
||||
|
||||
Result<Value> operator()(Interpreter &i, std::vector<Value> params);
|
||||
Result<Value> index(Interpreter &i, unsigned position);
|
||||
};
|
||||
|
||||
template<typename T, typename ...XS>
|
||||
@ -530,8 +531,13 @@ private:
|
||||
|
||||
struct Interpreter
|
||||
{
|
||||
/// Output of IO builtins like `say`
|
||||
std::ostream &out;
|
||||
|
||||
/// Operators defined for language
|
||||
std::unordered_map<std::string, Intrinsic> operators;
|
||||
|
||||
/// Current environment (current scope)
|
||||
std::shared_ptr<Env> env;
|
||||
|
||||
Interpreter();
|
||||
|
@ -114,7 +114,6 @@ suite lexer_test = [] {
|
||||
"Numeric tokens"_test = [] {
|
||||
expect_token_type_and_value(Token::Type::Numeric, "0");
|
||||
expect_token_type_and_value(Token::Type::Numeric, "123456789");
|
||||
expect_token_type_and_value(Token::Type::Numeric, ".75");
|
||||
expect_token_type_and_value(Token::Type::Numeric, "0.75");
|
||||
expect_token_type_and_value(Token::Type::Numeric, "123456789.123456789");
|
||||
expect_token_type_and_value(Token::Type::Numeric, "123.", "123");
|
||||
|
13
src/value.cc
13
src/value.cc
@ -152,3 +152,16 @@ Result<Value> Block::operator()(Interpreter &i, std::vector<Value> arguments)
|
||||
i.env = old_scope;
|
||||
return result;
|
||||
}
|
||||
|
||||
// TODO Add memoization
|
||||
Result<Value> Block::index(Interpreter &i, unsigned position)
|
||||
{
|
||||
assert(parameters.size() == 0, "cannot index into block with parameters (for now)");
|
||||
if (body.type != Ast::Type::Sequence) {
|
||||
assert(position == 0, "Out of range"); // TODO(assert)
|
||||
return i.eval((Ast)body);
|
||||
}
|
||||
|
||||
assert(position < body.arguments.size(), "Out of range"); // TODO(assert)
|
||||
return i.eval((Ast)body.arguments[position]);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user