Page namespace (page_namespace) | 0 |
Page title (without namespace) (page_title) | 'Glass' |
Full page title (page_prefixedtitle) | 'Glass' |
Old page wikitext, before the edit (old_wikitext) | '{{featured language}}
'''Glass''' is an [[esoteric programming language]] developed by [[Gregor Richards]] in 2005. It combines an unintuitive [[wikipedia:postfix notation|postfix notation]] with heavy [[wikipedia:Object-oriented programming|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:
*<code>(''name'')</code> or <code>(''number'')</code> is parsed as a single variable name or stack reference number.
*<code>"''string''"</code> is parsed as a string value.
*<code><''number''></code> is parsed as a numeric value (integer or floating-point).
*<code><nowiki>'</nowiki>''comment''<nowiki>'</nowiki></code> 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
:<code>{''class-name'' ''function-definitions''}</code>
The class-name must be the name of a global variable which becomes a reference to the class.
A function definition has the form
:<code>[''function-name'' ''content'']</code>
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:
*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.)
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.
==Commands==
Each command is listed in this form:
;''command'' <nowiki>:</nowiki> ''stack before'' — ''stack afterwards''
:''description''
In this notation (due to [[wikipedia:Forth|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===
;<code>(''name'')</code> <nowiki>:</nowiki> — ''name''
:Push a variable name onto the stack.
:If ''name'' is a single letter from a-z, A-Z, then the parentheses are optional.
;<code>(''number'')</code> <nowiki>:</nowiki> s<SUB>''number''</SUB> ... s<SUB>1</SUB> s<SUB>0</SUB> — s<SUB>''number''</SUB> ... s<SUB>1</SUB> s<SUB>0</SUB> s<SUB>''number''</SUB>
: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.
;<code>"''string''"</code> <nowiki>:</nowiki> — ''string''
:Push the ''string'' onto the stack.
;<code><''number''></code> <nowiki>:</nowiki> — ''number''
:Push the ''number'' onto the stack.
;<code>,</code> <nowiki>:</nowiki> ''value'' —
:Pop a value from the stack.
;<code>^</code> <nowiki>:</nowiki> —
:Return (from function).
;<code>=</code> <nowiki>:</nowiki> ''name'' ''value'' —
:Assign ''value'' to variable ''name''. For composite values, only references are copied.
;<code>!</code> <nowiki>:</nowiki> ''name'' ''cname'' —
: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.
;<code>.</code> <nowiki>:</nowiki> ''oname'' ''fname'' — ''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.
;<code>?</code> <nowiki>:</nowiki> ''stack-before'' ''function'' — ''stack-afterwards''
:Pop the ''function'' from the stack, then run it. The effect on the stack depends on the function.
;<code>*</code> <nowiki>:</nowiki> ''name'' — ''value''
:Retrieve the value of variable ''name'' (in the current context).
;<code>$</code> <nowiki>:</nowiki> ''name'' —
:Assign the current object to variable ''name''.
;<code>/(''name'')''commands''\</code> <nowiki>:</nowiki> ''stack-before'' — ''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'' <nowiki>:</nowiki> ''stack before'' — ''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 <nowiki>:</nowiki> ''x'' ''y'' — ''x''+''y''
:Addition
;A.s <nowiki>:</nowiki> ''x'' ''y'' — ''x''-''y''
:Subtraction
;A.m <nowiki>:</nowiki> ''x'' ''y'' — ''x''*''y''
:Multiplication
;A.d <nowiki>:</nowiki> ''x'' ''y'' — ''x''/''y''
:Division
;A.mod <nowiki>:</nowiki> ''x'' ''y'' — (''x'' mod ''y'')
:Modulus
;A.f <nowiki>:</nowiki> ''x'' — floor(''x'')
:Floor
;A.e <nowiki>:</nowiki> ''x'' ''y'' — ''x''==''y''
:Equality
;A.ne <nowiki>:</nowiki> ''x'' ''y'' — ''x''!=''y''
:Inequality
;A.lt <nowiki>:</nowiki> ''x'' ''y'' — ''x''<''y''
:Less than
;A.le <nowiki>:</nowiki> ''x'' ''y'' — ''x''<=''y''
:Less than or equal to
;A.gt <nowiki>:</nowiki> ''x'' ''y'' — ''x''>''y''
:Greater than
;A.ge <nowiki>:</nowiki> ''x'' ''y'' — ''x''>=''y''
:Greater than or equal to
===Class S (Strings)===
;S.l <nowiki>:</nowiki> ''string'' — ''length''
:Retrieve the length of ''string''.
;S.i <nowiki>:</nowiki> ''string'' ''n'' — ''character''
:Retrieve the ''n''th character of ''string''.
;S.si <nowiki>:</nowiki> ''string'' ''n'' ''char'' — ''newstring''
:Replace the ''n''th character of ''string'' with ''char''.
;S.a <nowiki>:</nowiki> ''s1'' ''s2'' — ''s1s2''
:Concatenate strings.
;S.d <nowiki>:</nowiki> ''string'' ''pos'' — ''s1'' ''s2''
: divide ''string'' at point ''pos'', ''s1'' is the first part, ''s2'' is the second.
;S.e <nowiki>:</nowiki> ''s1'' ''s2'' — ''s1==s2''
:String equality.
;S.ns <nowiki>:</nowiki> ''number'' — ''character''
:Convert a number to a character.
;S.sn <nowiki>:</nowiki> ''character'' — ''number''
:Convert a character to a number.
===Class V (autogenerated Variables)===
;V.n <nowiki>:</nowiki> — ''newname''
:Push name of a new global variable.
;V.d <nowiki>:</nowiki> ''name'' —
:Delete an autogenerated variable.
===Class O (Output)===
;O.o <nowiki>:</nowiki> ''string/name'' —
:Output string or name.
;O.on <nowiki>:</nowiki> ''number'' —
:Output number.
===Class I (Input)===
;I.l <nowiki>:</nowiki> — ''string''
:Retrieve a line of input.
;I.c <nowiki>:</nowiki> — ''char''
:Retrieve a character from input.
;I.e <nowiki>:</nowiki> — ''is-eof''
:Push 1 if end of input, 0 otherwise.
==Examples==
===[[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*<1103515245>(_a)m.?<4294967295>(_a)(mod).?
<12345>(_a)a.?=s*<65535>(_a)d.?<32768>(_a)(mod).?][(seed)s1=,][(randi)(_a)A!
(_t)$(_min)2=(_max)1=,,(_min)*(_max)*(_min)*(_a)s.?<1>(_a)a.?(_t)(rand).?(_a)m.
?<32768>(_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 program|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.?=\]}
==External resources==
* [http://codu.org/eso/glass/ Glass interpreter]
* [http://esoteric.voxelperfect.net/files/glass/ Glass] in [[the Esoteric File Archive]]
[[Category:Languages]]
[[Category:Implemented]]
[[Category:Stack-based]]
[[Category:Object-oriented paradigm]]
[[Category:2005]]
[[Category:Turing complete]]' |
New page wikitext, after the edit (new_wikitext) | '{{featured language}}
'''Glass''' is an [[esoteric programming language]] developed by [[Gregor Richards]] in 2005. It combines an unintuitive [[wikipedia:postfix notation|postfix notation]] with heavy [[wikipedia:Object-oriented programming|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:
*<code>(''name'')</code> or <code>(''number'')</code> is parsed as a single variable name or stack reference number.
*<code>"''string''"</code> is parsed as a string value.
*<code><''number''></code> is parsed as a numeric value (integer or floating-point).
*<code><nowiki>'</nowiki>''comment''<nowiki>'</nowiki></code> 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
:<code>{''class-name'' ''function-definitions''}</code>
The class-name must be the name of a global variable which becomes a reference to the class.
A function definition has the form
:<code>[''function-name'' ''content'']</code>
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:
*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.)
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.
==Commands==
Each command is listed in this form:
;''command'' <nowiki>:</nowiki> ''stack before'' — ''stack afterwards''
:''description''
In this notation (due to [[wikipedia:Forth|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===
;<code>(''name'')</code> <nowiki>:</nowiki> — ''name''
:Push a variable name onto the stack.
:If ''name'' is a single letter from a-z, A-Z, then the parentheses are optional.
;<code>(''number'')</code> <nowiki>:</nowiki> s<SUB>''number''</SUB> ... s<SUB>1</SUB> s<SUB>0</SUB> — s<SUB>''number''</SUB> ... s<SUB>1</SUB> s<SUB>0</SUB> s<SUB>''number''</SUB>
: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.
;<code>"''string''"</code> <nowiki>:</nowiki> — ''string''
:Push the ''string'' onto the stack.
;<code><''number''></code> <nowiki>:</nowiki> — ''number''
:Push the ''number'' onto the stack.
;<code>,</code> <nowiki>:</nowiki> ''value'' —
:Pop a value from the stack.
;<code>^</code> <nowiki>:</nowiki> —
:Return (from function).
;<code>=</code> <nowiki>:</nowiki> ''name'' ''value'' —
:Assign ''value'' to variable ''name''. For composite values, only references are copied.
;<code>!</code> <nowiki>:</nowiki> ''name'' ''cname'' —
: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.
;<code>.</code> <nowiki>:</nowiki> ''oname'' ''fname'' — ''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.
;<code>?</code> <nowiki>:</nowiki> ''stack-before'' ''function'' — ''stack-afterwards''
:Pop the ''function'' from the stack, then run it. The effect on the stack depends on the function.
;<code>*</code> <nowiki>:</nowiki> ''name'' — ''value''
:Retrieve the value of variable ''name'' (in the current context).
;<code>$</code> <nowiki>:</nowiki> ''name'' —
:Assign the current object to variable ''name''.
;<code>/(''name'')''commands''\</code> <nowiki>:</nowiki> ''stack-before'' — ''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'' <nowiki>:</nowiki> ''stack before'' — ''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 <nowiki>:</nowiki> ''x'' ''y'' — ''x''+''y''
:Addition
;A.s <nowiki>:</nowiki> ''x'' ''y'' — ''x''-''y''
:Subtraction
;A.m <nowiki>:</nowiki> ''x'' ''y'' — ''x''*''y''
:Multiplication
;A.d <nowiki>:</nowiki> ''x'' ''y'' — ''x''/''y''
:Division
;A.mod <nowiki>:</nowiki> ''x'' ''y'' — (''x'' mod ''y'')
:Modulus
;A.f <nowiki>:</nowiki> ''x'' — floor(''x'')
:Floor
;A.e <nowiki>:</nowiki> ''x'' ''y'' — ''x''==''y''
:Equality
;A.ne <nowiki>:</nowiki> ''x'' ''y'' — ''x''!=''y''
:Inequality
;A.lt <nowiki>:</nowiki> ''x'' ''y'' — ''x''<''y''
:Less than
;A.le <nowiki>:</nowiki> ''x'' ''y'' — ''x''<=''y''
:Less than or equal to
;A.gt <nowiki>:</nowiki> ''x'' ''y'' — ''x''>''y''
:Greater than
;A.ge <nowiki>:</nowiki> ''x'' ''y'' — ''x''>=''y''
:Greater than or equal to
===Class S (Strings)===
;S.l <nowiki>:</nowiki> ''string'' — ''length''
:Retrieve the length of ''string''.
;S.i <nowiki>:</nowiki> ''string'' ''n'' — ''character''
:Retrieve the ''n''th character of ''string''.
;S.si <nowiki>:</nowiki> ''string'' ''n'' ''char'' — ''newstring''
:Replace the ''n''th character of ''string'' with ''char''.
;S.a <nowiki>:</nowiki> ''s1'' ''s2'' — ''s1s2''
:Concatenate strings.
;S.d <nowiki>:</nowiki> ''string'' ''pos'' — ''s1'' ''s2''
: divide ''string'' at point ''pos'', ''s1'' is the first part, ''s2'' is the second.
;S.e <nowiki>:</nowiki> ''s1'' ''s2'' — ''s1==s2''
:String equality.
;S.ns <nowiki>:</nowiki> ''number'' — ''character''
:Convert a number to a character.
;S.sn <nowiki>:</nowiki> ''character'' — ''number''
:Convert a character to a number.
===Class V (autogenerated Variables)===
;V.n <nowiki>:</nowiki> — ''newname''
:Push name of a new global variable.
;V.d <nowiki>:</nowiki> ''name'' —
:Delete an autogenerated variable.
===Class O (Output)===
;O.o <nowiki>:</nowiki> ''string/name'' —
:Output string or name.
;O.on <nowiki>:</nowiki> ''number'' —
:Output number.
===Class I (Input)===
;I.l <nowiki>:</nowiki> — ''string''
:Retrieve a line of input.
;I.c <nowiki>:</nowiki> — ''char''
:Retrieve a character from input.
;I.e <nowiki>:</nowiki> — ''is-eof''
:Push 1 if end of input, 0 otherwise.
==Examples==
===[[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*<1103515245>(_a)m.?<4294967295>(_a)(mod).?
<12345>(_a)a.?=s*<65535>(_a)d.?<32768>(_a)(mod).?][(seed)s1=,][(randi)(_a)A!
(_t)$(_min)2=(_max)1=,,(_min)*(_max)*(_min)*(_a)s.?<1>(_a)a.?(_t)(rand).?(_a)m.
?<32768>(_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 program|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.?=\]}
==External resources==
* [http://codu.org/eso/glass/ Glass interpreter]
* [http://esoteric.voxelperfect.net/files/glass/ Glass] in [[the Esoteric File Archive]]
* [https://github.com/C-Bouthoorn/rust-glass A work-in-progress Glass compiler]
[[Category:Languages]]
[[Category:Implemented]]
[[Category:Stack-based]]
[[Category:Object-oriented paradigm]]
[[Category:2005]]
[[Category:Turing complete]]' |