build as library; add small target
parent
92680120c6
commit
5bc9e4d2ad
@ -1,3 +1,4 @@
|
|||||||
.*
|
.*
|
||||||
*.o
|
*.o
|
||||||
alee
|
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))
|
OBJFILES := $(subst .cpp,.o,$(CXXFILES))
|
||||||
|
LIBFILE := libalee.a
|
||||||
EXEFILE := alee
|
EXEFILE := alee
|
||||||
|
|
||||||
all: alee
|
all: $(EXEFILE)
|
||||||
|
|
||||||
alee: $(OBJFILES)
|
small: CXXFLAGS += -Os
|
||||||
|
small: $(EXEFILE)
|
||||||
|
|
||||||
|
$(EXEFILE): $(LIBFILE)
|
||||||
|
|
||||||
|
$(LIBFILE): $(OBJFILES)
|
||||||
|
$(AR) cr $@ $(OBJFILES)
|
||||||
|
|
||||||
clean:
|
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