It's like Forth but in Python

Related tags

Miscellaneousporth
Overview

Porth

WARNING! This language is a work in progress!

It's like Forth but written in Python. But I don't actually know for sure since I never programmed in Forth, I only heard that it's some sort of stack-based programming language. Porth is also stack-based programming language. Which makes it just like Forth am I rite?

Porth is planned to be

  • Compiled
  • Native
  • Stack-based (just like Forth)
  • Turing-complete
  • Self-hosted (Python is used only as an initial bootstrap, once the language is mature enough we gonna rewrite it in itself)
  • Statically typed (the type checking is probably gonna be similar to the WASM validation)

(these are not the selling points, but rather milestones of the development)

Examples

Hello, World:

include "std.porth"

"Hello, World\n" stdout write

Simple program that prints numbers from 0 to 99 in an ascending order:

do dup print 1 + end ">
include "std.porth"

100 0 while 2dup > do
    dup print 1 +
end

Quick Start

Simulation

Simulation simply interprets the program.

$ cat program.porth
34 35 + print
$ ./porth.py sim program.porth
69

It is strongly recommended to use PyPy for the Simulation Mode since CPython is too slow for that. Try to simulate ./euler/problem04.porth using CPython and compare it with PyPy and Compilation Mode.

Compilation

Compilation generates assembly code, compiles it with nasm, and then links it with GNU ld. So make sure you have both available in your $PATH.

$ cat program.porth
34 35 + print
$ ./porth.py com program.porth
[INFO] Generating ./program.asm
[CMD] nasm -felf64 ./program.asm
[CMD] ld -o ./program ./program.o
$ ./program
69

Testing

Test cases are located in ./tests/ folder. The *.txt files contain inputs (command line arguments, stdin) and expected outputs (exit code, stdout, stderr) of the corresponding programs.

Run ./test.py script to execute the programs and assert their outputs:

$ ./test.py run

To updated expected outputs of the programs run the update subcommand:

$ ./test.py update

To update expected command line arguments and stdin of a specific program run the update input subcommand:

$ ./test.py update input ./tests/argv.porth new cmd args
[INFO] Provide the stdin for the test case. Press ^D when you are done...
Hello, World
^D
[INFO] Saving input to ./tests/argv.txt

The ./examples/ folder contains programs that are ment for showcasing the language rather then testing it, but we still can use them for testing just like the stuff in the ./tests/ folder:

$ ./test.py run ./examples/
$ ./test.py update input ./examples/name.porth
$ ./test.py update output ./examples/

For more info see ./test.py help

Usage

If you wanna use the Porth compiler separately from its codebase you only need two things:

By default the compiler searches files to include in ./ and ./std/. You can add more search paths via the -I flag before the subcommand: ./porth.py -I com ... . See ./porth.py help for more info.

Language Reference

This is what the language supports so far. Since the language is a work in progress everything in this section is the subject to change.

Data Types

Integer

Currently an integer is anything that is parsable by int function of Python. When the compiler encounters an integer it pushes it onto the data stack for processing by the relevant operations.

Example:

10 20 +

The code above pushes 10 and 20 onto the data stack and sums them up with + operation.

String

Currently a string is any sequence of bytes sandwiched between two ". No newlines inside of the strings are allowed. Escaping is done by unicode_escape codec of Python. No way to escape " themselves for now. No special support for Unicode is provided right now too.

When the compiler encounters a string:

  1. the size of the string in bytes is pushed onto the data stack,
  2. the bytes of the string are copied somewhere into the memory (the exact location is implementation specific),
  3. the pointer to the beginning of the string is pushed onto the data stack.

Those, a single string pushes two values onto the data stack: the size and the pointer.

Example:

include "std.porth"
"Hello, World" stdout write

The write macro from std.porth module expects three values on the data stack:

  1. the size of the buffer it needs to print,
  2. the pointer to the beginning of the buffer,
  3. and the output file descriptor where it needs to print to.

The size and the pointer are provided by the string "Hello, World". The file descriptor is stdout macro from std.porth.

Character

