diff --git a/examples/.tests_cache/factorial.mq.json b/examples/.tests_cache/factorial.mq.json index 780bb7a..3547c27 100644 --- a/examples/.tests_cache/factorial.mq.json +++ b/examples/.tests_cache/factorial.mq.json @@ -1,6 +1,6 @@ { "returncode": 0, - "stdout": "1\n2\n6\n24\n120\n720\n5040\n40320\n362880\n3628800\n", + "stdout": "1\n2\n6\n24\n120\n720\n5040\n40320\n362880\n3628800\n1\n2\n6\n24\n120\n720\n5040\n40320\n362880\n3628800\n", "stderr": "", "flags": [] } \ No newline at end of file diff --git a/examples/factorial.mq b/examples/factorial.mq index ea84260..6119a1a 100644 --- a/examples/factorial.mq +++ b/examples/factorial.mq @@ -5,5 +5,11 @@ var for = [ start stop iteration | ]; var factorial = [n | if (n <= 1) [1] [n * (factorial (n-1))]]; - for 1 10 [i | say (factorial i)]; + +var factorial_iterative = [n | + var x = 1; + for 1 n [i|x *= i]; + x +]; +for 1 10 [i | say (factorial_iterative i)]; diff --git a/src/interpreter.cc b/src/interpreter.cc index 8ab35c1..858da5f 100644 --- a/src/interpreter.cc +++ b/src/interpreter.cc @@ -490,6 +490,7 @@ Result Interpreter::eval(Ast &&ast) return *v = Try(eval(std::move(rhs))); } + if (ast.token.source == "and" || ast.token.source == "or") { auto lhs = std::move(ast.arguments.front()); auto rhs = std::move(ast.arguments.back()); @@ -504,6 +505,25 @@ Result Interpreter::eval(Ast &&ast) auto op = operators.find(std::string(ast.token.source)); if (op == operators.end()) { + if (ast.token.source.ends_with('=')) { + auto op = operators.find(std::string(ast.token.source.substr(0, ast.token.source.size()-1))); + if (op == operators.end()) { + return Error { + .details = errors::Undefined_Operator { .op = ast.token.source }, + .location = ast.token.location + }; + } + + 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(op->second(*this, { *v, Try(eval(std::move(rhs))) })); + } + return Error { .details = errors::Undefined_Operator { .op = ast.token.source }, .location = ast.token.location