Senpai is an esoteric programming language that is inspired by anime girls. Don't ask why I made this.
Project description
Senpai: A dynamically-typed, Stack-Based Esolang
- For general info about the language, visit the esolang wiki page
- This document is about implementation-specific details
Implementation Features
- An implementation of the Senpai language purely interpreted in Python
- A simple Python API to create functions for the Senpai interpreter
- Many builtins that make the language easier to use that act as wrappers for Python classes
- An Earley parser, created with Lark
- A 100x slower than Python run speed (Yeah, I'm sorry)
- Only a single dependency outside of the Python standard library (Lark) that can be installed with
pip install lark - A probably slightly buggy interpreter.
Commandline Usage
- To use, use
python -m senpai_lang [commands]
Commands
-h,--help: View the help for the commandline arguments-i,--infile: The input file with the Senpai code to interpret-d,--debugfile: The file to write to for verbose logging. The log tracks almost everything the intepreter does down to the expression.-tb,--pytraceback: Disable the custom except hook and enable normal Python traceback. Should be used for reporting bugs with the intepreter.-w,--wiki: Visit the wiki page for the Senpai language-ps,--printstack: Print the execution time, variables, stacks, and builtins of the program after running the file
Python API
If you want to see the library of functions introduced using this api, read lib/lib_docs.md
Basic Tutorial For Making Your Own Extension Modules
-
- Import
senpai_lang.pyutils
- Import
-
- Create a class that inherits off of
senpai_lang.pyutils.FuncBasewith a class attribute of the name of the function
- Create a class that inherits off of
-
- Create a
__init__that inits thesuper()with args ofself.nameand the function you want to wrap.
- Create a
-
- Instantiate a
PyModuleobject with args of{name}and theclassof the command (not an instance of the class)
- Instantiate a
-
- Import the module from Senpai
- Example implementation of a wrapper for
os.system
import os
from senpai_lang.pyutils import FuncBase, PyModule
class System(FuncBase):
"""
Can take 2 or 1 argument
First argument is always the command to execute.
Second argument can be anything,
Second argument if it exists returns the value os.system
"""
name = 'cmd' # allows for overriding by the module name
def __init__(self):
super().__init__(self.name, self.system)
@staticmethod
def system(*args):
if len(args) == 1:
os.system(*args)
else:
return os.system(args[0])
PyModule('os', [System]) # initialize module
NOTE: A function's return value is pushed onto the current stack and all arguments to the function are destroyed in the process of calling the function.
Full Python API Docs
FuncBase
-
def __init__(self, name, function, iter_results=False)self.name: The name that the function will be referred to by calling from Senpaiself.function: The function that gets called from Senpai- If
iter_resultsisTrue, when function is called, iterate over the return value ofself.functionand push each item in the iterable on top of stack in reverse order such that the top item on the stack is the first item in the iterable. - Updates
SenpaiInterpreter.builtinswith{self.name: self} - Should probably not be instantiated manually unless you know what you are doing
-
def call(self, args, interpreter):- Pops the arguments from the top of the
interpreter's current stack and callsself.functionwith the unpacked version ofargsas arguments. - Should probably not be called explicitely unless you know exactly what you are doing.
- Pops the arguments from the top of the
-
self.interpreter: the interpreter that is calling the function. Only defined when the function is called.
PyModule
def __init__(self, name, functions, rename_funcs=True)self.name: the name of the moduleself.functions: an iterable of all of the classes for functions in the modulerename_funcs(self.rename): IfTrue(should almost always be), add the name of the module followed by an underscore (module_function) before the name of all the functions in the module. Should beTrue(or omitted) in almost all cases.- Instantiates all of the classes in
self.functionsand adds them to the builtins of theSenpaiInterpreterclass and logs imports.
SenpaiInterpreter
These are the useful attributes for making modules. If you want to know more methods and attributes of the SenpaiInterpreter, look at the source code. Most of the methods in there interpret the AST. SenpaiInterpreter objects should generally not be instantiated manually. If you really need to, the SenpaiInterpreter class is located in senpai_lang.src.classes.SenpaiInterpreter.
SenpaiInterpreter.builtins: All of the Python functions added to the interpreter.self.vars: The variables held by the interpreter. It is a dictionary that holds{name: object}.self.stacks: AStackHolderobject that holds the stacks.
StackHolder
A dictionary that holds the {name: Stack([items])} that also holds the name of the current stack.
StackHolder objects should generally not be instantiated manually. The StackHolder class is located in senpai_lang.src.classes.StackHolder
-
def __init__(self, current_stack, **kwargs):- Creates a new
StackHolderinitialized with a current stack name ofcurrent_stack, and contains the dictionary of**kwargs. The dictionary should have values ofStackobjects.
- Creates a new
-
self.current_stack_name: The name of the current stack -
self.current_stack: AStackobject that represents the current stack of the interpreter. -
def switch_stack(self, name): Switches the current stack to be the stack namednameif it exists. If not, creates a stack namednameinitialized with an emptyStack()
Stack
A class that inherits off of collections.deque that represents a stack in the Senpai language. Stack objects should generally not be instantiated manually.
def rot2(self): Performs a Senpairot2operation on the stack (swaps the top 2 items).
def rot3(self): Performs a Senpairot3operation on the stack.
Embedding the Interpreter in Python Applications (If you really want to) (Why would you?)
-
- Import
senpai_lang.src.classes.SenpaiInterpreterandsenpai_lang.src.parser.parser
- Import
-
- Regret all of your life decisions.
-
- Call
parser.parse(code)to get the Tree
- Call
-
- Instantiate the
SenpaiInterpreterwith the Tree as an argument
- Instantiate the
-
- Enjoy
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
File details
Details for the file senpai_lang-0.0.1.tar.gz.
File metadata
- Download URL: senpai_lang-0.0.1.tar.gz
- Upload date:
- Size: 17.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.4.2 importlib_metadata/3.10.1 pkginfo/1.7.1 requests/2.26.0 requests-toolbelt/0.9.1 tqdm/4.62.2 CPython/3.8.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bf2fb3c69b7bba18b74ee180858ae47581a732a47b7f8946dd7ef0d1a9125218
|
|
| MD5 |
b226596454b4d5d35e47b6fcde286bf3
|
|
| BLAKE2b-256 |
805f950b726cb67178fdc05e6b65729c5a790b088837fbfee4269ec62ff339ca
|