Currently a character is a single byte sandwiched between two '. Escaping is done by unicode_escape codec of Python. No way to escape ' themselves for now. No special support for Unicode is provided right now too.

When compiler encounters a character it pushes its value as an integer onto the stack.

Example:

'E' print

This program pushes integer 69 onto the stack (since the ASCII code of letter E is 69) and prints it with the print operation.

Built-in Words

Stack Manipulation

  • dup - duplicate an element on top of the stack.
a = pop()
push(a)
push(a)
  • swap - swap 2 elements on the top of the stack.
a = pop()
b = pop()
push(a)
push(b)
  • drop - drops the top element of the stack.
pop()
  • print - print the element on top of the stack in a free form to stdout and remove it from the stack.
a = pop()
print(a)
  • over
a = pop()
b = pop()
push(b)
push(a)
push(b)

Comparison

  • = - checks if two elements on top of the stack are equal. Removes the elements from the stack and pushes 1 if they are equal and 0 if they are not.
a = pop()
b = pop()
push(int(a == b))
  • != - checks if two elements on top of the stack are not equal.
a = pop()
b = pop()
push(int(a != b))
  • > - checks if the element below the top greater than the top.
b = pop()
a = pop()
push(int(a > b))
  • < - checks if the element below the top less than the top.
b = pop()
a = pop()
push(int(a < b))
  • >=
b = pop()
a = pop()
push(int(a >= b))
  • <=
b = pop()
a = pop()
push(int(a >= b))

Arithmetic

  • + - sums up two elements on the top of the stack.
a = pop()
b = pop()
push(a + b)
  • - - subtracts the top of the stack from the element below.
a = pop()
b = pop()
push(b - a)
  • * - multiples the top of the stack with the element below the top of the stack
a = pop()
b = pop()
push(b * a)
  • divmod
