Skip to content
Open

Forth #2947

Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ jobs:
- name: Install Host toolchain
run: |
apt-get update
apt-get install --assume-yes build-essential ruby-full
apt-get install --assume-yes build-essential gcc-multilib ruby-full

- name: Prebuild
run: |
Expand Down Expand Up @@ -275,7 +275,7 @@ jobs:
- name: Install Host toolchain
run: |
apt-get update
apt-get install --assume-yes build-essential ruby-full
apt-get install --assume-yes build-essential gcc-multilib ruby-full

- name: Prebuild
run: |
Expand Down Expand Up @@ -343,7 +343,7 @@ jobs:
- name: Install Host toolchain
run: |
apt-get update
apt-get install --assume-yes build-essential ruby-full
apt-get install --assume-yes build-essential gcc-multilib ruby-full

- name: Build
run: |
Expand Down Expand Up @@ -372,7 +372,7 @@ jobs:
- name: Install Host toolchain
run: |
apt-get update
apt-get install --assume-yes build-essential ruby-full
apt-get install --assume-yes build-essential gcc-multilib ruby-full

- name: Build
run: |
Expand Down Expand Up @@ -509,6 +509,9 @@ jobs:
with:
ruby-version: 2.6

- name: Install 32-bit build tools
run: sudo apt-get update && sudo apt-get install -y gcc-multilib

- name: Build lua
run: |
cd build
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/webapp.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ jobs:
submodules: recursive
fetch-depth: 0

- name: Install 32-bit build tools
run: sudo apt-get update && sudo apt-get install -y gcc-multilib

- name: Build
run: |
cd build
Expand Down
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -89,3 +89,6 @@
[submodule "vendor/lpeg"]
path = vendor/lpeg
url = https://github.com/roberto-ieru/LPeg.git
[submodule "vendor/pforth"]
path = vendor/pforth
url = https://github.com/philburk/pforth.git
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ include(cmake/squirrel.cmake)
include(cmake/pocketpy.cmake)
include(cmake/quickjs.cmake)
include(cmake/janet.cmake)
include(cmake/forth.cmake)

include(cmake/core.cmake)
include(cmake/wave.cmake)
Expand Down
2 changes: 2 additions & 0 deletions assets.bat
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ build\bin\prj2cart demos\schemedemo.scm build\schemedemo.tic
build\bin\prj2cart demos\sfx.lua build\sfx.tic
build\bin\prj2cart demos\squirreldemo.nut build\squirreldemo.tic
build\bin\prj2cart demos\tetris.lua build\tetris.tic
build\bin\prj2cart demos\forthdemo.fth build\forthdemo.tic
build\bin\prj2cart demos\wrendemo.wren build\wrendemo.tic
build\bin\prj2cart demos\yuedemo.yue build\yuedemo.tic

