Initial Commit

master
rubenwardy 2016-01-27 19:39:35 +00:00
commit 007e3d7cb9
6 changed files with 383 additions and 0 deletions

7
.gitignore vendored Normal file
View File

@ -0,0 +1,7 @@
bin
CMakeFiles
cmake_*
CMakeCache.txt
Makefile
*.*tmp*
*~*

76
CMakeLists.txt Normal file
View File

@ -0,0 +1,76 @@
#Change this if you need to target a specific CMake version
cmake_minimum_required(VERSION 2.6)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/")
project(RUFUNGE)
#################
# CONFIGURATION #
#################
# Enable debug symbols by default
if(CMAKE_BUILD_TYPE STREQUAL "")
set(CMAKE_BUILD_TYPE Debug)
endif()
# (you can also set it on the command line: -D CMAKE_BUILD_TYPE=Release)
# Set version information in a config.h file
set(VM_VERSION_MAJOR 0)
set(VM_VERSION_MINOR 1)
set(VM_VERSION_PATCH 0)
set(VM_VERSION_LABEL dev)
# configure_file(
# source/config.hpp.in
# source/config.hpp
# )
include_directories("${PROJECT_BINARY_DIR}")
###############################
# Source Files and Executable #
###############################
set(PROJECT_SRC
src/main.cpp
)
# Define sources and executable
set(EXECUTABLE_NAME "a")
add_executable(${EXECUTABLE_NAME} ${PROJECT_SRC})
file(MAKE_DIRECTORY "bin")
set(EXECUTABLE_OUTPUT_PATH "${CMAKE_SOURCE_DIR}/bin")
################
# DEPENDENCIES #
################
# Use C++11
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X)
if(COMPILER_SUPPORTS_CXX11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
elseif(COMPILER_SUPPORTS_CXX0X)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
else()
message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.")
endif()
##############################
# INSTALLATION AND PACKAGING #
##############################
install(TARGETS ${EXECUTABLE_NAME} DESTINATION bin)
# CPack packaging
#include(InstallRequiredSystemLibraries)
#set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/COPYING")
#set(CPACK_PACKAGE_VERSION_MAJOR "${myproject_VERSION_MAJOR}")
#set(CPACK_PACKAGE_VERSION_MINOR "${myproject_VERSION_MINOR}")
#include(CPack)

126
README.md Normal file
View File

@ -0,0 +1,126 @@
# Rufunge
Rufunge is a befunge clone which aims to make the language more practical.]
## Aims
* Should be a "superset" of befunge: a befunge program should work in rufunge.
* Adds good support for subprogram libraries.
* Adds file access.
# 1. The Stack
## 1.1 Types
An element in the stack is an unsigned number, 32 bit or larger.
## 1.2 Numbers
When the cursor reaches a number, it pushes that digit onto the stack.
For example, 123 will end up with a stack of `[3, 2, 1]`. (left most is top most)
The \` can be used to enter into numeric mode.
For example, \`123\` would give you a stack `[123]`.
## 1.3 Strings
Use " to enable string mode.
For example, "hello" ends up with
`['o', 'l', 'l', 'e', 'h'] = [111, 108, 108, 101, 104]`.
# 2 Standard Operators and Library
`a` is used to refer to the topmost element popped and
`b` to the second topmost element popped.
## 2.1 Arithmetic Operators
| Symbol | Name | Description |
| ------ | ---- |------------------------------ |
| + | Add | b + a |
| - | Sub | b - a |
| * | Mul | b * a |
| / | Div | b / a |
| % | Mod | b % a |
## 2.2 Logical Operators
| Symbol | Name | Description |
| ------ | ---- |------------------------------ |
| ! | Not | If a == 0, push 1 else push 0 |
| ` | Grtr | If b > a, push 1 else push 0 |
## 2.3 Flow Control
| Symbol | Name | Description |
| ------ | ---- |------------------------------ |
| ^ | DirU | Direction Flow |
| > | DirR | Direction Flow |
| v | DirD | Direction Flow |
| < | DirL | Direction Flow |
| ? | RndD | Random direction |
| _ | H-If | If a==0, go right else left |
| &#124; | V-If | If a==0, go down else up |
| # | brdg | Jump over next statement |
| @ | exit | Exit Program |
| [ | bs | Skip til next |
| ] | be | End skip |
## 2.4 Stack Operators
| Symbol | Name | Description |
| ------ | ---- |------------------------------ |
| 0 - 9 | Int | Input an integer digit |
| " | Str | Toggle string mode |
| : | Dup | Push a twice |
| \ | Swap | Swap a and b |
| $ | Del | Pop and discard $ |
## 2.5 Input and Output
| Symbol | Name | Description |
| ------ | ---- |------------------------------ |
| . | oint | Output a as int |
| , | ochr | Output a as char |
| & | iint | Input a as int |
| ~ | ichr | Input a as chat |
| g | get | a=y, b=x, get (x, y) |
| p | put | a=y, b=x, c=v. set (x, y) = v |
## 2.6 Core Functions
S, T, U are reverse strings. The first letter in the string is at
the top of the stack.
For example, to pass "hello" as a parameter would be:
`0"olleh" = ['h', 'e', 'l', 'l', 'o', 0] = [104, 101, 108, 108, 111, 0]`
| Symbol | Name | Description |
| ------ | ---- |--------------------------------------- |
| M | req | Load module S. Pop 1 on success else 0 |
| P | load | Load subprogram S::R and call it a. |
| R | rtn | Return to caller |
| L | lock | Hide the stack before a certain cell - use to stop bugs overwriting previous program's stack elements. |
### Examples
```
v Program to find the length of a string
> v
v M"str"0 < Load module "str"
v _ 0"rorre"#,:_ @ If failed output error
> v
v P"lstr"0"length"0 < Load str::length, call it l.
> 0"sdlmsdlmsd" l . @ Run l on "sdlmsdlmsd".
```
`str::length` means the subprogram length in the module str.
If the module is a rf module, then there will be some
str/length.rf or stf/length.bf somewhere. If it's a native module,
then there will be some C++ code or some binding somewhere.
# 3 Modules and Subprograms
Modules are collections of rufunge files.
Each rufunge file is a subprogram.

