compact implementation; runs on msp430
parent
914a75b209
commit
0b88b4596e
@ -1,4 +1,5 @@
|
||||
.*
|
||||
*.o
|
||||
alee
|
||||
alee-msp430
|
||||
libalee.a
|
||||
|
@ -1,24 +1,32 @@
|
||||
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
|
||||
OBJFILES := $(subst .cpp,.o,$(CXXFILES))
|
||||
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: $(EXEFILE)
|
||||
small: alee
|
||||
|
||||
fast: CXXFLAGS += -O3 -march=native -mtune=native
|
||||
fast: $(EXEFILE)
|
||||
fast: alee
|
||||
|
||||
alee: $(LIBFILE)
|
||||
|
||||
$(EXEFILE): $(LIBFILE)
|
||||
alee-msp430: $(LIBFILE)
|
||||
|
||||
$(LIBFILE): $(OBJFILES)
|
||||
$(AR) cr $@ $(OBJFILES)
|
||||
|
||||
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