Expand Down Expand Up @@ -59,6 +60,7 @@ build\bin\bin2txt build\schemedemo.tic build\assets\schemedemo.tic.dat -z
build\bin\bin2txt build\sfx.tic build\assets\sfx.tic.dat -z
build\bin\bin2txt build\squirreldemo.tic build\assets\squirreldemo.tic.dat -z
build\bin\bin2txt build\tetris.tic build\assets\tetris.tic.dat -z
build\bin\bin2txt build\forthdemo.tic build\assets\forthdemo.tic.dat -z
build\bin\bin2txt build\wrendemo.tic build\assets\wrendemo.tic.dat -z
build\bin\bin2txt build\janetmark.tic build\assets\janetmark.tic.dat -z
Comment thread
luginf marked this conversation as resolved.
build\bin\bin2txt build\jsmark.tic build\assets\jsmark.tic.dat -z
Expand Down
1 change: 1 addition & 0 deletions build/assets/forthdemo.tic.dat
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0x78, 0xda, 0xed, 0x92, 0xcf, 0x6e, 0xd3, 0x40, 0x10, 0xc6, 0xb7, 0x2d, 0x1c, 0xf0, 0xa1, 0x12, 0x12, 0x0f, 0xf0, 0xa5, 0x27, 0x50, 0xff, 0x28, 0x4e, 0x03, 0x02, 0x23, 0x55, 0x24, 0x25, 0x51, 0x2d, 0x85, 0x24, 0x4a, 0x2c, 0x4e, 0xbd, 0x04, 0x67, 0x5b, 0x5b, 0x38, 0xd9, 0xc8, 0x76, 0x4b, 0xf2, 0x06, 0x3e, 0xf4, 0x21, 0x38, 0x22, 0xcb, 0x0f, 0xe1, 0x73, 0xb5, 0xea, 0x93, 0x44, 0x7e, 0x06, 0x66, 0xd7, 0x29, 0x6d, 0x2a, 0x04, 0x87, 0x1e, 0xb8, 0x30, 0xeb, 0xd5, 0xee, 0xec, 0x6f, 0xbe, 0x9d, 0xdd, 0x1d, 0x3f, 0x67, 0x8c, 0x6d, 0x7c, 0xdf, 0x64, 0x7f, 0xb3, 0x1b, 0x49, 0x96, 0x24, 0x49, 0x96, 0xa6, 0x69, 0xa6, 0x46, 0x72, 0x33, 0x99, 0xff, 0xea, 0x52, 0x2e, 0x8b, 0x24, 0x91, 0x45, 0x9a, 0xe6, 0x45, 0xf2, 0x23, 0x2f, 0x64, 0x96, 0xcb, 0x3c, 0xcb, 0xf3, 0xdb, 0xfe, 0x7b, 0xbd, 0xfc, 0xa3, 0x5e, 0xde, 0xd3, 0xb3, 0xff, 0xf6, 0x4f, 0x4d, 0xd7, 0x4a, 0xd5, 0x4e, 0xb7, 0x6b, 0x3d, 0xbf, 0xa2, 0x3a, 0x4a, 0x96, 0x4b, 0xaa, 0xed, 0x8d, 0xcc, 0x98, 0xa4, 0xda, 0x2d, 0x33, 0xaa, 0x5f, 0xba, 0xea, 0xaa, 0x9e, 0x2c, 0x5f, 0x16, 0x52, 0x16, 0xc5, 0x63, 0xf5, 0xcf, 0x8e, 0x1e, 0x77, 0xfe, 0xad, 0x27, 0xdb, 0x1b, 0xf4, 0xa7, 0x3f, 0x7d, 0xb1, 0xc9, 0x4e, 0x11, 0xfb, 0x71, 0xc0, 0x2d, 0x00, 0xe7, 0xa3, 0x09, 0x2f, 0x3d, 0xe3, 0x14, 0xa3, 0x8b, 0xd8, 0x13, 0xa1, 0xb5, 0x5a, 0x1d, 0xf3, 0x4b, 0x1e, 0x88, 0x19, 0x0f, 0xf7, 0xc0, 0x27, 0x23, 0x3f, 0xa0, 0x21, 0x76, 0x0f, 0x28, 0x6c, 0xcc, 0x23, 0x57, 0x69, 0x11, 0x51, 0x74, 0xac, 0xdd, 0xd0, 0x9f, 0xc5, 0xbe, 0x98, 0x12, 0x8c, 0xfc, 0x58, 0x6f, 0x8c, 0x6f, 0xfc, 0x8b, 0x9a, 0x23, 0xf0, 0xa7, 0x5f, 0x69, 0x3d, 0xf0, 0x5d, 0x3e, 0x8d, 0x08, 0x7d, 0xb2, 0x1d, 0x74, 0x4a, 0x07, 0x2f, 0x5d, 0x6f, 0x34, 0x3d, 0xa7, 0x03, 0x78, 0x7e, 0x84, 0x58, 0x60, 0x21, 0x2e, 0xc2, 0xdb, 0x48, 0x88, 0x33, 0xb8, 0x9e, 0x20, 0xe7, 0x15, 0xc9, 0x2f, 0x79, 0x18, 0x51, 0x02, 0x0b, 0xd5, 0x03, 0x53, 0x65, 0xd1, 0x19, 0x2d, 0x9c, 0xd1, 0x01, 0x3c, 0xc3, 0xf8, 0xdc, 0x18, 0xd8, 0x8d, 0x66, 0xa7, 0x85, 0xd9, 0x5c, 0xa5, 0x26, 0x3e, 0x0b, 0x55, 0xee, 0xf9, 0x3d, 0xb2, 0x58, 0x23, 0x0b, 0xc3, 0xb0, 0xd0, 0xec, 0xf5, 0x1c, 0x03, 0x78, 0xf7, 0x46, 0xe9, 0x2a, 0x40, 0xad, 0xae, 0xc2, 0x2a, 0xc6, 0x7b, 0x05, 0xc7, 0x7c, 0x22, 0xaa, 0x26, 0xe1, 0x2a, 0x9a, 0x4e, 0x17, 0x76, 0x1b, 0x0a, 0x7e, 0x80, 0xb9, 0xaf, 0x83, 0xe0, 0x9c, 0xb4, 0xba, 0x44, 0xcd, 0x07, 0x74, 0x77, 0x8d, 0xd6, 0xee, 0xe8, 0x7c, 0xa5, 0x9d, 0xdf, 0xd1, 0xc3, 0x07, 0x74, 0x77, 0x8d, 0x9a, 0x87, 0x38, 0xee, 0x0c, 0x75, 0x0a, 0x8d, 0xcb, 0xfd, 0xeb, 0xa4, 0xaa, 0x52, 0xab, 0x51, 0x1b, 0xf6, 0x07, 0x84, 0x87, 0x3b, 0x38, 0xe1, 0x41, 0x20, 0xd0, 0x56, 0x8f, 0x51, 0xd9, 0xc1, 0xdb, 0xba, 0xfa, 0xcc, 0xd7, 0x68, 0x37, 0x3a, 0xc3, 0x16, 0xc9, 0xcb, 0xb1, 0x3f, 0xb0, 0xbb, 0x0e, 0x3e, 0x0e, 0x7a, 0xfd, 0xf2, 0x82, 0x8e, 0x7d, 0x6c, 0xac, 0x2e, 0x49, 0xfe, 0x4f, 0xb2, 0x0a, 0x49, 0x72,
1 change: 1 addition & 0 deletions build/baremetalpi/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ CFLAGS += -I "$(NEWLIBDIR)/include" -I $(STDDEF_INCPATH) -I $(CIRCLESTDLIB)/incl
LIBS := \
$(TIC80LIB)/libtic80studio.a \
$(TIC80LIB)/libtic80core.a \
$(TIC80LIB)/libforth.a \
$(TIC80LIB)/libgiflib.a \
$(TIC80LIB)/liblpeg.a \
$(TIC80LIB)/libluaapi.a \
Expand Down
4 changes: 4 additions & 0 deletions cmake/core.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,10 @@ if(BUILD_STATIC)
target_link_libraries(tic80core PRIVATE wasm)
endif()

if(BUILD_WITH_FORTH)
target_link_libraries(tic80core PRIVATE forth)
endif()

target_link_libraries(tic80core PRIVATE runtime)

endif()
Expand Down
166 changes: 166 additions & 0 deletions cmake/forth.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
################################
# Forth (pForth)
################################

option(BUILD_WITH_FORTH "Forth Enabled" ${BUILD_WITH_ALL})
message("BUILD_WITH_FORTH: ${BUILD_WITH_FORTH}")

if(BUILD_WITH_FORTH)

set(PFORTH_DIR ${THIRDPARTY_DIR}/pforth/csrc)
set(PFORTH_FTH_DIR ${THIRDPARTY_DIR}/pforth/fth)

# -------------------------------------------------------------------------
# pforth C sources — all files from sources.cmake, excluding the default
# pfcustom.c (our forth.c serves as the replacement).
# -------------------------------------------------------------------------
set(PFORTH_KERNEL_SOURCES
${PFORTH_DIR}/pf_cglue.c
${PFORTH_DIR}/pf_clib.c
${PFORTH_DIR}/pf_core.c
${PFORTH_DIR}/pf_inner.c
${PFORTH_DIR}/pf_io.c
${PFORTH_DIR}/pf_io_none.c
${PFORTH_DIR}/pf_mem.c
${PFORTH_DIR}/pf_save.c
${PFORTH_DIR}/pf_text.c
${PFORTH_DIR}/pf_words.c
${PFORTH_DIR}/pfcompil.c
${PFORTH_DIR}/paging/pagedmem.c
${PFORTH_DIR}/paging/lockpage.c
${PFORTH_DIR}/paging/qadmpage.c
)

# -------------------------------------------------------------------------
# pfdicdat.h — pforth standard dictionary, bootstrapped at configure time.
#
# vendor/pforth/csrc/pfdicdat.h is gitignored; it is generated here by
# building pforth natively on the host. This guarantees the dictionary
# stays in sync with the pinned pforth submodule automatically — no
# manual copy step needed.
#
# For WASM/Emscripten the dictionary must reflect a 32-bit cell size, so
# pforth is built with -m32 (requires gcc-multilib on Linux hosts).
#
# To force regeneration after a pforth submodule update:
# rm vendor/pforth/csrc/pfdicdat.h && cmake <build-dir>
# -------------------------------------------------------------------------
set(PFORTH_DICDAT ${PFORTH_DIR}/pfdicdat.h)

# Always regenerate: a stale 32-bit pfdicdat.h in a 64-bit build (or vice
# versa) causes a silent segfault at Forth VM startup. Regeneration runs
# at cmake configure time (not every build) so the cost is acceptable.
file(REMOVE ${PFORTH_DICDAT})
if(NOT EXISTS ${PFORTH_DICDAT})
message(STATUS "Forth: bootstrapping pforth to generate pfdicdat.h...")
set(_PFORTH_BOOTSTRAP_DIR "${CMAKE_BINARY_DIR}/pforth_bootstrap")

if(CMAKE_CROSSCOMPILING)
# Cross-compilation: CC may be set to the cross-compiler
# (emcc, arm-none-eabi-gcc, …). Always force the host native
# gcc so pforth runs on the build machine.
if(CMAKE_SIZEOF_VOID_P EQUAL 4)
# 32-bit target (WASM, 3DS, RPI bare-metal, …): build a
# 32-bit host pforth to produce a matching dictionary.
# Requires gcc-multilib on Linux hosts.
set(_PFORTH_EXTRA_ARGS
-DCMAKE_C_COMPILER=gcc
-DCMAKE_C_FLAGS=-m32
-DCMAKE_C_COMPILER_WORKS=TRUE
-DCMAKE_CXX_COMPILER_WORKS=TRUE)
else()
# 64-bit cross target (Switch ARM64, …): native host pforth.
set(_PFORTH_EXTRA_ARGS
-DCMAKE_C_COMPILER=gcc
-DCMAKE_C_COMPILER_WORKS=TRUE
-DCMAKE_CXX_COMPILER_WORKS=TRUE)
endif()
else()
# Native build: let cmake pick the host compiler automatically.
set(_PFORTH_EXTRA_ARGS
-DCMAKE_C_COMPILER_WORKS=TRUE
-DCMAKE_CXX_COMPILER_WORKS=TRUE)
endif()

execute_process(
COMMAND ${CMAKE_COMMAND}
${_PFORTH_EXTRA_ARGS}
-S "${THIRDPARTY_DIR}/pforth" -B "${_PFORTH_BOOTSTRAP_DIR}"
RESULT_VARIABLE _pforth_cfg_result
)
execute_process(
COMMAND ${CMAKE_COMMAND} --build "${_PFORTH_BOOTSTRAP_DIR}"
--target pforth_dic_header
RESULT_VARIABLE _pforth_build_result
)

if(NOT EXISTS ${PFORTH_DICDAT})
if(CMAKE_SIZEOF_VOID_P EQUAL 4 AND CMAKE_CROSSCOMPILING)
message(FATAL_ERROR
"Forth: could not generate 32-bit pfdicdat.h.\n"
"A 32-bit host gcc is required. On Linux:\n"
" sudo apt-get install gcc-multilib\n"
"Then delete the build directory and re-run cmake.")
else()
message(FATAL_ERROR
"Forth: failed to generate pfdicdat.h.\n"
"Try manually:\n"
" cd vendor/pforth && cmake . && make pforth_dic_header")
endif()
endif()

message(STATUS "Forth: pfdicdat.h generated successfully")
endif()

# -------------------------------------------------------------------------
# forthdemo.tic.dat — demo cartridge for 'new forth' command.
# Source: demos/forthdemo.fth
# Regenerate (after building prj2cart and bin2txt):
# prj2cart demos/forthdemo.fth /tmp/forthdemo.tic
# bin2txt /tmp/forthdemo.tic build/assets/forthdemo.tic.dat -z
# -------------------------------------------------------------------------

# -------------------------------------------------------------------------
# TIC-80 forth library
# -------------------------------------------------------------------------
set(FORTH_SRC
${PFORTH_KERNEL_SOURCES}
${CMAKE_SOURCE_DIR}/src/api/forth.c
${CMAKE_SOURCE_DIR}/src/api/parse_note.c
)

add_library(forth ${TIC_RUNTIME} ${FORTH_SRC})

if(NOT BUILD_STATIC)
set_target_properties(forth PROPERTIES PREFIX "")
endif()

target_compile_definitions(forth INTERFACE TIC_BUILD_WITH_FORTH=1)

