The Ursa Programming Language
What is Ursa?
Ursa is a simple programming language that I've been working on for awhile now. Ursa is heavily influenced by Python and Java, and its syntax is (at times) similar to Lisp, but instead of being list-based, it is "stream-based." Most in-built statements operate on types of data called streams. Streams are are variable-length arrays of data of a certain type.
The basic premise of ursa is to function as a very high-level abstraction layer between streams and "I/O devices." I/O devices are objects that represent locations that can be read and written using data streams; namely, the console, files, and network ports. Ursa greatly simplifies the implementation of programs that transfer data between these devices.
Ursa uses reverse polish notation for math and functions are simply seperated from their arguments by space characters. This makes implentation of Standard Ursa interpreters since this syntax is easier to write a parser for.
For example, consider this ursa program that sends an HTTP request to cygnus/x, then stores the server's response in the file response.txt:
declare file f
prt.connect "cygnus-x.net" 80
out "GET / HTTP/1.0" endl prt
out "Host: localhost endl endl prt
out (prt.readall) f
The code above is not only more legible than it would be in many other languages, but the underlying I/O processes are greatly abstracted using the "out" statement and the port.readall function.
Another example is a simple echo server. This code starts a listening port on port 20000, then echoes all lines of data it receives
# # ---echo-server.u--- # # basic echo server # copyright (c) cygnus/x design 2016 # # you are free to use and redistribute this code as long as the # copyright notice above is present # # declare a string to contain the version of this program declare string _version set _version "v0.01" # declare a serverport and a port to attach new connections to declare serverport sp declare port p # declare a string to contain lines of input declare string input # attach the serverport to port 20000 sp.attach 20000 # loop indefinitely, getting connections then echoing the data they send while true set p (sp.getconn) out "%msg: connection from " (p.addr) endl console out "echo server " _version endl endl p while true set input (in string p) out input endl p if (and (= input "") (not (p.isopen 1000))) break end if end while p.close out "%msg: connection closed" endl console end while
Click here to download version 0.78 (release 0) of the Cygnus/X ursa interpreter. It is written in java and contained in a jar file that needs to be started from the command line. You should be able to run the jar by changing to your Downloads directory and running the command:
java -jar ursa-0.78.jar
Known serious bugs in this release of v0.78:
- The last parts of certain blocks (i.e.
if...else) get executed sometimes when they're not supposed to be. This is being investigated.
whileloops don't work properly in functions. This is also under investigation.
Download the Ursa Standard Library
Click here to download the Ursa standard library. (version 0.78) You should unzip it in the same directory as your Cygnus/X Ursa .jar file. It currently contains the modules:
These modules can be imported using the
import command as long as the lib folder is in the proper location. For example, to import math, use the command:
Draft documentation for this library is available here.
A simple server program that reads two integers from a port and outputs their sum.
A basic qotd server written in ursa that implements the quote of the day protocol. Reads a quote from the file .qotd and outputs it to connections on port 17.
A simple server that reads strings from a port and outputs their sum.
A simple command-line based football game where you play against the computer. Essentially a clone of the Creative Computing game ftball.bas. It's not perfect, but it demonstrates a lot of the features of ursa.
Single-user remote ursa shell. Allows a single user to log in to an ursa shell on a remote machine through a raw connection.
Known issues in the current release of v0.78:
- Control statements (
for, if, try, while) don't have proper scopes yet and rely on the global scope. They'll have their own scope eventually but it'll be exceptionally difficult to implement.
- Nested function declarations and function declarations from within statements don't work properly yet.
- Subscripting a stream with a value from another stream doesn't work properly due to a bug in
Things to improve going forward:
- Many of the error messages printed out by the interpreter are far too cryptic for the general user, and some don't even indicate properly where the error's occuring.
- The interpreter really likes converting
doublevalues unnecessarily. This shouldn't be done nearly as much.
- Cygnus/X Ursa is a bit too reliant on Java. This makes sense for now, but hopefully it can move further away from Java in the future.
Click here to view a draft version of the language specification.
Standard Library Specification
Click here to view a draft version of the standard Ursa library specification.
- cygnus/x ursa currently consists of 5949 lines of code.
- The interpreter method itself is currently 4189 lines long. That's 70.42% of the entire project.
- There's currently 978 lines of documentation available for standard ursa.
More coming soon...
Questions? Comments? Click here to drop me a line. I'm open to criticism and happy to help you troubleshoot.