compact implementation; runs on msp430
parent
914a75b209
commit
0b88b4596e
@ -1,4 +1,5 @@
|
|||||||
.*
|
.*
|
||||||
*.o
|
*.o
|
||||||
alee
|
alee
|
||||||
|
alee-msp430
|
||||||
libalee.a
|
libalee.a
|
||||||
|
@ -1,24 +1,32 @@
|
|||||||
CXXFLAGS += -std=c++17 -g3 -ggdb -O0 \
|
CXXFLAGS += -std=c++17 -g3 -ggdb -O0 \
|
||||||
-Wall -Wextra -pedantic -Wno-vla -Werror
|
-Wall -Wextra -pedantic -Werror \
|
||||||
|
-fno-exceptions -fno-rtti #-fstack-usage
|
||||||
|
|
||||||
CXXFILES := corewords.cpp dictionary.cpp parser.cpp state.cpp
|
CXXFILES := corewords.cpp dictionary.cpp parser.cpp state.cpp
|
||||||
OBJFILES := $(subst .cpp,.o,$(CXXFILES))
|
OBJFILES := $(subst .cpp,.o,$(CXXFILES))
|
||||||
LIBFILE := libalee.a
|
LIBFILE := libalee.a
|
||||||
EXEFILE := alee
|
|
||||||
|
|
||||||
all: $(EXEFILE)
|
all: alee
|
||||||
|
|
||||||
|
msp430: CXX := msp430-elf32-g++
|
||||||
|
msp430: AR := msp430-elf32-ar
|
||||||
|
msp430: CXXFLAGS += -Os -mmcu=msp430g2553 -ffunction-sections -fdata-sections -DMEMDICTSIZE=200
|
||||||
|
msp430: LDFLAGS += -L/opt/msp430-elf32/include -Wl,-gc-sections
|
||||||
|
msp430: alee-msp430
|
||||||
|
|
||||||
small: CXXFLAGS += -Os
|
small: CXXFLAGS += -Os
|
||||||
small: $(EXEFILE)
|
small: alee
|
||||||
|
|
||||||
fast: CXXFLAGS += -O3 -march=native -mtune=native
|
fast: CXXFLAGS += -O3 -march=native -mtune=native
|
||||||
fast: $(EXEFILE)
|
fast: alee
|
||||||
|
|
||||||
|
alee: $(LIBFILE)
|
||||||
|
|
||||||
$(EXEFILE): $(LIBFILE)
|
alee-msp430: $(LIBFILE)
|
||||||
|
|
||||||
$(LIBFILE): $(OBJFILES)
|
$(LIBFILE): $(OBJFILES)
|
||||||
$(AR) cr $@ $(OBJFILES)
|
$(AR) cr $@ $(OBJFILES)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f $(EXEFILE) $(LIBFILE) $(OBJFILES)
|
rm -f alee alee-msp430 $(LIBFILE) $(OBJFILES)
|
||||||
|
|
||||||
|
@ -0,0 +1,162 @@
|
|||||||
|
/**
|
||||||
|
* 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 "alee.hpp"
|
||||||
|
#include "memdict.hpp"
|
||||||
|
|
||||||
|
#include <msp430.h>
|
||||||
|
|
||||||
|
static char strbuf[32];
|
||||||
|
|
||||||
|
static void readchar(State& state);
|
||||||
|
static void serput(int c);
|
||||||
|
static void serputs(const char *s);
|
||||||
|
static void printint(int n, char *buf);
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
WDTCTL = WDTPW | WDTHOLD;
|
||||||
|
DCOCTL = 0;
|
||||||
|
BCSCTL1 = CALBC1_1MHZ;
|
||||||
|
DCOCTL = CALDCO_1MHZ;
|
||||||
|
|
||||||
|
P1SEL |= BIT1 | BIT2;
|
||||||
|
P1SEL2 |= BIT1 | BIT2;
|
||||||
|
|
||||||
|
UCA0CTL1 = UCSWRST;
|
||||||
|
UCA0CTL1 |= UCSSEL_2;
|
||||||
|
UCA0BR0 = 104;
|
||||||
|
UCA0BR1 = 0;
|
||||||
|
UCA0MCTL = UCBRS0;
|
||||||
|
UCA0CTL1 &= (uint8_t)~UCSWRST;
|
||||||
|
|
||||||
|
__enable_interrupt();
|
||||||
|
|
||||||
|
static MemDict dict;
|
||||||
|
State state (dict, readchar);
|
||||||
|
Parser parser;
|
||||||
|
|
||||||
|
dict.write(Dictionary::Base, 10);
|
||||||
|
dict.write(Dictionary::Latest, Dictionary::Begin);
|
||||||
|
dict.write(Dictionary::Compiling, 0);
|
||||||
|
dict.write(Dictionary::Postpone, 0);
|
||||||
|
|
||||||
|
serputs("alee forth\n\r");
|
||||||
|
|
||||||
|
auto ptr = strbuf;
|
||||||
|
while (1) {
|
||||||
|
if (IFG2 & UCA0RXIFG) {
|
||||||
|
char c = UCA0RXBUF;
|
||||||
|
serput(c);
|
||||||
|
|
||||||
|
if (c == '\r') {
|
||||||
|
*ptr = '\0';
|
||||||
|
|
||||||
|
serputs("\n\r");
|
||||||
|
|
||||||
|
if (auto r = parser.parse(state, strbuf); r == 0) {
|
||||||
|
serputs(state.compiling() ? " compiled" : " ok");
|
||||||
|
} else {
|
||||||
|
switch (r) {
|
||||||
|
case Parser::UnknownWord:
|
||||||
|
serputs("unknown word...");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
serputs("\n\r");
|
||||||
|
|
||||||
|
ptr = strbuf;
|
||||||
|
} else if (c == '\b') {
|
||||||
|
if (ptr > strbuf)
|
||||||
|
--ptr;
|
||||||
|
} else if (ptr < strbuf + sizeof(strbuf)) {
|
||||||
|
if (c >= 'A' && c <= 'Z')
|
||||||
|
c += 32;
|
||||||
|
*ptr++ = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void readchar(State& state)
|
||||||
|
{
|
||||||
|
auto len = state.dict.read(Dictionary::Input);
|
||||||
|
Addr addr = Dictionary::Input + sizeof(Cell) +
|
||||||
|
Dictionary::InputCells - len - 1;
|
||||||
|
|
||||||
|
for (Cell i = 0; i < len; ++i, ++addr)
|
||||||
|
state.dict.writebyte(addr, state.dict.readbyte(addr + 1));
|
||||||
|
|
||||||
|
while (!(IFG2 & UCA0RXIFG));
|
||||||
|
state.dict.writebyte(addr, UCA0RXBUF);
|
||||||
|
state.dict.write(Dictionary::Input, len + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void serput(int c)
|
||||||
|
{
|
||||||
|
while (!(IFG2 & UCA0TXIFG));
|
||||||
|
UCA0TXBUF = (char)c;
|
||||||
|
}
|
||||||
|
|
||||||
|
void serputs(const char *s)
|
||||||
|
{
|
||||||
|
while (*s)
|
||||||
|
serput(*s++);
|
||||||
|
}
|
||||||
|
|
||||||
|
void printint(int n, char *buf)
|
||||||
|
{
|
||||||
|
char *ptr = buf;
|
||||||
|
bool neg = n < 0;
|
||||||
|
|
||||||
|
if (neg)
|
||||||
|
n = -n;
|
||||||
|
|
||||||
|
do {
|
||||||
|
*ptr++ = (char)(n % 10) + '0';
|
||||||
|
} while ((n /= 10));
|
||||||
|
|
||||||
|
if (neg)
|
||||||
|
serput('-');
|
||||||
|
|
||||||
|
do {
|
||||||
|
serput(*--ptr);
|
||||||
|
} while (ptr > buf);
|
||||||
|
serput(' ');
|
||||||
|
}
|
||||||
|
|
||||||
|
void user_sys(State& state)
|
||||||
|
{
|
||||||
|
switch (state.pop()) {
|
||||||
|
case 0:
|
||||||
|
printint(state.pop(), strbuf);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
serput(state.pop());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue