From a4635fb95235ba4bf077bd59957da0626fc5ba72 Mon Sep 17 00:00:00 2001 From: Benjamin Barenblat Date: Tue, 14 Dec 2021 12:34:06 -0500 Subject: EC, a terminal-based RPN calculator --- src/language.cc | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 src/language.cc (limited to 'src/language.cc') diff --git a/src/language.cc b/src/language.cc new file mode 100644 index 0000000..277c545 --- /dev/null +++ b/src/language.cc @@ -0,0 +1,95 @@ +// Copyright 2021 Benjamin Barenblat +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy of +// the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. + +#include "src/language.h" + +#include + +#include +#include +#include +#include + +#include "src/builtin.h" +#include "third_party/abseil/absl/strings/str_cat.h" + +namespace ec { + +State::State() noexcept : environment(BuiltinEnvironment()) {} + +void GroundTerm::Evaluate(State& state) const noexcept { + state.stack.push_back(Clone()); +} + +std::string GroundTerm::Show() const noexcept { + // A double-precision value has 13 decimal digits of precision. + std::ostringstream s; + s.precision(13); + s << value_; + return s.str(); +} + +std::string GroundTerm::DebugString() const noexcept { + return absl::StrCat("GroundTerm(", value_, ")"); +} + +GroundTerm* GroundTerm::CloneImpl() const noexcept { + return new GroundTerm(*this); +} + +void ForeignProgramTerm::Evaluate(State& state) const { impl_(state); } + +std::string ForeignProgramTerm::Show() const noexcept { return ""; } + +std::string ForeignProgramTerm::DebugString() const noexcept { + return absl::StrCat("ForeignProgramTerm(", reinterpret_cast(impl_), + ")"); +} + +ForeignProgramTerm* ForeignProgramTerm::CloneImpl() const noexcept { + return new ForeignProgramTerm(*this); +} + +void SymbolTerm::Evaluate(State& state) const { + auto it = state.environment.find(name_); + if (it == state.environment.end()) { + throw UndefinedName(name_); + } + it->second->Evaluate(state); +} + +std::string SymbolTerm::Show() const noexcept { + return absl::StrCat("'", name_); +} + +std::string SymbolTerm::DebugString() const noexcept { + return absl::StrCat("SymbolTerm(", name_, ")"); +} + +SymbolTerm* SymbolTerm::CloneImpl() const noexcept { + return new SymbolTerm(*this); +} + +void FormatStackElement(std::string* out, + std::shared_ptr term) noexcept { + out->append(term->Show()); +} + +void EvaluateAll(const Program& program, State& state) { + for (auto term : program) { + term->Evaluate(state); + } +} + +} // namespace ec -- cgit v1.2.3