Glass

Glass is an esoteric programming language developed by Gregor Richards in 2005. It combines an unintuitive postfix notation with heavy object-orientation, requiring extensive juggling of a main stack combined with its object-oriented structure. No other language that the author knows of is implemented like this, because it would be idiotic.

Syntax
The language is parsed into distinctive elements, each one character long, with the exception of these groupings:
 * or  is parsed as a single variable name or stack reference number.
 * is parsed as a string value.
 * is parsed as a numeric value (integer or floating-point).
 * isn't parsed at all, it's a comment (non-nestable).

Parentheses are optional around a single letter A-Z, a-z or digit 0-9. Therefore, the variable name a could be represented by both a and (a), but the name abc could only be represented as (abc).

A program consists of a sequence of class definitions.

Each class definition has the form

The class-name must be the name of a global variable which becomes a reference to the class.

A function definition has the form

The function-name must be the name of a class-local variable which becomes a reference to the function. The content is an arbitrary sequence of commands.

For example: {M[m...]} would declare a class M with a function named m which does ... {(Main)[(main)...]} would declare a class Main with a function named main which does ...

Execution
Execution starts by creating an instance of the class M and running the function M.m. That is, it is equivalent to the following sequence of commands: (_t)M!(_t)m.?

Variables
There are four types of variables, partly separated by the format of their name: Variable names are only resolved in the context where they are actually used - that is, if you introduce the name _a in function a, and pass it back to the parent function, which uses the returned name, it will not refer to the variable _a of function a, but to the _a of the parent function. Autogenerated global variables are available to alleviate this issue. The contextual-ness of variable names is also why the. operator (seen later) works even though you push the name of a class-local variable - it resolves that variable in the context of the called class, not the caller.
 * Global variables, with names beginning with upper-case characters.
 * Variables local to a class, with names beginning with lower-case characters. These are immutable and must be looked up with the . command rather than the * command.
 * Variables local to an object, with names beginning with lower-case characters.
 * Variables local to the current invocation of a function, with names beginning with an underscore. (Note that names beginning with an underscore must be parenthesized.)

Commands
Each command is listed in this form:
 * command : stack before &mdash; stack afterwards
 * description

In this notation (due to Forth), stack elements are separated by spaces, and the top of the stack (i.e. the most recently-pushed element) is listed last.

Command list

 * : &mdash; name
 * Push a variable name onto the stack.
 * If name is a single letter from a-z, A-Z, then the parentheses are optional.


 * : snumber ... s1 s0 &mdash; snumber ... s1 s0 snumber
 * Duplicate an element number positions down the stack to the top of the stack.
 * If number is a single digit 0-9, then the parentheses are optional.


 * : &mdash; string
 * Push the string onto the stack.


 * : &mdash; number
 * Push the number onto the stack.


 * : value &mdash;
 * Pop a value from the stack.


 * : &mdash;
 * Return (from function).


 * : name value &mdash;
 * Assign value to variable name. For composite values, only references are copied.


 * : name cname &mdash;
 * Assign a new instance of the class in variable cname to the variable name. Pop the names from the stack, then run the c__ (constructor) function of the newly instantiated object.


 * : oname fname &mdash; function
 * Retrieve the function fname defined in the class of the object oname. The object becomes the current object of the retrieved function.
 * The variable oname is looked up in the current context, while fname is looked up in the context of the class of the object.


 * : stack-before function &mdash; stack-afterwards
 * Pop the function from the stack, then run it. The effect on the stack depends on the function.


 * : name &mdash; value
 * Retrieve the value of variable name (in the current context).


 * : name &mdash;
 * Assign the current object to variable name.


 * : stack-before &mdash; stack-afterwards
 * Repeat commands while the variable name has a "true" value. The effect on the stack depends on content.
 * Values are considered "true" if they are non-zero numbers or non-empty strings.

As an example of using commands, here is a segment of code to instantiate a class O into the variable _o, then run the function _o.o with "Hello World!" on the stack: (_o)O!"Hello World!"(_o)o.?

