Assigments, array updating function. Test runner update
This commit is contained in:
parent
118837f6d8
commit
91eaa0ceea
@ -18,7 +18,7 @@ syn match musiqueInteger display "[0-9][0-9_]*"
|
||||
|
||||
syn keyword musiqueConstant true false nil
|
||||
|
||||
syn keyword musiqueDefaultBuiltins if len play
|
||||
syn keyword musiqueDefaultBuiltins if len play permute par shuffle chord bpm oct note_on note_off flat update
|
||||
syn keyword musiqueLinuxBuiltins say
|
||||
|
||||
syn match musiqueComment "--.*$"
|
||||
|
@ -116,18 +116,33 @@ def record_tests(file_paths: list):
|
||||
tc = Test_Case.from_run(res, [])
|
||||
tc.save(test_case_file)
|
||||
|
||||
def add_tests(file_paths: list):
|
||||
to_be_added = []
|
||||
|
||||
for program_file in file_paths:
|
||||
test_case_file = find_path_for_test_case(program_file)
|
||||
if not os.path.exists(test_case_file):
|
||||
print(f"Add test {program_file}? (yes/no)")
|
||||
if "yes".startswith(input().strip().lower()):
|
||||
to_be_added.append(program_file)
|
||||
|
||||
record_tests(to_be_added)
|
||||
|
||||
|
||||
# list of files to test
|
||||
def main():
|
||||
file_paths, mode = [], run_tests
|
||||
|
||||
if len(argv) < 2:
|
||||
print("[ERROR] Expected mode argument (either 'record' or 'test')")
|
||||
print("[ERROR] Expected mode argument (either 'record', 'add' or 'test')")
|
||||
exit(1)
|
||||
|
||||
if argv[1] == "test":
|
||||
mode = run_tests
|
||||
elif argv[1] == "record":
|
||||
mode = record_tests
|
||||
elif argv[1] == "add":
|
||||
mode = add_tests
|
||||
else:
|
||||
print(f"[ERROR] Unrecognized mode '{argv[1]}'")
|
||||
exit(1)
|
||||
@ -142,6 +157,8 @@ def main():
|
||||
file_paths.extend(glob(f"{path}/*.mq"))
|
||||
else:
|
||||
file_paths.append(path)
|
||||
elif mode == add_tests:
|
||||
print("Adding: " + path)
|
||||
|
||||
mode(file_paths)
|
||||
|
||||
|
@ -0,0 +1,6 @@
|
||||
{
|
||||
"returncode": 0,
|
||||
"stdout": "10\n20\n30\n20\n20\n20\n[1; 2; 3]\n[1; 10; 3]\n[1; 3; 3]\n",
|
||||
"stderr": "",
|
||||
"flags": []
|
||||
}
|
6
examples/.tests_cache/permutations.mq.json
Normal file
6
examples/.tests_cache/permutations.mq.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"returncode": 0,
|
||||
"stdout": "[1; 2; 3; 4; 5]\n[1; 2; 3; 5; 4]\n[1; 2; 4; 3; 5]\n[1; 2; 4; 5; 3]\n[1; 2; 5; 3; 4]\n[1; 2; 5; 4; 3]\n[1; 3; 2; 4; 5]\n[1; 3; 2; 5; 4]\n[1; 3; 4; 2; 5]\n[1; 3; 4; 5; 2]\n[1; 3; 5; 2; 4]\n[1; 3; 5; 4; 2]\n[1; 4; 2; 3; 5]\n[1; 4; 2; 5; 3]\n[1; 4; 3; 2; 5]\n[1; 4; 3; 5; 2]\n[1; 4; 5; 2; 3]\n[1; 4; 5; 3; 2]\n[1; 5; 2; 3; 4]\n[1; 5; 2; 4; 3]\n[1; 5; 3; 2; 4]\n[1; 5; 3; 4; 2]\n[1; 5; 4; 2; 3]\n[1; 5; 4; 3; 2]\n[2; 1; 3; 4; 5]\n[2; 1; 3; 5; 4]\n[2; 1; 4; 3; 5]\n[2; 1; 4; 5; 3]\n[2; 1; 5; 3; 4]\n[2; 1; 5; 4; 3]\n[2; 3; 1; 4; 5]\n[2; 3; 1; 5; 4]\n[2; 3; 4; 1; 5]\n[2; 3; 4; 5; 1]\n[2; 3; 5; 1; 4]\n[2; 3; 5; 4; 1]\n[2; 4; 1; 3; 5]\n[2; 4; 1; 5; 3]\n[2; 4; 3; 1; 5]\n[2; 4; 3; 5; 1]\n[2; 4; 5; 1; 3]\n[2; 4; 5; 3; 1]\n[2; 5; 1; 3; 4]\n[2; 5; 1; 4; 3]\n[2; 5; 3; 1; 4]\n[2; 5; 3; 4; 1]\n[2; 5; 4; 1; 3]\n[2; 5; 4; 3; 1]\n[3; 1; 2; 4; 5]\n[3; 1; 2; 5; 4]\n[3; 1; 4; 2; 5]\n[3; 1; 4; 5; 2]\n[3; 1; 5; 2; 4]\n[3; 1; 5; 4; 2]\n[3; 2; 1; 4; 5]\n[3; 2; 1; 5; 4]\n[3; 2; 4; 1; 5]\n[3; 2; 4; 5; 1]\n[3; 2; 5; 1; 4]\n[3; 2; 5; 4; 1]\n[3; 4; 1; 2; 5]\n[3; 4; 1; 5; 2]\n[3; 4; 2; 1; 5]\n[3; 4; 2; 5; 1]\n[3; 4; 5; 1; 2]\n[3; 4; 5; 2; 1]\n[3; 5; 1; 2; 4]\n[3; 5; 1; 4; 2]\n[3; 5; 2; 1; 4]\n[3; 5; 2; 4; 1]\n[3; 5; 4; 1; 2]\n[3; 5; 4; 2; 1]\n[4; 1; 2; 3; 5]\n[4; 1; 2; 5; 3]\n[4; 1; 3; 2; 5]\n[4; 1; 3; 5; 2]\n[4; 1; 5; 2; 3]\n[4; 1; 5; 3; 2]\n[4; 2; 1; 3; 5]\n[4; 2; 1; 5; 3]\n[4; 2; 3; 1; 5]\n[4; 2; 3; 5; 1]\n[4; 2; 5; 1; 3]\n[4; 2; 5; 3; 1]\n[4; 3; 1; 2; 5]\n[4; 3; 1; 5; 2]\n[4; 3; 2; 1; 5]\n[4; 3; 2; 5; 1]\n[4; 3; 5; 1; 2]\n[4; 3; 5; 2; 1]\n[4; 5; 1; 2; 3]\n[4; 5; 1; 3; 2]\n[4; 5; 2; 1; 3]\n[4; 5; 2; 3; 1]\n[4; 5; 3; 1; 2]\n[4; 5; 3; 2; 1]\n[5; 1; 2; 3; 4]\n[5; 1; 2; 4; 3]\n[5; 1; 3; 2; 4]\n[5; 1; 3; 4; 2]\n[5; 1; 4; 2; 3]\n[5; 1; 4; 3; 2]\n[5; 2; 1; 3; 4]\n[5; 2; 1; 4; 3]\n[5; 2; 3; 1; 4]\n[5; 2; 3; 4; 1]\n[5; 2; 4; 1; 3]\n[5; 2; 4; 3; 1]\n[5; 3; 1; 2; 4]\n[5; 3; 1; 4; 2]\n[5; 3; 2; 1; 4]\n[5; 3; 2; 4; 1]\n[5; 3; 4; 1; 2]\n[5; 3; 4; 2; 1]\n[5; 4; 1; 2; 3]\n[5; 4; 1; 3; 2]\n[5; 4; 2; 1; 3]\n[5; 4; 2; 3; 1]\n[5; 4; 3; 1; 2]\n[5; 4; 3; 2; 1]\n",
|
||||
"stderr": "",
|
||||
"flags": []
|
||||
}
|
27
examples/assigments-state-management.mq
Normal file
27
examples/assigments-state-management.mq
Normal file
@ -0,0 +1,27 @@
|
||||
----------------------------------
|
||||
Simple variable assigment
|
||||
----------------------------------
|
||||
var x = 10;
|
||||
var y = 20;
|
||||
say x;
|
||||
say y;
|
||||
|
||||
x = 30;
|
||||
say x;
|
||||
say y;
|
||||
|
||||
x = y;
|
||||
say x;
|
||||
say y;
|
||||
|
||||
----------------------------------
|
||||
Array updates
|
||||
----------------------------------
|
||||
var array = flat 1 2 3;
|
||||
say array;
|
||||
|
||||
array = update array 1 10;
|
||||
say array;
|
||||
|
||||
array = update array 1 (array.2);
|
||||
say array;
|
@ -14,6 +14,15 @@ static inline bool typecheck(std::vector<Value> const& args, auto const& ...expe
|
||||
} (std::make_index_sequence<sizeof...(expected_types)>{});
|
||||
}
|
||||
|
||||
/// Intrinsic implementation primitive providing a short way to move values based on matched type signature
|
||||
static inline bool typecheck_front(std::vector<Value> const& args, auto const& ...expected_types)
|
||||
{
|
||||
return (args.size() >= sizeof...(expected_types)) &&
|
||||
[&args, expected_types...]<std::size_t ...I>(std::index_sequence<I...>) {
|
||||
return ((expected_types == args[I].type) && ...);
|
||||
} (std::make_index_sequence<sizeof...(expected_types)>{});
|
||||
}
|
||||
|
||||
/// Intrinsic implementation primitive providing a short way to move values based on matched type signature
|
||||
template<auto ...Types>
|
||||
static inline auto move_from(std::vector<Value>& args)
|
||||
@ -27,8 +36,9 @@ static inline auto move_from(std::vector<Value>& args)
|
||||
template<auto ...Types>
|
||||
struct Shape
|
||||
{
|
||||
static inline auto move_from(std::vector<Value>& args) { return ::move_from<Types...>(args); }
|
||||
static inline auto typecheck(std::vector<Value>& args) { return ::typecheck(args, Types...); }
|
||||
static inline auto move_from(std::vector<Value>& args) { return ::move_from<Types...>(args); }
|
||||
static inline auto typecheck(std::vector<Value>& args) { return ::typecheck(args, Types...); }
|
||||
static inline auto typecheck_front(std::vector<Value>& args) { return ::typecheck_front(args, Types...); }
|
||||
};
|
||||
|
||||
/// Returns if type can be indexed
|
||||
@ -295,6 +305,27 @@ Interpreter::Interpreter()
|
||||
|
||||
register_note_length_constants();
|
||||
|
||||
global.force_define("update", +[](Interpreter &i, std::vector<Value> args) -> Result<Value> {
|
||||
assert(args.size() == 3, "Update requires 3 arguments"); // TODO(assert)
|
||||
using Eager_And_Number = Shape<Value::Type::Array, Value::Type::Number>;
|
||||
using Lazy_And_Number = Shape<Value::Type::Block, Value::Type::Number>;
|
||||
|
||||
if (Eager_And_Number::typecheck_front(args)) {
|
||||
auto [v, index] = Eager_And_Number::move_from(args);
|
||||
v.elements[index.as_int()] = std::move(args.back());
|
||||
return Value::from(std::move(v));
|
||||
}
|
||||
|
||||
if (Lazy_And_Number::typecheck_front(args)) {
|
||||
auto [v, index] = Lazy_And_Number::move_from(args);
|
||||
auto array = Try(into_flat_array(i, { Value::from(std::move(v)) }));
|
||||
array.elements[index.as_int()] = std::move(args.back());
|
||||
return Value::from(std::move(array));
|
||||
}
|
||||
|
||||
unimplemented("Wrong shape of update function");
|
||||
});
|
||||
|
||||
global.force_define("typeof", +[](Interpreter&, std::vector<Value> args) -> Result<Value> {
|
||||
assert(args.size() == 1, "typeof expects only one argument");
|
||||
return Value::from(std::string(type_name(args.front().type)));
|
||||
@ -446,11 +477,20 @@ Result<Value> Interpreter::eval(Ast &&ast)
|
||||
|
||||
case Ast::Type::Binary:
|
||||
{
|
||||
std::vector<Value> values;
|
||||
values.reserve(ast.arguments.size());
|
||||
assert(ast.arguments.size() == 2, "Expected arguments of binary operation to be 2 long");
|
||||
|
||||
if (ast.token.source == "=") {
|
||||
auto lhs = std::move(ast.arguments.front());
|
||||
auto rhs = std::move(ast.arguments.back());
|
||||
assert(lhs.type == Ast::Type::Literal && lhs.token.type == Token::Type::Symbol,
|
||||
"Currently LHS of assigment must be an identifier"); // TODO(assert)
|
||||
|
||||
Value *v = env->find(std::string(lhs.token.source));
|
||||
assert(v, "Cannot resolve variable: "s + std::string(lhs.token.source)); // TODO(assert)
|
||||
return *v = Try(eval(std::move(rhs)));
|
||||
}
|
||||
|
||||
if (ast.token.source == "and" || ast.token.source == "or") {
|
||||
assert(ast.arguments.size() == 2, "Expected arguments of binary operation to be 2 long");
|
||||
auto lhs = std::move(ast.arguments.front());
|
||||
auto rhs = std::move(ast.arguments.back());
|
||||
|
||||
@ -463,7 +503,6 @@ Result<Value> Interpreter::eval(Ast &&ast)
|
||||
}
|
||||
|
||||
auto op = operators.find(std::string(ast.token.source));
|
||||
|
||||
if (op == operators.end()) {
|
||||
return Error {
|
||||
.details = errors::Undefined_Operator { .op = ast.token.source },
|
||||
@ -471,6 +510,8 @@ Result<Value> Interpreter::eval(Ast &&ast)
|
||||
};
|
||||
}
|
||||
|
||||
std::vector<Value> values;
|
||||
values.reserve(ast.arguments.size());
|
||||
for (auto& a : ast.arguments) {
|
||||
values.push_back(Try(eval(std::move(a))));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user