Ruby on Spaces is a small experimental programming language built entirely in Python (with a Luau port for ver 2.1). It’s designed as a learning project in language design, parsing, and interpreter building, while still being usable for toy projects, scripting, or experimentation.
This language is minimal, hackable, and deliberately verbose. It’s not about performance — it’s about showing how a working interpreter can be constructed, extended, and modified.
If you are just here for the install go to Install page
def, end, while, if, but Python-like in strictness.number → integers and floatsstring → double quoted, supports escape sequencesbool → true, falsenull → nulllist → [1, 2, 3]dict → { key: value, "literal": 123 }=if, while, for-in, for-cdef, return, methods on objectsprint, len, range# Variables and math
x = 10
y = 20
z = x + y
print("Sum:", z)
# Conditionals
if (x < y)
print("x is less than y")
end
# While loop
while (x < 15)
print("x =", x)
x = x + 1
end
# For-in loop
for item in [1, 2, 3]
print("Item:", item)
end
# C-style for loop
for (i = 0; i < 3; i = i + 1)
print("i:", i)
end
# Functions
def greet(name)
print("Hello,", name)
end
greet("World")
# Methods on objects
person = {}
def person.new(self, name)
self.name = name
end
def person.greet(self)
print("Hi, I'm", self.name)
end
allen = person
allen.new("allen")
allen.greet()
Env (lexical scope).Function class, support interop.ReturnSignal exceptions.false and null are falsy.def py_upper(args_wrapped):
s = unwrap_from_py(args_wrapped[0])
return wrap_for_py(s.upper())
env = make_global_env()
register_pyfunc(env, "upper", py_upper)
run('''
print(upper("hello, world"))
end
''')
local ROSL = require(...)
local function concat(args)
local vals = ROSL.unwrapArgs(args)
return ROSL.wrap(vals[1]..vals[2])
end
local env = ROSL.BasicEnv()
ROSL.registorFunc(env, "concat", concat)
ROSL.run([[
print(concat("Hello, ", "World"))
end
]], env)
Edit KEYWORDS, parser methods, runtime eval.
Change precedence in Parser.lbp, parsing in led, runtime eval.
# Run a file
python ruby.py program.rbs
# REPL
python ruby.py
>>> x = 5
>>> def sq(n) return n*n end
>>> print(sq(x))
program ::= block EOF
block ::= { stmt (NL | ";")* } [ "end" ]
stmt ::= exprstmt | assign | defstmt | methoddef | returnstmt
| ifstmt | whilestmt | forstmt
exprstmt ::= expression
assign ::= lvalue "=" expression
defstmt ::= "def" ID "(" [paramlist] ")" block "end"
methoddef ::= "def" ID "." ID "(" [paramlist] ")" block "end"
returnstmt ::= "return" expression
ifstmt ::= "if" expression block "end"
whilestmt ::= "while" "(" expression ")" block "end"
forstmt ::= "for" "(" stmt ";" expression ";" stmt ")" block "end"
| "for" ID "in" expression block "end"
paramlist ::= ID { "," ID }
expression ::= primary { infixop expression }
primary ::= NUMBER | STRING | "true" | "false" | "null" | ID
| "(" expression ")" | listliteral | dictliteral
| "-" expression | "+" expression
listliteral ::= "[" [ expression { "," expression } ] "]"
dictliteral ::= "{" [ dictentry { "," dictentry } ] "}"
dictentry ::= (STRING | ID) ":" expression
infixop ::= "+" | "-" | "*" | "/" | "<" | ">" | "<=" | ">="
| "==" | "!=" | "." | "[" expression "]" | call
call ::= "(" [ expression { "," expression } ] ")"
lvalue ::= ID | prop | index
prop ::= expression "." ID
index ::= expression "[" expression "]"
See the GitHub README for source and updates.