RPNCalc

From Esolang
Jump to navigation Jump to search

RPNCalc (technically RPNCalc V4) is a Turing-complete, stack-based, dynamically-typed (vaguely *useful*) programming language that originally started off as a calculator on osmarks.net. It has 2 'dialects', a JS-based interpreted dialect and a dialect that compiles to x86-64 on Linux (sometimes referred to as RPNCC - RPNCalc Compiled). Both the dialects have the same syntax, but subtly different semantics.

Language Features

RPNCalc has support for inline lambdas, curried functions and closures. Lambdas can either be constructed in 'forth-style' (with arguments flipped):

(swap; a b -> b a)

or

(a b -> b a)

or 'curried style' (with arguments being popped off the stack one-by-one):

(swap; b -> (a -> b a))

or

(b -> (a -> b a))

Lambdas in RPNCalc return a list that represents their stack in a 'return stack' when they finished executing, which is subsequently merged back into the parent stack. To have support for higher-level functions, when a Lambda's return stack returns a nested lambda, the nested lambda is immediately applied onto the stack.

RPNCalc additionally has support for recursive local definitions, for example:

(def1; code executed upon definition)
(def2; def2 is a recursive definition)

The other major part of RPNCalc syntax is the special 'push' operator, which allows the user to avoid the merging process when a function returns, instead pushing a closure to the stack. Here, the dialects differ; if in the JS dialect you push a return stack, each element of the stack is pushed to the parent stack, while in the x86-64 version a pointer to the list is pushed instead. For example, in RPNCC:

(# include list #)
[ 1 : 2 : 3 : 4 : 5 : 6 ] '(x -> x 1 +) map

RPNCC StdLib

RPNCC exposes an assembly interface, and through it some useful functions are defined. These functions are grouped into RPNCC modules, namely:

  • arith
  • list
  • bool
  • mutref
  • io

arith exposes the basic arithmetic functions +, -, * and /

list exposes the 'nil list' ([] or [) and the 'cons/pair' operator (: and ])

bool exposes the comparison operators &= (equality by reference), == (recursive equality), the booleans true and false, as well as the 'if-else' branching operator (if-else or ?:)

mutref exposes mutable references, through the <> operator (construct a mutable reference with a given value) the << operator (set a mutable reference to a given value and return the reference) and the >> operator (extract a value from a mutable reference).

io exposes the IO operations putchar, putbyte, and putint.