Initial Commit
commit
007e3d7cb9
|
@ -0,0 +1,7 @@
|
|||
bin
|
||||
CMakeFiles
|
||||
cmake_*
|
||||
CMakeCache.txt
|
||||
Makefile
|
||||
*.*tmp*
|
||||
*~*
|
|
@ -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)
|
|
@ -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 |
|
||||
| | | 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.
|
|
@ -0,0 +1,5 @@
|
|||
> v
|
||||
v ,,,,,"Hello"<
|
||||
>48*, v
|
||||
v,,,,,,"World!"<
|
||||
>25*,@
|
|
@ -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;
|
||||
};
|
|
@ -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;
|
||||
}
|
Loading…
Reference in New Issue