npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

morphene

v0.1.1

Published

Morphene Turing Tarpit

Downloads

48

Readme

morphene

morphene is a programming language created for the first PLT Games.

Its core feature is the ability to redefine what happens to any input character. The rules that define this behaviour make up a context. Contexts are similar to states in a state machine, with the difference that they work like the JS prototype chain. That is, opening a new context will inherit all the rules already defined in the currently opened context.

Furthermore you have stacks for storage much like in a pushdown automaton. In principle this language should be equivalent in power to a turing machine (Proof left to the author as an exercise some time in the distant future).

If you want to code in morphene it is strongly recommended to find out how to type unicode characters on your operating system. (Hint for Mac users: enable the keyboard 'Unicode hex input')

More details please

The language has one fixed stack, called the first stack, that can be accessed and used everywhere. In addition to this each context has its own stack that is private to this context. It is called the second stack.

There is always only one active stack which the stack commands use, that is why the language also has two registers, $input and $collect. These are string-like buffers.

When morphene reads a character it tries to find a rule to apply to this character. If it cannot find such a rule the default is to put it into $input. Multi-character inputs are first matched and then exploded into their characters and the execution continues with the first one.

Predefined commands

Character choice is almost arbitrary. How lucky that you can redefine all of them.

Stacks

Stack operations

Other commands

Rule definition

Contexts

A context is just a stack of definitions, and → just pushes a new definition. When the system looks up a definition for an input, it walks down the stack. The active contexts are also arranged in a stack, which results in a prototype chain like behaviour.

When you switch to a stack, it is simply put ontop of the active-context-stack.

Now becomes easier to explain: it executes $input in the topmost active context, or the last one that was switched to. Only contexts you switch to by hand are considered for .

The topmost context, the one the programme starts in, is special: when your define rules are active immediately. For all other contexts the definitions are not active until you actually switch to them.

Input and output

No recursion?

With commands unalterable once defined, there can be no reference to the command itself inside. But fear not! It is possible with .

Because executes $input in the topmost context, it can be used for recursion and late binding.

Consider a programme that echos what you input. For this to work we need to be able to bind longer pieces of code to a symbol.

; make a new context for single quote strings
⿸
    ; append all chars to $input
    ∙→∪
    ; but ' ends this context
    '→⿴
; put context reference into $collect
⿹⿶
; let ' switch to that context
'⇉⿵

Now for the programme.

; put code for * in $collect
;  repeat: input; output; * into $input; execute
; this works because * is defined as '∩' at the current line
'←⇇*⿷'⿶
; redefine and run *
*⇉⿵
*

You can try this programme with bin/morphene code/03_echo.morphene.

Spread and compact

The only thing missing is comparisons. Equality is easily done with a new context and two rules, one for the same input and one for any other.

But what about <? This is where spread and compact come in: These two commands make it possible to compose larger data structures.

Spread opens a new context and expands whatever is in top of the first stack into the second stack of this new context.

  • If the input is a single character, its bit pattern is spread on the stack in 1s and 0s. This pattern is bewteeen 8 and 32 bits long. The least significant bit is on top.
  • If the input is a string, its characters are spread on the stack.
  • If the input is a more complex type, its elements are spread on the stack.

Compact pops what is at the top of the first stack and looks at it. Depending on the value it compacts the second stack differently. In any case compact pops the topmost context and thus throws the second stack away if you don't save a reference to it somewhere.

Compact arguments:

  • c - Interpret each stack item as characters. This produces a string.
  • b - Interpret binary. This takes up to 32 bits off the stack and interpretes the resulting number as a UTF-8 character.
  • s - Save as structural type. This basically just saves the stack as is.

Look at the examples folder for fun and profit.