target_compile_definitions(forth PRIVATE
PF_STATIC_DIC # load the pre-compiled dictionary from pfdicdat.h
PF_SUPPORT_FP # enable floating-point word set
PF_NO_FILEIO # stub out file I/O (no filesystem in cartridges)
PF_DEMAND_PAGING=0
)


target_link_libraries(forth PRIVATE runtime)

target_include_directories(forth
PRIVATE
# pfdicdat.h lives here; must come before any other include that
# could shadow it.
${PFORTH_DIR}
${CMAKE_SOURCE_DIR}/include
${CMAKE_SOURCE_DIR}/src
)

# Suppress warnings from pforth's own C files to avoid noise in TIC-80
# build logs (pforth was not written to match TIC-80's warning flags).
foreach(SRC ${PFORTH_KERNEL_SOURCES})
set_source_files_properties(${SRC} PROPERTIES COMPILE_FLAGS
"-w")
endforeach()

endif(BUILD_WITH_FORTH)
59 changes: 59 additions & 0 deletions demos/forthdemo.fth
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
\ title: game title
\ author: game developer, email, etc.
\ desc: short description
\ site: website link
\ license: MIT License (change this to your license of choice)
\ version: 0.1
\ script: forth

VARIABLE px \ sprite x
VARIABLE py \ sprite y

: BOOT
96 px ! 24 py !
;

: demo01
0 BTN IF py @ 1- py ! THEN
1 BTN IF py @ 1+ py ! THEN
2 BTN IF px @ 1- px ! THEN
3 BTN IF px @ 1+ px ! THEN
13 CLS
1 px @ py @ 14 3 0 0 2 2 SPR
S" Hello Forth!" 84 84 15 FALSE 1 FALSE PRINT DROP
;

: TIC
demo01
;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
: demo01
0 BTN IF py @ 1- py ! THEN
1 BTN IF py @ 1+ py ! THEN
2 BTN IF px @ 1- px ! THEN
3 BTN IF px @ 1+ px ! THEN
13 CLS
1 px @ py @ 14 3 0 0 2 2 SPR
S" Hello Forth!" 84 84 15 FALSE 1 FALSE PRINT DROP
;
: TIC
demo01
;
: TIC
0 BTN IF py @ 1- py ! THEN
1 BTN IF py @ 1+ py ! THEN
2 BTN IF px @ 1- px ! THEN
3 BTN IF px @ 1+ px ! THEN
13 CLS
1 px @ py @ 14 3 0 0 2 2 SPR
S" Hello Forth!" 84 84 15 FALSE 1 FALSE PRINT DROP
;

If the user wants to write their own code, they'll probably want to just delete the whole demo code, so having it be a separate word is just clutter.



\ <TILES>
\ 001:eccccccccc888888caaaaaaaca888888cacccccccacc0ccccacc0ccccacc0ccc
\ 002:ccccceee8888cceeaaaa0cee888a0ceeccca0ccc0cca0c0c0cca0c0c0cca0c0c
\ 003:eccccccccc888888caaaaaaaca888888cacccccccacccccccacc0ccccacc0ccc
\ 004:ccccceee8888cceeaaaa0cee888a0ceeccca0cccccca0c0c0cca0c0c0cca0c0c
\ 017:cacccccccaaaaaaacaaacaaacaaaaccccaaaaaaac8888888cc000cccecccccec
\ 018:ccca00ccaaaa0ccecaaa0ceeaaaa0ceeaaaa0cee8888ccee000cceeecccceeee
\ 019:cacccccccaaaaaaacaaacaaacaaaaccccaaaaaaac8888888cc000cccecccccec
\ 020:ccca00ccaaaa0ccecaaa0ceeaaaa0ceeaaaa0cee8888ccee000cceeecccceeee
\ </TILES>

\ <WAVES>
\ 000:00000000ffffffff00000000ffffffff
\ 001:0123456789abcdeffedcba9876543210
\ 002:0123456789abcdef0123456789abcdef
\ </WAVES>

\ <SFX>
\ 000:000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000304000000000
\ </SFX>

\ <PALETTE>
\ 000:1a1c2c5d275db13e53ef7d57ffcd75a7f07038b76425717929366f3b5dc941a6f673eff7f4f4f494b0c2566c86333c57
\ </PALETTE>

\ <TRACKS>
\ 000:100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
\ </TRACKS>

Loading
Loading