Obython
Jump to navigation
Jump to search
Obython is a language made in python, when i thought, what could be the longest way to make a hello world program
Things in it
Print - does stuff
Print(print=String(value="this is valid")),
Print(print="this is valid"),
Print("and so is this"),
Print("also the commas are because thats how you structure \
this in...")
Program
Program - contains the program
Program(code=[
Print("yeah thats why there was commas\
this is used to contain code, and etc"),
Print("it goes through everything in the code and\
calls .value() on it, and also some things that\
use it is...")
])
If
If - checks if condition is true, and if it is, does its program
If(condition=Equal(a=Number(value=1),
b=Number(value=1)),
program=Program(code=[
Print("yes this runs because 1 in fact does equal 1, also if\
you are wondering what Number and String are, they are...")
]))
Literals
Literal - when called .value() on, they return themselves but also for only literals, if .literal() is called on them, it returns its literal, which is used in print and Equal, and more String - a literal, specifically a string Number - a literal, specifically an int or float Boolean - a literal, specifically a bool Dict - a literal, specifically a dictionary List - a literal, specifically a list No - a literal, specifically None also Program returns a No(value=None) when the Program has empty code, as in [], or has its last statement not returning anything, it would return a None instead of a No, which is bad, because None isnt supported as an...
Object
Everything inherits from the Object class,
just with different value method, and for literals, different
typerfilter method
class Object:
def __init__(self, *positional, **values):
if self.typefilter(values):
self.values = values
self.positional = positional
else:
raise TypeError()
def value(self):
raise NotImplementedError("Subclasses must override value()")
def literal(self):
raise NotImplementedError("Only Literals implement literal(), but got class '"+str(type(self))+"'")
def typefilter(self, values):
return True
There is more
i am just too lazy to show them
Examples
99 bottles of beer
code = Program(code=[
Assign(variable=String(value="bottles"), value=Number(value=99)),
While(condition=GreaterThan(a=Get(variable=String(value="bottles")), b=Number(value=1)), code=Program(code=[
Print(Add(a=ToString(value=Get(variable=String(value="bottles"))), b=String(value=" bottles of beer on the wall"))),
Print(Add(a=ToString(value=Get(variable=String(value="bottles"))), b=String(value=" bottles of beer"))),
Print(String(value="Take one down, pass it around")),
Assign(variable=String(value="bottles"), value=Subtract(a=Get(variable=String(value="bottles")), b=Number(value=1))),
If(condition=GreaterThan(a=Get(variable=String(value="bottles")), b=Number(value=1)), program=Program(code=[
Print(Add(a=ToString(value=Get(variable=String(value="bottles"))), b=String(value=" bottles of beer on the wall")))
]))
])),
Print("1 bottle of beer on the wall"),
Print("1 bottle of beer"),
Print("Take one down, pass it around"),
Print("No more bottles of beer on the wall")
])
Interpeter
import time, random
class ReturnSignal(Exception):
def __init__(self, value):
self.value = value
class Helper:
def wrap_literal(value):
if isinstance(value, bool):
return Boolean(value=value)
elif isinstance(value, int) or isinstance(value, float):
return Number(value=value)
elif isinstance(value, str):
return String(value=value)
elif isinstance(value, list):
return List(value=[wrap_literal(v) for v in value])
else:
raise TypeError(f"No literal wrapper for: {type(value)}")
def wrapifneed(value):
if not(isinstance(value, Object)):
return Helper.wrap_literal(value)
return value
class Environment:
frames = [{}] # a list of dicts, top is current scope
recursionlimit = 100
@classmethod
def get(cls, name):
for frame in reversed(cls.frames):
if name in frame:
return frame[name]
raise NameError(f"Variable '{name}' not found in any scope")
@classmethod
def set(cls, name, value, scope="local"):
if scope == "local":
cls.frames[-1][name] = value
elif scope == "global":
cls.frames[0][name] = value
@classmethod
def push(cls):
if len(cls.frames) < cls.recursionlimit:
cls.frames.append({})
else:
raise RecursionError("too many recursive calls")
@classmethod
def pop(cls):
cls.frames.pop()
@classmethod
def define(cls, varibs):
for key in varibs:
cls.frames[-1][key] = varibs[key].value()
class Object:
def __init__(self, *positional, **values):
if self.typefilter(values):
self.values = values
self.positional = positional
else:
raise TypeError()
def value(self):
raise NotImplementedError("Subclasses must override value()")
def literal(self):
raise NotImplementedError("Only Literals implement literal(), but got class '"+str(type(self))+"'")
def typefilter(self, values):
return True
class Time(Object):
def value(self):
start = time.perf_counter()
self.values["do"].value() # Run the code block
end = time.perf_counter()
duration = end - start
return Number(value=duration)
class RandomInt(Object):
def value(self):
lo = self.values.get("min", Number(value=0)).value().literal()
hi = self.values.get("max", Number(value=100)).value().literal()
return Number(value=random.randint(lo, hi))
class Define(Object):
def value(self):
name = self.values["name"].value().literal()
val = self.values["code"]
Environment.set(name, val)
return None
class Return(Object):
def value(self):
result = self.values["value"].value()
raise ReturnSignal(result)
class Get(Object):
def value(self):
name = self.values["variable"].value().literal()
return Environment.get(name)
class Assign(Object):
def value(self):
if "scope" not in self.values:
self.values["scope"] = "local"
name = self.values["variable"].value().literal()
val = self.values["value"].value()
Environment.set(name, val, self.values["scope"])
return val # return the new value
class Call(Object):
def value(self):
if "inputs" not in self.values:
self.values["inputs"] = Dict(value={})
code = self.values["proced"]
Environment.push()
Environment.define(self.values["inputs"].value().literal())
try:
result = code.value()
except ReturnSignal as r:
Environment.pop()
return r.value
Environment.pop()
return result
class Literal(Object):
def value(self):
return self
def literal(self):
return self.value().values["value"]
class Program(Object):
def value(self):
lastval = No(value=None)
for code in self.values["code"]:
try:
lastval = code.value()
except ReturnSignal as r:
# Bubble return up immediately
raise r
return lastval
def literal(self):
return self
class Dot(Object):
def value(self):
obj = self.values["object"].value()
method = self.values["method"]
method.values["object"] = obj
return method.value()
class Number(Literal):
def typefilter(self, values):
return isinstance(values.get("value"), (int, float))
class String(Literal):
def typefilter(self, values):
return isinstance(values.get("value"), (str))
class List(Literal):
def typefilter(self, values):
return isinstance(values.get("value"), (list))
class Dict(Literal):
def typefilter(self, values):
return isinstance(values.get("value"), (dict))
class No(Literal):
def typefilter(self, values):
return isinstance(values.get("value"), type(None))
class Add(Object):
def value(self):
result = self.values["a"].value().literal() + self.values["b"].value().literal()
return Helper.wrapifneed(value=result)
class Subtract(Object):
def value(self):
result = self.values["a"].value().literal() - self.values["b"].value().literal()
return Helper.wrapifneed(value=result)
class Multiply(Object):
def value(self):
result = self.values["a"].value().literal() * self.values["b"].value().literal()
return Helper.wrapifneed(value=result)
class Divide(Object):
def value(self):
result = self.values["a"].value().literal() / self.values["b"].value().literal()
return Helper.wrapifneed(value=result)
class Print(Object):
def value(self):
if self.positional:
self.values["print"] = self.positional[0]
print(Helper.wrapifneed(self.values["print"]).value().literal(), flush=True)
class Read(Object):
def value(self):
prompt = ""
if "prompt" in self.values:
prompt = self.values["prompt"].value().literal()
user_input = input(prompt)
return Helper.wrapifneed(user_input)
class Repeat(Object):
def value(self):
for i in range(self.values["times"].literal()):
self.values["code"].value()
class Forever(Object):
def value(self):
while True:
self.values["code"].value()
class While(Object):
def value(self):
while self.values["condition"].value().literal():
self.values["code"].value()
class Index(Object):
def value(self):
return Helper.wrapifneed(self.values["object"].value().literal()[self.values["index"].value().literal()])
class Boolean(Literal):
def typefilter(self, values):
return isinstance(values.get("value"), (bool))
class String(Literal):
def typefilter(self, values):
return isinstance(values.get("value"), (str))
class List(Literal):
def typefilter(self, values):
return isinstance(values.get("value"), (list))
class Dict(Literal):
def typefilter(self, values):
return isinstance(values.get("value"), (dict))
class No(Literal):
def typefilter(self, values):
return isinstance(values.get("value"), type(None))
class If(Object):
def value(self):
if self.values["condition"].value().literal():
self.values["program"].value()
class Equal(Object):
def value(self):
result = self.values["a"].value().literal() == self.values["b"].value().literal()
return Boolean(value=result)
class GreaterThan(Object):
def value(self):
return Boolean(
value=self.values["a"].value().literal() > self.values["b"].value().literal()
)
class LessThan(Object):
def value(self):
return Boolean(
value=self.values["a"].value().literal() < self.values["b"].value().literal()
)
class Not(Object):
def value(self):
return Boolean(value=not(self.values["condition"].value().literal()))
class And(Object):
def value(self):
a = self.values["a"].value().literal()
if not(a):
return Boolean(value=False)
b = self.values["b"].value().literal()
return Boolean(value=b)
class Or(Object):
def value(self):
a = self.values["a"].value().literal()
if a:
return Boolean(value=True)
b = self.values["b"].value().literal()
return Boolean(value=b)
class Scope(Object):
def value(self):
Environment.push()
self.values["program"].value()
Environment.pop()
class ToNumber(Object):
def value(self):
val = self.values["value"].value().literal()
return Number(value=float(val))
class ToString(Object):
def value(self):
val = self.values["value"].value().literal()
return String(value=str(val))
code = Program(code=[
Assign(variable=String(value="bottles"), value=Number(value=99)),
While(condition=GreaterThan(a=Get(variable=String(value="bottles")), b=Number(value=1)), code=Program(code=[
Print(Add(a=ToString(value=Get(variable=String(value="bottles"))), b=String(value=" bottles of beer on the wall"))),
Print(Add(a=ToString(value=Get(variable=String(value="bottles"))), b=String(value=" bottles of beer"))),
Print(String(value="Take one down, pass it around")),
Assign(variable=String(value="bottles"), value=Subtract(a=Get(variable=String(value="bottles")), b=Number(value=1))),
If(condition=GreaterThan(a=Get(variable=String(value="bottles")), b=Number(value=1)), program=Program(code=[
Print(Add(a=ToString(value=Get(variable=String(value="bottles"))), b=String(value=" bottles of beer on the wall")))
]))
])),
Print("1 bottle of beer on the wall"),
Print("1 bottle of beer"),
Print("Take one down, pass it around"),
Print("No more bottles of beer on the wall")
])
try:
code.value()
except ReturnSignal as e:
print("execution stopped with exit code", e.value)