Assigments, array updating function. Test runner update

This commit is contained in:
Robert Bendun 2022-06-06 04:03:40 +02:00
parent 118837f6d8
commit 91eaa0ceea
6 changed files with 105 additions and 8 deletions

View File

@ -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 "--.*$"

View File

@ -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)

View File

@ -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": []
}

View 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": []
}

View 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;

View File

@ -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)
@ -29,6 +38,7 @@ 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 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))));
}