/* * Copyright (C) 2023 Riyyi * * SPDX-License-Identifier: MIT */ #include // std::span #include "ast.h" #include "environment.h" #include "eval.h" #include "ruc/meta/assert.h" #include "types.h" namespace blaze { Eval::Eval(ASTNode* ast, Environment* env) : m_ast(ast) , m_env(env) { } void Eval::eval() { m_ast = evalImpl(m_ast, m_env); } ASTNode* Eval::evalImpl(ASTNode* ast, Environment* env) { if (!is(ast)) { return evalAst(ast, env); } if (static_cast(ast)->empty()) { return ast; } return apply(static_cast(evalAst(ast, env))); } ASTNode* Eval::evalAst(ASTNode* ast, Environment* env) { if (is(ast)) { auto result = env->lookup(static_cast(ast)->symbol()); if (!result) { Error::the().addError(format("symbol’s function definition is void: {}", ast)); } return result; } else if (is(ast)) { auto result = new List(); auto nodes = static_cast(ast)->nodes(); for (auto node : nodes) { result->addNode(evalImpl(node, env)); } return result; } else if (is(ast)) { auto result = new Vector(); auto nodes = static_cast(ast)->nodes(); for (auto node : nodes) { result->addNode(evalImpl(node, env)); } return result; } else if (is(ast)) { auto result = new HashMap(); auto elements = static_cast(ast)->elements(); for (auto& element : elements) { result->addElement(element.first, evalImpl(element.second, env)); } return result; } return ast; } ASTNode* Eval::apply(List* evaluated_list) { auto nodes = evaluated_list->nodes(); if (!is(nodes[0])) { Error::the().addError(format("invalid function: {}", nodes[0])); return nullptr; } // car auto lambda = static_cast(nodes[0])->lambda(); // cdr std::span span { nodes.data() + 1, nodes.size() - 1 }; return lambda(span); } } // namespace blaze