a = pop()
b = pop()
push(b // a)
push(b % a)

Bitwise

  • shr
a = pop()
b = pop()
push(b >> a)
  • shl
a = pop()
b = pop()
push(b << a)
  • bor
a = pop()
b = pop()
push(b | a)
  • band
a = pop()
b = pop()
push(b & a)

Control Flow

  • if else end - pops the element on top of the stack and if the element is not 0 executes the , otherwise .
  • while do end - keeps executing both and until produces 0 at the top of the stack. Checking the result of the removes it from the stack.

Memory

  • mem - pushes the address of the beginning of the memory where you can read and write onto the stack.
push(mem_addr)
  • . - store a given byte at the address on the stack.
byte = pop()
addr = pop()
store(addr, byte)
  • , - load a byte from the address on the stack.
addr = pop()
byte = load(addr)
push(byte)
  • .64 - store an 8-byte word at the address on the stack.
word = pop()
addr = pop()
store(addr, word)
  • ,64 - load an 8-byte word from the address on the stack.
word = pop()
byte = load(word)
push(byte)

System

  • syscall - perform a syscall with n arguments where n is in range [0..6]. (syscall1, syscall2, etc)
syscall_number = pop()

   
    
for i in range(n):
    arg = pop()
    
    

     

     
    
   

Macros

Define a new word write that expands into a sequence of tokens 1 1 syscall3 during the compilation.

macro write
    1 1 syscall3
end

Include

Include tokens of file file.porth

include "file.porth"
Owner
Tsoding
Recreational Programming
Tsoding
Ml-design-patterns - Source code accompanying O'Reilly book: Machine Learning Design Patterns

This is not an official Google product ml-design-patterns Source code accompanying O'Reilly book: Title: Machine Learning Design Patterns Authors: Val

Google Cloud Platform 1.5k Jan 05, 2023
Get a list of content on your Netflix My List that is expiring in the next month or two.

Netflix My List Expiring Movies Annoyed at Netflix for taking away your movies? Now you don't have to be! Installation instructions Install selenium C

24 Aug 06, 2022
Data on Free Food at MIT

MIT Free Food Timing Procrastinating research by plotting data on how long it takes emails on the free-food at mit edu mailing list to go through. Dat

Peter Sharpe 2 Nov 01, 2021
原神抽卡记录导出

原神抽卡记录导出 抽卡记录分析工具 from @笑沐泽 抽卡记录导出工具js版,含油猴脚本可在浏览器导出 注意:我的是python版,带饼图的是隔壁electron版,功能类似 Wik

834 Jan 04, 2023
Suite of tools for retrieving USGS NWIS observations and evaluating National Water Model (NWM) data.

Documentation OWPHydroTools GitHub pages documentation Motivation We developed OWPHydroTools with data scientists in mind. We attempted to ensure the

36 Dec 11, 2022
🤞 Website-Survival-Detection

- 🤞 Website-Survival-Detection It can help you to detect the survival status of the website in batches and return the status code! - 📜 Instructions

B0kd1 4 Nov 14, 2022
Brython (Browser Python) is an implementation of Python 3 running in the browser

brython Brython (Browser Python) is an implementation of Python 3 running in the browser, with an interface to the DOM elements and events. Here is a

5.9k Jan 02, 2023
A community-driven python bot that aims to be as simple as possible to serve humans with their everyday tasks

JARVIS on Messenger Just A Rather Very Intelligent System, now on Messenger! Messenger is now used by 1.2 billion people every month. With the launch

Swapnil Agarwal 1.3k Jan 07, 2023
Automated, progress quest-inspired procedural adventuring

Tales of an Endless Journey (TEJ) Automated, progress quest-inspired procedural adventuring What is this project? Journey is the result of many, many

8 Dec 14, 2021
pyRTOS is a real-time operating system (RTOS), written in Python.

pyRTOS Introduction pyRTOS is a real-time operating system (RTOS), written in Python. The primary goal of pyRTOS is to provide a pure Python RTOS that

Ben Williams 96 Dec 30, 2022
A Trace Explorer for Reverse Engineers

Tenet - A Trace Explorer for Reverse Engineers Overview Tenet is an IDA Pro plugin for exploring execution traces. The goal of this plugin is to provi

1k Jan 02, 2023
Expose multicam options in the Blender VSE headers.

Multicam Expose multicam options in the Blender VSE headers. Install Download space_sequencer.py and swap it with the one that comes with the Blender

4 Feb 27, 2022
Load, explore and analyse data from Scotland and rest of the world related to Covid19.

Streamlit Examples This is my first attempt with Streamlit. It is an open-source framework, free, Python-based and easy to use tool to build and deplo

Eyad Elyan 12 Mar 01, 2021
Gmvault: Backup and restore your gmail account

Gmvault: Backup and restore your gmail account Gmvault is a tool for backing up your gmail account and never lose email correspondence. Gmvault is ope

Guillaume Aubert 3.5k Jan 01, 2023
Retrieve bank transactions and categorize for budgeting use

Budgeting After trying out some budgeting software, I decided to make my own. selenium_scraper Using the selenium package, this script runs an instanc

Marc 1 Nov 10, 2021
Python Multilingual Ucrel Semantic Analysis System

PymUSAS Python Multilingual Ucrel Semantic Analysis System, it currently is a rule based token level semantic tagger which can be added to any spaCy p

UCREL 13 Nov 18, 2022
Simple script to match riders with drivers.

theBestPooler Simple script to match riders with drivers. It's a greedy, unoptimised search, so no guarantees that it works. It just seems to work (ve

Devansh 1 Nov 22, 2021
Data Structures and Algorithms Python - Practice data structures and algorithms in python with few small projects

Data Structures and Algorithms All the essential resources and template code nee

Hesham 13 Dec 01, 2022
A tool to build reproducible wheels for you Python project or for all of your dependencies

asaman: Amra Saman (আমরা সমান) This is a tool to build reproducible wheels for your Python project or for all of your dependencies. What this means is

Kushal Das 14 Aug 05, 2022
The blancmange curve can be visually built up out of triangle wave functions if the infinite sum is approximated by finite sums of the first few terms.

Blancmange-curve The blancmange curve can be visually built up out of triangle wave functions if the infinite sum is approximated by finite sums of th

Shankar Mahadevan L 1 Nov 30, 2021