bass, The B.+ Awful Scripting System
A horrifically mutilated Scheme-like mess of lexical tokens reminiscent of Brainfuck. (All of the built-in identifiers are soley punctuation; I guess this language is kinda meat-language independent?)
The title is a regular expression; B.+ is any word of your choice starting with B to describe your anguish at or hatred of this language.
Types
There are 5 data types.
- None — A Nothing. The only None value is '()'.
- Integer — A signed, two's-compliment 32 bit integer. The radix these numbers are represented in is implementation-defined.
- String — A fixed-type list of bytes. Functions that apply to lists also apply to this type.
- Symbol — A name for a value or expression. Spaces aren't allowed inside symbols and they can't start with '$' or a decimal digit, and can't contain semicolons.
- List — Some stuff stuck in some brackets.
Syntax
Comments begin with a semicolon and end with an ASCII line-feed character.
Expressions begin with '(' and end with ')'.
Lists begin with '[' and end with ']'.
Strings begin and end with a double-quote. Double-quotes can be written inside strings by placing two directly next to eachother.
Built-in Functions
- +, -, *, / — Arithmetic
- =, ~=, >, <, <=, >= — Comparison
- &, |, ~ — Boolean Logic
- ! — Displays the given value or values on screen.
- (? expression [[value-1 branch-1] [value-2 branch-2] etc.]) — Conditionally evaluate expressions based on the value of another expression. '()' is returned if the given expression's value does not match any of the branch values.
- (>< list1 list2) — Concatenates two lists or two strings.
- (<- name value) — Defines a scope-visible identifier for an expression or value.
- (... list) — Gets the length of a list or string as an integer. Always returns 1 when given a non-list value.
- (^ list index) — Get a list's nth element. Lists start at index 1 and negative indices give values from the end of the list. Multiple indices are allowed. If the list doesn't contain the specified index, '()' is returned. Index 1 on a non-list value returns the value itself.
- (^< list) — Gets a list's first value. Similar to 'car' in Lisp. Non-list values return themselves.
- (^> list) — Gets all but the first of a lists values. Similar to 'cdr' in Lisp. Non-list values return '()'.
- (. [arg-names] (expr)) — Defines an anonymous function. The final expression in the function is the function's return value.
Formal-ish Kinda-EBNF Grammar
comment = ';' [^\n]* ;
none = '(' ')' ;
(* [0-9] is just an example, the base is implementation-defined :) *)
integer = '-'? [0-9]+ ;
string = '"' ('""'|[^"]) '"' ;
symbol = [^0-9;$ ]+ [^; ]* ;
atom = none | integer | string | symbol ;
list = '[' (atom | list)+ ']' ;
expr = '(' (atom | list | expr)+ ')';
Examples
;;; hello world
(! "hello, world")
;;; condition
(<- example (~ ()))
(? example
[[() (! "example is false")]
[(~ ()) (! "example is true")]])
;;; list concatenation
(! (>< [1 2 3] [4 5 10]))
;;; arithmetic
(! (+ 2 2))
;;; function
(<- square (. [n]
(* n n)))
;;; a kind of associative array
(<- my-array
[["name" "Ada"]
["gender" ":)"]
["prefers-tau" (~ ())]])
(! (? "name" my-array))
;;; making bass more like a regular scheme
(<- define <-)
(<- car ^<)
(<- cdr ^>)
(<- cond ?)
(<- display !)
(<- lambda .)