So, to make a hello world program (assuming that the O class is built in to the system), do the following: {M[m(_o)O!"Hello World!"(_o)o.?]}

Isn't that easy?!

Special definable functions

 * c__
 * Constructor function of a class, run whenever an object is created.


 * d__
 * Destructor function of a class, run when an object is garbage collected.


 * m
 * Function in class M, run to execute the whole program.

Built-in classes
Each built-in function is listed in the form
 * Class.function : stack before &mdash; stack afterwards
 * description

Note that Class.function is not legal Glass syntax for using the function, you need to do something like (_C)Class!(_C)function.?

Class A (Arithmetic)

 * A.a : x y &mdash; x+y
 * Addition


 * A.s : x y &mdash; x-y
 * Subtraction


 * A.m : x y &mdash; x*y
 * Multiplication


 * A.d : x y &mdash; x/y
 * Division


 * A.mod : x y &mdash; (x mod y)
 * Modulus


 * A.f : x &mdash; floor(x)
 * Floor


 * A.e : x y &mdash; x==y
 * Equality


 * A.ne : x y &mdash; x!=y
 * Inequality


 * A.lt : x y &mdash; xy
 * Greater than


 * A.ge : x y &mdash; x>=y
 * Greater than or equal to

Class S (Strings)

 * S.l : string &mdash; length
 * Retrieve the length of string.


 * S.i : string n &mdash; character
 * Retrieve the nth character of string.


 * S.si : string n char &mdash; newstring
 * Replace the nth character of string with char.


 * S.a : s1 s2 &mdash; s1s2
 * Concatenate strings.


 * S.d : string pos &mdash; s1 s2
 * divide string at point pos, s1 is the first part, s2 is the second.


 * S.e : s1 s2 &mdash; s1==s2
 * String equality.


 * S.ns : number &mdash; character
 * Convert a number to a character.


 * S.sn : character &mdash; number
 * Convert a character to a number.

Class V (autogenerated Variables)

 * V.n : &mdash; newname
 * Push name of a new global variable.


 * V.d : name &mdash;
 * Delete an autogenerated variable.

Class O (Output)

 * O.o : string/name &mdash;
 * Output string or name.


 * O.on : number &mdash;
 * Output number.

Class I (Input)

 * I.l : &mdash; string
 * Retrieve a line of input.


 * I.c : &mdash; char
 * Retrieve a character from input.


 * I.e : &mdash; is-eof
 * Push 1 if end of input, 0 otherwise.

Hello, world! program
{M[m(_o)O!"Hello World!"(_o)o.?]}

Fibonacci sequence
{F[f(_a)A!(_o)O!(_t)$(_n)1=,(_isle)(_n)*<2>(_a)(le).?=/(_isle)<1>^\(_n)*<1>(_a) s.?(_t)f.?(_n)*<2>(_a)s.?(_t)f.?(_a)a.?]}{M[m(_a)A!(_f)F!(_o)O!(_n)<1>=(_nlm) <1>=/(_nlm)(_n)*(_f)f.?(_o)(on).?" "(_o)o.?(_n)(_n)*<1>(_a)a.?=(_nlm)(_n)*<20> (_a)(le).?=\]}

Randomizer class
{(Rand)[(c__)s<5>=][(rand)(_a)A!ss* (_a)m.? (_a)(mod).? (_a)a.?=s* (_a)d.? (_a)(mod).?][(seed)s1=,][(randi)(_a)A! (_t)$(_min)2=(_max)1=,,(_min)*(_max)*(_min)*(_a)s.?<1>(_a)a.?(_t)(rand).?(_a)m. ? (_a)d.?(_a)a.?(_a)f.?]}

Quine
{M[m(_s)S!(_o)0O!o.<34>(_s)(ns).?"{M[m(_s)S!(_o)0O!o.<34>(_s)(ns).?" "14?24?14?24?24?04?24?04?]}"14?24?14?24?24?04?24?04?]}

