build as library; add small target
parent
92680120c6
commit
5bc9e4d2ad
@ -1,3 +1,4 @@
|
||||
.*
|
||||
*.o
|
||||
alee
|
||||
libalee.a
|
||||
|
@ -1,13 +1,21 @@
|
||||
CXXFLAGS += -g3 -ggdb -O0
|
||||
CXXFLAGS += -std=c++17 -g3 -ggdb -O0
|
||||
|
||||
CXXFILES := corewords.cpp types.cpp
|
||||
CXXFILES := corewords.cpp dictionary.cpp executor.cpp parser.cpp state.cpp \
|
||||
types.cpp
|
||||
OBJFILES := $(subst .cpp,.o,$(CXXFILES))
|
||||
LIBFILE := libalee.a
|
||||
EXEFILE := alee
|
||||
|
||||
all: alee
|
||||
all: $(EXEFILE)
|
||||
|
||||
alee: $(OBJFILES)
|
||||
small: CXXFLAGS += -Os
|
||||
small: $(EXEFILE)
|
||||
|
||||
$(EXEFILE): $(LIBFILE)
|
||||
|
||||
$(LIBFILE): $(OBJFILES)
|
||||
$(AR) cr $@ $(OBJFILES)
|
||||
|
||||
clean:
|
||||
rm -f alee $(OBJFILES)
|
||||
rm -f $(EXEFILE) $(LIBFILE) $(OBJFILES)
|
||||
|
||||
|
@ -0,0 +1,80 @@
|
||||
/**
|
||||
* Alee Forth: A portable and concise Forth implementation in modern C++.
|
||||
* Copyright (C) 2023 Clyne Sullivan <clyne@bitgloo.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "dictionary.hpp"
|
||||
|
||||
Addr Dictionary::allot(Cell amount)
|
||||
{
|
||||
Addr old = here;
|
||||
here += amount;
|
||||
return old;
|
||||
}
|
||||
|
||||
void Dictionary::add(Cell value)
|
||||
{
|
||||
write(here++, value);
|
||||
}
|
||||
|
||||
void Dictionary::addDefinition(std::string_view str)
|
||||
{
|
||||
add(str.size());
|
||||
for (char c : str)
|
||||
add(c);
|
||||
|
||||
if (here & 1)
|
||||
allot(1);
|
||||
}
|
||||
|
||||
bool Dictionary::issame(Addr addr, std::string_view str, std::size_t n)
|
||||
{
|
||||
if (str.size() != n)
|
||||
return false;
|
||||
|
||||
for (char c : str) {
|
||||
if (read(addr++) != c)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Addr Dictionary::find(std::string_view str)
|
||||
{
|
||||
if (latest == 0)
|
||||
return 0;
|
||||
|
||||
auto lt = latest;
|
||||
do {
|
||||
const auto l = read(lt);
|
||||
const auto len = l & 0x1F;
|
||||
|
||||
if (issame(lt + 1, str, len))
|
||||
return lt;
|
||||
else
|
||||
lt -= l >> 6;
|
||||
} while (lt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Addr Dictionary::getexec(Addr addr)
|
||||
{
|
||||
const auto len = read(addr) & 0x1F;
|
||||
return ((addr + 1 + len) + 1) & ~1;
|
||||
}
|
||||
|
@ -0,0 +1,34 @@
|
||||
/**
|
||||
* Alee Forth: A portable and concise Forth implementation in modern C++.
|
||||
* Copyright (C) 2023 Clyne Sullivan <clyne@bitgloo.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "corewords.hpp"
|
||||
#include "executor.hpp"
|
||||
|
||||
int Executor::fullexec(State& state, Addr addr)
|
||||
{
|
||||
state.pushr(0);
|
||||
state.ip = addr - 1;
|
||||
|
||||
do {
|
||||
++state.ip;
|
||||
CoreWords::run(state.dict.read(state.ip), state);
|
||||
} while (state.ip);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -0,0 +1,107 @@
|
||||
/**
|
||||
* Alee Forth: A portable and concise Forth implementation in modern C++.
|
||||
* Copyright (C) 2023 Clyne Sullivan <clyne@bitgloo.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "corewords.hpp"
|
||||
#include "executor.hpp"
|
||||
#include "parser.hpp"
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
ParseStatus Parser::parse(State& state, std::string_view& str)
|
||||
{
|
||||
const auto end = str.find_first_of(" \t\n\r");
|
||||
const auto sub = str.substr(0, end);
|
||||
if (sub.empty())
|
||||
return ParseStatus::Finished;
|
||||
|
||||
if (state.pass != Pass::None) {
|
||||
switch (state.pass) {
|
||||
case Pass::Comment:
|
||||
if (str.front() == ')')
|
||||
state.pass = Pass::None;
|
||||
|
||||
str = str.substr(1);
|
||||
break;
|
||||
case Pass::Colon:
|
||||
state.pass = Pass::None;
|
||||
state.compiling = true;
|
||||
state.dict.addDefinition(sub);
|
||||
break;
|
||||
case Pass::Constant:
|
||||
state.pass = Pass::None;
|
||||
state.compiling = true;
|
||||
state.dict.addDefinition(sub);
|
||||
state.dict.add(CoreWords::HiddenWordLiteral);
|
||||
state.dict.add(state.pop());
|
||||
state.dict.add(CoreWords::findi(";"));
|
||||
CoreWords::run(CoreWords::findi(";"), state);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (auto i = CoreWords::findi(sub); i >= 0) {
|
||||
if (state.compiling)
|
||||
state.dict.add(i);
|
||||
if (!state.compiling || sub.front() == ';')
|
||||
CoreWords::run(i, state);
|
||||
} else if (auto j = state.dict.find(sub); j > 0) {
|
||||
auto e = state.dict.getexec(j);
|
||||
|
||||
if (state.compiling) {
|
||||
if (state.dict.read(j) & CoreWords::Immediate) {
|
||||
state.compiling = false;
|
||||
Executor::fullexec(state, e);
|
||||
state.compiling = true;
|
||||
} else {
|
||||
state.dict.add(CoreWords::HiddenWordJump);
|
||||
state.dict.add(e);
|
||||
}
|
||||
} else {
|
||||
Executor::fullexec(state, e);
|
||||
}
|
||||
} else {
|
||||
char *p;
|
||||
const auto l = static_cast<Cell>(std::strtol(sub.data(), &p, 10));
|
||||
|
||||
if (p != sub.data()) {
|
||||
if (state.compiling) {
|
||||
state.dict.add(CoreWords::HiddenWordLiteral);
|
||||
state.dict.add(l);
|
||||
} else {
|
||||
state.push(l);
|
||||
}
|
||||
} else {
|
||||
return ParseStatus::Error;
|
||||
}
|
||||
}
|
||||
|
||||
if (end == std::string_view::npos)
|
||||
return ParseStatus::Finished;
|
||||
}
|
||||
|
||||
const auto next = str.find_first_not_of(" \t\n\r", end);
|
||||
|
||||
if (next == std::string_view::npos) {
|
||||
return ParseStatus::Finished;
|
||||
} else {
|
||||
str = str.substr(next);
|
||||
return ParseStatus::Continue;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,79 @@
|
||||
/**
|
||||
* Alee Forth: A portable and concise Forth implementation in modern C++.
|
||||
* Copyright (C) 2023 Clyne Sullivan <clyne@bitgloo.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "state.hpp"
|
||||
|
||||
#include <iterator>
|
||||
|
||||
Cell State::beyondip() const
|
||||
{
|
||||
return dict.read(ip + 1);
|
||||
}
|
||||
|
||||
void State::pushr(Cell value)
|
||||
{
|
||||
if (rsize() == ReturnStackSize)
|
||||
throw;
|
||||
*++rsp = value;
|
||||
}
|
||||
|
||||
Cell State::popr()
|
||||
{
|
||||
if (rsize() == 0)
|
||||
throw;
|
||||
return *rsp--;
|
||||
}
|
||||
|
||||
void State::push(Cell value)
|
||||
{
|
||||
if (size() == DataStackSize)
|
||||
throw;
|
||||
*++dsp = value;
|
||||
}
|
||||
|
||||
Cell State::pop()
|
||||
{
|
||||
if (size() == 0)
|
||||
throw;
|
||||
return *dsp--;
|
||||
}
|
||||
|
||||
Cell& State::top()
|
||||
{
|
||||
if (size() == 0)
|
||||
throw;
|
||||
return *dsp;
|
||||
}
|
||||
|
||||
Cell& State::pick(std::size_t i)
|
||||
{
|
||||
if (i >= size())
|
||||
throw;
|
||||
return *(dsp - i);
|
||||
}
|
||||
|
||||
std::size_t State::size() const noexcept
|
||||
{
|
||||
return std::distance(dstack, static_cast<const Cell *>(dsp)) + 1;
|
||||
}
|
||||
|
||||
std::size_t State::rsize() const noexcept
|
||||
{
|
||||
return std::distance(rstack, static_cast<const Cell *>(rsp)) + 1;
|
||||
}
|
||||
|
Loading…
Reference in New Issue