5
examples/hello_world.rf Normal file
View File

@ -0,0 +1,5 @@
> v
v ,,,,,"Hello"<
>48*, v
v,,,,,,"World!"<
>25*,@

134
src/cursor.hpp Normal file
View File

@ -0,0 +1,134 @@
#pragma once
#include <iostream>
#include <assert.h>
#include <cmath>
#include <stack>
#include <map>
#include <vector>
enum EDIR {
RIGHT,
DOWN,
LEFT,
UP
};
#define CHUNK_SIZE 16
class Chunk
{
public:
int x;
int y;
char data[CHUNK_SIZE * CHUNK_SIZE];
Chunk *next;
};
class Canvas
{
public:
Chunk* hashmap[1000] = {NULL};
Canvas() {}
int hashCPos(int cx, int cy)
{
int retval = (cx + 10 * cy) % 1000;
if (retval < 0) {
return -retval;
} else {
return retval;
}
}
Chunk *getChunk(int x, int y)
{
int cx = floor((float)x / CHUNK_SIZE);
int cy = floor((float)y / CHUNK_SIZE);
int hash = hashCPos(cx, cy);
assert(hash >= 0 && hash < 1000);
Chunk *c = hashmap[hash];
while (c && (c->x != cx || c->y != cy))
c = c->next;
return c;
}
Chunk *getChunkOrCreate(int x, int y)
{
int cx = floor((float)x / CHUNK_SIZE);
int cy = floor((float)y / CHUNK_SIZE);
int hash = hashCPos(cx, cy);
assert(hash >= 0 && hash < 1000);
Chunk *c = hashmap[hash];
while (c && (c->x != cx || c->y != cy))
c = c->next;
if (c) {
return c;
} else {
Chunk *tmp = new Chunk();
tmp->x = cx;
tmp->y = cy;
tmp->next = hashmap[hash];
hashmap[hash] = tmp;
return tmp;
}
}
void set(int x, int y, char value) {
//printf("get %d %d = %d\n", x, y, value);
Chunk *c = getChunkOrCreate(x, y);
assert(c);
int rx = x - c->x * CHUNK_SIZE;
int ry = y - c->y * CHUNK_SIZE;
c->data[rx + ry * CHUNK_SIZE] = value;
}
char get(int x, int y) {
Chunk *c = getChunk(x, y);
if (c) {
int rx = x - c->x * CHUNK_SIZE;
int ry = y - c->y * CHUNK_SIZE;
//int retval = c->data[rx + ry * CHUNK_SIZE];
//printf("get %d %d -> %d\n", x, y, retval);
return c->data[rx + ry * CHUNK_SIZE]; //retval;
} else {
//printf("get %d %d -> 0\n", x, y);
return 0;
}
}
};
struct Cursor
{
Canvas *canvas;
int x, y;
EDIR dir;
std::map<char, int> operators;
};
class Thread
{
Cursor *cursor;
std::stack<Cursor*> link;
std::stack<char> stack;
};
class VM;
class Subroutine
{
public:
/// Return true to
virtual bool init(VM *vm, Thread *th) = 0;
};
class VM
{
public:
std::vector<Thread*> threads;
std::map<int, Subroutine*> subroutines;
};

35
src/main.cpp Normal file
View File

@ -0,0 +1,35 @@
#include "cursor.hpp"
#define TEST(cond) if (!(cond)) { std::cerr << "Failed test, line " << __LINE__ << ": " << #cond << std::endl; return false; }
bool TEST_POS(Canvas &c, int x, int y, char b, char a)
{
TEST(c.get((x), (y)) == (b));
c.set((x), (y), (a));
TEST(c.get((x),(y)) == (a));
return true;
}
bool run_tests() {
Canvas c;
for (int x = -100; x < 100; x++) {
for (int y = -100; y < 100; y++) {
if (!TEST_POS(c, x, y, 0, (x + y * 200) % 255)) {
std::cerr << " - was " << x << ", " << y << std::endl;
return false;
}
}
}
return true;
}
int main() {
if (run_tests()) {
std::cerr << "All tests passed!" << std::endl;
} else {
std::cerr << "A test failed!" << std::endl;
return 1;
}
std::cerr << "Loaded!" << std::endl;
}