Cat
{M[maI!bO!cA!dae.?<1>c(ne).?=/dac.?bo.?dae.?<1>c(ne).?=\]}

99 bottles of beer
{B[b<99>^]}{P[(c__)oO!aA!][poo.?][b(_m)1=,(_x)<0>(_m)*ae. ?=(_y)<1>=/(_x)"No more"oo.?(_x)0=(_y)0=\/(_y)(_m)*o(on). ?(_y)0=\" bottle"oo.?(_x)<1>(_m)*ae.?=/(_x)^(_x)0=\"s"oo. ?]}{C[(c__)oO!aA!sS!pP!][gn*][xn1=,][dnn*<1>as.?=][vn*pb. ?" of beer on the wall,\n"pp.?n*pb.?qe" of beer,\n"pp.? "Take one down, pass it around\n"pp.?ln*<1>as.?=l*pb.?wu " of beer on the wall.\n\n"pp.?]}{M[moO!cC!bB!bb.?cx.?fc g.?=/fcv.?cd.?fcg.?=\]}

brainfuck interpreter
{B[(c__)k<1>=j<1>=u<0>=][(af)/kkB!(_e)$(_e)*kv.?\k*][(ae)/jjB !(_e)$(_e)*jw.?\j*][pu*][wk1=,][vj1=,][qu1=,]}{C[(c__)aA!iI!o O!sS!r""(_f)ic.?=(_d)ie.?<0>ae.?=/(_d)(_f)*sa.?(_f)ic.?=(_d)i e.?<0>ae.?=(_g)(_d)*=/(_g)(_d)(_f)*";"se.?<0>ae.?=(_g)<0>=\\= tr*sl.?=b<0>=h$gB!][(ai)gp.?<1>as.?(_a)1<-1>ae.?=/(_a), (_a)<0>=\gq.?][(ah)(_a)b*t*a(lt).?=/(_a)h(ag).?b0*<1>a0.?= (_a)b*t*a(lt).?=\][(ag)(_b)r*b*si.?=(_a)(_b)*"+"se.?=/(_a)h (ad).?^\(_a)(_b)*"-"se.?=/(_a)h(ai).?^\(_a)(_b)*">"se.?=/(_a) hy.?^\(_a)(_b)*"<"se.?=/(_a)hz.?^\(_a)(_b)*"["se.?=/(_a)h(ab) .?^\(_a)(_b)*"]"se.?=/(_a)h(aa).?^\(_a)(_b)*"."se.?=/(_a)hx.? ^\(_a)(_b)*","se.?=/(_a)h(ac).?^\][(ad)gp.?<1>a0.? a(mod) .?gq.?][(ac)ic.?(_h)ie.?=/(_h)<0>gq.?,^\s(sn).?gq.?][(ab)(_a) gp.?=/(_a)^\(_c)<1>=/(_c)b0*<1>a0.?=(_a)b*t*a(gt).?=/(_a)^\ (_b)r*b*si.?=(_a)(_b)*"["se.?=/(_a)(_c)0*<1>a0.?=(_a)<0>=\ (_a)(_b)*"]"se.?=/(_a)(_c)0*<1>as.?=(_a)<0>=\\][(aa)(_a)gp.? <0>ae.?=/(_a)^\(_c)<1>=/(_c)b0*<1>as.?=(_a)b*<0>a(le).?= /(_a)^\(_b)r*b*si.?=(_a)(_b)*"["se.?=/(_a)(_c)0*<1>as.?=(_a) <0>=\(_a)(_b)*"]"se.?=/(_a)(_c)0*<1>a0.?=(_a)<0>=\\][zg(af). ?g1=,][yg(ae).?g1=,][xgp.?s(ns).?o0.?]}{M[m(_i)C!(_i)(ah).?] }

External resources

 * Glass interpreter
 * Glass in the Esoteric File Archive
 * A work-in-progress Glass compiler